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(); } } }
private static int resourceMapSize(Address map) { int result = 0; int sz = map.getInt(); Address data = contentStart(map); for (int i = 0; i < sz; ++i) { if (data.getAddress() != null) { result++; } data = data.add(Address.sizeOf() * 2); } return result; }
@Unmanaged private void setSimpleNameCacheLowLevel(RuntimeObject object) { Address.ofObject(this).<RuntimeClass>toStructure().simpleName = object; }
long offset = object.toAddress().toLong() - heapAddress().toLong(); Region region = Structure.add(Region.class, regionsAddress(), (int) (offset / regionSize())); short relativeOffset = (short) (offset % regionSize() + 1); Address layout = cls.layout; if (layout != null) { short fieldCount = layout.getShort(); while (fieldCount-- > 0) { layout = layout.add(2); int fieldOffset = layout.getShort(); RuntimeObject reference = object.toAddress().add(fieldOffset).getAddress().toStructure(); if (reference != null && !isMarked(reference)) { MarkQueue.enqueue(reference); if ((cls.itemType.flags & RuntimeClass.PRIMITIVE) == 0) { RuntimeArray array = (RuntimeArray) object; Address base = Address.align(array.toAddress().add(RuntimeArray.class, 1), Address.sizeOf()); for (int i = 0; i < array.size; ++i) { RuntimeObject reference = base.getAddress().toStructure(); if (reference != null && !isMarked(reference)) { MarkQueue.enqueue(reference); base = base.add(Address.sizeOf());
int diff = source.toInt() - target.toInt(); if (diff == 0) { return; Address alignedSourceStart = Address.fromInt(source.toInt() >>> 2 << 2); Address alignedTargetStart = Address.fromInt(target.toInt() >>> 2 << 2); Address alignedSourceEnd = Address.fromInt((source.toInt() + count) >>> 2 << 2); Address alignedTargetEnd = Address.fromInt((target.toInt() + count) >>> 2 << 2); if (source.toInt() > target.toInt()) { switch (source.toInt() - alignedSourceStart.toInt()) { case 0: alignedTargetStart.putInt(alignedSourceStart.getInt()); break; case 1: alignedTargetStart.add(1).putByte(alignedSourceStart.add(1).getByte()); alignedTargetStart.add(2).putShort(alignedSourceStart.add(2).getShort()); break; case 2: alignedTargetStart.add(2).putShort(alignedSourceStart.add(2).getShort()); break; case 3: alignedTargetStart.add(3).putByte(alignedSourceStart.add(3).getByte()); break; alignedSourceStart = alignedSourceStart.add(4); alignedTargetStart = alignedTargetStart.add(4);
@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; }
public static void fillZero(Address address, int count) { int start = address.toInt(); address = Address.fromInt(alignedStart); switch (start - alignedStart) { case 0: address.putInt(0); break; case 1: address.add(1).putByte((byte) 0); address.add(2).putShort((short) 0); break; case 2: address.add(2).putShort((short) 0); break; case 3: address.add(3).putByte((byte) 0); break; address = Address.fromInt(alignedEnd); switch (end - alignedEnd) { case 0: break; case 1: address.putByte((byte) 0); break; case 2: address.putShort((short) 0); break; case 3:
private static void fillResourceMapKeys(Address map, String[] target) { int sz = map.getInt(); Address data = contentStart(map); Address targetData = Address.ofData(target); for (int i = 0; i < sz; ++i) { Address entry = data.getAddress(); if (entry != null) { targetData.putAddress(entry); targetData = targetData.add(Address.sizeOf()); } data = data.add(Address.sizeOf()); } }
@Unmanaged private static void fillEnumConstantsImpl(RuntimeClass cls, Address[] array) { Address enumValues = cls.enumValues; for (int i = 0; i < array.length; i++) { enumValues = enumValues.add(Address.sizeOf()); array[i] = enumValues.getAddress().getAddress(); } }
private static void slowMemoryMove(Address source, Address target, int count) { if (source.toInt() > target.toInt()) { while (count-- > 0) { target.putByte(source.getByte()); target = target.add(1); source = source.add(1); } } else { source = source.add(count); target = target.add(count); while (count-- > 0) { target = target.add(-1); source = source.add(-1); target.putByte(source.getByte()); } } }
@Unmanaged static void doArrayCopyLowLevel(RuntimeArray src, int srcPos, RuntimeArray dest, int destPos, int length) { RuntimeClass type = RuntimeClass.getClass(src); int itemSize = type.itemType.size; if ((type.itemType.flags & RuntimeClass.PRIMITIVE) == 0) { itemSize = Address.sizeOf(); } Address srcAddress = Address.align(src.toAddress().add(RuntimeArray.class, 1), itemSize); srcAddress = srcAddress.add(itemSize * srcPos); Address destAddress = Address.align(dest.toAddress().add(RuntimeArray.class, 1), itemSize); destAddress = destAddress.add(itemSize * destPos); Allocator.moveMemoryBlock(srcAddress, destAddress, length * itemSize); }
static void enqueue(RuntimeObject object) { GC.gcStorageAddress().add(Address.sizeOf() * tail).putAddress(object.toAddress()); if (++tail >= limit) { tail = 0; } }
private static void sweep() { FreeChunkHolder freeChunkPtr = gcStorageAddress().toStructure(); freeChunks = 0; FreeChunk object = heapAddress().toStructure(); FreeChunk lastFreeSpace = null; long heapSize = availableBytes(); int currentRegionIndex = 0; int regionsCount = (int) ((heapSize - 1) / regionSize()) + 1; Address currentRegionEnd = object.toAddress().add(regionSize()); Address limit = heapAddress().add(heapSize); loop: while (object.toAddress().isLessThan(limit)) { int tag = object.classReference; boolean free; if (!object.toAddress().isLessThan(currentRegionEnd)) { currentRegionIndex = (int) ((object.toAddress().toLong() - heapAddress().toLong()) / regionSize()); Region currentRegion = Structure.add(Region.class, regionsAddress(), currentRegionIndex); if (currentRegion.start == 0) { do { if (++currentRegionIndex == regionsCount) { object = limit.toStructure(); break loop; currentRegionEnd = currentRegion.toAddress().add(regionSize()); lastFreeSpace.size = (int) (object.toAddress().toLong() - lastFreeSpace.toAddress().toLong()); freeChunkPtr.value = lastFreeSpace;
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(); }
@Unmanaged private static int getEnumConstantsSizeImpl(RuntimeClass cls) { Address enumValues = cls.enumValues; if (enumValues == null) { return -1; } return enumValues.getAddress().toInt(); }