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/ftl/FTLCompile.cpp

    r172129 r172867  
    286286        // At this point it's perfectly fair to just blow away all state and restore the
    287287        // JS JIT view of the universe.
    288         checkJIT.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1);
    289 
    290         MacroAssembler::Label exceptionContinueArg1Set = checkJIT.label();
    291288        checkJIT.move(MacroAssembler::TrustedImm64(TagTypeNumber), GPRInfo::tagTypeNumberRegister);
    292289        checkJIT.move(MacroAssembler::TrustedImm64(TagMask), GPRInfo::tagMaskRegister);
    293290
    294291        checkJIT.move(MacroAssembler::TrustedImmPtr(&vm), GPRInfo::argumentGPR0);
    295         MacroAssembler::Call call = checkJIT.call();
     292        checkJIT.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1);
     293        MacroAssembler::Call callLookupExceptionHandler = checkJIT.call();
    296294        checkJIT.jumpToExceptionHandler();
    297295
    298296        stackOverflowException = checkJIT.label();
    299         checkJIT.emitGetCallerFrameFromCallFrameHeaderPtr(GPRInfo::argumentGPR1);
    300         checkJIT.jump(exceptionContinueArg1Set);
     297        checkJIT.move(MacroAssembler::TrustedImm64(TagTypeNumber), GPRInfo::tagTypeNumberRegister);
     298        checkJIT.move(MacroAssembler::TrustedImm64(TagMask), GPRInfo::tagMaskRegister);
     299
     300        checkJIT.move(MacroAssembler::TrustedImmPtr(&vm), GPRInfo::argumentGPR0);
     301        checkJIT.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1);
     302        MacroAssembler::Call callLookupExceptionHandlerFromCallerFrame = checkJIT.call();
     303        checkJIT.jumpToExceptionHandler();
    301304
    302305        OwnPtr<LinkBuffer> linkBuffer = adoptPtr(new LinkBuffer(
    303306            vm, checkJIT, codeBlock, JITCompilationMustSucceed));
    304         linkBuffer->link(call, FunctionPtr(lookupExceptionHandler));
    305        
     307        linkBuffer->link(callLookupExceptionHandler, FunctionPtr(lookupExceptionHandler));
     308        linkBuffer->link(callLookupExceptionHandlerFromCallerFrame, FunctionPtr(lookupExceptionHandlerFromCallerFrame));
     309
    306310        state.finalizer->handleExceptionsLinkBuffer = linkBuffer.release();
    307311    }
Note: See TracChangeset for help on using the changeset viewer.