// all sizes+addresses are in longs (8 bytes, 2 words) // longs are stored big-endian (like twoIntsToLong) asclass ManagedIntObjects64 { replace Addr with long. replace Addr2 with Long. new FreeList64 freeList; *() { alloc(reservedSpaceAtBeginning()); // so 0 is usable as the null pointer } // overridable public abstract long size(); public abstract int get(Addr i); public abstract void set(Addr i, int val); public void setLong(Addr i, long val) { set(i, firstIntFromLong(val)); set(i+1, secondIntFromLong(val)); } public long getLong(Addr i) { ret twoIntsToLong(get(i), get(i+1)); } swappable void onMemorySizeChanged() {} void ensureCapacity(long size) { if (memorySize() < size) setMemorySize(roundUpToPowerOfTwo(size)); } abstract void setMemorySize(long newSize); void growMemory() { setMemorySize(max(1, memorySize()*2)); } // all allocated ranges are filled with zero long alloc(long length) { LongRange r; while ((r = freeList.findFreeSpace(length)) == null) growMemory(); freeList.remove(LongRange(r.start, r.start+length)); ret r.start; } void free(long start, long length) { if (length == 0) ret; freeList.add(LongRange(start, start+length)); clearMemory(start, length); } abstract void clearMemory(long start, long length); abstract long memorySize(); final int read(Addr i) { ret get(i); } final long readLong(Addr i) { ret getLong(i); } final void write(Addr i, int val) { set(i, val); } final void writeLong(Addr i, long val) { setLong(i, val); } // words a pointer requires long sizeOfPointer() { ret 2; } int wordSizeInBytes() { ret 4; } public Addr nullPtr() { ret 0; } // convenience pointer array handling (memory layout: length + data) // it's a List, so max size 31 bit L pointerArray(Addr addr) { if (addr == 0) null; int size = get(addr); ret new RandomAccessAbstractList() { public int size() { ret size; } public Addr2 get(int i) { rangeCheck(i, size); ret readLong(addr+1+i*sizeOfPointer()); } public Addr2 set(int i, Int val) { rangeCheck(i, size); Addr2 old = get(i); writeLong(addr+1+i*sizeOfPointer(), val); ret old; } }; } Addr newPointerArray(int size) { Addr a = alloc(size*sizeOfPointer()+1); set(a, size); ret a; } void freePointerArray(Addr a) { if (a != 0) free(a, read(a)+1); } // a can be nullPtr(), then we just make a new array Addr resizePointerArray(Addr a, int newSize) { ifdef ManagedIntObjects_v1_debug printFunctionCall resizePointerArray(a, newSize); endifdef if (a == 0) ret newPointerArray(newSize); int oldSize = get(a); if (oldSize == newSize) ret a; Addr a2 = newPointerArray(newSize); memCopy(a+1, a2+1, min(oldSize, newSize)); ret a2; } abstract void memCopy(long from, long to, long length); long totalFree() { ret freeList.totalFree(); } long reservedSpaceAtBeginning() { ret 2; } void collectAndCompact(IManagedObject64 rootObject) { ManagedIntObjects64_Collector collector = new(this); if (rootObject != null) rootObject.scanForCollection(collector); collector.collectAndCompact(); } void printStats { print("Managed memory size: " + toM(size()*(long) wordSizeInBytes()) + " MB, free: " + ratioToIntPercent(freeList.totalFree(), size()) + "%"); } // +1, actually long highestUsedWord() { LongRange r = freeList.highestFreeRange(); ret r != null && r.end == size() ? r.start : size(); } }