Bug 1303013: Account memory for wasm guard pages; r=njn, r=luke
authorBenjamin Bouvier <benj@benj.me>
Mon, 19 Sep 2016 19:39:50 +0200
changeset 357808 1e3b7a0422b6533d5aca29d92fec1e3fd31149ec
parent 357807 89cf1ca5cf6c88f356edbc246521cdf0853411c2
child 357809 45762bec06031d64bc18368c9f515732562d2838
push id6795
push userjlund@mozilla.com
push dateMon, 23 Jan 2017 14:19:46 +0000
treeherdermozilla-beta@76101b503191 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnjn, luke
bugs1303013
milestone52.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 1303013: Account memory for wasm guard pages; r=njn, r=luke MozReview-Commit-ID: BHS1UfgT1yf
js/public/MemoryMetrics.h
js/src/vm/ArrayBufferObject.cpp
js/src/vm/MemoryMetrics.cpp
js/xpconnect/src/XPCJSContext.cpp
--- a/js/public/MemoryMetrics.h
+++ b/js/public/MemoryMetrics.h
@@ -163,21 +163,22 @@ namespace JS {
 
 struct ClassInfo
 {
 #define FOR_EACH_SIZE(macro) \
     macro(Objects, GCHeapUsed, objectsGCHeap) \
     macro(Objects, MallocHeap, objectsMallocHeapSlots) \
     macro(Objects, MallocHeap, objectsMallocHeapElementsNormal) \
     macro(Objects, MallocHeap, objectsMallocHeapElementsAsmJS) \
+    macro(Objects, MallocHeap, objectsMallocHeapMisc) \
     macro(Objects, NonHeap,    objectsNonHeapElementsNormal) \
-    macro(Objects, NonHeap,    objectsNonHeapElementsAsmJS) \
     macro(Objects, NonHeap,    objectsNonHeapElementsShared) \
-    macro(Objects, NonHeap,    objectsNonHeapCodeAsmJS) \
-    macro(Objects, MallocHeap, objectsMallocHeapMisc)
+    macro(Objects, NonHeap,    objectsNonHeapElementsWasm) \
+    macro(Objects, NonHeap,    objectsNonHeapCodeWasm) \
+    macro(Objects, Ignore,     wasmGuardPages)
 
     ClassInfo()
       : FOR_EACH_SIZE(ZERO_SIZE)
         dummy()
     {}
 
     void add(const ClassInfo& other) {
         FOR_EACH_SIZE(ADD_OTHER_SIZE)
--- a/js/src/vm/ArrayBufferObject.cpp
+++ b/js/src/vm/ArrayBufferObject.cpp
@@ -1136,23 +1136,28 @@ ArrayBufferObject::addSizeOfExcludingThi
 {
     ArrayBufferObject& buffer = AsArrayBuffer(obj);
 
     if (!buffer.ownsData())
         return;
 
     switch (buffer.bufferKind()) {
       case PLAIN:
-        info->objectsMallocHeapElementsNormal += mallocSizeOf(buffer.dataPointer());
+        if (buffer.isPreparedForAsmJS())
+            info->objectsMallocHeapElementsAsmJS += mallocSizeOf(buffer.dataPointer());
+        else
+            info->objectsMallocHeapElementsNormal += mallocSizeOf(buffer.dataPointer());
         break;
       case MAPPED:
         info->objectsNonHeapElementsNormal += buffer.byteLength();
         break;
       case WASM:
-        info->objectsNonHeapElementsAsmJS += buffer.byteLength();
+        info->objectsNonHeapElementsWasm += buffer.byteLength();
+        MOZ_ASSERT(buffer.wasmMappedSize() >= buffer.byteLength());
+        info->wasmGuardPages += buffer.wasmMappedSize() - buffer.byteLength();
         break;
       case KIND_MASK:
         MOZ_CRASH("bad bufferKind()");
     }
 }
 
 /* static */ void
 ArrayBufferObject::finalize(FreeOp* fop, JSObject* obj)
--- a/js/src/vm/MemoryMetrics.cpp
+++ b/js/src/vm/MemoryMetrics.cpp
@@ -466,27 +466,27 @@ StatsCellCallback(JSRuntime* rt, void* d
         // we must be careful not to report twice.
         if (obj->is<WasmModuleObject>()) {
             wasm::Module& module = obj->as<WasmModuleObject>().module();
             if (ScriptSource* ss = module.metadata().maybeScriptSource())
                 CollectScriptSourceStats<granularity>(closure, ss);
             module.addSizeOfMisc(rtStats->mallocSizeOf_,
                                  &closure->wasmSeenMetadata,
                                  &closure->wasmSeenBytes,
-                                 &info.objectsNonHeapCodeAsmJS,
+                                 &info.objectsNonHeapCodeWasm,
                                  &info.objectsMallocHeapMisc);
         } else if (obj->is<WasmInstanceObject>()) {
             wasm::Instance& instance = obj->as<WasmInstanceObject>().instance();
             if (ScriptSource* ss = instance.metadata().maybeScriptSource())
                 CollectScriptSourceStats<granularity>(closure, ss);
             instance.addSizeOfMisc(rtStats->mallocSizeOf_,
                                    &closure->wasmSeenMetadata,
                                    &closure->wasmSeenBytes,
                                    &closure->wasmSeenTables,
-                                   &info.objectsNonHeapCodeAsmJS,
+                                   &info.objectsNonHeapCodeWasm,
                                    &info.objectsMallocHeapMisc);
         }
 
         cStats.classInfo.add(info);
 
         const Class* clasp = obj->getClass();
         const char* className = clasp->name;
         AddClassInfo(granularity, cStats, className, info);
--- a/js/xpconnect/src/XPCJSContext.cpp
+++ b/js/xpconnect/src/XPCJSContext.cpp
@@ -2075,63 +2075,70 @@ ReportClassStats(const ClassInfo& classI
         REPORT_BYTES(path + NS_LITERAL_CSTRING("objects/malloc-heap/slots"),
             KIND_HEAP, classInfo.objectsMallocHeapSlots,
             "Non-fixed object slots.");
     }
 
     if (classInfo.objectsMallocHeapElementsNormal > 0) {
         REPORT_BYTES(path + NS_LITERAL_CSTRING("objects/malloc-heap/elements/normal"),
             KIND_HEAP, classInfo.objectsMallocHeapElementsNormal,
-            "Normal (non-asm.js) indexed elements.");
+            "Normal (non-wasm) indexed elements.");
     }
 
-    // asm.js arrays are heap-allocated on some platforms and
-    // non-heap-allocated on others.  We never put them under sundries,
-    // because (a) in practice they're almost always larger than the sundries
-    // threshold, and (b) we'd need a third category of sundries ("non-heap"),
-    // which would be a pain.
-    size_t mallocHeapElementsAsmJS = classInfo.objectsMallocHeapElementsAsmJS;
-    size_t nonHeapElementsAsmJS    = classInfo.objectsNonHeapElementsAsmJS;
-    MOZ_ASSERT(mallocHeapElementsAsmJS == 0 || nonHeapElementsAsmJS == 0);
-    if (mallocHeapElementsAsmJS > 0) {
+    if (classInfo.objectsMallocHeapElementsAsmJS > 0) {
         REPORT_BYTES(path + NS_LITERAL_CSTRING("objects/malloc-heap/elements/asm.js"),
-            KIND_HEAP, mallocHeapElementsAsmJS,
-            "asm.js array buffer elements on the malloc heap.");
+            KIND_HEAP, classInfo.objectsMallocHeapElementsAsmJS,
+            "asm.js array buffer elements allocated in the malloc heap.");
     }
-    if (nonHeapElementsAsmJS > 0) {
-        REPORT_BYTES(path + NS_LITERAL_CSTRING("objects/non-heap/elements/asm.js"),
-            KIND_NONHEAP, nonHeapElementsAsmJS,
-            "asm.js array buffer elements outside both the malloc heap and "
-            "the GC heap.");
+
+    if (classInfo.objectsMallocHeapMisc > 0) {
+        REPORT_BYTES(path + NS_LITERAL_CSTRING("objects/malloc-heap/misc"),
+            KIND_HEAP, classInfo.objectsMallocHeapMisc,
+            "Miscellaneous object data.");
     }
 
     if (classInfo.objectsNonHeapElementsNormal > 0) {
         REPORT_BYTES(path + NS_LITERAL_CSTRING("objects/non-heap/elements/normal"),
             KIND_NONHEAP, classInfo.objectsNonHeapElementsNormal,
             "Memory-mapped non-shared array buffer elements.");
     }
 
     if (classInfo.objectsNonHeapElementsShared > 0) {
         REPORT_BYTES(path + NS_LITERAL_CSTRING("objects/non-heap/elements/shared"),
             KIND_NONHEAP, classInfo.objectsNonHeapElementsShared,
             "Memory-mapped shared array buffer elements. These elements are "
             "shared between one or more runtimes; the reported size is divided "
             "by the buffer's refcount.");
     }
 
-    if (classInfo.objectsNonHeapCodeAsmJS > 0) {
-        REPORT_BYTES(path + NS_LITERAL_CSTRING("objects/non-heap/code/asm.js"),
-            KIND_NONHEAP, classInfo.objectsNonHeapCodeAsmJS,
-            "AOT-compiled asm.js code.");
+    // WebAssembly memories are always non-heap-allocated (mmap). We never put
+    // these under sundries, because (a) in practice they're almost always
+    // larger than the sundries threshold, and (b) we'd need a third category of
+    // sundries ("non-heap"), which would be a pain.
+    if (classInfo.objectsNonHeapElementsWasm > 0) {
+        REPORT_BYTES(path + NS_LITERAL_CSTRING("objects/non-heap/elements/wasm"),
+            KIND_NONHEAP, classInfo.objectsNonHeapElementsWasm,
+            "wasm/asm.js array buffer elements allocated outside both the "
+            "malloc heap and the GC heap.");
     }
 
-    if (classInfo.objectsMallocHeapMisc > 0) {
-        REPORT_BYTES(path + NS_LITERAL_CSTRING("objects/malloc-heap/misc"),
-            KIND_HEAP, classInfo.objectsMallocHeapMisc,
-            "Miscellaneous object data.");
+    if (classInfo.objectsNonHeapCodeWasm > 0) {
+        REPORT_BYTES(path + NS_LITERAL_CSTRING("objects/non-heap/code/wasm"),
+            KIND_NONHEAP, classInfo.objectsNonHeapCodeWasm,
+            "AOT-compiled wasm/asm.js code.");
+    }
+
+    // Although wasm guard pages aren't committed in memory they can be very
+    // large and contribute greatly to vsize and so are worth reporting.
+    if (classInfo.wasmGuardPages > 0) {
+        REPORT_BYTES(NS_LITERAL_CSTRING("wasm-guard-pages"),
+            KIND_OTHER, classInfo.wasmGuardPages,
+            "Guard pages mapped after the end of wasm memories, reserved for "
+            "optimization tricks, but not committed and thus never contributing"
+            " to RSS, only vsize.");
     }
 }
 
 static void
 ReportCompartmentStats(const JS::CompartmentStats& cStats,
                        const xpc::CompartmentStatsExtras& extras,
                        amIAddonManager* addonManager,
                        nsIHandleReportCallback* handleReport,