Uses 11335K of libraries. Click here for Pure Java version (6008L/37K).
1 | // all sizes+addresses are in ints (4 bytes) |
2 | // For a full persistent solution, see PersistentManagedObjects_v1 |
3 | |
4 | // TODO: |
5 | // -during GC collection, forbid writes from all users except GC itself |
6 | // -during GC compaction, forbid reads and writes from all users except GC |
7 | |
8 | sclass ManagedIntObjects_v1 implements IIntMemory { |
9 | replace Addr with int. |
10 | replace BoxedAddr with Int. |
11 | |
12 | int[] mem = new int[0]; |
13 | new FreeList freeList; |
14 | bool collecting, compacting; // GC phases |
15 | |
16 | *() { |
17 | assertEquals(0, alloc(reservedSpaceAtBeginning())); // so 0 is usable as the null pointer |
18 | } |
19 | |
20 | *(int[] *mem) {} |
21 | |
22 | // overridable |
23 | public long size() { ret mem.length; } |
24 | public int get(Addr i) { ret mem[i]; } |
25 | public void set(Addr i, int val) { mem[i] = val; } |
26 | |
27 | swappable void onMemorySizeChanged() {} |
28 | |
29 | void ensureCapacity(int size) { |
30 | if (memorySize() < size) |
31 | setMemorySize(roundUpToPowerOfTwo(size)); |
32 | } |
33 | |
34 | void setMemorySize(int newSize) { |
35 | int size = memorySize(); |
36 | if (newSize == size) ret; |
37 | if (newSize < size) unimplemented("Shrinking memory"); |
38 | print("New memory size: " + newSize); |
39 | mem = resizeIntArray(mem, newSize); |
40 | free(size, newSize-size); |
41 | onMemorySizeChanged(); |
42 | } |
43 | |
44 | void growMemory() { |
45 | setMemorySize(max(1, memorySize()*2)); |
46 | } |
47 | |
48 | // all allocated ranges are filled with zero |
49 | int alloc(int length) { |
50 | IntRange r; |
51 | while ((r = freeList.findFreeSpace(length)) == null) { |
52 | print("No free space for length " + length + " - growing"); |
53 | growMemory(); |
54 | } |
55 | |
56 | freeList.remove(IntRange(r.start, r.start+length)); |
57 | ret r.start; |
58 | } |
59 | |
60 | void free(int start, int length) { |
61 | if (length == 0) ret; |
62 | deb()?.print("Freeing " + start + " (l=" + length + ")"); |
63 | freeList.add(IntRange(start, start+length)); |
64 | fillMem(start, start+length, 0); |
65 | } |
66 | |
67 | void fillMem(int start, int end, int value) { |
68 | Arrays.fill(mem, start, end, value); |
69 | } |
70 | |
71 | final int memorySize() { ret mem.length; } |
72 | final public int read(Addr i) { ret get(i); } |
73 | final void write(Addr i, int val) { set(i, val); } |
74 | |
75 | // words a pointer requires |
76 | int sizeOfPointer() { ret 1; } |
77 | int wordSizeInBytes() { ret 4; } |
78 | |
79 | public Addr nullPtr() { ret 0; } |
80 | |
81 | // convenience pointer array handling (memory layout: length + data) |
82 | |
83 | L<BoxedAddr> pointerArray(Addr addr) { |
84 | if (addr == 0) null; |
85 | int size = get(addr); |
86 | ret new RandomAccessAbstractList<BoxedAddr>() { |
87 | public int size() { ret size; } |
88 | public BoxedAddr get(int i) { rangeCheck(i, size); ret read(addr+1+i); } |
89 | public Int set(int i, Int val) { rangeCheck(i, size); Int old = get(i); write(addr+1+i, val); ret old; } |
90 | }; |
91 | } |
92 | |
93 | Addr newPointerArray(int size) { |
94 | deb()?.printVars("newIntArray", +size); |
95 | Addr a = alloc(size+1); |
96 | set(a, size); |
97 | ret a; |
98 | } |
99 | |
100 | void freePointerArray aka freeIntArray(Addr a) { |
101 | if (a == 0) ret; |
102 | deb()?.print("freePointerArray at " + a); |
103 | free(a, read(a)+1); |
104 | } |
105 | |
106 | Addr newIntArray(int[] array) { |
107 | if (array == null) ret 0; |
108 | int n = l(array); |
109 | deb()?.printVars("newIntArray", +n); |
110 | Addr ptr = alloc(n+1); |
111 | set(ptr, n); |
112 | for i to n: |
113 | set(ptr+1+i, array[i]); |
114 | ret ptr; |
115 | } |
116 | |
117 | // a can be nullPtr(), then we just make a new array |
118 | Addr resizePointerArray(Addr a, int newSize) { |
119 | deb()?.printVars("resizePointerArray", +a, +newSize); |
120 | if (a == 0) ret newPointerArray(newSize); |
121 | int oldSize = get(a); |
122 | if (oldSize == newSize) ret a; |
123 | |
124 | Addr a2 = realloc(a, oldSize+1, newSize+1); |
125 | set(a2, newSize); |
126 | ret a2; |
127 | } |
128 | |
129 | // a can be nullPtr(), then we just make a new array |
130 | Addr realloc(Addr a, int oldSize, int newSize) { |
131 | deb()?.printVars("realloc", +a, +oldSize, +newSize); |
132 | if (a == 0) ret alloc(newSize); |
133 | if (oldSize == newSize) ret a; |
134 | if (oldSize > newSize) { |
135 | free(a+newSize, oldSize-newSize); |
136 | ret a; |
137 | } |
138 | // newSize is bigger than oldSize |
139 | // Try growing. |
140 | |
141 | IntRange r = new(a+oldSize, a+newSize); |
142 | if (freeList.canRemove(r)) { |
143 | // Great! Grow it and we're done |
144 | deb()?.print("Chunk grown"); |
145 | freeList.remove(r); |
146 | ret a; |
147 | } |
148 | |
149 | // We have to move the whole thing |
150 | deb()?.printVars("realloc copy", +newSize); |
151 | Addr a2 = alloc(newSize); |
152 | memCopy(a, a2, oldSize); |
153 | deb()?.printVars("realloc free old, returning", +a2); |
154 | free(a, oldSize); |
155 | ret a2; |
156 | } |
157 | |
158 | void memCopy(int src, int dest, int n) { |
159 | arraycopy(mem, src, mem, dest, n); |
160 | } |
161 | |
162 | |
163 | |
164 | // even more convenient typed object array handling as List |
165 | |
166 | <A extends AbstractManagedObject> L<A> objectArray(Addr addr, |
167 | IF1<BoxedAddr, A> wrapPointer) { |
168 | ret convertListElementsBothWays( |
169 | wrapPointer, |
170 | element -> element.addr, |
171 | pointerArray(addr)); |
172 | } |
173 | |
174 | int totalFree() { ret freeList.totalFree(); } |
175 | |
176 | int reservedSpaceAtBeginning() { ret 1; } |
177 | |
178 | void copyReservedArea(int[] newMem) { newMem[0] = get(0); } |
179 | |
180 | void collectAndCompact(IManagedObject rootObject, ManagedIntObjects_v1_Collector collector default new ManagedIntObjects_v1_Collector(this)) { |
181 | collecting = true; |
182 | if (rootObject != null) |
183 | rootObject.scanForCollection(collector); |
184 | compacting = true; |
185 | collector.collectAndCompact(); |
186 | compacting = false; |
187 | collecting = false; |
188 | } |
189 | |
190 | bool collecting() { ret collecting; } |
191 | bool compacting() { ret compacting; } |
192 | |
193 | void printStats { |
194 | print("Managed memory size: " + toM(size()*(long) wordSizeInBytes()) + " MB, free: " + ratioToIntPercent(freeList.totalFree(), size()) + "%"); |
195 | } |
196 | |
197 | // +1, actually |
198 | int highestUsedWord() { |
199 | IntRange r = freeList.highestFreeRange(); |
200 | ret r != null && r.end == size() ? r.start : (int) size(); |
201 | } |
202 | |
203 | void saveToFile(File f) { |
204 | // only save used part |
205 | stream2file(IntArrayInputStream_littleEndian(mem, 0, highestUsedWord()), f); |
206 | printFileInfo(f); |
207 | } |
208 | |
209 | // we use the reserved int for a user-defined value to bootstrap |
210 | // the system |
211 | void setRootField(int val) { |
212 | set(0, val); |
213 | } |
214 | |
215 | int getRootField() { |
216 | ret get(0); |
217 | } |
218 | |
219 | int[] readIntArray(BoxedAddr ptr) { |
220 | if (ptr == 0) null; |
221 | int n = mem[ptr++]; |
222 | int[] a = new[n]; |
223 | arraycopy(mem, ptr, a, 0, n); |
224 | ret a; |
225 | } |
226 | |
227 | Addr newString(S s) { |
228 | if (s == null) ret 0; |
229 | byte[] array = toUtf8(s); |
230 | int[] ints = intArrayFromBytes_littleEndian_flexLength(array); |
231 | Addr ptr = alloc(l(ints)+1); |
232 | for i over ints: |
233 | set(ptr+1+i, ints[i]); |
234 | set(ptr, l(array)^0x80000000); |
235 | ret ptr; |
236 | } |
237 | |
238 | S readString(Addr addr) { |
239 | if (addr == 0) null; |
240 | int n = get(addr) ^ 0x80000000; |
241 | int[] ints = new[(n+3)/4]; |
242 | for i over ints: |
243 | ints[i] = get(addr+1+i); |
244 | byte[] bytes = intArrayToBytes_littleEndian_flexLength(ints, n); |
245 | ret fromUtf8(bytes); |
246 | } |
247 | |
248 | // cycle from "disk" (memory) |
249 | selfType rotate() { |
250 | ret new ManagedIntObjects_v1(mem); |
251 | } |
252 | } |
download show line numbers debug dex old transpilations
Travelled to 7 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt, xrpafgyirdlv
No comments. add comment
Snippet ID: | #1029226 |
Snippet name: | ManagedIntObjects_v1 [manage our own objects in an int array] |
Eternal ID of this version: | #1029226/94 |
Text MD5: | 5296a912b88b0444e6d1d22e16742b20 |
Transpilation MD5: | 2effb06823066ede1f0571821443e3f4 |
Author: | stefan |
Category: | javax |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2021-06-28 21:11:52 |
Source code size: | 7143 bytes / 252 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 462 / 1100 |
Version history: | 93 change(s) |
Referenced in: | [show references] |