зеркало из https://github.com/mozilla/pjs.git
Dumping out my latest memory manager changes. Still not being built yet. New code includes stats collection, but no way to write out stats at the moment.
This commit is contained in:
Родитель
36f4bf7247
Коммит
6b88bb2485
|
@ -25,7 +25,6 @@
|
|||
#include <Processes.h>
|
||||
#include <CodeFragments.h>
|
||||
|
||||
|
||||
#include "nsMemAllocator.h"
|
||||
|
||||
#include "nsFixedSizeAllocator.h"
|
||||
|
@ -59,7 +58,7 @@ class nsAllocatorManager
|
|||
|
||||
static const SInt32 kNumMasterPointerBlocks;
|
||||
static const SInt32 kApplicationStackSizeIncrease;
|
||||
|
||||
static const SInt32 kHeapZoneHeapPercentage;
|
||||
|
||||
nsAllocatorManager();
|
||||
~nsAllocatorManager();
|
||||
|
@ -88,6 +87,9 @@ class nsAllocatorManager
|
|||
nsMemAllocator** mSmallBlockAllocators; // array of pointers to allocator objects
|
||||
|
||||
nsMemAllocator* mLargeAllocator;
|
||||
|
||||
THz mHeapZone; // the heap zone for our memory heaps
|
||||
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
@ -96,6 +98,7 @@ class nsAllocatorManager
|
|||
|
||||
const SInt32 nsAllocatorManager::kNumMasterPointerBlocks = 30;
|
||||
const SInt32 nsAllocatorManager::kApplicationStackSizeIncrease = (32 * 1024);
|
||||
const SInt32 nsAllocatorManager::kHeapZoneHeapPercentage = 60;
|
||||
|
||||
nsAllocatorManager* nsAllocatorManager::sAllocatorManager = nil;
|
||||
|
||||
|
@ -126,9 +129,6 @@ nsAllocatorManager::nsAllocatorManager() :
|
|||
mFixedSizeAllocators[i] = (nsMemAllocator *)NewPtr(sizeof(nsFixedSizeAllocator));
|
||||
if (mFixedSizeAllocators[i] == nil)
|
||||
throw((OSErr)memFullErr);
|
||||
|
||||
// placement new
|
||||
new (mFixedSizeAllocators[i]) nsFixedSizeAllocator((i + 1) * 4);
|
||||
}
|
||||
|
||||
for (SInt32 i = 0; i < mNumSmallBlockAllocators; i ++)
|
||||
|
@ -136,16 +136,42 @@ nsAllocatorManager::nsAllocatorManager() :
|
|||
mSmallBlockAllocators[i] = (nsMemAllocator *)NewPtr(sizeof(nsSmallHeapAllocator));
|
||||
if (mSmallBlockAllocators[i] == nil)
|
||||
throw((OSErr)memFullErr);
|
||||
|
||||
// placement new
|
||||
new (mSmallBlockAllocators[i]) nsSmallHeapAllocator();
|
||||
}
|
||||
|
||||
mLargeAllocator = (nsMemAllocator *)NewPtr(sizeof(nsLargeHeapAllocator));
|
||||
if (mLargeAllocator == nil)
|
||||
throw((OSErr)memFullErr);
|
||||
// placement new
|
||||
new (mLargeAllocator) nsLargeHeapAllocator();
|
||||
|
||||
// make the heap zone for our subheaps
|
||||
UInt32 heapZoneSize;
|
||||
|
||||
heapZoneSize = ( kHeapZoneHeapPercentage * ::FreeMem() ) / 100;
|
||||
heapZoneSize = ( ( heapZoneSize + 3 ) & ~3 ); // round up to a multiple of 4 bytes
|
||||
|
||||
Ptr heapZone = ::NewPtr(heapZoneSize);
|
||||
if (heapZone == nil)
|
||||
throw((OSErr)memFullErr);
|
||||
|
||||
#define kNumMasterPointers 24 // does not matter, since we won't be allocating handles
|
||||
// in this heap zone
|
||||
|
||||
Ptr endZone = heapZone + heapZoneSize;
|
||||
::InitZone(nil, kNumMasterPointers, endZone, heapZone);
|
||||
|
||||
// set the current zone back to the application zone
|
||||
::SetZone(::ApplicationZone());
|
||||
|
||||
mHeapZone = (THz)heapZone;
|
||||
|
||||
// now we have the heap zone, call (placement) new on our allocators
|
||||
for (SInt32 i = 0; i < mNumFixedSizeAllocators; i ++)
|
||||
new (mFixedSizeAllocators[i]) nsFixedSizeAllocator(mHeapZone, (i + 1) * 4);
|
||||
|
||||
for (SInt32 i = 0; i < mNumSmallBlockAllocators; i ++)
|
||||
new (mSmallBlockAllocators[i]) nsSmallHeapAllocator(mHeapZone);
|
||||
|
||||
new (mLargeAllocator) nsLargeHeapAllocator(mHeapZone);
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
@ -182,10 +208,11 @@ nsMemAllocator* nsAllocatorManager::GetAllocatorForBlockSize(size_t blockSize)
|
|||
{
|
||||
if (blockSize < mMinSmallBlockSize)
|
||||
return mFixedSizeAllocators[ (blockSize == 0) ? 0 : ((blockSize + 3) >> 2) - 1 ];
|
||||
else if (blockSize < mMinLargeBlockSize)
|
||||
|
||||
if (blockSize < mMinLargeBlockSize)
|
||||
return mSmallBlockAllocators[ ((blockSize + 3) >> 2) - mNumFixedSizeAllocators ];
|
||||
else
|
||||
return mLargeAllocator;
|
||||
|
||||
return mLargeAllocator;
|
||||
}
|
||||
|
||||
|
||||
|
@ -223,6 +250,7 @@ nsMemAllocator* nsAllocatorManager::GetAllocatorForBlockSize(size_t blockSize)
|
|||
}
|
||||
catch (...)
|
||||
{
|
||||
return paramErr;
|
||||
}
|
||||
|
||||
return noErr;
|
||||
|
@ -320,6 +348,8 @@ void *calloc(size_t nele, size_t elesize)
|
|||
|
||||
#pragma mark -
|
||||
|
||||
#if 0
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
__MemInitialize
|
||||
|
||||
|
@ -332,8 +362,12 @@ pascal OSErr __MemInitialize(const CFragInitBlock *theInitBlock)
|
|||
OSErr err = __initialize(theInitBlock);
|
||||
if (err != noErr) return err;
|
||||
|
||||
return nsAllocatorManager::InitializeMacMemory(nsAllocatorManager::kNumMasterPointerBlocks,
|
||||
nsAllocatorManager::kApplicationStackSizeIncrease);
|
||||
#if __profile__
|
||||
if (ProfilerInit(collectDetailed, bestTimeBase, 500, 20) != noErr)
|
||||
ExitToShell();
|
||||
#endif
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
||||
|
@ -350,6 +384,14 @@ pascal OSErr __MemInitialize(const CFragInitBlock *theInitBlock)
|
|||
|
||||
pascal void __MemTerminate(void)
|
||||
{
|
||||
#if __profile__
|
||||
ProfilerDump("\pMemory Tester.prof");
|
||||
ProfilerTerm();
|
||||
#endif
|
||||
|
||||
__terminate();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -25,8 +25,9 @@
|
|||
const UInt32 FixedMemoryBlock::kFixedSizeBlockOverhead = sizeof(FixedMemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
nsFixedSizeAllocator::nsFixedSizeAllocator(size_t blockSize) :
|
||||
mBlockSize(blockSize)
|
||||
nsFixedSizeAllocator::nsFixedSizeAllocator(THz heapZone, size_t blockSize)
|
||||
: nsMemAllocator(heapZone)
|
||||
, mBlockSize(blockSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
mBaseChunkSize = mTempChunkSize = (nsMemAllocator::kChunkSizeMultiple);
|
||||
|
@ -46,9 +47,9 @@ nsHeapChunk* nsFixedSizeAllocator::FindChunkWithSpace(size_t blockSize) const
|
|||
nsFixedSizeHeapChunk* chunk = (nsFixedSizeHeapChunk *)mFirstChunk;
|
||||
|
||||
// Try to find an existing chunk with a free block.
|
||||
while ( chunk != NULL )
|
||||
while (chunk != nil)
|
||||
{
|
||||
if ( chunk->GetFreeList() != nil )
|
||||
if (chunk->GetFreeList() != nil)
|
||||
return chunk;
|
||||
|
||||
chunk = (nsFixedSizeHeapChunk *)chunk->GetNextChunk();
|
||||
|
@ -71,16 +72,21 @@ void *nsFixedSizeAllocator::AllocatorMakeBlock(size_t blockSize)
|
|||
}
|
||||
|
||||
FixedMemoryBlock* blockHeader = chunk->FetchFirstFree();
|
||||
// these get stripped by the compiler in optimized builds
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
blockHeader->SetHeaderTag(kUsedBlockHeaderTag);
|
||||
blockHeader->SetTrailerTag(GetAllocatorBlockSize(), kUsedBlockTrailerTag);
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
UInt32 paddedSize = (blockSize + 3) & ~3;
|
||||
blockHeader->SetPaddingBytes(paddedSize - blockSize);
|
||||
blockHeader->FillPaddingBytes(mBlockSize);
|
||||
#endif
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
blockHeader->blockHeader.header.logicalBlockSize = blockSize;
|
||||
AccountForNewBlock(blockSize);
|
||||
#endif
|
||||
|
||||
return (void *)&blockHeader->memory;
|
||||
}
|
||||
|
||||
|
@ -91,15 +97,22 @@ void nsFixedSizeAllocator::AllocatorFreeBlock(void *freeBlock)
|
|||
{
|
||||
FixedMemoryBlock* blockHeader = FixedMemoryBlock::GetBlockHeader(freeBlock);
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
MEM_ASSERT(blockHeader->HasHeaderTag(kUsedBlockHeaderTag), "Bad block header");
|
||||
MEM_ASSERT(blockHeader->GetTrailerTag(GetAllocatorBlockSize()) == kUsedBlockTrailerTag, "Bad block trailer");
|
||||
MEM_ASSERT(blockHeader->CheckPaddingBytes(mBlockSize), "Block bounds have been overwritten");
|
||||
#endif
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
AccountForFreedBlock(blockHeader->blockHeader.header.logicalBlockSize);
|
||||
#endif
|
||||
|
||||
nsFixedSizeHeapChunk* chunk = blockHeader->GetOwningChunk();
|
||||
|
||||
// these get stripped by the compiler in optimized builds
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
blockHeader->SetHeaderTag(kFreeBlockHeaderTag);
|
||||
blockHeader->SetTrailerTag(GetAllocatorBlockSize(), kFreeBlockTrailerTag);
|
||||
#endif
|
||||
|
||||
chunk->ReturnToFreeList(blockHeader);
|
||||
|
||||
|
@ -121,11 +134,11 @@ void *nsFixedSizeAllocator::AllocatorResizeBlock(void *block, size_t newSize)
|
|||
|
||||
FixedMemoryBlock* blockHeader = FixedMemoryBlock::GetBlockHeader(block);
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
MEM_ASSERT(blockHeader->HasHeaderTag(kUsedBlockHeaderTag), "Bad block header");
|
||||
MEM_ASSERT(blockHeader->GetTrailerTag(GetAllocatorBlockSize()) == kUsedBlockTrailerTag, "Bad block trailer");
|
||||
MEM_ASSERT(blockHeader->CheckPaddingBytes(mBlockSize), "Block bounds have been overwritten");
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
// if we shrunk the block to below this allocator's normal size range, then these
|
||||
// padding bytes won't be any use. But they are tested using mBlockSize, so we
|
||||
// have to udpate them anyway.
|
||||
|
@ -133,7 +146,12 @@ void *nsFixedSizeAllocator::AllocatorResizeBlock(void *block, size_t newSize)
|
|||
blockHeader->SetPaddingBytes(paddedSize - newSize);
|
||||
blockHeader->FillPaddingBytes(mBlockSize);
|
||||
#endif
|
||||
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
AccountForResizedBlock(blockHeader->blockHeader.header.logicalBlockSize, newSize);
|
||||
blockHeader->blockHeader.header.logicalBlockSize = newSize;
|
||||
#endif
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
|
|
|
@ -83,16 +83,6 @@ struct FixedMemoryBlock
|
|||
MemoryBlockTrailer *trailer = (MemoryBlockTrailer *)((char *)&memory + blockSize);
|
||||
return trailer->trailerTag;
|
||||
}
|
||||
#else
|
||||
// stubs
|
||||
void SetPaddingBytes(UInt32 padding) {}
|
||||
void FillPaddingBytes(UInt32 blockSize)
|
||||
Boolean CheckPaddingBytes(UInt32 blockSize) { return true; }
|
||||
UInt32 GetPaddingBytes() { return 0; }
|
||||
Boolean HasHeaderTag(MemoryBlockTag inHeaderTag){ return true; }
|
||||
void SetHeaderTag(MemoryBlockTag inHeaderTag){}
|
||||
void SetTrailerTag(UInt32 blockSize, MemoryBlockTag theTag) {}
|
||||
MemoryBlockTag GetTrailerTag(UInt32 blockSize) { return 0; }
|
||||
#endif
|
||||
|
||||
static const UInt32 kFixedSizeBlockOverhead;
|
||||
|
@ -116,7 +106,7 @@ class nsFixedSizeAllocator : public nsMemAllocator
|
|||
|
||||
public:
|
||||
|
||||
nsFixedSizeAllocator(size_t blockSize);
|
||||
nsFixedSizeAllocator(THz heapZone, size_t blockSize);
|
||||
~nsFixedSizeAllocator();
|
||||
|
||||
virtual void * AllocatorMakeBlock(size_t blockSize);
|
||||
|
|
|
@ -25,7 +25,8 @@
|
|||
const UInt32 LargeBlockHeader::kLargeBlockOverhead = sizeof(LargeBlockHeader) + MEMORY_BLOCK_TAILER_SIZE;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
nsLargeHeapAllocator::nsLargeHeapAllocator()
|
||||
nsLargeHeapAllocator::nsLargeHeapAllocator(THz heapZone)
|
||||
: nsMemAllocator(heapZone)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
mBaseChunkSize = mTempChunkSize = (64 * 1024);
|
||||
|
@ -68,6 +69,12 @@ void * nsLargeHeapAllocator::AllocatorMakeBlock(size_t blockSize)
|
|||
if (theBlock)
|
||||
{
|
||||
theBlock->SetLogicalSize(blockSize);
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
theBlock->header.logicalBlockSize = blockSize; // yes, it is stored in 2 places in this allocator
|
||||
AccountForNewBlock(blockSize);
|
||||
#endif
|
||||
|
||||
return &(theBlock->memory);
|
||||
}
|
||||
|
||||
|
@ -79,6 +86,32 @@ void * nsLargeHeapAllocator::AllocatorMakeBlock(size_t blockSize)
|
|||
void *nsLargeHeapAllocator::AllocatorResizeBlock(void *block, size_t newSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
LargeBlockHeader *blockHeader = LargeBlockHeader::GetBlockHeader(block);
|
||||
nsLargeHeapChunk *chunk = blockHeader->GetOwningChunk();
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
MEM_ASSERT(blockHeader->HasHeaderTag(kUsedBlockHeaderTag), "Bad block header on realloc");
|
||||
MEM_ASSERT(blockHeader->HasTrailerTag(blockHeader->GetBlockSize(), kUsedBlockTrailerTag), "Bad block trailer on realloc");
|
||||
MEM_ASSERT(blockHeader->CheckPaddingBytes(), "Block has overwritten its bounds");
|
||||
#endif
|
||||
|
||||
UInt32 newAllocSize = (newSize + 3) & ~3;
|
||||
|
||||
// we can resize this block to any size, provided it fits.
|
||||
|
||||
if (newAllocSize < blockHeader->GetBlockSize()) // shrinking
|
||||
{
|
||||
return chunk->ShrinkBlock(blockHeader, newSize);
|
||||
}
|
||||
else if (newAllocSize > blockHeader->GetBlockSize()) // growing
|
||||
{
|
||||
return chunk->GrowBlock(blockHeader, newSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
return chunk->ResizeBlockInPlace(blockHeader, newSize);
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
@ -87,14 +120,25 @@ void *nsLargeHeapAllocator::AllocatorResizeBlock(void *block, size_t newSize)
|
|||
void nsLargeHeapAllocator::AllocatorFreeBlock(void *freeBlock)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
LargeBlockHeader *blockHeader = (LargeBlockHeader *)((char *)freeBlock - sizeof(LargeBlockHeader));
|
||||
LargeBlockHeader *blockHeader = LargeBlockHeader::GetBlockHeader(freeBlock);
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
MEM_ASSERT(blockHeader->HasHeaderTag(kUsedBlockHeaderTag), "Bad block header on free");
|
||||
MEM_ASSERT(blockHeader->HasTrailerTag(blockHeader->GetBlockSize(), kUsedBlockTrailerTag), "Bad block trailer on free");
|
||||
MEM_ASSERT(blockHeader->CheckPaddingBytes(), "Block overwrote bounds");
|
||||
nsLargeHeapChunk *chunk = blockHeader->GetOwningChunk();
|
||||
#endif
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
AccountForFreedBlock(blockHeader->header.logicalBlockSize);
|
||||
#endif
|
||||
|
||||
nsLargeHeapChunk *chunk = blockHeader->GetOwningChunk();
|
||||
chunk->ReturnBlock(blockHeader);
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
blockHeader->SetHeaderTag(kFreeBlockHeaderTag);
|
||||
#endif
|
||||
|
||||
// if this chunk is completely empty and it's not the first chunk then free it
|
||||
if (chunk->IsEmpty() && chunk != mFirstChunk)
|
||||
FreeChunk(chunk);
|
||||
|
@ -178,7 +222,7 @@ nsLargeHeapChunk::nsLargeHeapChunk(
|
|||
freeBlock->SetPrevBlock(nil);
|
||||
freeBlock->SetNextBlock( (LargeBlockHeader *) ( (UInt32)freeBlock + heapSize - 2 * LargeBlockHeader::kLargeBlockOverhead) );
|
||||
|
||||
// and then a zero sized allcated block at the end
|
||||
// and then a zero sized allocated block at the end
|
||||
mTail = freeBlock->GetNextBlock();
|
||||
mTail->SetNextBlock(nil);
|
||||
mTail->SetPrevBlock(freeBlock);
|
||||
|
@ -198,6 +242,8 @@ LargeBlockHeader* nsLargeHeapChunk::GetSpaceForBlock(UInt32 blockSize)
|
|||
{
|
||||
UInt32 allocSize = ((blockSize + 3) & ~3) + LargeBlockHeader::kLargeBlockOverhead;
|
||||
|
||||
if (allocSize > mTotalFree) return nil;
|
||||
|
||||
/* scan through the blocks in this chunk looking for a big enough free block */
|
||||
/* we never allocate the head block */
|
||||
LargeBlockHeader *prevBlock = GetHeadBlock();
|
||||
|
@ -235,10 +281,12 @@ LargeBlockHeader* nsLargeHeapChunk::GetSpaceForBlock(UInt32 blockSize)
|
|||
blockHeader->SetPrevBlock(prevBlock);
|
||||
blockHeader->SetOwningChunk(this);
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
blockHeader->SetHeaderTag(kUsedBlockHeaderTag);
|
||||
blockHeader->SetTrailerTag(blockHeader->GetBlockSize(), kUsedBlockTrailerTag);
|
||||
blockHeader->SetPaddingBytes(((blockSize + 3) & ~3) - blockSize);
|
||||
blockHeader->FillPaddingBytes();
|
||||
#endif
|
||||
|
||||
mTotalFree -= blockHeader->GetBlockHeapUsageSize();
|
||||
IncrementUsedBlocks();
|
||||
|
@ -267,6 +315,9 @@ void *nsLargeHeapChunk::GrowBlock(LargeBlockHeader *growBlock, size_t newSize)
|
|||
return nil;
|
||||
|
||||
// grow this block
|
||||
#if STATS_MAC_MEMORY
|
||||
UInt32 oldLogicalSize = growBlock->GetLogicalSize();
|
||||
#endif
|
||||
MEM_ASSERT(growBlock->logicalSize < newSize, "Wrong block size on grow block");
|
||||
growBlock->SetLogicalSize(newSize);
|
||||
|
||||
|
@ -281,6 +332,9 @@ void *nsLargeHeapChunk::GrowBlock(LargeBlockHeader *growBlock, size_t newSize)
|
|||
smallFree->GetNextBlock()->SetPrevBlock(smallFree);
|
||||
growBlock->SetNextBlock(smallFree);
|
||||
mTotalFree += smallFree->GetBlockHeapUsageSize();
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
smallFree->header.headerTag = kFreeBlockHeaderTag;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -288,8 +342,17 @@ void *nsLargeHeapChunk::GrowBlock(LargeBlockHeader *growBlock, size_t newSize)
|
|||
freeBlock->GetNextBlock()->SetPrevBlock(growBlock);
|
||||
}
|
||||
|
||||
return (void *)(&growBlock->memory);
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
growBlock->SetTrailerTag(growBlock->GetBlockSize(), kUsedBlockTrailerTag);
|
||||
growBlock->SetPaddingBytes(((newSize + 3) & ~3) - newSize);
|
||||
growBlock->FillPaddingBytes();
|
||||
#endif
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
GetOwningAllocator()->AccountForResizedBlock(oldLogicalSize, newSize);
|
||||
#endif
|
||||
|
||||
return (void *)(&growBlock->memory);
|
||||
}
|
||||
|
||||
|
||||
|
@ -305,7 +368,10 @@ void *nsLargeHeapChunk::ShrinkBlock(LargeBlockHeader *growBlock, size_t newSize)
|
|||
LargeBlockHeader* smallFree = nil; // Where the recovered freeblock will go
|
||||
|
||||
// shrink this block
|
||||
MEM_ASSERT(growBlock->logicalSize > newSize, "Wrong bock size on shrink block");
|
||||
#if STATS_MAC_MEMORY
|
||||
UInt32 oldLogicalSize = growBlock->GetLogicalSize();
|
||||
#endif
|
||||
MEM_ASSERT(oldAllocSize > newAllocSize, "Wrong bock size on shrink block");
|
||||
growBlock->SetLogicalSize(newSize);
|
||||
|
||||
// is the block following this block a free block?
|
||||
|
@ -335,9 +401,42 @@ void *nsLargeHeapChunk::ShrinkBlock(LargeBlockHeader *growBlock, size_t newSize)
|
|||
#endif
|
||||
}
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
growBlock->SetTrailerTag(growBlock->GetBlockSize(), kUsedBlockTrailerTag);
|
||||
growBlock->SetPaddingBytes(((newSize + 3) & ~3) - newSize);
|
||||
growBlock->FillPaddingBytes();
|
||||
#endif
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
GetOwningAllocator()->AccountForResizedBlock(oldLogicalSize, newSize);
|
||||
#endif
|
||||
|
||||
return (void *)(&growBlock->memory);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void* nsLargeHeapChunk::ResizeBlockInPlace(LargeBlockHeader *theBlock, size_t newSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
theBlock->SetLogicalSize(newSize);
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
UInt32 newAllocSize = (newSize + 3) & ~3;
|
||||
|
||||
theBlock->SetPaddingBytes(newAllocSize - newSize);
|
||||
theBlock->FillPaddingBytes();
|
||||
#endif
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
GetOwningAllocator()->AccountForResizedBlock(theBlock->header.logicalBlockSize, newSize);
|
||||
theBlock->header.logicalBlockSize = newSize;
|
||||
#endif
|
||||
|
||||
return (void *)(&theBlock->memory);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void nsLargeHeapChunk::ReturnBlock(LargeBlockHeader *deadBlock)
|
||||
//--------------------------------------------------------------------
|
||||
|
|
|
@ -23,6 +23,8 @@ class nsLargeHeapChunk;
|
|||
struct LargeBlockHeader
|
||||
{
|
||||
|
||||
static LargeBlockHeader *GetBlockHeader(void *block) { return (LargeBlockHeader *)((char *)block - sizeof(LargeBlockHeader)); }
|
||||
|
||||
Boolean IsFreeBlock() { return prev == nil; }
|
||||
UInt32 GetBlockSize() { return ((UInt32)next - (UInt32)this - kLargeBlockOverhead); }
|
||||
|
||||
|
@ -79,16 +81,6 @@ struct LargeBlockHeader
|
|||
MemoryBlockTrailer *trailer = (MemoryBlockTrailer *)((char *)&memory + blockSize);
|
||||
return (trailer->trailerTag == theTag);
|
||||
}
|
||||
#else
|
||||
// stubs
|
||||
void SetPaddingBytes(UInt32 padding) {}
|
||||
void FillPaddingBytes()
|
||||
Boolean CheckPaddingBytes() { return true; }
|
||||
UInt32 GetPaddingBytes() { return 0; }
|
||||
Boolean HasHeaderTag(MemoryBlockTag inHeaderTag){ return true; }
|
||||
void SetHeaderTag(MemoryBlockTag inHeaderTag){}
|
||||
void SetTrailerTag(UInt32 blockSize, MemoryBlockTag theTag) {}
|
||||
Boolean HasTrailerTag(UInt32 blockSize, MemoryBlockTag theTag) { return true; }
|
||||
#endif
|
||||
|
||||
static const UInt32 kLargeBlockOverhead;
|
||||
|
@ -116,7 +108,7 @@ class nsLargeHeapAllocator : public nsMemAllocator
|
|||
|
||||
|
||||
public:
|
||||
nsLargeHeapAllocator();
|
||||
nsLargeHeapAllocator(THz heapZone);
|
||||
~nsLargeHeapAllocator();
|
||||
|
||||
|
||||
|
@ -154,6 +146,7 @@ class nsLargeHeapChunk : public nsHeapChunk
|
|||
|
||||
void * GrowBlock(LargeBlockHeader *growBlock, size_t newSize);
|
||||
void * ShrinkBlock(LargeBlockHeader *shrinkBlock, size_t newSize);
|
||||
void * ResizeBlockInPlace(LargeBlockHeader *theBlock, size_t newSize);
|
||||
|
||||
void ReturnBlock(LargeBlockHeader *deadBlock);
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
#include "nsMemAllocator.h"
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
nsHeapChunk::nsHeapChunk(nsMemAllocator *inOwningAllocator, Size heapSize, Handle tempMemHandle)
|
||||
: mOwningAllocator(inOwningAllocator)
|
||||
|
@ -47,15 +46,15 @@ nsHeapChunk::~nsHeapChunk()
|
|||
#pragma mark -
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
nsMemAllocator::nsMemAllocator()
|
||||
: mFirstChunk(nil)
|
||||
nsMemAllocator::nsMemAllocator(THz inHeapZone)
|
||||
: mHeapZone(inHeapZone)
|
||||
, mFirstChunk(nil)
|
||||
, mLastChunk(nil)
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
, mSignature(kMemAllocatorSignature)
|
||||
#endif
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
@ -73,8 +72,10 @@ nsMemAllocator::~nsMemAllocator()
|
|||
//--------------------------------------------------------------------
|
||||
{
|
||||
MemoryBlockHeader *blockHeader = MemoryBlockHeader::GetHeaderFromBlock(thisBlock);
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
MEM_ASSERT(blockHeader->HasHeaderTag(kUsedBlockHeaderTag), "Bad block header tag");
|
||||
MEM_ASSERT(blockHeader->owningChunk->IsGoodChunk(), "Block has bad chunk pointer");
|
||||
#endif
|
||||
return (blockHeader->owningChunk->GetOwningAllocator());
|
||||
}
|
||||
|
||||
|
@ -83,7 +84,9 @@ nsMemAllocator::~nsMemAllocator()
|
|||
//--------------------------------------------------------------------
|
||||
{
|
||||
nsMemAllocator* allocator = GetAllocatorFromBlock(thisBlock);
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
MEM_ASSERT(allocator && allocator->IsGoodAllocator(), "Failed to get allocator for block");
|
||||
#endif
|
||||
return allocator->AllocatorGetBlockSize(thisBlock);
|
||||
}
|
||||
|
||||
|
@ -101,6 +104,12 @@ void nsMemAllocator::AddToChunkList(nsHeapChunk *inNewChunk)
|
|||
mFirstChunk = inNewChunk;
|
||||
|
||||
mLastChunk = inNewChunk;
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
mCurSubheapCount ++;
|
||||
if (mCurSubheapCount > mMaxSubheapCount)
|
||||
mMaxSubheapCount = mCurSubheapCount;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -134,6 +143,10 @@ void nsMemAllocator::RemoveFromChunkList(nsHeapChunk *inChunk)
|
|||
if (mLastChunk == thisChunk)
|
||||
mLastChunk = prevChunk;
|
||||
}
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
mCurSubheapCount --;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -144,6 +157,7 @@ const Size nsMemAllocator::kFreeHeapSpace = 512 * 1024;
|
|||
// block size multiple. All blocks should be multiples of this size,
|
||||
// to reduce heap fragmentation
|
||||
const Size nsMemAllocator::kChunkSizeMultiple = 2 * 1024;
|
||||
const Size nsMemAllocator::kMacMemoryPtrOvehead = 16;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
Ptr nsMemAllocator::DoMacMemoryAllocation(Size preferredSize, Size &outActualSize,
|
||||
|
@ -160,28 +174,27 @@ Ptr nsMemAllocator::DoMacMemoryAllocation(Size preferredSize, Size &outActualSiz
|
|||
// than preferredSize
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
|
||||
*outTempMemHandle = nil;
|
||||
|
||||
// calculate an ideal chunk size by rounding up
|
||||
//preferredSize += kChunkSizeMultiple * ((preferredSize % kChunkSizeMultiple) > 0);
|
||||
preferredSize = kChunkSizeMultiple * (((preferredSize % kChunkSizeMultiple) > 0) + preferredSize / kChunkSizeMultiple);
|
||||
preferredSize = kChunkSizeMultiple * ((preferredSize + (kChunkSizeMultiple - 1)) / kChunkSizeMultiple);
|
||||
|
||||
// take into accound the memory manager's pointer overhead (16 btyes), to avoid fragmentation
|
||||
preferredSize += ((preferredSize / kChunkSizeMultiple) - 1) * kMacMemoryPtrOvehead;
|
||||
outActualSize = preferredSize;
|
||||
|
||||
// Get the space available if a purge happened. This does not do the purge (despite the name)
|
||||
long total, contig;
|
||||
::PurgeSpace(&total, &contig);
|
||||
// try to allocate in our heap zone
|
||||
::SetZone(mHeapZone);
|
||||
|
||||
Ptr resultPtr = ::NewPtr(preferredSize);
|
||||
|
||||
// set the current zone back to the application zone
|
||||
::SetZone(::ApplicationZone());
|
||||
|
||||
if (resultPtr != nil)
|
||||
return resultPtr;
|
||||
|
||||
Ptr resultPtr = nil;
|
||||
|
||||
if (contig + preferredSize > kFreeHeapSpace) // space in heap
|
||||
{
|
||||
resultPtr = ::NewPtr(preferredSize);
|
||||
if (resultPtr != nil)
|
||||
return resultPtr;
|
||||
}
|
||||
|
||||
// try temp mem now
|
||||
// that failed, so try temp mem now
|
||||
OSErr err;
|
||||
Handle tempMemHandle = ::TempNewHandle(preferredSize, &err);
|
||||
if (tempMemHandle != nil)
|
||||
|
@ -195,3 +208,42 @@ Ptr nsMemAllocator::DoMacMemoryAllocation(Size preferredSize, Size &outActualSiz
|
|||
}
|
||||
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void nsMemAllocator::AccountForNewBlock(size_t logicalSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
mCurBlockCount ++;
|
||||
|
||||
if (mCurBlockCount > mMaxBlockCount)
|
||||
mMaxBlockCount = mCurBlockCount;
|
||||
|
||||
mCurBlockSpaceUsed += logicalSize;
|
||||
|
||||
if (mCurBlockSpaceUsed > mMaxBlockSpaceUsed)
|
||||
mMaxBlockSpaceUsed = mCurBlockSpaceUsed;
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void nsMemAllocator::AccountForResizedBlock(size_t oldLogicalSize, size_t newLogicalSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
mCurBlockSpaceUsed -= oldLogicalSize;
|
||||
mCurBlockSpaceUsed += newLogicalSize;
|
||||
|
||||
if (mCurBlockSpaceUsed > mMaxBlockSpaceUsed)
|
||||
mMaxBlockSpaceUsed = mCurBlockSpaceUsed;
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void nsMemAllocator::AccountForFreedBlock(size_t logicalSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
mCurBlockCount --;
|
||||
mCurBlockSpaceUsed -= logicalSize;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -16,12 +16,7 @@
|
|||
* Reserved. */
|
||||
|
||||
|
||||
|
||||
// temporary defines
|
||||
//#define DEBUG_MAC_MEMORY 0
|
||||
//#define TRACK_EACH_ALLOCATOR 0
|
||||
//#define DEBUG_HEAP_INTEGRITY DEBUG
|
||||
//#define STATS_MAC_MEMORY 0
|
||||
#include <stddef.h>
|
||||
|
||||
class nsMemAllocator;
|
||||
class nsHeapChunk;
|
||||
|
@ -45,6 +40,13 @@ typedef UInt32 MemoryBlockTag;
|
|||
struct MemoryBlockHeader
|
||||
{
|
||||
nsHeapChunk *owningChunk;
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
// it sucks putting an extra data member in here which affects stats, but there is no other
|
||||
// way to store the logical size of each block.
|
||||
size_t logicalBlockSize;
|
||||
#endif
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
//MemoryBlockHeader *next;
|
||||
//MemoryBlockHeader *prev;
|
||||
|
@ -106,7 +108,7 @@ class nsHeapChunk
|
|||
protected:
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
enum {
|
||||
kChunkSignature = 'oink'
|
||||
kChunkSignature = 'Chnk'
|
||||
};
|
||||
|
||||
OSType mSignature;
|
||||
|
@ -128,8 +130,8 @@ class nsMemAllocator
|
|||
{
|
||||
public:
|
||||
|
||||
nsMemAllocator();
|
||||
virtual ~nsMemAllocator();
|
||||
nsMemAllocator(THz inHeapZone);
|
||||
virtual ~nsMemAllocator() = 0;
|
||||
|
||||
static size_t GetBlockSize(void *thisBlock);
|
||||
static nsMemAllocator* GetAllocatorFromBlock(void *thisBlock);
|
||||
|
@ -156,6 +158,7 @@ class nsMemAllocator
|
|||
|
||||
static const Size kFreeHeapSpace;
|
||||
static const Size kChunkSizeMultiple;
|
||||
static const Size kMacMemoryPtrOvehead;
|
||||
|
||||
Ptr DoMacMemoryAllocation(Size preferredSize, Size &outActualSize, Handle *outTempMemHandle);
|
||||
|
||||
|
@ -163,22 +166,54 @@ class nsMemAllocator
|
|||
void RemoveFromChunkList(nsHeapChunk *inChunk);
|
||||
|
||||
enum {
|
||||
kMemAllocatorSignature = 'ARSE'
|
||||
kMemAllocatorSignature = 'ARSE' // Allocators R Supremely Efficient
|
||||
};
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
OSType mSignature; // signature for debugging
|
||||
#endif
|
||||
|
||||
#if DEBUG_BLOCK_TRACKING
|
||||
AllocationSet *mAllocationSet; // allocation set used by xp_tracker code
|
||||
#endif
|
||||
|
||||
nsHeapChunk *mFirstChunk; // pointer to first subheap managed by this allocator
|
||||
nsHeapChunk *mLastChunk; // pointer to last subheap managed by this allocator
|
||||
|
||||
UInt32 mBaseChunkSize; // size of subheap allocated at startup
|
||||
UInt32 mTempChunkSize; // size of additional subheaps
|
||||
|
||||
THz mHeapZone; // heap zone in which to allocate pointers
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
|
||||
public:
|
||||
|
||||
void AccountForNewBlock(size_t logicalSize);
|
||||
void AccountForFreedBlock(size_t logicalSize);
|
||||
void AccountForResizedBlock(size_t oldLogicalSize, size_t newLogicalSize);
|
||||
|
||||
private:
|
||||
|
||||
UInt32 mCurBlockCount; // number of malloc blocks allocated now
|
||||
UInt32 mMaxBlockCount; // max number of malloc blocks allocated
|
||||
|
||||
UInt32 mCurBlockSpaceUsed; // sum of logical size of allocated blocks
|
||||
UInt32 mMaxBlockSpaceUsed; // max of sum of logical size of allocated blocks
|
||||
|
||||
UInt32 mCurHeapSpaceUsed; // sum of physical size of allocated chunks
|
||||
UInt32 mMaxHeapSpaceUsed; // max of sum of logical size of allocated chunks
|
||||
|
||||
UInt32 mCurSubheapCount; // current number of subheaps allocated by this allocator
|
||||
UInt32 mMaxSubheapCount; // max number of subheaps allocated by this allocator
|
||||
|
||||
|
||||
// the difference between mCurBlockSpaceUsed and mCurHeapSpaceUsed is
|
||||
// the allocator overhead, which consists of:
|
||||
//
|
||||
// 1. Block overhead (rounding, headers & trailers)
|
||||
// 2. Unused block space in chunks
|
||||
// 3. Chunk overhead (rounding, headers & trailers)
|
||||
//
|
||||
// This is a reasonable measure of the space efficiency of these allocators
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -26,7 +26,8 @@ const UInt32 SmallHeapBlock::kBlockOverhead = sizeof(SmallHeapBlock) + MEMORY_BL
|
|||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
nsSmallHeapAllocator::nsSmallHeapAllocator()
|
||||
nsSmallHeapAllocator::nsSmallHeapAllocator(THz heapZone)
|
||||
: nsMemAllocator(heapZone)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
mBaseChunkSize = mTempChunkSize = (nsMemAllocator::kChunkSizeMultiple);
|
||||
|
@ -69,14 +70,18 @@ void nsSmallHeapAllocator::AllocatorFreeBlock(void *freeBlock)
|
|||
{
|
||||
SmallHeapBlock *deadBlock = SmallHeapBlock::GetBlockHeader(freeBlock);
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
MEM_ASSERT(deadBlock->HasHeaderTag(kUsedBlockHeaderTag), "Bad block header on free");
|
||||
MEM_ASSERT(deadBlock->HasTrailerTag(deadBlock->GetBlockSize(), kUsedBlockTrailerTag), "Bad block trailer on free");
|
||||
MEM_ASSERT(deadBlock->CheckPaddingBytes(), "Block has overwritten its bounds");
|
||||
#endif
|
||||
|
||||
nsSmallHeapChunk *chunk = deadBlock->GetOwningChunk();
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
deadBlock->SetHeaderTag(kFreeBlockHeaderTag);
|
||||
deadBlock->SetTrailerTag(deadBlock->GetBlockSize(), kFreeBlockTrailerTag);
|
||||
#endif
|
||||
|
||||
chunk->ReturnBlock(deadBlock);
|
||||
|
||||
|
@ -93,9 +98,11 @@ void *nsSmallHeapAllocator::AllocatorResizeBlock(void *block, size_t newSize)
|
|||
SmallHeapBlock *blockHeader = SmallHeapBlock::GetBlockHeader(block);
|
||||
nsSmallHeapChunk *chunk = blockHeader->GetOwningChunk();
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
MEM_ASSERT(blockHeader->HasHeaderTag(kUsedBlockHeaderTag), "Bad block header on realloc");
|
||||
MEM_ASSERT(blockHeader->HasTrailerTag(blockHeader->GetBlockSize(), kUsedBlockTrailerTag), "Bad block trailer on realloc");
|
||||
MEM_ASSERT(blockHeader->CheckPaddingBytes(), "Block has overwritten its bounds");
|
||||
#endif
|
||||
|
||||
UInt32 newAllocSize = (newSize + 3) & ~3;
|
||||
|
||||
|
@ -111,13 +118,7 @@ void *nsSmallHeapAllocator::AllocatorResizeBlock(void *block, size_t newSize)
|
|||
}
|
||||
else
|
||||
{
|
||||
// adjust padding
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
blockHeader->SetPaddingBytes(newAllocSize - newSize);
|
||||
blockHeader->FillPaddingBytes();
|
||||
#endif
|
||||
|
||||
return block; // stays same size
|
||||
return chunk->ResizeBlockInPlace(blockHeader, newSize);
|
||||
}
|
||||
|
||||
return nil;
|
||||
|
@ -129,7 +130,9 @@ size_t nsSmallHeapAllocator::AllocatorGetBlockSize(void *thisBlock)
|
|||
//--------------------------------------------------------------------
|
||||
{
|
||||
SmallHeapBlock *allocBlock = SmallHeapBlock::GetBlockHeader(thisBlock);
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
MEM_ASSERT(allocBlock->HasHeaderTag(kUsedBlockHeaderTag), "Bad block header on get block size");
|
||||
#endif
|
||||
return allocBlock->GetBlockSize();
|
||||
}
|
||||
|
||||
|
@ -343,14 +346,18 @@ done:
|
|||
|
||||
allocatedBlock->SetOwningChunk(this);
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
allocatedBlock->SetHeaderTag(kUsedBlockHeaderTag);
|
||||
allocatedBlock->SetTrailerTag(allocatedBlock->GetBlockSize(), kUsedBlockTrailerTag);
|
||||
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
allocatedBlock->SetPaddingBytes(roundedBlockSize - blockSize);
|
||||
allocatedBlock->FillPaddingBytes();
|
||||
#endif
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
allocatedBlock->SetLogicalBlockSize(blockSize);
|
||||
GetOwningAllocator()->AccountForNewBlock(blockSize);
|
||||
#endif
|
||||
|
||||
IncrementUsedBlocks();
|
||||
return &allocatedBlock->memory;
|
||||
}
|
||||
|
@ -421,8 +428,13 @@ void *nsSmallHeapChunk::GrowBlock(SmallHeapBlock *growBlock, size_t newSize)
|
|||
#if DEBUG_HEAP_INTEGRITY
|
||||
growBlock->SetPaddingBytes(newAllocSize - newSize);
|
||||
growBlock->FillPaddingBytes();
|
||||
#endif
|
||||
growBlock->SetTrailerTag(growBlock->GetBlockSize(), kUsedBlockTrailerTag);
|
||||
#endif
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
GetOwningAllocator()->AccountForResizedBlock(growBlock->GetLogicalBlockSize(), newSize);
|
||||
growBlock->SetLogicalBlockSize(newSize);
|
||||
#endif
|
||||
|
||||
return (void *)(&growBlock->memory);
|
||||
}
|
||||
|
@ -480,13 +492,38 @@ void *nsSmallHeapChunk::ShrinkBlock(SmallHeapBlock *shrinkBlock, size_t newSize)
|
|||
#if DEBUG_HEAP_INTEGRITY
|
||||
shrinkBlock->SetPaddingBytes(newAllocSize - newSize);
|
||||
shrinkBlock->FillPaddingBytes();
|
||||
#endif
|
||||
shrinkBlock->SetTrailerTag(shrinkBlock->GetBlockSize(), kUsedBlockTrailerTag);
|
||||
#endif
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
GetOwningAllocator()->AccountForResizedBlock(shrinkBlock->GetLogicalBlockSize(), newSize);
|
||||
shrinkBlock->SetLogicalBlockSize(newSize);
|
||||
#endif
|
||||
|
||||
return (void *)(&shrinkBlock->memory);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void* nsSmallHeapChunk::ResizeBlockInPlace(SmallHeapBlock *theBlock, size_t newSize)
|
||||
//--------------------------------------------------------------------
|
||||
{
|
||||
#if DEBUG_HEAP_INTEGRITY
|
||||
UInt32 newAllocSize = (newSize + 3) & ~3;
|
||||
|
||||
theBlock->SetPaddingBytes(newAllocSize - newSize);
|
||||
theBlock->FillPaddingBytes();
|
||||
#endif
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
GetOwningAllocator()->AccountForResizedBlock(theBlock->GetLogicalBlockSize(), newSize);
|
||||
theBlock->SetLogicalBlockSize(newSize);
|
||||
#endif
|
||||
|
||||
return (void *)(&theBlock->memory);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void nsSmallHeapChunk::ReturnBlock(SmallHeapBlock *deadBlock)
|
||||
//--------------------------------------------------------------------
|
||||
|
@ -494,6 +531,10 @@ void nsSmallHeapChunk::ReturnBlock(SmallHeapBlock *deadBlock)
|
|||
SmallHeapBlock *nextBlock = deadBlock->GetNextBlock();
|
||||
SmallHeapBlock *prevBlock = deadBlock->GetPrevBlock();
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
GetOwningAllocator()->AccountForFreedBlock(deadBlock->GetLogicalBlockSize());
|
||||
#endif
|
||||
|
||||
// If the block after us is free, then coalesce with it.
|
||||
if (! nextBlock->IsBlockUsed())
|
||||
{
|
||||
|
|
|
@ -91,18 +91,13 @@ struct SmallHeapBlock
|
|||
MemoryBlockTrailer *trailer = (MemoryBlockTrailer *)((char *)&memory + blockSize);
|
||||
return (trailer->trailerTag == theTag);
|
||||
}
|
||||
#else
|
||||
// stubs
|
||||
void SetPaddingBytes(UInt32 padding) {}
|
||||
void FillPaddingBytes()
|
||||
Boolean CheckPaddingBytes() { return true; }
|
||||
UInt32 GetPaddingBytes() { return 0; }
|
||||
Boolean HasHeaderTag(MemoryBlockTag inHeaderTag){ return true; }
|
||||
void SetHeaderTag(MemoryBlockTag inHeaderTag){}
|
||||
void SetTrailerTag(UInt32 blockSize, MemoryBlockTag theTag) {}
|
||||
Boolean HasTrailerTag(UInt32 blockSize, MemoryBlockTag theTag) { return true; }
|
||||
#endif
|
||||
|
||||
#if STATS_MAC_MEMORY
|
||||
size_t GetLogicalBlockSize() { return info.inUseInfo.freeProc.logicalBlockSize; }
|
||||
void SetLogicalBlockSize(size_t blockSize) { info.inUseInfo.freeProc.logicalBlockSize = blockSize; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
SmallHeapBlock *prevBlock;
|
||||
|
@ -135,7 +130,7 @@ class nsSmallHeapAllocator : public nsMemAllocator
|
|||
|
||||
public:
|
||||
|
||||
nsSmallHeapAllocator();
|
||||
nsSmallHeapAllocator(THz heapZone);
|
||||
~nsSmallHeapAllocator();
|
||||
|
||||
virtual void * AllocatorMakeBlock(size_t blockSize);
|
||||
|
@ -168,7 +163,7 @@ class nsSmallHeapChunk : public nsHeapChunk
|
|||
|
||||
void * GrowBlock(SmallHeapBlock *growBlock, size_t newSize);
|
||||
void * ShrinkBlock(SmallHeapBlock *shrinkBlock, size_t newSize);
|
||||
|
||||
void * ResizeBlockInPlace(SmallHeapBlock *shrinkBlock, size_t newSize);
|
||||
|
||||
protected:
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче