Changeset 61588 in webkit
- Timestamp:
- Jun 21, 2010 4:17:48 PM (14 years ago)
- Location:
- trunk/JavaScriptCore
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r61577 r61588 1 2010-06-21 Oliver Hunt <oliver@apple.com> 2 3 Reviewed by Geoffrey Garen. 4 5 Make JSC more resilient in the face of parse failures 6 https://bugs.webkit.org/show_bug.cgi?id=40951 7 8 A number of recent bugs have occurred due to issues like miscounting 9 BOMs, etc which lead to interesting crashes later on. Adding this 10 logic hardens JSC in the face of these errors, and has no impact on 11 performance (32bit jit actually gets 0.7% faster but I put that down 12 to cache effects). 13 14 * bytecode/CodeBlock.cpp: 15 (JSC::CodeBlock::reparseForExceptionInfoIfNecessary): 16 (JSC::CodeBlock::lineNumberForBytecodeOffset): 17 (JSC::CodeBlock::expressionRangeForBytecodeOffset): 18 (JSC::CodeBlock::getByIdExceptionInfoForBytecodeOffset): 19 * bytecode/CodeBlock.h: 20 (JSC::CodeBlock::bytecodeOffset): 21 * interpreter/Interpreter.cpp: 22 (JSC::Interpreter::execute): 23 (JSC::Interpreter::executeCall): 24 (JSC::Interpreter::executeConstruct): 25 (JSC::Interpreter::prepareForRepeatCall): 26 (JSC::Interpreter::privateExecute): 27 * jit/JITOpcodes.cpp: 28 (JSC::JIT::privateCompileCTIMachineTrampolines): 29 * jit/JITOpcodes32_64.cpp: 30 (JSC::JIT::privateCompileCTIMachineTrampolines): 31 * jit/JITStubs.cpp: 32 (JSC::DEFINE_STUB_FUNCTION): 33 * runtime/ArrayPrototype.cpp: 34 (JSC::isNumericCompareFunction): 35 * runtime/Executable.cpp: 36 (JSC::FunctionExecutable::compileForCall): 37 (JSC::FunctionExecutable::compileForConstruct): 38 (JSC::FunctionExecutable::generateJITCodeForCall): 39 (JSC::FunctionExecutable::generateJITCodeForConstruct): 40 (JSC::FunctionExecutable::reparseExceptionInfo): 41 (JSC::EvalExecutable::reparseExceptionInfo): 42 * runtime/Executable.h: 43 (JSC::FunctionExecutable::bytecodeForCall): 44 (JSC::FunctionExecutable::bytecodeForConstruct): 45 * runtime/JSGlobalData.cpp: 46 (JSC::JSGlobalData::numericCompareFunction): 47 1 48 2010-06-21 John Sullivan <sullivan@apple.com> 2 49 -
trunk/JavaScriptCore/bytecode/CodeBlock.cpp
r61430 r61588 1520 1520 } 1521 1521 1522 voidCodeBlock::reparseForExceptionInfoIfNecessary(CallFrame* callFrame)1522 bool CodeBlock::reparseForExceptionInfoIfNecessary(CallFrame* callFrame) 1523 1523 { 1524 1524 if (m_exceptionInfo) 1525 return ;1525 return true; 1526 1526 1527 1527 ASSERT(!m_rareData || !m_rareData->m_exceptionHandlers.size()); … … 1540 1540 1541 1541 m_exceptionInfo.set(m_ownerExecutable->reparseExceptionInfo(m_globalData, scopeChain, this)); 1542 return m_exceptionInfo; 1542 1543 } 1543 1544 … … 1564 1565 ASSERT(bytecodeOffset < m_instructionCount); 1565 1566 1566 reparseForExceptionInfoIfNecessary(callFrame); 1567 ASSERT(m_exceptionInfo); 1568 1569 if (!m_exceptionInfo->m_lineInfo.size()) 1570 return m_ownerExecutable->source().firstLine(); // Empty function 1567 if (!reparseForExceptionInfoIfNecessary(callFrame) || !m_exceptionInfo->m_lineInfo.size()) 1568 return m_ownerExecutable->source().firstLine(); // Empty function or unable to reparse 1571 1569 1572 1570 int low = 0; … … 1589 1587 ASSERT(bytecodeOffset < m_instructionCount); 1590 1588 1591 reparseForExceptionInfoIfNecessary(callFrame); 1592 ASSERT(m_exceptionInfo); 1593 1594 if (!m_exceptionInfo->m_expressionInfo.size()) { 1589 if (!reparseForExceptionInfoIfNecessary(callFrame) || !m_exceptionInfo->m_expressionInfo.size()) { 1595 1590 // We didn't think anything could throw. Apparently we were wrong. 1591 // Alternatively something went wrong when trying to reparse 1596 1592 startOffset = 0; 1597 1593 endOffset = 0; … … 1628 1624 ASSERT(bytecodeOffset < m_instructionCount); 1629 1625 1630 reparseForExceptionInfoIfNecessary(callFrame); 1631 ASSERT(m_exceptionInfo); 1632 1633 if (!m_exceptionInfo->m_getByIdExceptionInfo.size()) 1626 if (!reparseForExceptionInfoIfNecessary(callFrame) || !m_exceptionInfo->m_getByIdExceptionInfo.size()) 1634 1627 return false; 1635 1628 -
trunk/JavaScriptCore/bytecode/CodeBlock.h
r61324 r61588 352 352 unsigned bytecodeOffset(CallFrame* callFrame, ReturnAddressPtr returnAddress) 353 353 { 354 reparseForExceptionInfoIfNecessary(callFrame); 354 if (!reparseForExceptionInfoIfNecessary(callFrame)) 355 return 0; 355 356 return binaryChop<CallReturnOffsetToBytecodeOffset, unsigned, getCallReturnOffset>(callReturnIndexVector().begin(), callReturnIndexVector().size(), getJITCode().offsetOf(returnAddress.value()))->bytecodeOffset; 356 357 } … … 522 523 #endif 523 524 524 void reparseForExceptionInfoIfNecessary(CallFrame*);525 bool reparseForExceptionInfoIfNecessary(CallFrame*) WARN_UNUSED_RETURN; 525 526 526 527 void createRareDataIfNecessary() -
trunk/JavaScriptCore/interpreter/Interpreter.cpp
r61553 r61588 644 644 645 645 CodeBlock* codeBlock = &program->bytecode(callFrame, scopeChain); 646 if (!codeBlock) { 647 *exception = createStackOverflowError(callFrame); 648 return jsNull(); 649 } 646 650 647 651 Register* oldEnd = m_registerFile.end(); … … 723 727 if (callType == CallTypeJS) { 724 728 ScopeChainNode* callDataScopeChain = callData.js.scopeChain; 725 CodeBlock* newCodeBlock = &callData.js.functionExecutable->bytecodeForCall(callFrame, callDataScopeChain); 726 727 newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, registerOffset, argCount); 729 CodeBlock* newCodeBlock = callData.js.functionExecutable->bytecodeForCall(callFrame, callDataScopeChain); 730 731 if (newCodeBlock) 732 newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, registerOffset, argCount); 733 else 734 newCallFrame = 0; 728 735 if (UNLIKELY(!newCallFrame)) { 729 736 *exception = createStackOverflowError(callFrame); … … 812 819 if (constructType == ConstructTypeJS) { 813 820 ScopeChainNode* constructDataScopeChain = constructData.js.scopeChain; 814 CodeBlock* newCodeBlock = &constructData.js.functionExecutable->bytecodeForConstruct(callFrame, constructDataScopeChain); 815 816 newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, registerOffset, argCount); 821 CodeBlock* newCodeBlock = constructData.js.functionExecutable->bytecodeForConstruct(callFrame, constructDataScopeChain); 822 if (newCodeBlock) 823 newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, registerOffset, argCount); 824 else 825 newCallFrame = 0; 826 817 827 if (UNLIKELY(!newCallFrame)) { 818 828 *exception = createStackOverflowError(callFrame); … … 903 913 newCallFrame->r(++dst) = jsUndefined(); 904 914 905 CodeBlock* codeBlock = &FunctionExecutable->bytecodeForCall(callFrame, scopeChain); 906 newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc); 915 CodeBlock* codeBlock = FunctionExecutable->bytecodeForCall(callFrame, scopeChain); 916 if (codeBlock) 917 newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc); 918 else 919 newCallFrame = 0; 907 920 if (UNLIKELY(!newCallFrame)) { 908 921 *exception = createStackOverflowError(callFrame); … … 969 982 970 983 EvalCodeBlock* codeBlock = &eval->bytecode(callFrame, scopeChain); 984 if (!codeBlock) { 985 *exception = createStackOverflowError(callFrame); 986 return jsNull(); 987 } 971 988 972 989 JSVariableObject* variableObject; … … 3620 3637 if (callType == CallTypeJS) { 3621 3638 ScopeChainNode* callDataScopeChain = callData.js.scopeChain; 3622 CodeBlock* newCodeBlock = &callData.js.functionExecutable->bytecodeForCall(callFrame, callDataScopeChain);3639 CodeBlock* newCodeBlock = callData.js.functionExecutable->bytecodeForCall(callFrame, callDataScopeChain); 3623 3640 3624 3641 CallFrame* previousCallFrame = callFrame; 3625 3626 callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount); 3642 if (newCodeBlock) 3643 callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount); 3644 else 3645 callFrame = 0; 3627 3646 if (UNLIKELY(!callFrame)) { 3628 3647 callFrame = previousCallFrame; … … 3772 3791 if (callType == CallTypeJS) { 3773 3792 ScopeChainNode* callDataScopeChain = callData.js.scopeChain; 3774 CodeBlock* newCodeBlock = &callData.js.functionExecutable->bytecodeForCall(callFrame, callDataScopeChain);3793 CodeBlock* newCodeBlock = callData.js.functionExecutable->bytecodeForCall(callFrame, callDataScopeChain); 3775 3794 3776 3795 CallFrame* previousCallFrame = callFrame; 3777 3778 callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount); 3796 if (newCodeBlock) 3797 callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount); 3798 else 3799 callFrame = 0; 3779 3800 if (UNLIKELY(!callFrame)) { 3780 3801 callFrame = previousCallFrame; … … 4095 4116 if (constructType == ConstructTypeJS) { 4096 4117 ScopeChainNode* callDataScopeChain = constructData.js.scopeChain; 4097 CodeBlock* newCodeBlock = &constructData.js.functionExecutable->bytecodeForConstruct(callFrame, callDataScopeChain);4118 CodeBlock* newCodeBlock = constructData.js.functionExecutable->bytecodeForConstruct(callFrame, callDataScopeChain); 4098 4119 4099 4120 CallFrame* previousCallFrame = callFrame; 4100 4121 4101 callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount); 4122 if (newCodeBlock) 4123 callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount); 4124 else 4125 callFrame = 0; 4126 4102 4127 if (UNLIKELY(!callFrame)) { 4103 4128 callFrame = previousCallFrame; -
trunk/JavaScriptCore/jit/JITOpcodes.cpp
r60901 r61588 74 74 // VirtualCallLink Trampoline 75 75 // regT0 holds callee, regT1 holds argCount. regT2 will hold the FunctionExecutable. 76 JumpList callLazyLinkFailures; 76 77 Label virtualCallLinkBegin = align(); 77 78 compileOpCallInitializeCallFrame(); … … 80 81 restoreArgumentReference(); 81 82 Call callLazyLinkCall = call(); 83 callLazyLinkFailures.append(branchTestPtr(Zero, regT0)); 82 84 restoreReturnAddressBeforeReturn(regT3); 83 85 emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT1); … … 92 94 restoreArgumentReference(); 93 95 Call callLazyLinkConstruct = call(); 96 callLazyLinkFailures.append(branchTestPtr(Zero, regT0)); 94 97 restoreReturnAddressBeforeReturn(regT3); 95 98 emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT1); 96 99 jump(regT0); 100 101 // If the parser fails we want to be able to be able to keep going, 102 // So we handle this as a parse failure. 103 callLazyLinkFailures.link(this); 104 emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1); 105 emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister); 106 restoreReturnAddressBeforeReturn(regT1); 107 move(ImmPtr(&globalData->exceptionLocation), regT2); 108 storePtr(regT1, regT2); 109 poke(callFrameRegister, 1 + OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*)); 110 poke(ImmPtr(FunctionPtr(ctiVMThrowTrampoline).value())); 111 ret(); 112 97 113 98 114 // VirtualCall Trampoline -
trunk/JavaScriptCore/jit/JITOpcodes32_64.cpp
r60901 r61588 67 67 68 68 // (2) Trampolines for the slow cases of op_call / op_call_eval / op_construct. 69 70 69 #if ENABLE(JIT_OPTIMIZE_CALL) 70 JumpList callLazyLinkFailures; 71 71 // VirtualCallLink Trampoline 72 72 // regT0 holds callee, regT1 holds argCount. regT2 will hold the FunctionExecutable. … … 77 77 restoreArgumentReference(); 78 78 Call callLazyLinkCall = call(); 79 callLazyLinkFailures.append(branchTestPtr(Zero, regT0)); 79 80 restoreReturnAddressBeforeReturn(regT3); 80 81 emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT1); … … 90 91 Call callLazyLinkConstruct = call(); 91 92 restoreReturnAddressBeforeReturn(regT3); 93 callLazyLinkFailures.append(branchTestPtr(Zero, regT0)); 92 94 emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT1); 93 95 jump(regT0); 96 97 // If the parser fails we want to be able to be able to keep going, 98 // So we handle this as a parse failure. 99 callLazyLinkFailures.link(this); 100 emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1); 101 emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister); 102 restoreReturnAddressBeforeReturn(regT1); 103 move(ImmPtr(&globalData->exceptionLocation), regT2); 104 storePtr(regT1, regT2); 105 poke(callFrameRegister, 1 + OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*)); 106 poke(ImmPtr(FunctionPtr(ctiVMThrowTrampoline).value())); 107 ret(); 108 94 109 #endif // ENABLE(JIT_OPTIMIZE_CALL) 95 110 -
trunk/JavaScriptCore/jit/JITStubs.cpp
r61553 r61588 1968 1968 else { 1969 1969 FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable); 1970 codeBlock = &functionExecutable->bytecodeForCall(stackFrame.callFrame, callee->scope().node()); 1970 codeBlock = functionExecutable->bytecodeForCall(stackFrame.callFrame, callee->scope().node()); 1971 if (!codeBlock) { 1972 stackFrame.callFrame->globalData().exception = createStackOverflowError(callFrame); 1973 return 0; 1974 } 1971 1975 functionExecutable->jitCodeForCall(callFrame, callee->scope().node()); 1972 1976 if (callFrame->argumentCountIncludingThis() == static_cast<size_t>(codeBlock->m_numParameters)) … … 1998 2002 else { 1999 2003 FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable); 2000 codeBlock = &functionExecutable->bytecodeForConstruct(stackFrame.callFrame, callee->scope().node()); 2004 codeBlock = functionExecutable->bytecodeForConstruct(stackFrame.callFrame, callee->scope().node()); 2005 if (!codeBlock) { 2006 throwStackOverflowError(callFrame, stackFrame.globalData, ReturnAddressPtr(callFrame->returnPC()), STUB_RETURN_ADDRESS); 2007 VM_THROW_EXCEPTION(); 2008 } 2001 2009 functionExecutable->jitCodeForConstruct(callFrame, callee->scope().node()); 2002 2010 if (callFrame->argumentCountIncludingThis() == static_cast<size_t>(codeBlock->m_numParameters)) -
trunk/JavaScriptCore/runtime/ArrayPrototype.cpp
r60762 r61588 78 78 // function with a CodeBlock also has JIT code. 79 79 callData.js.functionExecutable->jitCodeForCall(exec, callData.js.scopeChain); 80 CodeBlock & codeBlock =callData.js.functionExecutable->generatedBytecodeForCall();80 CodeBlock* codeBlock = &callData.js.functionExecutable->generatedBytecodeForCall(); 81 81 #else 82 CodeBlock &codeBlock = callData.js.functionExecutable->bytecodeForCall(exec, callData.js.scopeChain);82 CodeBlock* codeBlock = callData.js.functionExecutable->bytecodeForCall(exec, callData.js.scopeChain); 83 83 #endif 84 85 return codeBlock.isNumericCompareFunction(); 84 if (!codeBlock) 85 return false; 86 87 return codeBlock->isNumericCompareFunction(); 86 88 } 87 89 -
trunk/JavaScriptCore/runtime/Executable.cpp
r60762 r61588 120 120 } 121 121 122 voidFunctionExecutable::compileForCall(ExecState*, ScopeChainNode* scopeChainNode)122 bool FunctionExecutable::compileForCall(ExecState*, ScopeChainNode* scopeChainNode) 123 123 { 124 124 JSGlobalData* globalData = scopeChainNode->globalData; 125 125 RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, m_source); 126 if (!body) 127 return false; 126 128 if (m_forceUsesArguments) 127 129 body->setUsesArguments(); … … 142 144 143 145 body->destroyData(); 144 } 145 146 void FunctionExecutable::compileForConstruct(ExecState*, ScopeChainNode* scopeChainNode) 146 return true; 147 } 148 149 bool FunctionExecutable::compileForConstruct(ExecState*, ScopeChainNode* scopeChainNode) 147 150 { 148 151 JSGlobalData* globalData = scopeChainNode->globalData; 149 152 RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, m_source); 153 if (!body) 154 return false; 150 155 if (m_forceUsesArguments) 151 156 body->setUsesArguments(); … … 166 171 167 172 body->destroyData(); 173 return true; 168 174 } 169 175 … … 194 200 void FunctionExecutable::generateJITCodeForCall(ExecState* exec, ScopeChainNode* scopeChainNode) 195 201 { 196 CodeBlock* codeBlock = &bytecodeForCall(exec, scopeChainNode);202 CodeBlock* codeBlock = bytecodeForCall(exec, scopeChainNode); 197 203 m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, codeBlock, &m_jitCodeForCallWithArityCheck); 198 204 … … 205 211 void FunctionExecutable::generateJITCodeForConstruct(ExecState* exec, ScopeChainNode* scopeChainNode) 206 212 { 207 CodeBlock* codeBlock = &bytecodeForConstruct(exec, scopeChainNode);213 CodeBlock* codeBlock = bytecodeForConstruct(exec, scopeChainNode); 208 214 m_jitCodeForConstruct = JIT::compile(scopeChainNode->globalData, codeBlock, &m_jitCodeForConstructWithArityCheck); 209 215 … … 227 233 { 228 234 RefPtr<FunctionBodyNode> newFunctionBody = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, m_source); 235 if (!newFunctionBody) 236 return 0; 229 237 if (m_forceUsesArguments) 230 238 newFunctionBody->setUsesArguments(); … … 256 264 { 257 265 RefPtr<EvalNode> newEvalBody = globalData->parser->parse<EvalNode>(globalData, 0, 0, m_source); 266 if (!newEvalBody) 267 return 0; 258 268 259 269 ScopeChain scopeChain(scopeChainNode); -
trunk/JavaScriptCore/runtime/Executable.h
r60376 r61588 306 306 } 307 307 308 FunctionCodeBlock &bytecodeForCall(ExecState* exec, ScopeChainNode* scopeChainNode)308 FunctionCodeBlock* bytecodeForCall(ExecState* exec, ScopeChainNode* scopeChainNode) 309 309 { 310 310 ASSERT(scopeChainNode); 311 311 if (!m_codeBlockForCall) 312 312 compileForCall(exec, scopeChainNode); 313 return *m_codeBlockForCall;313 return m_codeBlockForCall; 314 314 } 315 315 … … 325 325 } 326 326 327 FunctionCodeBlock &bytecodeForConstruct(ExecState* exec, ScopeChainNode* scopeChainNode)327 FunctionCodeBlock* bytecodeForConstruct(ExecState* exec, ScopeChainNode* scopeChainNode) 328 328 { 329 329 ASSERT(scopeChainNode); 330 330 if (!m_codeBlockForConstruct) 331 331 compileForConstruct(exec, scopeChainNode); 332 return *m_codeBlockForConstruct;332 return m_codeBlockForConstruct; 333 333 } 334 334 … … 384 384 } 385 385 386 voidcompileForCall(ExecState*, ScopeChainNode*);387 voidcompileForConstruct(ExecState*, ScopeChainNode*);386 bool compileForCall(ExecState*, ScopeChainNode*); 387 bool compileForConstruct(ExecState*, ScopeChainNode*); 388 388 389 389 unsigned m_numVariables : 31; -
trunk/JavaScriptCore/runtime/JSGlobalData.cpp
r59746 r61588 247 247 initializingLazyNumericCompareFunction = true; 248 248 RefPtr<FunctionExecutable> function = FunctionExecutable::fromGlobalCode(Identifier(exec, "numericCompare"), exec, 0, makeSource(UString("(function (v1, v2) { return v1 - v2; })")), 0, 0); 249 lazyNumericCompareFunction = function->bytecodeForCall(exec, exec->scopeChain()) .instructions();249 lazyNumericCompareFunction = function->bytecodeForCall(exec, exec->scopeChain())->instructions(); 250 250 initializingLazyNumericCompareFunction = false; 251 251 }
Note: See TracChangeset
for help on using the changeset viewer.