if (nextFreePtr.EQ(Address.zero())) { /* This heap is full */
return null;
}
final Offset tibOffset = this.tibOffset;
final Word headerSize = Word.fromIntZeroExtend(this.headerSize);
final Offset flagsOffset = this.flagsOffset;
final Offset sizeOffset = this.sizeOffset;
Word alignedSizeW = Word.fromIntZeroExtend(alignedSize);
final Word totalSize = alignedSizeW.add(headerSize);
final Object tib = vmClass.getTIB();
if (tib == null) {
throw new IllegalArgumentException("vmClass.TIB is null");
}
//final int size = getSize();
Address objectPtr = Address.zero();
lock();
try {
// Search for the first free block that is large enough
//Screen.debug("a");
while (objectPtr == null) {
final Address ptr = nextFreePtr;
final Word objSize = ptr.loadWord(sizeOffset);
final Object objVmt = ptr.loadObjectReference(tibOffset);
final Address nextPtr = ptr.add(objSize.add(headerSize));
if ((objVmt == FREE) && alignedSizeW.LE(objSize)) {
objectPtr = ptr;
} else {
if (!inHeap(nextPtr)) {
// No large enough free space has been found
// A collect may recover smaller free spaces in this
// heap, but we leave that to a GC iteration.
nextFreePtr = Address.zero();
//Screen.debug("B");
return null;
} else {
this.nextFreePtr = nextPtr;
}
}
}
//Screen.debug("A");
final Word curFreeSize = objectPtr.loadWord(sizeOffset);
if (curFreeSize.GT(totalSize)) {
// Block is larger then we need, split it up.
final Word newFreeSize = curFreeSize.sub(totalSize);
/*if (newFreeSize <= headerSize) {
Unsafe.debug("Block splitup failed");
Unsafe.debug("\ncurFreeSize "); Unsafe.debug(curFreeSize);
Unsafe.debug("\ntotalSize "); Unsafe.debug(totalSize);
Unsafe.debug("\nnewFreeSize "); Unsafe.debug(newFreeSize);