Bug 1417961 - Fix Baseline debug mode OSR to delazify type monitor chains correctly. r=tcampbell, a=gchang
authorJan de Mooij <jdemooij@mozilla.com>
Thu, 30 Nov 2017 15:53:38 +0100
changeset 442683 43f74013ae081e9b5a84cdc6c087d4e206af068b
parent 442682 d23f5b4bf54978803f0c4b5312b00b209d12b55d
child 442684 503237c7de504e66df56ec3c16e2d8e262e11122
push id8299
push userryanvm@gmail.com
push dateSun, 03 Dec 2017 18:46:48 +0000
treeherdermozilla-beta@43f74013ae08 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstcampbell, gchang
bugs1417961
milestone58.0
Bug 1417961 - Fix Baseline debug mode OSR to delazify type monitor chains correctly. r=tcampbell, a=gchang
js/src/jit-test/tests/debug/bug1417961.js
js/src/jit/BaselineDebugModeOSR.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/bug1417961.js
@@ -0,0 +1,31 @@
+var evalInFrame = (function evalInFrame(global) {
+    var dbgGlobal = newGlobal();
+    var dbg = new dbgGlobal.Debugger();
+    return function evalInFrame(upCount, code) {
+	dbg.addDebuggee(global);
+	var frame = dbg.getNewestFrame().older;
+	for (var i = 0; i < upCount; i++)
+	    frame = frame.older;
+	var completion = frame.eval(code);
+	if (completion.throw)
+	    throw 1;
+    };
+})(this);
+function f() {
+    for (var i = 0; i < 10; - i)
+	g();
+}
+function h() {
+    evalInFrame(0, "a.push(1)");
+    evalInFrame(1, "a.push(2)");
+}
+function g() {
+    h();
+}
+try {
+    f();
+} catch(e) {}
+var a = [];
+for (var i = 0; i < 3; i++)
+    g();
+assertEq(a.length, 6);
--- a/js/src/jit/BaselineDebugModeOSR.cpp
+++ b/js/src/jit/BaselineDebugModeOSR.cpp
@@ -727,16 +727,31 @@ CloneOldBaselineStub(JSContext* cx, Debu
         // stub to nullptr as we will never return to this stub frame anyway.
         entry.newStub = nullptr;
         return true;
     }
 
     // Get the new fallback stub from the recompiled baseline script.
     ICFallbackStub* fallbackStub = entry.fallbackStub();
 
+    // Some stubs are monitored, get the first stub in the monitor chain from
+    // the new fallback stub if so. We do this before checking for fallback
+    // stubs below, to ensure monitored fallback stubs have a type monitor
+    // chain.
+    ICStub* firstMonitorStub;
+    if (fallbackStub->isMonitoredFallback()) {
+        ICMonitoredFallbackStub* monitored = fallbackStub->toMonitoredFallbackStub();
+        ICTypeMonitor_Fallback* fallback = monitored->getFallbackMonitorStub(cx, entry.script);
+        if (!fallback)
+            return false;
+        firstMonitorStub = fallback->firstMonitorStub();
+    } else {
+        firstMonitorStub = nullptr;
+    }
+
     // We don't need to clone fallback stubs, as they are guaranteed to
     // exist. Furthermore, their JitCode is cached and should be the same even
     // across the recompile.
     if (oldStub->isFallback()) {
         MOZ_ASSERT(oldStub->jitCode() == fallbackStub->jitCode());
         entry.newStub = fallbackStub;
         return true;
     }
@@ -747,28 +762,16 @@ CloneOldBaselineStub(JSContext* cx, Debu
     for (size_t i = 0; i < entryIndex; i++) {
         if (oldStub == entries[i].oldStub && entries[i].frameKind != ICEntry::Kind_Invalid) {
             MOZ_ASSERT(entries[i].newStub);
             entry.newStub = entries[i].newStub;
             return true;
         }
     }
 
-    // Some stubs are monitored, get the first stub in the monitor chain from
-    // the new fallback stub if so.
-    ICStub* firstMonitorStub;
-    if (fallbackStub->isMonitoredFallback()) {
-        ICMonitoredFallbackStub* monitored = fallbackStub->toMonitoredFallbackStub();
-        ICTypeMonitor_Fallback* fallback = monitored->getFallbackMonitorStub(cx, entry.script);
-        if (!fallback)
-            return false;
-        firstMonitorStub = fallback->firstMonitorStub();
-    } else {
-        firstMonitorStub = nullptr;
-    }
     ICStubSpace* stubSpace = ICStubCompiler::StubSpaceForStub(oldStub->makesGCCalls(), entry.script,
                                                               ICStubCompiler::Engine::Baseline);
 
     // Clone the existing stub into the recompiled IC.
     //
     // Note that since JitCode is a GC thing, cloning an ICStub with the same
     // JitCode ensures it won't be collected.
     switch (oldStub->kind()) {