Bug 1130039 - Bailout: Add padding to reconstructed BaselineStub and Rectifier frames. r=jandem
authorNicolas B. Pierron <nicolas.b.pierron@mozilla.com>
Wed, 11 Feb 2015 14:51:43 +0100
changeset 228601 8dfe4f1d46f3773ebbcb600a2b8b17e7905449e1
parent 228600 d96d552ff899418b2a6324ee1ca662df18d586e9
child 228638 037072f411fe811230f90b3904bb0b456abd4aed
push id55473
push usernpierron@mozilla.com
push dateWed, 11 Feb 2015 13:52:08 +0000
treeherdermozilla-inbound@8dfe4f1d46f3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1130039
milestone38.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 1130039 - Bailout: Add padding to reconstructed BaselineStub and Rectifier frames. r=jandem
js/src/jit/BaselineBailouts.cpp
--- a/js/src/jit/BaselineBailouts.cpp
+++ b/js/src/jit/BaselineBailouts.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "jsprf.h"
+#include "jsutil.h"
 #include "jit/arm/Simulator-arm.h"
 #include "jit/BaselineIC.h"
 #include "jit/BaselineJIT.h"
 #include "jit/CompileInfo.h"
 #include "jit/JitSpewer.h"
 #include "jit/mips/Simulator-mips.h"
 #include "jit/Recover.h"
 #include "jit/RematerializedFrame.h"
@@ -234,16 +235,28 @@ struct BaselineStackBuilder
             JitSpew(JitSpew_BaselineBailouts,
                     "      WRITE_VAL %p/%p %-15s %016llx",
                     header_->copyStackBottom, virtualPointerAtStackOffset(0), info,
                     *((uint64_t *) &val));
         }
         return true;
     }
 
+    bool maybeWritePadding(size_t alignment, size_t after, const char *info) {
+        MOZ_ASSERT(framePushed_ % sizeof(Value) == 0);
+        MOZ_ASSERT(after % sizeof(Value) == 0);
+        size_t offset = ComputeByteAlignment(after, alignment);
+        while (framePushed_ % alignment != offset) {
+            if (!writeValue(MagicValue(JS_ARG_POISON), info))
+                return false;
+        }
+
+        return true;
+    }
+
     Value popValue() {
         MOZ_ASSERT(bufferUsed_ >= sizeof(Value));
         MOZ_ASSERT(framePushed_ >= sizeof(Value));
         bufferAvail_ += sizeof(Value);
         bufferUsed_ -= sizeof(Value);
         framePushed_ -= sizeof(Value);
         Value result = *((Value *) header_->copyStackBottom);
         header_->copyStackBottom += sizeof(Value);
@@ -502,40 +515,44 @@ HasLiveIteratorAtStackDepth(JSScript *sc
 //         |   --   |   +---------------+  --- IF NOT LAST INLINE FRAME,
 //         +------------|  Descr(BLJS)  |  --- CALLING INFO STARTS HERE
 //                  |   +---------------+
 //                  |   |  ReturnAddr   | <-- return into main jitcode after IC
 //             --   |   +===============+
 //             |    |   |    StubPtr    |
 //             |    |   +---------------+
 //             |    +---|   FramePtr    |
-//             |        +---------------+
-//             |        |     ArgA      |
+//             |        +---------------+  --- The inlined frame might OSR in Ion
+//             |        |   Padding?    |  --- Thus the return address should be aligned.
 //             |        +---------------+
-//             |        |     ...       |
-//         +--<         +---------------+
+//         +--<         |     ArgA      |
+//         |   |        +---------------+
+//         |   |        |     ...       |
+//         |   |        +---------------+
 //         |   |        |     Arg0      |
 //         |   |        +---------------+
 //         |   |        |     ThisV     |
 //         |   --       +---------------+
 //         |            |  ActualArgC   |
 //         |            +---------------+
 //         |            |  CalleeToken  |
 //         |            +---------------+
 //         +------------| Descr(BLStub) |
 //                      +---------------+
 //                      |  ReturnAddr   | <-- return into ICCall_Scripted IC
 //             --       +===============+ --- IF CALLEE FORMAL ARGS > ActualArgC
+//             |        |   Padding?    |
+//             |        +---------------+
 //             |        |  UndefinedU   |
 //             |        +---------------+
 //             |        |     ...       |
 //             |        +---------------+
 //             |        |  Undefined0   |
-//             |        +---------------+
-//         +--<         |     ArgA      |
+//         +--<         +---------------+
+//         |   |        |     ArgA      |
 //         |   |        +---------------+
 //         |   |        |     ...       |
 //         |   |        +---------------+
 //         |   |        |     Arg0      |
 //         |   |        +---------------+
 //         |   |        |     ThisV     |
 //         |   --       +---------------+
 //         |            |  ActualArgC   |
@@ -1132,16 +1149,18 @@ InitFromBailout(JSContext *cx, HandleScr
         return false;
 
     // Build baseline stub frame:
     // +===============+
     // |    StubPtr    |
     // +---------------+
     // |   FramePtr    |
     // +---------------+
+    // |   Padding?    |
+    // +---------------+
     // |     ArgA      |
     // +---------------+
     // |     ...       |
     // +---------------+
     // |     Arg0      |
     // +---------------+
     // |     ThisV     |
     // +---------------+
@@ -1175,30 +1194,41 @@ InitFromBailout(JSContext *cx, HandleScr
     if (needToSaveArgs) {
         // For FUNAPPLY or an accessor, the arguments are not on the stack anymore,
         // but they are copied in a vector and are written here.
         if (op == JSOP_FUNAPPLY)
             actualArgc = blFrame->numActualArgs();
         else
             actualArgc = IsSetPropPC(pc);
 
+        // Align the stack based on the number of arguments.
+        size_t afterFrameSize = (actualArgc + 1) * sizeof(Value) + JitFrameLayout::Size();
+        if (!builder.maybeWritePadding(JitStackAlignment, afterFrameSize, "Padding"))
+            return false;
+
+        // Push arguments.
         MOZ_ASSERT(actualArgc + 2 <= exprStackSlots);
         MOZ_ASSERT(savedCallerArgs.length() == actualArgc + 2);
         for (unsigned i = 0; i < actualArgc + 1; i++) {
             size_t arg = savedCallerArgs.length() - (i + 1);
             if (!builder.writeValue(savedCallerArgs[arg], "ArgVal"))
                 return false;
         }
     } else {
         actualArgc = GET_ARGC(pc);
         if (op == JSOP_FUNCALL) {
             MOZ_ASSERT(actualArgc > 0);
             actualArgc--;
         }
 
+        // Align the stack based on the number of arguments.
+        size_t afterFrameSize = (actualArgc + 1) * sizeof(Value) + JitFrameLayout::Size();
+        if (!builder.maybeWritePadding(JitStackAlignment, afterFrameSize, "Padding"))
+            return false;
+
         MOZ_ASSERT(actualArgc + 2 <= exprStackSlots);
         for (unsigned i = 0; i < actualArgc + 1; i++) {
             size_t argSlot = (script->nfixed() + exprStackSlots) - (i + 1);
             if (!builder.writeValue(*blFrame->valueSlot(argSlot), "ArgVal"))
                 return false;
         }
     }
 
@@ -1239,24 +1269,27 @@ InitFromBailout(JSContext *cx, HandleScr
     if (!builder.writeWord(baselineStubFrameDescr, "Descriptor"))
         return false;
 
     // Push return address into ICCall_Scripted stub, immediately after the call.
     void *baselineCallReturnAddr = GetStubReturnAddress(cx, pc);
     MOZ_ASSERT(baselineCallReturnAddr);
     if (!builder.writePtr(baselineCallReturnAddr, "ReturnAddr"))
         return false;
+    MOZ_ASSERT(builder.framePushed() % JitStackAlignment == 0);
 
     // If actualArgc >= fun->nargs, then we are done.  Otherwise, we need to push on
     // a reconstructed rectifier frame.
     if (actualArgc >= calleeFun->nargs())
         return true;
 
     // Push a reconstructed rectifier frame.
     // +===============+
+    // |   Padding?    |
+    // +---------------+
     // |  UndefinedU   |
     // +---------------+
     // |     ...       |
     // +---------------+
     // |  Undefined0   |
     // +---------------+
     // |     ArgA      |
     // +---------------+
@@ -1278,18 +1311,27 @@ InitFromBailout(JSContext *cx, HandleScr
     JitSpew(JitSpew_BaselineBailouts, "      [RECTIFIER FRAME]");
 
     size_t startOfRectifierFrame = builder.framePushed();
 
     // On x86-only, the frame pointer is saved again in the rectifier frame.
 #if defined(JS_CODEGEN_X86)
     if (!builder.writePtr(prevFramePtr, "PrevFramePtr-X86Only"))
         return false;
+    // Follow the same logic as in JitRuntime::generateArgumentsRectifier.
+    prevFramePtr = builder.virtualPointerAtStackOffset(0);
+    if (!builder.writePtr(prevFramePtr, "Padding-X86Only"))
+        return false;
 #endif
 
+    // Align the stack based on the number of arguments.
+    size_t afterFrameSize = (calleeFun->nargs() + 1) * sizeof(Value) + RectifierFrameLayout::Size();
+    if (!builder.maybeWritePadding(JitStackAlignment, afterFrameSize, "Padding"))
+        return false;
+
     // Push undefined for missing arguments.
     for (unsigned i = 0; i < (calleeFun->nargs() - actualArgc); i++) {
         if (!builder.writeValue(UndefinedValue(), "FillerVal"))
             return false;
     }
 
     // Copy arguments + thisv from BaselineStub frame.
     if (!builder.subtract((actualArgc + 1) * sizeof(Value), "CopiedArgs"))
@@ -1318,16 +1360,17 @@ InitFromBailout(JSContext *cx, HandleScr
         return false;
 
     // Push return address into the ArgumentsRectifier code, immediately after the ioncode
     // call.
     void *rectReturnAddr = cx->runtime()->jitRuntime()->getArgumentsRectifierReturnAddr();
     MOZ_ASSERT(rectReturnAddr);
     if (!builder.writePtr(rectReturnAddr, "ReturnAddr"))
         return false;
+    MOZ_ASSERT(builder.framePushed() % JitStackAlignment == 0);
 
     return true;
 }
 
 uint32_t
 jit::BailoutIonToBaseline(JSContext *cx, JitActivation *activation, JitFrameIterator &iter,
                           bool invalidate, BaselineBailoutInfo **bailoutInfo,
                           const ExceptionBailoutInfo *excInfo)