Bug 546477 - add explicit/js/stack memory reporter. r=luke.
authorNicholas Nethercote <nnethercote@mozilla.com>
Thu, 02 Jun 2011 19:40:57 -0700
changeset 71171 bf418b38bfe37cc9fdb7f7455a5d5faaf6bd5f0d
parent 71170 7a8dc72beb430c113aca7c080fc43bf7531370f1
child 71172 85083c2d1f32cbc0ce4a278f640901f8e9cba499
child 111128 e669c8c0755b4b66ea4787c8296124fc519f0598
push id159
push usereakhgari@mozilla.com
push dateTue, 16 Aug 2011 17:53:11 +0000
treeherdermozilla-beta@8786e3e49240 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs546477
milestone6.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 546477 - add explicit/js/stack memory reporter. r=luke.
js/src/vm/Stack.cpp
js/src/vm/Stack.h
js/src/xpconnect/src/xpcjsruntime.cpp
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -151,19 +151,17 @@ StackSegment::computeNextFrame(StackFram
         next = prev;
     return next;
 }
 
 /*****************************************************************************/
 
 StackSpace::StackSpace()
   : base_(NULL),
-#ifdef XP_WIN
     commitEnd_(NULL),
-#endif
     end_(NULL),
     seg_(NULL)
 {
     override_.top = NULL;
 #ifdef DEBUG
     override_.seg = NULL;
     override_.frame = NULL;
 #endif
@@ -183,24 +181,24 @@ StackSpace::init()
     base_ = reinterpret_cast<Value *>(p);
     commitEnd_ = base_ + COMMIT_VALS;
     end_ = base_ + CAPACITY_VALS;
 #elif defined(XP_OS2)
     if (DosAllocMem(&p, CAPACITY_BYTES, PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_ANY) &&
         DosAllocMem(&p, CAPACITY_BYTES, PAG_COMMIT | PAG_READ | PAG_WRITE))
         return false;
     base_ = reinterpret_cast<Value *>(p);
-    end_ = base_ + CAPACITY_VALS;
+    end_ = commitEnd_ = base_ + CAPACITY_VALS;
 #else
     JS_ASSERT(CAPACITY_BYTES % getpagesize() == 0);
     p = mmap(NULL, CAPACITY_BYTES, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
     if (p == MAP_FAILED)
         return false;
     base_ = reinterpret_cast<Value *>(p);
-    end_ = base_ + CAPACITY_VALS;
+    end_ = commitEnd_ = base_ + CAPACITY_VALS;
 #endif
     return true;
 }
 
 StackSpace::~StackSpace()
 {
     JS_ASSERT(!seg_);
     if (!base_)
@@ -351,16 +349,22 @@ StackSpace::popSegment()
 void
 StackSpace::pushSegment(StackSegment &seg)
 {
     JS_ASSERT(seg.empty());
     seg.setPreviousInMemory(seg_);
     seg_ = &seg;
 }
 
+size_t
+StackSpace::committedSize()
+{
+    return (commitEnd_ - base_) * sizeof(Value);
+}
+
 /*****************************************************************************/
 
 ContextStack::ContextStack(JSContext *cx)
   : regs_(NULL),
     seg_(NULL),
     space_(&JS_THREAD_DATA(cx)->stackSpace),
     cx_(cx)
 {
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -1041,20 +1041,18 @@ struct StackOverride
 #endif
 };
 
 /*****************************************************************************/
 
 class StackSpace
 {
     Value         *base_;
-#ifdef XP_WIN
     mutable Value *commitEnd_;
-#endif
-    Value *end_;
+    Value         *end_;
     StackSegment  *seg_;
     StackOverride override_;
 
     static const size_t CAPACITY_VALS  = 512 * 1024;
     static const size_t CAPACITY_BYTES = CAPACITY_VALS * sizeof(Value);
     static const size_t COMMIT_VALS    = 16 * 1024;
     static const size_t COMMIT_BYTES   = COMMIT_VALS * sizeof(Value);
 
@@ -1119,16 +1117,19 @@ class StackSpace
      * does indeed have this required space and reports an error and returns
      * NULL if this reserve space cannot be allocated.
      */
     inline Value *getStackLimit(JSContext *cx);
     bool tryBumpLimit(JSContext *maybecx, Value *from, uintN nvals, Value **limit);
 
     /* Called during GC: mark segments, frames, and slots under firstUnused. */
     void mark(JSTracer *trc);
+
+    /* We only report the committed size;  uncommitted size is uninteresting. */
+    JS_FRIEND_API(size_t) committedSize();
 };
 
 /*****************************************************************************/
 
 class ContextStack
 {
     FrameRegs *regs_;
     StackSegment *seg_;
--- a/js/src/xpconnect/src/xpcjsruntime.cpp
+++ b/js/src/xpconnect/src/xpcjsruntime.cpp
@@ -1281,16 +1281,35 @@ GetPerCompartmentSize(PRInt64 (*f)(JSCom
     JSRuntime *rt = nsXPConnect::GetRuntimeInstance()->GetJSRuntime();
     js::AutoLockGC lock(rt);
     PRInt64 n = 0;
     for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); ++c)
         n += f(*c);
     return n;
 }
 
+static PRInt64
+GetJSStack(void *data)
+{
+    JSRuntime *rt = nsXPConnect::GetRuntimeInstance()->GetJSRuntime();
+    PRInt64 n = 0;
+    for (js::ThreadDataIter i(rt); !i.empty(); i.popFront())
+        n += i.threadData()->stackSpace.committedSize();
+    return n;
+}
+
+NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSStack,
+    "explicit/js/stack",
+    MR_MAPPED,
+    "Memory used for the JavaScript stack.  This is the committed portion "
+    "of the stack;  any uncommitted portion is not measured because it "
+    "hardly costs anything.",
+    GetJSStack,
+    NULL)
+
 #ifdef JS_METHODJIT
 
 static PRInt64
 GetCompartmentMjitCodeSize(JSCompartment *c)
 {
     return c->getMjitCodeSize();
 }
 
@@ -1453,16 +1472,17 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* 
         if (!mWatchdogWakeup)
             NS_RUNTIMEABORT("JS_NEW_CONDVAR failed.");
 
         mJSRuntime->setActivityCallback(ActivityCallback, this);
 
         mJSRuntime->setCustomGCChunkAllocator(&gXPCJSChunkAllocator);
 
         NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSGCHeap));
+        NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSStack));
 #ifdef JS_METHODJIT
         NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSMjitCode));
         NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSMjitData));
 #endif
 #ifdef JS_TRACER
         NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSTjitCode));
         NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSTjitDataAllocatorsMain));
         NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSTjitDataAllocatorsReserve));