Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

252
LINES

< > BotCompany Repo | #1029226 // ManagedIntObjects_v1 [manage our own objects in an int array]

JavaX fragment (include) [tags: use-pretranspiled]

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: 385 / 997
Version history: 93 change(s)
Referenced in: [show references]