Bug 1109889 - Share more exception handling code. r=nbp, a=abillings
authorJan de Mooij <jdemooij@mozilla.com>
Tue, 16 Dec 2014 22:52:51 +0100
changeset 234241 942a5a358648162fd16973a2bfca71d91a607dd5
parent 234240 7c0b02faa71c2cfc8d73c712c8d3061291bda9ed
child 234242 096a9cc7a37904b23d17ba65ea4554d03c97ac78
push id4246
push userryanvm@gmail.com
push dateThu, 18 Dec 2014 15:27:54 +0000
treeherdermozilla-beta@6758b70a72cd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp, abillings
bugs1109889
milestone35.0
Bug 1109889 - Share more exception handling code. r=nbp, a=abillings
js/src/jit/Ion.cpp
js/src/jit/JitCompartment.h
js/src/jit/MacroAssembler.cpp
js/src/jit/arm/MacroAssembler-arm.cpp
js/src/jit/arm/MacroAssembler-arm.h
js/src/jit/arm/Trampoline-arm.cpp
js/src/jit/mips/MacroAssembler-mips.cpp
js/src/jit/mips/MacroAssembler-mips.h
js/src/jit/mips/Trampoline-mips.cpp
js/src/jit/none/Trampoline-none.cpp
js/src/jit/shared/MacroAssembler-x86-shared.h
js/src/jit/x64/MacroAssembler-x64.cpp
js/src/jit/x64/MacroAssembler-x64.h
js/src/jit/x64/Trampoline-x64.cpp
js/src/jit/x86/MacroAssembler-x86.cpp
js/src/jit/x86/MacroAssembler-x86.h
js/src/jit/x86/Trampoline-x86.cpp
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -150,16 +150,17 @@ jit::InitializeIon()
     CheckPerf();
     return true;
 }
 
 JitRuntime::JitRuntime()
   : execAlloc_(nullptr),
     ionAlloc_(nullptr),
     exceptionTail_(nullptr),
+    exceptionTailParallel_(nullptr),
     bailoutTail_(nullptr),
     enterJIT_(nullptr),
     bailoutHandler_(nullptr),
     argumentsRectifier_(nullptr),
     argumentsRectifierReturnAddr_(nullptr),
     parallelArgumentsRectifier_(nullptr),
     invalidator_(nullptr),
     debugTrapHandler_(nullptr),
@@ -204,20 +205,28 @@ JitRuntime::initialize(JSContext *cx)
     if (!cx->compartment()->ensureJitCompartmentExists(cx))
         return false;
 
     functionWrappers_ = cx->new_<VMWrapperMap>(cx);
     if (!functionWrappers_ || !functionWrappers_->init())
         return false;
 
     JitSpew(JitSpew_Codegen, "# Emitting exception tail stub");
-    exceptionTail_ = generateExceptionTailStub(cx);
+
+    void *handler = JS_FUNC_TO_DATA_PTR(void *, jit::HandleException);
+    void *handlerParallel = JS_FUNC_TO_DATA_PTR(void *, jit::HandleParallelFailure);
+
+    exceptionTail_ = generateExceptionTailStub(cx, handler);
     if (!exceptionTail_)
         return false;
 
+    exceptionTailParallel_ = generateExceptionTailStub(cx, handlerParallel);
+    if (!exceptionTailParallel_)
+        return false;
+
     JitSpew(JitSpew_Codegen, "# Emitting bailout tail stub");
     bailoutTail_ = generateBailoutTailStub(cx);
     if (!bailoutTail_)
         return false;
 
     if (cx->runtime()->jitSupportsFloatingPoint) {
         JitSpew(JitSpew_Codegen, "# Emitting bailout tables");
 
--- a/js/src/jit/JitCompartment.h
+++ b/js/src/jit/JitCompartment.h
@@ -147,18 +147,19 @@ class JitRuntime
 
     // Executable allocator used for allocating the main code in an IonScript.
     // All accesses on this allocator must be protected by the runtime's
     // interrupt lock, as the executable memory may be protected() when
     // requesting an interrupt to force a fault in the Ion code and avoid the
     // need for explicit interrupt checks.
     ExecutableAllocator *ionAlloc_;
 
-    // Shared post-exception-handler tail
+    // Shared exception-handler tail.
     JitCode *exceptionTail_;
+    JitCode *exceptionTailParallel_;
 
     // Shared post-bailout-handler tail.
     JitCode *bailoutTail_;
 
     // Trampoline for entering JIT code. Contains OSR prologue.
     JitCode *enterJIT_;
 
     // Trampoline for entering baseline JIT code.
@@ -238,17 +239,17 @@ class JitRuntime
     // their callee.
     js::Value ionReturnOverride_;
 
     // Global table of jitcode native address => bytecode address mappings.
     JitcodeGlobalTable *jitcodeGlobalTable_;
 
   private:
     JitCode *generateLazyLinkStub(JSContext *cx);
-    JitCode *generateExceptionTailStub(JSContext *cx);
+    JitCode *generateExceptionTailStub(JSContext *cx, void *handler);
     JitCode *generateBailoutTailStub(JSContext *cx);
     JitCode *generateEnterJIT(JSContext *cx, EnterJitType type);
     JitCode *generateArgumentsRectifier(JSContext *cx, ExecutionMode mode, void **returnAddrOut);
     JitCode *generateBailoutTable(JSContext *cx, uint32_t frameClass);
     JitCode *generateBailoutHandler(JSContext *cx, ExecutionMode mode);
     JitCode *generateInvalidator(JSContext *cx);
     JitCode *generatePreBarrier(JSContext *cx, MIRType type);
     JitCode *generateMallocStub(JSContext *cx);
@@ -321,16 +322,19 @@ class JitRuntime
           case ParallelExecution:   return parallelBailoutHandler_;
           default:                  MOZ_CRASH("No such execution mode");
         }
     }
 
     JitCode *getExceptionTail() const {
         return exceptionTail_;
     }
+    JitCode *getExceptionTailParallel() const {
+        return exceptionTailParallel_;
+    }
 
     JitCode *getBailoutTail() const {
         return bailoutTail_;
     }
 
     JitCode *getBailoutTable(const FrameSizeClass &frameClass) const;
 
     JitCode *getArgumentsRectifier(ExecutionMode mode) const {
--- a/js/src/jit/MacroAssembler.cpp
+++ b/js/src/jit/MacroAssembler.cpp
@@ -1336,28 +1336,28 @@ void
 MacroAssembler::handleFailure(ExecutionMode executionMode)
 {
     // Re-entry code is irrelevant because the exception will leave the
     // running function and never come back
     if (sps_)
         sps_->skipNextReenter();
     leaveSPSFrame();
 
-    void *handler;
+    JitCode *excTail;
     switch (executionMode) {
       case SequentialExecution:
-        handler = JS_FUNC_TO_DATA_PTR(void *, jit::HandleException);
+        excTail = GetJitContext()->runtime->jitRuntime()->getExceptionTail();
         break;
       case ParallelExecution:
-        handler = JS_FUNC_TO_DATA_PTR(void *, jit::HandleParallelFailure);
+        excTail = GetJitContext()->runtime->jitRuntime()->getExceptionTailParallel();
         break;
       default:
         MOZ_CRASH("No such execution mode");
     }
-    MacroAssemblerSpecific::handleFailureWithHandler(handler);
+    jump(excTail);
 
     // Doesn't actually emit code, but balances the leave()
     if (sps_)
         sps_->reenter(*this, InvalidReg);
 }
 
 #ifdef DEBUG
 static void
--- a/js/src/jit/arm/MacroAssembler-arm.cpp
+++ b/js/src/jit/arm/MacroAssembler-arm.cpp
@@ -4170,36 +4170,29 @@ MacroAssemblerARMCompat::callWithABI(Reg
     ma_mov(fun, r12);
     uint32_t stackAdjust;
     callWithABIPre(&stackAdjust);
     call(r12);
     callWithABIPost(stackAdjust, result);
 }
 
 void
-MacroAssemblerARMCompat::handleFailureWithHandler(void *handler)
+MacroAssemblerARMCompat::handleFailureWithHandlerTail(void *handler)
 {
     // Reserve space for exception information.
     int size = (sizeof(ResumeFromException) + 7) & ~7;
 
     ma_sub(Imm32(size), sp);
     ma_mov(sp, r0);
 
-    // Ask for an exception handler.
+    // Call the handler.
     setupUnalignedABICall(1, r1);
     passABIArg(r0);
     callWithABI(handler);
 
-    JitCode *excTail = GetJitContext()->runtime->jitRuntime()->getExceptionTail();
-    branch(excTail);
-}
-
-void
-MacroAssemblerARMCompat::handleFailureWithHandlerTail()
-{
     Label entryFrame;
     Label catch_;
     Label finally;
     Label return_;
     Label bailout;
 
     ma_ldr(Operand(sp, offsetof(ResumeFromException, kind)), r0);
     branch32(Assembler::Equal, r0, Imm32(ResumeFromException::RESUME_ENTRY_FRAME), &entryFrame);
--- a/js/src/jit/arm/MacroAssembler-arm.h
+++ b/js/src/jit/arm/MacroAssembler-arm.h
@@ -681,16 +681,19 @@ class MacroAssemblerARMCompat : public M
     }
     CodeOffsetLabel movWithPatch(ImmPtr imm, Register dest) {
         return movWithPatch(ImmWord(uintptr_t(imm.value)), dest);
     }
 
     void jump(Label *label) {
         as_b(label);
     }
+    void jump(JitCode *code) {
+        branch(code);
+    }
     void jump(Register reg) {
         ma_bx(reg);
     }
     void jump(const Address &address) {
         ma_ldr(Operand(address.base, address.offset), ScratchRegister);
         ma_bx(ScratchRegister);
     }
 
@@ -1201,18 +1204,17 @@ class MacroAssemblerARMCompat : public M
     void storeTypeTag(ImmTag tag, Operand dest);
     void storeTypeTag(ImmTag tag, const BaseIndex &dest);
 
     void makeFrameDescriptor(Register frameSizeReg, FrameType type) {
         ma_lsl(Imm32(FRAMESIZE_SHIFT), frameSizeReg, frameSizeReg);
         ma_orr(Imm32(type), frameSizeReg);
     }
 
-    void handleFailureWithHandler(void *handler);
-    void handleFailureWithHandlerTail();
+    void handleFailureWithHandlerTail(void *handler);
 
     /////////////////////////////////////////////////////////////////
     // Common interface.
     /////////////////////////////////////////////////////////////////
   public:
     // The following functions are exposed for use in platform-shared code.
     void Push(Register reg) {
         ma_push(reg);
--- a/js/src/jit/arm/Trampoline-arm.cpp
+++ b/js/src/jit/arm/Trampoline-arm.cpp
@@ -990,21 +990,21 @@ JitRuntime::generateDebugTrapHandler(JSC
 #ifdef JS_ION_PERF
     writePerfSpewerJitCodeProfile(codeDbg, "DebugTrapHandler");
 #endif
 
     return codeDbg;
 }
 
 JitCode *
-JitRuntime::generateExceptionTailStub(JSContext *cx)
+JitRuntime::generateExceptionTailStub(JSContext *cx, void *handler)
 {
     MacroAssembler masm;
 
-    masm.handleFailureWithHandlerTail();
+    masm.handleFailureWithHandlerTail(handler);
 
     Linker linker(masm);
     AutoFlushICache afc("ExceptionTailStub");
     JitCode *code = linker.newCode<NoGC>(cx, OTHER_CODE);
 
 #ifdef JS_ION_PERF
     writePerfSpewerJitCodeProfile(code, "ExceptionTailStub");
 #endif
--- a/js/src/jit/mips/MacroAssembler-mips.cpp
+++ b/js/src/jit/mips/MacroAssembler-mips.cpp
@@ -3447,35 +3447,28 @@ MacroAssemblerMIPSCompat::callWithABI(Re
     ma_move(t9, fun);
     uint32_t stackAdjust;
     callWithABIPre(&stackAdjust);
     call(t9);
     callWithABIPost(stackAdjust, result);
 }
 
 void
-MacroAssemblerMIPSCompat::handleFailureWithHandler(void *handler)
+MacroAssemblerMIPSCompat::handleFailureWithHandlerTail(void *handler)
 {
     // Reserve space for exception information.
     int size = (sizeof(ResumeFromException) + ABIStackAlignment) & ~(ABIStackAlignment - 1);
     ma_subu(StackPointer, StackPointer, Imm32(size));
     ma_move(a0, StackPointer); // Use a0 since it is a first function argument
 
-    // Ask for an exception handler.
+    // Call the handler.
     setupUnalignedABICall(1, a1);
     passABIArg(a0);
     callWithABI(handler);
 
-    JitCode *excTail = GetJitContext()->runtime->jitRuntime()->getExceptionTail();
-    branch(excTail);
-}
-
-void
-MacroAssemblerMIPSCompat::handleFailureWithHandlerTail()
-{
     Label entryFrame;
     Label catch_;
     Label finally;
     Label return_;
     Label bailout;
 
     // Already clobbered a0, so use it...
     ma_lw(a0, Address(StackPointer, offsetof(ResumeFromException, kind)));
--- a/js/src/jit/mips/MacroAssembler-mips.h
+++ b/js/src/jit/mips/MacroAssembler-mips.h
@@ -513,16 +513,20 @@ class MacroAssemblerMIPSCompat : public 
         as_nop();
     }
     void jump(const Address &address) {
         ma_lw(ScratchRegister, address);
         as_jr(ScratchRegister);
         as_nop();
     }
 
+    void jump(JitCode *code) {
+        branch(code);
+    }
+
     void neg32(Register reg) {
         ma_negu(reg, reg);
     }
     void negl(Register reg) {
         ma_negu(reg, reg);
     }
 
     // Returns the register containing the type tag.
@@ -910,18 +914,17 @@ public:
     void storeTypeTag(ImmTag tag, Address dest);
     void storeTypeTag(ImmTag tag, const BaseIndex &dest);
 
     void makeFrameDescriptor(Register frameSizeReg, FrameType type) {
         ma_sll(frameSizeReg, frameSizeReg, Imm32(FRAMESIZE_SHIFT));
         ma_or(frameSizeReg, frameSizeReg, Imm32(type));
     }
 
-    void handleFailureWithHandler(void *handler);
-    void handleFailureWithHandlerTail();
+    void handleFailureWithHandlerTail(void *handler);
 
     /////////////////////////////////////////////////////////////////
     // Common interface.
     /////////////////////////////////////////////////////////////////
   public:
     // The following functions are exposed for use in platform-shared code.
     void Push(Register reg) {
         ma_push(reg);
--- a/js/src/jit/mips/Trampoline-mips.cpp
+++ b/js/src/jit/mips/Trampoline-mips.cpp
@@ -1001,21 +1001,21 @@ JitRuntime::generateDebugTrapHandler(JSC
     writePerfSpewerJitCodeProfile(codeDbg, "DebugTrapHandler");
 #endif
 
     return codeDbg;
 }
 
 
 JitCode *
-JitRuntime::generateExceptionTailStub(JSContext *cx)
+JitRuntime::generateExceptionTailStub(JSContext *cx, void *handler)
 {
     MacroAssembler masm;
 
-    masm.handleFailureWithHandlerTail();
+    masm.handleFailureWithHandlerTail(handler);
 
     Linker linker(masm);
     AutoFlushICache afc("ExceptionTailStub");
     JitCode *code = linker.newCode<NoGC>(cx, OTHER_CODE);
 
 #ifdef JS_ION_PERF
     writePerfSpewerJitCodeProfile(code, "ExceptionTailStub");
 #endif
--- a/js/src/jit/none/Trampoline-none.cpp
+++ b/js/src/jit/none/Trampoline-none.cpp
@@ -20,17 +20,17 @@ using namespace js::jit;
 JitCode *JitRuntime::generateEnterJIT(JSContext *, EnterJitType) { MOZ_CRASH(); }
 JitCode *JitRuntime::generateInvalidator(JSContext *) { MOZ_CRASH(); }
 JitCode *JitRuntime::generateArgumentsRectifier(JSContext *, ExecutionMode, void **) { MOZ_CRASH(); }
 JitCode *JitRuntime::generateBailoutTable(JSContext *, uint32_t) { MOZ_CRASH(); }
 JitCode *JitRuntime::generateBailoutHandler(JSContext *, ExecutionMode) { MOZ_CRASH(); }
 JitCode *JitRuntime::generateVMWrapper(JSContext *, const VMFunction &) { MOZ_CRASH(); }
 JitCode *JitRuntime::generatePreBarrier(JSContext *, MIRType) { MOZ_CRASH(); }
 JitCode *JitRuntime::generateDebugTrapHandler(JSContext *) { MOZ_CRASH(); }
-JitCode *JitRuntime::generateExceptionTailStub(JSContext *) { MOZ_CRASH(); }
+JitCode *JitRuntime::generateExceptionTailStub(JSContext *, void *) { MOZ_CRASH(); }
 JitCode *JitRuntime::generateBailoutTailStub(JSContext *) { MOZ_CRASH(); }
 JitCode *JitRuntime::generateForkJoinGetSliceStub(JSContext *) { MOZ_CRASH(); }
 
 FrameSizeClass FrameSizeClass::FromDepth(uint32_t) { MOZ_CRASH(); }
 FrameSizeClass FrameSizeClass::ClassLimit() { MOZ_CRASH(); }
 uint32_t FrameSizeClass::frameSize() const { MOZ_CRASH(); }
 
 void DispatchIonCache::initializeAddCacheState(LInstruction *, AddCacheState *) { MOZ_CRASH(); }
--- a/js/src/jit/shared/MacroAssembler-x86-shared.h
+++ b/js/src/jit/shared/MacroAssembler-x86-shared.h
@@ -291,16 +291,19 @@ class MacroAssemblerX86Shared : public A
     }
     void setFramePushed(uint32_t framePushed) {
         framePushed_ = framePushed;
     }
 
     void jump(Label *label) {
         jmp(label);
     }
+    void jump(JitCode *code) {
+        jmp(code);
+    }
     void jump(RepatchLabel *label) {
         jmp(label);
     }
     void jump(Register reg) {
         jmp(Operand(reg));
     }
     void jump(const Address &addr) {
         jmp(Operand(addr));
--- a/js/src/jit/x64/MacroAssembler-x64.cpp
+++ b/js/src/jit/x64/MacroAssembler-x64.cpp
@@ -373,34 +373,27 @@ MacroAssemblerX64::callWithABI(Register 
 
     uint32_t stackAdjust;
     callWithABIPre(&stackAdjust);
     call(Operand(fun));
     callWithABIPost(stackAdjust, result);
 }
 
 void
-MacroAssemblerX64::handleFailureWithHandler(void *handler)
+MacroAssemblerX64::handleFailureWithHandlerTail(void *handler)
 {
     // Reserve space for exception information.
     subq(Imm32(sizeof(ResumeFromException)), rsp);
     movq(rsp, rax);
 
-    // Ask for an exception handler.
+    // Call the handler.
     setupUnalignedABICall(1, rcx);
     passABIArg(rax);
     callWithABI(handler);
 
-    JitCode *excTail = GetJitContext()->runtime->jitRuntime()->getExceptionTail();
-    jmp(excTail);
-}
-
-void
-MacroAssemblerX64::handleFailureWithHandlerTail()
-{
     Label entryFrame;
     Label catch_;
     Label finally;
     Label return_;
     Label bailout;
 
     loadPtr(Address(rsp, offsetof(ResumeFromException, kind)), rax);
     branch32(Assembler::Equal, rax, Imm32(ResumeFromException::RESUME_ENTRY_FRAME), &entryFrame);
--- a/js/src/jit/x64/MacroAssembler-x64.h
+++ b/js/src/jit/x64/MacroAssembler-x64.h
@@ -1380,18 +1380,17 @@ class MacroAssemblerX64 : public MacroAs
 
   public:
     // Emits a call to a C/C++ function, resolving all argument moves.
     void callWithABI(void *fun, MoveOp::Type result = MoveOp::GENERAL);
     void callWithABI(AsmJSImmPtr imm, MoveOp::Type result = MoveOp::GENERAL);
     void callWithABI(Address fun, MoveOp::Type result = MoveOp::GENERAL);
     void callWithABI(Register fun, MoveOp::Type result = MoveOp::GENERAL);
 
-    void handleFailureWithHandler(void *handler);
-    void handleFailureWithHandlerTail();
+    void handleFailureWithHandlerTail(void *handler);
 
     void makeFrameDescriptor(Register frameSizeReg, FrameType type) {
         shlq(Imm32(FRAMESIZE_SHIFT), frameSizeReg);
         orq(Imm32(type), frameSizeReg);
     }
 
     void callWithExitFrame(JitCode *target, Register dynStack) {
         addPtr(Imm32(framePushed()), dynStack);
--- a/js/src/jit/x64/Trampoline-x64.cpp
+++ b/js/src/jit/x64/Trampoline-x64.cpp
@@ -819,21 +819,21 @@ JitRuntime::generateDebugTrapHandler(JSC
 #ifdef JS_ION_PERF
     writePerfSpewerJitCodeProfile(codeDbg, "DebugTrapHandler");
 #endif
 
     return codeDbg;
 }
 
 JitCode *
-JitRuntime::generateExceptionTailStub(JSContext *cx)
+JitRuntime::generateExceptionTailStub(JSContext *cx, void *handler)
 {
     MacroAssembler masm;
 
-    masm.handleFailureWithHandlerTail();
+    masm.handleFailureWithHandlerTail(handler);
 
     Linker linker(masm);
     JitCode *code = linker.newCode<NoGC>(cx, OTHER_CODE);
 
 #ifdef JS_ION_PERF
     writePerfSpewerJitCodeProfile(code, "ExceptionTailStub");
 #endif
 
--- a/js/src/jit/x86/MacroAssembler-x86.cpp
+++ b/js/src/jit/x86/MacroAssembler-x86.cpp
@@ -353,34 +353,27 @@ MacroAssemblerX86::callWithABI(Register 
 {
     uint32_t stackAdjust;
     callWithABIPre(&stackAdjust);
     call(Operand(fun));
     callWithABIPost(stackAdjust, result);
 }
 
 void
-MacroAssemblerX86::handleFailureWithHandler(void *handler)
+MacroAssemblerX86::handleFailureWithHandlerTail(void *handler)
 {
     // Reserve space for exception information.
     subl(Imm32(sizeof(ResumeFromException)), esp);
     movl(esp, eax);
 
-    // Ask for an exception handler.
+    // Call the handler.
     setupUnalignedABICall(1, ecx);
     passABIArg(eax);
     callWithABI(handler);
 
-    JitCode *excTail = GetJitContext()->runtime->jitRuntime()->getExceptionTail();
-    jmp(excTail);
-}
-
-void
-MacroAssemblerX86::handleFailureWithHandlerTail()
-{
     Label entryFrame;
     Label catch_;
     Label finally;
     Label return_;
     Label bailout;
 
     loadPtr(Address(esp, offsetof(ResumeFromException, kind)), eax);
     branch32(Assembler::Equal, eax, Imm32(ResumeFromException::RESUME_ENTRY_FRAME), &entryFrame);
--- a/js/src/jit/x86/MacroAssembler-x86.h
+++ b/js/src/jit/x86/MacroAssembler-x86.h
@@ -1121,18 +1121,17 @@ class MacroAssemblerX86 : public MacroAs
   public:
     // Emits a call to a C/C++ function, resolving all argument moves.
     void callWithABI(void *fun, MoveOp::Type result = MoveOp::GENERAL);
     void callWithABI(AsmJSImmPtr fun, MoveOp::Type result = MoveOp::GENERAL);
     void callWithABI(const Address &fun, MoveOp::Type result = MoveOp::GENERAL);
     void callWithABI(Register fun, MoveOp::Type result = MoveOp::GENERAL);
 
     // Used from within an Exit frame to handle a pending exception.
-    void handleFailureWithHandler(void *handler);
-    void handleFailureWithHandlerTail();
+    void handleFailureWithHandlerTail(void *handler);
 
     void makeFrameDescriptor(Register frameSizeReg, FrameType type) {
         shll(Imm32(FRAMESIZE_SHIFT), frameSizeReg);
         orl(Imm32(type), frameSizeReg);
     }
 
     void callWithExitFrame(JitCode *target, Register dynStack) {
         addPtr(Imm32(framePushed()), dynStack);
--- a/js/src/jit/x86/Trampoline-x86.cpp
+++ b/js/src/jit/x86/Trampoline-x86.cpp
@@ -859,21 +859,21 @@ JitRuntime::generateDebugTrapHandler(JSC
 #ifdef JS_ION_PERF
     writePerfSpewerJitCodeProfile(codeDbg, "DebugTrapHandler");
 #endif
 
     return codeDbg;
 }
 
 JitCode *
-JitRuntime::generateExceptionTailStub(JSContext *cx)
+JitRuntime::generateExceptionTailStub(JSContext *cx, void *handler)
 {
     MacroAssembler masm;
 
-    masm.handleFailureWithHandlerTail();
+    masm.handleFailureWithHandlerTail(handler);
 
     Linker linker(masm);
     JitCode *code = linker.newCode<NoGC>(cx, OTHER_CODE);
 
 #ifdef JS_ION_PERF
     writePerfSpewerJitCodeProfile(code, "ExceptionTailStub");
 #endif