diff --git a/mozilla/lib/mac/MacMemoryAllocator/src/nsAllocatorManager.cp b/mozilla/lib/mac/MacMemoryAllocator/src/nsAllocatorManager.cp index fcaf4a6df61..26eaf85468b 100644 --- a/mozilla/lib/mac/MacMemoryAllocator/src/nsAllocatorManager.cp +++ b/mozilla/lib/mac/MacMemoryAllocator/src/nsAllocatorManager.cp @@ -16,6 +16,7 @@ * Reserved. */ #include +#include #include // for placement new @@ -25,6 +26,10 @@ #include #include +#if __profile__ +#include +#endif + #include "nsMemAllocator.h" #include "nsFixedSizeAllocator.h" @@ -52,48 +57,106 @@ pascal void __MemTerminate(void); //-------------------------------------------------------------------- -class nsAllocatorManager +nsHeapZoneHeader::nsHeapZoneHeader(Ptr zonePtr, Size ptrSize) +: mNextHeapZone(nil) +, mZoneHandle(nil) +, mChunkCount(0) +, mHeapZone(nil) +#if DEBUG_HEAP_INTEGRITY +, mSignature(kHeapZoneSignature) +#endif +// This ctor is used for zones in our heap, which are allocated with +// NewPtr +//-------------------------------------------------------------------- { - public: + SetupHeapZone(zonePtr, ptrSize); +} - static const SInt32 kNumMasterPointerBlocks; - static const SInt32 kApplicationStackSizeIncrease; - static const SInt32 kHeapZoneHeapPercentage; - - nsAllocatorManager(); - ~nsAllocatorManager(); - - static OSErr InitializeMacMemory(SInt32 inNumMasterPointerBlocks, - SInt32 inAppStackSizeInc); - - - nsMemAllocator* GetAllocatorForBlockSize(size_t blockSize); - - static nsAllocatorManager* GetAllocatorManager(); - - protected: - - static nsAllocatorManager *sAllocatorManager; - - private: - - SInt32 mNumFixedSizeAllocators; - SInt32 mNumSmallBlockAllocators; - - UInt32 mMinSmallBlockSize; // blocks >= this size come out of the small block allocator - UInt32 mMinLargeBlockSize; // blocks >= this size come out of the large allocator - - nsMemAllocator** mFixedSizeAllocators; // array of pointers to allocator objects - nsMemAllocator** mSmallBlockAllocators; // array of pointers to allocator objects - - nsMemAllocator* mLargeAllocator; - - THz mHeapZone; // the heap zone for our memory heaps - -}; //-------------------------------------------------------------------- +nsHeapZoneHeader::nsHeapZoneHeader(Handle zoneHandle, Size handleSize) +: mNextHeapZone(nil) +, mZoneHandle(zoneHandle) +, mChunkCount(0) +, mHeapZone(nil) +#if DEBUG_HEAP_INTEGRITY +, mSignature(kHeapZoneSignature) +#endif +// This ctor is used for zones in temporary memory, which are allocated +// with TempNewHandle +//-------------------------------------------------------------------- +{ + // handle should be locked here + SetupHeapZone(*zoneHandle, handleSize); +} +//-------------------------------------------------------------------- +nsHeapZoneHeader::~nsHeapZoneHeader() +//-------------------------------------------------------------------- +{ + if (mZoneHandle) + ::DisposeHandle(mZoneHandle); + else + ::DisposePtr((Ptr)this); + + MEM_ASSERT(::MemError() == noErr, "Error on Mac memory dispose"); +} + + +//-------------------------------------------------------------------- +void nsHeapZoneHeader::SetupHeapZone(Ptr zonePtr, Size ptrSize) +//-------------------------------------------------------------------- +{ + Ptr zoneStart = zonePtr + sizeof(nsHeapZoneHeader); + Ptr endZone = zonePtr + ptrSize; + + ::InitZone(nil, kHeapZoneMasterPointers, endZone, zoneStart); + + mHeapZone = (THz)zoneStart; + + // set the current zone back to the application zone, because InitZone changes it + ::SetZone(::ApplicationZone()); +} + + +//-------------------------------------------------------------------- +Ptr nsHeapZoneHeader::AllocateZonePtr(Size ptrSize) +//-------------------------------------------------------------------- +{ + ::SetZone(mHeapZone); + Ptr thePtr = ::NewPtr(ptrSize); + ::SetZone(::ApplicationZone()); + + mChunkCount += (thePtr != nil); + + return thePtr; +} + + +//-------------------------------------------------------------------- +void nsHeapZoneHeader::DisposeZonePtr(Ptr thePtr, Boolean &outWasLastChunk) +//-------------------------------------------------------------------- +{ + MEM_ASSERT(::PtrZone(thePtr) == mHeapZone, "Ptr disposed from wrong zone!"); + ::DisposePtr(thePtr); + mChunkCount --; + outWasLastChunk = (mChunkCount == 0); +} + + +//-------------------------------------------------------------------- +/* static */ nsHeapZoneHeader* nsHeapZoneHeader::GetZoneFromPtr(Ptr subheapPtr) +//-------------------------------------------------------------------- +{ + THz ptrZone = ::PtrZone(subheapPtr); + MEM_ASSERT(ptrZone && (::MemError() == noErr), "Problem getting zone from ptr"); + + return (nsHeapZoneHeader *)((char *)ptrZone - sizeof(nsHeapZoneHeader)); +} + + + +#pragma mark - const SInt32 nsAllocatorManager::kNumMasterPointerBlocks = 30; @@ -103,10 +166,12 @@ const SInt32 nsAllocatorManager::kHeapZoneHeapPercentage = 60; nsAllocatorManager* nsAllocatorManager::sAllocatorManager = nil; //-------------------------------------------------------------------- -nsAllocatorManager::nsAllocatorManager() : - mFixedSizeAllocators(nil), - mSmallBlockAllocators(nil), - mLargeAllocator(nil) +nsAllocatorManager::nsAllocatorManager() +: mFixedSizeAllocators(nil) +, mSmallBlockAllocators(nil) +, mLargeAllocator(nil) +, mFirstHeapZone(nil) +, mLastHeapZone(nil) //-------------------------------------------------------------------- { mMinSmallBlockSize = 44; // some magic numbers for now @@ -129,6 +194,7 @@ nsAllocatorManager::nsAllocatorManager() : mFixedSizeAllocators[i] = (nsMemAllocator *)NewPtr(sizeof(nsFixedSizeAllocator)); if (mFixedSizeAllocators[i] == nil) throw((OSErr)memFullErr); + new (mFixedSizeAllocators[i]) nsFixedSizeAllocator((i + 1) * 4); } for (SInt32 i = 0; i < mNumSmallBlockAllocators; i ++) @@ -136,11 +202,13 @@ nsAllocatorManager::nsAllocatorManager() : mSmallBlockAllocators[i] = (nsMemAllocator *)NewPtr(sizeof(nsSmallHeapAllocator)); if (mSmallBlockAllocators[i] == nil) throw((OSErr)memFullErr); + new (mSmallBlockAllocators[i]) nsSmallHeapAllocator(); } mLargeAllocator = (nsMemAllocator *)NewPtr(sizeof(nsLargeHeapAllocator)); if (mLargeAllocator == nil) throw((OSErr)memFullErr); + new (mLargeAllocator) nsLargeHeapAllocator(); // make the heap zone for our subheaps UInt32 heapZoneSize; @@ -148,30 +216,10 @@ nsAllocatorManager::nsAllocatorManager() : heapZoneSize = ( kHeapZoneHeapPercentage * ::FreeMem() ) / 100; heapZoneSize = ( ( heapZoneSize + 3 ) & ~3 ); // round up to a multiple of 4 bytes - Ptr heapZone = ::NewPtr(heapZoneSize); - if (heapZone == nil) + nsHeapZoneHeader *firstZone = MakeNewHeapZone(heapZoneSize, heapZoneSize); + if (!firstZone) 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); - } //-------------------------------------------------------------------- @@ -215,6 +263,131 @@ nsMemAllocator* nsAllocatorManager::GetAllocatorForBlockSize(size_t blockSize) return mLargeAllocator; } +//-------------------------------------------------------------------- +nsHeapZoneHeader* nsAllocatorManager::MakeNewHeapZone(Size zoneSize, Size minZoneSize) +//-------------------------------------------------------------------- +{ + if (mFirstHeapZone == nil) + { + Ptr firstZonePtr = ::NewPtr(zoneSize); + + if (!firstZonePtr) return nil; + + mFirstHeapZone = new (firstZonePtr) nsHeapZoneHeader(firstZonePtr, zoneSize); + mLastHeapZone = mFirstHeapZone; + } + else + { + OSErr err; + Handle tempMemHandle = ::TempNewHandle(zoneSize, &err); + + while (!tempMemHandle && zoneSize > minZoneSize) + { + zoneSize -= (128 * 1024); + tempMemHandle = ::TempNewHandle(zoneSize, &err); + } + + if (!tempMemHandle) return nil; + + // first, lock the handle hi + HLockHi(tempMemHandle); + + nsHeapZoneHeader *newZone = new (*tempMemHandle) nsHeapZoneHeader(tempMemHandle, zoneSize); + mLastHeapZone->SetNextZone(newZone); + mLastHeapZone = newZone; + } + + return mLastHeapZone; +} + + +// block size multiple. All blocks should be multiples of this size, +// to reduce heap fragmentation +const Size nsAllocatorManager::kChunkSizeMultiple = 2 * 1024; +const Size nsAllocatorManager::kMacMemoryPtrOvehead = 16; // this overhead is documented in IM:Memory 2-22 +const Size nsAllocatorManager::kTempMemHeapZoneSize = 1024 * 1024; // 1MB temp handles +const Size nsAllocatorManager::kTempMemHeapMinZoneSize = 256 * 1024; // min 256K handle + + +//-------------------------------------------------------------------- +Ptr nsAllocatorManager::AllocateSubheap(Size preferredSize, Size &outActualSize) +//-------------------------------------------------------------------- +{ + nsHeapZoneHeader *thisHeapZone = mFirstHeapZone; + + // calculate an ideal chunk size by rounding up + 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; + + while (thisHeapZone) + { + Ptr subheapPtr = thisHeapZone->AllocateZonePtr(preferredSize); + if (subheapPtr) + return subheapPtr; + + thisHeapZone = thisHeapZone->GetNextZone(); + } + + // we failed to allocate. Let's make a new heap zone + thisHeapZone = MakeNewHeapZone(kTempMemHeapZoneSize, kTempMemHeapMinZoneSize); + if (thisHeapZone) + return thisHeapZone->AllocateZonePtr(preferredSize); + + return nil; +} + + +//-------------------------------------------------------------------- +void nsAllocatorManager::FreeSubheap(Ptr subheapPtr) +//-------------------------------------------------------------------- +{ + nsHeapZoneHeader *ptrHeapZone = nsHeapZoneHeader::GetZoneFromPtr(subheapPtr); + +#if DEBUG_HEAP_INTEGRITY + MEM_ASSERT(ptrHeapZone->IsGoodZone(), "Got bad heap zone header"); +#endif + + Boolean lastChunk; + ptrHeapZone->DisposeZonePtr(subheapPtr, lastChunk); + + if (lastChunk) + { + // remove from the list + nsHeapZoneHeader *prevZone = nil; + nsHeapZoneHeader *nextZone = nil; + nsHeapZoneHeader *thisZone = mFirstHeapZone; + + while (thisZone) + { + nextZone = thisZone->GetNextZone(); + + if (thisZone == ptrHeapZone) + break; + + prevZone = thisZone; + thisZone = nextZone; + } + + if (thisZone) + { + if (prevZone) + prevZone->SetNextZone(nextZone); + + if (mFirstHeapZone == thisZone) + mFirstHeapZone = nextZone; + + if (mLastHeapZone == thisZone) + mLastHeapZone = prevZone; + } + + // dispose it + ptrHeapZone->~nsHeapZoneHeader(); // this disposes the ptr/handle + } +} + //-------------------------------------------------------------------- /* static */ OSErr nsAllocatorManager::InitializeMacMemory(SInt32 inNumMasterPointerBlocks, @@ -258,7 +431,7 @@ nsMemAllocator* nsAllocatorManager::GetAllocatorForBlockSize(size_t blockSize) //-------------------------------------------------------------------- -/* static */ nsAllocatorManager * nsAllocatorManager::GetAllocatorManager() +/* static */ nsAllocatorManager * nsAllocatorManager::CreateAllocatorManager() //-------------------------------------------------------------------- { if (sAllocatorManager) return sAllocatorManager; @@ -269,6 +442,57 @@ nsMemAllocator* nsAllocatorManager::GetAllocatorForBlockSize(size_t blockSize) return sAllocatorManager; } + + +#if STATS_MAC_MEMORY +//-------------------------------------------------------------------- +void nsAllocatorManager::DumpMemoryStats() +//-------------------------------------------------------------------- +{ + UInt32 i; + char outString[ 1024 ]; + PRFileDesc *outFile; + + // Enter a valid, UNIX-style full path on your system to get this + // to work. + outFile = PR_Open("/System/MemoryStats.txt", PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE, 0644); + if ( outFile == NULL ) + { + return; + } + + for (i = 0; i < mNumFixedSizeAllocators; i ++) + { + mFixedSizeAllocators[i]->DumpMemoryStats(outFile); + } + + for (i = 0; i < mNumSmallBlockAllocators; i ++) + { + mSmallBlockAllocators[i]->DumpMemoryStats(outFile); + } + + mLargeAllocator->DumpMemoryStats(outFile); + + PR_Close(outFile); +} + + +//-------------------------------------------------------------------- +void WriteString(PRFileDesc *file, const char * string) +//-------------------------------------------------------------------- +{ + long len; + long bytesWritten; + + len = strlen ( string ); + if ( len >= 1024 ) Debugger(); + bytesWritten = PR_Write(file, string, len); +} + + +#endif + + #pragma mark - @@ -348,13 +572,11 @@ void *calloc(size_t nele, size_t elesize) #pragma mark - -#if 0 - /*---------------------------------------------------------------------------- __MemInitialize Note the people can call malloc() or new() before we come here, - so we only initialize the memory if we've not alredy done it.s + so we can't rely on this being called before we do allocation. ----------------------------------------------------------------------------*/ pascal OSErr __MemInitialize(const CFragInitBlock *theInitBlock) @@ -389,9 +611,11 @@ pascal void __MemTerminate(void) ProfilerTerm(); #endif +#if STATS_MAC_MEMORY + nsAllocatorManager::GetAllocatorManager()->DumpMemoryStats(); +#endif + __terminate(); } -#endif - diff --git a/mozilla/lib/mac/MacMemoryAllocator/src/nsAllocatorManager.h b/mozilla/lib/mac/MacMemoryAllocator/src/nsAllocatorManager.h index 5698fc76cd2..191d4493bb5 100644 --- a/mozilla/lib/mac/MacMemoryAllocator/src/nsAllocatorManager.h +++ b/mozilla/lib/mac/MacMemoryAllocator/src/nsAllocatorManager.h @@ -18,7 +18,9 @@ #include - +#if STATS_MAC_MEMORY +#include "prio.h" +#endif #ifdef __cplusplus extern "C" { @@ -30,6 +32,123 @@ void* realloc(void* block, size_t newSize); void *calloc(size_t nele, size_t elesize); +#if STATS_MAC_MEMORY +void WriteString(PRFileDesc *file, const char * string); +#endif + + #ifdef __cplusplus } #endif + + +//-------------------------------------------------------------------- +class nsHeapZoneHeader +{ + public: + + nsHeapZoneHeader(Ptr zonePtr, Size ptrSize); + nsHeapZoneHeader(Handle zoneHandle, Size handleSize); + ~nsHeapZoneHeader(); + + nsHeapZoneHeader * GetNextZone() { return mNextHeapZone; } + void SetNextZone(nsHeapZoneHeader *nextZone) { mNextHeapZone = nextZone; } + + Ptr AllocateZonePtr(Size ptrSize); + void DisposeZonePtr(Ptr thePtr, Boolean &outWasLastChunk); + +#if DEBUG_HEAP_INTEGRITY + Boolean IsGoodZone() { return (mSignature == kHeapZoneSignature); } +#endif + + static nsHeapZoneHeader* GetZoneFromPtr(Ptr subheapPtr); + + protected: + + void SetupHeapZone(Ptr zonePtr, Size zoneSize); + + enum + { + kHeapZoneMasterPointers = 24 // this number doesn't really matter, because we never + // allocate handles in our heap zones + }; + + +#if DEBUG_HEAP_INTEGRITY + enum { + kHeapZoneSignature = 'HZne' + }; + + OSType mSignature; +#endif + + nsHeapZoneHeader *mNextHeapZone; + Handle mZoneHandle; // the handle containing the zone. Nil if Ptr in app heap + UInt32 mChunkCount; // how many chunks are allocated in this zone + THz mHeapZone; +}; + + + + +class nsAllocatorManager +{ + public: + + static const SInt32 kNumMasterPointerBlocks; + static const SInt32 kApplicationStackSizeIncrease; + + static const SInt32 kHeapZoneHeapPercentage; + static const SInt32 kTempMemHeapZoneSize; + static const SInt32 kTempMemHeapMinZoneSize; + + static const Size kChunkSizeMultiple; + + static nsAllocatorManager* GetAllocatorManager() { return sAllocatorManager ? sAllocatorManager : CreateAllocatorManager(); } + + nsAllocatorManager(); + ~nsAllocatorManager(); + + static OSErr InitializeMacMemory(SInt32 inNumMasterPointerBlocks, + SInt32 inAppStackSizeInc); + + nsMemAllocator* GetAllocatorForBlockSize(size_t blockSize); + + + Ptr AllocateSubheap(Size preferredSize, Size &outActualSize); + void FreeSubheap(Ptr subheapPtr); + +#if STATS_MAC_MEMORY + void DumpMemoryStats(); +#endif + + protected: + + static nsAllocatorManager * CreateAllocatorManager(); + + static const Size kMacMemoryPtrOvehead; + + nsHeapZoneHeader * MakeNewHeapZone(Size zoneSize, Size minZoneSize); + + private: + + SInt32 mNumFixedSizeAllocators; + SInt32 mNumSmallBlockAllocators; + + UInt32 mMinSmallBlockSize; // blocks >= this size come out of the small block allocator + UInt32 mMinLargeBlockSize; // blocks >= this size come out of the large allocator + + nsMemAllocator** mFixedSizeAllocators; // array of pointers to allocator objects + nsMemAllocator** mSmallBlockAllocators; // array of pointers to allocator objects + + nsMemAllocator* mLargeAllocator; + + nsHeapZoneHeader* mFirstHeapZone; // first of a linked list of heap zones + nsHeapZoneHeader* mLastHeapZone; // last of a linked list of heap zones + + THz mHeapZone; // the heap zone for our memory heaps + + static nsAllocatorManager *sAllocatorManager; + +}; + diff --git a/mozilla/lib/mac/MacMemoryAllocator/src/nsFixedSizeAllocator.cp b/mozilla/lib/mac/MacMemoryAllocator/src/nsFixedSizeAllocator.cp index 0b5e54dfdb8..cf8de98a030 100644 --- a/mozilla/lib/mac/MacMemoryAllocator/src/nsFixedSizeAllocator.cp +++ b/mozilla/lib/mac/MacMemoryAllocator/src/nsFixedSizeAllocator.cp @@ -20,17 +20,19 @@ #include #include "nsMemAllocator.h" +#include "nsAllocatorManager.h" #include "nsFixedSizeAllocator.h" const UInt32 FixedMemoryBlock::kFixedSizeBlockOverhead = sizeof(FixedMemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE; //-------------------------------------------------------------------- -nsFixedSizeAllocator::nsFixedSizeAllocator(THz heapZone, size_t blockSize) -: nsMemAllocator(heapZone) +nsFixedSizeAllocator::nsFixedSizeAllocator(size_t blockSize) +: nsMemAllocator() , mBlockSize(blockSize) +, mChunkWithSpace(nil) //-------------------------------------------------------------------- { - mBaseChunkSize = mTempChunkSize = (nsMemAllocator::kChunkSizeMultiple); + mBaseChunkSize = mTempChunkSize = (nsAllocatorManager::kChunkSizeMultiple); } //-------------------------------------------------------------------- @@ -46,6 +48,9 @@ nsHeapChunk* nsFixedSizeAllocator::FindChunkWithSpace(size_t blockSize) const { nsFixedSizeHeapChunk* chunk = (nsFixedSizeHeapChunk *)mFirstChunk; + if (mChunkWithSpace && mChunkWithSpace->GetFreeList()) + return mChunkWithSpace; + // Try to find an existing chunk with a free block. while (chunk != nil) { @@ -69,10 +74,12 @@ void *nsFixedSizeAllocator::AllocatorMakeBlock(size_t blockSize) { chunk = (nsFixedSizeHeapChunk *)AllocateChunk(blockSize); if (!chunk) return nil; + + mChunkWithSpace = chunk; } FixedMemoryBlock* blockHeader = chunk->FetchFirstFree(); - + #if DEBUG_HEAP_INTEGRITY blockHeader->SetHeaderTag(kUsedBlockHeaderTag); blockHeader->SetTrailerTag(GetAllocatorBlockSize(), kUsedBlockTrailerTag); @@ -119,8 +126,14 @@ void nsFixedSizeAllocator::AllocatorFreeBlock(void *freeBlock) // if this chunk is completely empty and it's not the first chunk then free it if ( chunk->IsEmpty() && chunk != mFirstChunk ) { + if (chunk == mChunkWithSpace) + mChunkWithSpace = nil; FreeChunk(chunk); } + else + { + mChunkWithSpace = chunk; // we know is has some space now + } } @@ -170,13 +183,13 @@ nsHeapChunk *nsFixedSizeAllocator::AllocateChunk(size_t requestedBlockSize) //-------------------------------------------------------------------- { Size actualChunkSize; - Handle tempMemHandle; - Ptr chunkMemory = DoMacMemoryAllocation(mBaseChunkSize, actualChunkSize, &tempMemHandle); + Ptr chunkMemory = nsAllocatorManager::GetAllocatorManager()->AllocateSubheap(mBaseChunkSize, actualChunkSize); // use placement new to initialize the chunk in the memory block - nsHeapChunk *newHeapChunk = new (chunkMemory) nsFixedSizeHeapChunk(this, actualChunkSize, tempMemHandle); + nsHeapChunk *newHeapChunk = new (chunkMemory) nsFixedSizeHeapChunk(this, actualChunkSize); if (newHeapChunk) AddToChunkList(newHeapChunk); + return newHeapChunk; } @@ -190,11 +203,7 @@ void nsFixedSizeAllocator::FreeChunk(nsHeapChunk *chunkToFree) nsFixedSizeHeapChunk *thisChunk = (nsFixedSizeHeapChunk *)chunkToFree; thisChunk->~nsFixedSizeHeapChunk(); - Handle tempMemHandle = thisChunk->GetMemHandle(); - if (tempMemHandle) - DisposeHandle(tempMemHandle); - else - DisposePtr((Ptr)thisChunk); + nsAllocatorManager::GetAllocatorManager()->FreeSubheap((Ptr)thisChunk); } @@ -203,9 +212,8 @@ void nsFixedSizeAllocator::FreeChunk(nsHeapChunk *chunkToFree) //-------------------------------------------------------------------- nsFixedSizeHeapChunk::nsFixedSizeHeapChunk( nsMemAllocator *inOwningAllocator, - Size heapSize, - Handle tempMemHandle) : - nsHeapChunk(inOwningAllocator, heapSize, tempMemHandle) + Size heapSize) : + nsHeapChunk(inOwningAllocator, heapSize) //-------------------------------------------------------------------- { nsFixedSizeAllocator *allocator = (nsFixedSizeAllocator *)mOwningAllocator; diff --git a/mozilla/lib/mac/MacMemoryAllocator/src/nsFixedSizeAllocator.h b/mozilla/lib/mac/MacMemoryAllocator/src/nsFixedSizeAllocator.h index bcaac577c2e..bec487ea3f4 100644 --- a/mozilla/lib/mac/MacMemoryAllocator/src/nsFixedSizeAllocator.h +++ b/mozilla/lib/mac/MacMemoryAllocator/src/nsFixedSizeAllocator.h @@ -106,7 +106,7 @@ class nsFixedSizeAllocator : public nsMemAllocator public: - nsFixedSizeAllocator(THz heapZone, size_t blockSize); + nsFixedSizeAllocator(size_t blockSize); ~nsFixedSizeAllocator(); virtual void * AllocatorMakeBlock(size_t blockSize); @@ -130,7 +130,9 @@ class nsFixedSizeAllocator : public nsMemAllocator UInt32 mBlockSize; // upper bound for blocks allocated in this heap // does not include block overhead - + nsFixedSizeHeapChunk *mChunkWithSpace; // cheap optimization + + #if STATS_MAC_MEMORY UInt32 mChunksAllocated; UInt32 mMaxChunksAllocated; @@ -156,20 +158,20 @@ class nsFixedSizeHeapChunk : public nsHeapChunk { public: - nsFixedSizeHeapChunk(nsMemAllocator *inOwningAllocator, Size heapSize, Handle tempMemHandle); - ~nsFixedSizeHeapChunk(); + nsFixedSizeHeapChunk(nsMemAllocator *inOwningAllocator, Size heapSize); + ~nsFixedSizeHeapChunk(); FixedMemoryBlock* GetFreeList() const { return mFreeList; } - void SetFreeList(FixedMemoryBlock *nextFree) { mFreeList = nextFree; } + void SetFreeList(FixedMemoryBlock *nextFree) { mFreeList = nextFree; } FixedMemoryBlock* FetchFirstFree(); - void ReturnToFreeList(FixedMemoryBlock *freeBlock); + void ReturnToFreeList(FixedMemoryBlock *freeBlock); protected: #if STATS_MAC_MEMORY - UInt32 chunkSize; - UInt32 numBlocks; + UInt32 chunkSize; + UInt32 numBlocks; #endif FixedMemoryBlock *mFreeList; diff --git a/mozilla/lib/mac/MacMemoryAllocator/src/nsLargeHeapAllocator.cp b/mozilla/lib/mac/MacMemoryAllocator/src/nsLargeHeapAllocator.cp index 2aa5096f74b..1b5530eca21 100644 --- a/mozilla/lib/mac/MacMemoryAllocator/src/nsLargeHeapAllocator.cp +++ b/mozilla/lib/mac/MacMemoryAllocator/src/nsLargeHeapAllocator.cp @@ -19,14 +19,15 @@ #include #include "nsMemAllocator.h" +#include "nsAllocatorManager.h" #include "nsLargeHeapAllocator.h" const UInt32 LargeBlockHeader::kLargeBlockOverhead = sizeof(LargeBlockHeader) + MEMORY_BLOCK_TAILER_SIZE; //-------------------------------------------------------------------- -nsLargeHeapAllocator::nsLargeHeapAllocator(THz heapZone) -: nsMemAllocator(heapZone) +nsLargeHeapAllocator::nsLargeHeapAllocator() +: nsMemAllocator() //-------------------------------------------------------------------- { mBaseChunkSize = mTempChunkSize = (64 * 1024); @@ -160,17 +161,16 @@ nsHeapChunk *nsLargeHeapAllocator::AllocateChunk(size_t requestedBlockSize) //-------------------------------------------------------------------- { Size chunkSize = mBaseChunkSize, actualChunkSize; - Handle tempMemHandle; size_t paddedBlockSize = (( requestedBlockSize + 3 ) & ~3) + 3 * LargeBlockHeader::kLargeBlockOverhead + sizeof(nsLargeHeapChunk); if (paddedBlockSize > chunkSize) chunkSize = paddedBlockSize; - Ptr chunkMemory = DoMacMemoryAllocation(chunkSize, actualChunkSize, &tempMemHandle); + Ptr chunkMemory = nsAllocatorManager::GetAllocatorManager()->AllocateSubheap(chunkSize, actualChunkSize); // use placement new to initialize the chunk in the memory block - nsHeapChunk *newHeapChunk = new (chunkMemory) nsLargeHeapChunk(this, actualChunkSize, tempMemHandle); + nsHeapChunk *newHeapChunk = new (chunkMemory) nsLargeHeapChunk(this, actualChunkSize); if (newHeapChunk) AddToChunkList(newHeapChunk); @@ -188,11 +188,7 @@ void nsLargeHeapAllocator::FreeChunk(nsHeapChunk *chunkToFree) nsLargeHeapChunk *thisChunk = (nsLargeHeapChunk *)chunkToFree; thisChunk->~nsLargeHeapChunk(); - Handle tempMemHandle = thisChunk->GetMemHandle(); - if (tempMemHandle) - DisposeHandle(tempMemHandle); - else - DisposePtr((Ptr)thisChunk); + nsAllocatorManager::GetAllocatorManager()->FreeSubheap((Ptr)thisChunk); } @@ -201,9 +197,8 @@ void nsLargeHeapAllocator::FreeChunk(nsHeapChunk *chunkToFree) //-------------------------------------------------------------------- nsLargeHeapChunk::nsLargeHeapChunk( nsMemAllocator *inOwningAllocator, - Size heapSize, - Handle tempMemHandle) : - nsHeapChunk(inOwningAllocator, heapSize, tempMemHandle) + Size heapSize) : + nsHeapChunk(inOwningAllocator, heapSize) //-------------------------------------------------------------------- { heapSize -= sizeof(nsLargeHeapChunk); // subtract heap overhead diff --git a/mozilla/lib/mac/MacMemoryAllocator/src/nsLargeHeapAllocator.h b/mozilla/lib/mac/MacMemoryAllocator/src/nsLargeHeapAllocator.h index 15f95b8f8cf..27a8652fb8f 100644 --- a/mozilla/lib/mac/MacMemoryAllocator/src/nsLargeHeapAllocator.h +++ b/mozilla/lib/mac/MacMemoryAllocator/src/nsLargeHeapAllocator.h @@ -108,7 +108,7 @@ class nsLargeHeapAllocator : public nsMemAllocator public: - nsLargeHeapAllocator(THz heapZone); + nsLargeHeapAllocator(); ~nsLargeHeapAllocator(); @@ -136,8 +136,7 @@ class nsLargeHeapChunk : public nsHeapChunk public: nsLargeHeapChunk( nsMemAllocator *inOwningAllocator, - Size heapSize, - Handle tempMemHandle); + Size heapSize); ~nsLargeHeapChunk(); LargeBlockHeader* GetHeadBlock() { return mHead; } diff --git a/mozilla/lib/mac/MacMemoryAllocator/src/nsMemAllocator.cp b/mozilla/lib/mac/MacMemoryAllocator/src/nsMemAllocator.cp index 6b566e039ef..19c7a29e312 100644 --- a/mozilla/lib/mac/MacMemoryAllocator/src/nsMemAllocator.cp +++ b/mozilla/lib/mac/MacMemoryAllocator/src/nsMemAllocator.cp @@ -15,18 +15,19 @@ * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ +#include #include - #include "nsMemAllocator.h" +#include "nsAllocatorManager.h" + //-------------------------------------------------------------------- -nsHeapChunk::nsHeapChunk(nsMemAllocator *inOwningAllocator, Size heapSize, Handle tempMemHandle) +nsHeapChunk::nsHeapChunk(nsMemAllocator *inOwningAllocator, Size heapSize) : mOwningAllocator(inOwningAllocator) , mNextChunk(nil) , mHeapSize(heapSize) , mUsedBlocks(0) -, mTempMemHandle(tempMemHandle) #if DEBUG_HEAP_INTEGRITY , mSignature(kChunkSignature) #endif @@ -46,13 +47,22 @@ nsHeapChunk::~nsHeapChunk() #pragma mark - //-------------------------------------------------------------------- -nsMemAllocator::nsMemAllocator(THz inHeapZone) -: mHeapZone(inHeapZone) -, mFirstChunk(nil) +nsMemAllocator::nsMemAllocator() +: mFirstChunk(nil) , mLastChunk(nil) #if DEBUG_HEAP_INTEGRITY , mSignature(kMemAllocatorSignature) #endif +#if STATS_MAC_MEMORY +, mCurBlockCount(0) +, mMaxBlockCount(0) +, mCurBlockSpaceUsed(0) +, mMaxBlockSpaceUsed(0) +, mCurHeapSpaceUsed(0) +, mMaxHeapSpaceUsed(0) +, mCurSubheapCount(0) +, mMaxSubheapCount(0) +#endif //-------------------------------------------------------------------- { } @@ -109,6 +119,10 @@ void nsMemAllocator::AddToChunkList(nsHeapChunk *inNewChunk) mCurSubheapCount ++; if (mCurSubheapCount > mMaxSubheapCount) mMaxSubheapCount = mCurSubheapCount; + + mCurHeapSpaceUsed += inNewChunk->GetChunkSize(); + if (mCurHeapSpaceUsed > mMaxHeapSpaceUsed) + mMaxHeapSpaceUsed = mCurHeapSpaceUsed; #endif } @@ -146,67 +160,13 @@ void nsMemAllocator::RemoveFromChunkList(nsHeapChunk *inChunk) #if STATS_MAC_MEMORY mCurSubheapCount --; + + mCurHeapSpaceUsed -= inChunk->GetChunkSize(); #endif } -// amount of free space to maintain in the heap. This is used by -// plugins, GWorlds and other things. -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, - Handle *outTempMemHandle) -// This is the routine that does the actual memory allocation. -// Possible results: -// 1. Allocate pointer in heap. Return ptr, *outTempMemHandle==nil. -// 2. Allocate handle in temp mem. Return *handle, and put handle in *outTempMemHandle -// 3. Fail to allocate. Return nil, *outTempMemHandle==nil. -// -// outActualSize may be larger than preferredSize because we -// want to avoid heap fragmentation by keeping all blocks multiples -// of one smallest block size. outActualSize will not be smaller -// than preferredSize -//-------------------------------------------------------------------- -{ - *outTempMemHandle = nil; - - // calculate an ideal chunk size by rounding up - 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; - - // 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; - - // that failed, so try temp mem now - OSErr err; - Handle tempMemHandle = ::TempNewHandle(preferredSize, &err); - if (tempMemHandle != nil) - { - HLock(tempMemHandle); // may thee remain locked for all time - *outTempMemHandle = tempMemHandle; - return *tempMemHandle; - } - - return nil; // failure -} - +#pragma mark - #if STATS_MAC_MEMORY @@ -246,4 +206,31 @@ void nsMemAllocator::AccountForFreedBlock(size_t logicalSize) mCurBlockSpaceUsed -= logicalSize; } + +//-------------------------------------------------------------------- +void nsMemAllocator::DumpMemoryStats(PRFileDesc *outFile) +//-------------------------------------------------------------------- +{ + char outString[ 1024 ]; + + WriteString ( outFile, "\n\n--------------------------------------------------------------------------------\n" ); + WriteString(outFile, "Stats for heap\n"); + WriteString ( outFile, "--------------------------------------------------------------------------------\n" ); + WriteString ( outFile, " Current Max\n" ); + WriteString ( outFile, " ---------- -------\n" ); + sprintf( outString, "Num chunks: %10d %10d\n", mCurSubheapCount, mMaxSubheapCount); + WriteString ( outFile, outString ); + sprintf( outString, "Chunk total: %10d %10d\n", mCurHeapSpaceUsed, mMaxHeapSpaceUsed); + WriteString ( outFile, outString ); + sprintf( outString, "Block space: %10d %10d\n", mCurBlockSpaceUsed, mMaxBlockSpaceUsed ); + WriteString ( outFile, outString ); + sprintf( outString, "Blocks used: %10d %10d\n", mCurBlockCount, mMaxBlockCount ); + WriteString ( outFile, outString ); + WriteString ( outFile, " -------\n" ); + sprintf( outString, "%s of allocated space used: %10.2f\n", "%", 100.0 * mMaxBlockSpaceUsed / mMaxHeapSpaceUsed ); + WriteString ( outFile, outString ); + + WriteString ( outFile, "\n\n"); +} + #endif diff --git a/mozilla/lib/mac/MacMemoryAllocator/src/nsMemAllocator.h b/mozilla/lib/mac/MacMemoryAllocator/src/nsMemAllocator.h index 256305793dd..c8b783c070b 100644 --- a/mozilla/lib/mac/MacMemoryAllocator/src/nsMemAllocator.h +++ b/mozilla/lib/mac/MacMemoryAllocator/src/nsMemAllocator.h @@ -18,6 +18,10 @@ #include +#if STATS_MAC_MEMORY +#include "prio.h" +#endif + class nsMemAllocator; class nsHeapChunk; @@ -86,7 +90,7 @@ class nsHeapChunk { public: - nsHeapChunk(nsMemAllocator *inOwningAllocator, Size heapSize, Handle tempMemHandle); + nsHeapChunk(nsMemAllocator *inOwningAllocator, Size heapSize); ~nsHeapChunk(); nsHeapChunk* GetNextChunk() const { return mNextChunk; } @@ -99,8 +103,8 @@ class nsHeapChunk Boolean IsEmpty() const { return mUsedBlocks == 0; } - Handle GetMemHandle() { return mTempMemHandle; } - + UInt32 GetChunkSize() { return mHeapSize; } + #if DEBUG_HEAP_INTEGRITY Boolean IsGoodChunk() { return mSignature == kChunkSignature; } #endif @@ -117,9 +121,6 @@ class nsHeapChunk nsHeapChunk *mNextChunk; UInt32 mUsedBlocks; UInt32 mHeapSize; - - private: - Handle mTempMemHandle; // if nil, this chunk is a pointer in the heap }; @@ -130,7 +131,7 @@ class nsMemAllocator { public: - nsMemAllocator(THz inHeapZone); + nsMemAllocator(); virtual ~nsMemAllocator() = 0; static size_t GetBlockSize(void *thisBlock); @@ -155,13 +156,7 @@ class nsMemAllocator #endif protected: - - static const Size kFreeHeapSpace; - static const Size kChunkSizeMultiple; - static const Size kMacMemoryPtrOvehead; - - Ptr DoMacMemoryAllocation(Size preferredSize, Size &outActualSize, Handle *outTempMemHandle); - + void AddToChunkList(nsHeapChunk *inNewChunk); void RemoveFromChunkList(nsHeapChunk *inChunk); @@ -178,8 +173,6 @@ class nsMemAllocator 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 @@ -189,6 +182,8 @@ class nsMemAllocator void AccountForFreedBlock(size_t logicalSize); void AccountForResizedBlock(size_t oldLogicalSize, size_t newLogicalSize); + void DumpMemoryStats(PRFileDesc *statsFile); + private: UInt32 mCurBlockCount; // number of malloc blocks allocated now diff --git a/mozilla/lib/mac/MacMemoryAllocator/src/nsSmallHeapAllocator.cp b/mozilla/lib/mac/MacMemoryAllocator/src/nsSmallHeapAllocator.cp index a31aa9eb457..3e277832147 100644 --- a/mozilla/lib/mac/MacMemoryAllocator/src/nsSmallHeapAllocator.cp +++ b/mozilla/lib/mac/MacMemoryAllocator/src/nsSmallHeapAllocator.cp @@ -20,17 +20,18 @@ #include #include "nsMemAllocator.h" +#include "nsAllocatorManager.h" #include "nsSmallHeapAllocator.h" const UInt32 SmallHeapBlock::kBlockOverhead = sizeof(SmallHeapBlock) + MEMORY_BLOCK_TAILER_SIZE; //-------------------------------------------------------------------- -nsSmallHeapAllocator::nsSmallHeapAllocator(THz heapZone) -: nsMemAllocator(heapZone) +nsSmallHeapAllocator::nsSmallHeapAllocator() +: nsMemAllocator() //-------------------------------------------------------------------- { - mBaseChunkSize = mTempChunkSize = (nsMemAllocator::kChunkSizeMultiple); + mBaseChunkSize = mTempChunkSize = (nsAllocatorManager::kChunkSizeMultiple); } //-------------------------------------------------------------------- @@ -146,12 +147,10 @@ nsHeapChunk *nsSmallHeapAllocator::AllocateChunk(size_t blockSize) minChunkSize = mBaseChunkSize; Size actualChunkSize; - Handle tempMemHandle; - Ptr chunkMemory = DoMacMemoryAllocation(minChunkSize, actualChunkSize, &tempMemHandle); + Ptr chunkMemory = nsAllocatorManager::GetAllocatorManager()->AllocateSubheap(mBaseChunkSize, actualChunkSize); // use placement new to initialize the chunk in the memory block - nsHeapChunk *newHeapChunk = new (chunkMemory) nsSmallHeapChunk(this, actualChunkSize, tempMemHandle); - + nsHeapChunk *newHeapChunk = new (chunkMemory) nsSmallHeapChunk(this, actualChunkSize); if (newHeapChunk) AddToChunkList(newHeapChunk); @@ -168,11 +167,7 @@ void nsSmallHeapAllocator::FreeChunk(nsHeapChunk *chunkToFree) nsSmallHeapChunk *thisChunk = (nsSmallHeapChunk *)chunkToFree; thisChunk->~nsSmallHeapChunk(); - Handle tempMemHandle = thisChunk->GetMemHandle(); - if (tempMemHandle) - DisposeHandle(tempMemHandle); - else - DisposePtr((Ptr)thisChunk); + nsAllocatorManager::GetAllocatorManager()->FreeSubheap((Ptr)thisChunk); } @@ -181,9 +176,8 @@ void nsSmallHeapAllocator::FreeChunk(nsHeapChunk *chunkToFree) //-------------------------------------------------------------------- nsSmallHeapChunk::nsSmallHeapChunk( nsMemAllocator *inOwningAllocator, - Size heapSize, - Handle tempMemHandle) : - nsHeapChunk(inOwningAllocator, heapSize, tempMemHandle), + Size heapSize) : + nsHeapChunk(inOwningAllocator, heapSize), mOverflow(nil) //-------------------------------------------------------------------- { @@ -298,8 +292,6 @@ void *nsSmallHeapChunk::GetSpaceForBlock(size_t blockSize) // room for another allocation out of the // block, then split the block up. - //blockToCarve->SetUnusedBlockSize(roundedBlockSize); - //leftovers = blockToCarveSize - blockToCarve->GetBlockHeapUsage(); SInt32 leftovers = blockToCarveSize - roundedBlockSize - SmallHeapBlock::kBlockOverhead; if (leftovers >= kDefaultSmallHeadMinSize) diff --git a/mozilla/lib/mac/MacMemoryAllocator/src/nsSmallHeapAllocator.h b/mozilla/lib/mac/MacMemoryAllocator/src/nsSmallHeapAllocator.h index afc3d794f93..ca9c60b28b4 100644 --- a/mozilla/lib/mac/MacMemoryAllocator/src/nsSmallHeapAllocator.h +++ b/mozilla/lib/mac/MacMemoryAllocator/src/nsSmallHeapAllocator.h @@ -130,7 +130,7 @@ class nsSmallHeapAllocator : public nsMemAllocator public: - nsSmallHeapAllocator(THz heapZone); + nsSmallHeapAllocator(); ~nsSmallHeapAllocator(); virtual void * AllocatorMakeBlock(size_t blockSize); @@ -153,9 +153,7 @@ class nsSmallHeapChunk : public nsHeapChunk { public: - nsSmallHeapChunk( nsMemAllocator *inOwningAllocator, - Size heapSize, - Handle tempMemHandle); + nsSmallHeapChunk(nsMemAllocator *inOwningAllocator, Size heapSize); ~nsSmallHeapChunk(); void * GetSpaceForBlock(UInt32 roundedBlockSize);