Ignore:
Timestamp:
Aug 22, 2014, 12:54:30 PM (11 years ago)
Author:
[email protected]
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.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r172665 r172867  
    646646class UnwindFunctor {
    647647public:
    648     UnwindFunctor(CallFrame*& callFrame, bool isTermination, CodeBlock*& codeBlock, HandlerInfo*& handler)
    649         : m_callFrame(callFrame)
     648    UnwindFunctor(VMEntryFrame*& vmEntryFrame, CallFrame*& callFrame, bool isTermination, CodeBlock*& codeBlock, HandlerInfo*& handler)
     649        : m_vmEntryFrame(vmEntryFrame)
     650        , m_callFrame(callFrame)
    650651        , m_isTermination(isTermination)
    651652        , m_codeBlock(codeBlock)
     
    657658    {
    658659        VM& vm = m_callFrame->vm();
     660        m_vmEntryFrame = visitor->vmEntryFrame();
    659661        m_callFrame = visitor->callFrame();
    660662        m_codeBlock = visitor->codeBlock();
     
    674676
    675677private:
     678    VMEntryFrame*& m_vmEntryFrame;
    676679    CallFrame*& m_callFrame;
    677680    bool m_isTermination;
     
    680683};
    681684
    682 NEVER_INLINE HandlerInfo* Interpreter::unwind(CallFrame*& callFrame, JSValue& exceptionValue)
     685NEVER_INLINE HandlerInfo* Interpreter::unwind(VMEntryFrame*& vmEntryFrame, CallFrame*& callFrame, JSValue& exceptionValue)
    683686{
    684687    CodeBlock* codeBlock = callFrame->codeBlock();
     
    725728    VM& vm = callFrame->vm();
    726729    ASSERT(callFrame == vm.topCallFrame);
    727     UnwindFunctor functor(callFrame, isTermination, codeBlock, handler);
     730    UnwindFunctor functor(vmEntryFrame, callFrame, isTermination, codeBlock, handler);
    728731    callFrame->iterate(functor);
    729732    if (!handler)
Note: See TracChangeset for help on using the changeset viewer.