diff options
| author | Dylan Ascencio <empressglatia@gmail.com> | 2023-09-16 18:13:11 -0400 |
|---|---|---|
| committer | Dylan Ascencio <empressglatia@gmail.com> | 2023-09-16 18:13:11 -0400 |
| commit | e940e4f4e0961aaa01c687dbfd96fdb6dec02cfe (patch) | |
| tree | d22f3e7228cf89ac7152517c98149b4778c6db04 /src/JSystem/JKernel/JKRExpHeap.cpp | |
| parent | 331847e88ff809875cb2b643e8434a3a10b7446e (diff) | |
| parent | f0cc6a9bef1422bb5d63cfe452772a76499ea0fd (diff) | |
Merge remote-tracking branch 'upstream/main'
Diffstat (limited to 'src/JSystem/JKernel/JKRExpHeap.cpp')
| -rw-r--r-- | src/JSystem/JKernel/JKRExpHeap.cpp | 952 |
1 files changed, 872 insertions, 80 deletions
diff --git a/src/JSystem/JKernel/JKRExpHeap.cpp b/src/JSystem/JKernel/JKRExpHeap.cpp index e09b0383..7cbc894e 100644 --- a/src/JSystem/JKernel/JKRExpHeap.cpp +++ b/src/JSystem/JKernel/JKRExpHeap.cpp @@ -4,209 +4,1001 @@ // #include "JSystem/JKernel/JKRExpHeap.h" +#include "JSystem/JSupport/JSupport.h" +#include "JSystem/JUtility/JUTAssert.h" +#include "JSystem/JUtility/JUTConsole.h" +#include "JSystem/JUtility/JUTException.h" +#include "dolphin/os/OS.h" #include "dolphin/types.h" /* 802B1558-802B15D0 .text createRoot__10JKRExpHeapFib */ -void JKRExpHeap::createRoot(int, bool) { - /* Nonmatching */ +JKRExpHeap* JKRExpHeap::createRoot(int maxHeaps, bool errorFlag) { + JKRExpHeap* heap = NULL; + if (!sRootHeap) { + void* memory; + u32 memorySize; + initArena((char**)&memory, &memorySize, maxHeaps); + u8* start = (u8*)memory + OSRoundUp(sizeof(JKRExpHeap), 0x10); + u32 alignedSize = memorySize - OSRoundUp(sizeof(JKRExpHeap), 0x10); + heap = new (memory) JKRExpHeap(start, alignedSize, NULL, errorFlag); + sRootHeap = heap; + } + heap->field_0x6e = true; + return heap; } /* 802B15D0-802B16A4 .text create__10JKRExpHeapFUlP7JKRHeapb */ -void JKRExpHeap::create(unsigned long, JKRHeap*, bool) { - /* Nonmatching */ +JKRExpHeap* JKRExpHeap::create(u32 size, JKRHeap* parent, bool errorFlag) { + if (!parent) { + parent = sRootHeap; + } + + if (size == 0xffffffff) { + size = parent->getMaxAllocatableSize(0x10); + } + + u32 alignedSize = OSRoundDown(size, 0x10); + u32 expHeapSize = OSRoundUp(sizeof(JKRExpHeap), 0x10); + if (alignedSize < 0xa0) + return NULL; + + u8* memory = (u8*)JKRAllocFromHeap(parent, alignedSize, 0x10); + u8* dataPtr = (memory + expHeapSize); + if (!memory) { + return NULL; + } + + JKRExpHeap* newHeap = + new (memory) JKRExpHeap(dataPtr, alignedSize - expHeapSize, parent, errorFlag); + + if (newHeap == NULL) { + i_JKRFree(memory); + return NULL; + } + + newHeap->field_0x6e = false; + return newHeap; } /* 802B16A4-802B1728 .text do_destroy__10JKRExpHeapFv */ void JKRExpHeap::do_destroy() { - /* Nonmatching */ + if (!field_0x6e) { + JKRHeap* heap = mChildTree.getParent()->getObject(); + if (heap) { + this->~JKRExpHeap(); + JKRHeap::free(this, heap); + } + } else { + this->~JKRExpHeap(); + } } /* 802B1728-802B17B8 .text __ct__10JKRExpHeapFPvUlP7JKRHeapb */ -JKRExpHeap::JKRExpHeap(void*, unsigned long, JKRHeap*, bool) { - /* Nonmatching */ +JKRExpHeap::JKRExpHeap(void* data, u32 size, JKRHeap* parent, bool errorFlag) : JKRHeap(data, size, parent, errorFlag) { + mAllocMode = 0; + mCurrentGroupId = 0xff; + mHeadFreeList = (CMemBlock*)data; + mTailFreeList = mHeadFreeList; + mHeadFreeList->initiate(NULL, NULL, size - sizeof(CMemBlock), 0, 0); + mHeadUsedList = NULL; + mTailUsedList = NULL; } /* 802B17B8-802B1820 .text __dt__10JKRExpHeapFv */ JKRExpHeap::~JKRExpHeap() { - /* Nonmatching */ + dispose(); } /* 802B1820-802B192C .text do_alloc__10JKRExpHeapFUli */ -void JKRExpHeap::do_alloc(unsigned long, int) { - /* Nonmatching */ -} +void* JKRExpHeap::do_alloc(u32 size, int alignment) { + void* ptr; + + lock(); + if (size < 4) { + size = 4; + } + + if (alignment >= 0) { + if (alignment <= 4) { + ptr = allocFromHead(size); + } else { + ptr = allocFromHead(size, alignment); + } + } else { + if (-alignment <= 4) { + ptr = allocFromTail(size); + } else { + ptr = allocFromTail(size, -alignment); + } + } + + if (ptr == NULL) { + JUTWarningConsole_f(":::cannot alloc memory (0x%x byte).\n", size); + if (mErrorFlag == true) { + callErrorHandler(this, size, alignment); + } + } + unlock(); + + return ptr; +} + +static u32 DBfoundSize; +static u32 DBfoundOffset; +static JKRExpHeap::CMemBlock* DBfoundBlock; +static JKRExpHeap::CMemBlock* DBnewFreeBlock; +static JKRExpHeap::CMemBlock* DBnewUsedBlock; /* 802B192C-802B1B88 .text allocFromHead__10JKRExpHeapFUli */ -void JKRExpHeap::allocFromHead(unsigned long, int) { - /* Nonmatching */ +// wrong register at end +void* JKRExpHeap::allocFromHead(u32 size, int align) { + /* Nonmatching */ + u32 foundOffset; + int foundSize; + CMemBlock* newFreeBlock; + CMemBlock* newUsedBlock; + CMemBlock* foundBlock; + + size = ALIGN_NEXT(size, 4); + foundSize = -1; + foundOffset = 0; + foundBlock = NULL; + + for (CMemBlock* block = mHeadFreeList; block; block = block->mNext) { + u32 offset = + ALIGN_PREV(align - 1 + (u32)block->getContent(), align) - (u32)block->getContent(); + if (block->size < size + offset) { + continue; + } + + if (foundSize <= (u32)block->size) { + continue; + } + + foundSize = block->size; + foundBlock = block; + foundOffset = offset; + if (mAllocMode != 0) { + break; + } + + u32 blockSize = block->size; + if (blockSize == size) { + break; + } + } + + DBfoundSize = foundSize; + DBfoundOffset = foundOffset; + DBfoundBlock = foundBlock; + + if (foundBlock) { + if (foundOffset >= sizeof(CMemBlock)) { + CMemBlock* prev = foundBlock->mPrev; + CMemBlock* next = foundBlock->mNext; + newUsedBlock = foundBlock->allocFore(foundOffset - sizeof(CMemBlock), 0, 0, 0, 0); + + if (newUsedBlock) { + newFreeBlock = newUsedBlock->allocFore(size, mCurrentGroupId, 0, 0, 0); + } else { + newFreeBlock = NULL; + } + + if (newFreeBlock) { + setFreeBlock(foundBlock, prev, newFreeBlock); + } else { + setFreeBlock(foundBlock, prev, next); + } + + if (newFreeBlock) { + setFreeBlock(newFreeBlock, foundBlock, next); + } + + appendUsedList(newUsedBlock); + DBnewFreeBlock = newFreeBlock; + DBnewUsedBlock = newUsedBlock; + return newUsedBlock->getContent(); + } else { + if (foundOffset != 0) { + CMemBlock* prev = foundBlock->mPrev; + CMemBlock* next = foundBlock->mNext; + removeFreeBlock(foundBlock); + newUsedBlock = (CMemBlock*)((u32)foundBlock + foundOffset); + newUsedBlock->size = foundBlock->size - foundOffset; + newFreeBlock = + newUsedBlock->allocFore(size, mCurrentGroupId, (u8)foundOffset, 0, 0); + if (newFreeBlock) { + setFreeBlock(newFreeBlock, prev, next); + } + appendUsedList(newUsedBlock); + return newUsedBlock->getContent(); + } else { + CMemBlock* prev = foundBlock->mPrev; + CMemBlock* next = foundBlock->mNext; + // Works but very fake match + /*size = (u32)foundBlock->allocFore(size, mCurrentGroupId, 0, 0, 0); + removeFreeBlock(foundBlock); + if (size) { + setFreeBlock((CMemBlock*)size, prev, next); + }*/ + newFreeBlock = foundBlock->allocFore(size, mCurrentGroupId, 0, 0, 0); + removeFreeBlock(foundBlock); + if (newFreeBlock) { + setFreeBlock(newFreeBlock, prev, next); + } + appendUsedList(foundBlock); + return foundBlock->getContent(); + } + } + } + + return NULL; } /* 802B1B88-802B1C6C .text allocFromHead__10JKRExpHeapFUl */ -void JKRExpHeap::allocFromHead(unsigned long) { - /* Nonmatching */ +void* JKRExpHeap::allocFromHead(u32 size) { + size = ALIGN_NEXT(size, 4); + s32 foundSize = -1; + CMemBlock* foundBlock = NULL; + for (CMemBlock* block = mHeadFreeList; block; block = block->getNextBlock()) { + if (block->getSize() < size) { + continue; + } + + if (foundSize <= block->getSize()) { + continue; + } + + foundSize = block->getSize(); + foundBlock = block; + if (mAllocMode != 0) { + break; + } + + if (foundSize == size) { + break; + } + } + + if (foundBlock) { + CMemBlock* newblock = foundBlock->allocFore(size, mCurrentGroupId, 0, 0, 0); + if (newblock) { + setFreeBlock(newblock, foundBlock->getPrevBlock(), foundBlock->getNextBlock()); + } else { + removeFreeBlock(foundBlock); + } + appendUsedList(foundBlock); + return foundBlock->getContent(); + } + return NULL; } /* 802B1C6C-802B1DCC .text allocFromTail__10JKRExpHeapFUli */ -void JKRExpHeap::allocFromTail(unsigned long, int) { - /* Nonmatching */ +void* JKRExpHeap::allocFromTail(u32 size, int align) { + u32 offset = 0; + CMemBlock* foundBlock = NULL; + CMemBlock* newBlock = NULL; + u32 usedSize; + u32 start; + + for (CMemBlock* block = mTailFreeList; block; block = block->mPrev) { + start = ALIGN_PREV((u32)block->getContent() + block->size - size, align); + usedSize = (u32)block->getContent() + block->size - start; + if (block->size >= usedSize) { + foundBlock = block; + offset = block->size - usedSize; + newBlock = (CMemBlock*)start - 1; + break; + } + } + + if (foundBlock != NULL) { + if (offset >= sizeof(CMemBlock)) { + newBlock->initiate(NULL, NULL, usedSize, mCurrentGroupId, -0x80); + foundBlock->size = foundBlock->size - usedSize - sizeof(CMemBlock); + appendUsedList(newBlock); + return newBlock->getContent(); + } else { + if (offset != 0) { + removeFreeBlock(foundBlock); + newBlock->initiate(NULL, NULL, usedSize, mCurrentGroupId, offset | 0x80); + appendUsedList(newBlock); + return newBlock->getContent(); + } else { + removeFreeBlock(foundBlock); + newBlock->initiate(NULL, NULL, usedSize, mCurrentGroupId, -0x80); + appendUsedList(newBlock); + return newBlock->getContent(); + } + } + } + + return NULL; } /* 802B1DCC-802B1EA4 .text allocFromTail__10JKRExpHeapFUl */ -void JKRExpHeap::allocFromTail(unsigned long) { - /* Nonmatching */ +void* JKRExpHeap::allocFromTail(u32 size) { + u32 size2 = ALIGN_NEXT(size, 4); + CMemBlock* foundBlock = NULL; + for (CMemBlock* block = mTailFreeList; block; block = block->getPrevBlock()) { + if (block->getSize() >= size2) { + foundBlock = block; + break; + } + } + + if (foundBlock != NULL) { + CMemBlock* usedBlock = foundBlock->allocBack(size2, 0, 0, mCurrentGroupId, 0); + CMemBlock* freeBlock; + if (usedBlock) { + freeBlock = foundBlock; + } else { + removeFreeBlock(foundBlock); + usedBlock = foundBlock; + freeBlock = NULL; + } + + if (freeBlock) { + setFreeBlock(freeBlock, foundBlock->getPrevBlock(), foundBlock->getNextBlock()); + } + appendUsedList(usedBlock); + return usedBlock->getContent(); + } + return NULL; } /* 802B1EA4-802B1F44 .text do_free__10JKRExpHeapFPv */ -void JKRExpHeap::do_free(void*) { - /* Nonmatching */ +void JKRExpHeap::do_free(void* ptr) { + lock(); + if (getStartAddr() <= ptr && ptr <= getEndAddr()) { + CMemBlock* block = CMemBlock::getHeapBlock(ptr); + if (block) { + block->free(this); + } + } else { + JUT_WARN(888, "free: memblock %x not in heap %x", ptr, this); + } + unlock(); } /* 802B1F44-802B1FC0 .text do_freeAll__10JKRExpHeapFv */ void JKRExpHeap::do_freeAll() { - /* Nonmatching */ + lock(); + JKRHeap::callAllDisposer(); + mHeadFreeList = (CMemBlock*)getStartAddr(); + mTailFreeList = mHeadFreeList; + mHeadFreeList->initiate(NULL, NULL, getSize() - 0x10, 0, 0); + mHeadUsedList = NULL; + mTailUsedList = NULL; + unlock(); } /* 802B1FC0-802B2048 .text do_freeTail__10JKRExpHeapFv */ void JKRExpHeap::do_freeTail() { - /* Nonmatching */ + lock(); + for (CMemBlock* block = mHeadUsedList; block != NULL;) { + if ((block->mFlags & 0x80) != 0) { + dispose(block + 1, block->size); + CMemBlock* temp = block->mNext; + block->free(this); + block = temp; + } else { + block = block->mNext; + } + } + unlock(); } /* 802B2048-802B2098 .text do_changeGroupID__10JKRExpHeapFUc */ -void JKRExpHeap::do_changeGroupID(unsigned char) { - /* Nonmatching */ +s32 JKRExpHeap::do_changeGroupID(u8 groupId) { + lock(); + u8 prev = mCurrentGroupId; + mCurrentGroupId = groupId; + unlock(); + return prev; } /* 802B2098-802B2244 .text do_resize__10JKRExpHeapFPvUl */ -void JKRExpHeap::do_resize(void*, unsigned long) { - /* Nonmatching */ +s32 JKRExpHeap::do_resize(void* ptr, u32 size) { + lock(); + CMemBlock* block = CMemBlock::getHeapBlock(ptr); + if (block == NULL || ptr < mStart || mEnd < ptr) { + unlock(); + return -1; + } + + size = ALIGN_NEXT(size, 4); + if (size == block->size) { + unlock(); + return size; + } + + if (size > block->size) { + CMemBlock* foundBlock = NULL; + for (CMemBlock* freeBlock = mHeadFreeList; freeBlock; freeBlock = freeBlock->mNext) { + if (freeBlock == (CMemBlock*)((u32)(block + 1) + block->size)) { + foundBlock = freeBlock; + break; + } + } + + if (foundBlock == NULL) { + unlock(); + return -1; + } + + if (size > block->size + sizeof(CMemBlock) + foundBlock->size) { + unlock(); + return -1; + } + + removeFreeBlock(foundBlock); + block->size += foundBlock->size + sizeof(CMemBlock); + if (block->size - size > sizeof(CMemBlock)) { + CMemBlock* newBlock = block->allocFore(size, block->mGroupId, block->mFlags, 0, 0); + if (newBlock) { + recycleFreeBlock(newBlock); + } + } + } else { + if (block->size - size > sizeof(CMemBlock)) { + CMemBlock* freeBlock = block->allocFore(size, block->mGroupId, block->mFlags, 0, 0); + if (freeBlock) { + recycleFreeBlock(freeBlock); + } + } + } + + unlock(); + return block->size; } /* 802B2244-802B22C4 .text do_getSize__10JKRExpHeapFPv */ -void JKRExpHeap::do_getSize(void*) { - /* Nonmatching */ +s32 JKRExpHeap::do_getSize(void* ptr) { + lock(); + CMemBlock* block = CMemBlock::getHeapBlock(ptr); + if (!block || ptr < getStartAddr() || getEndAddr() < ptr) { + unlock(); + return -1; + } + unlock(); + return block->getSize(); } /* 802B22C4-802B2330 .text do_getFreeSize__10JKRExpHeapFv */ -void JKRExpHeap::do_getFreeSize() { - /* Nonmatching */ +s32 JKRExpHeap::do_getFreeSize() { + lock(); + s32 size = 0; + for (CMemBlock* block = mHeadFreeList; block; block = block->getNextBlock()) { + if (size < (s32)block->getSize()) { + size = block->getSize(); + } + } + unlock(); + return size; } /* 802B2330-802B23A4 .text do_getMaxFreeBlock__10JKRExpHeapFv */ -void JKRExpHeap::do_getMaxFreeBlock() { - /* Nonmatching */ +void* JKRExpHeap::do_getMaxFreeBlock() { + lock(); + s32 size = 0; + CMemBlock* res = NULL; + for (CMemBlock* block = mHeadFreeList; block; block = block->getNextBlock()) { + if (size < (s32)block->getSize()) { + size = block->getSize(); + res = block; + } + } + unlock(); + return res; } /* 802B23A4-802B2408 .text do_getTotalFreeSize__10JKRExpHeapFv */ -void JKRExpHeap::do_getTotalFreeSize() { - /* Nonmatching */ +s32 JKRExpHeap::do_getTotalFreeSize() { + u32 size = 0; + lock(); + for (CMemBlock* block = mHeadFreeList; block; block = block->getNextBlock()) { + size += block->getSize(); + } + unlock(); + return size; } /* 802B2408-802B2484 .text getUsedSize__10JKRExpHeapCFUc */ -void JKRExpHeap::getUsedSize(unsigned char) const { - /* Nonmatching */ +s32 JKRExpHeap::getUsedSize(u8 groupId) const { + JKRExpHeap* this2 = const_cast<JKRExpHeap*>(this); + this2->lock(); + u32 size = 0; + + for (CMemBlock* block = mHeadUsedList; block; block = block->getNextBlock()) { + u8 blockGroupId = block->getGroupId(); + if (blockGroupId == groupId) { + size += block->getSize() + sizeof(CMemBlock); + } + } + + this2->unlock(); + return size; } /* 802B2484-802B24EC .text getTotalUsedSize__10JKRExpHeapCFv */ -void JKRExpHeap::getTotalUsedSize() const { - /* Nonmatching */ +s32 JKRExpHeap::getTotalUsedSize() const { + JKRExpHeap* this2 = const_cast<JKRExpHeap*>(this); + this2->lock(); + u32 size = 0; + + for (CMemBlock* block = mHeadUsedList; block; block = block->getNextBlock()) { + size += block->getSize() + sizeof(CMemBlock); + } + + this2->unlock(); + return size; +} + +static void dummy1() { + OSReport("newSize > 0"); + OSReport("Halt"); } /* 802B24EC-802B2584 .text appendUsedList__10JKRExpHeapFPQ210JKRExpHeap9CMemBlock */ -void JKRExpHeap::appendUsedList(JKRExpHeap::CMemBlock*) { - /* Nonmatching */ +void JKRExpHeap::appendUsedList(CMemBlock* newblock) { + if (!newblock) { + OSPanic(__FILE__, 1466, ":::ERROR! appendUsedList\n"); + } + + CMemBlock* block = mTailUsedList; + newblock->mMagic = 'HM'; + + if (block) { + block->mNext = newblock; + newblock->mPrev = block; + } else { + newblock->mPrev = NULL; + } + + mTailUsedList = newblock; + if (!mHeadUsedList) { + mHeadUsedList = newblock; + } + newblock->mNext = NULL; } /* 802B2584-802B25D0 .text setFreeBlock__10JKRExpHeapFPQ210JKRExpHeap9CMemBlockPQ210JKRExpHeap9CMemBlockPQ210JKRExpHeap9CMemBlock */ -void JKRExpHeap::setFreeBlock(JKRExpHeap::CMemBlock*, JKRExpHeap::CMemBlock*, JKRExpHeap::CMemBlock*) { - /* Nonmatching */ +void JKRExpHeap::setFreeBlock(CMemBlock* block, CMemBlock* prev, CMemBlock* next) { + if (prev == NULL) { + mHeadFreeList = block; + block->mPrev = NULL; + } else { + prev->mNext = block; + block->mPrev = prev; + } + + if (next == NULL) { + mTailFreeList = block; + block->mNext = NULL; + } else { + next->mPrev = block; + block->mNext = next; + } + + block->mMagic = 0; } /* 802B25D0-802B2604 .text removeFreeBlock__10JKRExpHeapFPQ210JKRExpHeap9CMemBlock */ -void JKRExpHeap::removeFreeBlock(JKRExpHeap::CMemBlock*) { - /* Nonmatching */ +void JKRExpHeap::removeFreeBlock(CMemBlock* block) { + CMemBlock* prev = block->mPrev; + CMemBlock* next = block->mNext; + + if (prev == NULL) { + mHeadFreeList = next; + } else { + prev->mNext = next; + } + + if (next == NULL) { + mTailFreeList = prev; + } else { + next->mPrev = prev; + } } /* 802B2604-802B2638 .text removeUsedBlock__10JKRExpHeapFPQ210JKRExpHeap9CMemBlock */ -void JKRExpHeap::removeUsedBlock(JKRExpHeap::CMemBlock*) { - /* Nonmatching */ +void JKRExpHeap::removeUsedBlock(CMemBlock* block) { + CMemBlock* prev = block->mPrev; + CMemBlock* next = block->mNext; + + if (prev == NULL) { + mHeadUsedList = next; + } else { + prev->mNext = next; + } + + if (next == NULL) { + mTailUsedList = prev; + } else { + next->mPrev = prev; + } } /* 802B2638-802B27D0 .text recycleFreeBlock__10JKRExpHeapFPQ210JKRExpHeap9CMemBlock */ -void JKRExpHeap::recycleFreeBlock(JKRExpHeap::CMemBlock*) { - /* Nonmatching */ +void JKRExpHeap::recycleFreeBlock(CMemBlock* block) { + JKRExpHeap::CMemBlock* newBlock = block; + int size = block->size; + void* blockEnd = (u8*)block + size; + block->mMagic = 0; + + if ((block->mFlags & 0x7f) != 0) { + newBlock = (CMemBlock*)((u8*)block - (block->mFlags & 0x7f)); + size += (block->mFlags & 0x7f); + blockEnd = (u8*)newBlock + size; + newBlock->mGroupId = 0; + newBlock->mFlags = 0; + newBlock->size = size; + } + + if (!mHeadFreeList) { + newBlock->initiate(NULL, NULL, size, 0, 0); + mHeadFreeList = newBlock; + mTailFreeList = newBlock; + setFreeBlock(newBlock, NULL, NULL); + return; + } + + if (mHeadFreeList >= blockEnd) { + newBlock->initiate(NULL, NULL, size, 0, 0); + setFreeBlock(newBlock, NULL, mHeadFreeList); + joinTwoBlocks(newBlock); + return; + } + + if (mTailFreeList <= newBlock) { + newBlock->initiate(NULL, NULL, size, 0, 0); + setFreeBlock(newBlock, mTailFreeList, NULL); + joinTwoBlocks(newBlock->mPrev); + return; + } + + for (CMemBlock* freeBlock = mHeadFreeList; freeBlock; freeBlock = freeBlock->mNext) { + if (freeBlock >= newBlock || newBlock >= freeBlock->mNext) { + continue; + } + newBlock->mNext = freeBlock->mNext; + newBlock->mPrev = freeBlock; + freeBlock->mNext = newBlock; + newBlock->mNext->mPrev = newBlock; + newBlock->mGroupId = 0; + joinTwoBlocks(newBlock); + joinTwoBlocks(freeBlock); + return; + } } /* 802B27D0-802B291C .text joinTwoBlocks__10JKRExpHeapFPQ210JKRExpHeap9CMemBlock */ -void JKRExpHeap::joinTwoBlocks(JKRExpHeap::CMemBlock*) { - /* Nonmatching */ +// regalloc +void JKRExpHeap::joinTwoBlocks(CMemBlock* block) { + /* Nonmatching */ + u32 endAddr = (u32)(block + 1) + block->size; + CMemBlock* next = block->mNext; + u32 nextAddr = (u32)next - (next->mFlags & 0x7f); + if (endAddr > nextAddr) { + JUTWarningConsole_f(":::Heap may be broken. (block = %x)", block); + OSReport(":::block = %x\n", block); + OSReport(":::joinTwoBlocks [%x %x %x][%x %x %x]\n", block, block->mFlags, block->size, block->mNext, block->mNext->mFlags, block->mNext->size); + OSReport(":::: endAddr = %x\n", endAddr); + OSReport(":::: nextAddr = %x\n", nextAddr); + JKRGetCurrentHeap()->dump(); + OSPanic(__FILE__, 1718, ":::: Bad Block\n"); + } + + if (endAddr == nextAddr) { + block->size = next->size + sizeof(CMemBlock) + next->getAlignment() + block->size; + setFreeBlock(block, block->mPrev, next->mNext); + } } /* 802B291C-802B2B44 .text check__10JKRExpHeapFv */ -void JKRExpHeap::check() { - /* Nonmatching */ +bool JKRExpHeap::check() { + lock(); + int totalBytes = 0; + bool ok = true; + for (CMemBlock* block = mHeadUsedList; block; block = block->mNext) { + if (!block->isValid()) { + ok = false; + JUTWarningConsole_f(":::addr %08x: bad heap signature. (%c%c)\n", block, + JSUHiByte(block->mMagic), JSULoByte(block->mMagic)); + } + + if (block->mNext) { + if (!block->mNext->isValid()) { + ok = false; + JUTWarningConsole_f(":::addr %08x: bad next pointer (%08x)\nabort\n", block, + block->mNext); + break; + } + if (block->mNext->mPrev != block) { + ok = false; + JUTWarningConsole_f(":::addr %08x: bad previous pointer (%08x)\n", block->mNext, + block->mNext->mPrev); + } + } else { + if (mTailUsedList != block) { + ok = false; + JUTWarningConsole_f(":::addr %08x: bad used list(REV) (%08x)\n", block, + mTailUsedList); + } + } + totalBytes += sizeof(CMemBlock) + block->size + block->getAlignment(); + } + + for (CMemBlock* block = mHeadFreeList; block; block = block->mNext) { + totalBytes += block->size + sizeof(CMemBlock); + if (block->mNext) { + if (block->mNext->mPrev != block) { + ok = false; + JUTWarningConsole_f(":::addr %08x: bad previous pointer (%08x)\n", block->mNext, + block->mNext->mPrev); + } + + if ((u32)block + block->size + sizeof(CMemBlock) > (u32)block->mNext) { + ok = false; + JUTWarningConsole_f(":::addr %08x: bad block size (%08x)\n", block, block->size); + } + } else { + if (mTailFreeList != block) { + ok = false; + JUTWarningConsole_f(":::addr %08x: bad used list(REV) (%08x)\n", block, + mTailFreeList); + } + } + } + + if (totalBytes != mSize) { + ok = false; + JUTWarningConsole_f(":::bad total memory block size (%08X, %08X)\n", mSize, totalBytes); + } + + if (!ok) { + JUTWarningConsole(":::there is some error in this heap!\n"); + } + + unlock(); + return ok; } /* 802B2B44-802B2B48 .text do_freeFill__10JKRExpHeapFv */ -void JKRExpHeap::do_freeFill() { - /* Nonmatching */ -} +void JKRExpHeap::do_freeFill() {} /* 802B2B48-802B2D5C .text dump__10JKRExpHeapFv */ -void JKRExpHeap::dump() { - /* Nonmatching */ +bool JKRExpHeap::dump() { + lock(); + bool result = check(); + u32 usedBytes = 0; + u32 usedCount = 0; + u32 freeCount = 0; + + JUTReportConsole(" attr address: size gid aln prev_ptr next_ptr\n"); + JUTReportConsole("(Used Blocks)\n"); + if (!mHeadUsedList) { + JUTReportConsole(" NONE\n"); + } + + for (CMemBlock* block = mHeadUsedList; block; block = block->mNext) { + if (!block->isValid()) { + JUTReportConsole_f("xxxxx %08x: -------- --- --- (-------- --------)\nabort\n", + block); + break; + } + + JUTReportConsole_f("%s %08x: %08x %3d %3d (%08x %08x)\n", + block->_isTempMemBlock() ? " temp" : "alloc", block->getContent(), + block->size, block->mGroupId, block->getAlignment(), block->mPrev, + block->mNext); + usedBytes += sizeof(CMemBlock) + block->size + block->getAlignment(); + usedCount++; + } + + JUTReportConsole("(Free Blocks)\n"); + if (!mHeadFreeList) { + JUTReportConsole(" NONE\n"); + } + + for (CMemBlock* block = mHeadFreeList; block; block = block->mNext) { + JUTReportConsole_f("%s %08x: %08x %3d %3d (%08x %08x)\n", " free", block->getContent(), + block->size, block->mGroupId, block->getAlignment(), block->mPrev, + block->mNext); + freeCount++; + } + + float percent = ((float)usedBytes / (float)mSize) * 100.0f; + JUTReportConsole_f("%d / %d bytes (%6.2f%%) used (U:%d F:%d)\n", usedBytes, mSize, percent, + usedCount, freeCount); + unlock(); + return result; } /* 802B2D5C-802B2F5C .text dump_sort_by_address__10JKRExpHeapFv */ -void JKRExpHeap::dump_sort_by_address() { - /* Nonmatching */ +// regalloc, stack +bool JKRExpHeap::dump_sort_by_address() { + /* Nonmatching */ + lock(); + bool result = check(); + u32 usedBytes = 0; + u32 usedCount = 0; + u32 freeCount = 0; + JUTReportConsole(" attr address: size gid aln prev_ptr next_ptr\n"); + + CMemBlock* block; + for (CMemBlock* var1 = NULL; true; var1 = block) { + CMemBlock* block = (CMemBlock*)0xffffffff; + for (CMemBlock* iterBlock = mHeadFreeList; iterBlock; iterBlock = iterBlock->getNextBlock()) { + if (var1 < iterBlock && iterBlock < block) { + block = iterBlock; + } + } + + for (CMemBlock* iterBlock = mHeadUsedList; iterBlock; iterBlock = iterBlock->getNextBlock()) { + if (var1 < iterBlock && iterBlock < block) { + block = iterBlock; + } + } + + if (block == (CMemBlock*)0xffffffff) { + break; + } + + if (block->mMagic == 0) { + JUTReportConsole_f("%s %08x: %08x %3d %3d (%08x %08x)\n", " free", block->getContent(), block->getSize(), block->getGroupId(), block->getAlignment(), block->getPrevBlock(), block->getNextBlock()); + freeCount += 1; + continue; + } + + if (!block->isValid()) { + JUTReportConsole_f("xxxxx %08x: -------- --- --- (-------- --------)\nabort\n"); + break; + } + + int offset = block->getAlignment(); + void* content = block->getContent(); + const char* type = block->_isTempMemBlock() ? " temp" : "alloc"; + JUTReportConsole_f("%s %08x: %08x %3d %3d (%08x %08x)\n", type, content, block->getSize(), + block->getGroupId(), offset, block->getPrevBlock(), block->getNextBlock()); + usedBytes += sizeof(CMemBlock) + block->size + block->getAlignment(); + usedCount++; + } + + float percent = ((float)usedBytes / (float)mSize) * 100.0f; + JUTReportConsole_f("%d / %d bytes (%6.2f%%) used (U:%d F:%d)\n", usedBytes, mSize, percent, + usedCount, freeCount); + unlock(); + return result; } /* 802B2F5C-802B2F7C .text dump_sort__10JKRExpHeapFv */ -void JKRExpHeap::dump_sort() { - /* Nonmatching */ +bool JKRExpHeap::dump_sort() { + return dump_sort_by_address(); } /* 802B2F7C-802B2F9C .text initiate__Q210JKRExpHeap9CMemBlockFPQ210JKRExpHeap9CMemBlockPQ210JKRExpHeap9CMemBlockUlUcUc */ -void JKRExpHeap::CMemBlock::initiate(JKRExpHeap::CMemBlock*, JKRExpHeap::CMemBlock*, unsigned long, unsigned char, unsigned char) { - /* Nonmatching */ +void JKRExpHeap::CMemBlock::initiate(CMemBlock* prev, CMemBlock* next, u32 size, u8 groupId, u8 alignment) { + mMagic = 'HM'; + mFlags = alignment; + mGroupId = groupId; + this->size = size; + mPrev = prev; + mNext = next; } /* 802B2F9C-802B2FE0 .text allocFore__Q210JKRExpHeap9CMemBlockFUlUcUcUcUc */ -void JKRExpHeap::CMemBlock::allocFore(unsigned long, unsigned char, unsigned char, unsigned char, unsigned char) { - /* Nonmatching */ +JKRExpHeap::CMemBlock* JKRExpHeap::CMemBlock::allocFore(u32 size, u8 groupId1, u8 alignment1, u8 groupId2, u8 alignment2) { + CMemBlock* block = NULL; + mGroupId = groupId1; + mFlags = alignment1; + if (getSize() >= size + sizeof(CMemBlock)) { + block = (CMemBlock*)(size + (u32)this); + block[1].mGroupId = groupId2; + block[1].mFlags = alignment2; + block[1].size = this->size - (size + sizeof(CMemBlock)); + this->size = size; + block = block + 1; + } + return block; } /* 802B2FE0-802B3038 .text allocBack__Q210JKRExpHeap9CMemBlockFUlUcUcUcUc */ -void JKRExpHeap::CMemBlock::allocBack(unsigned long, unsigned char, unsigned char, unsigned char, unsigned char) { - /* Nonmatching */ +JKRExpHeap::CMemBlock* JKRExpHeap::CMemBlock::allocBack(u32 size, u8 groupId1, u8 alignment1, u8 groupId2, u8 alignment2) { + CMemBlock* newblock = NULL; + if (getSize() >= size + sizeof(CMemBlock)) { + newblock = (CMemBlock*)((u32)this + getSize() - size); + newblock->mGroupId = groupId2; + newblock->mFlags = alignment2 | 0x80; + newblock->size = size; + mGroupId = groupId1; + mFlags = alignment1; + this->size -= size + sizeof(CMemBlock); + } else { + mGroupId = groupId2; + mFlags = 0x80; + } + return newblock; } /* 802B3038-802B3088 .text free__Q210JKRExpHeap9CMemBlockFP10JKRExpHeap */ -void JKRExpHeap::CMemBlock::free(JKRExpHeap*) { - /* Nonmatching */ +int JKRExpHeap::CMemBlock::free(JKRExpHeap* heap) { + heap->removeUsedBlock(this); + heap->recycleFreeBlock(this); + return 0; } /* 802B3088-802B30A4 .text getHeapBlock__Q210JKRExpHeap9CMemBlockFPv */ -void JKRExpHeap::CMemBlock::getHeapBlock(void*) { - /* Nonmatching */ +JKRExpHeap::CMemBlock* JKRExpHeap::CMemBlock::getHeapBlock(void* ptr) { + if (ptr) { + CMemBlock* block = (CMemBlock*)ptr - 1; + if (block->isValid()) { + return block; + } + } + return NULL; +} + +static void dummy2() { + OSReport("+---------------JKRExpHeap\n"); + OSReport("| Align Group size ( prev , next )\n"); + OSReport("| ---- FreeFirst\n"); + OSReport("| %08x "); + OSReport("%2x %3d %6x (%08x %08x)\n"); + OSReport("| ---- FreeLast\n"); + OSReport("| ---- UsedFirst\n"); + OSReport("| ---- UsedLast\n"); + OSReport("+---------------End\n"); } /* 802B30A4-802B31D4 .text state_register__10JKRExpHeapCFPQ27JKRHeap6TStateUl */ -void JKRExpHeap::state_register(JKRHeap::TState*, unsigned long) const { - /* Nonmatching */ +void JKRExpHeap::state_register(TState* p, u32 param_1) const { + JUT_ASSERT(2423, p != 0); + JUT_ASSERT(2424, p->getHeap() == this); + p->mId = param_1; + if (param_1 <= 0xff) { + p->mUsedSize = getUsedSize(param_1); + } else { + s32 freeSize = const_cast<JKRExpHeap*>(this)->getTotalFreeSize(); + p->mUsedSize = getSize() - freeSize; + } + + u32 checkCode = 0; + for (CMemBlock* block = mHeadUsedList; block; block = block->getNextBlock()) { + if (param_1 <= 0xff) { + u8 groupId = block->getGroupId(); + if (groupId == param_1) { + checkCode += (u32)block * 3; + } + } else { + checkCode += (u32)block * 3; + } + } + p->mCheckCode = checkCode; } /* 802B31D4-802B327C .text state_compare__10JKRExpHeapCFRCQ27JKRHeap6TStateRCQ27JKRHeap6TState */ -void JKRExpHeap::state_compare(const JKRHeap::TState&, const JKRHeap::TState&) const { - /* Nonmatching */ +bool JKRExpHeap::state_compare(const JKRHeap::TState& r1, const JKRHeap::TState& r2) const { + JUT_ASSERT(2471, r1.getHeap() == r2.getHeap()); + bool result = true; + if (r1.mCheckCode != r2.mCheckCode) { + result = false; + } + + if (r1.mUsedSize != r2.mUsedSize) { + result = false; + } + + return result; } /* 802B327C-802B3288 .text getHeapType__10JKRExpHeapFv */ -void JKRExpHeap::getHeapType() { - /* Nonmatching */ +u32 JKRExpHeap::getHeapType() { + return 'EXPH'; } /* 802B3288-802B3290 .text do_getCurrentGroupId__10JKRExpHeapFv */ -void JKRExpHeap::do_getCurrentGroupId() { - /* Nonmatching */ +u8 JKRExpHeap::do_getCurrentGroupId() { + return mCurrentGroupId; } |
