Changeset 126093 in webkit


Ignore:
Timestamp:
Aug 20, 2012 4:48:00 PM (12 years ago)
Author:
commit-queue@webkit.org
Message:

Fixed erroneous line number for LLint frame when throwing exceptions.
https://bugs.webkit.org/show_bug.cgi?id=94051.

Patch by Mark Lam <mark.lam@apple.com> on 2012-08-20
Reviewed by Filip Pizlo.

For LLInt frames, before throwing an exception, adjust the PC from the
return PC back to the call PC if we are indeed at a call site.

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::adjustPCIfAtCallSite):
(JSC):
(JSC::CodeBlock::bytecodeOffset):

  • bytecode/CodeBlock.h:

(CodeBlock):

  • llint/LLIntExceptions.cpp:

(JSC::LLInt::fixupPCforExceptionIfNeeded):
(LLInt):
(JSC::LLInt::interpreterThrowInCaller):
(JSC::LLInt::returnToThrow):
(JSC::LLInt::callToThrow):

Location:
trunk/Source/JavaScriptCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r126082 r126093  
     12012-08-20  Mark Lam  <mark.lam@apple.com>
     2
     3        Fixed erroneous line number for LLint frame when throwing exceptions.
     4        https://bugs.webkit.org/show_bug.cgi?id=94051.
     5
     6        Reviewed by Filip Pizlo.
     7
     8        For LLInt frames, before throwing an exception, adjust the PC from the
     9        return PC back to the call PC if we are indeed at a call site.
     10
     11        * bytecode/CodeBlock.cpp:
     12        (JSC::CodeBlock::adjustPCIfAtCallSite):
     13        (JSC):
     14        (JSC::CodeBlock::bytecodeOffset):
     15        * bytecode/CodeBlock.h:
     16        (CodeBlock):
     17        * llint/LLIntExceptions.cpp:
     18        (JSC::LLInt::fixupPCforExceptionIfNeeded):
     19        (LLInt):
     20        (JSC::LLInt::interpreterThrowInCaller):
     21        (JSC::LLInt::returnToThrow):
     22        (JSC::LLInt::callToThrow):
     23
    1242012-08-20  Filip Pizlo  <fpizlo@apple.com>
    225
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r125982 r126093  
    25812581}
    25822582
     2583#if ENABLE(LLINT)
     2584Instruction* CodeBlock::adjustPCIfAtCallSite(Instruction* potentialReturnPC)
     2585{
     2586    ASSERT(potentialReturnPC);
     2587
     2588    unsigned returnPCOffset = potentialReturnPC - instructions().begin();
     2589    Instruction* adjustedPC;
     2590    unsigned opcodeLength;
     2591
     2592    // If we are at a callsite, the LLInt stores the PC after the call
     2593    // instruction rather than the PC of the call instruction. This requires
     2594    // some correcting. If so, we can rely on the fact that the preceding
     2595    // instruction must be one of the call instructions, so either it's a
     2596    // call_varargs or it's a call, construct, or eval.
     2597    //
     2598    // If we are not at a call site, then we need to guard against the
     2599    // possibility of peeking past the start of the bytecode range for this
     2600    // codeBlock. Hence, we do a bounds check before we peek at the
     2601    // potential "preceding" instruction.
     2602    //     The bounds check is done by comparing the offset of the potential
     2603    // returnPC with the length of the opcode. If there is room for a call
     2604    // instruction before the returnPC, then the offset of the returnPC must
     2605    // be greater than the size of the call opcode we're looking for.
     2606
     2607    // The determination of the call instruction present (if we are at a
     2608    // callsite) depends on the following assumptions. So, assert that
     2609    // they are still true:
     2610    ASSERT(OPCODE_LENGTH(op_call_varargs) <= OPCODE_LENGTH(op_call));
     2611    ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct));
     2612    ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_call_eval));
     2613
     2614    // Check for the case of a preceeding op_call_varargs:
     2615    opcodeLength = OPCODE_LENGTH(op_call_varargs);
     2616    adjustedPC = potentialReturnPC - opcodeLength;
     2617    if ((returnPCOffset >= opcodeLength)
     2618        && (adjustedPC->u.pointer == bitwise_cast<void*>(llint_op_call_varargs))) {
     2619        return adjustedPC;
     2620    }
     2621
     2622    // Check for the case of the other 3 call instructions:
     2623    opcodeLength = OPCODE_LENGTH(op_call);
     2624    adjustedPC = potentialReturnPC - opcodeLength;
     2625    if ((returnPCOffset >= opcodeLength)
     2626        && (adjustedPC->u.pointer == bitwise_cast<void*>(llint_op_call)
     2627            || adjustedPC->u.pointer == bitwise_cast<void*>(llint_op_construct)
     2628            || adjustedPC->u.pointer == bitwise_cast<void*>(llint_op_call_eval))) {
     2629        return adjustedPC;
     2630    }
     2631
     2632    // Not a call site. No need to adjust PC. Just return the original.
     2633    return potentialReturnPC;
     2634}
     2635#endif
     2636
    25832637unsigned CodeBlock::bytecodeOffset(ExecState* exec, ReturnAddressPtr returnAddress)
    25842638{
     
    25912645        Instruction* instruction = exec->currentVPC();
    25922646        ASSERT(instruction);
    2593        
    2594         // The LLInt stores the PC after the call instruction rather than the PC of
    2595         // the call instruction. This requires some correcting. We rely on the fact
    2596         // that the preceding instruction must be one of the call instructions, so
    2597         // either it's a call_varargs or it's a call, construct, or eval.
    2598         ASSERT(OPCODE_LENGTH(op_call_varargs) <= OPCODE_LENGTH(op_call));
    2599         ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct));
    2600         ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_call_eval));
    2601         if (instruction[-OPCODE_LENGTH(op_call_varargs)].u.pointer == bitwise_cast<void*>(llint_op_call_varargs)) {
    2602             // We know that the preceding instruction must be op_call_varargs because there is no way that
    2603             // the pointer to the call_varargs could be an operand to the call.
    2604             instruction -= OPCODE_LENGTH(op_call_varargs);
    2605             ASSERT(instruction[-OPCODE_LENGTH(op_call)].u.pointer != bitwise_cast<void*>(llint_op_call)
    2606                    && instruction[-OPCODE_LENGTH(op_call)].u.pointer != bitwise_cast<void*>(llint_op_construct)
    2607                    && instruction[-OPCODE_LENGTH(op_call)].u.pointer != bitwise_cast<void*>(llint_op_call_eval));
    2608         } else {
    2609             // Must be that the last instruction was some op_call.
    2610             ASSERT(instruction[-OPCODE_LENGTH(op_call)].u.pointer == bitwise_cast<void*>(llint_op_call)
    2611                    || instruction[-OPCODE_LENGTH(op_call)].u.pointer == bitwise_cast<void*>(llint_op_construct)
    2612                    || instruction[-OPCODE_LENGTH(op_call)].u.pointer == bitwise_cast<void*>(llint_op_call_eval));
    2613             instruction -= OPCODE_LENGTH(op_call);
    2614         }
     2647
     2648        instruction = adjustPCIfAtCallSite(instruction);
    26152649       
    26162650        return bytecodeOffset(instruction);
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.h

    r125982 r126093  
    231231        }
    232232
     233#if ENABLE(LLINT)
     234        Instruction* adjustPCIfAtCallSite(Instruction*);
     235#endif
    233236        unsigned bytecodeOffset(ExecState*, ReturnAddressPtr);
    234237
  • trunk/Source/JavaScriptCore/llint/LLIntExceptions.cpp

    r114702 r126093  
    3838namespace JSC { namespace LLInt {
    3939
     40static void fixupPCforExceptionIfNeeded(ExecState* exec)
     41{
     42    CodeBlock* codeBlock = exec->codeBlock();
     43    ASSERT(!!codeBlock);
     44    Instruction* pc = exec->currentVPC();
     45    exec->setCurrentVPC(codeBlock->adjustPCIfAtCallSite(pc));
     46}
     47
    4048void interpreterThrowInCaller(ExecState* exec, ReturnAddressPtr pc)
    4149{
     
    4553    dataLog("Throwing exception %s.\n", globalData->exception.description());
    4654#endif
     55    fixupPCforExceptionIfNeeded(exec);
    4756    genericThrow(
    4857        globalData, exec, globalData->exception,
     
    6271    dataLog("Throwing exception %s (returnToThrow).\n", globalData->exception.description());
    6372#endif
     73    fixupPCforExceptionIfNeeded(exec);
    6474    genericThrow(globalData, exec, globalData->exception, pc - exec->codeBlock()->instructions().begin());
    6575   
     
    7484    dataLog("Throwing exception %s (callToThrow).\n", globalData->exception.description());
    7585#endif
     86    fixupPCforExceptionIfNeeded(exec);
    7687    genericThrow(globalData, exec, globalData->exception, pc - exec->codeBlock()->instructions().begin());
    7788   
Note: See TracChangeset for help on using the changeset viewer.