Title: [172867] trunk/Source/_javascript_Core
Revision
172867
Author
msab...@apple.com
Date
2014-08-22 12:54:30 -0700 (Fri, 22 Aug 2014)

Log Message

REGRESSION(r163179): Sporadic crash in js/dom/line-column-numbers.html test
https://bugs.webkit.org/show_bug.cgi?id=136111

Reviewed by Filip Pizlo.

The problem was that we weren't properly handling VM::topVMEntryFrame in two ways.

First in the case where we get an exception of a stack overflow during setup of the direct
callee frame of a VM entry frame, we need to throw the exception in the caller's frame.
This requires unrolling topVMEntryFrame while creating the exception object.  This is
accomplished with the renamed NativeCallFrameTracerWithRestore object.  As part of this,
split the JIT rollback exception handling to call a new helper,
callLookupExceptionHandlerFromCallerFrame, which will unroll the callFrame and VMEntryFrame.

Second, when we unwind to find a handler, we also need to unwind topVMCallFrame for the
case where we end up (re)throwing another exception after entering the catch block, but
before another vmEntry call.  Added VM::vmEntryFrameForThrow as a way similar to
VM::callFrameForThrow to pass the appropriate VMENtryFrame to the catch block.


* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::compileExceptionHandlers):
* ftl/FTLCompile.cpp:
(JSC::FTL::fixFunctionBasedOnStackMaps):
* jit/JIT.cpp:
(JSC::JIT::privateCompileExceptionHandlers):
Split out the unroll cases to use the new helper callLookupExceptionHandlerFromCallerFrame()
to unwind both the callFrame and topVMEntryFrame.

* interpreter/Interpreter.cpp:
(JSC::UnwindFunctor::UnwindFunctor):
(JSC::UnwindFunctor::operator()):
(JSC::Interpreter::unwind):
* jit/JITExceptions.cpp:
(JSC::genericUnwind):
Added VMEntryFrame as another component to unwind.

* interpreter/Interpreter.h:
(JSC::NativeCallFrameTracer::NativeCallFrameTracer):
(JSC::NativeCallFrameTracerWithRestore::NativeCallFrameTracerWithRestore):
(JSC::NativeCallFrameTracerWithRestore::~NativeCallFrameTracerWithRestore):
Renamed and changed to save and restore topCallFrame and topVMEntryFrame around the setting of
both values.

* interpreter/StackVisitor.cpp:
(JSC::StackVisitor::gotoNextFrame):
(JSC::StackVisitor::readNonInlinedFrame):
* interpreter/StackVisitor.h:
(JSC::StackVisitor::Frame::vmEntryFrame):
Added code to unwind the VMEntryFrame.

* jit/CCallHelpers.h:
(JSC::CCallHelpers::jumpToExceptionHandler): Updated comment to indicate that the value
the handler should use for VM::topEntryFrame is in VM::vmEntryFrameForThrow.

* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_catch):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_catch):
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
Added code to update VM::topVMEntryFrame from VM::vmEntryFrameForThrowOffset.

* jit/JITOperations.cpp:
* jit/JITOperations.h:
(JSC::operationThrowStackOverflowError):
(JSC::operationCallArityCheck):
(JSC::operationConstructArityCheck):

* runtime/VM.h:
(JSC::VM::vmEntryFrameForThrowOffset):
(JSC::VM::topVMEntryFrameOffset):
Added as the side channel to return the topVMEntryFrame that the handler should use.

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (172866 => 172867)


--- trunk/Source/_javascript_Core/ChangeLog	2014-08-22 19:39:51 UTC (rev 172866)
+++ trunk/Source/_javascript_Core/ChangeLog	2014-08-22 19:54:30 UTC (rev 172867)
@@ -1,3 +1,79 @@
+2014-08-21  Michael Saboff  <msab...@apple.com>
+
+        REGRESSION(r163179): Sporadic crash in js/dom/line-column-numbers.html test
+        https://bugs.webkit.org/show_bug.cgi?id=136111
+
+        Reviewed by Filip Pizlo.
+
+        The problem was that we weren't properly handling VM::topVMEntryFrame in two ways.
+
+        First in the case where we get an exception of a stack overflow during setup of the direct
+        callee frame of a VM entry frame, we need to throw the exception in the caller's frame.
+        This requires unrolling topVMEntryFrame while creating the exception object.  This is
+        accomplished with the renamed NativeCallFrameTracerWithRestore object.  As part of this,
+        split the JIT rollback exception handling to call a new helper,
+        callLookupExceptionHandlerFromCallerFrame, which will unroll the callFrame and VMEntryFrame.
+
+        Second, when we unwind to find a handler, we also need to unwind topVMCallFrame for the
+        case where we end up (re)throwing another exception after entering the catch block, but
+        before another vmEntry call.  Added VM::vmEntryFrameForThrow as a way similar to
+        VM::callFrameForThrow to pass the appropriate VMENtryFrame to the catch block.
+
+
+        * dfg/DFGJITCompiler.cpp:
+        (JSC::DFG::JITCompiler::compileExceptionHandlers):
+        * ftl/FTLCompile.cpp:
+        (JSC::FTL::fixFunctionBasedOnStackMaps):
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileExceptionHandlers):
+        Split out the unroll cases to use the new helper callLookupExceptionHandlerFromCallerFrame()
+        to unwind both the callFrame and topVMEntryFrame.
+
+        * interpreter/Interpreter.cpp:
+        (JSC::UnwindFunctor::UnwindFunctor):
+        (JSC::UnwindFunctor::operator()):
+        (JSC::Interpreter::unwind):
+        * jit/JITExceptions.cpp:
+        (JSC::genericUnwind):
+        Added VMEntryFrame as another component to unwind.
+
+        * interpreter/Interpreter.h:
+        (JSC::NativeCallFrameTracer::NativeCallFrameTracer):
+        (JSC::NativeCallFrameTracerWithRestore::NativeCallFrameTracerWithRestore):
+        (JSC::NativeCallFrameTracerWithRestore::~NativeCallFrameTracerWithRestore):
+        Renamed and changed to save and restore topCallFrame and topVMEntryFrame around the setting of
+        both values.
+
+        * interpreter/StackVisitor.cpp:
+        (JSC::StackVisitor::gotoNextFrame):
+        (JSC::StackVisitor::readNonInlinedFrame):
+        * interpreter/StackVisitor.h:
+        (JSC::StackVisitor::Frame::vmEntryFrame):
+        Added code to unwind the VMEntryFrame.
+
+        * jit/CCallHelpers.h:
+        (JSC::CCallHelpers::jumpToExceptionHandler): Updated comment to indicate that the value
+        the handler should use for VM::topEntryFrame is in VM::vmEntryFrameForThrow.
+
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_catch):
+        * jit/JITOpcodes32_64.cpp:
+        (JSC::JIT::emit_op_catch):
+        * llint/LowLevelInterpreter32_64.asm:
+        * llint/LowLevelInterpreter64.asm:
+        Added code to update VM::topVMEntryFrame from VM::vmEntryFrameForThrowOffset.
+
+        * jit/JITOperations.cpp:
+        * jit/JITOperations.h:
+        (JSC::operationThrowStackOverflowError):
+        (JSC::operationCallArityCheck):
+        (JSC::operationConstructArityCheck):
+
+        * runtime/VM.h:
+        (JSC::VM::vmEntryFrameForThrowOffset):
+        (JSC::VM::topVMEntryFrameOffset):
+        Added as the side channel to return the topVMEntryFrame that the handler should use.
+
 2014-08-22  Daniel Bates  <daba...@apple.com>
 
         [iOS] Disable ENABLE_IOS_{GESTURE, TOUCH}_EVENTS, and temporarily disable ENABLE_TOUCH_EVENTS

Modified: trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp (172866 => 172867)


--- trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp	2014-08-22 19:39:51 UTC (rev 172866)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp	2014-08-22 19:54:30 UTC (rev 172867)
@@ -116,35 +116,39 @@
 
 void JITCompiler::compileExceptionHandlers()
 {
-    if (m_exceptionChecks.empty() && m_exceptionChecksWithCallFrameRollback.empty())
-        return;
+    if (!m_exceptionChecksWithCallFrameRollback.empty()) {
+        m_exceptionChecksWithCallFrameRollback.link(this);
 
-    Jump doLookup;
+        // lookupExceptionHandlerFromCallerFrame is passed two arguments, the VM and the exec (the CallFrame*).
+        move(TrustedImmPtr(vm()), GPRInfo::argumentGPR0);
+        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1);
 
-    if (!m_exceptionChecksWithCallFrameRollback.empty()) {
-        m_exceptionChecksWithCallFrameRollback.link(this);
-        emitGetCallerFrameFromCallFrameHeaderPtr(GPRInfo::argumentGPR1);
-        doLookup = jump();
+#if CPU(X86)
+        // FIXME: should use the call abstraction, but this is currently in the SpeculativeJIT layer!
+        poke(GPRInfo::argumentGPR0);
+        poke(GPRInfo::argumentGPR1, 1);
+#endif
+        m_calls.append(CallLinkRecord(call(), lookupExceptionHandlerFromCallerFrame));
+
+        jumpToExceptionHandler();
     }
 
-    if (!m_exceptionChecks.empty())
+    if (!m_exceptionChecks.empty()) {
         m_exceptionChecks.link(this);
 
-    // lookupExceptionHandler is passed two arguments, the VM and the exec (the CallFrame*).
-    move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1);
+        // lookupExceptionHandler is passed two arguments, the VM and the exec (the CallFrame*).
+        move(TrustedImmPtr(vm()), GPRInfo::argumentGPR0);
+        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1);
 
-    if (doLookup.isSet())
-        doLookup.link(this);
-
-    move(TrustedImmPtr(vm()), GPRInfo::argumentGPR0);
-
 #if CPU(X86)
-    // FIXME: should use the call abstraction, but this is currently in the SpeculativeJIT layer!
-    poke(GPRInfo::argumentGPR0);
-    poke(GPRInfo::argumentGPR1, 1);
+        // FIXME: should use the call abstraction, but this is currently in the SpeculativeJIT layer!
+        poke(GPRInfo::argumentGPR0);
+        poke(GPRInfo::argumentGPR1, 1);
 #endif
-    m_calls.append(CallLinkRecord(call(), lookupExceptionHandler));
-    jumpToExceptionHandler();
+        m_calls.append(CallLinkRecord(call(), lookupExceptionHandler));
+
+        jumpToExceptionHandler();
+    }
 }
 
 void JITCompiler::link(LinkBuffer& linkBuffer)

Modified: trunk/Source/_javascript_Core/ftl/FTLCompile.cpp (172866 => 172867)


--- trunk/Source/_javascript_Core/ftl/FTLCompile.cpp	2014-08-22 19:39:51 UTC (rev 172866)
+++ trunk/Source/_javascript_Core/ftl/FTLCompile.cpp	2014-08-22 19:54:30 UTC (rev 172867)
@@ -285,24 +285,28 @@
         
         // At this point it's perfectly fair to just blow away all state and restore the
         // JS JIT view of the universe.
+        checkJIT.move(MacroAssembler::TrustedImm64(TagTypeNumber), GPRInfo::tagTypeNumberRegister);
+        checkJIT.move(MacroAssembler::TrustedImm64(TagMask), GPRInfo::tagMaskRegister);
+
+        checkJIT.move(MacroAssembler::TrustedImmPtr(&vm), GPRInfo::argumentGPR0);
         checkJIT.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1);
+        MacroAssembler::Call callLookupExceptionHandler = checkJIT.call();
+        checkJIT.jumpToExceptionHandler();
 
-        MacroAssembler::Label exceptionContinueArg1Set = checkJIT.label();
+        stackOverflowException = checkJIT.label();
         checkJIT.move(MacroAssembler::TrustedImm64(TagTypeNumber), GPRInfo::tagTypeNumberRegister);
         checkJIT.move(MacroAssembler::TrustedImm64(TagMask), GPRInfo::tagMaskRegister);
 
         checkJIT.move(MacroAssembler::TrustedImmPtr(&vm), GPRInfo::argumentGPR0);
-        MacroAssembler::Call call = checkJIT.call();
+        checkJIT.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1);
+        MacroAssembler::Call callLookupExceptionHandlerFromCallerFrame = checkJIT.call();
         checkJIT.jumpToExceptionHandler();
 
-        stackOverflowException = checkJIT.label();
-        checkJIT.emitGetCallerFrameFromCallFrameHeaderPtr(GPRInfo::argumentGPR1);
-        checkJIT.jump(exceptionContinueArg1Set);
-
         OwnPtr<LinkBuffer> linkBuffer = adoptPtr(new LinkBuffer(
             vm, checkJIT, codeBlock, JITCompilationMustSucceed));
-        linkBuffer->link(call, FunctionPtr(lookupExceptionHandler));
-        
+        linkBuffer->link(callLookupExceptionHandler, FunctionPtr(lookupExceptionHandler));
+        linkBuffer->link(callLookupExceptionHandlerFromCallerFrame, FunctionPtr(lookupExceptionHandlerFromCallerFrame));
+
         state.finalizer->handleExceptionsLinkBuffer = linkBuffer.release();
     }
 

Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.cpp (172866 => 172867)


--- trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2014-08-22 19:39:51 UTC (rev 172866)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2014-08-22 19:54:30 UTC (rev 172867)
@@ -645,8 +645,9 @@
 
 class UnwindFunctor {
 public:
-    UnwindFunctor(CallFrame*& callFrame, bool isTermination, CodeBlock*& codeBlock, HandlerInfo*& handler)
-        : m_callFrame(callFrame)
+    UnwindFunctor(VMEntryFrame*& vmEntryFrame, CallFrame*& callFrame, bool isTermination, CodeBlock*& codeBlock, HandlerInfo*& handler)
+        : m_vmEntryFrame(vmEntryFrame)
+        , m_callFrame(callFrame)
         , m_isTermination(isTermination)
         , m_codeBlock(codeBlock)
         , m_handler(handler)
@@ -656,6 +657,7 @@
     StackVisitor::Status operator()(StackVisitor& visitor)
     {
         VM& vm = m_callFrame->vm();
+        m_vmEntryFrame = visitor->vmEntryFrame();
         m_callFrame = visitor->callFrame();
         m_codeBlock = visitor->codeBlock();
         unsigned bytecodeOffset = visitor->bytecodeOffset();
@@ -673,13 +675,14 @@
     }
 
 private:
+    VMEntryFrame*& m_vmEntryFrame;
     CallFrame*& m_callFrame;
     bool m_isTermination;
     CodeBlock*& m_codeBlock;
     HandlerInfo*& m_handler;
 };
 
-NEVER_INLINE HandlerInfo* Interpreter::unwind(CallFrame*& callFrame, JSValue& exceptionValue)
+NEVER_INLINE HandlerInfo* Interpreter::unwind(VMEntryFrame*& vmEntryFrame, CallFrame*& callFrame, JSValue& exceptionValue)
 {
     CodeBlock* codeBlock = callFrame->codeBlock();
     ASSERT(codeBlock);
@@ -724,7 +727,7 @@
     HandlerInfo* handler = 0;
     VM& vm = callFrame->vm();
     ASSERT(callFrame == vm.topCallFrame);
-    UnwindFunctor functor(callFrame, isTermination, codeBlock, handler);
+    UnwindFunctor functor(vmEntryFrame, callFrame, isTermination, codeBlock, handler);
     callFrame->iterate(functor);
     if (!handler)
         return 0;

Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.h (172866 => 172867)


--- trunk/Source/_javascript_Core/interpreter/Interpreter.h	2014-08-22 19:39:51 UTC (rev 172866)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.h	2014-08-22 19:54:30 UTC (rev 172867)
@@ -175,18 +175,33 @@
         {
             ASSERT(vm);
             ASSERT(callFrame);
-            ASSERT(callFrame < vm->topVMEntryFrame);
             vm->topCallFrame = callFrame;
         }
+    };
 
-        ALWAYS_INLINE NativeCallFrameTracer(VM* vm, VMEntryFrame* vmEntryFrame, CallFrame* callFrame)
+    class NativeCallFrameTracerWithRestore {
+    public:
+        ALWAYS_INLINE NativeCallFrameTracerWithRestore(VM* vm, VMEntryFrame* vmEntryFrame, CallFrame* callFrame)
+            : m_vm(vm)
         {
             ASSERT(vm);
             ASSERT(callFrame);
-            ASSERT(callFrame < vmEntryFrame);
+            m_savedTopVMEntryFrame = vm->topVMEntryFrame;
+            m_savedTopCallFrame = vm->topCallFrame;
             vm->topVMEntryFrame = vmEntryFrame;
             vm->topCallFrame = callFrame;
         }
+
+        ALWAYS_INLINE ~NativeCallFrameTracerWithRestore()
+        {
+            m_vm->topVMEntryFrame = m_savedTopVMEntryFrame;
+            m_vm->topCallFrame = m_savedTopCallFrame;
+        }
+
+    private:
+        VM* m_vm;
+        VMEntryFrame* m_savedTopVMEntryFrame;
+        CallFrame* m_savedTopCallFrame;
     };
 
     class Interpreter {
@@ -236,7 +251,7 @@
         
         SamplingTool* sampler() { return m_sampler.get(); }
 
-        NEVER_INLINE HandlerInfo* unwind(CallFrame*&, JSValue&);
+        NEVER_INLINE HandlerInfo* unwind(VMEntryFrame*&, CallFrame*&, JSValue&);
         NEVER_INLINE void debug(CallFrame*, DebugHookID);
         JSString* stackTraceAsString(ExecState*, Vector<StackFrame>);
 

Modified: trunk/Source/_javascript_Core/interpreter/StackVisitor.cpp (172866 => 172867)


--- trunk/Source/_javascript_Core/interpreter/StackVisitor.cpp	2014-08-22 19:39:51 UTC (rev 172866)
+++ trunk/Source/_javascript_Core/interpreter/StackVisitor.cpp	2014-08-22 19:54:30 UTC (rev 172867)
@@ -61,10 +61,11 @@
         InlineCallFrame* inlineCallFrame = m_frame.inlineCallFrame();
         CodeOrigin* callerCodeOrigin = &inlineCallFrame->caller;
         readInlinedFrame(m_frame.callFrame(), callerCodeOrigin);
-
-    } else
+        return;
+    }
 #endif // ENABLE(DFG_JIT)
-        readFrame(m_frame.callerFrame());
+    m_frame.m_VMEntryFrame = m_frame.m_CallerVMEntryFrame;
+    readFrame(m_frame.callerFrame());
 }
 
 void StackVisitor::readFrame(CallFrame* callFrame)
@@ -116,9 +117,9 @@
 {
     m_frame.m_callFrame = callFrame;
     m_frame.m_argumentCountIncludingThis = callFrame->argumentCountIncludingThis();
-    VMEntryFrame* currentVMEntryFrame = m_frame.m_VMEntryFrame;
-    m_frame.m_callerFrame = callFrame->callerFrame(m_frame.m_VMEntryFrame);
-    m_frame.m_callerIsVMEntryFrame = currentVMEntryFrame != m_frame.m_VMEntryFrame;
+    m_frame.m_CallerVMEntryFrame = m_frame.m_VMEntryFrame;
+    m_frame.m_callerFrame = callFrame->callerFrame(m_frame.m_CallerVMEntryFrame);
+    m_frame.m_callerIsVMEntryFrame = m_frame.m_CallerVMEntryFrame != m_frame.m_VMEntryFrame;
     m_frame.m_callee = callFrame->callee();
     m_frame.m_scope = callFrame->scope();
     m_frame.m_codeBlock = callFrame->codeBlock();

Modified: trunk/Source/_javascript_Core/interpreter/StackVisitor.h (172866 => 172867)


--- trunk/Source/_javascript_Core/interpreter/StackVisitor.h	2014-08-22 19:39:51 UTC (rev 172866)
+++ trunk/Source/_javascript_Core/interpreter/StackVisitor.h	2014-08-22 19:54:30 UTC (rev 172867)
@@ -81,6 +81,7 @@
 
         Arguments* createArguments();
         Arguments* existingArguments();
+        VMEntryFrame* vmEntryFrame() const { return m_VMEntryFrame; }
         CallFrame* callFrame() const { return m_callFrame; }
         
 #ifndef NDEBUG
@@ -97,6 +98,7 @@
         size_t m_index;
         size_t m_argumentCountIncludingThis;
         VMEntryFrame* m_VMEntryFrame;
+        VMEntryFrame* m_CallerVMEntryFrame;
         CallFrame* m_callerFrame;
         JSObject* m_callee;
         JSScope* m_scope;

Modified: trunk/Source/_javascript_Core/jit/CCallHelpers.h (172866 => 172867)


--- trunk/Source/_javascript_Core/jit/CCallHelpers.h	2014-08-22 19:39:51 UTC (rev 172866)
+++ trunk/Source/_javascript_Core/jit/CCallHelpers.h	2014-08-22 19:54:30 UTC (rev 172867)
@@ -1700,6 +1700,7 @@
     void jumpToExceptionHandler()
     {
         // genericUnwind() leaves the handler CallFrame* in vm->callFrameForThrow,
+        // the topVMEntryFrame for the handler in vm->vmEntryFrameForThrow,
         // and the address of the handler in vm->targetMachinePCForThrow.
         loadPtr(&vm()->targetMachinePCForThrow, GPRInfo::regT1);
         jump(GPRInfo::regT1);

Modified: trunk/Source/_javascript_Core/jit/JIT.cpp (172866 => 172867)


--- trunk/Source/_javascript_Core/jit/JIT.cpp	2014-08-22 19:39:51 UTC (rev 172866)
+++ trunk/Source/_javascript_Core/jit/JIT.cpp	2014-08-22 19:54:30 UTC (rev 172867)
@@ -722,35 +722,38 @@
 
 void JIT::privateCompileExceptionHandlers()
 {
-    if (m_exceptionChecks.empty() && m_exceptionChecksWithCallFrameRollback.empty())
-        return;
+    if (!m_exceptionChecksWithCallFrameRollback.empty()) {
+        m_exceptionChecksWithCallFrameRollback.link(this);
 
-    Jump doLookup;
+        // lookupExceptionHandlerFromCallerFrame is passed two arguments, the VM and the exec (the CallFrame*).
 
-    if (!m_exceptionChecksWithCallFrameRollback.empty()) {
-        m_exceptionChecksWithCallFrameRollback.link(this);
-        emitGetCallerFrameFromCallFrameHeaderPtr(GPRInfo::argumentGPR1);
-        doLookup = jump();
+        move(TrustedImmPtr(vm()), GPRInfo::argumentGPR0);
+        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1);
+
+#if CPU(X86)
+        // FIXME: should use the call abstraction, but this is currently in the SpeculativeJIT layer!
+        poke(GPRInfo::argumentGPR0);
+        poke(GPRInfo::argumentGPR1, 1);
+#endif
+        m_calls.append(CallRecord(call(), (unsigned)-1, FunctionPtr(lookupExceptionHandlerFromCallerFrame).value()));
+        jumpToExceptionHandler();
     }
 
-    if (!m_exceptionChecks.empty())
+    if (!m_exceptionChecks.empty()) {
         m_exceptionChecks.link(this);
-    
-    // lookupExceptionHandler is passed two arguments, the VM and the exec (the CallFrame*).
-    move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1);
 
-    if (doLookup.isSet())
-        doLookup.link(this);
+        // lookupExceptionHandler is passed two arguments, the VM and the exec (the CallFrame*).
+        move(TrustedImmPtr(vm()), GPRInfo::argumentGPR0);
+        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1);
 
-    move(TrustedImmPtr(vm()), GPRInfo::argumentGPR0);
-
 #if CPU(X86)
-    // FIXME: should use the call abstraction, but this is currently in the SpeculativeJIT layer!
-    poke(GPRInfo::argumentGPR0);
-    poke(GPRInfo::argumentGPR1, 1);
+        // FIXME: should use the call abstraction, but this is currently in the SpeculativeJIT layer!
+        poke(GPRInfo::argumentGPR0);
+        poke(GPRInfo::argumentGPR1, 1);
 #endif
-    m_calls.append(CallRecord(call(), (unsigned)-1, FunctionPtr(lookupExceptionHandler).value()));
-    jumpToExceptionHandler();
+        m_calls.append(CallRecord(call(), (unsigned)-1, FunctionPtr(lookupExceptionHandler).value()));
+        jumpToExceptionHandler();
+    }
 }
 
 unsigned JIT::frameRegisterCountFor(CodeBlock* codeBlock)

Modified: trunk/Source/_javascript_Core/jit/JITExceptions.cpp (172866 => 172867)


--- trunk/Source/_javascript_Core/jit/JITExceptions.cpp	2014-08-22 19:39:51 UTC (rev 172866)
+++ trunk/Source/_javascript_Core/jit/JITExceptions.cpp	2014-08-22 19:54:30 UTC (rev 172867)
@@ -48,7 +48,8 @@
     }
     
     RELEASE_ASSERT(exceptionValue);
-    HandlerInfo* handler = vm->interpreter->unwind(callFrame, exceptionValue); // This may update callFrame.
+    VMEntryFrame* vmEntryFrame = vm->topVMEntryFrame;
+    HandlerInfo* handler = vm->interpreter->unwind(vmEntryFrame, callFrame, exceptionValue); // This may update vmEntryFrame and callFrame.
 
     void* catchRoutine;
     Instruction* catchPCForInterpreter = 0;
@@ -62,6 +63,7 @@
     } else
         catchRoutine = LLInt::getCodePtr(handleUncaughtException);
     
+    vm->vmEntryFrameForThrow = vmEntryFrame;
     vm->callFrameForThrow = callFrame;
     vm->targetMachinePCForThrow = catchRoutine;
     vm->targetInterpreterPCForThrow = catchPCForInterpreter;

Modified: trunk/Source/_javascript_Core/jit/JITOpcodes.cpp (172866 => 172867)


--- trunk/Source/_javascript_Core/jit/JITOpcodes.cpp	2014-08-22 19:39:51 UTC (rev 172866)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes.cpp	2014-08-22 19:54:30 UTC (rev 172867)
@@ -532,6 +532,8 @@
 {
     move(TrustedImmPtr(m_vm), regT3);
     load64(Address(regT3, VM::callFrameForThrowOffset()), callFrameRegister);
+    load64(Address(regT3, VM::vmEntryFrameForThrowOffset()), regT0);
+    store64(regT0, Address(regT3, VM::topVMEntryFrameOffset()));
 
     addPtr(TrustedImm32(stackPointerOffsetFor(codeBlock()) * sizeof(Register)), callFrameRegister, stackPointerRegister);
 

Modified: trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp (172866 => 172867)


--- trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp	2014-08-22 19:39:51 UTC (rev 172866)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp	2014-08-22 19:54:30 UTC (rev 172867)
@@ -813,6 +813,8 @@
     move(TrustedImmPtr(m_vm), regT3);
     // operationThrow returns the callFrame for the handler.
     load32(Address(regT3, VM::callFrameForThrowOffset()), callFrameRegister);
+    load32(Address(regT3, VM::vmEntryFrameForThrowOffset()), regT0);
+    store32(regT0, Address(regT3, VM::topVMEntryFrameOffset()));
 
     addPtr(TrustedImm32(stackPointerOffsetFor(codeBlock()) * sizeof(Register)), callFrameRegister, stackPointerRegister);
 

Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (172866 => 172867)


--- trunk/Source/_javascript_Core/jit/JITOperations.cpp	2014-08-22 19:39:51 UTC (rev 172866)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp	2014-08-22 19:54:30 UTC (rev 172867)
@@ -86,7 +86,7 @@
     if (!callerFrame)
         callerFrame = exec;
 
-    NativeCallFrameTracer tracer(vm, vmEntryFrame, callerFrame);
+    NativeCallFrameTracerWithRestore tracer(vm, vmEntryFrame, callerFrame);
     ErrorHandlingScope errorScope(*vm);
     vm->throwException(callerFrame, createStackOverflowError(callerFrame));
 }
@@ -101,7 +101,7 @@
 
     int32_t missingArgCount = CommonSlowPaths::arityCheckFor(exec, &stack, CodeForCall);
     if (missingArgCount < 0) {
-        NativeCallFrameTracer tracer(vm, vmEntryFrame, callerFrame);
+        NativeCallFrameTracerWithRestore tracer(vm, vmEntryFrame, callerFrame);
         throwStackOverflowError(callerFrame);
     }
 
@@ -118,7 +118,7 @@
 
     int32_t missingArgCount = CommonSlowPaths::arityCheckFor(exec, &stack, CodeForConstruct);
     if (missingArgCount < 0) {
-        NativeCallFrameTracer tracer(vm, vmEntryFrame, callerFrame);
+        NativeCallFrameTracerWithRestore tracer(vm, vmEntryFrame, callerFrame);
         throwStackOverflowError(callerFrame);
     }
 
@@ -1790,7 +1790,7 @@
     JSValue exceptionValue = JSValue::decode(encodedExceptionValue);
     vm->throwException(exec, exceptionValue);
 
-    // Results stored out-of-band in vm.targetMachinePCForThrow & vm.callFrameForThrow
+    // Results stored out-of-band in vm.targetMachinePCForThrow, vm.callFrameForThrow & vm.vmEntryFrameForThrow
     genericUnwind(vm, exec, exceptionValue);
 }
 
@@ -1838,6 +1838,21 @@
     ASSERT(vm->targetMachinePCForThrow);
 }
 
+void JIT_OPERATION lookupExceptionHandlerFromCallerFrame(VM* vm, ExecState* exec)
+{
+    VMEntryFrame* vmEntryFrame = vm->topVMEntryFrame;
+    CallFrame* callerFrame = exec->callerFrame(vmEntryFrame);
+    ASSERT(callerFrame);
+
+    NativeCallFrameTracer tracer(vm, callerFrame);
+
+    JSValue exceptionValue = vm->exception();
+    ASSERT(exceptionValue);
+    
+    genericUnwind(vm, callerFrame, exceptionValue);
+    ASSERT(vm->targetMachinePCForThrow);
+}
+
 void JIT_OPERATION operationVMHandleException(ExecState* exec)
 {
     VM* vm = &exec->vm();

Modified: trunk/Source/_javascript_Core/jit/JITOperations.h (172866 => 172867)


--- trunk/Source/_javascript_Core/jit/JITOperations.h	2014-08-22 19:39:51 UTC (rev 172866)
+++ trunk/Source/_javascript_Core/jit/JITOperations.h	2014-08-22 19:54:30 UTC (rev 172867)
@@ -205,6 +205,7 @@
 // the return location from one of the calls out to one of the helper operations above.
 
 void JIT_OPERATION lookupExceptionHandler(VM*, ExecState*) WTF_INTERNAL;
+void JIT_OPERATION lookupExceptionHandlerFromCallerFrame(VM*, ExecState*) WTF_INTERNAL;
 void JIT_OPERATION operationVMHandleException(ExecState*) WTF_INTERNAL;
 
 void JIT_OPERATION operationThrowStackOverflowError(ExecState*, CodeBlock*) WTF_INTERNAL;

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm (172866 => 172867)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2014-08-22 19:39:51 UTC (rev 172866)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2014-08-22 19:54:30 UTC (rev 172867)
@@ -2048,6 +2048,8 @@
     andp MarkedBlockMask, t3
     loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
     loadp VM::callFrameForThrow[t3], cfr
+    loadp VM::vmEntryFrameForThrow[t3], t0
+    storep t0, VM::topVMEntryFrame[t3]
     restoreStackPointerAfterCall()
 
     loadi VM::targetInterpreterPCForThrow[t3], PC

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm (172866 => 172867)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2014-08-22 19:39:51 UTC (rev 172866)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2014-08-22 19:54:30 UTC (rev 172867)
@@ -1903,6 +1903,8 @@
     andp MarkedBlockMask, t3
     loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
     loadp VM::callFrameForThrow[t3], cfr
+    loadp VM::vmEntryFrameForThrow[t3], t0
+    storep t0, VM::topVMEntryFrame[t3]
     restoreStackPointerAfterCall()
 
     loadp CodeBlock[cfr], PB

Modified: trunk/Source/_javascript_Core/runtime/VM.h (172866 => 172867)


--- trunk/Source/_javascript_Core/runtime/VM.h	2014-08-22 19:39:51 UTC (rev 172866)
+++ trunk/Source/_javascript_Core/runtime/VM.h	2014-08-22 19:54:30 UTC (rev 172867)
@@ -346,6 +346,16 @@
             return OBJECT_OFFSETOF(VM, m_exception);
         }
 
+        static ptrdiff_t vmEntryFrameForThrowOffset()
+        {
+            return OBJECT_OFFSETOF(VM, vmEntryFrameForThrow);
+        }
+
+        static ptrdiff_t topVMEntryFrameOffset()
+        {
+            return OBJECT_OFFSETOF(VM, topVMEntryFrame);
+        }
+
         static ptrdiff_t callFrameForThrowOffset()
         {
             return OBJECT_OFFSETOF(VM, callFrameForThrow);
@@ -401,6 +411,7 @@
 
         JSValue hostCallReturnValue;
         ExecState* newCallFrameReturnValue;
+        VMEntryFrame* vmEntryFrameForThrow;
         ExecState* callFrameForThrow;
         void* targetMachinePCForThrow;
         Instruction* targetInterpreterPCForThrow;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to