Bug 807850 - Add a memory reporter for the nsScriptNameSpaceManager. r=jst.
authorNicholas Nethercote <nnethercote@mozilla.com>
Sun, 04 Nov 2012 14:18:44 -0800
changeset 112282 5a5775d8c49887ea2ebfde1224e71298bab94754
parent 112281 52feef2d0c8e5c5dfb922b7d9e56aaa1a928762f
child 112283 92cdd367285d6e1633b33a37197bfcc3b2e43352
push id17496
push usernnethercote@mozilla.com
push dateSun, 04 Nov 2012 22:57:48 +0000
treeherdermozilla-inbound@5a5775d8c498 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjst
bugs807850
milestone19.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 807850 - Add a memory reporter for the nsScriptNameSpaceManager. r=jst.
dom/base/nsJSEnvironment.cpp
dom/base/nsScriptNameSpaceManager.cpp
dom/base/nsScriptNameSpaceManager.h
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -169,17 +169,36 @@ static uint32_t sTotalForgetSkippableTim
 static uint32_t sRemovedPurples = 0;
 static uint32_t sForgetSkippableBeforeCC = 0;
 static uint32_t sPreviousSuspectedCount = 0;
 static uint32_t sCompartmentGCCount = NS_MAX_COMPARTMENT_GC_COUNT;
 static uint32_t sCleanupsSinceLastGC = UINT32_MAX;
 static bool sNeedsFullCC = false;
 static nsJSContext *sContextList = nullptr;
 
-nsScriptNameSpaceManager *gNameSpaceManager;
+static nsScriptNameSpaceManager *gNameSpaceManager;
+static nsIMemoryReporter *gReporter;
+
+NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(ScriptNameSpaceManagerMallocSizeOf,
+                                     "script-namespace-manager")
+
+static int64_t
+GetScriptNameSpaceManagerSize()
+{
+  MOZ_ASSERT(gNameSpaceManager);
+  return gNameSpaceManager->SizeOfIncludingThis(
+             ScriptNameSpaceManagerMallocSizeOf);
+}
+
+NS_MEMORY_REPORTER_IMPLEMENT(ScriptNameSpaceManager,
+    "explicit/script-namespace-manager",
+    KIND_HEAP,
+    nsIMemoryReporter::UNITS_BYTES,
+    GetScriptNameSpaceManagerSize,
+    "Memory used for the script namespace manager.")
 
 static nsIJSRuntimeService *sRuntimeService;
 JSRuntime *nsJSRuntime::sRuntime;
 
 static const char kJSRuntimeServiceContractID[] =
   "@mozilla.org/js/xpc/RuntimeService;1";
 
 static PRTime sFirstCollectionTime;
@@ -3639,16 +3658,17 @@ nsJSRuntime::Startup()
   sLastCCEndTime = 0;
   sPendingLoadCount = 0;
   sLoadingInProgress = false;
   sCCollectedWaitingForGC = 0;
   sPostGCEventsToConsole = false;
   sDisableExplicitCompartmentGC = false;
   sNeedsFullCC = false;
   gNameSpaceManager = nullptr;
+  gReporter = nullptr;
   sRuntimeService = nullptr;
   sRuntime = nullptr;
   sIsInitialized = false;
   sDidShutdown = false;
   sContextCount = 0;
   sSecurityManager = nullptr;
 }
 
@@ -3981,32 +4001,39 @@ nsJSRuntime::GetNameSpaceManager()
     return nullptr;
 
   if (!gNameSpaceManager) {
     gNameSpaceManager = new nsScriptNameSpaceManager;
     NS_ADDREF(gNameSpaceManager);
 
     nsresult rv = gNameSpaceManager->Init();
     NS_ENSURE_SUCCESS(rv, nullptr);
+
+    gReporter = new NS_MEMORY_REPORTER_NAME(ScriptNameSpaceManager);
+    NS_RegisterMemoryReporter(gReporter);
   }
 
   return gNameSpaceManager;
 }
 
 /* static */
 void
 nsJSRuntime::Shutdown()
 {
   nsJSContext::KillGCTimer();
   nsJSContext::KillShrinkGCBuffersTimer();
   nsJSContext::KillCCTimer();
   nsJSContext::KillFullGCTimer();
   nsJSContext::KillInterSliceGCTimer();
 
   NS_IF_RELEASE(gNameSpaceManager);
+  if (gReporter) {
+    (void)::NS_UnregisterMemoryReporter(gReporter);
+    gReporter = nullptr;
+  }
 
   if (!sContextCount) {
     // We're being shutdown, and there are no more contexts
     // alive, release the JS runtime service and the security manager.
 
     NS_IF_RELEASE(sRuntimeService);
     NS_IF_RELEASE(sSecurityManager);
   }
--- a/dom/base/nsScriptNameSpaceManager.cpp
+++ b/dom/base/nsScriptNameSpaceManager.cpp
@@ -3,16 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsScriptNameSpaceManager.h"
 #include "nsCOMPtr.h"
 #include "nsIComponentManager.h"
 #include "nsIComponentRegistrar.h"
 #include "nsICategoryManager.h"
+#include "nsIMemoryReporter.h"
 #include "nsIServiceManager.h"
 #include "nsXPCOM.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIScriptExternalNameSet.h"
 #include "nsIScriptNameSpaceManager.h"
 #include "nsIScriptContext.h"
 #include "nsIInterfaceInfoManager.h"
 #include "nsIInterfaceInfo.h"
@@ -32,16 +33,23 @@ using namespace mozilla;
 
 // Our extended PLDHashEntryHdr
 class GlobalNameMapEntry : public PLDHashEntryHdr
 {
 public:
   // Our hash table ops don't care about the order of these members
   nsString mKey;
   nsGlobalNameStruct mGlobalName;
+
+  size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) {
+    // Measurement of the following members may be added later if DMD finds it
+    // is worthwhile:
+    // - mGlobalName
+    return mKey.SizeOfExcludingThisMustBeUnshared(aMallocSizeOf);
+  }
 };
 
 
 static PLDHashNumber
 GlobalNameHashHashKey(PLDHashTable *table, const void *key)
 {
   const nsAString *str = static_cast<const nsAString *>(key);
   return HashString(*str);
@@ -788,8 +796,27 @@ nsScriptNameSpaceManager::RegisterDefine
   if (s) {
     if (s->mType == nsGlobalNameStruct::eTypeNotInitialized) {
       s->mType = nsGlobalNameStruct::eTypeNewDOMBinding;
     }
     s->mDefineDOMInterface = aDefineDOMInterface;
     s->mPrefEnabled = aPrefEnabled;
   }
 }
+
+static size_t
+SizeOfEntryExcludingThis(PLDHashEntryHdr *aHdr, nsMallocSizeOfFun aMallocSizeOf,
+                         void *aArg)
+{
+    GlobalNameMapEntry* entry = static_cast<GlobalNameMapEntry*>(aHdr);
+    return entry->SizeOfExcludingThis(aMallocSizeOf);
+}
+
+size_t
+nsScriptNameSpaceManager::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf)
+{
+  size_t n = 0;
+  n += PL_DHashTableSizeOfExcludingThis(&mGlobalNames,
+         SizeOfEntryExcludingThis, aMallocSizeOf);
+  n += PL_DHashTableSizeOfExcludingThis(&mNavigatorNames,
+         SizeOfEntryExcludingThis, aMallocSizeOf);
+  return n;
+}
--- a/dom/base/nsScriptNameSpaceManager.h
+++ b/dom/base/nsScriptNameSpaceManager.h
@@ -138,16 +138,18 @@ public:
                              const nsCID *aConstructorCID);
 
   nsGlobalNameStruct* GetConstructorProto(const nsGlobalNameStruct* aStruct);
 
   void RegisterDefineDOMInterface(const nsAFlatString& aName,
     mozilla::dom::DefineInterface aDefineDOMInterface,
     mozilla::dom::PrefEnabled aPrefEnabled);
 
+  size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf);
+
 private:
   // Adds a new entry to the hash and returns the nsGlobalNameStruct
   // that aKey will be mapped to. If mType in the returned
   // nsGlobalNameStruct is != eTypeNotInitialized, an entry for aKey
   // already existed.
   nsGlobalNameStruct *AddToHash(PLDHashTable *aTable, const nsAString *aKey,
                                 const PRUnichar **aClassName = nullptr);
   nsGlobalNameStruct *AddToHash(PLDHashTable *aTable, const char *aKey,