Bug 1494473 - Using IONFLAGS=bl-ic-stats dump baseline IC statistics on script cleanup r=jandem
authorMatthew Gaudet <mgaudet@mozilla.com>
Fri, 19 Oct 2018 15:33:27 +0000
changeset 490696 4bdddb2c5100121222fef51a89da476fed899b42
parent 490695 2ac1bca7094c959bf382ee37779566056f8792a7
child 490697 23f77dfb5679f3cd4e34250c9511c8a49041a956
push id247
push userfmarier@mozilla.com
push dateSat, 27 Oct 2018 01:06:44 +0000
reviewersjandem
bugs1494473
milestone64.0a1
Bug 1494473 - Using IONFLAGS=bl-ic-stats dump baseline IC statistics on script cleanup r=jandem The output for a particular IC chain looks like this: box2d.js:174:250 (sub) 1009 -> 772 -> (fb) 2 Which is read like this: This sub opcode has two ICs attached. The first IC was entered 1009 times, the second 772 and the fallback stub was hit twice. There are some conclusions we can draw from this (and some we cannot) - We can say with confidence the fallback stub was only hit twice, meaning 99.998% of queries to the IC chain hit in the IC rather than the fallback. - We cannot however say necessarily that the first IC failed to provide a value 771 times. Since new ICs are added at the front, it is possible that there was a phase transition that happened, and the first 771 requests were served by the first IC, followed by a transition to a new type and addition of a new IC, and subsequently 1009 queries were served by the newly added IC. - We can conclude with confidence that there have been at least two different ICs involved in computation across the lifetime of the IC chain, and they are almost equally probable. Though we can't do temporal reasoning with entry counters, we can still do some reasoning. Depends on D8859 Differential Revision: https://phabricator.services.mozilla.com/D8860
js/src/jit/BaselineJIT.cpp
js/src/jit/JitSpewer.cpp
js/src/jit/JitSpewer.h
--- a/js/src/jit/BaselineJIT.cpp
+++ b/js/src/jit/BaselineJIT.cpp
@@ -1162,23 +1162,83 @@ BaselineScript::purgeOptimizedStubs(Zone
         while (stub->next()) {
             MOZ_ASSERT(stub->allocatedInFallbackSpace());
             stub = stub->next();
         }
     }
 #endif
 }
 
+#ifdef JS_JITSPEW
+static bool
+GetStubEnteredCount(ICStub* stub, uint32_t* count)
+{
+    if (stub->isCacheIR_Regular()) {
+        *count = stub->toCacheIR_Regular()->enteredCount();
+        return true;
+    }
+    return false;
+}
+
+static void
+DumpICInfo(JSScript* script)
+{
+    MOZ_ASSERT(script->hasBaselineScript());
+    BaselineScript* blScript = script->baselineScript();
+
+    if (!JitSpewEnabled(JitSpew_BaselineIC_Statistics)) {
+        return;
+    }
+
+    Fprinter& out = JitSpewPrinter();
+
+    const char* filename = script->filename() ? script->filename() : "unknown";
+    out.printf("Dumping IC info for %s:%d\n", filename,
+            PCToLineNumber(script, script->code()));
+
+    for (size_t i = 0; i < blScript->numICEntries(); i++) {
+        ICEntry& entry = blScript->icEntry(i);
+        if (!entry.hasStub()) {
+            continue;
+        }
+
+        unsigned column;
+        jsbytecode* pc = entry.pc(script);
+        unsigned int line = PCToLineNumber(script, pc, &column);
+        out.printf("\t%s:%u:%u (%s) \t", filename, line, column, CodeName[*pc]);
+
+        ICStub* stub = entry.firstStub();
+        while (stub) {
+            uint32_t count;
+            if (GetStubEnteredCount(stub, &count)) {
+                out.printf("%u -> ", count);
+            } else if (stub->isFallback()) {
+                out.printf("(fb) %u", stub->toFallbackStub()->enteredCount());
+            } else {
+                out.printf(" <unknown> -> ");
+            }
+            stub = stub->next();
+        }
+        out.printf("\n");
+    }
+}
+#endif
+
+
 void
 jit::FinishDiscardBaselineScript(FreeOp* fop, JSScript* script)
 {
     if (!script->hasBaselineScript()) {
         return;
     }
 
+#ifdef JS_JITSPEW
+    DumpICInfo(script);
+#endif
+
     if (script->baselineScript()->active()) {
         // Script is live on the stack. Keep the BaselineScript, but destroy
         // stubs allocated in the optimized stub space.
         script->baselineScript()->purgeOptimizedStubs(script->zone());
 
         // Reset |active| flag so that we don't need a separate script
         // iteration to unmark them.
         script->baselineScript()->resetActive();
--- a/js/src/jit/JitSpewer.cpp
+++ b/js/src/jit/JitSpewer.cpp
@@ -471,16 +471,17 @@ jit::CheckLogging()
             "  bl-scripts    Baseline script-compilation\n"
             "  bl-op         Baseline compiler detailed op-specific messages\n"
             "  bl-ic         Baseline inline-cache messages\n"
             "  bl-ic-fb      Baseline IC fallback stub messages\n"
             "  bl-osr        Baseline IC OSR messages\n"
             "  bl-bails      Baseline bailouts\n"
             "  bl-dbg-osr    Baseline debug mode on stack recompile messages\n"
             "  bl-all        All baseline spew\n"
+            "  bl-ic-stats   Baseline IC Statistics\n"
             "\n"
         );
         exit(0);
         /*NOTREACHED*/
     }
     if (ContainsFlag(env, "aborts")) {
         EnableChannel(JitSpew_IonAbort);
     }
@@ -601,16 +602,19 @@ jit::CheckLogging()
         EnableChannel(JitSpew_BaselineOSR);
     }
     if (ContainsFlag(env, "bl-bails")) {
         EnableChannel(JitSpew_BaselineBailouts);
     }
     if (ContainsFlag(env, "bl-dbg-osr")) {
         EnableChannel(JitSpew_BaselineDebugModeOSR);
     }
+    if (ContainsFlag(env, "bl-ic-stats")) {
+        EnableChannel(JitSpew_BaselineIC_Statistics);
+    }
     if (ContainsFlag(env, "bl-all")) {
         EnableChannel(JitSpew_BaselineAbort);
         EnableChannel(JitSpew_BaselineScripts);
         EnableChannel(JitSpew_BaselineOp);
         EnableChannel(JitSpew_BaselineIC);
         EnableChannel(JitSpew_BaselineICFallback);
         EnableChannel(JitSpew_BaselineOSR);
         EnableChannel(JitSpew_BaselineBailouts);
--- a/js/src/jit/JitSpewer.h
+++ b/js/src/jit/JitSpewer.h
@@ -101,17 +101,19 @@ namespace jit {
     _(IonMIR)                               \
     /* Information during bailouts */       \
     _(IonBailouts)                          \
     /* Information during OSI */            \
     _(IonInvalidate)                        \
     /* Debug info about snapshots */        \
     _(IonSnapshots)                         \
     /* Generated inline cache stubs */      \
-    _(IonIC)
+    _(IonIC)                                \
+    /* Baseline IC Statistic information */ \
+    _(BaselineIC_Statistics)
 
 enum JitSpewChannel {
 #define JITSPEW_CHANNEL(name) JitSpew_##name,
     JITSPEW_CHANNEL_LIST(JITSPEW_CHANNEL)
 #undef JITSPEW_CHANNEL
     JitSpew_Terminator
 };