Ignore:
Timestamp:
Aug 15, 2013, 6:47:41 PM (12 years ago)
Author:
[email protected]
Message:

Fix crash when performing activation tearoff.
https://bugs.webkit.org/show_bug.cgi?id=119848

Reviewed by Oliver Hunt.

The activation tearoff crash was due to a bug in the baseline JIT.
If we have a scenario where the a baseline JIT frame calls a LLINT
frame, an exception may be thrown while in the LLINT.

Interpreter::throwException() which handles the exception will unwind
all frames until it finds a catcher or sees a host frame. When we
return from the LLINT to the baseline JIT code, the baseline JIT code
errorneously sets topCallFrame to the value in its call frame register,
and starts unwinding the stack frames that have already been unwound.

The fix is:

  1. Rename ctiVMThrowTrampolineSlowpath to ctiVMHandleException. This is a more accurate description of what this runtime function is supposed to do i.e. it handles the exception which include doing nothing (if there are no more frames to unwind).
  2. Fix up topCallFrame values so that the HostCallFrameFlag is never set on it.
  3. Reloading the call frame register from topCallFrame when we're returning from a callee and detect exception handling in progress.
  • interpreter/Interpreter.cpp:

(JSC::Interpreter::unwindCallFrame):

  • Ensure that topCallFrame is not set with the HostCallFrameFlag.

(JSC::Interpreter::getStackTrace):

  • interpreter/Interpreter.h:

(JSC::TopCallFrameSetter::TopCallFrameSetter):
(JSC::TopCallFrameSetter::~TopCallFrameSetter):
(JSC::NativeCallFrameTracer::NativeCallFrameTracer):

  • Ensure that topCallFrame is not set with the HostCallFrameFlag.
  • jit/JIT.h:
  • jit/JITExceptions.cpp:

(JSC::uncaughtExceptionHandler):

  • Convenience function to get the handler for uncaught exceptions.
  • jit/JITExceptions.h:
  • jit/JITInlines.h:

(JSC::JIT::reloadCallFrameFromTopCallFrame):

  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::privateCompileCTINativeCall):

  • Rename ctiVMThrowTrampolineSlowpath to ctiVMHandleException.
  • jit/JITStubs.cpp:

(JSC::throwExceptionFromOpCall):

  • Ensure that topCallFrame is not set with the HostCallFrameFlag.

(JSC::cti_vm_handle_exception):

  • Check for the case when there are no more frames to unwind.
  • jit/JITStubs.h:
  • jit/JITStubsARM.h:
  • jit/JITStubsARMv7.h:
  • jit/JITStubsMIPS.h:
  • jit/JITStubsSH4.h:
  • jit/JITStubsX86.h:
  • jit/JITStubsX86_64.h:
  • Rename ctiVMThrowTrampolineSlowpath to ctiVMHandleException.
  • jit/SlowPathCall.h:

(JSC::JITSlowPathCall::call):

  • reload cfr from topcallFrame when handling an exception.
  • Rename ctiVMThrowTrampolineSlowpath to ctiVMHandleException.
  • jit/ThunkGenerators.cpp:

(JSC::nativeForGenerator):

  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
  • reload cfr from topcallFrame when handling an exception.
  • runtime/VM.cpp:

(JSC::VM::VM):

  • Ensure that topCallFrame is not set with the HostCallFrameFlag.
File:
1 edited

Legend:

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

    r153825 r154156  
    136136    class TopCallFrameSetter {
    137137    public:
    138         TopCallFrameSetter(VM& global, CallFrame* callFrame)
    139             : vm(global)
    140             , oldCallFrame(global.topCallFrame)
    141         {
    142             global.topCallFrame = callFrame;
     138        TopCallFrameSetter(VM& currentVM, CallFrame* callFrame)
     139            : vm(currentVM)
     140            , oldCallFrame(currentVM.topCallFrame)
     141        {
     142            ASSERT(!callFrame->hasHostCallFrameFlag());
     143            currentVM.topCallFrame = callFrame;
    143144        }
    144145       
    145146        ~TopCallFrameSetter()
    146147        {
     148            ASSERT(!oldCallFrame->hasHostCallFrameFlag());
    147149            vm.topCallFrame = oldCallFrame;
    148150        }
     
    154156    class NativeCallFrameTracer {
    155157    public:
    156         ALWAYS_INLINE NativeCallFrameTracer(VM* global, CallFrame* callFrame)
    157         {
    158             ASSERT(global);
     158        ALWAYS_INLINE NativeCallFrameTracer(VM* vm, CallFrame* callFrame)
     159        {
     160            ASSERT(vm);
    159161            ASSERT(callFrame);
    160             global->topCallFrame = callFrame;
     162            ASSERT(!callFrame->hasHostCallFrameFlag());
     163            vm->topCallFrame = callFrame;
    161164        }
    162165    };
Note: See TracChangeset for help on using the changeset viewer.