From f6824360d306bb73fc6dd8077f6f1cf8cd4930db Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 22 Dec 2011 17:24:43 -0800 Subject: [PATCH] Bug 712835 (part 2 of 3) - Add a memory reporter for the nsAtomTable. r=khuey. --HG-- extra : rebase_source : 3c934649d072e0d519c905cb8baf49b12bce0312 --- xpcom/base/Makefile.in | 5 ++- xpcom/base/nsMemoryReporterManager.cpp | 21 ++++++++++ xpcom/ds/nsAtomTable.cpp | 53 +++++++++++++++++++++----- xpcom/ds/nsAtomTable.h | 8 +++- 4 files changed, 75 insertions(+), 12 deletions(-) diff --git a/xpcom/base/Makefile.in b/xpcom/base/Makefile.in index bf22dfa5c33..d42f1edea1d 100644 --- a/xpcom/base/Makefile.in +++ b/xpcom/base/Makefile.in @@ -171,4 +171,7 @@ ifneq (,$(filter gtk2,$(MOZ_WIDGET_TOOLKIT))) CXXFLAGS += $(MOZ_GTK2_CFLAGS) endif -LOCAL_INCLUDES += -I$(srcdir)/../build +LOCAL_INCLUDES += \ + -I$(srcdir)/../build \ + -I$(topsrcdir)/xpcom/ds \ + $(NULL) diff --git a/xpcom/base/nsMemoryReporterManager.cpp b/xpcom/base/nsMemoryReporterManager.cpp index b1e1a11baf4..459260c3c82 100644 --- a/xpcom/base/nsMemoryReporterManager.cpp +++ b/xpcom/base/nsMemoryReporterManager.cpp @@ -37,6 +37,7 @@ * * ***** END LICENSE BLOCK ***** */ +#include "nsAtomTable.h" #include "nsAutoPtr.h" #include "nsCOMPtr.h" #include "nsServiceManagerUtils.h" @@ -496,6 +497,24 @@ NS_MEMORY_REPORTER_IMPLEMENT(HeapAllocated, "application because the allocator regularly rounds up request sizes. (The " "exact amount requested is not recorded.)") +NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(AtomTableMallocSizeOf, "atom-table") + +static PRInt64 GetAtomTableSize() { + return NS_SizeOfAtomTableIncludingThis(AtomTableMallocSizeOf); +} + +// Why is this here? At first glance, you'd think it could be defined and +// registered with nsMemoryReporterManager entirely within nsAtomTable.cpp. +// However, the obvious time to register it is when the table is initialized, +// and that happens before XPCOM components are initialized, which means the +// NS_RegisterMemoryReporter call fails. So instead we do it here. +NS_MEMORY_REPORTER_IMPLEMENT(AtomTable, + "explicit/atom-table", + KIND_HEAP, + UNITS_BYTES, + GetAtomTableSize, + "Memory used by the atoms table.") + /** ** nsMemoryReporterManager implementation **/ @@ -538,6 +557,8 @@ nsMemoryReporterManager::Init() REGISTER(HeapZone0Used); #endif + REGISTER(AtomTable); + return NS_OK; } diff --git a/xpcom/ds/nsAtomTable.cpp b/xpcom/ds/nsAtomTable.cpp index 6706519e765..7fc3f174a30 100644 --- a/xpcom/ds/nsAtomTable.cpp +++ b/xpcom/ds/nsAtomTable.cpp @@ -369,21 +369,58 @@ AtomImpl::IsStaticAtom() return IsPermanent(); } +size_t +AtomImpl::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const +{ + return aMallocSizeOf(this, sizeof(AtomImpl)) + + nsStringBuffer::FromData(mString)-> + SizeOfIncludingThisIfUnshared(aMallocSizeOf); +} + //---------------------------------------------------------------------- +static size_t +SizeOfAtomTableEntryExcludingThis(PLDHashEntryHdr *aHdr, + nsMallocSizeOfFun aMallocSizeOf, + void *aArg) +{ + AtomTableEntry* entry = static_cast(aHdr); + return entry->mAtom->SizeOfIncludingThis(aMallocSizeOf); +} + +size_t NS_SizeOfAtomTableIncludingThis(nsMallocSizeOfFun aMallocSizeOf) { + if (gAtomTable.ops) { + return PL_DHashTableSizeOfExcludingThis(&gAtomTable, + SizeOfAtomTableEntryExcludingThis, + aMallocSizeOf); + } + return 0; +} + #define ATOM_HASHTABLE_INITIAL_SIZE 4096 +static inline bool +EnsureTableExists() +{ + if (gAtomTable.ops) { + return true; + } + if (PL_DHashTableInit(&gAtomTable, &AtomTableOps, 0, + sizeof(AtomTableEntry), ATOM_HASHTABLE_INITIAL_SIZE)) { + return true; + } + // Initialization failed. + gAtomTable.ops = nsnull; + return false; +} + static inline AtomTableEntry* GetAtomHashEntry(const char* aString, PRUint32 aLength) { NS_ASSERTION(NS_IsMainThread(), "wrong thread"); - if (!gAtomTable.ops && - !PL_DHashTableInit(&gAtomTable, &AtomTableOps, 0, - sizeof(AtomTableEntry), ATOM_HASHTABLE_INITIAL_SIZE)) { - gAtomTable.ops = nsnull; + if (!EnsureTableExists()) { return nsnull; } - AtomTableKey key(aString, aLength); return static_cast (PL_DHashTableOperate(&gAtomTable, &key, PL_DHASH_ADD)); @@ -393,13 +430,9 @@ static inline AtomTableEntry* GetAtomHashEntry(const PRUnichar* aString, PRUint32 aLength) { NS_ASSERTION(NS_IsMainThread(), "wrong thread"); - if (!gAtomTable.ops && - !PL_DHashTableInit(&gAtomTable, &AtomTableOps, 0, - sizeof(AtomTableEntry), ATOM_HASHTABLE_INITIAL_SIZE)) { - gAtomTable.ops = nsnull; + if (!EnsureTableExists()) { return nsnull; } - AtomTableKey key(aString, aLength); return static_cast (PL_DHashTableOperate(&gAtomTable, &key, PL_DHASH_ADD)); diff --git a/xpcom/ds/nsAtomTable.h b/xpcom/ds/nsAtomTable.h index c6313cdfb05..bc1fb1b0f2b 100644 --- a/xpcom/ds/nsAtomTable.h +++ b/xpcom/ds/nsAtomTable.h @@ -85,6 +85,8 @@ public: // for |#ifdef NS_BUILD_REFCNT_LOGGING| access to reference count nsrefcnt GetRefCount() { return mRefCnt; } + + size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const; }; /** @@ -108,14 +110,18 @@ public: virtual bool IsPermanent(); + // SizeOfIncludingThis() isn't needed -- the one inherited from AtomImpl is + // good enough, because PermanentAtomImpl doesn't add any new data members. + void* operator new(size_t size, AtomImpl* aAtom) CPP_THROW_NEW; void* operator new(size_t size) CPP_THROW_NEW { return ::operator new(size); } - }; void NS_PurgeAtomTable(); +size_t NS_SizeOfAtomTableIncludingThis(nsMallocSizeOfFun aMallocSizeOf); + #endif // nsAtomTable_h__