Bug 720219 (part 4) - Clean up JS script measurement. r=bhackett.
authorNicholas Nethercote <nnethercote@mozilla.com>
Mon, 23 Jan 2012 15:39:39 -0800
changeset 86551 a6849eb97d824cdc6731de769c369f2cadf6204e
parent 86550 4af91c6b9316ec670db4510a5cd38e9d0f81f6aa
child 86552 27583d9d31b4a1341207a44b24254cf69369b98b
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)
reviewersbhackett
bugs720219
milestone12.0a1
Bug 720219 (part 4) - Clean up JS script measurement. r=bhackett.
js/src/MemoryMetrics.cpp
js/src/jit-test/tests/basic/bug684796.js
js/src/jsscript.cpp
js/src/jsscript.h
js/src/methodjit/Compiler.cpp
js/src/methodjit/MethodJIT.cpp
js/src/methodjit/MethodJIT.h
js/src/shell/js.cpp
--- a/js/src/MemoryMetrics.cpp
+++ b/js/src/MemoryMetrics.cpp
@@ -163,19 +163,19 @@ CellCallback(JSContext *cx, void *vdata,
     {
         curr->gcHeapShapesBase += thingSize;
         break;
     }
     case JSTRACE_SCRIPT:
     {
         JSScript *script = static_cast<JSScript *>(thing);
         curr->gcHeapScripts += thingSize;
-        curr->scriptData += script->dataSize(data->mallocSizeOf);
+        curr->scriptData += script->sizeOfData(data->mallocSizeOf);
 #ifdef JS_METHODJIT
-        curr->mjitData += script->jitDataSize(data->mallocSizeOf);
+        curr->mjitData += script->sizeOfJitScripts(data->mallocSizeOf);
 #endif
         break;
     }
     case JSTRACE_TYPE_OBJECT:
     {
         types::TypeObject *obj = static_cast<types::TypeObject *>(thing);
         curr->gcHeapTypeObjects += thingSize;
         SizeOfObjectTypeInferenceData(obj, &curr->typeInferenceMemory,
deleted file mode 100644
--- a/js/src/jit-test/tests/basic/bug684796.js
+++ /dev/null
@@ -1,2 +0,0 @@
-if (typeof mjitdatastats == "function")
-    mjitdatastats();
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -1262,37 +1262,37 @@ JSScript::NewScriptFromEmitter(JSContext
 
     if (cx->hasRunOption(JSOPTION_PCCOUNT))
         (void) script->initCounts(cx);
 
     return script;
 }
 
 size_t
-JSScript::dataSize()
+JSScript::computedSizeOfData()
 {
 #if JS_SCRIPT_INLINE_DATA_LIMIT
     if (data == inlineData)
         return 0;
 #endif
 
     uint8_t *dataEnd = code + length * sizeof(jsbytecode) + numNotes() * sizeof(jssrcnote);
     JS_ASSERT(dataEnd >= data);
     return dataEnd - data;
 }
 
 size_t
-JSScript::dataSize(JSMallocSizeOfFun mallocSizeOf)
+JSScript::sizeOfData(JSMallocSizeOfFun mallocSizeOf)
 {
 #if JS_SCRIPT_INLINE_DATA_LIMIT
     if (data == inlineData)
         return 0;
 #endif
 
-    return mallocSizeOf(data, dataSize());
+    return mallocSizeOf(data, computedSizeOfData());
 }
 
 /*
  * 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()
@@ -1365,17 +1365,17 @@ JSScript::finalize(JSContext *cx, bool b
         }
         cx->free_(debug);
     }
 
 #if JS_SCRIPT_INLINE_DATA_LIMIT
     if (data != inlineData)
 #endif
     {
-        JS_POISON(data, 0xdb, dataSize());
+        JS_POISON(data, 0xdb, computedSizeOfData());
         cx->free_(data);
     }
 }
 
 namespace js {
 
 static const uint32_t GSN_CACHE_THRESHOLD = 100;
 static const uint32_t GSN_CACHE_MAP_INIT_SIZE = 20;
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -633,17 +633,17 @@ struct JSScript : public js::gc::Cell {
     }
 
     size_t getUseCount() const  { return useCount; }
     size_t incUseCount() { return ++useCount; }
     size_t *addressOfUseCount() { return &useCount; }
     void resetUseCount() { useCount = 0; }
 
     /* Size of the JITScript and all sections.  (This method is implemented in MethodJIT.cpp.) */
-    size_t jitDataSize(JSMallocSizeOfFun mallocSizeOf);
+    size_t sizeOfJitScripts(JSMallocSizeOfFun mallocSizeOf);
 
 #endif
 
     /* Counter accessors. */
     js::OpcodeCounts getCounts(jsbytecode *pc) {
         JS_ASSERT(size_t(pc - code) < length);
         return pcCounters.counts[pc - code];
     }
@@ -651,22 +651,23 @@ struct JSScript : public js::gc::Cell {
     bool initCounts(JSContext *cx);
     void destroyCounts(JSContext *cx);
 
     jsbytecode *main() {
         return code + mainOffset;
     }
 
     /*
-     * The first dataSize() is the in-use size of all the data sections, the
-     * second is the size of the block allocated to hold all the data sections
+     * computedSizeOfData() is the in-use size of all the data sections. 
+     * sizeOfData() is the size of the block allocated to hold all the data sections
      * (which can be larger than the in-use size).
      */
-    JS_FRIEND_API(size_t) dataSize();                               /* Size of all data sections */
-    JS_FRIEND_API(size_t) dataSize(JSMallocSizeOfFun mallocSizeOf); /* Size of all data sections */
+    size_t computedSizeOfData();
+    size_t sizeOfData(JSMallocSizeOfFun mallocSizeOf);
+
     uint32_t numNotes();  /* Number of srcnote slots in the srcnotes section */
 
     /* Script notes are allocated right after the code. */
     jssrcnote *notes() { return (jssrcnote *)(code + length); }
 
     static const uint8_t INVALID_OFFSET = 0xFF;
     static bool isValidOffset(uint8_t offset) { return offset != INVALID_OFFSET; }
 
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -1329,17 +1329,17 @@ mjit::Compiler::finishThisUp()
 
     size_t nNmapLive = loopEntries.length();
     for (size_t i = outerChunk.begin; i < outerChunk.end; i++) {
         Bytecode *opinfo = analysis->maybeCode(i);
         if (opinfo && opinfo->safePoint)
             nNmapLive++;
     }
 
-    /* Please keep in sync with JITChunk::scriptDataSize! */
+    /* Please keep in sync with JITChunk::sizeOfIncludingThis! */
     size_t dataSize = sizeof(JITChunk) +
                       sizeof(NativeMapEntry) * nNmapLive +
                       sizeof(InlineFrame) * inlineFrames.length() +
                       sizeof(CallSite) * callSites.length() +
 #if defined JS_MONOIC
                       sizeof(ic::GetGlobalNameIC) * getGlobalNames.length() +
                       sizeof(ic::SetGlobalNameIC) * setGlobalNames.length() +
                       sizeof(ic::CallICInfo) * callICs.length() +
@@ -1721,18 +1721,18 @@ mjit::Compiler::finishThisUp()
                 jitPics[i].u.get.typeCheckOffset = distance;
             }
         }
         stubCode.patch(pics[i].paramAddr, &jitPics[i]);
     }
 #endif
 
     JS_ASSERT(size_t(cursor - (uint8_t*)chunk) == dataSize);
-    /* Pass in NULL here -- we don't want slop bytes to be counted. */
-    JS_ASSERT(chunk->scriptDataSize(NULL) == dataSize);
+    /* Use the computed size here -- we don't want slop bytes to be counted. */
+    JS_ASSERT(chunk->computedSizeOfIncludingThis() == dataSize);
 
     /* Link fast and slow paths together. */
     stubcc.fixCrossJumps(result, masm.size(), masm.size() + stubcc.size());
 
 #if defined(JS_CPU_MIPS)
     /* Make sure doubleOffset is aligned to sizeof(double) bytes.  */ 
     size_t doubleOffset = (((size_t)result + masm.size() + stubcc.size() +
                             sizeof(double) - 1) & (~(sizeof(double) - 1))) -
--- a/js/src/methodjit/MethodJIT.cpp
+++ b/js/src/methodjit/MethodJIT.cpp
@@ -1357,64 +1357,68 @@ JITScript::destroyChunk(JSContext *cx, u
             repatch.repatch(ic->funGuard, NULL);
             repatch.relink(ic->funJump, ic->slowPathStart);
             ic->purgeGuardedObject();
         }
     }
 }
 
 size_t
-JSScript::jitDataSize(JSMallocSizeOfFun mallocSizeOf)
+JSScript::sizeOfJitScripts(JSMallocSizeOfFun mallocSizeOf)
 {
     size_t n = 0;
     if (jitNormal)
-        n += jitNormal->scriptDataSize(mallocSizeOf); 
+        n += jitNormal->sizeOfIncludingThis(mallocSizeOf); 
     if (jitCtor)
-        n += jitCtor->scriptDataSize(mallocSizeOf); 
+        n += jitCtor->sizeOfIncludingThis(mallocSizeOf); 
     return n;
 }
 
 size_t
-mjit::JITScript::scriptDataSize(JSMallocSizeOfFun mallocSizeOf)
+mjit::JITScript::sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf)
 {
-    size_t usable = mallocSizeOf(this,
-                                 sizeof(JITScript)
-                                 + (nchunks * sizeof(ChunkDescriptor))
-                                 + (nedges * sizeof(CrossChunkEdge)));
+    size_t computedSize = sizeof(JITScript) +
+                          (nchunks * sizeof(ChunkDescriptor)) +
+                          (nedges * sizeof(CrossChunkEdge));
+    size_t n = mallocSizeOf(this, computedSize);
     for (unsigned i = 0; i < nchunks; i++) {
         const ChunkDescriptor &desc = chunkDescriptor(i);
         if (desc.chunk)
-            usable += desc.chunk->scriptDataSize(mallocSizeOf);
+            n += desc.chunk->sizeOfIncludingThis(mallocSizeOf);
     }
-    return usable;
+    return n;
 }
 
 /* Please keep in sync with Compiler::finishThisUp! */
 size_t
-mjit::JITChunk::scriptDataSize(JSMallocSizeOfFun mallocSizeOf)
+mjit::JITChunk::computedSizeOfIncludingThis()
 {
-    size_t computedSize =
-        sizeof(JITChunk) +
-        sizeof(NativeMapEntry) * nNmapPairs +
-        sizeof(InlineFrame) * nInlineFrames +
-        sizeof(CallSite) * nCallSites +
+    return sizeof(JITChunk) +
+           sizeof(NativeMapEntry) * nNmapPairs +
+           sizeof(InlineFrame) * nInlineFrames +
+           sizeof(CallSite) * nCallSites +
 #if defined JS_MONOIC
-        sizeof(ic::GetGlobalNameIC) * nGetGlobalNames +
-        sizeof(ic::SetGlobalNameIC) * nSetGlobalNames +
-        sizeof(ic::CallICInfo) * nCallICs +
-        sizeof(ic::EqualityICInfo) * nEqualityICs +
+           sizeof(ic::GetGlobalNameIC) * nGetGlobalNames +
+           sizeof(ic::SetGlobalNameIC) * nSetGlobalNames +
+           sizeof(ic::CallICInfo) * nCallICs +
+           sizeof(ic::EqualityICInfo) * nEqualityICs +
 #endif
 #if defined JS_POLYIC
-        sizeof(ic::PICInfo) * nPICs +
-        sizeof(ic::GetElementIC) * nGetElems +
-        sizeof(ic::SetElementIC) * nSetElems +
+           sizeof(ic::PICInfo) * nPICs +
+           sizeof(ic::GetElementIC) * nGetElems +
+           sizeof(ic::SetElementIC) * nSetElems +
 #endif
-        0;
-    /* |mallocSizeOf| can be null here. */
-    return mallocSizeOf ? mallocSizeOf(this, computedSize) : computedSize;
+           0;
+}
+
+/* Please keep in sync with Compiler::finishThisUp! */
+size_t
+mjit::JITChunk::sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf)
+{
+    return mallocSizeOf(this, computedSizeOfIncludingThis());
 }
 
 void
 mjit::ReleaseScriptCode(JSContext *cx, JSScript *script, bool construct)
 {
     // NB: The recompiler may call ReleaseScriptCode, in which case it
     // will get called again when the script is destroyed, so we
     // must protect against calling ReleaseScriptCode twice.
--- a/js/src/methodjit/MethodJIT.h
+++ b/js/src/methodjit/MethodJIT.h
@@ -714,18 +714,18 @@ struct JITChunk
     bool isValidCode(void *ptr) {
         char *jitcode = (char *)code.m_code.executableAddress();
         char *jcheck = (char *)ptr;
         return jcheck >= jitcode && jcheck < jitcode + code.m_size;
     }
 
     void nukeScriptDependentICs();
 
-    /* |mallocSizeOf| can be NULL here, in which case the fallback size computation will be used. */
-    size_t scriptDataSize(JSMallocSizeOfFun mallocSizeOf);
+    size_t computedSizeOfIncludingThis();
+    size_t sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf);
 
     ~JITChunk();
 
   private:
     /* Helpers used to navigate the variable-length sections. */
     char *commonSectionLimit() const;
     char *monoICSectionsLimit() const;
     char *polyICSectionsLimit() const;
@@ -837,17 +837,17 @@ struct JITScript
         return (CrossChunkEdge *) (&chunkDescriptor(0) + nchunks);
     }
 
     /* Patch any compiled sources in edge to jump to label. */
     void patchEdge(const CrossChunkEdge &edge, void *label);
 
     jsbytecode *nativeToPC(void *returnAddress, CallSite **pinline);
 
-    size_t scriptDataSize(JSMallocSizeOfFun mallocSizeOf);
+    size_t sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf);
 
     void destroy(JSContext *cx);
     void destroyChunk(JSContext *cx, unsigned chunkIndex, bool resetUses = true);
 };
 
 /*
  * Execute the given mjit code. This is a low-level call and callers must
  * provide the same guarantees as JaegerShot/CheckStackAndEnterMethodJIT.
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -3808,53 +3808,16 @@ MJitCodeStats(JSContext *cx, uintN argc,
     }
     JS_SET_RVAL(cx, vp, INT_TO_JSVAL(n));
 #else
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
 #endif
     return true;
 }
 
-#ifdef JS_METHODJIT
-
-static size_t
-computedSize(const void *p, size_t size)
-{
-    return size;
-}
-
-static void
-SumJitDataSizeCallback(JSContext *cx, void *data, void *thing,
-                       JSGCTraceKind traceKind, size_t thingSize)
-{
-    size_t *sump = static_cast<size_t *>(data);
-    JS_ASSERT(traceKind == JSTRACE_SCRIPT);
-    JSScript *script = static_cast<JSScript *>(thing);
-    /*
-     * Passing in |computedSize| causes jitDataSize to fall back to its
-     * secondary size computation.
-     */
-    *sump += script->jitDataSize(computedSize);
-}
-
-#endif
-
-JSBool
-MJitDataStats(JSContext *cx, uintN argc, jsval *vp)
-{
-#ifdef JS_METHODJIT
-    size_t n = 0;
-    IterateCells(cx, NULL, gc::FINALIZE_SCRIPT, &n, SumJitDataSizeCallback);
-    JS_SET_RVAL(cx, vp, INT_TO_JSVAL(n));
-#else
-    JS_SET_RVAL(cx, vp, JSVAL_VOID);
-#endif
-    return true;
-}
-
 JSBool
 MJitChunkLimit(JSContext *cx, uintN argc, jsval *vp)
 {
     if (argc > 1) {
         JS_ReportError(cx, "Wrong number of arguments");
         return JS_FALSE;
     }
 
@@ -4036,17 +3999,16 @@ static JSFunctionSpec shell_functions[] 
     JS_FN("timeout",        Timeout,        1,0),
     JS_FN("elapsed",        Elapsed,        0,0),
     JS_FN("parent",         Parent,         1,0),
     JS_FN("wrap",           Wrap,           1,0),
     JS_FN("serialize",      Serialize,      1,0),
     JS_FN("deserialize",    Deserialize,    1,0),
 #ifdef JS_METHODJIT
     JS_FN("mjitcodestats",  MJitCodeStats,  0,0),
-    JS_FN("mjitdatastats",  MJitDataStats,  0,0),
 #endif
     JS_FN("mjitChunkLimit", MJitChunkLimit, 1,0),
     JS_FN("stringstats",    StringStats,    0,0),
     JS_FN("newGlobal",      NewGlobal,      1,0),
     JS_FN("parseLegacyJSON",ParseLegacyJSON,1,0),
     JS_FN("enableStackWalkingAssertion",EnableStackWalkingAssertion,1,0),
     JS_FN("getMaxArgs",     GetMaxArgs,     0,0),
     JS_FN("terminate",      Terminate,      0,0),
@@ -4184,17 +4146,16 @@ static const char *const shell_help_mess
 "  A negative value (default) means that the execution time is unlimited.",
 "elapsed()                Execution time elapsed for the current context.",
 "parent(obj)              Returns the parent of obj.",
 "wrap(obj)                Wrap an object into a noop wrapper.",
 "serialize(sd)            Serialize sd using JS_WriteStructuredClone. Returns a TypedArray.",
 "deserialize(a)           Deserialize data generated by serialize.",
 #ifdef JS_METHODJIT
 "mjitcodestats()          Return stats on mjit code memory usage.",
-"mjitdatastats()          Return stats on mjit data memory usage.",
 #endif
 "mjitChunkLimit(N)        Specify limit on compiled chunk size during mjit compilation.",
 "stringstats()            Return stats on string memory usage.",
 "newGlobal(kind)          Return a new global object, in the current\n"
 "                         compartment if kind === 'same-compartment' or in a\n"
 "                         new compartment if kind === 'new-compartment'",
 "parseLegacyJSON(str)     Parse str as legacy JSON, returning the result if the\n"
 "                         parse succeeded and throwing a SyntaxError if not.",