void xHeap::FreeLarge(void * p) { ASSERT("Trying to free NULL pointer" && p); ASSERT("Heap corrupted!" && largeStats.allocCount > largeStats.freeCount); #ifdef DEBUG_APP_HEAP p = (uint8*)p - sizeof(int); ASSERT("Heap corrupted!" && *(int*)p == DUMMY_LARGE_USED_ID_PRE); *(int*)p = DUMMY_LARGE_FREE_ID_PRE; #endif Block * block = ((Block*)p) - 1; ASSERT("Double deallocation!" && !block->isFree); #ifdef DEBUG_APP_HEAP { int * check_p = (int*)((uint8*)p + block->DataSize() + sizeof(int)); ASSERT("Heap corrupted!" && *check_p == DUMMY_LARGE_USED_ID_POST); *check_p = DUMMY_LARGE_FREE_ID_POST; } #endif uint32 size = block->size; largeStats.RegisterFree(size, block->DataSize()); largeStats.allocSize -= size; block->RemoveLink(); // MEMSET(block, 0, size); FREE(block); }
uint32 xHeap::SizeLarge(void * p) { ASSERT("Trying to free NULL pointer" && p); #ifdef DEBUG_APP_HEAP p = (uint8*)p - sizeof(int); ASSERT("Heap corrupted!" && *(int*)p == DUMMY_LARGE_USED_ID_PRE); #endif Block * block = ((Block*)p) - 1; #ifdef DEBUG_APP_HEAP ASSERT("Heap corrupted!" && *(int*)((uint8*)p + block->DataSize() + sizeof(int)) == DUMMY_LARGE_USED_ID_POST); #endif return block->DataSize(); }
void * xHeap::AllocLarge(uint32 size, const char * filename, int line) { #else void * xHeap::AllocLarge(uint32 size) { #endif size = (size + ALIGN - 1 + sizeof(Block) + DUMMY_ID_SIZE) & ~(ALIGN - 1); Block * block = (Block *)MALLOC(size); if(!block) { return NULL; } #ifdef DEBUG_APP_HEAP block->filename = filename; block->line = line; #endif block->page = (uint16)-1; block->size = size; block->isFree = false; block->InsertBefore(dummyLargeBlock.next); largeStats.allocSize += size; uint32 dataSize = block->DataSize(); largeStats.RegisterAlloc(block->size, dataSize); uint8 * p = (uint8*)(block + 1); #ifndef USE_APP_HEAP_SAVING_MODE p[-1] = BT_LARGE; #else p[-1] &= ~BLOCK_TYPE_MASK; #endif #ifdef DEBUG_APP_HEAP *(int*)p = DUMMY_LARGE_USED_ID_PRE; p += sizeof(int); *(int*)(p + dataSize) = DUMMY_LARGE_USED_ID_POST; #endif MEMSET(p, 0, dataSize); #if defined(DEBUG_APP_HEAP) && defined(AEE_SIMULATOR) // CheckMemory(); #endif return p; }
void xHeap::FreeMedium(void * p) { ASSERT("Trying to free NULL pointer" && p); ASSERT("Heap corrupted!" && mediumStats.allocCount > mediumStats.freeCount); #ifdef DEBUG_APP_HEAP p = (uint8*)p - sizeof(int); ASSERT("Heap corrupted!" && *(int*)p == DUMMY_MEDIUM_USED_ID_PRE); // *(int*)p = DUMMY_MEDIUM_FREE_ID_PRE; #endif Block * block = ((Block*)p) - 1; ASSERT("Double deallocation!" && !block->isFree); #ifdef DEBUG_APP_HEAP { ASSERT("Heap corrupted!" && *((int*)((uint8*)p + block->DataSize() + sizeof(int))) == DUMMY_MEDIUM_USED_ID_POST); // *check_p = DUMMY_MEDIUM_FREE_ID_POST; } #endif mediumStats.RegisterFree(block->size, block->DataSize()); Block * prev = block->prev; if(prev->isFree && prev->page == block->page) { ASSERT("Heap corrupted!" && ((uint8*)prev) + prev->size == (uint8*)block); prev->size += block->size; ((FreeBlock*)prev)->RemoveFreeLink(); block->RemoveLink(); block = prev; mediumStats.mergeCount++; } Block * next = block->next; if(next->isFree && next->page == block->page) { ASSERT("Heap corrupted!" && ((uint8*)block) + block->size == (uint8*)next); block->size += next->size; ((FreeBlock*)next)->RemoveFreeLink(); next->RemoveLink(); mediumStats.mergeCount++; } block->isFree = true; #ifdef DEBUG_APP_HEAP *(int*)(block+1) = DUMMY_MEDIUM_FREE_ID_PRE; *(int*)((uint8*)(block+1) + block->DataSize() + sizeof(int)) = DUMMY_MEDIUM_FREE_ID_POST; #endif InsertFreeBlock((FreeBlock*)block); #if defined(DEBUG_APP_HEAP) && defined(AEE_SIMULATOR) // CheckMemory(); #endif }
void * xHeap::AllocMedium(uint32 size, const char * filename, int line) { #else void * xHeap::AllocMedium(uint32 size) { #endif #ifdef DEBUG_APP_HEAP // static int step = 0; // step++; #endif uint32 saveSize = size; size = (size + ALIGN - 1 + sizeof(Block) + DUMMY_ID_SIZE) & ~(ALIGN - 1); Block * block = dummyFree.nextFree; if(block->size < size) // block == &dummyFree => dummyFree.size == 0 { if(size > pageSize / 2) { #ifdef DEBUG_APP_HEAP return AllocLarge(saveSize, filename, line); #else return AllocLarge(saveSize); #endif } block = (Block*)MALLOC(pageSize); if(!block) { return NULL; } #ifdef DEBUG_APP_HEAP block->filename = filename; block->line = line; #endif block->page = nextPage++; block->size = pageSize; block->isFree = true; block->InsertBefore(dummyBlock.next); ((FreeBlock*)block)->InsertBeforeFreeLink(dummyFree.nextFree); mediumStats.allocSize += block->size; } else { mediumStats.hitCount++; #ifdef FIND_BEST_FREE_BLOCK for(FreeBlock * next = ((FreeBlock*)block)->nextFree; next->size >= size; ) { block = next; next = ((FreeBlock*)block)->nextFree; } #endif } block->size -= size; if(block->size < MAX_SMALL_SIZE && (block->size < MAX_SMALL_SIZE/2 || block->next->page != block->page)) { #ifdef DEBUG_APP_HEAP block->filename = filename; block->line = line; #endif block->size += size; ((FreeBlock*)block)->RemoveFreeLink(); } else { #ifdef DEBUG_APP_HEAP *(int*)(block+1) = DUMMY_MEDIUM_FREE_ID_PRE; *(int*)((uint8*)(block+1) + block->DataSize() + sizeof(int)) = DUMMY_MEDIUM_FREE_ID_POST; #endif if(block->size < ((FreeBlock*)block)->nextFree->size) { ((FreeBlock*)block)->RemoveFreeLink(); InsertFreeBlock((FreeBlock*)block); } ASSERT("Heap corrupted!" && (block->size & 3) == 0); Block * newBlock = (Block*)(((uint8*)block) + block->size); #ifdef DEBUG_APP_HEAP newBlock->filename = filename; newBlock->line = line; #endif newBlock->page = block->page; newBlock->size = size; newBlock->InsertAfter(block); block = newBlock; } block->isFree = false; uint32 dataSize = block->DataSize(); mediumStats.RegisterAlloc(block->size, dataSize); uint8 * p = (uint8*)(block+1); p[-1] = BT_MEDIUM; #ifdef DEBUG_APP_HEAP *(int*)p = DUMMY_MEDIUM_USED_ID_PRE; p += sizeof(int); *(int*)(p + dataSize) = DUMMY_MEDIUM_USED_ID_POST; #endif MEMSET(p, 0, dataSize); #if defined(DEBUG_APP_HEAP) && defined(AEE_SIMULATOR) // CheckMemory(); #endif return p; }
void xHeap::CheckMemory() { #ifdef DEBUG_APP_HEAP uint32 allocSize, usedSize, dataSize; allocSize = usedSize = dataSize = 0; for(SmallPage * smallPage = this->smallPage; smallPage; smallPage = smallPage->next) { allocSize += smallPage->size; } ASSERT("Heap corrupted!" && allocSize == smallStats.allocSize); for(SmallBlock * smallBlock = dummySmallBlock.next; smallBlock != &dummySmallBlock; smallBlock = smallBlock->next) { ASSERT("Heap corrupted!" && smallBlock->next->prev == smallBlock); ASSERT("Heap corrupted!" && smallBlock->prev->next == smallBlock); uint32 blockDataSize = smallBlock->DataSize(); ASSERT("Heap corrupted!" && (blockDataSize & 3) == 0); ASSERT("Heap corrupted!" && blockDataSize <= MAX_SMALL_SIZE); ASSERT("Heap corrupted!" && blockDataSize >= smallStats.minBlockDataSize); ASSERT("Heap corrupted!" && blockDataSize <= smallStats.maxBlockDataSize); ASSERT("Heap corrupted!" && *(int *)(smallBlock + 1) == DUMMY_SMALL_USED_ID_PRE); ASSERT("Heap corrupted!" && *(int *)((uint8 *)(smallBlock + 1) + blockDataSize + sizeof(int)) == DUMMY_SMALL_USED_ID_POST); usedSize += smallBlock->Size(); dataSize += blockDataSize; } ASSERT("Heap corrupted!" && usedSize == smallStats.usedSize); ASSERT("Heap corrupted!" && dataSize == smallStats.dataSize); for(int i = 0; i < SMALL_SLOT_COUNT; i++) { for(FreeSmallBlock * freeSmallBlock = freeSmallBlocks[i]; freeSmallBlock; freeSmallBlock = freeSmallBlock->next) { #ifndef NDEBUG /* fixing warning with unused smallBlock variable */ SmallBlock * smallBlock = (SmallBlock*)freeSmallBlock; ASSERT("Heap corrupted!" && (smallBlock->DataSize() & 3) == 0); ASSERT("Heap corrupted!" && smallBlock->sizeSlot == (uint8)i); ASSERT("Heap corrupted!" && *(int *)(smallBlock + 1) == DUMMY_SMALL_FREE_ID_PRE); ASSERT("Heap corrupted!" && *(int *)((uint8 *)(smallBlock + 1) + smallBlock->DataSize() + sizeof(int)) == DUMMY_SMALL_FREE_ID_POST); #endif/*NDEBUG*/ } } #ifndef USE_APP_HEAP_SAVING_MODE allocSize = usedSize = dataSize = 0; for(Block * block = dummyBlock.next; block != &dummyBlock; block = block->next) { ASSERT("Heap corrupted!" && block->isFree == 0 || block->isFree == 1); ASSERT("Heap corrupted!" && block->page < nextPage); ASSERT("Heap corrupted!" && block->next->prev == block); ASSERT("Heap corrupted!" && block->prev->next == block); uint32 blockDataSize = block->DataSize(); ASSERT("Heap corrupted!" && (blockDataSize & 3) == 0); if(!block->isFree) { ASSERT("Heap corrupted!" && blockDataSize >= mediumStats.minBlockDataSize); ASSERT("Heap corrupted!" && blockDataSize <= mediumStats.maxBlockDataSize); ASSERT("Heap corrupted!" && *(int *)(block + 1) == DUMMY_MEDIUM_USED_ID_PRE); ASSERT("Heap corrupted!" && *(int *)((uint8 *)(block + 1) + blockDataSize + sizeof(int)) == DUMMY_MEDIUM_USED_ID_POST); usedSize += block->size; dataSize += blockDataSize; } else { // ASSERT("Heap corrupted!" && dataSize < pageSize); ASSERT("Heap corrupted!" && *(int *)(block + 1) == DUMMY_MEDIUM_FREE_ID_PRE); ASSERT("Heap corrupted!" && *(int *)((uint8 *)(block + 1) + blockDataSize + sizeof(int)) == DUMMY_MEDIUM_FREE_ID_POST); } allocSize += block->size; } ASSERT("Heap corrupted!" && allocSize == mediumStats.allocSize); ASSERT("Heap corrupted!" && usedSize == mediumStats.usedSize); ASSERT("Heap corrupted!" && dataSize == mediumStats.dataSize); for(FreeBlock * block = dummyFree.nextFree; block != &dummyFree; block = block->nextFree) { ASSERT("Heap corrupted!" && block->isFree == 1); ASSERT("Heap corrupted!" && block->page < nextPage); ASSERT("Heap corrupted!" && block->nextFree->prevFree == block); ASSERT("Heap corrupted!" && block->prevFree->nextFree == block); } #endif // USE_APP_HEAP_SAVING_MODE allocSize = usedSize = dataSize = 0; for(Block * largeBlock = dummyLargeBlock.next; largeBlock != &dummyLargeBlock; largeBlock = largeBlock->next) { ASSERT("Heap corrupted!" && largeBlock->next->prev == largeBlock); ASSERT("Heap corrupted!" && largeBlock->prev->next == largeBlock); uint32 blockDataSize = largeBlock->DataSize(); ASSERT("Heap corrupted!" && blockDataSize >= largeStats.minBlockDataSize); ASSERT("Heap corrupted!" && blockDataSize <= largeStats.maxBlockDataSize); allocSize += largeBlock->size; usedSize += largeBlock->size; dataSize += blockDataSize; } ASSERT("Heap corrupted!" && allocSize == largeStats.allocSize); ASSERT("Heap corrupted!" && usedSize == largeStats.usedSize); ASSERT("Heap corrupted!" && dataSize == largeStats.dataSize); #endif // DEBUG_APP_HEAP }