Bug 714264 - Part b: Move CompartmentStats to MemoryMetrics.h; r=njn
authorMs2ger <ms2ger@gmail.com>
Wed, 11 Jan 2012 09:23:08 +0100
changeset 85392 b9077aadd3d745c00159ac95aedc2402d94c7d39
parent 85391 6324ddbe266839db9a2395a13064857e20f44940
child 85393 2e7afd15d01a48fcdd692fc8543c9d1541ac25bf
push id805
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 18:17:35 +0000
treeherdermozilla-aurora@6fb3bf232436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnjn
bugs714264
milestone12.0a1
Bug 714264 - Part b: Move CompartmentStats to MemoryMetrics.h; r=njn The name member is implemented as a void*, because it needs to remain an nsCString, and as such the logic to get the name also remains in XPConnect.
js/public/MemoryMetrics.h
js/src/jsfriendapi.cpp
js/src/jsfriendapi.h
js/xpconnect/src/XPCJSRuntime.cpp
js/xpconnect/src/xpcpublic.h
--- a/js/public/MemoryMetrics.h
+++ b/js/public/MemoryMetrics.h
@@ -37,31 +37,86 @@
 #ifndef js_MemoryMetrics_h
 #define js_MemoryMetrics_h
 
 /*
  * These declarations are not within jsapi.h because they are highly likely
  * to change in the future. Depend on them at your own risk.
  */
 
+#include <string.h>
+
 #include "jspubtd.h"
 
 #include "js/Utility.h"
 
 namespace JS {
 
 /* Data for tracking analysis/inference memory usage. */
 struct TypeInferenceMemoryStats
 {
     int64_t scripts;
     int64_t objects;
     int64_t tables;
     int64_t temporary;
 };
 
+typedef void (* DestroyNameCallback)(void *string);
+
+struct CompartmentStats
+{
+    CompartmentStats()
+    {
+        memset(this, 0, sizeof(*this));
+    }
+
+    void init(void *name_, DestroyNameCallback destroyName)
+    {
+        name = name_;
+        destroyNameCb = destroyName;
+    }
+
+    ~CompartmentStats()
+    {
+        destroyNameCb(name);
+    }
+
+    // Pointer to an nsCString, which we can't use here.
+    void *name;
+    DestroyNameCallback destroyNameCb;
+
+    int64_t gcHeapArenaHeaders;
+    int64_t gcHeapArenaPadding;
+    int64_t gcHeapArenaUnused;
+
+    int64_t gcHeapObjectsNonFunction;
+    int64_t gcHeapObjectsFunction;
+    int64_t gcHeapStrings;
+    int64_t gcHeapShapesTree;
+    int64_t gcHeapShapesDict;
+    int64_t gcHeapShapesBase;
+    int64_t gcHeapScripts;
+    int64_t gcHeapTypeObjects;
+    int64_t gcHeapXML;
+
+    int64_t objectSlots;
+    int64_t stringChars;
+    int64_t shapesExtraTreeTables;
+    int64_t shapesExtraDictTables;
+    int64_t shapesExtraTreeShapeKids;
+    int64_t shapesCompartmentTables;
+    int64_t scriptData;
+
+#ifdef JS_METHODJIT
+    int64_t mjitCode;
+    int64_t mjitData;
+#endif
+    TypeInferenceMemoryStats typeInferenceMemory;
+};
+
 extern JS_PUBLIC_API(void)
 SizeOfCompartmentTypeInferenceData(JSContext *cx, JSCompartment *compartment,
                                    TypeInferenceMemoryStats *stats,
                                    JSMallocSizeOfFun mallocSizeOf);
 
 extern JS_PUBLIC_API(void)
 SizeOfObjectTypeInferenceData(/*TypeObject*/ void *object,
                               TypeInferenceMemoryStats *stats,
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -192,16 +192,22 @@ AutoSwitchCompartment::~AutoSwitchCompar
 
 JS_FRIEND_API(bool)
 js::IsSystemCompartment(const JSCompartment *c)
 {
     return c->isSystemCompartment;
 }
 
 JS_FRIEND_API(bool)
+js::IsAtomsCompartmentFor(const JSContext *cx, const JSCompartment *c)
+{
+    return c == cx->runtime->atomsCompartment;
+}
+
+JS_FRIEND_API(bool)
 js::IsScopeObject(JSObject *obj)
 {
     return obj->isScope();
 }
 
 JS_FRIEND_API(JSObject *)
 js::GetObjectParentMaybeScope(JSObject *obj)
 {
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -191,16 +191,19 @@ class JS_FRIEND_API(AutoSwitchCompartmen
 #ifdef OLD_GETTER_SETTER_METHODS
 JS_FRIEND_API(JSBool) obj_defineGetter(JSContext *cx, uintN argc, js::Value *vp);
 JS_FRIEND_API(JSBool) obj_defineSetter(JSContext *cx, uintN argc, js::Value *vp);
 #endif
 
 extern JS_FRIEND_API(bool)
 IsSystemCompartment(const JSCompartment *compartment);
 
+extern JS_FRIEND_API(bool)
+IsAtomsCompartmentFor(const JSContext *cx, const JSCompartment *c);
+
 /*
  * Check whether it is OK to assign an undeclared property with name
  * propname of the global object in the current script on cx.  Reports
  * an error if one needs to be reported (in particular in all cases
  * when it returns false).
  */
 extern JS_FRIEND_API(bool)
 CheckUndeclaredVarAssignment(JSContext *cx, JSString *propname);
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -1,9 +1,9 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  *
  * ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
  * 1.1 (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
@@ -52,16 +52,17 @@
 #include "nsPrintfCString.h"
 #include "mozilla/FunctionTimer.h"
 #include "prsystem.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 
 #include "nsContentUtils.h"
 
+#include "jsfriendapi.h"
 #include "js/MemoryMetrics.h"
 
 #ifdef MOZ_CRASHREPORTER
 #include "nsExceptionHandler.h"
 #endif
 
 #include "jscntxt.h"
 #if 0
@@ -72,17 +73,16 @@
             while ((acx = JS_ContextIterator(cx->runtime, &iter))) {
                 if (!acx->hasRunOption(JSOPTION_UNROOTED_GLOBAL))
                     JS_ToggleOptions(acx, JSOPTION_UNROOTED_GLOBAL);
 
 JS_LOCK_GC, JS_UNLOCK_GC
 
 js_NextActiveContext, js::TriggerOperationCallback
 JSString::charsHeapSize
-c == cx->runtime->atomsCompartment
 CollectCompartmentStatsForRuntime
         mWatchdogWakeup = JS_NEW_CONDVAR(mJSRuntime->gcLock);
         mJSRuntime->setActivityCallback(ActivityCallback, this);
 #endif
 
 using namespace mozilla;
 using namespace mozilla::xpconnect::memory;
 
@@ -1249,28 +1249,75 @@ XPCJSRuntime::~XPCJSRuntime()
 #ifdef DEBUG_shaver_off
         fprintf(stderr, "nJRSI: destroyed runtime %p\n", (void *)mJSRuntime);
 #endif
     }
 
     XPCPerThreadData::ShutDown();
 }
 
+static void*
+GetCompartmentName(JSContext *cx, JSCompartment *c)
+{
+    nsCString* name = new nsCString();
+    if (js::IsAtomsCompartmentFor(cx, c)) {
+        name->AssignLiteral("atoms");
+    } else if (JSPrincipals *principals = JS_GetCompartmentPrincipals(c)) {
+        if (principals->codebase) {
+            name->Assign(principals->codebase);
+
+            // If it's the system compartment, append the address.
+            // This means that multiple system compartments (and there
+            // can be many) can be distinguished.
+            if (js::IsSystemCompartment(c)) {
+                xpc::CompartmentPrivate *compartmentPrivate =
+                    static_cast<xpc::CompartmentPrivate*>(JS_GetCompartmentPrivate(cx, c));
+                if (compartmentPrivate &&
+                    !compartmentPrivate->location.IsEmpty()) {
+                    name->AppendLiteral(", ");
+                    name->Append(compartmentPrivate->location);
+                }
+
+                // ample; 64-bit address max is 18 chars
+                static const int maxLength = 31;
+                nsPrintfCString address(maxLength, ", 0x%llx", PRUint64(c));
+                name->Append(address);
+            }
+
+            // A hack: replace forward slashes with '\\' so they aren't
+            // treated as path separators.  Users of the reporters
+            // (such as about:memory) have to undo this change.
+            name->ReplaceChar('/', '\\');
+        } else {
+            name->AssignLiteral("null-codebase");
+        }
+    } else {
+        name->AssignLiteral("null-principal");
+    }
+    return name;
+}
+
+static void
+DestroyCompartmentName(void *string)
+{
+    delete static_cast<nsCString*>(string);
+}
+
 namespace {
 
 NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(JsMallocSizeOf, "js")
 
 void
 CompartmentMemoryCallback(JSContext *cx, void *vdata, JSCompartment *compartment)
 {
     // Append a new CompartmentStats to the vector.
     IterateData *data = static_cast<IterateData *>(vdata);
-    CompartmentStats compartmentStats(cx, compartment);
-    CompartmentStats *curr =
-        data->compartmentStatsVector.AppendElement(compartmentStats);
+    JS::CompartmentStats *curr =
+        data->compartmentStatsVector.AppendElement();
+    curr->init(GetCompartmentName(cx, compartment), DestroyCompartmentName);
     data->currCompartmentStats = curr;
 
     // Get the compartment-level numbers.
 #ifdef JS_METHODJIT
     curr->mjitCode = JS::SizeOfCompartmentMjitCode(compartment);
 #endif
     JS::SizeOfCompartmentTypeInferenceData(cx, compartment,
                                            &curr->typeInferenceMemory,
@@ -1317,17 +1364,17 @@ ArenaCallback(JSContext *cx, void *vdata
     data->currCompartmentStats->gcHeapArenaUnused += allocationSpace;
 }
 
 void
 CellCallback(JSContext *cx, void *vdata, void *thing, JSGCTraceKind traceKind,
              size_t thingSize)
 {
     IterateData *data = static_cast<IterateData *>(vdata);
-    CompartmentStats *curr = data->currCompartmentStats;
+    JS::CompartmentStats *curr = data->currCompartmentStats;
     switch (traceKind) {
         case JSTRACE_OBJECT:
         {
             JSObject *obj = static_cast<JSObject *>(thing);
             if (JS_ObjectIsFunction(cx, obj)) {
                 curr->gcHeapObjectsFunction += thingSize;
             } else {
                 curr->gcHeapObjectsNonFunction += thingSize;
@@ -1454,20 +1501,21 @@ ReportMemoryPercentage(const nsACString 
 {
     ReportMemory(path, kind, nsIMemoryReporter::UNITS_PERCENTAGE, amount, desc,
                  callback, closure);
 }
 
 template <int N>
 inline const nsCString
 MakeMemoryReporterPath(const nsACString &pathPrefix,
-                       const nsACString &compartmentName,
+                       const JS::CompartmentStats &compartmentStats,
                        const char (&reporterName)[N])
 {
-  return pathPrefix + NS_LITERAL_CSTRING("compartment(") + compartmentName +
+  return pathPrefix + NS_LITERAL_CSTRING("compartment(") +
+         *static_cast<nsCString*>(compartmentStats.name) +
          NS_LITERAL_CSTRING(")/") + nsDependentCString(reporterName);
 }
 
 } // anonymous namespace
 
 // We have per-compartment GC heap totals, so we can't put the total GC heap
 // size in the explicit allocations tree.  But it's a useful figure, so put it
 // in the "others" list.
@@ -1524,56 +1572,16 @@ NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJS
                              "and 'js-compartments-system' might not match the number of "
                              "compartments listed under 'js' if a garbage collection occurs at an "
                              "inopportune time, but such cases should be rare.")
 
 namespace mozilla {
 namespace xpconnect {
 namespace memory {
 
-CompartmentStats::CompartmentStats(JSContext *cx, JSCompartment *c)
-{
-    memset(this, 0, sizeof(*this));
-
-    if (c == cx->runtime->atomsCompartment) {
-        name.AssignLiteral("atoms");
-    } else if (JSPrincipals *principals = JS_GetCompartmentPrincipals(c)) {
-        if (principals->codebase) {
-            name.Assign(principals->codebase);
-
-            // If it's the system compartment, append the address.
-            // This means that multiple system compartments (and there
-            // can be many) can be distinguished.
-            if (js::IsSystemCompartment(c)) {
-                xpc::CompartmentPrivate *compartmentPrivate =
-                        static_cast<xpc::CompartmentPrivate*>(JS_GetCompartmentPrivate(cx, c));
-                if (compartmentPrivate &&
-                    !compartmentPrivate->location.IsEmpty()) {
-                    name.AppendLiteral(", ");
-                    name.Append(compartmentPrivate->location);
-                }
-
-                // ample; 64-bit address max is 18 chars
-                static const int maxLength = 31;
-                nsPrintfCString address(maxLength, ", 0x%llx", PRUint64(c));
-                name.Append(address);
-            }
-
-            // A hack: replace forward slashes with '\\' so they aren't
-            // treated as path separators.  Users of the reporters
-            // (such as about:memory) have to undo this change.
-            name.ReplaceChar('/', '\\');
-        } else {
-            name.AssignLiteral("null-codebase");
-        }
-    } else {
-        name.AssignLiteral("null-principal");
-    }
-}
-
 JSBool
 CollectCompartmentStatsForRuntime(JSRuntime *rt, void *vdata)
 {
     IterateData *data = (IterateData *)vdata;
     JSContext *cx = JS_NewContext(rt, 0);
     if (!cx) {
         NS_ERROR("couldn't create context for memory tracing");
         return false;
@@ -1651,17 +1659,17 @@ CollectCompartmentStatsForRuntime(JSRunt
     data->gcHeapChunkDirtyUnused = data->gcHeapChunkTotal -
                                    data->gcHeapChunkCleanUnused -
                                    data->gcHeapChunkCleanDecommitted -
                                    data->gcHeapChunkDirtyDecommitted;
 
     for (PRUint32 index = 0;
          index < data->compartmentStatsVector.Length();
          index++) {
-        CompartmentStats &stats = data->compartmentStatsVector[index];
+        JS::CompartmentStats &stats = data->compartmentStatsVector[index];
 
         PRInt64 used = stats.gcHeapArenaHeaders +
                        stats.gcHeapArenaPadding +
                        stats.gcHeapArenaUnused +
                        stats.gcHeapObjectsNonFunction +
                        stats.gcHeapObjectsFunction +
                        stats.gcHeapStrings +
                        stats.gcHeapShapesTree +
@@ -1771,206 +1779,206 @@ GetExplicitNonHeapForRuntime(JSRuntime *
 
     return true;
 }
 
 #define SLOP_BYTES_STRING \
     " The measurement includes slop bytes caused by the heap allocator rounding up request sizes."
 
 static PRInt64
-ReportCompartmentStats(const CompartmentStats &stats,
+ReportCompartmentStats(const JS::CompartmentStats &stats,
                        const nsACString &pathPrefix,
                        nsIMemoryMultiReporterCallback *callback,
                        nsISupports *closure)
 {
     PRInt64 gcTotal = 0;
 
-    ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
+    ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
                                               "gc-heap/arena/headers"),
                        &gcTotal, stats.gcHeapArenaHeaders,
                        "Memory on the compartment's garbage-collected JavaScript heap, within "
                        "arenas, that is used to hold internal book-keeping information.",
                        callback, closure);
 
-    ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
+    ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
                                               "gc-heap/arena/padding"),
                        &gcTotal, stats.gcHeapArenaPadding,
                        "Memory on the compartment's garbage-collected JavaScript heap, within "
                        "arenas, that is unused and present only so that other data is aligned. "
                        "This constitutes internal fragmentation.",
                        callback, closure);
 
-    ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
+    ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
                                               "gc-heap/arena/unused"),
                        &gcTotal, stats.gcHeapArenaUnused,
                        "Memory on the compartment's garbage-collected JavaScript heap, within "
                        "arenas, that could be holding useful data but currently isn't.",
                        callback, closure);
 
-    ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
+    ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
                                               "gc-heap/objects/non-function"),
                        &gcTotal, stats.gcHeapObjectsNonFunction,
                        "Memory on the compartment's garbage-collected JavaScript heap that holds "
                        "non-function objects.",
                        callback, closure);
 
-    ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
+    ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
                                               "gc-heap/objects/function"),
                        &gcTotal, stats.gcHeapObjectsFunction,
                        "Memory on the compartment's garbage-collected JavaScript heap that holds "
                        "function objects.",
                        callback, closure);
 
-    ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
+    ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
                                               "gc-heap/strings"),
                        &gcTotal, stats.gcHeapStrings,
                        "Memory on the compartment's garbage-collected JavaScript heap that holds "
                        "string headers.  String headers contain various pieces of information "
                        "about a string, but do not contain (except in the case of very short "
                        "strings) the string characters;  characters in longer strings are counted "
                        "under 'gc-heap/string-chars' instead.",
                        callback, closure);
 
-    ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
+    ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
                                               "gc-heap/scripts"),
                        &gcTotal, stats.gcHeapScripts,
                        "Memory on the compartment's garbage-collected JavaScript heap that holds "
                        "JSScript instances. A JSScript is created for each user-defined function "
                        "in a script. One is also created for the top-level code in a script.",
                        callback, closure);
 
-    ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
+    ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
                                               "gc-heap/shapes/tree"),
                        &gcTotal, stats.gcHeapShapesTree,
                        "Memory on the compartment's garbage-collected JavaScript heap that holds "
                        "shapes that are in a property tree.",
                        callback, closure);
 
-    ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
+    ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
                                               "gc-heap/shapes/dict"),
                        &gcTotal, stats.gcHeapShapesDict,
                        "Memory on the compartment's garbage-collected JavaScript heap that holds "
                        "shapes that are in dictionary mode.",
                        callback, closure);
 
-    ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
+    ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
                                               "gc-heap/shapes/base"),
                        &gcTotal, stats.gcHeapShapesBase,
                        "Memory on the compartment's garbage-collected JavaScript heap that collates "
                        "data common to many shapes.",
                        callback, closure);
 
-    ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
+    ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
                                               "gc-heap/type-objects"),
                        &gcTotal, stats.gcHeapTypeObjects,
                        "Memory on the compartment's garbage-collected JavaScript heap that holds "
                        "type inference information.",
                        callback, closure);
 
-    ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
+    ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
                                               "gc-heap/xml"),
                        &gcTotal, stats.gcHeapXML,
                        "Memory on the compartment's garbage-collected JavaScript heap that holds "
                        "E4X XML objects.",
                        callback, closure);
 
-    ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
+    ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
                                               "object-slots"),
                        nsIMemoryReporter::KIND_HEAP, stats.objectSlots,
                        "Memory allocated for the compartment's non-fixed object slot arrays, "
                        "which are used to represent object properties.  Some objects also "
                        "contain a fixed number of slots which are stored on the compartment's "
                        "JavaScript heap; those slots are not counted here, but in "
                        "'gc-heap/objects' instead." SLOP_BYTES_STRING,
                        callback, closure);
 
-    ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
+    ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
                                               "string-chars"),
                        nsIMemoryReporter::KIND_HEAP, stats.stringChars,
                        "Memory allocated to hold the compartment's string characters.  Sometimes "
                        "more memory is allocated than necessary, to simplify string "
                        "concatenation.  Each string also includes a header which is stored on the "
                        "compartment's JavaScript heap;  that header is not counted here, but in "
                        "'gc-heap/strings' instead.",
                        callback, closure);
 
-    ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
+    ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
                                               "shapes-extra/tree-tables"),
                        nsIMemoryReporter::KIND_HEAP, stats.shapesExtraTreeTables,
                        "Memory allocated for the compartment's property tables that belong to "
                        "shapes that are in a property tree." SLOP_BYTES_STRING,
                        callback, closure);
 
-    ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
+    ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
                                               "shapes-extra/dict-tables"),
                        nsIMemoryReporter::KIND_HEAP, stats.shapesExtraDictTables,
                        "Memory allocated for the compartment's property tables that belong to "
                        "shapes that are in dictionary mode." SLOP_BYTES_STRING,
                        callback, closure);
 
-    ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
+    ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
                                               "shapes-extra/tree-shape-kids"),
                        nsIMemoryReporter::KIND_HEAP, stats.shapesExtraTreeShapeKids,
                        "Memory allocated for the compartment's kid hashes that belong to shapes "
                        "that are in a property tree.",
                        callback, closure);
 
-    ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
+    ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
                                               "shapes-extra/compartment-tables"),
                        nsIMemoryReporter::KIND_HEAP, stats.shapesCompartmentTables,
                        "Memory used by compartment wide tables storing shape information "
                        "for use during object construction.",
                        callback, closure);
 
-    ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
+    ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
                                               "script-data"),
                        nsIMemoryReporter::KIND_HEAP, stats.scriptData,
                        "Memory allocated for JSScript bytecode and various variable-length "
                        "tables." SLOP_BYTES_STRING,
                        callback, closure);
 
 #ifdef JS_METHODJIT
-    ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
+    ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
                                               "mjit-code"),
                        nsIMemoryReporter::KIND_NONHEAP, stats.mjitCode,
                        "Memory used by the method JIT to hold the compartment's generated code.",
                        callback, closure);
 
-    ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
+    ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
                                               "mjit-data"),
                        nsIMemoryReporter::KIND_HEAP, stats.mjitData,
                        "Memory used by the method JIT for the compartment's compilation data: "
                        "JITScripts, native maps, and inline cache structs." SLOP_BYTES_STRING,
                        callback, closure);
 #endif
 
-    ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
+    ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
                                               "type-inference/script-main"),
                        nsIMemoryReporter::KIND_HEAP,
                        stats.typeInferenceMemory.scripts,
                        "Memory used during type inference to store type sets of variables "
                        "and dynamically observed types.",
                        callback, closure);
 
-    ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
+    ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
                                               "type-inference/object-main"),
                        nsIMemoryReporter::KIND_HEAP,
                        stats.typeInferenceMemory.objects,
                        "Memory used during type inference to store types and possible "
                        "property types of JS objects.",
                        callback, closure);
 
-    ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
+    ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
                                               "type-inference/tables"),
                        nsIMemoryReporter::KIND_HEAP,
                        stats.typeInferenceMemory.tables,
                        "Memory used during type inference for compartment-wide tables.",
                        callback, closure);
 
-    ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
+    ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
                                               "analysis-temporary"),
                        nsIMemoryReporter::KIND_HEAP,
                        stats.typeInferenceMemory.temporary,
                        "Memory used during type inference and compilation to hold transient "
                        "analysis information.  Cleared on GC.",
                        callback, closure);
 
     return gcTotal;
--- a/js/xpconnect/src/xpcpublic.h
+++ b/js/xpconnect/src/xpcpublic.h
@@ -210,50 +210,16 @@ bool StringToJsval(JSContext *cx, nsStri
 } // namespace xpc
 
 class nsIMemoryMultiReporterCallback;
 
 namespace mozilla {
 namespace xpconnect {
 namespace memory {
 
-struct CompartmentStats
-{
-    CompartmentStats(JSContext *cx, JSCompartment *c);
-
-    nsCString name;
-    PRInt64 gcHeapArenaHeaders;
-    PRInt64 gcHeapArenaPadding;
-    PRInt64 gcHeapArenaUnused;
-
-    PRInt64 gcHeapObjectsNonFunction;
-    PRInt64 gcHeapObjectsFunction;
-    PRInt64 gcHeapStrings;
-    PRInt64 gcHeapShapesTree;
-    PRInt64 gcHeapShapesDict;
-    PRInt64 gcHeapShapesBase;
-    PRInt64 gcHeapScripts;
-    PRInt64 gcHeapTypeObjects;
-    PRInt64 gcHeapXML;
-
-    PRInt64 objectSlots;
-    PRInt64 stringChars;
-    PRInt64 shapesExtraTreeTables;
-    PRInt64 shapesExtraDictTables;
-    PRInt64 shapesExtraTreeShapeKids;
-    PRInt64 shapesCompartmentTables;
-    PRInt64 scriptData;
-
-#ifdef JS_METHODJIT
-    PRInt64 mjitCode;
-    PRInt64 mjitData;
-#endif
-    JS::TypeInferenceMemoryStats typeInferenceMemory;
-};
-
 struct IterateData
 {
     IterateData()
       : runtimeObject(0),
         runtimeAtomsTable(0),
         runtimeContexts(0),
         runtimeThreadsNormal(0),
         runtimeThreadsTemporary(0),
@@ -301,18 +267,18 @@ struct IterateData
     PRInt64 totalScripts;
     PRInt64 totalStrings;
 #ifdef JS_METHODJIT
     PRInt64 totalMjit;
 #endif
     PRInt64 totalTypeInference;
     PRInt64 totalAnalysisTemp;
 
-    nsTArray<CompartmentStats> compartmentStatsVector;
-    CompartmentStats *currCompartmentStats;
+    nsTArray<JS::CompartmentStats> compartmentStatsVector;
+    JS::CompartmentStats *currCompartmentStats;
 };
 
 JSBool
 CollectCompartmentStatsForRuntime(JSRuntime *rt, void *data);
 JSBool
 GetExplicitNonHeapForRuntime(JSRuntime *rt, void *data);
 
 void