Bug 1417961 - Fix Baseline debug mode OSR to delazify type monitor chains correctly. r=tcampbell
authorJan de Mooij <jdemooij@mozilla.com>
Thu, 30 Nov 2017 15:53:38 +0100
changeset 394321 6f20971085399fe1c166f61afc8562fd0e6eabe0
parent 394320 ba350c82d8233199e3c822f0836f4ad1e588f518
child 394322 48ba62a0feb0c7431807e0d586c0e310da21f721
push id97860
push userjandemooij@gmail.com
push dateThu, 30 Nov 2017 14:55:09 +0000
treeherdermozilla-inbound@6f2097108539 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstcampbell
bugs1417961
milestone59.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 1417961 - Fix Baseline debug mode OSR to delazify type monitor chains correctly. r=tcampbell
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()) {