Changeset 44844 in webkit
- Timestamp:
- Jun 19, 2009 12:10:49 AM (15 years ago)
- Location:
- trunk/JavaScriptCore
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r44843 r44844 1 2009-06-18 Oliver Hunt <oliver@apple.com> 2 3 Reviewed by Gavin "Viceroy of Venezuela" Barraclough. 4 5 Bug 26532: Native functions do not correctly unlink from optimised callsites when they're collected 6 <https://bugs.webkit.org/show_bug.cgi?id=26532> <rdar://problem/6625385> 7 8 We need to make sure that each native function instance correctly unlinks any references to it 9 when it is collected. Allowing this to happen required a few changes: 10 * Every native function needs a codeblock to track the link information 11 * To have this codeblock, every function now also needs its own functionbodynode 12 so we no longer get to have a single shared instance. 13 * Identifying a host function is now done by looking for CodeBlock::codeType() == NativeCode 14 15 * JavaScriptCore.exp: 16 * bytecode/CodeBlock.cpp: 17 (JSC::CodeBlock::CodeBlock): 18 Constructor for NativeCode CodeBlock 19 (JSC::CodeBlock::derefStructures): 20 (JSC::CodeBlock::refStructures): 21 (JSC::CodeBlock::reparseForExceptionInfoIfNecessary): 22 (JSC::CodeBlock::handlerForBytecodeOffset): 23 (JSC::CodeBlock::lineNumberForBytecodeOffset): 24 (JSC::CodeBlock::expressionRangeForBytecodeOffset): 25 (JSC::CodeBlock::getByIdExceptionInfoForBytecodeOffset): 26 (JSC::CodeBlock::functionRegisterForBytecodeOffset): 27 (JSC::CodeBlock::hasGlobalResolveInstructionAtBytecodeOffset): 28 (JSC::CodeBlock::hasGlobalResolveInfoAtBytecodeOffset): 29 (JSC::CodeBlock::setJITCode): 30 Add assertions to ensure we don't try and use NativeCode CodeBlocks as 31 a normal codeblock. 32 33 * bytecode/CodeBlock.h: 34 (JSC::): 35 (JSC::CodeBlock::source): 36 (JSC::CodeBlock::sourceOffset): 37 (JSC::CodeBlock::evalCodeCache): 38 (JSC::CodeBlock::createRareDataIfNecessary): 39 More assertions. 40 41 * jit/JIT.cpp: 42 (JSC::JIT::privateCompileCTIMachineTrampolines): 43 (JSC::JIT::linkCall): 44 Update logic to allow native function caching 45 46 * jit/JITStubs.cpp: 47 * parser/Nodes.cpp: 48 (JSC::FunctionBodyNode::createNativeThunk): 49 (JSC::FunctionBodyNode::isHostFunction): 50 * parser/Nodes.h: 51 * runtime/JSFunction.cpp: 52 (JSC::JSFunction::JSFunction): 53 (JSC::JSFunction::~JSFunction): 54 (JSC::JSFunction::mark): 55 * runtime/JSGlobalData.cpp: 56 (JSC::JSGlobalData::~JSGlobalData): 57 * runtime/JSGlobalData.h: 58 1 59 2009-06-18 Gavin Barraclough <barraclough@apple.com> 2 60 -
trunk/JavaScriptCore/JavaScriptCore.exp
r44831 r44844 332 332 __ZNK3JSC12StringObject8toStringEPNS_9ExecStateE 333 333 __ZNK3JSC14JSGlobalObject14isDynamicScopeEv 334 __ZNK3JSC16FunctionBodyNode14isHostFunctionEv 334 335 __ZNK3JSC16InternalFunction9classInfoEv 335 336 __ZNK3JSC16JSVariableObject16isVariableObjectEv -
trunk/JavaScriptCore/bytecode/CodeBlock.cpp
r44076 r44844 1266 1266 } 1267 1267 1268 CodeBlock::CodeBlock(ScopeNode* ownerNode) 1269 : m_numCalleeRegisters(0) 1270 , m_numConstants(0) 1271 , m_numVars(0) 1272 , m_numParameters(0) 1273 , m_ownerNode(ownerNode) 1274 , m_globalData(0) 1275 #ifndef NDEBUG 1276 , m_instructionCount(0) 1277 #endif 1278 , m_needsFullScopeChain(false) 1279 , m_usesEval(false) 1280 , m_isNumericCompareFunction(false) 1281 , m_codeType(NativeCode) 1282 , m_source(0) 1283 , m_sourceOffset(0) 1284 , m_exceptionInfo(0) 1285 { 1286 #if DUMP_CODE_BLOCK_STATISTICS 1287 liveCodeBlockSet.add(this); 1288 #endif 1289 } 1268 1290 1269 1291 CodeBlock::CodeBlock(ScopeNode* ownerNode, CodeType codeType, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset) … … 1343 1365 void CodeBlock::derefStructures(Instruction* vPC) const 1344 1366 { 1367 ASSERT(m_codeType != NativeCode); 1345 1368 Interpreter* interpreter = m_globalData->interpreter; 1346 1369 … … 1388 1411 void CodeBlock::refStructures(Instruction* vPC) const 1389 1412 { 1413 ASSERT(m_codeType != NativeCode); 1390 1414 Interpreter* interpreter = m_globalData->interpreter; 1391 1415 … … 1442 1466 void CodeBlock::reparseForExceptionInfoIfNecessary(CallFrame* callFrame) 1443 1467 { 1468 ASSERT(m_codeType != NativeCode); 1444 1469 if (m_exceptionInfo) 1445 1470 return; … … 1512 1537 HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset) 1513 1538 { 1539 ASSERT(m_codeType != NativeCode); 1514 1540 ASSERT(bytecodeOffset < m_instructionCount); 1515 1541 … … 1530 1556 int CodeBlock::lineNumberForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset) 1531 1557 { 1558 ASSERT(m_codeType != NativeCode); 1532 1559 ASSERT(bytecodeOffset < m_instructionCount); 1533 1560 … … 1555 1582 int CodeBlock::expressionRangeForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset) 1556 1583 { 1584 ASSERT(m_codeType != NativeCode); 1557 1585 ASSERT(bytecodeOffset < m_instructionCount); 1558 1586 … … 1594 1622 bool CodeBlock::getByIdExceptionInfoForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset, OpcodeID& opcodeID) 1595 1623 { 1624 ASSERT(m_codeType != NativeCode); 1596 1625 ASSERT(bytecodeOffset < m_instructionCount); 1597 1626 … … 1622 1651 bool CodeBlock::functionRegisterForBytecodeOffset(unsigned bytecodeOffset, int& functionRegisterIndex) 1623 1652 { 1653 ASSERT(m_codeType != NativeCode); 1624 1654 ASSERT(bytecodeOffset < m_instructionCount); 1625 1655 … … 1648 1678 bool CodeBlock::hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset) 1649 1679 { 1680 ASSERT(m_codeType != NativeCode); 1650 1681 if (m_globalResolveInstructions.isEmpty()) 1651 1682 return false; … … 1668 1699 bool CodeBlock::hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset) 1669 1700 { 1701 ASSERT(m_codeType != NativeCode); 1670 1702 if (m_globalResolveInfos.isEmpty()) 1671 1703 return false; … … 1690 1722 void CodeBlock::setJITCode(JITCode jitCode) 1691 1723 { 1724 ASSERT(m_codeType != NativeCode); 1692 1725 ownerNode()->setJITCode(jitCode); 1693 1726 #if !ENABLE(OPCODE_SAMPLING) -
trunk/JavaScriptCore/bytecode/CodeBlock.h
r44711 r44844 50 50 class ExecState; 51 51 52 enum CodeType { GlobalCode, EvalCode, FunctionCode };52 enum CodeType { GlobalCode, EvalCode, FunctionCode, NativeCode }; 53 53 54 54 static ALWAYS_INLINE int missingThisObjectMarker() { return std::numeric_limits<int>::max(); } … … 218 218 friend class JIT; 219 219 public: 220 CodeBlock(ScopeNode* ownerNode); 220 221 CodeBlock(ScopeNode* ownerNode, CodeType, PassRefPtr<SourceProvider>, unsigned sourceOffset); 221 222 ~CodeBlock(); … … 340 341 CodeType codeType() const { return m_codeType; } 341 342 342 SourceProvider* source() const { return m_source.get(); }343 unsigned sourceOffset() const { return m_sourceOffset; }343 SourceProvider* source() const { ASSERT(m_codeType != NativeCode); return m_source.get(); } 344 unsigned sourceOffset() const { ASSERT(m_codeType != NativeCode); return m_sourceOffset; } 344 345 345 346 size_t numberOfJumpTargets() const { return m_jumpTargets.size(); } … … 433 434 SymbolTable& symbolTable() { return m_symbolTable; } 434 435 435 EvalCodeCache& evalCodeCache() { createRareDataIfNecessary(); return m_rareData->m_evalCodeCache; }436 EvalCodeCache& evalCodeCache() { ASSERT(m_codeType != NativeCode); createRareDataIfNecessary(); return m_rareData->m_evalCodeCache; } 436 437 437 438 void shrinkToFit(); … … 457 458 void createRareDataIfNecessary() 458 459 { 460 ASSERT(m_codeType != NativeCode); 459 461 if (!m_rareData) 460 462 m_rareData.set(new RareData); -
trunk/JavaScriptCore/jit/JIT.cpp
r44745 r44844 547 547 548 548 // (3) Trampolines for the slow cases of op_call / op_call_eval / op_construct. 549 549 COMPILE_ASSERT(sizeof(CodeType) == 4, CodeTypeEnumMustBe32Bit); 550 550 551 Label virtualCallPreLinkBegin = align(); 551 552 … … 554 555 loadPtr(Address(regT3, FIELD_OFFSET(FunctionBodyNode, m_code)), regT0); 555 556 Jump hasCodeBlock1 = branchTestPtr(NonZero, regT0); 556 // If m_code is null and m_jitCode is not, then we have a native function, so arity is irrelevant557 loadPtr(Address(regT3, FIELD_OFFSET(FunctionBodyNode, m_jitCode)), regT0);558 Jump isNativeFunc1 = branchTestPtr(NonZero, regT0);559 557 preverveReturnAddressAfterCall(regT3); 560 558 restoreArgumentReference(); … … 564 562 restoreReturnAddressBeforeReturn(regT3); 565 563 hasCodeBlock1.link(this); 564 565 Jump isNativeFunc1 = branch32(Equal, Address(regT0, FIELD_OFFSET(CodeBlock, m_codeType)), Imm32(NativeCode)); 566 566 567 567 // Check argCount matches callee arity. … … 596 596 loadPtr(Address(regT3, FIELD_OFFSET(FunctionBodyNode, m_code)), regT0); 597 597 Jump hasCodeBlock2 = branchTestPtr(NonZero, regT0); 598 // If m_code is null and m_jitCode is not, then we have a native function, so arity is irrelevant599 loadPtr(Address(regT3, FIELD_OFFSET(FunctionBodyNode, m_jitCode)), regT0);600 Jump isNativeFunc2 = branchTestPtr(NonZero, regT0);601 598 preverveReturnAddressAfterCall(regT3); 602 599 restoreArgumentReference(); … … 606 603 restoreReturnAddressBeforeReturn(regT3); 607 604 hasCodeBlock2.link(this); 605 606 Jump isNativeFunc2 = branch32(Equal, Address(regT0, FIELD_OFFSET(CodeBlock, m_codeType)), Imm32(NativeCode)); 608 607 609 608 // Check argCount matches callee arity. … … 637 636 loadPtr(Address(regT3, FIELD_OFFSET(FunctionBodyNode, m_code)), regT0); 638 637 Jump hasCodeBlock3 = branchTestPtr(NonZero, regT0); 639 // If m_code is null and m_jitCode is not, then we have a native function, so arity is irrelevant640 loadPtr(Address(regT3, FIELD_OFFSET(FunctionBodyNode, m_jitCode)), regT0);641 Jump isNativeFunc3 = branchTestPtr(NonZero, regT0);642 638 preverveReturnAddressAfterCall(regT3); 643 639 restoreArgumentReference(); … … 648 644 loadPtr(Address(regT2, FIELD_OFFSET(JSFunction, m_body)), regT3); // reload the function body nody, so we can reload the code pointer. 649 645 hasCodeBlock3.link(this); 646 647 Jump isNativeFunc3 = branch32(Equal, Address(regT0, FIELD_OFFSET(CodeBlock, m_codeType)), Imm32(NativeCode)); 650 648 651 649 // Check argCount matches callee arity. … … 662 660 loadPtr(Address(regT2, FIELD_OFFSET(JSFunction, m_body)), regT3); // reload the function body nody, so we can reload the code pointer. 663 661 arityCheckOkay3.link(this); 662 isNativeFunc3.link(this); 663 664 664 // load ctiCode from the new codeBlock. 665 665 loadPtr(Address(regT3, FIELD_OFFSET(FunctionBodyNode, m_jitCode)), regT0); 666 isNativeFunc3.link(this); 667 666 668 667 compileOpCallInitializeCallFrame(); 669 668 jump(regT0); … … 912 911 void JIT::linkCall(JSFunction* callee, CodeBlock* calleeCodeBlock, JITCode& code, CallLinkInfo* callLinkInfo, int callerArgCount, JSGlobalData* globalData) 913 912 { 913 ASSERT(calleeCodeBlock); 914 914 RepatchBuffer repatchBuffer; 915 915 916 916 // Currently we only link calls with the exact number of arguments. 917 917 // If this is a native call calleeCodeBlock is null so the number of parameters is unimportant 918 if ( !calleeCodeBlock || callerArgCount == calleeCodeBlock->m_numParameters) {918 if (callerArgCount == calleeCodeBlock->m_numParameters || calleeCodeBlock->codeType() == NativeCode) { 919 919 ASSERT(!callLinkInfo->isLinked()); 920 920 -
trunk/JavaScriptCore/jit/JITStubs.cpp
r44838 r44844 1192 1192 1193 1193 JSFunction* function = asFunction(stackFrame.args[0].jsValue()); 1194 ASSERT(!function->isHostFunction()); 1194 1195 FunctionBodyNode* body = function->body(); 1195 1196 ScopeChainNode* callDataScopeChain = function->scope().node(); … … 1205 1206 CallFrame* callFrame = stackFrame.callFrame; 1206 1207 CodeBlock* newCodeBlock = stackFrame.args[3].codeBlock(); 1208 ASSERT(newCodeBlock->codeType() != NativeCode); 1207 1209 int argCount = stackFrame.args[2].int32(); 1208 1210 … … 1266 1268 if (!callee->isHostFunction()) 1267 1269 codeBlock = &callee->body()->bytecode(callee->scope().node()); 1270 else 1271 codeBlock = &callee->body()->generatedBytecode(); 1268 1272 1269 1273 CallLinkInfo* callLinkInfo = &stackFrame.callFrame->callerFrame()->codeBlock()->getCallLinkInfo(stackFrame.args[1].returnAddress()); -
trunk/JavaScriptCore/parser/Nodes.cpp
r44224 r44844 2038 2038 RefPtr<FunctionBodyNode> body = new FunctionBodyNode(globalData); 2039 2039 globalData->parser->arena().reset(); 2040 body->m_code.set(new CodeBlock(body.get())); 2040 2041 body->m_jitCode = JITCode(JITCode::HostFunction(globalData->jitStubs.ctiNativeCallThunk())); 2041 2042 return body.release(); 2042 2043 } 2043 2044 #endif 2045 2046 bool FunctionBodyNode::isHostFunction() const 2047 { 2048 return m_code && m_code->codeType() == NativeCode; 2049 } 2044 2050 2045 2051 FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData) -
trunk/JavaScriptCore/parser/Nodes.h
r44224 r44844 1555 1555 } 1556 1556 1557 bool isHostFunction() const 1558 { 1559 #if ENABLE(JIT) 1560 return !!m_jitCode && !m_code; 1561 #else 1562 return true; 1563 #endif 1564 } 1557 bool isHostFunction() const; 1565 1558 1566 1559 virtual void mark(); -
trunk/JavaScriptCore/runtime/JSFunction.cpp
r43661 r44844 49 49 : Base(&exec->globalData(), structure, name) 50 50 #if ENABLE(JIT) 51 , m_body( exec->globalData().nativeFunctionThunk())51 , m_body(FunctionBodyNode::createNativeThunk(&exec->globalData())) 52 52 #else 53 53 , m_body(0) … … 77 77 // are based on a check for the this pointer value for this JSFunction - which will no longer be valid once 78 78 // this memory is freed and may be reused (potentially for another, different JSFunction). 79 if ( !isHostFunction()) {80 if (m_body && m_body->isGenerated())81 m_body->generatedBytecode().unlinkCallers();79 if (m_body && m_body->isGenerated()) 80 m_body->generatedBytecode().unlinkCallers(); 81 if (!isHostFunction()) 82 82 scopeChain().~ScopeChain(); 83 }84 85 83 #endif 86 84 } … … 89 87 { 90 88 Base::mark(); 91 if (!isHostFunction()) {92 m_body->mark();89 m_body->mark(); 90 if (!isHostFunction()) 93 91 scopeChain().mark(); 94 }95 92 } 96 93 -
trunk/JavaScriptCore/runtime/JSGlobalData.cpp
r44813 r44844 165 165 regExpConstructorTable->deleteTable(); 166 166 stringTable->deleteTable(); 167 #if ENABLE(JIT)168 lazyNativeFunctionThunk.clear();169 #endif170 167 171 168 fastDelete(const_cast<HashTable*>(arrayTable)); … … 228 225 } 229 226 230 #if ENABLE(JIT)231 232 void JSGlobalData::createNativeThunk()233 {234 lazyNativeFunctionThunk = FunctionBodyNode::createNativeThunk(this);235 }236 237 #endif238 239 227 // FIXME: We can also detect forms like v1 < v2 ? -1 : 0, reverse comparison, etc. 240 228 const Vector<Instruction>& JSGlobalData::numericCompareFunction(ExecState* exec) -
trunk/JavaScriptCore/runtime/JSGlobalData.h
r44813 r44844 121 121 #if ENABLE(JIT) 122 122 JITThunks jitStubs; 123 FunctionBodyNode* nativeFunctionThunk()124 {125 if (!lazyNativeFunctionThunk)126 createNativeThunk();127 return lazyNativeFunctionThunk.get();128 }129 RefPtr<FunctionBodyNode> lazyNativeFunctionThunk;130 123 #endif 131 124 TimeoutChecker timeoutChecker;
Note: See TracChangeset
for help on using the changeset viewer.