Bug 1437978 - Add memory reporting for scriptCountsMap. r=nbp draft
authorAndrew McCreight <continuation@gmail.com>
Tue, 13 Feb 2018 10:00:14 -0800
changeset 754551 71134b7ed977480aa5a24f4add83b73c6d79bf4a
parent 754550 1cdd2f83ed442ba2228e166ab22d0cc9bb6834c2
push id98917
push userbmo:continuation@gmail.com
push dateTue, 13 Feb 2018 19:36:17 +0000
reviewersnbp
bugs1437978
milestone60.0a1
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.");
     }