!include once #1027304 // Eclipse Collections import org.eclipse.collections.impl.set.mutable.primitive.*; import org.eclipse.collections.api.iterator.*; sclass ManagedIntObjects_v1_Collector implements IManagedObjectCollector { ManagedIntObjects_v1 mem; CompactTreeSet objects = new(intRangeComparatorByStart()); new IntHashSet pointers; IntIntHashMap relocationMap; // TODO: turn into a set new MultiMap> relocationCallbacks; bool discardFreeListEarly; // saves memory, but ironically makes original memory unusable when compacting fails because of OOM bool verbose = true; *(ManagedIntObjects_v1 *mem) {} // notify collector that there is an object in a location public void noteObject(int start, int size, IVF1 updateAddress default null) { objects.add(intRange(start, start+size)); if (updateAddress != null) relocationCallbacks.add(start, updateAddress); } // notify collector that there is a pointer in a location public void notePointer(int addr) { if (addr != 0) pointers.add(addr); } // notify collector that there is a pointer array in a location public void notePointerArray(int start) { if (start == 0) ret; int n = mem.get(start); noteObject(start, n+1); for i to n: notePointer(start+1+i); } int sizeNeeded() { ret totalIntRangesLength_int(objects); } void collectAndCompact() { int sizeNeeded = sizeNeeded(); if (mem.size() == sizeNeeded) ret; if (discardFreeListEarly) mem.freeList.clear(); // reserve new memory print("Reserving " + toM(sizeNeeded*(long) mem.wordSizeInBytes()) + " MB"); int freePtr = mem.reservedSpaceAtBeginning(); int[] newMem = new[freePtr+sizeNeeded]; // copy all the objects, fill relocationMap print("Copying " + nObjects(objects)); for (IntRange r : objects) { int oldPtr = r.start, newPtr = freePtr; if (oldPtr != newPtr) { relocationMap.put(oldPtr, newPtr); for (IVF1 f : relocationCallbacks.get(oldPtr)) f.get(freePtr); } arraycopy(mem.mem, r.start, newMem, freePtr, r.length()); freePtr += r.length(); } // update the pointers print("Updating " + n2(pointers.size(), "pointer")); IntIterator itPointers = pointers.intIterator(); while (itPointers.hasNext()) { int pointerAddr = itPointers.next(); // find enclosing object IntRange obj = objects.floor(IntRange(pointerAddr, pointerAddr)); if (obj == null) continue with print("Pointer without object"); int newObjAddr = relocationMap.getIfAbsent(obj.start, obj.start); int newPointerAddr = newObjAddr-obj.start+pointerAddr; // find target, update pointer int target = mem.get(pointerAddr); if (target == 0) continue; int newTarget = relocationMap.getIfAbsent(target, -1); if (newTarget >= 0) newMem[newPointerAddr] = newTarget; } print("Managed GC done"); mem.mem = newMem; if (!discardFreeListEarly) mem.freeList.clear(); } // call after collectAndCompact to get new location of objects public int getNewLocation(int addr) { ret relocationMap.getIfAbsent(addr, addr); } }