mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-02 03:49:37 +00:00
Allocators now use shared heap zones, for better temp mem use. Other minor changes.
This commit is contained in:
parent
5e512d94a3
commit
8de3b16eb4
@ -16,6 +16,7 @@
|
|||||||
* Reserved. */
|
* Reserved. */
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <new.h> // for placement new
|
#include <new.h> // for placement new
|
||||||
|
|
||||||
@ -25,6 +26,10 @@
|
|||||||
#include <Processes.h>
|
#include <Processes.h>
|
||||||
#include <CodeFragments.h>
|
#include <CodeFragments.h>
|
||||||
|
|
||||||
|
#if __profile__
|
||||||
|
#include <Profiler.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "nsMemAllocator.h"
|
#include "nsMemAllocator.h"
|
||||||
|
|
||||||
#include "nsFixedSizeAllocator.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;
|
const SInt32 nsAllocatorManager::kNumMasterPointerBlocks = 30;
|
||||||
@ -103,10 +166,12 @@ const SInt32 nsAllocatorManager::kHeapZoneHeapPercentage = 60;
|
|||||||
nsAllocatorManager* nsAllocatorManager::sAllocatorManager = nil;
|
nsAllocatorManager* nsAllocatorManager::sAllocatorManager = nil;
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
nsAllocatorManager::nsAllocatorManager() :
|
nsAllocatorManager::nsAllocatorManager()
|
||||||
mFixedSizeAllocators(nil),
|
: mFixedSizeAllocators(nil)
|
||||||
mSmallBlockAllocators(nil),
|
, mSmallBlockAllocators(nil)
|
||||||
mLargeAllocator(nil)
|
, mLargeAllocator(nil)
|
||||||
|
, mFirstHeapZone(nil)
|
||||||
|
, mLastHeapZone(nil)
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
{
|
{
|
||||||
mMinSmallBlockSize = 44; // some magic numbers for now
|
mMinSmallBlockSize = 44; // some magic numbers for now
|
||||||
@ -129,6 +194,7 @@ nsAllocatorManager::nsAllocatorManager() :
|
|||||||
mFixedSizeAllocators[i] = (nsMemAllocator *)NewPtr(sizeof(nsFixedSizeAllocator));
|
mFixedSizeAllocators[i] = (nsMemAllocator *)NewPtr(sizeof(nsFixedSizeAllocator));
|
||||||
if (mFixedSizeAllocators[i] == nil)
|
if (mFixedSizeAllocators[i] == nil)
|
||||||
throw((OSErr)memFullErr);
|
throw((OSErr)memFullErr);
|
||||||
|
new (mFixedSizeAllocators[i]) nsFixedSizeAllocator((i + 1) * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (SInt32 i = 0; i < mNumSmallBlockAllocators; i ++)
|
for (SInt32 i = 0; i < mNumSmallBlockAllocators; i ++)
|
||||||
@ -136,11 +202,13 @@ nsAllocatorManager::nsAllocatorManager() :
|
|||||||
mSmallBlockAllocators[i] = (nsMemAllocator *)NewPtr(sizeof(nsSmallHeapAllocator));
|
mSmallBlockAllocators[i] = (nsMemAllocator *)NewPtr(sizeof(nsSmallHeapAllocator));
|
||||||
if (mSmallBlockAllocators[i] == nil)
|
if (mSmallBlockAllocators[i] == nil)
|
||||||
throw((OSErr)memFullErr);
|
throw((OSErr)memFullErr);
|
||||||
|
new (mSmallBlockAllocators[i]) nsSmallHeapAllocator();
|
||||||
}
|
}
|
||||||
|
|
||||||
mLargeAllocator = (nsMemAllocator *)NewPtr(sizeof(nsLargeHeapAllocator));
|
mLargeAllocator = (nsMemAllocator *)NewPtr(sizeof(nsLargeHeapAllocator));
|
||||||
if (mLargeAllocator == nil)
|
if (mLargeAllocator == nil)
|
||||||
throw((OSErr)memFullErr);
|
throw((OSErr)memFullErr);
|
||||||
|
new (mLargeAllocator) nsLargeHeapAllocator();
|
||||||
|
|
||||||
// make the heap zone for our subheaps
|
// make the heap zone for our subheaps
|
||||||
UInt32 heapZoneSize;
|
UInt32 heapZoneSize;
|
||||||
@ -148,30 +216,10 @@ nsAllocatorManager::nsAllocatorManager() :
|
|||||||
heapZoneSize = ( kHeapZoneHeapPercentage * ::FreeMem() ) / 100;
|
heapZoneSize = ( kHeapZoneHeapPercentage * ::FreeMem() ) / 100;
|
||||||
heapZoneSize = ( ( heapZoneSize + 3 ) & ~3 ); // round up to a multiple of 4 bytes
|
heapZoneSize = ( ( heapZoneSize + 3 ) & ~3 ); // round up to a multiple of 4 bytes
|
||||||
|
|
||||||
Ptr heapZone = ::NewPtr(heapZoneSize);
|
nsHeapZoneHeader *firstZone = MakeNewHeapZone(heapZoneSize, heapZoneSize);
|
||||||
if (heapZone == nil)
|
if (!firstZone)
|
||||||
throw((OSErr)memFullErr);
|
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;
|
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,
|
/* 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;
|
if (sAllocatorManager) return sAllocatorManager;
|
||||||
@ -269,6 +442,57 @@ nsMemAllocator* nsAllocatorManager::GetAllocatorForBlockSize(size_t blockSize)
|
|||||||
return sAllocatorManager;
|
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 -
|
#pragma mark -
|
||||||
|
|
||||||
|
|
||||||
@ -348,13 +572,11 @@ void *calloc(size_t nele, size_t elesize)
|
|||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
__MemInitialize
|
__MemInitialize
|
||||||
|
|
||||||
Note the people can call malloc() or new() before we come here,
|
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)
|
pascal OSErr __MemInitialize(const CFragInitBlock *theInitBlock)
|
||||||
@ -389,9 +611,11 @@ pascal void __MemTerminate(void)
|
|||||||
ProfilerTerm();
|
ProfilerTerm();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if STATS_MAC_MEMORY
|
||||||
|
nsAllocatorManager::GetAllocatorManager()->DumpMemoryStats();
|
||||||
|
#endif
|
||||||
|
|
||||||
__terminate();
|
__terminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,7 +18,9 @@
|
|||||||
|
|
||||||
#include <MacTypes.h>
|
#include <MacTypes.h>
|
||||||
|
|
||||||
|
#if STATS_MAC_MEMORY
|
||||||
|
#include "prio.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -30,6 +32,123 @@ void* realloc(void* block, size_t newSize);
|
|||||||
void *calloc(size_t nele, size_t elesize);
|
void *calloc(size_t nele, size_t elesize);
|
||||||
|
|
||||||
|
|
||||||
|
#if STATS_MAC_MEMORY
|
||||||
|
void WriteString(PRFileDesc *file, const char * string);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#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;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
@ -20,17 +20,19 @@
|
|||||||
#include <MacMemory.h>
|
#include <MacMemory.h>
|
||||||
|
|
||||||
#include "nsMemAllocator.h"
|
#include "nsMemAllocator.h"
|
||||||
|
#include "nsAllocatorManager.h"
|
||||||
#include "nsFixedSizeAllocator.h"
|
#include "nsFixedSizeAllocator.h"
|
||||||
|
|
||||||
const UInt32 FixedMemoryBlock::kFixedSizeBlockOverhead = sizeof(FixedMemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE;
|
const UInt32 FixedMemoryBlock::kFixedSizeBlockOverhead = sizeof(FixedMemoryBlockHeader) + MEMORY_BLOCK_TAILER_SIZE;
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
nsFixedSizeAllocator::nsFixedSizeAllocator(THz heapZone, size_t blockSize)
|
nsFixedSizeAllocator::nsFixedSizeAllocator(size_t blockSize)
|
||||||
: nsMemAllocator(heapZone)
|
: nsMemAllocator()
|
||||||
, mBlockSize(blockSize)
|
, 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;
|
nsFixedSizeHeapChunk* chunk = (nsFixedSizeHeapChunk *)mFirstChunk;
|
||||||
|
|
||||||
|
if (mChunkWithSpace && mChunkWithSpace->GetFreeList())
|
||||||
|
return mChunkWithSpace;
|
||||||
|
|
||||||
// Try to find an existing chunk with a free block.
|
// Try to find an existing chunk with a free block.
|
||||||
while (chunk != nil)
|
while (chunk != nil)
|
||||||
{
|
{
|
||||||
@ -69,10 +74,12 @@ void *nsFixedSizeAllocator::AllocatorMakeBlock(size_t blockSize)
|
|||||||
{
|
{
|
||||||
chunk = (nsFixedSizeHeapChunk *)AllocateChunk(blockSize);
|
chunk = (nsFixedSizeHeapChunk *)AllocateChunk(blockSize);
|
||||||
if (!chunk) return nil;
|
if (!chunk) return nil;
|
||||||
|
|
||||||
|
mChunkWithSpace = chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
FixedMemoryBlock* blockHeader = chunk->FetchFirstFree();
|
FixedMemoryBlock* blockHeader = chunk->FetchFirstFree();
|
||||||
|
|
||||||
#if DEBUG_HEAP_INTEGRITY
|
#if DEBUG_HEAP_INTEGRITY
|
||||||
blockHeader->SetHeaderTag(kUsedBlockHeaderTag);
|
blockHeader->SetHeaderTag(kUsedBlockHeaderTag);
|
||||||
blockHeader->SetTrailerTag(GetAllocatorBlockSize(), kUsedBlockTrailerTag);
|
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 this chunk is completely empty and it's not the first chunk then free it
|
||||||
if ( chunk->IsEmpty() && chunk != mFirstChunk )
|
if ( chunk->IsEmpty() && chunk != mFirstChunk )
|
||||||
{
|
{
|
||||||
|
if (chunk == mChunkWithSpace)
|
||||||
|
mChunkWithSpace = nil;
|
||||||
FreeChunk(chunk);
|
FreeChunk(chunk);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mChunkWithSpace = chunk; // we know is has some space now
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -170,13 +183,13 @@ nsHeapChunk *nsFixedSizeAllocator::AllocateChunk(size_t requestedBlockSize)
|
|||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
{
|
{
|
||||||
Size actualChunkSize;
|
Size actualChunkSize;
|
||||||
Handle tempMemHandle;
|
Ptr chunkMemory = nsAllocatorManager::GetAllocatorManager()->AllocateSubheap(mBaseChunkSize, actualChunkSize);
|
||||||
Ptr chunkMemory = DoMacMemoryAllocation(mBaseChunkSize, actualChunkSize, &tempMemHandle);
|
|
||||||
|
|
||||||
// use placement new to initialize the chunk in the memory block
|
// 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)
|
if (newHeapChunk)
|
||||||
AddToChunkList(newHeapChunk);
|
AddToChunkList(newHeapChunk);
|
||||||
|
|
||||||
return newHeapChunk;
|
return newHeapChunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,11 +203,7 @@ void nsFixedSizeAllocator::FreeChunk(nsHeapChunk *chunkToFree)
|
|||||||
nsFixedSizeHeapChunk *thisChunk = (nsFixedSizeHeapChunk *)chunkToFree;
|
nsFixedSizeHeapChunk *thisChunk = (nsFixedSizeHeapChunk *)chunkToFree;
|
||||||
thisChunk->~nsFixedSizeHeapChunk();
|
thisChunk->~nsFixedSizeHeapChunk();
|
||||||
|
|
||||||
Handle tempMemHandle = thisChunk->GetMemHandle();
|
nsAllocatorManager::GetAllocatorManager()->FreeSubheap((Ptr)thisChunk);
|
||||||
if (tempMemHandle)
|
|
||||||
DisposeHandle(tempMemHandle);
|
|
||||||
else
|
|
||||||
DisposePtr((Ptr)thisChunk);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -203,9 +212,8 @@ void nsFixedSizeAllocator::FreeChunk(nsHeapChunk *chunkToFree)
|
|||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
nsFixedSizeHeapChunk::nsFixedSizeHeapChunk(
|
nsFixedSizeHeapChunk::nsFixedSizeHeapChunk(
|
||||||
nsMemAllocator *inOwningAllocator,
|
nsMemAllocator *inOwningAllocator,
|
||||||
Size heapSize,
|
Size heapSize) :
|
||||||
Handle tempMemHandle) :
|
nsHeapChunk(inOwningAllocator, heapSize)
|
||||||
nsHeapChunk(inOwningAllocator, heapSize, tempMemHandle)
|
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
{
|
{
|
||||||
nsFixedSizeAllocator *allocator = (nsFixedSizeAllocator *)mOwningAllocator;
|
nsFixedSizeAllocator *allocator = (nsFixedSizeAllocator *)mOwningAllocator;
|
||||||
|
@ -106,7 +106,7 @@ class nsFixedSizeAllocator : public nsMemAllocator
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
nsFixedSizeAllocator(THz heapZone, size_t blockSize);
|
nsFixedSizeAllocator(size_t blockSize);
|
||||||
~nsFixedSizeAllocator();
|
~nsFixedSizeAllocator();
|
||||||
|
|
||||||
virtual void * AllocatorMakeBlock(size_t blockSize);
|
virtual void * AllocatorMakeBlock(size_t blockSize);
|
||||||
@ -130,7 +130,9 @@ class nsFixedSizeAllocator : public nsMemAllocator
|
|||||||
UInt32 mBlockSize; // upper bound for blocks allocated in this heap
|
UInt32 mBlockSize; // upper bound for blocks allocated in this heap
|
||||||
// does not include block overhead
|
// does not include block overhead
|
||||||
|
|
||||||
|
nsFixedSizeHeapChunk *mChunkWithSpace; // cheap optimization
|
||||||
|
|
||||||
|
|
||||||
#if STATS_MAC_MEMORY
|
#if STATS_MAC_MEMORY
|
||||||
UInt32 mChunksAllocated;
|
UInt32 mChunksAllocated;
|
||||||
UInt32 mMaxChunksAllocated;
|
UInt32 mMaxChunksAllocated;
|
||||||
@ -156,20 +158,20 @@ class nsFixedSizeHeapChunk : public nsHeapChunk
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
nsFixedSizeHeapChunk(nsMemAllocator *inOwningAllocator, Size heapSize, Handle tempMemHandle);
|
nsFixedSizeHeapChunk(nsMemAllocator *inOwningAllocator, Size heapSize);
|
||||||
~nsFixedSizeHeapChunk();
|
~nsFixedSizeHeapChunk();
|
||||||
|
|
||||||
FixedMemoryBlock* GetFreeList() const { return mFreeList; }
|
FixedMemoryBlock* GetFreeList() const { return mFreeList; }
|
||||||
void SetFreeList(FixedMemoryBlock *nextFree) { mFreeList = nextFree; }
|
void SetFreeList(FixedMemoryBlock *nextFree) { mFreeList = nextFree; }
|
||||||
|
|
||||||
FixedMemoryBlock* FetchFirstFree();
|
FixedMemoryBlock* FetchFirstFree();
|
||||||
void ReturnToFreeList(FixedMemoryBlock *freeBlock);
|
void ReturnToFreeList(FixedMemoryBlock *freeBlock);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
#if STATS_MAC_MEMORY
|
#if STATS_MAC_MEMORY
|
||||||
UInt32 chunkSize;
|
UInt32 chunkSize;
|
||||||
UInt32 numBlocks;
|
UInt32 numBlocks;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FixedMemoryBlock *mFreeList;
|
FixedMemoryBlock *mFreeList;
|
||||||
|
@ -19,14 +19,15 @@
|
|||||||
#include <MacMemory.h>
|
#include <MacMemory.h>
|
||||||
|
|
||||||
#include "nsMemAllocator.h"
|
#include "nsMemAllocator.h"
|
||||||
|
#include "nsAllocatorManager.h"
|
||||||
#include "nsLargeHeapAllocator.h"
|
#include "nsLargeHeapAllocator.h"
|
||||||
|
|
||||||
|
|
||||||
const UInt32 LargeBlockHeader::kLargeBlockOverhead = sizeof(LargeBlockHeader) + MEMORY_BLOCK_TAILER_SIZE;
|
const UInt32 LargeBlockHeader::kLargeBlockOverhead = sizeof(LargeBlockHeader) + MEMORY_BLOCK_TAILER_SIZE;
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
nsLargeHeapAllocator::nsLargeHeapAllocator(THz heapZone)
|
nsLargeHeapAllocator::nsLargeHeapAllocator()
|
||||||
: nsMemAllocator(heapZone)
|
: nsMemAllocator()
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
{
|
{
|
||||||
mBaseChunkSize = mTempChunkSize = (64 * 1024);
|
mBaseChunkSize = mTempChunkSize = (64 * 1024);
|
||||||
@ -160,17 +161,16 @@ nsHeapChunk *nsLargeHeapAllocator::AllocateChunk(size_t requestedBlockSize)
|
|||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
{
|
{
|
||||||
Size chunkSize = mBaseChunkSize, actualChunkSize;
|
Size chunkSize = mBaseChunkSize, actualChunkSize;
|
||||||
Handle tempMemHandle;
|
|
||||||
|
|
||||||
size_t paddedBlockSize = (( requestedBlockSize + 3 ) & ~3) + 3 * LargeBlockHeader::kLargeBlockOverhead + sizeof(nsLargeHeapChunk);
|
size_t paddedBlockSize = (( requestedBlockSize + 3 ) & ~3) + 3 * LargeBlockHeader::kLargeBlockOverhead + sizeof(nsLargeHeapChunk);
|
||||||
|
|
||||||
if (paddedBlockSize > chunkSize)
|
if (paddedBlockSize > chunkSize)
|
||||||
chunkSize = paddedBlockSize;
|
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
|
// 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)
|
if (newHeapChunk)
|
||||||
AddToChunkList(newHeapChunk);
|
AddToChunkList(newHeapChunk);
|
||||||
@ -188,11 +188,7 @@ void nsLargeHeapAllocator::FreeChunk(nsHeapChunk *chunkToFree)
|
|||||||
nsLargeHeapChunk *thisChunk = (nsLargeHeapChunk *)chunkToFree;
|
nsLargeHeapChunk *thisChunk = (nsLargeHeapChunk *)chunkToFree;
|
||||||
thisChunk->~nsLargeHeapChunk();
|
thisChunk->~nsLargeHeapChunk();
|
||||||
|
|
||||||
Handle tempMemHandle = thisChunk->GetMemHandle();
|
nsAllocatorManager::GetAllocatorManager()->FreeSubheap((Ptr)thisChunk);
|
||||||
if (tempMemHandle)
|
|
||||||
DisposeHandle(tempMemHandle);
|
|
||||||
else
|
|
||||||
DisposePtr((Ptr)thisChunk);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -201,9 +197,8 @@ void nsLargeHeapAllocator::FreeChunk(nsHeapChunk *chunkToFree)
|
|||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
nsLargeHeapChunk::nsLargeHeapChunk(
|
nsLargeHeapChunk::nsLargeHeapChunk(
|
||||||
nsMemAllocator *inOwningAllocator,
|
nsMemAllocator *inOwningAllocator,
|
||||||
Size heapSize,
|
Size heapSize) :
|
||||||
Handle tempMemHandle) :
|
nsHeapChunk(inOwningAllocator, heapSize)
|
||||||
nsHeapChunk(inOwningAllocator, heapSize, tempMemHandle)
|
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
{
|
{
|
||||||
heapSize -= sizeof(nsLargeHeapChunk); // subtract heap overhead
|
heapSize -= sizeof(nsLargeHeapChunk); // subtract heap overhead
|
||||||
|
@ -108,7 +108,7 @@ class nsLargeHeapAllocator : public nsMemAllocator
|
|||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
nsLargeHeapAllocator(THz heapZone);
|
nsLargeHeapAllocator();
|
||||||
~nsLargeHeapAllocator();
|
~nsLargeHeapAllocator();
|
||||||
|
|
||||||
|
|
||||||
@ -136,8 +136,7 @@ class nsLargeHeapChunk : public nsHeapChunk
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
nsLargeHeapChunk( nsMemAllocator *inOwningAllocator,
|
nsLargeHeapChunk( nsMemAllocator *inOwningAllocator,
|
||||||
Size heapSize,
|
Size heapSize);
|
||||||
Handle tempMemHandle);
|
|
||||||
~nsLargeHeapChunk();
|
~nsLargeHeapChunk();
|
||||||
|
|
||||||
LargeBlockHeader* GetHeadBlock() { return mHead; }
|
LargeBlockHeader* GetHeadBlock() { return mHead; }
|
||||||
|
@ -15,18 +15,19 @@
|
|||||||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||||
* Reserved. */
|
* Reserved. */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include <MacMemory.h>
|
#include <MacMemory.h>
|
||||||
|
|
||||||
|
|
||||||
#include "nsMemAllocator.h"
|
#include "nsMemAllocator.h"
|
||||||
|
#include "nsAllocatorManager.h"
|
||||||
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
nsHeapChunk::nsHeapChunk(nsMemAllocator *inOwningAllocator, Size heapSize, Handle tempMemHandle)
|
nsHeapChunk::nsHeapChunk(nsMemAllocator *inOwningAllocator, Size heapSize)
|
||||||
: mOwningAllocator(inOwningAllocator)
|
: mOwningAllocator(inOwningAllocator)
|
||||||
, mNextChunk(nil)
|
, mNextChunk(nil)
|
||||||
, mHeapSize(heapSize)
|
, mHeapSize(heapSize)
|
||||||
, mUsedBlocks(0)
|
, mUsedBlocks(0)
|
||||||
, mTempMemHandle(tempMemHandle)
|
|
||||||
#if DEBUG_HEAP_INTEGRITY
|
#if DEBUG_HEAP_INTEGRITY
|
||||||
, mSignature(kChunkSignature)
|
, mSignature(kChunkSignature)
|
||||||
#endif
|
#endif
|
||||||
@ -46,13 +47,22 @@ nsHeapChunk::~nsHeapChunk()
|
|||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
nsMemAllocator::nsMemAllocator(THz inHeapZone)
|
nsMemAllocator::nsMemAllocator()
|
||||||
: mHeapZone(inHeapZone)
|
: mFirstChunk(nil)
|
||||||
, mFirstChunk(nil)
|
|
||||||
, mLastChunk(nil)
|
, mLastChunk(nil)
|
||||||
#if DEBUG_HEAP_INTEGRITY
|
#if DEBUG_HEAP_INTEGRITY
|
||||||
, mSignature(kMemAllocatorSignature)
|
, mSignature(kMemAllocatorSignature)
|
||||||
#endif
|
#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 ++;
|
mCurSubheapCount ++;
|
||||||
if (mCurSubheapCount > mMaxSubheapCount)
|
if (mCurSubheapCount > mMaxSubheapCount)
|
||||||
mMaxSubheapCount = mCurSubheapCount;
|
mMaxSubheapCount = mCurSubheapCount;
|
||||||
|
|
||||||
|
mCurHeapSpaceUsed += inNewChunk->GetChunkSize();
|
||||||
|
if (mCurHeapSpaceUsed > mMaxHeapSpaceUsed)
|
||||||
|
mMaxHeapSpaceUsed = mCurHeapSpaceUsed;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,67 +160,13 @@ void nsMemAllocator::RemoveFromChunkList(nsHeapChunk *inChunk)
|
|||||||
|
|
||||||
#if STATS_MAC_MEMORY
|
#if STATS_MAC_MEMORY
|
||||||
mCurSubheapCount --;
|
mCurSubheapCount --;
|
||||||
|
|
||||||
|
mCurHeapSpaceUsed -= inChunk->GetChunkSize();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// amount of free space to maintain in the heap. This is used by
|
#pragma mark -
|
||||||
// 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
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if STATS_MAC_MEMORY
|
#if STATS_MAC_MEMORY
|
||||||
|
|
||||||
@ -246,4 +206,31 @@ void nsMemAllocator::AccountForFreedBlock(size_t logicalSize)
|
|||||||
mCurBlockSpaceUsed -= 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
|
#endif
|
||||||
|
@ -18,6 +18,10 @@
|
|||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#if STATS_MAC_MEMORY
|
||||||
|
#include "prio.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
class nsMemAllocator;
|
class nsMemAllocator;
|
||||||
class nsHeapChunk;
|
class nsHeapChunk;
|
||||||
|
|
||||||
@ -86,7 +90,7 @@ class nsHeapChunk
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
nsHeapChunk(nsMemAllocator *inOwningAllocator, Size heapSize, Handle tempMemHandle);
|
nsHeapChunk(nsMemAllocator *inOwningAllocator, Size heapSize);
|
||||||
~nsHeapChunk();
|
~nsHeapChunk();
|
||||||
|
|
||||||
nsHeapChunk* GetNextChunk() const { return mNextChunk; }
|
nsHeapChunk* GetNextChunk() const { return mNextChunk; }
|
||||||
@ -99,8 +103,8 @@ class nsHeapChunk
|
|||||||
|
|
||||||
Boolean IsEmpty() const { return mUsedBlocks == 0; }
|
Boolean IsEmpty() const { return mUsedBlocks == 0; }
|
||||||
|
|
||||||
Handle GetMemHandle() { return mTempMemHandle; }
|
UInt32 GetChunkSize() { return mHeapSize; }
|
||||||
|
|
||||||
#if DEBUG_HEAP_INTEGRITY
|
#if DEBUG_HEAP_INTEGRITY
|
||||||
Boolean IsGoodChunk() { return mSignature == kChunkSignature; }
|
Boolean IsGoodChunk() { return mSignature == kChunkSignature; }
|
||||||
#endif
|
#endif
|
||||||
@ -117,9 +121,6 @@ class nsHeapChunk
|
|||||||
nsHeapChunk *mNextChunk;
|
nsHeapChunk *mNextChunk;
|
||||||
UInt32 mUsedBlocks;
|
UInt32 mUsedBlocks;
|
||||||
UInt32 mHeapSize;
|
UInt32 mHeapSize;
|
||||||
|
|
||||||
private:
|
|
||||||
Handle mTempMemHandle; // if nil, this chunk is a pointer in the heap
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -130,7 +131,7 @@ class nsMemAllocator
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
nsMemAllocator(THz inHeapZone);
|
nsMemAllocator();
|
||||||
virtual ~nsMemAllocator() = 0;
|
virtual ~nsMemAllocator() = 0;
|
||||||
|
|
||||||
static size_t GetBlockSize(void *thisBlock);
|
static size_t GetBlockSize(void *thisBlock);
|
||||||
@ -155,13 +156,7 @@ class nsMemAllocator
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
protected:
|
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 AddToChunkList(nsHeapChunk *inNewChunk);
|
||||||
void RemoveFromChunkList(nsHeapChunk *inChunk);
|
void RemoveFromChunkList(nsHeapChunk *inChunk);
|
||||||
|
|
||||||
@ -178,8 +173,6 @@ class nsMemAllocator
|
|||||||
|
|
||||||
UInt32 mBaseChunkSize; // size of subheap allocated at startup
|
UInt32 mBaseChunkSize; // size of subheap allocated at startup
|
||||||
UInt32 mTempChunkSize; // size of additional subheaps
|
UInt32 mTempChunkSize; // size of additional subheaps
|
||||||
|
|
||||||
THz mHeapZone; // heap zone in which to allocate pointers
|
|
||||||
|
|
||||||
#if STATS_MAC_MEMORY
|
#if STATS_MAC_MEMORY
|
||||||
|
|
||||||
@ -189,6 +182,8 @@ class nsMemAllocator
|
|||||||
void AccountForFreedBlock(size_t logicalSize);
|
void AccountForFreedBlock(size_t logicalSize);
|
||||||
void AccountForResizedBlock(size_t oldLogicalSize, size_t newLogicalSize);
|
void AccountForResizedBlock(size_t oldLogicalSize, size_t newLogicalSize);
|
||||||
|
|
||||||
|
void DumpMemoryStats(PRFileDesc *statsFile);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
UInt32 mCurBlockCount; // number of malloc blocks allocated now
|
UInt32 mCurBlockCount; // number of malloc blocks allocated now
|
||||||
|
@ -20,17 +20,18 @@
|
|||||||
#include <MacMemory.h>
|
#include <MacMemory.h>
|
||||||
|
|
||||||
#include "nsMemAllocator.h"
|
#include "nsMemAllocator.h"
|
||||||
|
#include "nsAllocatorManager.h"
|
||||||
#include "nsSmallHeapAllocator.h"
|
#include "nsSmallHeapAllocator.h"
|
||||||
|
|
||||||
const UInt32 SmallHeapBlock::kBlockOverhead = sizeof(SmallHeapBlock) + MEMORY_BLOCK_TAILER_SIZE;
|
const UInt32 SmallHeapBlock::kBlockOverhead = sizeof(SmallHeapBlock) + MEMORY_BLOCK_TAILER_SIZE;
|
||||||
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
nsSmallHeapAllocator::nsSmallHeapAllocator(THz heapZone)
|
nsSmallHeapAllocator::nsSmallHeapAllocator()
|
||||||
: nsMemAllocator(heapZone)
|
: nsMemAllocator()
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
{
|
{
|
||||||
mBaseChunkSize = mTempChunkSize = (nsMemAllocator::kChunkSizeMultiple);
|
mBaseChunkSize = mTempChunkSize = (nsAllocatorManager::kChunkSizeMultiple);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
@ -146,12 +147,10 @@ nsHeapChunk *nsSmallHeapAllocator::AllocateChunk(size_t blockSize)
|
|||||||
minChunkSize = mBaseChunkSize;
|
minChunkSize = mBaseChunkSize;
|
||||||
|
|
||||||
Size actualChunkSize;
|
Size actualChunkSize;
|
||||||
Handle tempMemHandle;
|
Ptr chunkMemory = nsAllocatorManager::GetAllocatorManager()->AllocateSubheap(mBaseChunkSize, actualChunkSize);
|
||||||
Ptr chunkMemory = DoMacMemoryAllocation(minChunkSize, actualChunkSize, &tempMemHandle);
|
|
||||||
|
|
||||||
// use placement new to initialize the chunk in the memory block
|
// 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)
|
if (newHeapChunk)
|
||||||
AddToChunkList(newHeapChunk);
|
AddToChunkList(newHeapChunk);
|
||||||
|
|
||||||
@ -168,11 +167,7 @@ void nsSmallHeapAllocator::FreeChunk(nsHeapChunk *chunkToFree)
|
|||||||
nsSmallHeapChunk *thisChunk = (nsSmallHeapChunk *)chunkToFree;
|
nsSmallHeapChunk *thisChunk = (nsSmallHeapChunk *)chunkToFree;
|
||||||
thisChunk->~nsSmallHeapChunk();
|
thisChunk->~nsSmallHeapChunk();
|
||||||
|
|
||||||
Handle tempMemHandle = thisChunk->GetMemHandle();
|
nsAllocatorManager::GetAllocatorManager()->FreeSubheap((Ptr)thisChunk);
|
||||||
if (tempMemHandle)
|
|
||||||
DisposeHandle(tempMemHandle);
|
|
||||||
else
|
|
||||||
DisposePtr((Ptr)thisChunk);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -181,9 +176,8 @@ void nsSmallHeapAllocator::FreeChunk(nsHeapChunk *chunkToFree)
|
|||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
nsSmallHeapChunk::nsSmallHeapChunk(
|
nsSmallHeapChunk::nsSmallHeapChunk(
|
||||||
nsMemAllocator *inOwningAllocator,
|
nsMemAllocator *inOwningAllocator,
|
||||||
Size heapSize,
|
Size heapSize) :
|
||||||
Handle tempMemHandle) :
|
nsHeapChunk(inOwningAllocator, heapSize),
|
||||||
nsHeapChunk(inOwningAllocator, heapSize, tempMemHandle),
|
|
||||||
mOverflow(nil)
|
mOverflow(nil)
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
{
|
{
|
||||||
@ -298,8 +292,6 @@ void *nsSmallHeapChunk::GetSpaceForBlock(size_t blockSize)
|
|||||||
// room for another allocation out of the
|
// room for another allocation out of the
|
||||||
// block, then split the block up.
|
// block, then split the block up.
|
||||||
|
|
||||||
//blockToCarve->SetUnusedBlockSize(roundedBlockSize);
|
|
||||||
//leftovers = blockToCarveSize - blockToCarve->GetBlockHeapUsage();
|
|
||||||
SInt32 leftovers = blockToCarveSize - roundedBlockSize - SmallHeapBlock::kBlockOverhead;
|
SInt32 leftovers = blockToCarveSize - roundedBlockSize - SmallHeapBlock::kBlockOverhead;
|
||||||
|
|
||||||
if (leftovers >= kDefaultSmallHeadMinSize)
|
if (leftovers >= kDefaultSmallHeadMinSize)
|
||||||
|
@ -130,7 +130,7 @@ class nsSmallHeapAllocator : public nsMemAllocator
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
nsSmallHeapAllocator(THz heapZone);
|
nsSmallHeapAllocator();
|
||||||
~nsSmallHeapAllocator();
|
~nsSmallHeapAllocator();
|
||||||
|
|
||||||
virtual void * AllocatorMakeBlock(size_t blockSize);
|
virtual void * AllocatorMakeBlock(size_t blockSize);
|
||||||
@ -153,9 +153,7 @@ class nsSmallHeapChunk : public nsHeapChunk
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
nsSmallHeapChunk( nsMemAllocator *inOwningAllocator,
|
nsSmallHeapChunk(nsMemAllocator *inOwningAllocator, Size heapSize);
|
||||||
Size heapSize,
|
|
||||||
Handle tempMemHandle);
|
|
||||||
~nsSmallHeapChunk();
|
~nsSmallHeapChunk();
|
||||||
|
|
||||||
void * GetSpaceForBlock(UInt32 roundedBlockSize);
|
void * GetSpaceForBlock(UInt32 roundedBlockSize);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user