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.h

    r172792 r172867  
    176176            ASSERT(vm);
    177177            ASSERT(callFrame);
    178             ASSERT(callFrame < vm->topVMEntryFrame);
    179178            vm->topCallFrame = callFrame;
    180179        }
    181 
    182         ALWAYS_INLINE NativeCallFrameTracer(VM* vm, VMEntryFrame* vmEntryFrame, CallFrame* callFrame)
     180    };
     181
     182    class NativeCallFrameTracerWithRestore {
     183    public:
     184        ALWAYS_INLINE NativeCallFrameTracerWithRestore(VM* vm, VMEntryFrame* vmEntryFrame, CallFrame* callFrame)
     185            : m_vm(vm)
    183186        {
    184187            ASSERT(vm);
    185188            ASSERT(callFrame);
    186             ASSERT(callFrame < vmEntryFrame);
     189            m_savedTopVMEntryFrame = vm->topVMEntryFrame;
     190            m_savedTopCallFrame = vm->topCallFrame;
    187191            vm->topVMEntryFrame = vmEntryFrame;
    188192            vm->topCallFrame = callFrame;
    189193        }
     194
     195        ALWAYS_INLINE ~NativeCallFrameTracerWithRestore()
     196        {
     197            m_vm->topVMEntryFrame = m_savedTopVMEntryFrame;
     198            m_vm->topCallFrame = m_savedTopCallFrame;
     199        }
     200
     201    private:
     202        VM* m_vm;
     203        VMEntryFrame* m_savedTopVMEntryFrame;
     204        CallFrame* m_savedTopCallFrame;
    190205    };
    191206
     
    237252        SamplingTool* sampler() { return m_sampler.get(); }
    238253
    239         NEVER_INLINE HandlerInfo* unwind(CallFrame*&, JSValue&);
     254        NEVER_INLINE HandlerInfo* unwind(VMEntryFrame*&, CallFrame*&, JSValue&);
    240255        NEVER_INLINE void debug(CallFrame*, DebugHookID);
    241256        JSString* stackTraceAsString(ExecState*, Vector<StackFrame>);
Note: See TracChangeset for help on using the changeset viewer.