Bug 1268863 - Report ScriptSources that are only reachable via AsmJSModule (r=njn)
authorLuke Wagner <luke@mozilla.com>
Fri, 29 Apr 2016 12:46:07 -0500
changeset 295761 5f92a21902622c9afedaa23f7939e6d710410d38
parent 295760 05545a4f02d5fc2581494da6de7147b7a54c999b
child 295762 5d2a22f7aa3963f33c0f551f48e26cee99e0fa93
push id76068
push userlwagner@mozilla.com
push dateMon, 02 May 2016 22:37:21 +0000
treeherdermozilla-inbound@5f92a2190262 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnjn
bugs1268863
milestone49.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 1268863 - Report ScriptSources that are only reachable via AsmJSModule (r=njn) MozReview-Commit-ID: ByGKq7bUi0l
js/src/asmjs/AsmJS.cpp
js/src/asmjs/WasmModule.h
js/src/vm/MemoryMetrics.cpp
--- a/js/src/asmjs/AsmJS.cpp
+++ b/js/src/asmjs/AsmJS.cpp
@@ -387,16 +387,19 @@ class js::AsmJSModule final : public Mod
         *data += mallocSizeOf(module_.get()) + module_->sizeOfExcludingThis(mallocSizeOf);
     }
     virtual bool mutedErrors() const override {
         return scriptSource()->mutedErrors();
     }
     virtual const char16_t* displayURL() const override {
         return scriptSource()->hasDisplayURL() ? scriptSource()->displayURL() : nullptr;
     }
+    virtual ScriptSource* maybeScriptSource() const override {
+        return scriptSource();
+    }
 
     uint32_t minHeapLength() const { return module_->minHeapLength; }
     uint32_t numFFIs() const { return module_->numFFIs; }
     bool strict() const { return module_->strict; }
     ScriptSource* scriptSource() const { return module_->scriptSource.get(); }
     const AsmJSGlobalVector& asmJSGlobals() const { return module_->globals; }
     const AsmJSImportVector& asmJSImports() const { return module_->imports; }
     const AsmJSExportVector& asmJSExports() const { return module_->exports; }
--- a/js/src/asmjs/WasmModule.h
+++ b/js/src/asmjs/WasmModule.h
@@ -547,16 +547,17 @@ class Module : public mozilla::LinkedLis
     // semantics. The asAsmJS() member may be used as a checked downcast when
     // isAsmJS() is true.
 
     bool isAsmJS() const { return module_->kind == ModuleKind::AsmJS; }
     AsmJSModule& asAsmJS() { MOZ_ASSERT(isAsmJS()); return *(AsmJSModule*)this; }
     const AsmJSModule& asAsmJS() const { MOZ_ASSERT(isAsmJS()); return *(const AsmJSModule*)this; }
     virtual bool mutedErrors() const;
     virtual const char16_t* displayURL() const;
+    virtual ScriptSource* maybeScriptSource() const { return nullptr; }
 
     // The range [0, functionBytes) is a subrange of [0, codeBytes) that
     // contains only function body code, not the stub code. This distinction is
     // used by the async interrupt handler to only interrupt when the pc is in
     // function code which, in turn, simplifies reasoning about how stubs
     // enter/exit.
 
     bool containsFunctionPC(void* pc) const;
--- a/js/src/vm/MemoryMetrics.cpp
+++ b/js/src/vm/MemoryMetrics.cpp
@@ -9,16 +9,17 @@
 #include "mozilla/DebugOnly.h"
 
 #include "jsapi.h"
 #include "jscompartment.h"
 #include "jsgc.h"
 #include "jsobj.h"
 #include "jsscript.h"
 
+#include "asmjs/WasmModule.h"
 #include "gc/Heap.h"
 #include "jit/BaselineJIT.h"
 #include "jit/Ion.h"
 #include "vm/ArrayObject.h"
 #include "vm/Runtime.h"
 #include "vm/Shape.h"
 #include "vm/String.h"
 #include "vm/Symbol.h"
@@ -390,16 +391,53 @@ AddClassInfo(Granularity granularity, Co
             // object/shape/base-shape as notable.
             (void)ok;
         } else {
             p->value().add(info);
         }
     }
 }
 
+template <Granularity granularity>
+static void
+CollectScriptSourceStats(StatsClosure* closure, ScriptSource* ss)
+{
+    RuntimeStats* rtStats = closure->rtStats;
+
+    SourceSet::AddPtr entry = closure->seenSources.lookupForAdd(ss);
+    if (entry)
+        return;
+
+    bool ok = closure->seenSources.add(entry, ss);
+    (void)ok; // Not much to be done on failure.
+
+    JS::ScriptSourceInfo info;  // This zeroes all the sizes.
+    ss->addSizeOfIncludingThis(rtStats->mallocSizeOf_, &info);
+    MOZ_ASSERT(info.compressed == 0 || info.uncompressed == 0);
+
+    rtStats->runtime.scriptSourceInfo.add(info);
+
+    if (granularity == FineGrained) {
+        const char* filename = ss->filename();
+        if (!filename)
+            filename = "<no filename>";
+
+        JS::RuntimeSizes::ScriptSourcesHashMap::AddPtr p =
+            rtStats->runtime.allScriptSources->lookupForAdd(filename);
+        if (!p) {
+            bool ok = rtStats->runtime.allScriptSources->add(p, filename, info);
+            // Ignore failure -- we just won't record the script source as notable.
+            (void)ok;
+        } else {
+            p->value().add(info);
+        }
+    }
+}
+
+
 // The various kinds of hashing are expensive, and the results are unused when
 // doing coarse-grained measurements. Skipping them more than doubles the
 // profile speed for complex pages such as gmail.com.
 template <Granularity granularity>
 static void
 StatsCellCallback(JSRuntime* rt, void* data, void* thing, JS::TraceKind traceKind,
                   size_t thingSize)
 {
@@ -420,58 +458,34 @@ StatsCellCallback(JSRuntime* rt, void* d
         const char* className = clasp->name;
         AddClassInfo(granularity, cStats, className, info);
 
         if (ObjectPrivateVisitor* opv = closure->opv) {
             nsISupports* iface;
             if (opv->getISupports_(obj, &iface) && iface)
                 cStats.objectsPrivate += opv->sizeOfIncludingThis(iface);
         }
+
+        if (obj->is<WasmModuleObject>()) {
+            if (ScriptSource* ss = obj->as<WasmModuleObject>().module().maybeScriptSource())
+                CollectScriptSourceStats<granularity>(closure, ss);
+        }
         break;
       }
 
       case JS::TraceKind::Script: {
         JSScript* script = static_cast<JSScript*>(thing);
         CompartmentStats& cStats = script->compartment()->compartmentStats();
         cStats.scriptsGCHeap += thingSize;
         cStats.scriptsMallocHeapData += script->sizeOfData(rtStats->mallocSizeOf_);
         cStats.typeInferenceTypeScripts += script->sizeOfTypeScript(rtStats->mallocSizeOf_);
         jit::AddSizeOfBaselineData(script, rtStats->mallocSizeOf_, &cStats.baselineData,
                                    &cStats.baselineStubsFallback);
         cStats.ionData += jit::SizeOfIonData(script, rtStats->mallocSizeOf_);
-
-        ScriptSource* ss = script->scriptSource();
-        SourceSet::AddPtr entry = closure->seenSources.lookupForAdd(ss);
-        if (!entry) {
-            bool ok = closure->seenSources.add(entry, ss);
-            (void)ok; // Not much to be done on failure.
-
-            JS::ScriptSourceInfo info;  // This zeroes all the sizes.
-            ss->addSizeOfIncludingThis(rtStats->mallocSizeOf_, &info);
-            MOZ_ASSERT(info.compressed == 0 || info.uncompressed == 0);
-
-            rtStats->runtime.scriptSourceInfo.add(info);
-
-            if (granularity == FineGrained) {
-                const char* filename = ss->filename();
-                if (!filename)
-                    filename = "<no filename>";
-
-                JS::RuntimeSizes::ScriptSourcesHashMap::AddPtr p =
-                    rtStats->runtime.allScriptSources->lookupForAdd(filename);
-                if (!p) {
-                    bool ok = rtStats->runtime.allScriptSources->add(p, filename, info);
-                    // Ignore failure -- we just won't record the script source as notable.
-                    (void)ok;
-                } else {
-                    p->value().add(info);
-                }
-            }
-        }
-
+        CollectScriptSourceStats<granularity>(closure, script->scriptSource());
         break;
       }
 
       case JS::TraceKind::String: {
         JSString* str = static_cast<JSString*>(thing);
 
         JS::StringInfo info;
         if (str->hasLatin1Chars()) {