Bug 729403 (part 2, take 2) - Add js/runtime/gc-marker memory reporter. r=wmccloskey.
authorNicholas Nethercote <nnethercote@mozilla.com>
Sun, 26 Feb 2012 20:20:15 -0800
changeset 90777 dbe3f8bad3b5ecb2d10719f83b9956c172a50bde
parent 90776 89c46aa25a143e3a6c2b4eb81df6b5bc869e381c
child 90778 d913e27b169bf432b3f7d31ddec50903208c885c
push idunknown
push userunknown
push dateunknown
reviewerswmccloskey
bugs729403
milestone13.0a1
Bug 729403 (part 2, take 2) - Add js/runtime/gc-marker memory reporter. r=wmccloskey.
js/public/MemoryMetrics.h
js/src/MemoryMetrics.cpp
js/src/jscntxt.cpp
js/src/jscntxt.h
js/src/jsgc.cpp
js/src/jsgc.h
js/xpconnect/src/XPCJSRuntime.cpp
--- a/js/public/MemoryMetrics.h
+++ b/js/public/MemoryMetrics.h
@@ -123,16 +123,17 @@ struct RuntimeStats
                  DestroyNameCallback destroyNameCb)
       : runtimeObject(0)
       , runtimeAtomsTable(0)
       , runtimeContexts(0)
       , runtimeNormal(0)
       , runtimeTemporary(0)
       , runtimeRegexpCode(0)
       , runtimeStackCommitted(0)
+      , runtimeGCMarker(0)
       , gcHeapChunkTotal(0)
       , gcHeapChunkCleanUnused(0)
       , gcHeapChunkDirtyUnused(0)
       , gcHeapChunkCleanDecommitted(0)
       , gcHeapChunkDirtyDecommitted(0)
       , gcHeapArenaUnused(0)
       , gcHeapChunkAdmin(0)
       , gcHeapUnusedPercentage(0)
@@ -154,16 +155,17 @@ struct RuntimeStats
 
     size_t runtimeObject;
     size_t runtimeAtomsTable;
     size_t runtimeContexts;
     size_t runtimeNormal;
     size_t runtimeTemporary;
     size_t runtimeRegexpCode;
     size_t runtimeStackCommitted;
+    size_t runtimeGCMarker;
     size_t gcHeapChunkTotal;
     size_t gcHeapChunkCleanUnused;
     size_t gcHeapChunkDirtyUnused;
     size_t gcHeapChunkCleanDecommitted;
     size_t gcHeapChunkDirtyDecommitted;
     size_t gcHeapArenaUnused;
     size_t gcHeapChunkAdmin;
     size_t gcHeapUnusedPercentage;
--- a/js/src/MemoryMetrics.cpp
+++ b/js/src/MemoryMetrics.cpp
@@ -206,20 +206,19 @@ CollectRuntimeStats(JSRuntime *rt, Runti
         IterateChunks(cx, rtStats, StatsChunkCallback);
 
         rtStats->runtimeObject = rtStats->mallocSizeOf(rt);
 
         rt->sizeOfExcludingThis(rtStats->mallocSizeOf,
                                 &rtStats->runtimeNormal,
                                 &rtStats->runtimeTemporary,
                                 &rtStats->runtimeRegexpCode,
-                                &rtStats->runtimeStackCommitted);
+                                &rtStats->runtimeStackCommitted,
+                                &rtStats->runtimeGCMarker);
 
-        // Nb: we use sizeOfExcludingThis() because atomState.atoms is within
-        // JSRuntime, and so counted when JSRuntime is counted.
         rtStats->runtimeAtomsTable =
             rt->atomState.atoms.sizeOfExcludingThis(rtStats->mallocSizeOf);
 
         JSContext *acx, *iter = NULL;
         while ((acx = JS_ContextIteratorUnlocked(rt, &iter)) != NULL)
             rtStats->runtimeContexts += acx->sizeOfIncludingThis(rtStats->mallocSizeOf);
     }
 
@@ -330,17 +329,18 @@ GetExplicitNonHeapForRuntime(JSRuntime *
 
         // explicit/runtime/regexp-code
         // explicit/runtime/stack-committed
         size_t regexpCode, stackCommitted;
         rt->sizeOfExcludingThis(mallocSizeOf,
                                 NULL,
                                 NULL,
                                 &regexpCode,
-                                &stackCommitted);
+                                &stackCommitted,
+                                NULL);
 
         *amount += regexpCode;
         *amount += stackCommitted;
     }
 
     JS_DestroyContextNoGC(cx);
 
     return true;
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -90,17 +90,17 @@
 #include "jscompartment.h"
 #include "jsobjinlines.h"
 
 using namespace js;
 using namespace js::gc;
 
 void
 JSRuntime::sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf, size_t *normal, size_t *temporary,
-                               size_t *regexpCode, size_t *stackCommitted)
+                               size_t *regexpCode, size_t *stackCommitted, size_t *gcMarkerSize)
 {
     if (normal)
         *normal = mallocSizeOf(dtoaState);
 
     if (temporary)
         *temporary = tempLifoAlloc.sizeOfExcludingThis(mallocSizeOf);
 
     if (regexpCode) {
@@ -108,16 +108,19 @@ JSRuntime::sizeOfExcludingThis(JSMallocS
         if (execAlloc_)
             execAlloc_->sizeOfCode(&method, &regexp, &unused);
         JS_ASSERT(method == 0);     /* this execAlloc is only used for regexp code */
         *regexpCode = regexp + unused;
     }
 
     if (stackCommitted)
         *stackCommitted = stackSpace.sizeOfCommitted();
+
+    if (gcMarkerSize)
+        *gcMarkerSize = gcMarker.sizeOfExcludingThis(mallocSizeOf);
 }
 
 JS_FRIEND_API(void)
 JSRuntime::triggerOperationCallback()
 {
     /*
      * Use JS_ATOMIC_SET in the hope that it ensures the write will become
      * immediately visible to other processors polling the flag.
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -684,17 +684,17 @@ struct JSRuntime : js::RuntimeFriendFiel
     JS_FRIEND_API(void) triggerOperationCallback();
 
     void setJitHardening(bool enabled);
     bool getJitHardening() const {
         return jitHardening;
     }
 
     void sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf, size_t *normal, size_t *temporary,
-                             size_t *regexpCode, size_t *stackCommitted);
+                             size_t *regexpCode, size_t *stackCommitted, size_t *gcMarker);
 
     void purge(JSContext *cx);
 };
 
 /* Common macros to access thread-local caches in JSRuntime. */
 #define JS_PROPERTY_CACHE(cx)   (cx->runtime->propertyCache)
 
 #define JS_KEEP_ATOMS(rt)   (rt)->gcKeepAtoms++;
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -2113,16 +2113,23 @@ GCMarker::appendGrayRoot(void *thing, JS
 
 void
 GCMarker::GrayCallback(JSTracer *trc, void **thingp, JSGCTraceKind kind)
 {
     GCMarker *gcmarker = static_cast<GCMarker *>(trc);
     gcmarker->appendGrayRoot(*thingp, kind);
 }
 
+size_t
+GCMarker::sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf) const
+{
+    return stack.sizeOfExcludingThis(mallocSizeOf) +
+           grayRoots.sizeOfExcludingThis(mallocSizeOf);
+}
+
 void
 SetMarkStackLimit(JSRuntime *rt, size_t limit)
 {
     JS_ASSERT(!rt->gcRunning);
     rt->gcMarker.setSizeLimit(limit);
     for (CompartmentsIter c(rt); !c.done(); c.next())
         c->barrierMarker_.setSizeLimit(limit);
 }
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -1685,16 +1685,24 @@ struct MarkStack {
             if (!newStack)
                 return false;
         }
         stack = newStack;
         tos = stack + tosIndex;
         limit = newStack + newcap;
         return true;
     }
+
+    size_t sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf) const {
+        size_t n = 0;
+        if (stack != ballast)
+            n += mallocSizeOf(stack);
+        n += mallocSizeOf(ballast);
+        return n;
+    }
 };
 
 /*
  * This class records how much work has been done in a given GC slice, so that
  * we can return before pausing for too long. Some slices are allowed to run for
  * unlimited time, and others are bounded. To reduce the number of gettimeofday
  * calls, we only check the time every 1000 operations.
  */
@@ -1822,16 +1830,18 @@ struct GCMarker : public JSTracer {
      */
     bool hasBufferedGrayRoots() const;
     void startBufferingGrayRoots();
     void endBufferingGrayRoots();
     void markBufferedGrayRoots();
 
     static void GrayCallback(JSTracer *trc, void **thing, JSGCTraceKind kind);
 
+    size_t sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf) const;
+
     MarkStack<uintptr_t> stack;
 
   private:
 #ifdef DEBUG
     void checkCompartment(void *p);
 #else
     void checkCompartment(void *p) {}
 #endif
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -1680,16 +1680,21 @@ ReportJSRuntimeExplicitTreeStats(const J
 
     ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/stack-committed"),
                       nsIMemoryReporter::KIND_NONHEAP, rtStats.runtimeStackCommitted,
                       "Memory used for the JS call stack.  This is the committed portion "
                       "of the stack; the uncommitted portion is not measured because it "
                       "hardly costs anything.",
                       callback, closure);
 
+    ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/gc-marker"),
+                      nsIMemoryReporter::KIND_NONHEAP, rtStats.runtimeGCMarker,
+                      "Memory used for the GC mark stack and gray roots.",
+                      callback, closure);
+
     ReportGCHeapBytes(pathPrefix +
                       NS_LITERAL_CSTRING("gc-heap-chunk-dirty-unused"),
                       &gcTotal, rtStats.gcHeapChunkDirtyUnused,
                       "Memory on the garbage-collected JavaScript heap, within chunks with at "
                       "least one allocated GC thing, that could be holding useful data but "
                       "currently isn't.  Memory here is mutually exclusive with memory reported"
                       "under 'explicit/js/gc-heap-decommitted'.",
                       callback, closure);