Bug 1405994 part 1 - Handle rectifier frames following c++ entry frame in profiler code. r=bbouvier
authorJan de Mooij <jdemooij@mozilla.com>
Tue, 10 Oct 2017 14:03:24 +0200
changeset 427918 7774c8002d5fad2626b7778c86602546af0cebdb
parent 427917 2a21d7780597b9760df66a084095fbedfc446517
child 427919 fd1fe0931730ae57be8aee0969183be0121e2857
push id97
push userfmarier@mozilla.com
push dateSat, 14 Oct 2017 01:12:59 +0000
reviewersbbouvier
bugs1405994
milestone58.0a1
Bug 1405994 part 1 - Handle rectifier frames following c++ entry frame in profiler code. r=bbouvier
js/src/jit/BaselineBailouts.cpp
js/src/jit/JSJitFrameIter.cpp
js/src/jit/JSJitFrameIter.h
js/src/jit/MacroAssembler.cpp
js/src/jit/arm/Trampoline-arm.cpp
js/src/jit/arm64/Trampoline-arm64.cpp
js/src/jit/mips32/Trampoline-mips32.cpp
js/src/jit/mips64/Trampoline-mips64.cpp
js/src/jit/x64/Trampoline-x64.cpp
js/src/jit/x86/Trampoline-x86.cpp
--- a/js/src/jit/BaselineBailouts.cpp
+++ b/js/src/jit/BaselineBailouts.cpp
@@ -389,23 +389,23 @@ struct BaselineStackBuilder
 #elif defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) || \
       defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) || \
       defined(JS_CODEGEN_X64)
         // On X64, ARM, ARM64, and MIPS, the frame pointer save location depends on
         // the caller of the rectifier frame.
         BufferPointer<RectifierFrameLayout> priorFrame =
             pointerAtStackOffset<RectifierFrameLayout>(priorOffset);
         FrameType priorType = priorFrame->prevType();
-        MOZ_ASSERT(priorType == JitFrame_WasmToJSJit ||
+        MOZ_ASSERT(JSJitFrameIter::isEntry(priorType) ||
                    priorType == JitFrame_IonJS ||
                    priorType == JitFrame_BaselineStub);
 
-        // If the frame preceding the rectifier is an IonJS or WasmToJSJit
-        // entry frame, then once again the frame pointer does not matter.
-        if (priorType == JitFrame_IonJS || priorType == JitFrame_WasmToJSJit)
+        // If the frame preceding the rectifier is an IonJS or entry frame,
+        // then once again the frame pointer does not matter.
+        if (priorType == JitFrame_IonJS || JSJitFrameIter::isEntry(priorType))
             return nullptr;
 
         // Otherwise, the frame preceding the rectifier is a BaselineStub frame.
         //  let X = STACK_START_ADDR + JitFrameLayout::Size() + PREV_FRAME_SIZE
         //      X + RectifierFrameLayout::Size()
         //        + ((RectifierFrameLayout*) X)->prevFrameLocalSize()
         //        - BaselineStubFrameLayout::reverseOffsetOfSavedFramePtr()
         size_t extraOffset = RectifierFrameLayout::Size() + priorFrame->prevFrameLocalSize() +
--- a/js/src/jit/JSJitFrameIter.cpp
+++ b/js/src/jit/JSJitFrameIter.cpp
@@ -650,16 +650,26 @@ JSJitProfilingFrameIterator::moveToWasmF
     // pass a wasm iterator the correct value of FP.
     returnAddressToFp_ = nullptr;
     fp_ = GetPreviousRawFrame<uint8_t*>(frame);
     type_ = JitFrame_WasmToJSJit;
     MOZ_ASSERT(!done());
 }
 
 void
+JSJitProfilingFrameIterator::moveToCppEntryFrame()
+{
+    // No previous frame, set to nullptr to indicate that
+    // JSJitProfilingFrameIterator is done().
+    returnAddressToFp_ = nullptr;
+    fp_ = nullptr;
+    type_ = JitFrame_CppToJSJit;
+}
+
+void
 JSJitProfilingFrameIterator::moveToNextFrame(CommonFrameLayout* frame)
 {
     /*
      * fp_ points to a Baseline or Ion frame.  The possible call-stacks
      * patterns occurring between this frame and a previous Ion or Baseline
      * frame are as follows:
      *
      * <Baseline-Or-Ion>
@@ -674,16 +684,18 @@ JSJitProfilingFrameIterator::moveToNextF
      * ^--- Argument Rectifier
      * |    ^
      * |    |
      * |    ^--- Ion
      * |    |
      * |    ^--- Baseline Stub <---- Baseline
      * |    |
      * |    ^--- WasmToJSJit <--- (other wasm frames)
+     * |    |
+     * |    ^--- CppToJSJit
      * |
      * ^--- Entry Frame (From C++)
      *      Exit Frame (From previous JitActivation)
      *      ^
      *      |
      *      ^--- Ion
      *      |
      *      ^--- Baseline
@@ -739,16 +751,21 @@ JSJitProfilingFrameIterator::moveToNextF
             return;
         }
 
         if (rectPrevType == JitFrame_WasmToJSJit) {
             moveToWasmFrame(rectFrame);
             return;
         }
 
+        if (rectPrevType == JitFrame_CppToJSJit) {
+            moveToCppEntryFrame();
+            return;
+        }
+
         MOZ_CRASH("Bad frame type prior to rectifier frame.");
     }
 
     if (prevType == JitFrame_IonICCall) {
         IonICCallFrameLayout* callFrame =
             GetPreviousRawFrame<IonICCallFrameLayout*>(frame);
 
         MOZ_ASSERT(callFrame->prevType() == JitFrame_IonJS);
@@ -760,18 +777,14 @@ JSJitProfilingFrameIterator::moveToNextF
     }
 
     if (prevType == JitFrame_WasmToJSJit) {
         moveToWasmFrame(frame);
         return;
     }
 
     if (prevType == JitFrame_CppToJSJit) {
-        // No previous frame, set to null to indicate that
-        // JSJitProfilingFrameIterator is done().
-        returnAddressToFp_ = nullptr;
-        fp_ = nullptr;
-        type_ = JitFrame_CppToJSJit;
+        moveToCppEntryFrame();
         return;
     }
 
     MOZ_CRASH("Bad frame type.");
 }
--- a/js/src/jit/JSJitFrameIter.h
+++ b/js/src/jit/JSJitFrameIter.h
@@ -292,16 +292,17 @@ class JSJitProfilingFrameIterator
 
     inline JitFrameLayout* framePtr();
     inline JSScript* frameScript();
     MOZ_MUST_USE bool tryInitWithPC(void* pc);
     MOZ_MUST_USE bool tryInitWithTable(JitcodeGlobalTable* table, void* pc, JSRuntime* rt,
                                        bool forLastCallSite);
     void fixBaselineReturnAddress();
 
+    void moveToCppEntryFrame();
     void moveToWasmFrame(CommonFrameLayout* frame);
     void moveToNextFrame(CommonFrameLayout* frame);
 
   public:
     JSJitProfilingFrameIterator(JSContext* cx,
                               const JS::ProfilingFrameIterator::RegisterState& state);
     explicit JSJitProfilingFrameIterator(void* exitFrame);
 
--- a/js/src/jit/MacroAssembler.cpp
+++ b/js/src/jit/MacroAssembler.cpp
@@ -1659,16 +1659,17 @@ MacroAssembler::assertRectifierFramePare
 {
 #ifdef DEBUG
     {
         // Check the possible previous frame types here.
         Label checkOk;
         branch32(Assembler::Equal, frameType, Imm32(JitFrame_IonJS), &checkOk);
         branch32(Assembler::Equal, frameType, Imm32(JitFrame_BaselineStub), &checkOk);
         branch32(Assembler::Equal, frameType, Imm32(JitFrame_WasmToJSJit), &checkOk);
+        branch32(Assembler::Equal, frameType, Imm32(JitFrame_CppToJSJit), &checkOk);
         assumeUnreachable("Unrecognized frame type preceding RectifierFrame.");
         bind(&checkOk);
     }
 #endif
 }
 
 void
 MacroAssembler::loadBaselineOrIonRaw(Register script, Register dest, Label* failure)
--- a/js/src/jit/arm/Trampoline-arm.cpp
+++ b/js/src/jit/arm/Trampoline-arm.cpp
@@ -1282,20 +1282,20 @@ JitRuntime::generateProfilerExitFrameTai
         masm.storePtr(scratch2, lastProfilingFrame);
         masm.ret();
     }
 
 
     //
     // JitFrame_Rectifier
     //
-    // The rectifier frame can be preceded by either an IonJS, a WasmToJSJit or
-    // a BaselineStub frame.
+    // The rectifier frame can be preceded by either an IonJS, a BaselineStub,
+    // or a CppToJSJit/WasmToJSJit frame.
     //
-    // Stack layout if caller of rectifier was Ion or WasmToJSJit:
+    // Stack layout if caller of rectifier was Ion or CppToJSJit/WasmToJSJit:
     //
     //              Ion-Descriptor
     //              Ion-ReturnAddr
     //              ... ion frame data ... |- Rect-Descriptor.Size
     //              < COMMON LAYOUT >
     //
     // Stack layout if caller of rectifier was Baseline:
     //
@@ -1349,18 +1349,18 @@ JitRuntime::generateProfilerExitFrameTai
         // scratch3 := RectFrame + Rect-Descriptor.Size + RectifierFrameLayout::Size()
         masm.ma_add(scratch2, scratch1, scratch3);
         masm.add32(Imm32(RectifierFrameLayout::Size()), scratch3);
         masm.storePtr(scratch3, lastProfilingFrame);
         masm.ret();
 
         masm.bind(&notIonFrame);
 
-        // Check for either BaselineStub or WasmToJSJit: since WasmToJSJit is
-        // just an entry, jump there if we see it.
+        // Check for either BaselineStub or a CppToJSJit/WasmToJSJit entry
+        // frame.
         masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_BaselineStub), &handle_Entry);
 
         // Handle Rectifier <- BaselineStub <- BaselineJS
         masm.ma_add(scratch2, scratch1, scratch3);
         Address stubFrameReturnAddr(scratch3, RectifierFrameLayout::Size() +
                                               BaselineStubFrameLayout::offsetOfReturnAddress());
         masm.loadPtr(stubFrameReturnAddr, scratch2);
         masm.storePtr(scratch2, lastProfilingCallSite);
--- a/js/src/jit/arm64/Trampoline-arm64.cpp
+++ b/js/src/jit/arm64/Trampoline-arm64.cpp
@@ -1074,20 +1074,20 @@ JitRuntime::generateProfilerExitFrameTai
         masm.storePtr(scratch2, lastProfilingFrame);
         masm.ret();
     }
 
 
     //
     // JitFrame_Rectifier
     //
-    // The rectifier frame can be preceded by either an IonJS or a
-    // BaselineStub frame.
+    // The rectifier frame can be preceded by either an IonJS, a BaselineStub,
+    // or a CppToJSJit/WasmToJSJit frame.
     //
-    // Stack layout if caller of rectifier was Ion:
+    // Stack layout if caller of rectifier was Ion or CppToJSJit/WasmToJSJit:
     //
     //              Ion-Descriptor
     //              Ion-ReturnAddr
     //              ... ion frame data ... |- Rect-Descriptor.Size
     //              < COMMON LAYOUT >
     //
     // Stack layout if caller of rectifier was Baseline:
     //
@@ -1114,17 +1114,17 @@ JitRuntime::generateProfilerExitFrameTai
     //              Descriptor      |
     //    FP -----> ReturnAddr      |
     //
     masm.bind(&handle_Rectifier);
     {
         // scratch2 := StackPointer + Descriptor.size*1 + JitFrameLayout::Size();
         masm.addPtr(masm.getStackPointer(), scratch1, scratch2);
         masm.syncStackPtr();
-        masm.add32(Imm32(JitFrameLayout::Size()), scratch2);
+        masm.addPtr(Imm32(JitFrameLayout::Size()), scratch2);
         masm.loadPtr(Address(scratch2, RectifierFrameLayout::offsetOfDescriptor()), scratch3);
         masm.rshiftPtr(Imm32(FRAMESIZE_SHIFT), scratch3, scratch1);
         masm.and32(Imm32((1 << FRAMETYPE_BITS) - 1), scratch3);
 
         // Now |scratch1| contains Rect-Descriptor.Size
         // and |scratch2| points to Rectifier frame
         // and |scratch3| contains Rect-Descriptor.Type
 
@@ -1142,18 +1142,18 @@ JitRuntime::generateProfilerExitFrameTai
         // scratch3 := RectFrame + Rect-Descriptor.Size + RectifierFrameLayout::Size()
         masm.addPtr(scratch2, scratch1, scratch3);
         masm.add32(Imm32(RectifierFrameLayout::Size()), scratch3);
         masm.storePtr(scratch3, lastProfilingFrame);
         masm.ret();
 
         masm.bind(&notIonFrame);
 
-        // Check for either BaselineStub or WasmToJSJit: since WasmToJSJit is
-        // just an entry, jump there if we see it.
+        // Check for either BaselineStub or a CppToJSJit/WasmToJSJit entry
+        // frame.
         masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_BaselineStub), &handle_Entry);
 
         // Handle Rectifier <- BaselineStub <- BaselineJS
         masm.addPtr(scratch2, scratch1, scratch3);
         Address stubFrameReturnAddr(scratch3, RectifierFrameLayout::Size() +
                                               BaselineStubFrameLayout::offsetOfReturnAddress());
         masm.loadPtr(stubFrameReturnAddr, scratch2);
         masm.storePtr(scratch2, lastProfilingCallSite);
--- a/js/src/jit/mips32/Trampoline-mips32.cpp
+++ b/js/src/jit/mips32/Trampoline-mips32.cpp
@@ -1261,20 +1261,20 @@ JitRuntime::generateProfilerExitFrameTai
         masm.storePtr(scratch2, lastProfilingFrame);
         masm.ret();
     }
 
 
     //
     // JitFrame_Rectifier
     //
-    // The rectifier frame can be preceded by either an IonJS, a WasmToJSJit or
-    // a BaselineStub frame.
+    // The rectifier frame can be preceded by either an IonJS, a BaselineStub,
+    // or a CppToJSJit/WasmToJSJit frame.
     //
-    // Stack layout if caller of rectifier was Ion or WasmToJSJit:
+    // Stack layout if caller of rectifier was Ion or CppToJSJit/WasmToJSJit:
     //
     //              Ion-Descriptor
     //              Ion-ReturnAddr
     //              ... ion frame data ... |- Rect-Descriptor.Size
     //              < COMMON LAYOUT >
     //
     // Stack layout if caller of rectifier was Baseline:
     //
@@ -1328,18 +1328,18 @@ JitRuntime::generateProfilerExitFrameTai
         // scratch3 := RectFrame + Rect-Descriptor.Size + RectifierFrameLayout::Size()
         masm.as_addu(scratch3, scratch2, scratch1);
         masm.add32(Imm32(RectifierFrameLayout::Size()), scratch3);
         masm.storePtr(scratch3, lastProfilingFrame);
         masm.ret();
 
         masm.bind(&notIonFrame);
 
-        // Check for either BaselineStub or WasmToJSJit: since WasmToJSJit is
-        // just an entry, jump there if we see it.
+        // Check for either BaselineStub or a CppToJSJit/WasmToJSJit entry
+        // frame.
         masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_BaselineStub), &handle_Entry);
 
         // Handle Rectifier <- BaselineStub <- BaselineJS
         masm.as_addu(scratch3, scratch2, scratch1);
         Address stubFrameReturnAddr(scratch3, RectifierFrameLayout::Size() +
                                               BaselineStubFrameLayout::offsetOfReturnAddress());
         masm.loadPtr(stubFrameReturnAddr, scratch2);
         masm.storePtr(scratch2, lastProfilingCallSite);
--- a/js/src/jit/mips64/Trampoline-mips64.cpp
+++ b/js/src/jit/mips64/Trampoline-mips64.cpp
@@ -1202,20 +1202,20 @@ JitRuntime::generateProfilerExitFrameTai
         masm.storePtr(scratch2, lastProfilingFrame);
         masm.ret();
     }
 
 
     //
     // JitFrame_Rectifier
     //
-    // The rectifier frame can be preceded by either an IonJS, a WasmToJSJit or
-    // a BaselineStub frame.
+    // The rectifier frame can be preceded by either an IonJS, a BaselineStub,
+    // or a CppToJSJit/WasmToJSJit frame.
     //
-    // Stack layout if caller of rectifier was Ion or WasmToJSJit:
+    // Stack layout if caller of rectifier was Ion or CppToJSJit/WasmToJSJit:
     //
     //              Ion-Descriptor
     //              Ion-ReturnAddr
     //              ... ion frame data ... |- Rect-Descriptor.Size
     //              < COMMON LAYOUT >
     //
     // Stack layout if caller of rectifier was Baseline:
     //
@@ -1269,18 +1269,18 @@ JitRuntime::generateProfilerExitFrameTai
         // scratch3 := RectFrame + Rect-Descriptor.Size + RectifierFrameLayout::Size()
         masm.as_daddu(scratch3, scratch2, scratch1);
         masm.addPtr(Imm32(RectifierFrameLayout::Size()), scratch3);
         masm.storePtr(scratch3, lastProfilingFrame);
         masm.ret();
 
         masm.bind(&notIonFrame);
 
-        // Check for either BaselineStub or WasmToJSJit: since WasmToJSJit is
-        // just an entry, jump there if we see it.
+        // Check for either BaselineStub or a CppToJSJit/WasmToJSJit entry
+        // frame.
         masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_BaselineStub), &handle_Entry);
 
         // Handle Rectifier <- BaselineStub <- BaselineJS
         masm.as_daddu(scratch3, scratch2, scratch1);
         Address stubFrameReturnAddr(scratch3, RectifierFrameLayout::Size() +
                                               BaselineStubFrameLayout::offsetOfReturnAddress());
         masm.loadPtr(stubFrameReturnAddr, scratch2);
         masm.storePtr(scratch2, lastProfilingCallSite);
--- a/js/src/jit/x64/Trampoline-x64.cpp
+++ b/js/src/jit/x64/Trampoline-x64.cpp
@@ -1175,20 +1175,20 @@ JitRuntime::generateProfilerExitFrameTai
         masm.storePtr(scratch2, lastProfilingFrame);
         masm.ret();
     }
 
 
     //
     // JitFrame_Rectifier
     //
-    // The rectifier frame can be preceded by either an IonJS, a WasmToJSJit or
-    // a BaselineStub frame.
+    // The rectifier frame can be preceded by either an IonJS, a BaselineStub,
+    // or a CppToJSJit/WasmToJSJit frame.
     //
-    // Stack layout if caller of rectifier was Ion or WasmToJSJit:
+    // Stack layout if caller of rectifier was Ion or CppToJSJit/WasmToJSJit:
     //
     //              Ion-Descriptor
     //              Ion-ReturnAddr
     //              ... ion frame data ... |- Rect-Descriptor.Size
     //              < COMMON LAYOUT >
     //
     // Stack layout if caller of rectifier was Baseline:
     //
@@ -1241,18 +1241,18 @@ JitRuntime::generateProfilerExitFrameTai
 
         // scratch3 := RectFrame + Rect-Descriptor.Size + RectifierFrameLayout::Size()
         masm.lea(Operand(scratch2, scratch1, TimesOne, RectifierFrameLayout::Size()), scratch3);
         masm.storePtr(scratch3, lastProfilingFrame);
         masm.ret();
 
         masm.bind(&notIonFrame);
 
-        // Check for either BaselineStub or WasmToJSJit: since WasmToJSJit is
-        // just an entry, jump there if we see it.
+        // Check for either BaselineStub or a CppToJSJit/WasmToJSJit entry
+        // frame.
         masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_BaselineStub), &handle_Entry);
 
         // Handle Rectifier <- BaselineStub <- BaselineJS
         BaseIndex stubFrameReturnAddr(scratch2, scratch1, TimesOne,
                                          RectifierFrameLayout::Size() +
                                          BaselineStubFrameLayout::offsetOfReturnAddress());
         masm.loadPtr(stubFrameReturnAddr, scratch3);
         masm.storePtr(scratch3, lastProfilingCallSite);
--- a/js/src/jit/x86/Trampoline-x86.cpp
+++ b/js/src/jit/x86/Trampoline-x86.cpp
@@ -1209,20 +1209,20 @@ JitRuntime::generateProfilerExitFrameTai
         masm.storePtr(scratch2, lastProfilingFrame);
         masm.ret();
     }
 
 
     //
     // JitFrame_Rectifier
     //
-    // The rectifier frame can be preceded by either an IonJS, a WasmToJSJit or
-    // a BaselineStub frame.
+    // The rectifier frame can be preceded by either an IonJS, a BaselineStub,
+    // or a CppToJSJit/WasmToJSJit frame.
     //
-    // Stack layout if caller of rectifier was Ion or WasmToJSJit:
+    // Stack layout if caller of rectifier was Ion or CppToJSJit/WasmToJSJit:
     //
     //              Ion-Descriptor
     //              Ion-ReturnAddr
     //              ... ion frame data ... |- Rect-Descriptor.Size
     //              < COMMON LAYOUT >
     //
     // Stack layout if caller of rectifier was Baseline:
     //
@@ -1275,18 +1275,18 @@ JitRuntime::generateProfilerExitFrameTai
 
         // scratch3 := RectFrame + Rect-Descriptor.Size + RectifierFrameLayout::Size()
         masm.lea(Operand(scratch2, scratch1, TimesOne, RectifierFrameLayout::Size()), scratch3);
         masm.storePtr(scratch3, lastProfilingFrame);
         masm.ret();
 
         masm.bind(&notIonFrame);
 
-        // Check for either BaselineStub or WasmToJSJit: since WasmToJSJit is
-        // just an entry, jump there if we see it.
+        // Check for either BaselineStub or a CppToJSJit/WasmToJSJit entry
+        // frame.
         masm.branch32(Assembler::NotEqual, scratch3, Imm32(JitFrame_BaselineStub), &handle_Entry);
 
         // Handle Rectifier <- BaselineStub <- BaselineJS
         BaseIndex stubFrameReturnAddr(scratch2, scratch1, TimesOne,
                                          RectifierFrameLayout::Size() +
                                          BaselineStubFrameLayout::offsetOfReturnAddress());
         masm.loadPtr(stubFrameReturnAddr, scratch3);
         masm.storePtr(scratch3, lastProfilingCallSite);