Changeset 160656 in webkit


Ignore:
Timestamp:
Dec 16, 2013 12:46:39 PM (10 years ago)
Author:
mark.lam@apple.com
Message:

Fix exception handling for the baseline JIT.
https://bugs.webkit.org/show_bug.cgi?id=125736.

Reviewed by Geoffrey Garen.

  • interpreter/Interpreter.cpp:

(JSC::unwindCallFrame):
Removed some unneeded code.

  1. Removed use of the oldCodeBlock variable which is only a copy of the codeBlock variable. There is no longer any reason to use a copy. Just use codeBlock directly instead.
  2. There's no need to set VM::topCallFrame. The UnwindFunctor automatically updates the incoming callFrame pointer reference to the frame that should be catching / handling the exception, and that is adequate for what we need.
  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_catch):

  • Restored sp.
  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::privateCompileCTINativeCall):
(JSC::JIT::emit_op_catch):

  • jit/ThunkGenerators.cpp:

(JSC::nativeForGenerator):
Fixed 2 issues:

  1. After returning from a native / host function, the thunk did not pop the native / host frame before executing exception handling code. This resulted in the VM trying to "unwind" the native / host frame which is not possible, and crashes ensue.
  2. After returning from a native / host function and discovering the need to handle an exception, the thunk was wrongly popping a non-existant return address off the stack. This caused the callerFrame pointer of the current frame to be popped off the stack, and havoc ensues.
  • llint/LowLevelInterpreter32_64.asm:
  • Updated to match exception handling code in LowLevelInterpreter64.asm.
  • runtime/VM.h:
  • Removed dead code.
Location:
branches/jsCStack/Source/JavaScriptCore
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • branches/jsCStack/Source/JavaScriptCore/ChangeLog

    r160610 r160656  
     12013-12-14  Mark Lam  <mark.lam@apple.com>
     2
     3        Fix exception handling for the baseline JIT.
     4        https://bugs.webkit.org/show_bug.cgi?id=125736.
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        * interpreter/Interpreter.cpp:
     9        (JSC::unwindCallFrame):
     10        Removed some unneeded code.
     11        1. Removed use of the oldCodeBlock variable which is only a copy of
     12           the codeBlock variable. There is no longer any reason to use a copy.
     13           Just use codeBlock directly instead.
     14        2. There's no need to set VM::topCallFrame. The UnwindFunctor
     15           automatically updates the incoming callFrame pointer reference to
     16           the frame that should be catching / handling the exception, and that
     17           is adequate for what we need.
     18
     19        * jit/JITOpcodes.cpp:
     20        (JSC::JIT::emit_op_catch):
     21        - Restored sp.
     22
     23        * jit/JITOpcodes32_64.cpp:
     24        (JSC::JIT::privateCompileCTINativeCall):
     25        (JSC::JIT::emit_op_catch):
     26        * jit/ThunkGenerators.cpp:
     27        (JSC::nativeForGenerator):
     28        Fixed 2 issues:
     29        1. After returning from a native / host function, the thunk did not pop
     30           the native / host frame before executing exception handling code.
     31           This resulted in the VM trying to "unwind" the native / host frame
     32           which is not possible, and crashes ensue.
     33        2. After returning from a native / host function and discovering the
     34           need to handle an exception, the thunk was wrongly popping a
     35           non-existant return address off the stack. This caused the
     36           callerFrame pointer of the current frame to be popped off the stack,
     37           and havoc ensues.
     38
     39        * llint/LowLevelInterpreter32_64.asm:
     40        - Updated to match exception handling code in LowLevelInterpreter64.asm.
     41
     42        * runtime/VM.h:
     43        - Removed dead code.
     44
    1452013-12-14  Filip Pizlo  <fpizlo@apple.com>
    246
  • branches/jsCStack/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r160497 r160656  
    422422    CallFrame* callFrame = visitor->callFrame();
    423423    CodeBlock* codeBlock = visitor->codeBlock();
    424     CodeBlock* oldCodeBlock = codeBlock;
    425424    JSScope* scope = callFrame->scope();
    426425
     
    433432
    434433    JSValue activation;
    435     if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->needsActivation()) {
     434    if (codeBlock->codeType() == FunctionCode && codeBlock->needsActivation()) {
    436435#if ENABLE(DFG_JIT)
    437436        RELEASE_ASSERT(!visitor->isInlinedFrame());
    438437#endif
    439         activation = callFrame->uncheckedR(oldCodeBlock->activationRegister().offset()).jsValue();
     438        activation = callFrame->uncheckedR(codeBlock->activationRegister().offset()).jsValue();
    440439        if (activation)
    441440            jsCast<JSActivation*>(activation)->tearOff(*scope->vm());
    442441    }
    443442
    444     if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->usesArguments()) {
     443    if (codeBlock->codeType() == FunctionCode && codeBlock->usesArguments()) {
    445444        if (Arguments* arguments = visitor->existingArguments()) {
    446445            if (activation)
     
    456455
    457456    CallFrame* callerFrame = callFrame->callerFrame();
    458     if (callerFrame->isVMEntrySentinel()) {
    459         if (callerFrame->vmEntrySentinelCallerFrame())
    460             callFrame->vm().topCallFrame = callerFrame->vmEntrySentinelCallerFrame();
    461         else
    462             callFrame->vm().topCallFrame = callFrame; // _handleUncaughtException will pop the frame off.
    463         return false;
    464     }
    465     return true;
     457    return !callerFrame->isVMEntrySentinel();
    466458}
    467459
  • branches/jsCStack/Source/JavaScriptCore/jit/JITOpcodes.cpp

    r160499 r160656  
    3939#include "JSPropertyNameIterator.h"
    4040#include "LinkBuffer.h"
     41#include "MaxFrameExtentForSlowPathCall.h"
    4142#include "SlowPathCall.h"
    4243#include "VirtualRegister.h"
     
    636637    move(TrustedImmPtr(m_vm), regT3);
    637638    load64(Address(regT3, VM::callFrameForThrowOffset()), callFrameRegister);
     639
     640    size_t frameExtent = JIT::frameRegisterCountFor(codeBlock()) * sizeof(Register) + maxFrameExtentForSlowPathCall;
     641    ASSERT(frameExtent == WTF::roundUpToMultipleOf(stackAlignmentBytes(), frameExtent));
     642    addPtr(TrustedImm32(-frameExtent), callFrameRegister, stackPointerRegister);
     643
    638644    load64(Address(regT3, VM::exceptionOffset()), regT0);
    639645    store64(TrustedImm64(JSValue::encode(JSValue())), Address(regT3, VM::exceptionOffset()));
  • branches/jsCStack/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp

    r160213 r160656  
    4040#include "JSVariableObject.h"
    4141#include "LinkBuffer.h"
     42#include "MaxFrameExtentForSlowPathCall.h"
    4243#include "SlowPathCall.h"
    4344#include "VirtualRegister.h"
     
    120121    sawException.link(this);
    121122
    122     // Grab the return address.
    123     preserveReturnAddressAfterCall(regT1);
    124 
    125     move(TrustedImmPtr(&vm->exceptionLocation), regT2);
    126     storePtr(regT1, regT2);
    127123    storePtr(callFrameRegister, &m_vm->topCallFrame);
    128124
     
    928924    // operationThrow returns the callFrame for the handler.
    929925    load32(Address(regT3, VM::callFrameForThrowOffset()), callFrameRegister);
     926
     927    size_t frameExtent = JIT::frameRegisterCountFor(codeBlock()) * sizeof(Register) + maxFrameExtentForSlowPathCall;
     928    ASSERT(frameExtent == WTF::roundUpToMultipleOf(stackAlignmentBytes(), frameExtent));
     929    addPtr(TrustedImm32(-frameExtent), callFrameRegister, stackPointerRegister);
     930
    930931    // Now store the exception returned by operationThrow.
    931932    load32(Address(regT3, VM::exceptionOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0);
  • branches/jsCStack/Source/JavaScriptCore/jit/ThunkGenerators.cpp

    r160468 r160656  
    368368#endif
    369369
     370    jit.emitFunctionEpilogue();
     371
    370372    // Check for an exception
    371373#if USE(JSVALUE64)
     
    380382
    381383    // Return.
    382     jit.emitFunctionEpilogue();
    383384    jit.ret();
    384385
    385386    // Handle an exception
    386387    exceptionHandler.link(&jit);
    387 
    388     // Grab the return address.
    389     jit.preserveReturnAddressAfterCall(JSInterfaceJIT::regT1);
    390    
    391     jit.move(JSInterfaceJIT::TrustedImmPtr(&vm->exceptionLocation), JSInterfaceJIT::regT2);
    392     jit.storePtr(JSInterfaceJIT::regT1, JSInterfaceJIT::regT2);
    393388
    394389    jit.storePtr(JSInterfaceJIT::callFrameRegister, &vm->topCallFrame);
  • branches/jsCStack/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm

    r160573 r160656  
    345345
    346346_handleUncaughtException:
    347     loadp ScopeChain[cfr], t3
     347    loadp ScopeChain + PayloadOffset[cfr], t3
    348348    andp MarkedBlockMask, t3
    349349    loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
     
    353353    # We need to pop to the sentinel frame and do the necessary clean up for
    354354    # returning to the caller C frame.
    355     loadp CallerFrame[cfr], cfr
    356 
    357     loadp Callee[cfr], t3 # VM.topCallFrame
    358     loadp ScopeChain[cfr], t6
     355    loadp CallerFrame + PayloadOffset[cfr], cfr
     356
     357    loadp Callee + PayloadOffset[cfr], t3 # VM.topCallFrame
     358    loadp ScopeChain + PayloadOffset[cfr], t6
    359359    storep t6, [t3]
    360360
     
    20032003    # The throwing code must have known that we were throwing to the interpreter,
    20042004    # and have set VM::targetInterpreterPCForThrow.
    2005     loadp ScopeChain[cfr], t3
     2005    loadp ScopeChain + PayloadOffset[cfr], t3
    20062006    andp MarkedBlockMask, t3
    20072007    loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
    20082008    loadp VM::callFrameForThrow[t3], cfr
     2009    restoreStackPointerAfterCall()
     2010
    20092011    loadi VM::targetInterpreterPCForThrow[t3], PC
    20102012    loadi VM::m_exception + PayloadOffset[t3], t0
  • branches/jsCStack/Source/JavaScriptCore/runtime/VM.h

    r160591 r160656  
    382382        const ClassInfo* const jsFinalObjectClassInfo;
    383383
    384         ReturnAddressPtr exceptionLocation;
    385384        JSValue hostCallReturnValue;
    386385        ExecState* newCallFrameReturnValue;
Note: See TracChangeset for help on using the changeset viewer.