Bug 946781 - part 2 - add memory used by mozJSComponentLoader to about:memory; r=bholley,njn
authorNathan Froyd <froydnj@mozilla.com>
Thu, 05 Dec 2013 16:54:30 -0500
changeset 175808 1949b601ca45bdf5988518f36cde2c4541b0c0e1
parent 175807 529a6786d7053a0377864747e6d9a84ee3cdbcbc
child 175809 223cd199faa2e396e240d7eb57ae7710b35ec62c
push id3343
push userffxbld
push dateMon, 17 Mar 2014 21:55:32 +0000
treeherdermozilla-beta@2f7d3415f79f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley, njn
bugs946781
milestone29.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 946781 - part 2 - add memory used by mozJSComponentLoader to about:memory; r=bholley,njn
js/xpconnect/loader/mozJSComponentLoader.cpp
js/xpconnect/loader/mozJSComponentLoader.h
js/xpconnect/src/XPCJSRuntime.cpp
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -565,16 +565,47 @@ mozJSComponentLoader::NoteSubScript(Hand
 {
   if (!mInitialized && NS_FAILED(ReallyInit())) {
       MOZ_CRASH();
   }
 
   mThisObjects.Put(aScript, aThisObject);
 }
 
+/* static */ size_t
+mozJSComponentLoader::DataEntrySizeOfExcludingThis(const nsACString& aKey,
+                                                   ModuleEntry* const& aData,
+                                                   MallocSizeOf aMallocSizeOf, void*)
+{
+    return aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf) +
+        aData->SizeOfIncludingThis(aMallocSizeOf);
+}
+
+/* static */ size_t
+mozJSComponentLoader::ClassEntrySizeOfExcludingThis(const nsACString& aKey,
+                                                    const nsAutoPtr<ModuleEntry>& aData,
+                                                    MallocSizeOf aMallocSizeOf, void*)
+{
+    return aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf) +
+        aData->SizeOfIncludingThis(aMallocSizeOf);
+}
+
+size_t
+mozJSComponentLoader::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf)
+{
+    size_t amount = aMallocSizeOf(this);
+
+    amount += mModules.SizeOfExcludingThis(DataEntrySizeOfExcludingThis, aMallocSizeOf);
+    amount += mImports.SizeOfExcludingThis(ClassEntrySizeOfExcludingThis, aMallocSizeOf);
+    amount += mInProgressImports.SizeOfExcludingThis(DataEntrySizeOfExcludingThis, aMallocSizeOf);
+    amount += mThisObjects.SizeOfExcludingThis(nullptr, aMallocSizeOf);
+
+    return amount;
+}
+
 // Some stack based classes for cleaning up on early return
 #ifdef HAVE_PR_MEMMAP
 class FileAutoCloser
 {
  public:
     explicit FileAutoCloser(PRFileDesc *file) : mFile(file) {}
     ~FileAutoCloser() { PR_Close(mFile); }
  private:
@@ -1348,16 +1379,25 @@ mozJSComponentLoader::Observe(nsISupport
         UnloadModules();
     } else {
         NS_ERROR("Unexpected observer topic.");
     }
 
     return NS_OK;
 }
 
+size_t
+mozJSComponentLoader::ModuleEntry::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
+{
+    size_t n = aMallocSizeOf(this);
+    n += aMallocSizeOf(location);
+
+    return n;
+}
+
 /* static */ already_AddRefed<nsIFactory>
 mozJSComponentLoader::ModuleEntry::GetFactory(const mozilla::Module& module,
                                               const mozilla::Module::CIDEntry& entry)
 {
     const ModuleEntry& self = static_cast<const ModuleEntry&>(module);
     MOZ_ASSERT(self.getfactoryobj, "Handing out an uninitialized module?");
 
     nsCOMPtr<nsIFactory> f;
--- a/js/xpconnect/loader/mozJSComponentLoader.h
+++ b/js/xpconnect/loader/mozJSComponentLoader.h
@@ -2,16 +2,17 @@
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * 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/. */
 
 #ifndef mozJSComponentLoader_h
 #define mozJSComponentLoader_h
 
+#include "mozilla/MemoryReporting.h"
 #include "mozilla/ModuleLoader.h"
 #include "nsISupports.h"
 #include "nsIObserver.h"
 #include "nsIURI.h"
 #include "xpcIJSModuleLoader.h"
 #include "nsClassHashtable.h"
 #include "nsDataHashtable.h"
 #include "jsapi.h"
@@ -50,16 +51,18 @@ class mozJSComponentLoader : public mozi
 
     nsresult FindTargetObject(JSContext* aCx,
                               JS::MutableHandleObject aTargetObject);
 
     static mozJSComponentLoader* Get() { return sSelf; }
 
     void NoteSubScript(JS::HandleScript aScript, JS::HandleObject aThisObject);
 
+    size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
+
  protected:
     static mozJSComponentLoader* sSelf;
 
     nsresult ReallyInit();
     void UnloadModules();
 
     JSObject* PrepareObjectForLocation(JSCLContextHelper& aCx,
                                        nsIFile* aComponentFile,
@@ -120,26 +123,34 @@ class mozJSComponentLoader : public mozi
 
             if (location)
                 NS_Free(location);
 
             obj = nullptr;
             location = nullptr;
         }
 
+        size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
+
         static already_AddRefed<nsIFactory> GetFactory(const mozilla::Module& module,
                                                        const mozilla::Module::CIDEntry& entry);
 
         nsCOMPtr<xpcIJSGetFactory> getfactoryobj;
         JSObject            *obj;
         char                *location;
     };
 
     friend class ModuleEntry;
 
+    static size_t DataEntrySizeOfExcludingThis(const nsACString& aKey, ModuleEntry* const& aData,
+                                               mozilla::MallocSizeOf aMallocSizeOf, void* arg);
+    static size_t ClassEntrySizeOfExcludingThis(const nsACString& aKey,
+                                                const nsAutoPtr<ModuleEntry>& aData,
+                                                mozilla::MallocSizeOf aMallocSizeOf, void* arg);
+
     // Modules are intentionally leaked, but still cleared.
     static PLDHashOperator ClearModules(const nsACString& key, ModuleEntry*& entry, void* cx);
     nsDataHashtable<nsCStringHashKey, ModuleEntry*> mModules;
 
     nsClassHashtable<nsCStringHashKey, ModuleEntry> mImports;
     nsDataHashtable<nsCStringHashKey, ModuleEntry*> mInProgressImports;
     nsDataHashtable<nsPtrHashKey<JSScript>, JSObject*> mThisObjects;
 
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -9,16 +9,17 @@
 #include "mozilla/MemoryReporting.h"
 
 #include "xpcprivate.h"
 #include "xpcpublic.h"
 #include "XPCWrapper.h"
 #include "XPCJSMemoryReporter.h"
 #include "WrapperFactory.h"
 #include "dom_quickstubs.h"
+#include "mozJSComponentLoader.h"
 
 #include "nsIMemoryReporter.h"
 #include "nsIObserverService.h"
 #include "nsIDebug2.h"
 #include "amIAddonManager.h"
 #include "nsPIDOMWindow.h"
 #include "nsPrintfCString.h"
 #include "mozilla/Preferences.h"
@@ -2629,16 +2630,19 @@ JSReporter::CollectReports(WindowPaths *
     OrphanReporter orphanReporter(XPCConvert::GetISupportsFromJSObject);
     if (!JS::CollectRuntimeStats(xpcrt->Runtime(), &rtStats, &orphanReporter))
         return NS_ERROR_FAILURE;
 
     size_t xpconnect = xpcrt->SizeOfIncludingThis(JSMallocSizeOf);
 
     size_t scopes = XPCWrappedNativeScope::SizeOfAllScopesIncludingThis(JSMallocSizeOf);
 
+    mozJSComponentLoader* loader = mozJSComponentLoader::Get();
+    size_t jsComponentLoaderSize = loader ? loader->SizeOfIncludingThis(JSMallocSizeOf) : 0;
+
     // This is the second step (see above).  First we report stuff in the
     // "explicit" tree, then we report other stuff.
 
     nsresult rv;
     size_t rtTotal = 0;
     rv = xpc::ReportJSRuntimeExplicitTreeStats(rtStats,
                                                NS_LITERAL_CSTRING("explicit/js-non-window/"),
                                                addonManager, cb, closure,
@@ -2718,16 +2722,20 @@ JSReporter::CollectReports(WindowPaths *
     REPORT_BYTES(NS_LITERAL_CSTRING("explicit/xpconnect/runtime"),
                  KIND_HEAP, xpconnect,
                  "Memory used by XPConnect runtime.");
 
     REPORT_BYTES(NS_LITERAL_CSTRING("explicit/xpconnect/scopes"),
                  KIND_HEAP, scopes,
                  "Memory used by XPConnect scopes.");
 
+    REPORT_BYTES(NS_LITERAL_CSTRING("explicit/xpconnect/js-component-loader"),
+                 KIND_HEAP, jsComponentLoaderSize,
+                 "Memory used by XPConnect's JS component loader.");
+
     return NS_OK;
 }
 
 static nsresult
 JSSizeOfTab(JSObject *objArg, size_t *jsObjectsSize, size_t *jsStringsSize,
             size_t *jsPrivateSize, size_t *jsOtherSize)
 {
     JSRuntime *rt = nsXPConnect::GetRuntimeInstance()->Runtime();