Bug 692277 - Part a: Introduce an unstable public API for JS memory measurements to be used in XPCJSRuntime; r=njn sr=dmandelin
authorMs2ger <ms2ger@gmail.com>
Sat, 24 Dec 2011 09:27:39 +0100
changeset 85727 53c2fc22835b43d2fe60a5fce7e2e9cec97ecc1d
parent 85726 a16ef2789fc3f2422a6a215f2ba94207b3547f16
child 85728 f4d8adba8d7494ff58e16b66c27512a87b44e210
push id674
push userffxbld
push dateTue, 13 Mar 2012 21:17:50 +0000
treeherdermozilla-beta@e3c4c92dec31 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnjn, dmandelin
bugs692277
milestone12.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 692277 - Part a: Introduce an unstable public API for JS memory measurements to be used in XPCJSRuntime; r=njn sr=dmandelin
js/public/MemoryMetrics.h
js/src/Makefile.in
js/src/jsapi-tests/testIntTypesABI.cpp
js/src/jsapi.cpp
js/src/jscompartment.cpp
js/src/jscompartment.h
js/src/jsfriendapi.cpp
js/src/jsfriendapi.h
js/src/jsinfer.cpp
js/src/jsobj.cpp
js/src/jsscope.cpp
js/src/jsscript.cpp
js/src/jsscript.h
js/src/methodjit/MethodJIT.cpp
js/src/shell/js.cpp
js/xpconnect/src/XPCJSRuntime.cpp
js/xpconnect/src/xpcpublic.h
new file mode 100644
--- /dev/null
+++ b/js/public/MemoryMetrics.h
@@ -0,0 +1,104 @@
+/* ***** 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/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is about:memory glue.
+ *
+ * The Initial Developer of the Original Code is
+ * Ms2ger <ms2ger@gmail.com>.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#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 "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;
+};
+
+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,
+                              JSMallocSizeOfFun mallocSizeOf);
+
+extern JS_PUBLIC_API(size_t)
+SizeOfObjectDynamicSlots(JSObject *obj, JSMallocSizeOfFun mallocSizeOf);
+
+extern JS_PUBLIC_API(size_t)
+SizeOfCompartmentShapeTable(JSCompartment *c, JSMallocSizeOfFun mallocSizeOf);
+
+extern JS_PUBLIC_API(size_t)
+SizeOfCompartmentMjitCode(const JSCompartment *c);
+
+extern JS_PUBLIC_API(bool)
+IsShapeInDictionary(const void *shape);
+
+extern JS_PUBLIC_API(size_t)
+SizeOfShapePropertyTable(const void *shape, JSMallocSizeOfFun mallocSizeOf);
+
+extern JS_PUBLIC_API(size_t)
+SizeOfShapeKids(const void *shape, JSMallocSizeOfFun mallocSizeOf);
+
+extern JS_PUBLIC_API(size_t)
+SizeOfScriptData(JSScript *script, JSMallocSizeOfFun mallocSizeOf);
+
+#ifdef JS_METHODJIT
+extern JS_PUBLIC_API(size_t)
+SizeOfScriptJitData(JSScript *script, JSMallocSizeOfFun mallocSizeOf);
+#endif
+
+extern JS_PUBLIC_API(size_t)
+SystemCompartmentCount(const JSRuntime *rt);
+
+extern JS_PUBLIC_API(size_t)
+UserCompartmentCount(const JSRuntime *rt);
+
+} // namespace JS
+
+#endif // js_MemoryMetrics_h
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -264,16 +264,17 @@ VPATH		+= \
 EXPORTS_NAMESPACES += js
 
 # If you add a header here, add it to js/src/jsapi-tests/testIntTypesABI.cpp so
 # that we ensure we don't over-expose our internal integer typedefs.  Note that
 # LegacyIntTypes.h below is deliberately exempted from this requirement.
 EXPORTS_js = \
 		HashTable.h \
 		LegacyIntTypes.h \
+		MemoryMetrics.h \
 		TemplateLib.h \
 		Utility.h \
 		Vector.h \
 		$(NULL)
 
 ###############################################
 # BEGIN include sources for low-level code shared with mfbt
 #
--- a/js/src/jsapi-tests/testIntTypesABI.cpp
+++ b/js/src/jsapi-tests/testIntTypesABI.cpp
@@ -13,16 +13,17 @@
 #include "jscpucfg.h"
 #include "jspubtd.h"
 #include "jsstdint.h"
 #include "jstypes.h"
 #include "jsval.h"
 #include "jsxdrapi.h"
 
 #include "js/HashTable.h"
+#include "js/MemoryMetrics.h"
 #include "js/TemplateLib.h"
 #include "js/Utility.h"
 #include "js/Vector.h"
 
 /*
  * Verify that our public (and intended to be public, versus being that way
  * because we haven't made them private yet) headers don't define
  * {u,}int{8,16,32,64} or JS{Ui,I}nt{8,16,32,64} types.  If any do, they will
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -81,16 +81,17 @@
 #include "jsweakmap.h"
 #include "jswrapper.h"
 #include "jstypedarray.h"
 
 #include "ds/LifoAlloc.h"
 #include "builtin/RegExp.h"
 #include "frontend/BytecodeCompiler.h"
 #include "frontend/BytecodeEmitter.h"
+#include "js/MemoryMetrics.h"
 
 #include "jsatominlines.h"
 #include "jsinferinlines.h"
 #include "jsobjinlines.h"
 #include "jsscopeinlines.h"
 #include "jsscriptinlines.h"
 
 #include "vm/RegExpObject-inl.h"
@@ -918,16 +919,40 @@ JS_GetRuntimePrivate(JSRuntime *rt)
 }
 
 JS_PUBLIC_API(void)
 JS_SetRuntimePrivate(JSRuntime *rt, void *data)
 {
     rt->data = data;
 }
 
+JS_PUBLIC_API(size_t)
+JS::SystemCompartmentCount(const JSRuntime *rt)
+{
+    size_t n = 0;
+    for (size_t i = 0; i < rt->compartments.length(); i++) {
+        if (rt->compartments[i]->isSystemCompartment) {
+            ++n;
+        }
+    }
+    return n;
+}
+
+JS_PUBLIC_API(size_t)
+JS::UserCompartmentCount(const JSRuntime *rt)
+{
+    size_t n = 0;
+    for (size_t i = 0; i < rt->compartments.length(); i++) {
+        if (!rt->compartments[i]->isSystemCompartment) {
+            ++n;
+        }
+    }
+    return n;
+}
+
 #ifdef JS_THREADSAFE
 static void
 StartRequest(JSContext *cx)
 {
     JSThread *t = cx->thread();
     JS_ASSERT(CURRENT_THREAD_IS_ME(t));
 
     if (t->data.requestDepth) {
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -43,22 +43,24 @@
 #include "jsgc.h"
 #include "jsgcmark.h"
 #include "jsiter.h"
 #include "jsmath.h"
 #include "jsproxy.h"
 #include "jsscope.h"
 #include "jswatchpoint.h"
 #include "jswrapper.h"
+
 #include "assembler/wtf/Platform.h"
-#include "yarr/BumpPointerAllocator.h"
+#include "js/MemoryMetrics.h"
 #include "methodjit/MethodJIT.h"
 #include "methodjit/PolyIC.h"
 #include "methodjit/MonoIC.h"
 #include "vm/Debugger.h"
+#include "yarr/BumpPointerAllocator.h"
 
 #include "jsgcinlines.h"
 #include "jsobjinlines.h"
 #include "jsscopeinlines.h"
 
 #if ENABLE_YARR_JIT
 #include "assembler/jit/ExecutableAllocator.h"
 #endif
@@ -137,27 +139,34 @@ JSCompartment::ensureJaegerCompartmentEx
     if (!jc->Initialize()) {
         cx->delete_(jc);
         return false;
     }
     jaegerCompartment_ = jc;
     return true;
 }
 
-void
-JSCompartment::sizeOfCode(size_t *method, size_t *regexp, size_t *unused) const
+size_t
+JSCompartment::sizeOfMjitCode() const
 {
-    if (jaegerCompartment_) {
-        jaegerCompartment_->execAlloc()->sizeOfCode(method, regexp, unused);
-    } else {
-        *method = 0;
-        *regexp = 0;
-        *unused = 0;
-    }
+    if (!jaegerCompartment_)
+        return 0;
+
+    size_t method, regexp, unused;
+    jaegerCompartment_->execAlloc()->sizeOfCode(&method, &regexp, &unused);
+    JS_ASSERT(regexp == 0);
+    return method + unused;
 }
+
+JS_PUBLIC_API(size_t)
+JS::SizeOfCompartmentMjitCode(const JSCompartment *c)
+{
+    return c->sizeOfMjitCode();
+}
+
 #endif
 
 bool
 JSCompartment::wrap(JSContext *cx, Value *vp)
 {
     JS_ASSERT(cx->compartment == this);
 
     uintN flags = 0;
@@ -735,8 +744,17 @@ JSCompartment::sweepBreakpoints(JSContex
 }
 
 GCMarker *
 JSCompartment::createBarrierTracer()
 {
     JS_ASSERT(!gcIncrementalTracer);
     return NULL;
 }
+
+JS_PUBLIC_API(size_t)
+JS::SizeOfCompartmentShapeTable(JSCompartment *c, JSMallocSizeOfFun mallocSizeOf)
+{
+    return c->baseShapes.sizeOfExcludingThis(mallocSizeOf)
+         + c->initialShapes.sizeOfExcludingThis(mallocSizeOf)
+         + c->newTypeObjects.sizeOfExcludingThis(mallocSizeOf)
+         + c->lazyTypeObjects.sizeOfExcludingThis(mallocSizeOf);
+}
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -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/
@@ -230,17 +230,17 @@ struct JS_FRIEND_API(JSCompartment) {
 
     js::mjit::JaegerCompartment *jaegerCompartment() const {
         JS_ASSERT(jaegerCompartment_);
         return jaegerCompartment_;
     }
 
     bool ensureJaegerCompartmentExists(JSContext *cx);
 
-    void sizeOfCode(size_t *method, size_t *regexp, size_t *unused) const;
+    size_t sizeOfMjitCode() const;
 #endif
 
     /*
      * Shared scope property tree, and arena-pool for allocating its nodes.
      */
     js::PropertyTree             propertyTree;
 
 #ifdef DEBUG
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -179,31 +179,16 @@ AutoSwitchCompartment::AutoSwitchCompart
 }
 
 AutoSwitchCompartment::~AutoSwitchCompartment()
 {
     /* The old compartment may have been destroyed, so we can't use cx->setCompartment. */
     cx->compartment = oldCompartment;
 }
 
-JS_FRIEND_API(size_t)
-js::GetObjectDynamicSlotSize(JSObject *obj, JSMallocSizeOfFun mallocSizeOf)
-{
-    return obj->dynamicSlotSize(mallocSizeOf);
-}
-
-JS_FRIEND_API(size_t)
-js::GetCompartmentShapeTableSize(JSCompartment *c, JSMallocSizeOfFun mallocSizeOf)
-{
-    return c->baseShapes.sizeOfExcludingThis(mallocSizeOf)
-         + c->initialShapes.sizeOfExcludingThis(mallocSizeOf)
-         + c->newTypeObjects.sizeOfExcludingThis(mallocSizeOf)
-         + c->lazyTypeObjects.sizeOfExcludingThis(mallocSizeOf);
-}
-
 JS_FRIEND_API(bool)
 js::IsScopeObject(const JSObject *obj)
 {
     return obj->isInternalScope();
 }
 
 JS_FRIEND_API(JSObject *)
 js::GetObjectParentMaybeScope(const JSObject *obj)
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -109,35 +109,16 @@ extern JS_FRIEND_API(void)
 JS_SetAccumulateTelemetryCallback(JSRuntime *rt, JSAccumulateTelemetryDataCallback callback);
 
 typedef void
 (* JSGCFinishedCallback)(JSRuntime *rt, JSCompartment *comp, const char *description);
 
 extern JS_FRIEND_API(void)
 JS_SetGCFinishedCallback(JSRuntime *rt, JSGCFinishedCallback callback);
 
-/* Data for tracking analysis/inference memory usage. */
-typedef struct TypeInferenceMemoryStats
-{
-    int64_t scripts;
-    int64_t objects;
-    int64_t tables;
-    int64_t temporary;
-} TypeInferenceMemoryStats;
-
-extern JS_FRIEND_API(void)
-JS_GetTypeInferenceMemoryStats(JSContext *cx, JSCompartment *compartment,
-                               TypeInferenceMemoryStats *stats,
-                               JSMallocSizeOfFun mallocSizeOf);
-
-extern JS_FRIEND_API(void)
-JS_GetTypeInferenceObjectStats(/*TypeObject*/ void *object,
-                               TypeInferenceMemoryStats *stats,
-                               JSMallocSizeOfFun mallocSizeOf);
-
 extern JS_FRIEND_API(JSPrincipals *)
 JS_GetCompartmentPrincipals(JSCompartment *compartment);
 
 /* Safe to call with input obj == NULL. Returns non-NULL iff obj != NULL. */
 extern JS_FRIEND_API(JSObject *)
 JS_ObjectToInnerObject(JSContext *cx, JSObject *obj);
 
 /* Requires obj != NULL. */
@@ -204,22 +185,16 @@ class JS_FRIEND_API(AutoSwitchCompartmen
     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
 #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(size_t)
-GetObjectDynamicSlotSize(JSObject *obj, JSMallocSizeOfFun mallocSizeOf);
-
-extern JS_FRIEND_API(size_t)
-GetCompartmentShapeTableSize(JSCompartment *c, JSMallocSizeOfFun mallocSizeOf);
-
 /*
  * 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/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -51,16 +51,17 @@
 #include "jsobj.h"
 #include "jsscript.h"
 #include "jscntxt.h"
 #include "jsscope.h"
 #include "jsstr.h"
 #include "jsiter.h"
 
 #include "frontend/TokenStream.h"
+#include "js/MemoryMetrics.h"
 #include "methodjit/MethodJIT.h"
 #include "methodjit/Retcon.h"
 
 #include "jsatominlines.h"
 #include "jsgcinlines.h"
 #include "jsinferinlines.h"
 #include "jsobjinlines.h"
 #include "jsscriptinlines.h"
@@ -6289,30 +6290,30 @@ GetScriptMemoryStats(JSScript *script, T
     TypeResult *result = typeScript->dynamicList;
     while (result) {
         stats->scripts += mallocSizeOf(result, sizeof(TypeResult));
         result = result->next;
     }
 
     /*
      * This counts memory that is in the temp pool but gets attributed
-     * elsewhere.  See JS_GetTypeInferenceMemoryStats for more details.
+     * elsewhere.  See JS::SizeOfCompartmentTypeInferenceData for more details.
      */
     TypeSet *typeArray = typeScript->typeArray();
     for (unsigned i = 0; i < count; i++) {
         size_t bytes = typeArray[i].dynamicSize();
         stats->scripts += bytes;
         stats->temporary -= bytes;
     }
 }
 
-JS_FRIEND_API(void)
-JS_GetTypeInferenceMemoryStats(JSContext *cx, JSCompartment *compartment,
-                               TypeInferenceMemoryStats *stats,
-                               JSMallocSizeOfFun mallocSizeOf)
+JS_PUBLIC_API(void)
+JS::SizeOfCompartmentTypeInferenceData(JSContext *cx, JSCompartment *compartment,
+                                       TypeInferenceMemoryStats *stats,
+                                       JSMallocSizeOfFun mallocSizeOf)
 {
     /*
      * Note: not all data in the pool is temporary, and some will survive GCs
      * by being copied to the replacement pool. This memory will be counted
      * elsewhere and deducted from the amount of temporary data.
      */
     stats->temporary += compartment->typeLifoAlloc.sizeOfExcludingThis(mallocSizeOf);
 
@@ -6345,18 +6346,18 @@ JS_GetTypeInferenceMemoryStats(JSContext
 
             /* key.ids and values.types have the same length. */
             stats->tables += mallocSizeOf(key.ids, key.nslots * sizeof(jsid)) +
                              mallocSizeOf(value.types, key.nslots * sizeof(Type));
         }
     }
 }
 
-JS_FRIEND_API(void)
-JS_GetTypeInferenceObjectStats(void *object_, TypeInferenceMemoryStats *stats, JSMallocSizeOfFun mallocSizeOf)
+JS_PUBLIC_API(void)
+JS::SizeOfObjectTypeInferenceData(void *object_, TypeInferenceMemoryStats *stats, JSMallocSizeOfFun mallocSizeOf)
 {
     TypeObject *object = (TypeObject *) object_;
 
     if (object->singleton) {
         /*
          * Properties and associated type sets for singletons are cleared on
          * every GC. The type object is normally destroyed too, but we don't
          * charge this to 'temporary' as this is not for GC heap values.
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -77,16 +77,17 @@
 #include "jsdbgapi.h"
 #include "json.h"
 #include "jswatchpoint.h"
 #include "jswrapper.h"
 
 #include "frontend/BytecodeCompiler.h"
 #include "frontend/BytecodeEmitter.h"
 #include "frontend/Parser.h"
+#include "js/MemoryMetrics.h"
 
 #include "jsarrayinlines.h"
 #include "jsinterpinlines.h"
 #include "jsobjinlines.h"
 #include "jsscopeinlines.h"
 #include "jsscriptinlines.h"
 #include "jsstrinlines.h"
 
@@ -7125,16 +7126,22 @@ js::HandleNonGenericMethodClassMismatch(
         if (thisObj.isProxy())
             return Proxy::nativeCall(cx, &thisObj, clasp, native, args);
     }
 
     ReportIncompatibleMethod(cx, args, clasp);
     return false;
 }
 
+JS_PUBLIC_API(size_t)
+JS::SizeOfObjectDynamicSlots(JSObject *obj, JSMallocSizeOfFun mallocSizeOf)
+{
+    return obj->dynamicSlotSize(mallocSizeOf);
+}
+
 #ifdef DEBUG
 
 /*
  * Routines to print out values during debugging.  These are FRIEND_API to help
  * the debugger find them and to support temporarily hacking js_Dump* calls
  * into other code.
  */
 
--- a/js/src/jsscope.cpp
+++ b/js/src/jsscope.cpp
@@ -54,16 +54,18 @@
 #include "jscntxt.h"
 #include "jsdbgapi.h"
 #include "jslock.h"
 #include "jsnum.h"
 #include "jsobj.h"
 #include "jsscope.h"
 #include "jsstr.h"
 
+#include "js/MemoryMetrics.h"
+
 #include "jsatominlines.h"
 #include "jsobjinlines.h"
 #include "jsscopeinlines.h"
 
 using namespace js;
 using namespace js::gc;
 
 bool
@@ -1444,8 +1446,26 @@ JSCompartment::sweepInitialShapeTable(JS
     if (initialShapes.initialized()) {
         for (InitialShapeSet::Enum e(initialShapes); !e.empty(); e.popFront()) {
             const InitialShapeEntry &entry = e.front();
             if (!entry.shape->isMarked() || (entry.proto && !entry.proto->isMarked()))
                 e.removeFront();
         }
     }
 }
+
+JS_PUBLIC_API(bool)
+JS::IsShapeInDictionary(const void *shape)
+{
+    return static_cast<const Shape*>(shape)->inDictionary();
+}
+
+JS_PUBLIC_API(size_t)
+JS::SizeOfShapePropertyTable(const void *shape, JSMallocSizeOfFun mallocSizeOf)
+{
+    return static_cast<const Shape*>(shape)->sizeOfPropertyTable(mallocSizeOf);
+}
+
+JS_PUBLIC_API(size_t)
+JS::SizeOfShapeKids(const void *shape, JSMallocSizeOfFun mallocSizeOf)
+{
+    return static_cast<const Shape*>(shape)->sizeOfKids(mallocSizeOf);
+}
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -63,16 +63,17 @@
 #include "jsscope.h"
 #include "jsscript.h"
 #if JS_HAS_XDR
 #include "jsxdrapi.h"
 #endif
 
 #include "frontend/BytecodeEmitter.h"
 #include "frontend/Parser.h"
+#include "js/MemoryMetrics.h"
 #include "methodjit/MethodJIT.h"
 #include "methodjit/Retcon.h"
 #include "vm/Debugger.h"
 
 #include "jsinferinlines.h"
 #include "jsinterpinlines.h"
 #include "jsobjinlines.h"
 #include "jsscriptinlines.h"
@@ -1306,16 +1307,22 @@ JSScript::dataSize(JSMallocSizeOfFun mal
 #if JS_SCRIPT_INLINE_DATA_LIMIT
     if (data == inlineData)
         return 0;
 #endif
 
     return mallocSizeOf(data, dataSize());
 }
 
+JS_PUBLIC_API(size_t)
+JS::SizeOfScriptData(JSScript *script, JSMallocSizeOfFun mallocSizeOf)
+{
+    return script->dataSize(mallocSizeOf);
+}
+
 /*
  * Nb: srcnotes are variable-length.  This function computes the number of
  * srcnote *slots*, which may be greater than the number of srcnotes.
  */
 uint32_t
 JSScript::numNotes()
 {
     jssrcnote *sn;
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -646,18 +646,18 @@ struct JSScript : public js::gc::Cell {
         void *addr = constructing ? jitArityCheckCtor : jitArityCheckNormal;
         if (addr == NULL)
             return JITScript_None;
         if (addr == JS_UNJITTABLE_SCRIPT)
             return JITScript_Invalid;
         return JITScript_Valid;
     }
 
-    /* Size of the JITScript and all sections.  (This method is implemented in MethodJIT.h.) */
-    JS_FRIEND_API(size_t) jitDataSize(JSMallocSizeOfFun mallocSizeOf);
+    /* Size of the JITScript and all sections.  (This method is implemented in MethodJIT.cpp.) */
+    size_t jitDataSize(JSMallocSizeOfFun mallocSizeOf);
 
 #endif
 
     /* Counter accessors. */
     js::OpcodeCounts getCounts(jsbytecode *pc) {
         JS_ASSERT(size_t(pc - code) < length);
         return pcCounters.counts[pc - code];
     }
--- a/js/src/methodjit/MethodJIT.cpp
+++ b/js/src/methodjit/MethodJIT.cpp
@@ -35,16 +35,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "MethodJIT.h"
 #include "Logging.h"
 #include "assembler/jit/ExecutableAllocator.h"
 #include "assembler/assembler/RepatchBuffer.h"
+#include "js/MemoryMetrics.h"
 #include "jsgcmark.h"
 #include "BaseAssembler.h"
 #include "Compiler.h"
 #include "MonoIC.h"
 #include "PolyIC.h"
 #include "TrampolineCompiler.h"
 #include "jscntxtinlines.h"
 #include "jscompartment.h"
@@ -1307,16 +1308,22 @@ JSScript::jitDataSize(JSMallocSizeOfFun 
     size_t n = 0;
     if (jitNormal)
         n += jitNormal->scriptDataSize(mallocSizeOf); 
     if (jitCtor)
         n += jitCtor->scriptDataSize(mallocSizeOf); 
     return n;
 }
 
+JS_PUBLIC_API(size_t)
+JS::SizeOfScriptJitData(JSScript *script, JSMallocSizeOfFun mallocSizeOf)
+{
+    return script->jitDataSize(mallocSizeOf);
+}
+
 /* Please keep in sync with Compiler::finishThisUp! */
 size_t
 mjit::JITScript::scriptDataSize(JSMallocSizeOfFun mallocSizeOf)
 {
     size_t computedSize =
         sizeof(JITScript) +
         sizeof(NativeMapEntry) * nNmapPairs +
         sizeof(InlineFrame) * nInlineFrames +
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -3820,21 +3820,19 @@ Deserialize(JSContext *cx, uintN argc, j
 }
 
 JSBool
 MJitCodeStats(JSContext *cx, uintN argc, jsval *vp)
 {
 #ifdef JS_METHODJIT
     JSRuntime *rt = cx->runtime;
     AutoLockGC lock(rt);
-    size_t n = 0, method, regexp, unused;
-    for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); ++c)
-    {
-        (*c)->sizeOfCode(&method, &regexp, &unused);
-        n += method + regexp + unused;
+    size_t n = 0;
+    for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); ++c) {
+        n += (*c)->sizeOfMjitCode();
     }
     JS_SET_RVAL(cx, vp, INT_TO_JSVAL(n));
 #else
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
 #endif
     return true;
 }
 
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -44,27 +44,27 @@
 #include "mozilla/Util.h"
 
 #include "xpcprivate.h"
 #include "xpcpublic.h"
 #include "WrapperFactory.h"
 #include "dom_quickstubs.h"
 
 #include "jscompartment.h"
-#include "jsgcchunk.h"
-#include "jsscope.h"
 #include "nsIMemoryReporter.h"
 #include "nsPrintfCString.h"
 #include "mozilla/FunctionTimer.h"
 #include "prsystem.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 
 #include "nsContentUtils.h"
 
+#include "js/MemoryMetrics.h"
+
 #ifdef MOZ_CRASHREPORTER
 #include "nsExceptionHandler.h"
 #endif
 
 using namespace mozilla;
 using namespace mozilla::xpconnect::memory;
 
 /***************************************************************************/
@@ -1235,36 +1235,34 @@ XPCJSRuntime::~XPCJSRuntime()
     XPCPerThreadData::ShutDown();
 }
 
 namespace {
 
 NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(JsMallocSizeOf, "js")
 
 void
-CompartmentCallback(JSContext *cx, void *vdata, JSCompartment *compartment)
+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);
     data->currCompartmentStats = curr;
 
     // Get the compartment-level numbers.
 #ifdef JS_METHODJIT
-    size_t method, regexp, unused;
-    compartment->sizeOfCode(&method, &regexp, &unused);
-    JS_ASSERT(regexp == 0);     /* this execAlloc is only used for method code */
-    curr->mjitCode = method + unused;
+    curr->mjitCode = JS::SizeOfCompartmentMjitCode(compartment);
 #endif
-    JS_GetTypeInferenceMemoryStats(cx, compartment, &curr->typeInferenceMemory,
-                                   JsMallocSizeOf);
+    JS::SizeOfCompartmentTypeInferenceData(cx, compartment,
+                                           &curr->typeInferenceMemory,
+                                           JsMallocSizeOf);
     curr->shapesCompartmentTables =
-        js::GetCompartmentShapeTableSize(compartment, JsMallocSizeOf);
+        JS::SizeOfCompartmentShapeTable(compartment, JsMallocSizeOf);
 }
 
 void
 ChunkCallback(JSContext *cx, void *vdata, js::gc::Chunk *chunk)
 {
     // Nb: This function is only called for dirty chunks, which is why we
     // increment gcHeapChunkDirtyDecommitted.
     IterateData *data = static_cast<IterateData *>(vdata);
@@ -1301,63 +1299,62 @@ CellCallback(JSContext *cx, void *vdata,
         case JSTRACE_OBJECT:
         {
             JSObject *obj = static_cast<JSObject *>(thing);
             if (JS_ObjectIsFunction(cx, obj)) {
                 curr->gcHeapObjectsFunction += thingSize;
             } else {
                 curr->gcHeapObjectsNonFunction += thingSize;
             }
-            curr->objectSlots += js::GetObjectDynamicSlotSize(obj, JsMallocSizeOf);
+            curr->objectSlots += JS::SizeOfObjectDynamicSlots(obj, JsMallocSizeOf);
             break;
         }
         case JSTRACE_STRING:
         {
             JSString *str = static_cast<JSString *>(thing);
             curr->gcHeapStrings += thingSize;
             curr->stringChars += str->charsHeapSize(JsMallocSizeOf);
             break;
         }
         case JSTRACE_SHAPE:
         {
-            js::Shape *shape = static_cast<js::Shape *>(thing);
-            if (shape->inDictionary()) {
+            if (JS::IsShapeInDictionary(thing)) {
                 curr->gcHeapShapesDict += thingSize;
                 curr->shapesExtraDictTables +=
-                    shape->sizeOfPropertyTable(JsMallocSizeOf);
+                    JS::SizeOfShapePropertyTable(thing, JsMallocSizeOf);
             } else {
                 curr->gcHeapShapesTree += thingSize;
                 curr->shapesExtraTreeTables +=
-                    shape->sizeOfPropertyTable(JsMallocSizeOf);
+                    JS::SizeOfShapePropertyTable(thing, JsMallocSizeOf);
                 curr->shapesExtraTreeShapeKids +=
-                    shape->sizeOfKids(JsMallocSizeOf);
+                    JS::SizeOfShapeKids(thing, JsMallocSizeOf);
             }
             break;
         }
         case JSTRACE_BASE_SHAPE:
         {
             curr->gcHeapShapesBase += thingSize;
             break;
         }
         case JSTRACE_SCRIPT:
         {
             JSScript *script = static_cast<JSScript *>(thing);
             curr->gcHeapScripts += thingSize;
-            curr->scriptData += script->dataSize(JsMallocSizeOf);
+            curr->scriptData += JS::SizeOfScriptData(script, JsMallocSizeOf);
 #ifdef JS_METHODJIT
-            curr->mjitData += script->jitDataSize(JsMallocSizeOf);
+            curr->mjitData += JS::SizeOfScriptJitData(script, JsMallocSizeOf);
 #endif
             break;
         }
         case JSTRACE_TYPE_OBJECT:
         {
             js::types::TypeObject *obj = static_cast<js::types::TypeObject *>(thing);
             curr->gcHeapTypeObjects += thingSize;
-            JS_GetTypeInferenceObjectStats(obj, &curr->typeInferenceMemory,
-                                           JsMallocSizeOf);
+            JS::SizeOfObjectTypeInferenceData(obj, &curr->typeInferenceMemory,
+                                              JsMallocSizeOf);
             break;
         }
         case JSTRACE_XML:
         {
             curr->gcHeapXML += thingSize;
             break;
         }
     }
@@ -1459,37 +1456,23 @@ NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJS
                              KIND_OTHER,
                              nsIMemoryReporter::UNITS_BYTES,
                              GetGCChunkTotalBytes,
                              "Memory used by the garbage-collected JavaScript heap.")
 
 static PRInt64
 GetJSSystemCompartmentCount()
 {
-    JSRuntime *rt = nsXPConnect::GetRuntimeInstance()->GetJSRuntime();
-    size_t n = 0;
-    for (size_t i = 0; i < rt->compartments.length(); i++) {
-        if (rt->compartments[i]->isSystemCompartment) {
-            n++;
-        }
-    }
-    return n;
+    return JS::SystemCompartmentCount(nsXPConnect::GetRuntimeInstance()->GetJSRuntime());
 }
 
 static PRInt64
 GetJSUserCompartmentCount()
 {
-    JSRuntime *rt = nsXPConnect::GetRuntimeInstance()->GetJSRuntime();
-    size_t n = 0;
-    for (size_t i = 0; i < rt->compartments.length(); i++) {
-        if (!rt->compartments[i]->isSystemCompartment) {
-            n++;
-        }
-    }
-    return n;
+    return JS::UserCompartmentCount(nsXPConnect::GetRuntimeInstance()->GetJSRuntime());
 }
 
 // Nb: js-system-compartment-count + js-user-compartment-count could be
 // different to the number of compartments reported by
 // XPConnectJSCompartmentsMultiReporter if a garbage collection occurred
 // between them being consulted.  We could move these reporters into
 // XPConnectJSCompartmentCount to avoid that problem, but then we couldn't
 // easily report them via telemetry, so we live with the small risk of
@@ -1576,17 +1559,17 @@ CollectCompartmentStatsForRuntime(JSRunt
         data->gcHeapChunkCleanUnused =
             PRInt64(JS_GetGCParameter(rt, JSGC_UNUSED_CHUNKS)) *
             js::gc::ChunkSize -
             data->gcHeapChunkCleanDecommitted;
         data->gcHeapChunkTotal =
             PRInt64(JS_GetGCParameter(rt, JSGC_TOTAL_CHUNKS)) *
             js::gc::ChunkSize;
 
-        js::IterateCompartmentsArenasCells(cx, data, CompartmentCallback,
+        js::IterateCompartmentsArenasCells(cx, data, CompartmentMemoryCallback,
                                            ArenaCallback, CellCallback);
         js::IterateChunks(cx, data, ChunkCallback);
 
         data->runtimeObject = JsMallocSizeOf(rt, sizeof(JSRuntime));
 
         // Nb: we use sizeOfExcludingThis() because atomState.atoms is within
         // JSRuntime, and so counted when JSRuntime is counted.
         data->runtimeAtomsTable =
--- a/js/xpconnect/src/xpcpublic.h
+++ b/js/xpconnect/src/xpcpublic.h
@@ -36,16 +36,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef xpcpublic_h
 #define xpcpublic_h
 
 #include "jsapi.h"
+#include "js/MemoryMetrics.h"
 #include "jsclass.h"
 #include "jsfriendapi.h"
 #include "jsgc.h"
 #include "jspubtd.h"
 #include "jsproxy.h"
 
 #include "nsISupports.h"
 #include "nsIPrincipal.h"
@@ -234,17 +235,17 @@ struct CompartmentStats
     PRInt64 shapesExtraTreeShapeKids;
     PRInt64 shapesCompartmentTables;
     PRInt64 scriptData;
 
 #ifdef JS_METHODJIT
     PRInt64 mjitCode;
     PRInt64 mjitData;
 #endif
-    TypeInferenceMemoryStats typeInferenceMemory;
+    JS::TypeInferenceMemoryStats typeInferenceMemory;
 };
 
 struct IterateData
 {
     IterateData()
       : runtimeObject(0),
         runtimeAtomsTable(0),
         runtimeContexts(0),