Bug 1261324 - Fix bogus return address for star generators' .throw being observed by the profiler in Debugger's onExceptionUnwind in Baseline. (r=jandem)
authorShu-yu Guo <shu@rfrn.org>
Tue, 12 Apr 2016 10:21:25 -0700
changeset 292858 fb125ff927eae1b7adb8d0e3db798c341d71d8ab
parent 292857 d5486d4fde026515df62c90d759baab1105b3b2c
child 292880 fb921246e2d60f521f83defed54e30a38df1be3e
child 292896 716d75c8abc204d419caa0c28f9fd0e63dd5a609
push id30167
push userkwierso@gmail.com
push dateTue, 12 Apr 2016 22:28:26 +0000
treeherdermozilla-central@fb125ff927ea [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1261324
milestone48.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 1261324 - Fix bogus return address for star generators' .throw being observed by the profiler in Debugger's onExceptionUnwind in Baseline. (r=jandem)
js/src/jit-test/tests/profiler/bug1261324.js
js/src/jit/JitFrameIterator.h
js/src/jit/JitFrames.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/profiler/bug1261324.js
@@ -0,0 +1,24 @@
+g = newGlobal()
+g.parent = this
+g.eval("new Debugger(parent).onExceptionUnwind = function () {}")
+enableSPSProfiling()
+
+try {
+  // Only the ARM simulator supports single step profiling.
+  enableSingleStepProfiling();
+} catch (e) {
+  quit();
+}
+
+function assertThrowsInstanceOf(f) {
+    try {
+        f()
+    } catch (exc) {}
+}
+function testThrow(thunk) {
+    for (i = 0; i < 20; i++) {
+        iter = thunk()
+        assertThrowsInstanceOf(function() iter.throw())
+    }
+}
+testThrow(function*() {})
--- a/js/src/jit/JitFrameIterator.h
+++ b/js/src/jit/JitFrameIterator.h
@@ -272,17 +272,17 @@ class JitProfilingFrameIterator
     FrameType type_;
     void* returnAddressToFp_;
 
     inline JitFrameLayout* framePtr();
     inline JSScript* frameScript();
     bool tryInitWithPC(void* pc);
     bool tryInitWithTable(JitcodeGlobalTable* table, void* pc, JSRuntime* rt,
                           bool forLastCallSite);
-    void fixBaselineDebugModeOSRReturnAddress();
+    void fixBaselineReturnAddress();
 
     void moveToNextFrame(CommonFrameLayout* frame);
 
   public:
     JitProfilingFrameIterator(JSRuntime* rt,
                               const JS::ProfilingFrameIterator::RegisterState& state);
     explicit JitProfilingFrameIterator(void* exitFrame);
 
--- a/js/src/jit/JitFrames.cpp
+++ b/js/src/jit/JitFrames.cpp
@@ -2919,23 +2919,37 @@ JitProfilingFrameIterator::tryInitWithTa
         returnAddressToFp_ = pc;
         return true;
     }
 
     return false;
 }
 
 void
-JitProfilingFrameIterator::fixBaselineDebugModeOSRReturnAddress()
+JitProfilingFrameIterator::fixBaselineReturnAddress()
 {
     MOZ_ASSERT(type_ == JitFrame_BaselineJS);
     BaselineFrame* bl = (BaselineFrame*)(fp_ - BaselineFrame::FramePointerOffset -
                                          BaselineFrame::Size());
-    if (BaselineDebugModeOSRInfo* info = bl->getDebugModeOSRInfo())
+
+    // Debug mode OSR for Baseline uses a "continuation fixer" and stashes the
+    // actual return address in an auxiliary structure.
+    if (BaselineDebugModeOSRInfo* info = bl->getDebugModeOSRInfo()) {
         returnAddressToFp_ = info->resumeAddr;
+        return;
+    }
+
+    // Resuming a generator via .throw() pushes a bogus return address onto
+    // the stack. We have the actual jsbytecode* stashed on the frame itself;
+    // translate that into the Baseline code address.
+    if (jsbytecode* override = bl->maybeOverridePc()) {
+        JSScript* script = bl->script();
+        returnAddressToFp_ = script->baselineScript()->nativeCodeForPC(script, override);
+        return;
+    }
 }
 
 void
 JitProfilingFrameIterator::operator++()
 {
     JitFrameLayout* frame = framePtr();
     moveToNextFrame(frame);
 }
@@ -2980,17 +2994,17 @@ JitProfilingFrameIterator::moveToNextFra
         type_ = JitFrame_IonJS;
         return;
     }
 
     if (prevType == JitFrame_BaselineJS) {
         returnAddressToFp_ = frame->returnAddress();
         fp_ = GetPreviousRawFrame<uint8_t*>(frame);
         type_ = JitFrame_BaselineJS;
-        fixBaselineDebugModeOSRReturnAddress();
+        fixBaselineReturnAddress();
         return;
     }
 
     if (prevType == JitFrame_BaselineStub) {
         BaselineStubFrameLayout* stubFrame = GetPreviousRawFrame<BaselineStubFrameLayout*>(frame);
         MOZ_ASSERT(stubFrame->prevType() == JitFrame_BaselineJS);
 
         returnAddressToFp_ = stubFrame->returnAddress();