private static boolean getAvailableChunkIfPossible(int size) { if (freeChunks == 0) { return false; } while (true) { if (currentChunk.toAddress().add(size) == currentChunkLimit) { break; } if (currentChunk.toAddress().add(size + Structure.sizeOf(FreeChunk.class)).isLessThan(currentChunkLimit)) { break; } if (--freeChunks == 0) { return false; } freeMemory -= currentChunk.size; currentChunkPointer = Structure.add(FreeChunkHolder.class, currentChunkPointer, 1); currentChunk = currentChunkPointer.value; currentChunkLimit = currentChunk.toAddress().add(currentChunk.size); } return true; }
@SuppressWarnings("unused") private static RuntimeObject cloneLowLevel(RuntimeObject self) { RuntimeClass cls = RuntimeClass.getClass(self); int skip = Structure.sizeOf(RuntimeObject.class); int size; RuntimeObject copy; if (cls.itemType == null) { copy = Allocator.allocate(cls).toStructure(); size = cls.size; } else { RuntimeArray array = (RuntimeArray) self; copy = Allocator.allocateArray(cls, array.size).toStructure(); int itemSize = (cls.itemType.flags & RuntimeClass.PRIMITIVE) == 0 ? Address.sizeOf() : cls.itemType.size; Address headerSize = Address.align(Address.fromInt(Structure.sizeOf(RuntimeArray.class)), itemSize); size = itemSize * array.size + headerSize.toInt(); } if (size > skip) { Allocator.moveMemoryBlock(self.toAddress().add(skip), copy.toAddress().add(skip), size - skip); } return copy; }
private static void updateFreeMemory() { freeMemory = 0; FreeChunkHolder freeChunkPtr = currentChunkPointer; for (int i = 0; i < freeChunks; ++i) { freeMemory += freeChunkPtr.value.size; freeChunkPtr = Structure.add(FreeChunkHolder.class, freeChunkPtr, 1); } }
public static Address allocateArray(RuntimeClass tag, int size) { int itemSize = (tag.itemType.flags & RuntimeClass.PRIMITIVE) != 0 ? tag.itemType.size : Address.sizeOf(); int sizeInBytes = Address.align(Address.fromInt(Structure.sizeOf(RuntimeArray.class)), itemSize).toInt(); sizeInBytes += itemSize * size; sizeInBytes = Address.align(Address.fromInt(sizeInBytes), Address.sizeOf()).toInt(); Address result = GC.alloc(sizeInBytes).toAddress(); fillZero(result, sizeInBytes); RuntimeArray array = result.toStructure(); array.classReference = tag.pack(); array.size = size; return result; }
private static FreeChunkHolder getFreeChunk(int index) { return Structure.add(FreeChunkHolder.class, currentChunkPointer, index); }
public static RuntimeObject alloc(int size) { FreeChunk current = currentChunk; Address next = current.toAddress().add(size); if (!next.add(Structure.sizeOf(FreeChunk.class)).isLessThan(currentChunkLimit)) { getAvailableChunk(size); current = currentChunk; next = currentChunk.toAddress().add(size); } int freeSize = current.size; freeSize -= size; if (freeSize > 0) { currentChunk = next.toStructure(); currentChunk.size = freeSize; } else { freeMemory -= size; getAvailableChunkIfPossible(currentChunk.size + 1); } currentChunk.classReference = 0; freeMemory -= size; return current.toAddress().toStructure(); }
private static boolean getAvailableChunkIfPossible(int size) { if (freeChunks == 0) { return false; } while (true) { if (currentChunk.toAddress().add(size) == currentChunkLimit) { break; } if (currentChunk.toAddress().add(size + Structure.sizeOf(FreeChunk.class)).isLessThan(currentChunkLimit)) { break; } if (--freeChunks == 0) { return false; } freeMemory -= currentChunk.size; currentChunkPointer = Structure.add(FreeChunkHolder.class, currentChunkPointer, 1); currentChunk = currentChunkPointer.value; currentChunkLimit = currentChunk.toAddress().add(currentChunk.size); } return true; }
@Unmanaged public static void throwException(Throwable exception) { thrownException = exception; RuntimeObject exceptionPtr = Address.ofObject(exception).toStructure(); RuntimeClass exceptionClass = RuntimeClass.getClass(exceptionPtr); Address stackFrame = ShadowStack.getStackTop(); stackLoop: while (stackFrame != null) { int callSiteId = ShadowStack.getCallSiteId(stackFrame); CallSite callSite = findCallSiteById(callSiteId); ExceptionHandler handler = callSite.firstHandler; for (int i = 0; i < callSite.handlerCount; ++i) { if (handler.exceptionClass == null || handler.exceptionClass.isSupertypeOf.apply(exceptionClass)) { ShadowStack.setExceptionHandlerId(stackFrame, handler.id); break stackLoop; } handler = Structure.add(ExceptionHandler.class, handler, 1); } ShadowStack.setExceptionHandlerId(stackFrame, callSiteId - 1); stackFrame = ShadowStack.getNextStackFrame(stackFrame); } }
private static int objectSize(FreeChunk object) { if (object.classReference == 0) { return object.size; } else { RuntimeClass cls = RuntimeClass.getClass(object.toAddress().toStructure()); if (cls.itemType == null) { return cls.size; } else { int itemSize = (cls.itemType.flags & RuntimeClass.PRIMITIVE) == 0 ? Address.sizeOf() : cls.itemType.size; RuntimeArray array = object.toAddress().toStructure(); Address address = Address.fromInt(Structure.sizeOf(RuntimeArray.class)); address = Address.align(address, itemSize); address = address.add(itemSize * array.size); address = Address.align(address, Address.sizeOf()); return address.toInt(); } } }
@Unmanaged public static RuntimeArray allocateMultiArray(RuntimeClass tag, Address dimensions, int dimensionCount) { int size = dimensions.getInt(); RuntimeArray array = allocateArray(tag, dimensions.getInt()).toStructure(); if (dimensionCount > 1) { Address arrayData = Structure.add(RuntimeArray.class, array, 1).toAddress(); arrayData = Address.align(arrayData, Address.sizeOf()); for (int i = 0; i < size; ++i) { RuntimeArray innerArray = allocateMultiArray(tag.itemType, dimensions.add(4), dimensionCount - 1); arrayData.putAddress(innerArray.toAddress()); arrayData = arrayData.add(Address.sizeOf()); } } return array; }
private static void mark() { Allocator.fillZero(regionsAddress().toAddress(), regionMaxCount() * Structure.sizeOf(Region.class)); Address staticRoots = Mutator.getStaticGCRoots(); int staticCount = staticRoots.getInt(); staticRoots = staticRoots.add(Address.sizeOf()); while (staticCount-- > 0) { RuntimeObject object = staticRoots.getAddress().getAddress().toStructure(); if (object != null) { mark(object); } staticRoots = staticRoots.add(Address.sizeOf()); } for (Address stackRoots = ShadowStack.getStackTop(); stackRoots != null; stackRoots = ShadowStack.getNextStackFrame(stackRoots)) { int count = ShadowStack.getStackRootCount(stackRoots); Address stackRootsPtr = ShadowStack.getStackRootPointer(stackRoots); while (count-- > 0) { RuntimeObject obj = stackRootsPtr.getAddress().toStructure(); mark(obj); stackRootsPtr = stackRootsPtr.add(Address.sizeOf()); } } }
Region currentRegion = Structure.add(Region.class, regionsAddress(), currentRegionIndex); if (currentRegion.start == 0) { do { break loop; currentRegion = Structure.add(Region.class, regionsAddress(), currentRegionIndex); } while (currentRegion.start == 0); lastFreeSpace.size = (int) (object.toAddress().toLong() - lastFreeSpace.toAddress().toLong()); freeChunkPtr.value = lastFreeSpace; freeChunkPtr = Structure.add(FreeChunkHolder.class, freeChunkPtr, 1); freeChunks++; reclaimedSpace += lastFreeSpace.size; lastFreeSpace.size = freeSize; freeChunkPtr.value = lastFreeSpace; freeChunkPtr = Structure.add(FreeChunkHolder.class, freeChunkPtr, 1); freeChunks++; reclaimedSpace += freeSize;
private static int objectSize(RuntimeObject object) { if (object.classReference == 0) { return ((FreeChunk) object).size; } else { RuntimeClass cls = RuntimeClass.getClass(object); if (cls.itemType == null) { return cls.size; } else { int itemSize = (cls.itemType.flags & RuntimeClass.PRIMITIVE) == 0 ? Address.sizeOf() : cls.itemType.size; RuntimeArray array = (RuntimeArray) object; Address address = Address.fromInt(Structure.sizeOf(RuntimeArray.class)); address = Address.align(address, itemSize); address = address.add(itemSize * array.size); address = Address.align(address, 4); return address.toInt(); } } }
Region region = Structure.add(Region.class, regionsAddress(), (int) (offset / regionSize())); short relativeOffset = (short) (offset % regionSize() + 1); if (region.start == 0 || region.start > relativeOffset) {
public static RuntimeObject alloc(int size) { FreeChunk current = currentChunk; Address next = currentChunk.toAddress().add(size); if (!next.add(Structure.sizeOf(FreeChunk.class)).isLessThan(currentChunkLimit)) { getAvailableChunk(size); current = currentChunk; next = currentChunk.toAddress().add(size); } int freeSize = current.size; freeSize -= size; if (freeSize > 0) { currentChunk = next.toStructure(); currentChunk.size = freeSize; } else { freeMemory -= size; getAvailableChunkIfPossible(currentChunk.size + 1); } currentChunk.classReference = 0; freeMemory -= size; return current; }
private static void updateFreeMemory() { freeMemory = 0; FreeChunkHolder freeChunkPtr = currentChunkPointer; for (int i = 0; i < freeChunks; ++i) { freeMemory += freeChunkPtr.value.size; freeChunkPtr = Structure.add(FreeChunkHolder.class, freeChunkPtr, 1); } }
public static Address allocateArray(RuntimeClass tag, int size) { int itemSize = (tag.itemType.flags & RuntimeClass.PRIMITIVE) != 0 ? tag.itemType.size : 4; int sizeInBytes = Address.align(Address.fromInt(Structure.sizeOf(RuntimeArray.class)), itemSize).toInt(); sizeInBytes += itemSize * size; sizeInBytes = Address.align(Address.fromInt(sizeInBytes), 4).toInt(); Address result = GC.alloc(sizeInBytes).toAddress(); fillZero(result, sizeInBytes); RuntimeArray array = result.toStructure(); array.classReference = tag.toAddress().toInt() >> 3; array.size = size; return result; }
private static FreeChunkHolder getFreeChunk(int index) { return Structure.add(FreeChunkHolder.class, currentChunkPointer, index); }
private static void mark() { Allocator.fillZero(regionsAddress().toAddress(), regionMaxCount() * Structure.sizeOf(Region.class)); Address staticRoots = Mutator.getStaticGCRoots(); int staticCount = staticRoots.getInt(); staticRoots = staticRoots.add(8); while (staticCount-- > 0) { RuntimeObject object = staticRoots.getAddress().getAddress().toStructure(); if (object != null) { mark(object); } staticRoots = staticRoots.add(Address.sizeOf()); } for (Address stackRoots = ShadowStack.getStackTop(); stackRoots != null; stackRoots = ShadowStack.getNextStackFrame(stackRoots)) { int count = ShadowStack.getStackRootCount(stackRoots); Address stackRootsPtr = ShadowStack.getStackRootPointer(stackRoots); while (count-- > 0) { RuntimeObject obj = stackRootsPtr.getAddress().toStructure(); mark(obj); stackRootsPtr = stackRootsPtr.add(Address.sizeOf()); } } }
public static RuntimeArray allocateMultiArray(RuntimeClass tag, Address dimensions, int dimensionCount) { int size = dimensions.getInt(); RuntimeArray array = allocateArray(tag, dimensions.getInt()).toStructure(); if (dimensionCount > 1) { Address arrayData = Structure.add(RuntimeArray.class, array, 1).toAddress(); arrayData = Address.align(arrayData, Address.sizeOf()); for (int i = 0; i < size; ++i) { RuntimeArray innerArray = allocateMultiArray(tag.itemType, dimensions.add(4), dimensionCount - 1); arrayData.putAddress(innerArray.toAddress()); arrayData = arrayData.add(Address.sizeOf()); } } return array; }