Bug 617904 - Reset profile info in methodjit when tracejit is flushed (r=dmandelin)
authorBill McCloskey <wmccloskey@mozilla.com>
Wed, 12 Jan 2011 10:09:48 -0800
changeset 60567 4f71ecca94fe1c220de703e52aa6ca78b05eab45
parent 60566 1e5925b72c513e2c5e4643b6174930f7ad531112
child 60568 d1adb7b245bdeebc6167f0e068e0366d1e3d0da6
push id18037
push usercleary@mozilla.com
push dateFri, 14 Jan 2011 17:42:55 +0000
treeherdermozilla-central@4e0501a0c5e5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdmandelin
bugs617904
milestone2.0b10pre
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 617904 - Reset profile info in methodjit when tracejit is flushed (r=dmandelin)
js/src/jstracer.cpp
js/src/methodjit/InvokeHelpers.cpp
js/src/methodjit/MethodJIT.h
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -1411,17 +1411,17 @@ static void
 Unblacklist(JSScript *script, jsbytecode *pc)
 {
     JS_ASSERT(*pc == JSOP_NOTRACE || *pc == JSOP_TRACE);
     if (*pc == JSOP_NOTRACE) {
         *pc = JSOP_TRACE;
 
 #ifdef JS_METHODJIT
         /* This code takes care of unblacklisting in the method JIT. */
-        js::mjit::EnableTraceHint(script, pc, GET_UINT16(pc));
+        js::mjit::ResetTraceHint(script, pc, GET_UINT16(pc), false);
 #endif
     }
 }
 
 static bool
 IsBlacklisted(jsbytecode* pc)
 {
     if (*pc == JSOP_NOTRACE)
@@ -2740,16 +2740,27 @@ TraceMonitor::flush()
 
     verbose_only(
         for (Seq<Fragment*>* f = branches; f; f = f->tail)
             FragProfiling_FragFinalizer(f->head, this);
     )
 
     flushEpoch++;
 
+#ifdef JS_METHODJIT
+    if (loopProfiles) {
+        for (LoopProfileMap::Enum e(*loopProfiles); !e.empty(); e.popFront()) {
+            jsbytecode *pc = e.front().key;
+            LoopProfile *prof = e.front().value;
+            /* This code takes care of resetting all methodjit state. */
+            js::mjit::ResetTraceHint(prof->entryScript, pc, GET_UINT16(pc), true);
+        }
+    }
+#endif
+
     frameCache->reset();
     dataAlloc->reset();
     traceAlloc->reset();
     codeAlloc->reset();
     tempAlloc->reset();
     oracle->clear();
     loopProfiles->clear();
 
@@ -7794,16 +7805,21 @@ PurgeScriptFragments(TraceMonitor* tm, J
 {
     debug_only_printf(LC_TMTracer,
                       "Purging fragments for JSScript %p.\n", (void*)script);
 
     /* A recorder script is being evaluated and can not be destroyed or GC-ed. */
     JS_ASSERT_IF(tm->recorder, 
                  JS_UPTRDIFF(tm->recorder->getTree()->ip, script->code) >= script->length);
 
+    for (LoopProfileMap::Enum e(*tm->loopProfiles); !e.empty(); e.popFront()) {
+        if (JS_UPTRDIFF(e.front().key, script->code) < script->length)
+            e.removeFront();
+    }
+
     TracedScriptSet::Ptr found = tm->tracedScripts.lookup(script);
     if (!found)
         return;
     tm->tracedScripts.remove(found);
 
     for (size_t i = 0; i < FRAGMENT_TABLE_SIZE; ++i) {
         TreeFragment** fragp = &tm->vmfragments[i];
         while (TreeFragment* frag = *fragp) {
@@ -7822,21 +7838,16 @@ PurgeScriptFragments(TraceMonitor* tm, J
                     TrashTree(frag);
                 } while ((frag = frag->peer) != NULL);
                 continue;
             }
             fragp = &frag->next;
         }
     }
 
-    for (LoopProfileMap::Enum e(*tm->loopProfiles); !e.empty(); e.popFront()) {
-        if (JS_UPTRDIFF(e.front().key, script->code) < script->length)
-            e.removeFront();
-    }
-
     RecordAttemptMap &table = *tm->recordAttempts;
     for (RecordAttemptMap::Enum e(table); !e.empty(); e.popFront()) {
         if (JS_UPTRDIFF(e.front().key, script->code) < script->length)
             e.removeFront();
     }
 }
 
 bool
--- a/js/src/methodjit/InvokeHelpers.cpp
+++ b/js/src/methodjit/InvokeHelpers.cpp
@@ -912,62 +912,69 @@ UpdateTraceHintSingle(Repatcher &repatch
      */
     repatcher.relink(jump, target);
 
     JaegerSpew(JSpew_PICs, "relinking trace hint %p to %p\n",
                jump.executableAddress(), target.executableAddress());
 }
 
 static void
-DisableTraceHint(VMFrame &f, ic::TraceICInfo &tic)
+DisableTraceHint(VMFrame &f, ic::TraceICInfo &ic)
 {
     Repatcher repatcher(f.jit());
-    UpdateTraceHintSingle(repatcher, tic.traceHint, tic.jumpTarget);
+    UpdateTraceHintSingle(repatcher, ic.traceHint, ic.jumpTarget);
 
-    if (tic.hasSlowTraceHint)
-        UpdateTraceHintSingle(repatcher, tic.slowTraceHint, tic.jumpTarget);
+    if (ic.hasSlowTraceHint)
+        UpdateTraceHintSingle(repatcher, ic.slowTraceHint, ic.jumpTarget);
 }
 
 static void
-EnableTraceHintAt(JSScript *script, js::mjit::JITScript *jit, jsbytecode *pc, uint16_t index)
+ResetTraceHintAt(JSScript *script, js::mjit::JITScript *jit,
+                 jsbytecode *pc, uint16_t index, bool full)
 {
     if (index >= jit->nTraceICs)
         return;
-    ic::TraceICInfo &tic = jit->traceICs[index];
-    if (!tic.initialized)
+    ic::TraceICInfo &ic = jit->traceICs[index];
+    if (!ic.initialized)
         return;
     
-    JS_ASSERT(tic.jumpTargetPC == pc);
+    JS_ASSERT(ic.jumpTargetPC == pc);
 
     JaegerSpew(JSpew_PICs, "Enabling trace IC %u in script %p\n", index, script);
 
     Repatcher repatcher(jit);
 
-    UpdateTraceHintSingle(repatcher, tic.traceHint, tic.stubEntry);
+    UpdateTraceHintSingle(repatcher, ic.traceHint, ic.stubEntry);
+
+    if (ic.hasSlowTraceHint)
+        UpdateTraceHintSingle(repatcher, ic.slowTraceHint, ic.stubEntry);
 
-    if (tic.hasSlowTraceHint)
-        UpdateTraceHintSingle(repatcher, tic.slowTraceHint, tic.stubEntry);
+    if (full) {
+        ic.traceData = NULL;
+        ic.loopCounterStart = 1;
+        ic.loopCounter = ic.loopCounterStart;
+    }
 }
 #endif
 
 void
-js::mjit::EnableTraceHint(JSScript *script, jsbytecode *pc, uint16_t index)
+js::mjit::ResetTraceHint(JSScript *script, jsbytecode *pc, uint16_t index, bool full)
 {
 #if JS_MONOIC
     if (script->jitNormal)
-        EnableTraceHintAt(script, script->jitNormal, pc, index);
+        ResetTraceHintAt(script, script->jitNormal, pc, index, full);
 
     if (script->jitCtor)
-        EnableTraceHintAt(script, script->jitCtor, pc, index);
+        ResetTraceHintAt(script, script->jitCtor, pc, index, full);
 #endif
 }
 
 #if JS_MONOIC
 void *
-RunTracer(VMFrame &f, ic::TraceICInfo &tic)
+RunTracer(VMFrame &f, ic::TraceICInfo &ic)
 #else
 void *
 RunTracer(VMFrame &f)
 #endif
 {
     JSContext *cx = f.cx;
     JSStackFrame *entryFrame = f.fp();
     TracePointAction tpa;
@@ -988,35 +995,35 @@ RunTracer(VMFrame &f)
 
     bool blacklist;
     uintN inlineCallCount = 0;
     void **traceData;
     uintN *traceEpoch;
     uint32 *loopCounter;
     uint32 hits;
 #if JS_MONOIC
-    traceData = &tic.traceData;
-    traceEpoch = &tic.traceEpoch;
-    loopCounter = &tic.loopCounter;
+    traceData = &ic.traceData;
+    traceEpoch = &ic.traceEpoch;
+    loopCounter = &ic.loopCounter;
     *loopCounter = 1;
-    hits = tic.loopCounterStart;
+    hits = ic.loopCounterStart;
 #else
     traceData = NULL;
     traceEpoch = NULL;
     loopCounter = NULL;
     hits = 1;
 #endif
     tpa = MonitorTracePoint(f.cx, inlineCallCount, &blacklist, traceData, traceEpoch,
                             loopCounter, hits);
     JS_ASSERT(!TRACE_RECORDER(cx));
 
 #if JS_MONOIC
-    tic.loopCounterStart = *loopCounter;
+    ic.loopCounterStart = *loopCounter;
     if (blacklist)
-        DisableTraceHint(f, tic);
+        DisableTraceHint(f, ic);
 #endif
 
     // Even though ExecuteTree() bypasses the interpreter, it should propagate
     // error failures correctly.
     JS_ASSERT_IF(cx->isExceptionPending(), tpa == TPA_Error);
 
 	f.fp() = cx->fp();
     JS_ASSERT(f.fp() == cx->fp());
@@ -1089,19 +1096,19 @@ RunTracer(VMFrame &f)
     goto restart;
 }
 
 #endif /* JS_TRACER */
 
 #if defined JS_TRACER
 # if defined JS_MONOIC
 void *JS_FASTCALL
-stubs::InvokeTracer(VMFrame &f, ic::TraceICInfo *tic)
+stubs::InvokeTracer(VMFrame &f, ic::TraceICInfo *ic)
 {
-    return RunTracer(f, *tic);
+    return RunTracer(f, *ic);
 }
 
 # else
 
 void *JS_FASTCALL
 stubs::InvokeTracer(VMFrame &f)
 {
     return RunTracer(f);
--- a/js/src/methodjit/MethodJIT.h
+++ b/js/src/methodjit/MethodJIT.h
@@ -419,19 +419,22 @@ struct CallSite
         this->id = id;
     }
 
     bool isTrap() const {
         return id == MAGIC_TRAP_ID;
     }
 };
 
-/* Re-enables a tracepoint in the method JIT. */
+/*
+ * Re-enables a tracepoint in the method JIT. When full is true, we
+ * also reset the iteration counter.
+ */
 void
-EnableTraceHint(JSScript *script, jsbytecode *pc, uint16_t index);
+ResetTraceHint(JSScript *script, jsbytecode *pc, uint16_t index, bool full);
 
 uintN
 GetCallTargetCount(JSScript *script, jsbytecode *pc);
 
 inline void * bsearch_nmap(NativeMapEntry *nmap, size_t nPairs, size_t bcOff)
 {
     size_t lo = 1, hi = nPairs;
     while (1) {