michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * vim: set ts=2 sw=2 et tw=78: michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. michael@0: */ michael@0: michael@0: /* arena allocation for the frame tree and closely-related objects */ michael@0: michael@0: #ifndef nsPresArena_h___ michael@0: #define nsPresArena_h___ michael@0: michael@0: #include "mozilla/MemoryChecking.h" // Note: Do not remove this, needed for MOZ_HAVE_MEM_CHECKS below michael@0: #include "mozilla/MemoryReporting.h" michael@0: #include michael@0: #include "nscore.h" michael@0: #include "nsQueryFrame.h" michael@0: #include "nsTArray.h" michael@0: #include "nsTHashtable.h" michael@0: #include "plarena.h" michael@0: michael@0: struct nsArenaMemoryStats; michael@0: michael@0: class nsPresArena { michael@0: public: michael@0: nsPresArena(); michael@0: ~nsPresArena(); michael@0: michael@0: enum ObjectID { michael@0: nsLineBox_id = nsQueryFrame::NON_FRAME_MARKER, michael@0: nsRuleNode_id, michael@0: nsStyleContext_id, michael@0: nsFrameList_id, michael@0: michael@0: /** michael@0: * The PresArena implementation uses this bit to distinguish objects michael@0: * allocated by size from objects allocated by type ID (that is, frames michael@0: * using AllocateByFrameID and other objects using AllocateByObjectID). michael@0: * It should not collide with any Object ID (above) or frame ID (in michael@0: * nsQueryFrame.h). It is not 0x80000000 to avoid the question of michael@0: * whether enumeration constants are signed. michael@0: */ michael@0: NON_OBJECT_MARKER = 0x40000000 michael@0: }; michael@0: michael@0: /** michael@0: * Pool allocation with recycler lists indexed by object size, aSize. michael@0: */ michael@0: NS_HIDDEN_(void*) AllocateBySize(size_t aSize) michael@0: { michael@0: return Allocate(uint32_t(aSize) | uint32_t(NON_OBJECT_MARKER), aSize); michael@0: } michael@0: NS_HIDDEN_(void) FreeBySize(size_t aSize, void* aPtr) michael@0: { michael@0: Free(uint32_t(aSize) | uint32_t(NON_OBJECT_MARKER), aPtr); michael@0: } michael@0: michael@0: /** michael@0: * Pool allocation with recycler lists indexed by frame-type ID. michael@0: * Every aID must always be used with the same object size, aSize. michael@0: */ michael@0: NS_HIDDEN_(void*) AllocateByFrameID(nsQueryFrame::FrameIID aID, size_t aSize) michael@0: { michael@0: return Allocate(aID, aSize); michael@0: } michael@0: NS_HIDDEN_(void) FreeByFrameID(nsQueryFrame::FrameIID aID, void* aPtr) michael@0: { michael@0: Free(aID, aPtr); michael@0: } michael@0: michael@0: /** michael@0: * Pool allocation with recycler lists indexed by object-type ID (see above). michael@0: * Every aID must always be used with the same object size, aSize. michael@0: */ michael@0: NS_HIDDEN_(void*) AllocateByObjectID(ObjectID aID, size_t aSize) michael@0: { michael@0: return Allocate(aID, aSize); michael@0: } michael@0: NS_HIDDEN_(void) FreeByObjectID(ObjectID aID, void* aPtr) michael@0: { michael@0: Free(aID, aPtr); michael@0: } michael@0: michael@0: /** michael@0: * Increment aArenaStats with sizes of interesting objects allocated in this michael@0: * arena and its mOther field with the size of everything else. michael@0: */ michael@0: void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf, michael@0: nsArenaMemoryStats* aArenaStats); michael@0: michael@0: private: michael@0: NS_HIDDEN_(void*) Allocate(uint32_t aCode, size_t aSize); michael@0: NS_HIDDEN_(void) Free(uint32_t aCode, void* aPtr); michael@0: michael@0: // All keys to this hash table fit in 32 bits (see below) so we do not michael@0: // bother actually hashing them. michael@0: class FreeList : public PLDHashEntryHdr michael@0: { michael@0: public: michael@0: typedef uint32_t KeyType; michael@0: nsTArray mEntries; michael@0: size_t mEntrySize; michael@0: size_t mEntriesEverAllocated; michael@0: michael@0: typedef const void* KeyTypePointer; michael@0: KeyTypePointer mKey; michael@0: michael@0: FreeList(KeyTypePointer aKey) michael@0: : mEntrySize(0), mEntriesEverAllocated(0), mKey(aKey) {} michael@0: // Default copy constructor and destructor are ok. michael@0: michael@0: bool KeyEquals(KeyTypePointer const aKey) const michael@0: { return mKey == aKey; } michael@0: michael@0: static KeyTypePointer KeyToPointer(KeyType aKey) michael@0: { return NS_INT32_TO_PTR(aKey); } michael@0: michael@0: static PLDHashNumber HashKey(KeyTypePointer aKey) michael@0: { return NS_PTR_TO_INT32(aKey); } michael@0: michael@0: enum { ALLOW_MEMMOVE = false }; michael@0: }; michael@0: michael@0: #if defined(MOZ_HAVE_MEM_CHECKS) michael@0: static PLDHashOperator UnpoisonFreeList(FreeList* aEntry, void*); michael@0: #endif michael@0: static PLDHashOperator FreeListEnumerator(FreeList* aEntry, void* aData); michael@0: static size_t SizeOfFreeListEntryExcludingThis(FreeList* aEntry, michael@0: mozilla::MallocSizeOf aMallocSizeOf, michael@0: void*); michael@0: michael@0: nsTHashtable mFreeLists; michael@0: PLArenaPool mPool; michael@0: }; michael@0: michael@0: #endif