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