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);
Unsafe.debug("\nheaderSize "); Unsafe.debug(headerSize);
throw new Error("Block splitup failed");
}*/
final Address newFreePtr = objectPtr.add(totalSize);
// Set the header for the remaining free block
newFreePtr.store(newFreeSize, sizeOffset);
newFreePtr.store(0, flagsOffset);
newFreePtr.store(ObjectReference.fromObject(FREE), tibOffset);
// Set the next free offset
nextFreePtr = newFreePtr;
} else {
// The block is not large enough to split up, make the
// new object the size of the free block.