Bug 866888 part 4 - Move bailout tail code to its own stub. r=h4writer
authorJan de Mooij <jdemooij@mozilla.com>
Tue, 23 Jul 2013 09:23:42 +0200
changeset 151830 599fe516bed5dc59a91c97d1b6eefdb14b494704
parent 151829 a5977e4a4707e2a94d622f04c4987415a233ca97
child 151831 5e1f00b1fa6f975a1fb55e96a38d9a33e1e99225
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersh4writer
bugs866888
milestone25.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 866888 part 4 - Move bailout tail code to its own stub. r=h4writer
js/src/ion/Ion.cpp
js/src/ion/IonCompartment.h
js/src/ion/arm/Trampoline-arm.cpp
js/src/ion/x64/Trampoline-x64.cpp
js/src/ion/x86/Trampoline-x86.cpp
--- a/js/src/ion/Ion.cpp
+++ b/js/src/ion/Ion.cpp
@@ -166,16 +166,17 @@ ion::InitializeIon()
     CheckLogging();
     CheckPerf();
     return true;
 }
 
 IonRuntime::IonRuntime()
   : execAlloc_(NULL),
     exceptionTail_(NULL),
+    bailoutTail_(NULL),
     enterJIT_(NULL),
     bailoutHandler_(NULL),
     argumentsRectifier_(NULL),
     argumentsRectifierReturnAddr_(NULL),
     parallelArgumentsRectifier_(NULL),
     invalidator_(NULL),
     debugTrapHandler_(NULL),
     functionWrappers_(NULL),
@@ -209,16 +210,20 @@ IonRuntime::initialize(JSContext *cx)
     functionWrappers_ = cx->new_<VMWrapperMap>(cx);
     if (!functionWrappers_ || !functionWrappers_->init())
         return false;
 
     exceptionTail_ = generateExceptionTailStub(cx);
     if (!exceptionTail_)
         return false;
 
+    bailoutTail_ = generateBailoutTailStub(cx);
+    if (!bailoutTail_)
+        return false;
+
     if (cx->runtime()->jitSupportsFloatingPoint) {
         // Initialize some Ion-only stubs that require floating-point support.
         if (!bailoutTables_.reserve(FrameSizeClass::ClassLimit().classId()))
             return false;
 
         for (uint32_t id = 0;; id++) {
             FrameSizeClass class_ = FrameSizeClass::FromClass(id);
             if (class_ == FrameSizeClass::ClassLimit())
--- a/js/src/ion/IonCompartment.h
+++ b/js/src/ion/IonCompartment.h
@@ -124,16 +124,19 @@ class IonRuntime
     friend class IonCompartment;
 
     // Executable allocator.
     JSC::ExecutableAllocator *execAlloc_;
 
     // Shared post-exception-handler tail
     IonCode *exceptionTail_;
 
+    // Shared post-bailout-handler tail.
+    IonCode *bailoutTail_;
+
     // Trampoline for entering JIT code. Contains OSR prologue.
     IonCode *enterJIT_;
 
     // Trampoline for entering baseline JIT code.
     IonCode *enterBaselineJIT_;
 
     // Vector mapping frame class sizes to bailout tables.
     Vector<IonCode*, 4, SystemAllocPolicy> bailoutTables_;
@@ -168,16 +171,17 @@ class IonRuntime
     // (after returning from JIT code).
     uint8_t *osrTempData_;
 
     // Keep track of memoryregions that are going to be flushed.
     AutoFlushCache *flusher_;
 
   private:
     IonCode *generateExceptionTailStub(JSContext *cx);
+    IonCode *generateBailoutTailStub(JSContext *cx);
     IonCode *generateEnterJIT(JSContext *cx, EnterJitType type);
     IonCode *generateArgumentsRectifier(JSContext *cx, ExecutionMode mode, void **returnAddrOut);
     IonCode *generateBailoutTable(JSContext *cx, uint32_t frameClass);
     IonCode *generateBailoutHandler(JSContext *cx);
     IonCode *generateInvalidator(JSContext *cx);
     IonCode *generatePreBarrier(JSContext *cx, MIRType type);
     IonCode *generateDebugTrapHandler(JSContext *cx);
     IonCode *generateVMWrapper(JSContext *cx, const VMFunction &f);
@@ -287,16 +291,20 @@ class IonCompartment
     IonCode *getGenericBailoutHandler() {
         return rt->bailoutHandler_;
     }
 
     IonCode *getExceptionTail() {
         return rt->exceptionTail_;
     }
 
+    IonCode *getBailoutTail() {
+        return rt->bailoutTail_;
+    }
+
     IonCode *getBailoutTable(const FrameSizeClass &frameClass);
 
     IonCode *getArgumentsRectifier(ExecutionMode mode) {
         switch (mode) {
           case SequentialExecution: return rt->argumentsRectifier_;
           case ParallelExecution:   return rt->parallelArgumentsRectifier_;
           default:                  MOZ_ASSUME_UNREACHABLE("No such execution mode");
         }
--- a/js/src/ion/arm/Trampoline-arm.cpp
+++ b/js/src/ion/arm/Trampoline-arm.cpp
@@ -341,17 +341,21 @@ IonRuntime::generateInvalidator(JSContex
     masm.ma_ldr(Address(sp, 0), r2);
     masm.ma_ldr(Address(sp, sizeOfBailoutInfo), r1);
     // Remove the return address, the IonScript, the register state
     // (InvaliationBailoutStack) and the space that was allocated for the return value
     masm.ma_add(sp, Imm32(sizeof(InvalidationBailoutStack) + sizeOfRetval + sizeOfBailoutInfo), sp);
     // remove the space that this frame was using before the bailout
     // (computed by InvalidationBailout)
     masm.ma_add(sp, r1, sp);
-    masm.generateBailoutTail(r1, r2);
+
+    // Jump to shared bailout tail. The BailoutInfo pointer has to be in r2.
+    IonCode *bailoutTail = cx->compartment()->ionCompartment()->getBailoutTail();
+    masm.branch(bailoutTail);
+
     Linker linker(masm);
     IonCode *code = linker.newCode(cx, JSC::OTHER_CODE);
     IonSpew(IonSpew_Invalidate, "   invalidation thunk created at %p", (void *) code->raw());
     return code;
 }
 
 IonCode *
 IonRuntime::generateArgumentsRectifier(JSContext *cx, ExecutionMode mode, void **returnAddrOut)
@@ -451,17 +455,17 @@ IonRuntime::generateArgumentsRectifier(J
     CodeOffsetLabel returnLabel(returnOffset);
     returnLabel.fixup(&masm);
     if (returnAddrOut)
         *returnAddrOut = (void *) (code->raw() + returnLabel.offset());
     return code;
 }
 
 static void
-GenerateBailoutThunk(MacroAssembler &masm, uint32_t frameClass)
+GenerateBailoutThunk(JSContext *cx, MacroAssembler &masm, uint32_t frameClass)
 {
     // the stack should look like:
     // [IonFrame]
     // bailoutFrame.registersnapshot
     // bailoutFrame.fpsnapshot
     // bailoutFrame.snapshotOffset
     // bailoutFrame.frameSize
 
@@ -505,20 +509,16 @@ GenerateBailoutThunk(MacroAssembler &mas
     // STEP 1c: Call the bailout function, giving a pointer to the
     //          structure we just blitted onto the stack
     masm.ma_mov(sp, r0);
     const int sizeOfBailoutInfo = sizeof(void *)*2;
     masm.reserveStack(sizeOfBailoutInfo);
     masm.mov(sp, r1);
     masm.setupAlignedABICall(2);
 
-    // Copy the present stack pointer into a temp register (it happens to be the
-    // argument register)
-    //masm.as_mov(r0, O2Reg(sp));
-
     // Decrement sp by another 4, so we keep alignment
     // Not Anymore!  pushing both the snapshotoffset as well as the
     // masm.as_sub(sp, sp, Imm8(4));
 
     // Set the old (4-byte aligned) value of the sp as the first argument
     masm.passABIArg(r0);
     masm.passABIArg(r1);
 
@@ -545,40 +545,43 @@ GenerateBailoutThunk(MacroAssembler &mas
         masm.as_add(sp, sp, O2Reg(r4));
     } else {
         uint32_t frameSize = FrameSizeClass::FromClass(frameClass).frameSize();
         masm.ma_add(Imm32(frameSize // the frame that was added when we entered the most recent function
                           + sizeof(void*) // the size of the "return address" that was dumped on the stack
                           + bailoutFrameSize) // everything else that was pushed on the stack
                     , sp);
     }
-    masm.generateBailoutTail(r1, r2);
+
+    // Jump to shared bailout tail. The BailoutInfo pointer has to be in r2.
+    IonCode *bailoutTail = cx->compartment()->ionCompartment()->getBailoutTail();
+    masm.branch(bailoutTail);
 }
 
 IonCode *
 IonRuntime::generateBailoutTable(JSContext *cx, uint32_t frameClass)
 {
     MacroAssembler masm(cx);
 
     Label bailout;
     for (size_t i = 0; i < BAILOUT_TABLE_SIZE; i++)
         masm.ma_bl(&bailout);
     masm.bind(&bailout);
 
-    GenerateBailoutThunk(masm, frameClass);
+    GenerateBailoutThunk(cx, masm, frameClass);
 
     Linker linker(masm);
     return linker.newCode(cx, JSC::OTHER_CODE);
 }
 
 IonCode *
 IonRuntime::generateBailoutHandler(JSContext *cx)
 {
     MacroAssembler masm(cx);
-    GenerateBailoutThunk(masm, NO_FRAME_SIZE_CLASS_ID);
+    GenerateBailoutThunk(cx, masm, NO_FRAME_SIZE_CLASS_ID);
 
     Linker linker(masm);
     return linker.newCode(cx, JSC::OTHER_CODE);
 }
 
 IonCode *
 IonRuntime::generateVMWrapper(JSContext *cx, const VMFunction &f)
 {
@@ -830,8 +833,19 @@ IonRuntime::generateExceptionTailStub(JS
 {
     MacroAssembler masm;
 
     masm.handleFailureWithHandlerTail();
 
     Linker linker(masm);
     return linker.newCode(cx, JSC::OTHER_CODE);
 }
+
+IonCode *
+IonRuntime::generateBailoutTailStub(JSContext *cx)
+{
+    MacroAssembler masm;
+
+    masm.generateBailoutTail(r1, r2);
+
+    Linker linker(masm);
+    return linker.newCode(cx, JSC::OTHER_CODE);
+}
--- a/js/src/ion/x64/Trampoline-x64.cpp
+++ b/js/src/ion/x64/Trampoline-x64.cpp
@@ -305,17 +305,19 @@ IonRuntime::generateInvalidator(JSContex
     masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, InvalidationBailout));
 
     masm.pop(r9); // Get the bailoutInfo outparam.
     masm.pop(rbx); // Get the frameSize outparam.
 
     // Pop the machine state and the dead frame.
     masm.lea(Operand(rsp, rbx, TimesOne, sizeof(InvalidationBailoutStack)), rsp);
 
-    masm.generateBailoutTail(rdx, r9);
+    // Jump to shared bailout tail. The BailoutInfo pointer has to be in r9.
+    IonCode *bailoutTail = cx->compartment()->ionCompartment()->getBailoutTail();
+    masm.jmp(bailoutTail);
 
     Linker linker(masm);
     return linker.newCode(cx, JSC::OTHER_CODE);
 }
 
 IonCode *
 IonRuntime::generateArgumentsRectifier(JSContext *cx, ExecutionMode mode, void **returnAddrOut)
 {
@@ -437,17 +439,19 @@ GenerateBailoutThunk(JSContext *cx, Macr
     //
     // Remove both the bailout frame and the topmost Ion frame's stack.
     static const uint32_t BailoutDataSize = sizeof(void *) * Registers::Total +
                                           sizeof(double) * FloatRegisters::Total;
     masm.addq(Imm32(BailoutDataSize), rsp);
     masm.pop(rcx);
     masm.lea(Operand(rsp, rcx, TimesOne, sizeof(void *)), rsp);
 
-    masm.generateBailoutTail(rdx, r9);
+    // Jump to shared bailout tail. The BailoutInfo pointer has to be in r9.
+    IonCode *bailoutTail = cx->compartment()->ionCompartment()->getBailoutTail();
+    masm.jmp(bailoutTail);
 }
 
 IonCode *
 IonRuntime::generateBailoutTable(JSContext *cx, uint32_t frameClass)
 {
     MOZ_ASSUME_UNREACHABLE("x64 does not use bailout tables");
 }
 
@@ -721,8 +725,19 @@ IonRuntime::generateExceptionTailStub(JS
 {
     MacroAssembler masm;
 
     masm.handleFailureWithHandlerTail();
 
     Linker linker(masm);
     return linker.newCode(cx, JSC::OTHER_CODE);
 }
+
+IonCode *
+IonRuntime::generateBailoutTailStub(JSContext *cx)
+{
+    MacroAssembler masm;
+
+    masm.generateBailoutTail(rdx, r9);
+
+    Linker linker(masm);
+    return linker.newCode(cx, JSC::OTHER_CODE);
+}
--- a/js/src/ion/x86/Trampoline-x86.cpp
+++ b/js/src/ion/x86/Trampoline-x86.cpp
@@ -291,17 +291,19 @@ IonRuntime::generateInvalidator(JSContex
     masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, InvalidationBailout));
 
     masm.pop(ecx); // Get bailoutInfo outparam.
     masm.pop(ebx); // Get the frameSize outparam.
 
     // Pop the machine state and the dead frame.
     masm.lea(Operand(esp, ebx, TimesOne, sizeof(InvalidationBailoutStack)), esp);
 
-    masm.generateBailoutTail(edx, ecx);
+    // Jump to shared bailout tail. The BailoutInfo pointer has to be in ecx.
+    IonCode *bailoutTail = cx->compartment()->ionCompartment()->getBailoutTail();
+    masm.jmp(bailoutTail);
 
     Linker linker(masm);
     IonCode *code = linker.newCode(cx, JSC::OTHER_CODE);
     IonSpew(IonSpew_Invalidate, "   invalidation thunk created at %p", (void *) code->raw());
     return code;
 }
 
 IonCode *
@@ -425,44 +427,46 @@ GenerateBailoutThunk(JSContext *cx, Macr
     masm.movl(esp, ebx);
 
     // Call the bailout function. This will correct the size of the bailout.
     masm.setupUnalignedABICall(2, ecx);
     masm.passABIArg(eax);
     masm.passABIArg(ebx);
     masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, Bailout));
 
-    masm.pop(ebx); // Get bailoutInfo outparam.
+    masm.pop(ecx); // Get bailoutInfo outparam.
 
     // Common size of stuff we've pushed.
     const uint32_t BailoutDataSize = sizeof(void *) + // frameClass
                                    sizeof(double) * FloatRegisters::Total +
                                    sizeof(void *) * Registers::Total;
 
     // Remove both the bailout frame and the topmost Ion frame's stack.
     if (frameClass == NO_FRAME_SIZE_CLASS_ID) {
         // We want the frameSize. Stack is:
         //    ... frame ...
         //    snapshotOffset
         //    frameSize
         //    ... bailoutFrame ...
         masm.addl(Imm32(BailoutDataSize), esp);
-        masm.pop(ecx);
+        masm.pop(ebx);
         masm.addl(Imm32(sizeof(uint32_t)), esp);
-        masm.addl(ecx, esp);
+        masm.addl(ebx, esp);
     } else {
         // Stack is:
         //    ... frame ...
         //    bailoutId
         //    ... bailoutFrame ...
         uint32_t frameSize = FrameSizeClass::FromClass(frameClass).frameSize();
         masm.addl(Imm32(BailoutDataSize + sizeof(void *) + frameSize), esp);
     }
 
-    masm.generateBailoutTail(edx, ebx);
+    // Jump to shared bailout tail. The BailoutInfo pointer has to be in ecx.
+    IonCode *bailoutTail = cx->compartment()->ionCompartment()->getBailoutTail();
+    masm.jmp(bailoutTail);
 }
 
 IonCode *
 IonRuntime::generateBailoutTable(JSContext *cx, uint32_t frameClass)
 {
     MacroAssembler masm;
 
     Label bailout;
@@ -747,8 +751,19 @@ IonRuntime::generateExceptionTailStub(JS
 {
     MacroAssembler masm;
 
     masm.handleFailureWithHandlerTail();
 
     Linker linker(masm);
     return linker.newCode(cx, JSC::OTHER_CODE);
 }
+
+IonCode *
+IonRuntime::generateBailoutTailStub(JSContext *cx)
+{
+    MacroAssembler masm;
+
+    masm.generateBailoutTail(edx, ecx);
+
+    Linker linker(masm);
+    return linker.newCode(cx, JSC::OTHER_CODE);
+}