work on LaxMalloc

This commit is contained in:
lax1dude 2024-11-01 17:47:27 -07:00
parent f266d21f58
commit 9181299a6d

View File

@ -82,6 +82,9 @@ public final class LaxMalloc {
sizeBytes = MIN_ALLOC_SIZE; sizeBytes = MIN_ALLOC_SIZE;
} }
// Make sure all allocations are at least a multiple of 4 to maintain alignment
sizeBytes = (sizeBytes + 3) & 0xFFFFFFFC;
// always between 0-63 // always between 0-63
int bucket = getListBucket(sizeBytes); int bucket = getListBucket(sizeBytes);
@ -124,7 +127,7 @@ public final class LaxMalloc {
Address bucketStartAddr = Address.fromInt(ADDR_HEAP_BUCKETS_START).add(availableBucket << SIZEOF_PTR_SH); Address bucketStartAddr = Address.fromInt(ADDR_HEAP_BUCKETS_START).add(availableBucket << SIZEOF_PTR_SH);
Address chunkPtr = bucketStartAddr.getAddress(); Address chunkPtr = bucketStartAddr.getAddress();
int chunkSize = readChunkSize(chunkPtr); int chunkSize = readChunkSize(chunkPtr);
boolean bucketHasMultipleChunks = false; Address itrChunkStart = Address.fromInt(0);
// check if the first chunk in the bucket is large enough // check if the first chunk in the bucket is large enough
if(chunkSize - 8 < sizeBytes) { // size - 2 ints if(chunkSize - 8 < sizeBytes) { // size - 2 ints
@ -136,8 +139,7 @@ public final class LaxMalloc {
Address chunkNextPtr = readChunkNextFreeAddr(chunkPtr); Address chunkNextPtr = readChunkNextFreeAddr(chunkPtr);
if(chunkNextPtr.getInt() != chunkPtr.getInt()) { if(chunkNextPtr.getInt() != chunkPtr.getInt()) {
bucketStartAddr.putAddress(chunkNextPtr); bucketStartAddr.putAddress(chunkNextPtr);
chunkPtr = chunkNextPtr; itrChunkStart = chunkNextPtr;
bucketHasMultipleChunks = true;
} }
// extend mask to the next bucket // extend mask to the next bucket
@ -179,15 +181,15 @@ public final class LaxMalloc {
return ret; return ret;
} }
if(bucketHasMultipleChunks) { if(itrChunkStart.toInt() != 0) {
// if we've reached this point, it means the first chunk in the bucket wasn't large enough // if we've reached this point, it means the first chunk in the bucket wasn't large enough
// and there weren't any chunks in the larger buckets we could split up // and there weren't any chunks in the larger buckets we could split up
// so we need to look closer // so we need to look closer
// iterate the (only) bucket of possibly large enough chunks // iterate the (only) bucket of possibly large enough chunks
Address addrIterator = chunkPtr; Address addrIterator = itrChunkStart;
while((addrIterator = readChunkNextFreeAddr(addrIterator)).getInt() != chunkPtr.getInt()) { do {
chunkSize = readChunkSize(addrIterator); chunkSize = readChunkSize(addrIterator);
// check if the chunk is large enough // check if the chunk is large enough
@ -206,7 +208,7 @@ public final class LaxMalloc {
return ret; return ret;
} }
} }while((addrIterator = readChunkNextFreeAddr(addrIterator)).getInt() != chunkPtr.getInt());
} }
// no other options, time to sbrk // no other options, time to sbrk
@ -292,11 +294,12 @@ public final class LaxMalloc {
// chunk actually starts 4 bytes before // chunk actually starts 4 bytes before
Address chunkPtr = address.add(-4); Address chunkPtr = address.add(-4);
// set the chunk no longer in use
setChunkInUse(chunkPtr, false);
// bring the size of the chunk into the stack // bring the size of the chunk into the stack
int chunkSize = chunkPtr.getInt(); int chunkSize = chunkPtr.getInt();
boolean sizeChanged = false;
// set the chunk no longer in use
chunkSize &= 0x7FFFFFFF;
if(Address.fromInt(ADDR_HEAP_DATA_START).isLessThan(chunkPtr)) { if(Address.fromInt(ADDR_HEAP_DATA_START).isLessThan(chunkPtr)) {
// check if we can merge with the previous chunk, and move it to another bucket // check if we can merge with the previous chunk, and move it to another bucket
@ -311,8 +314,7 @@ public final class LaxMalloc {
// resize the current chunk to also contain the previous chunk // resize the current chunk to also contain the previous chunk
chunkPtr = prevChunkPtr; chunkPtr = prevChunkPtr;
chunkSize += prevChunkSize; chunkSize += prevChunkSize;
chunkPtr.putInt(chunkSize); sizeChanged = true;
chunkPtr.add(chunkSize - 4).putInt(chunkSize);
} }
} }
@ -328,11 +330,18 @@ public final class LaxMalloc {
// resize the current chunk to also contain the next chunk // resize the current chunk to also contain the next chunk
chunkSize += nextChunkSize; chunkSize += nextChunkSize;
chunkPtr.putInt(chunkSize); sizeChanged = true;
chunkPtr.add(chunkSize - 4).putInt(chunkSize);
} }
} }
// store the final chunk size (also clears the in use flag)
chunkPtr.putInt(chunkSize);
if(sizeChanged) {
// if the size of the chunk changed, we also need to update the chunk's second size integer
chunkPtr.add(chunkSize - 4).putInt(chunkSize);
}
// add the final chunk to the free chunks list // add the final chunk to the free chunks list
linkChunkInFreeList(chunkPtr, chunkSize); linkChunkInFreeList(chunkPtr, chunkSize);
} }
@ -368,7 +377,7 @@ public final class LaxMalloc {
}else { }else {
// not large enough to split, just take the entire chunk // not large enough to split, just take the entire chunk
setChunkInUse(chunkPtr, true); chunkPtr.putInt(chunkSize | 0x80000000); // sets the in use flag
} }
} }
@ -508,11 +517,6 @@ public final class LaxMalloc {
chunkAddr.putInt(sizeStatus); chunkAddr.putInt(sizeStatus);
} }
private static void setChunkInUse(Address chunkAddr, boolean inUse) {
int i = chunkAddr.getInt();
chunkAddr.putInt(inUse ? (i | 0x80000000) : (i & 0x7FFFFFFF));
}
private static Address readChunkPrevFreeAddr(Address chunkAddr) { private static Address readChunkPrevFreeAddr(Address chunkAddr) {
return chunkAddr.add(4).getAddress(); return chunkAddr.add(4).getAddress();
} }