Changeset 147670 in webkit
- Timestamp:
- Apr 4, 2013 2:25:26 PM (11 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r147668 r147670 1 2013-04-04 Oliver Hunt <oliver@apple.com> 2 3 Exception stack unwinding doesn't handle inline callframes correctly 4 https://bugs.webkit.org/show_bug.cgi?id=113952 5 6 Reviewed by Geoffrey Garen. 7 8 Yay tests! 9 10 * fast/js/js-correct-exception-handler-expected.txt: Added. 11 * fast/js/js-correct-exception-handler.html: Added. 12 * fast/js/script-tests/js-correct-exception-handler.js: Added. 13 (throwEventually): 14 (f.g): 15 (f): 16 (test): 17 1 18 2013-04-04 Glenn Adams <glenn@skynav.com> 2 19 -
trunk/Source/JavaScriptCore/ChangeLog
r147669 r147670 1 2013-04-04 Oliver Hunt <oliver@apple.com> 2 3 Exception stack unwinding doesn't handle inline callframes correctly 4 https://bugs.webkit.org/show_bug.cgi?id=113952 5 6 Reviewed by Geoffrey Garen. 7 8 The basic problem here is that the exception stack unwinding was 9 attempting to be "clever" and avoid doing a correct stack walk 10 as it "knew" inline callframes couldn't have exception handlers. 11 12 This used to be safe as the exception handling machinery was 13 designed to fail gently and just claim that no handler existed. 14 This was "safe" and even "correct" inasmuch as we currently 15 don't run any code with exception handlers through the dfg. 16 17 This patch fixes the logic by simply making everything uniformly 18 use the safe stack walking machinery, and making the correct 19 boundary checks occur everywhere that they should. 20 21 * bytecode/CodeBlock.cpp: 22 (JSC::CodeBlock::findClosureCallForReturnPC): 23 (JSC::CodeBlock::bytecodeOffset): 24 * interpreter/Interpreter.cpp: 25 (JSC): 26 (JSC::Interpreter::dumpRegisters): 27 (JSC::Interpreter::unwindCallFrame): 28 (JSC::getCallerInfo): 29 (JSC::Interpreter::getStackTrace): 30 (JSC::Interpreter::retrieveCallerFromVMCode): 31 1 32 2013-04-04 Geoffrey Garen <ggaren@apple.com> 2 33 -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r147514 r147670 2463 2463 HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset) 2464 2464 { 2465 ASSERT(bytecodeOffset < instructions().size());2465 RELEASE_ASSERT(bytecodeOffset < instructions().size()); 2466 2466 2467 2467 if (!m_rareData) … … 2661 2661 if (!info.stub->code().executableMemory()->contains(returnAddress.value())) 2662 2662 continue; 2663 2663 2664 RELEASE_ASSERT(info.stub->codeOrigin().bytecodeIndex < info.stub->codeOrigin().maximumBytecodeIndex); 2664 2665 return info.stub.get(); 2665 2666 } … … 2674 2675 if (!stub->code().executableMemory()->contains(returnAddress.value())) 2675 2676 continue; 2677 RELEASE_ASSERT(stub->codeOrigin().bytecodeIndex < stub->codeOrigin().maximumBytecodeIndex); 2676 2678 return stub; 2677 2679 } … … 2725 2727 callIndices, callIndices.size(), callReturnOffset, getCallReturnOffset); 2726 2728 RELEASE_ASSERT(result->callReturnOffset == callReturnOffset); 2729 RELEASE_ASSERT(result->bytecodeOffset < instructionCount()); 2727 2730 return result->bytecodeOffset; 2728 2731 } 2729 2730 return findClosureCallForReturnPC(returnAddress)->codeOrigin().bytecodeIndex; 2732 ClosureCallStubRoutine* closureInfo = findClosureCallForReturnPC(returnAddress); 2733 CodeOrigin origin = closureInfo->codeOrigin(); 2734 while (InlineCallFrame* inlineCallFrame = origin.inlineCallFrame) { 2735 if (inlineCallFrame->baselineCodeBlock() == this) 2736 break; 2737 origin = inlineCallFrame->caller; 2738 RELEASE_ASSERT(origin.bytecodeIndex < origin.maximumBytecodeIndex); 2739 } 2740 RELEASE_ASSERT(origin.bytecodeIndex < origin.maximumBytecodeIndex); 2741 unsigned bytecodeIndex = origin.bytecodeIndex; 2742 RELEASE_ASSERT(bytecodeIndex < instructionCount()); 2743 return bytecodeIndex; 2731 2744 #endif // ENABLE(JIT) 2732 2745 -
trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp
r146552 r147670 200 200 201 201 202 static CallFrame* getCallerInfo(JSGlobalData*, CallFrame*, int& lineNumber, unsigned& bytecodeOffset );202 static CallFrame* getCallerInfo(JSGlobalData*, CallFrame*, int& lineNumber, unsigned& bytecodeOffset, CodeBlock*& callerOut); 203 203 204 204 // Returns the depth of the scope chain within a given call frame. … … 423 423 unsigned bytecodeOffset = 0; 424 424 int line = 0; 425 getCallerInfo(&callFrame->globalData(), callFrame, line, bytecodeOffset); 425 CodeBlock* unusedCallerCodeBlock = 0; 426 getCallerInfo(&callFrame->globalData(), callFrame, line, bytecodeOffset, unusedCallerCodeBlock); 426 427 dataLogF("[ReturnVPC] | %10p | %d (line %d)\n", it, bytecodeOffset, line); 427 428 ++it; … … 507 508 if (callerFrame->hasHostCallFrameFlag()) 508 509 return false; 509 510 codeBlock = callerFrame->codeBlock(); 511 512 // Because of how the JIT records call site->bytecode offset 513 // information the JIT reports the bytecodeOffset for the returnPC 514 // to be at the beginning of the opcode that has caused the call. 515 #if ENABLE(JIT) || ENABLE(LLINT) 516 bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnPC()); 517 #endif 518 519 callFrame = callerFrame; 510 int unusedLineNumber = 0; 511 callFrame = getCallerInfo(&callFrame->globalData(), callFrame, unusedLineNumber, bytecodeOffset, codeBlock); 520 512 return true; 521 513 } … … 589 581 } 590 582 591 static CallFrame* getCallerInfo(JSGlobalData* globalData, CallFrame* callFrame, int& lineNumber, unsigned& bytecodeOffset )592 { 593 UNUSED_PARAM(globalData);583 static CallFrame* getCallerInfo(JSGlobalData* globalData, CallFrame* callFrame, int& lineNumber, unsigned& bytecodeOffset, CodeBlock*& caller) 584 { 585 ASSERT_UNUSED(globalData, globalData); 594 586 bytecodeOffset = 0; 595 587 lineNumber = -1; … … 599 591 ASSERT(!callerFrame->hasHostCallFrameFlag()); 600 592 601 if (callerFrame == CallFrame::noCaller() || !callerFrame || !callerFrame->codeBlock()) 593 if (callerFrame == CallFrame::noCaller() || !callerFrame || !callerFrame->codeBlock()) { 594 caller = 0; 602 595 return callerFrame; 596 } 603 597 604 598 CodeBlock* callerCodeBlock = callerFrame->codeBlock(); … … 660 654 661 655 RELEASE_ASSERT(callerCodeBlock); 656 caller = callerCodeBlock; 662 657 lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset); 663 658 return callerFrame; … … 706 701 } 707 702 unsigned unusedBytecodeOffset = 0; 708 callFrame = getCallerInfo(globalData, callFrame, line, unusedBytecodeOffset); 703 CodeBlock* unusedCallerCodeBlock = 0; 704 callFrame = getCallerInfo(globalData, callFrame, line, unusedBytecodeOffset, unusedCallerCodeBlock); 709 705 } 710 706 } … … 1382 1378 int lineNumber; 1383 1379 unsigned bytecodeOffset; 1384 CallFrame* callerFrame = getCallerInfo(&callFrame->globalData(), functionCallFrame, lineNumber, bytecodeOffset); 1380 CodeBlock* unusedCallerCodeBlock = 0; 1381 CallFrame* callerFrame = getCallerInfo(&callFrame->globalData(), functionCallFrame, lineNumber, bytecodeOffset, unusedCallerCodeBlock); 1385 1382 if (!callerFrame) 1386 1383 return jsNull(); … … 1392 1389 ASSERT(caller.isObject()); 1393 1390 while (asObject(caller)->inherits(&JSBoundFunction::s_info)) { 1394 callerFrame = getCallerInfo(&callFrame->globalData(), callerFrame, lineNumber, bytecodeOffset );1391 callerFrame = getCallerInfo(&callFrame->globalData(), callerFrame, lineNumber, bytecodeOffset, unusedCallerCodeBlock); 1395 1392 if (!callerFrame) 1396 1393 return jsNull();
Note: See TracChangeset
for help on using the changeset viewer.