Changeset 126093 in webkit
- Timestamp:
- Aug 20, 2012 4:48:00 PM (12 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r126082 r126093 1 2012-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 1 24 2012-08-20 Filip Pizlo <fpizlo@apple.com> 2 25 -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r125982 r126093 2581 2581 } 2582 2582 2583 #if ENABLE(LLINT) 2584 Instruction* 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 2583 2637 unsigned CodeBlock::bytecodeOffset(ExecState* exec, ReturnAddressPtr returnAddress) 2584 2638 { … … 2591 2645 Instruction* instruction = exec->currentVPC(); 2592 2646 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); 2615 2649 2616 2650 return bytecodeOffset(instruction); -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.h
r125982 r126093 231 231 } 232 232 233 #if ENABLE(LLINT) 234 Instruction* adjustPCIfAtCallSite(Instruction*); 235 #endif 233 236 unsigned bytecodeOffset(ExecState*, ReturnAddressPtr); 234 237 -
trunk/Source/JavaScriptCore/llint/LLIntExceptions.cpp
r114702 r126093 38 38 namespace JSC { namespace LLInt { 39 39 40 static 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 40 48 void interpreterThrowInCaller(ExecState* exec, ReturnAddressPtr pc) 41 49 { … … 45 53 dataLog("Throwing exception %s.\n", globalData->exception.description()); 46 54 #endif 55 fixupPCforExceptionIfNeeded(exec); 47 56 genericThrow( 48 57 globalData, exec, globalData->exception, … … 62 71 dataLog("Throwing exception %s (returnToThrow).\n", globalData->exception.description()); 63 72 #endif 73 fixupPCforExceptionIfNeeded(exec); 64 74 genericThrow(globalData, exec, globalData->exception, pc - exec->codeBlock()->instructions().begin()); 65 75 … … 74 84 dataLog("Throwing exception %s (callToThrow).\n", globalData->exception.description()); 75 85 #endif 86 fixupPCforExceptionIfNeeded(exec); 76 87 genericThrow(globalData, exec, globalData->exception, pc - exec->codeBlock()->instructions().begin()); 77 88
Note: See TracChangeset
for help on using the changeset viewer.