Bug 1161351 - Fix unwound exit frame sizes in JitProfilingFrameIterator. (r=nbp)
authorShu-yu Guo <shu@rfrn.org>
Thu, 07 May 2015 18:16:53 -0700
changeset 274278 cade54db387c971000eee1f6a27336c5da41aa65
parent 274277 98f15494f0d47b1f1d9db26cfa34d55d415fb7cc
child 274279 4923c566a7f2adb0c143be6a2007c7b5735b5df6
push id863
push userraliiev@mozilla.com
push dateMon, 03 Aug 2015 13:22:43 +0000
treeherdermozilla-release@f6321b14228d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp
bugs1161351
milestone40.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 1161351 - Fix unwound exit frame sizes in JitProfilingFrameIterator. (r=nbp)
js/src/jit-test/tests/profiler/bug1161351.js
js/src/jit/JitFrames-inl.h
js/src/jit/JitFrames.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/profiler/bug1161351.js
@@ -0,0 +1,16 @@
+function x() { n; }
+function f() {
+  try  { x(); } catch(ex) {}
+}
+var g = newGlobal();
+g.parent = this;
+g.eval("new Debugger(parent).onExceptionUnwind = function () {};");
+enableSPSProfiling();
+try {
+  enableSingleStepProfiling();
+} catch (e) {
+  // Not all platforms support single-step profiling.
+}
+f();
+f();
+f();
--- a/js/src/jit/JitFrames-inl.h
+++ b/js/src/jit/JitFrames-inl.h
@@ -44,26 +44,32 @@ JitFrameIterator::prevFrameLocalSize() c
 inline FrameType
 JitFrameIterator::prevType() const
 {
     CommonFrameLayout* current = (CommonFrameLayout*) current_;
     return current->prevType();
 }
 
 inline bool
+IsUnwoundFrame(FrameType type)
+{
+    return type == JitFrame_Unwound_Rectifier ||
+           type == JitFrame_Unwound_IonJS ||
+           type == JitFrame_Unwound_BaselineJS ||
+           type == JitFrame_Unwound_BaselineStub ||
+           type == JitFrame_Unwound_IonAccessorIC;
+}
+
+inline bool
 JitFrameIterator::isFakeExitFrame() const
 {
     if (type() == JitFrame_LazyLink)
         return false;
-    bool res = (prevType() == JitFrame_Unwound_Rectifier ||
-                prevType() == JitFrame_Unwound_IonJS ||
-                prevType() == JitFrame_Unwound_BaselineJS ||
-                prevType() == JitFrame_Unwound_BaselineStub ||
-                prevType() == JitFrame_Unwound_IonAccessorIC ||
-                (prevType() == JitFrame_Entry && type() == JitFrame_Exit));
+    bool res = IsUnwoundFrame(prevType()) ||
+               (prevType() == JitFrame_Entry && type() == JitFrame_Exit);
     MOZ_ASSERT_IF(res, type() == JitFrame_Exit || type() == JitFrame_BaselineJS);
     return res;
 }
 
 inline ExitFrameLayout*
 JitFrameIterator::exitFrame() const
 {
     MOZ_ASSERT(isExitFrame());
--- a/js/src/jit/JitFrames.cpp
+++ b/js/src/jit/JitFrames.cpp
@@ -2930,42 +2930,56 @@ JitProfilingFrameIterator::JitProfilingF
     returnAddressToFp_ = frameScript()->baselineScript()->method()->raw();
 }
 
 template <typename FrameType, typename ReturnType=CommonFrameLayout*>
 inline ReturnType
 GetPreviousRawFrame(FrameType* frame)
 {
     size_t prevSize = frame->prevFrameLocalSize() + FrameType::Size();
-    return (ReturnType) (((uint8_t*) frame) + prevSize);
+    return ReturnType(((uint8_t*) frame) + prevSize);
+}
+
+template <typename ReturnType=CommonFrameLayout*>
+inline ReturnType
+GetPreviousRawFrameOfExitFrame(ExitFrameLayout* frame)
+{
+    // Unwound exit frames are fake exit frames, and have the size of a
+    // JitFrameLayout instead of ExitFrameLayout. See
+    // JitFrameIterator::prevFp.
+    size_t frameSize = IsUnwoundFrame(frame->prevType())
+                       ? JitFrameLayout::Size()
+                       : ExitFrameLayout::Size();
+    size_t prevSize = frame->prevFrameLocalSize() + frameSize;
+    return ReturnType(((uint8_t*) frame) + prevSize);
 }
 
 JitProfilingFrameIterator::JitProfilingFrameIterator(void* exitFrame)
 {
     ExitFrameLayout* frame = (ExitFrameLayout*) exitFrame;
     FrameType prevType = frame->prevType();
 
     if (prevType == JitFrame_IonJS || prevType == JitFrame_Unwound_IonJS) {
         returnAddressToFp_ = frame->returnAddress();
-        fp_ = GetPreviousRawFrame<ExitFrameLayout, uint8_t*>(frame);
+        fp_ = GetPreviousRawFrameOfExitFrame<uint8_t*>(frame);
         type_ = JitFrame_IonJS;
         return;
     }
 
-    if (prevType == JitFrame_BaselineJS) {
+    if (prevType == JitFrame_BaselineJS || prevType == JitFrame_Unwound_BaselineJS) {
         returnAddressToFp_ = frame->returnAddress();
-        fp_ = GetPreviousRawFrame<ExitFrameLayout, uint8_t*>(frame);
+        fp_ = GetPreviousRawFrameOfExitFrame<uint8_t*>(frame);
         type_ = JitFrame_BaselineJS;
         fixBaselineDebugModeOSRReturnAddress();
         return;
     }
 
     if (prevType == JitFrame_BaselineStub || prevType == JitFrame_Unwound_BaselineStub) {
         BaselineStubFrameLayout* stubFrame =
-            GetPreviousRawFrame<ExitFrameLayout, BaselineStubFrameLayout*>(frame);
+            GetPreviousRawFrameOfExitFrame<BaselineStubFrameLayout*>(frame);
         MOZ_ASSERT_IF(prevType == JitFrame_BaselineStub,
                       stubFrame->prevType() == JitFrame_BaselineJS);
         MOZ_ASSERT_IF(prevType == JitFrame_Unwound_BaselineStub,
                       stubFrame->prevType() == JitFrame_BaselineJS ||
                       stubFrame->prevType() == JitFrame_IonJS);
         returnAddressToFp_ = stubFrame->returnAddress();
         fp_ = ((uint8_t*) stubFrame->reverseSavedFramePtr())
                 + jit::BaselineFrame::FramePointerOffset;