Bug 1437978 - Add memory reporting for scriptCountsMap. r=nbp
authorAndrew McCreight <continuation@gmail.com>
Tue, 13 Feb 2018 10:00:14 -0800
changeset 458766 f86256e3a26ee645a27de17a61c52eaff5c49f2d
parent 458765 8ed6a4bfec68227c2aa576a907579aff8a9a6bcd
child 458767 4eab912e9f421ba541322033c17fbf10772c09b1
push id1683
push usersfraser@mozilla.com
push dateThu, 26 Apr 2018 16:43:40 +0000
treeherdermozilla-release@5af6cb21869d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp
bugs1437978
milestone60.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 1437978 - Add memory reporting for scriptCountsMap. r=nbp MozReview-Commit-ID: 1AJHhJDJerr
js/public/MemoryMetrics.h
js/src/jit/IonCode.h
js/src/jscompartment.cpp
js/src/jscompartment.h
js/src/jsscript.cpp
js/src/jsscript.h
js/src/vm/MemoryMetrics.cpp
js/xpconnect/src/XPCJSRuntime.cpp
--- a/js/public/MemoryMetrics.h
+++ b/js/public/MemoryMetrics.h
@@ -771,17 +771,18 @@ struct CompartmentStats
     macro(Other,   MallocHeap, lazyArrayBuffersTable) \
     macro(Other,   MallocHeap, objectMetadataTable) \
     macro(Other,   MallocHeap, crossCompartmentWrappersTable) \
     macro(Other,   MallocHeap, savedStacksSet) \
     macro(Other,   MallocHeap, varNamesSet) \
     macro(Other,   MallocHeap, nonSyntacticLexicalScopesTable) \
     macro(Other,   MallocHeap, templateLiteralMap) \
     macro(Other,   MallocHeap, jitCompartment) \
-    macro(Other,   MallocHeap, privateData)
+    macro(Other,   MallocHeap, privateData) \
+    macro(Other,   MallocHeap, scriptCountsMap)
 
     CompartmentStats()
       : FOR_EACH_SIZE(ZERO_SIZE)
         classInfo(),
         extra(),
         allClasses(nullptr),
         notableClasses(),
         isTotals(true)
--- a/js/src/jit/IonCode.h
+++ b/js/src/jit/IonCode.h
@@ -678,16 +678,21 @@ struct IonBlockCounts
             strcpy(ncode, code);
             code_ = ncode;
         }
     }
 
     const char* code() const {
         return code_;
     }
+
+    size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
+        return mallocSizeOf(description_) + mallocSizeOf(successors_) +
+            mallocSizeOf(code_);
+    }
 };
 
 // Execution information for a compiled script which may persist after the
 // IonScript is destroyed, for use during profiling.
 struct IonScriptCounts
 {
   private:
     // Any previous invalidated compilation(s) for the script.
@@ -738,16 +743,35 @@ struct IonScriptCounts
 
     void setPrevious(IonScriptCounts* previous) {
         previous_ = previous;
     }
 
     IonScriptCounts* previous() const {
         return previous_;
     }
+
+    size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
+        size_t size = 0;
+        auto currCounts = this;
+        while (currCounts) {
+            const IonScriptCounts* currCount = currCounts;
+            currCounts = currCount->previous_;
+            size += currCount->sizeOfOneIncludingThis(mallocSizeOf);
+        }
+        return size;
+    }
+
+    size_t sizeOfOneIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
+        size_t size = mallocSizeOf(this) + mallocSizeOf(blocks_);
+        for (size_t i = 0; i < numBlocks_; i++)
+            blocks_[i].sizeOfExcludingThis(mallocSizeOf);
+        return size;
+    }
+
 };
 
 struct VMFunction;
 
 struct AutoFlushICache
 {
   private:
 #if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) || defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -1378,24 +1378,26 @@ JSCompartment::addSizeOfIncludingThis(mo
                                       size_t* lazyArrayBuffersArg,
                                       size_t* objectMetadataTablesArg,
                                       size_t* crossCompartmentWrappersArg,
                                       size_t* savedStacksSet,
                                       size_t* varNamesSet,
                                       size_t* nonSyntacticLexicalEnvironmentsArg,
                                       size_t* templateLiteralMap,
                                       size_t* jitCompartment,
-                                      size_t* privateData)
+                                      size_t* privateData,
+                                      size_t* scriptCountsMapArg)
 {
     *compartmentObject += mallocSizeOf(this);
     objectGroups.addSizeOfExcludingThis(mallocSizeOf, tiAllocationSiteTables,
                                         tiArrayTypeTables, tiObjectTypeTables,
                                         compartmentTables);
     wasm.addSizeOfExcludingThis(mallocSizeOf, compartmentTables);
     *innerViewsArg += innerViews.sizeOfExcludingThis(mallocSizeOf);
+
     if (lazyArrayBuffers)
         *lazyArrayBuffersArg += lazyArrayBuffers->sizeOfIncludingThis(mallocSizeOf);
     if (objectMetadataTable)
         *objectMetadataTablesArg += objectMetadataTable->sizeOfIncludingThis(mallocSizeOf);
     *crossCompartmentWrappersArg += crossCompartmentWrappers.sizeOfExcludingThis(mallocSizeOf);
     *savedStacksSet += savedStacks_.sizeOfExcludingThis(mallocSizeOf);
     *varNamesSet += varNames_.sizeOfExcludingThis(mallocSizeOf);
     if (nonSyntacticLexicalEnvironments_)
@@ -1403,16 +1405,23 @@ JSCompartment::addSizeOfIncludingThis(mo
             nonSyntacticLexicalEnvironments_->sizeOfIncludingThis(mallocSizeOf);
     *templateLiteralMap += templateLiteralMap_.sizeOfExcludingThis(mallocSizeOf);
     if (jitCompartment_)
         *jitCompartment += jitCompartment_->sizeOfIncludingThis(mallocSizeOf);
 
     auto callback = runtime_->sizeOfIncludingThisCompartmentCallback;
     if (callback)
         *privateData += callback(mallocSizeOf, this);
+
+    if (scriptCountsMap) {
+        *scriptCountsMapArg += scriptCountsMap->sizeOfIncludingThis(mallocSizeOf);
+        for (auto r = scriptCountsMap->all(); !r.empty(); r.popFront()) {
+            *scriptCountsMapArg += r.front().value()->sizeOfIncludingThis(mallocSizeOf);
+        }
+    }
 }
 
 void
 JSCompartment::reportTelemetry()
 {
     // Only report telemetry for web content, not add-ons or chrome JS.
     if (creationOptions_.addonIdOrNull() || isSystem_)
         return;
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -776,17 +776,18 @@ struct JSCompartment
                                 size_t* lazyArrayBuffers,
                                 size_t* objectMetadataTables,
                                 size_t* crossCompartmentWrappers,
                                 size_t* savedStacksSet,
                                 size_t* varNamesSet,
                                 size_t* nonSyntacticLexicalScopes,
                                 size_t* templateLiteralMap,
                                 size_t* jitCompartment,
-                                size_t* privateData);
+                                size_t* privateData,
+                                size_t* scriptCountsMapArg);
 
     // Object group tables and other state in the compartment.
     js::ObjectGroupCompartment   objectGroups;
 
 #ifdef JSGC_HASH_TABLE_CHECKS
     void checkWrapperMapAfterMovingGC();
     void checkScriptMapsAfterMovingGC();
 #endif
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -1257,16 +1257,24 @@ js::PCCounts*
 ScriptCounts::getThrowCounts(size_t offset) {
     PCCounts searched = PCCounts(offset);
     PCCounts* elem = std::lower_bound(throwCounts_.begin(), throwCounts_.end(), searched);
     if (elem == throwCounts_.end() || elem->pcOffset() != offset)
         elem = throwCounts_.insert(elem, searched);
     return elem;
 }
 
+size_t
+ScriptCounts::sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) {
+    return mallocSizeOf(this) +
+        pcCounts_.sizeOfExcludingThis(mallocSizeOf) +
+        throwCounts_.sizeOfExcludingThis(mallocSizeOf) +
+        ionCounts_->sizeOfIncludingThis(mallocSizeOf);
+}
+
 void
 JSScript::setIonScript(JSRuntime* rt, js::jit::IonScript* ionScript)
 {
     MOZ_ASSERT_IF(ionScript != ION_DISABLED_SCRIPT, !baselineScript()->hasPendingIonBuilder());
     if (hasIonScript())
         js::jit::IonScript::writeBarrierPre(zone(), ion);
     ion = ionScript;
     MOZ_ASSERT_IF(hasIonScript(), hasBaselineScript());
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -210,16 +210,18 @@ class ScriptCounts
     // the immediate preceding PCCount, then this throw happened in the same
     // basic block.
     const PCCounts* getImmediatePrecedingThrowCounts(size_t offset) const;
 
     // Return the counter used to count the number of throws. Allocate it if
     // none exists yet. Returns null if the allocation failed.
     PCCounts* getThrowCounts(size_t offset);
 
+    size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
+
   private:
     friend class ::JSScript;
     friend struct ScriptAndCounts;
 
     // This sorted array is used to map an offset to the number of times a
     // branch got visited.
     PCCountsVector pcCounts_;
 
--- a/js/src/vm/MemoryMetrics.cpp
+++ b/js/src/vm/MemoryMetrics.cpp
@@ -357,17 +357,18 @@ StatsCompartmentCallback(JSContext* cx, 
                                         &cStats.lazyArrayBuffersTable,
                                         &cStats.objectMetadataTable,
                                         &cStats.crossCompartmentWrappersTable,
                                         &cStats.savedStacksSet,
                                         &cStats.varNamesSet,
                                         &cStats.nonSyntacticLexicalScopesTable,
                                         &cStats.templateLiteralMap,
                                         &cStats.jitCompartment,
-                                        &cStats.privateData);
+                                        &cStats.privateData,
+                                        &cStats.scriptCountsMap);
 }
 
 static void
 StatsArenaCallback(JSRuntime* rt, void* data, gc::Arena* arena,
                    JS::TraceKind traceKind, size_t thingSize)
 {
     RuntimeStats* rtStats = static_cast<StatsClosure*>(data)->rtStats;
 
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -1838,16 +1838,20 @@ ReportCompartmentStats(const JS::Compart
         cStats.jitCompartment,
         "The JIT compartment.");
 
     ZCREPORT_BYTES(cJSPathPrefix + NS_LITERAL_CSTRING("private-data"),
         cStats.privateData,
         "Extra data attached to the compartment by XPConnect, including "
         "its wrapped-js.");
 
+    ZCREPORT_BYTES(cJSPathPrefix + NS_LITERAL_CSTRING("script-counts-map"),
+        cStats.scriptCountsMap,
+        "Profiling-related information for scripts.");
+
     if (sundriesGCHeap > 0) {
         // We deliberately don't use ZCREPORT_GC_BYTES here.
         REPORT_GC_BYTES(cJSPathPrefix + NS_LITERAL_CSTRING("sundries/gc-heap"),
             sundriesGCHeap,
             "The sum of all 'gc-heap' measurements that are too small to be "
             "worth showing individually.");
     }