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: | 367 / 394 |
| Referenced in: | [show references] |