Changeset 138921 in webkit
- Timestamp:
- Jan 6, 2013 6:24:58 PM (11 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 18 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r138915 r138921 1 2013-01-05 Filip Pizlo <fpizlo@apple.com> 2 3 DFG should inline closure calls 4 https://bugs.webkit.org/show_bug.cgi?id=106067 5 6 Reviewed by Gavin Barraclough. 7 8 This adds initial support for inlining closure calls to the DFG. A call is considered 9 to be a closure call when the JSFunction* varies, but always has the same executable. 10 We already have closure call inline caching in both JITs, which works by checking that 11 the callee has an expected structure (as a cheap way of detecting that it is in fact 12 a JSFunction) and an expected executable. Closure call inlining uses profiling data 13 aggregated by CallLinkStatus to decide when to specialize the call to the particular 14 structure/executable, and inline the call rather than emitting a call sequence. When 15 we choose to do a closure inline rather than an ordinary inline, a number of things 16 change about how inlining is performed: 17 18 - The inline is guarded by a CheckStructure/CheckExecutable rather than a 19 CheckFunction. 20 21 - Instead of propagating a constant value for the scope, we emit GetMyScope every time 22 that the scope is needed, which loads the scope from a local variable. We do similar 23 things for the callee. 24 25 - The prologue of the inlined code includes SetMyScope and SetCallee nodes to eagerly 26 plant the scope and callee into the "true call frame", i.e. the place on the stack 27 where the call frame would have been if the call had been actually performed. This 28 allows GetMyScope/GetCallee to work as they would if the code wasn't inlined. It 29 also allows for trivial handling of scope and callee for call frame reconstruction 30 upon stack introspection and during OSR. 31 32 - A new node called GetScope is introduced, which just gets the scope of a function. 33 This node has the expected CSE support. This allows for the 34 SetMyScope(GetScope(@function)) sequence to set up the scope in the true call frame. 35 36 - GetMyScope/GetCallee CSE can match against SetMyScope/SetCallee, which means that 37 the GetMyScope/GetCallee nodes emitted during parsing are often removed during CSE, 38 if we can prove that it is safe to do so. 39 40 - Inlining heuristics are adjusted to grok the cost of inlining a closure. We are 41 less likely to inline a closure call than we are to inline a normal call, since we 42 end up emitting more code for closures due to CheckStructure, CheckExecutable, 43 GetScope, SetMyScope, and SetCallee. 44 45 Additionally, I've fixed the VariableEventStream to ensure that we don't attempt to 46 plant Undefined into the true call frames. This was previously a harmless oversight, 47 but it becomes quite bad if OSR is relying on the scope/callee already having been 48 set and not subsequently clobbered by the OSR itself. 49 50 This is a ~60% speed-up on programs that frequently make calls to closures. It's 51 neutral on V8v7 and other major benchmark suites. 52 53 The lack of a definite speed-up is likely due the fact that closure inlining currently 54 does not do any cardinality [1] optimizations. We don't observe when a closure was 55 constructed within its caller, and so used the scope from its caller; and furthermore 56 we have no facility to detect when the scope is single. All scoped variable accesses 57 are assumed to be multiple instead. A subsequent step will be to ensure that closure 58 call inlining will be single and loving it. 59 60 [1] Single and loving it: Must-alias analysis for higher-order languages. Suresh 61 Jagannathan, Peter Thiemann, Stephen Weeks, and Andrew Wright. In POPL '98. 62 63 * bytecode/CallLinkStatus.cpp: 64 (JSC::CallLinkStatus::dump): 65 * bytecode/CallLinkStatus.h: 66 (JSC::CallLinkStatus::isClosureCall): 67 (CallLinkStatus): 68 * bytecode/CodeBlock.cpp: 69 (JSC::CodeBlock::globalObjectFor): 70 (JSC): 71 * bytecode/CodeBlock.h: 72 (CodeBlock): 73 * bytecode/CodeOrigin.cpp: 74 (JSC::InlineCallFrame::dump): 75 * dfg/DFGAbstractState.cpp: 76 (JSC::DFG::AbstractState::execute): 77 * dfg/DFGByteCodeParser.cpp: 78 (ByteCodeParser): 79 (JSC::DFG::ByteCodeParser::handleCall): 80 (JSC::DFG::ByteCodeParser::emitFunctionChecks): 81 (JSC::DFG::ByteCodeParser::handleInlining): 82 * dfg/DFGCSEPhase.cpp: 83 (JSC::DFG::CSEPhase::pureCSE): 84 (CSEPhase): 85 (JSC::DFG::CSEPhase::getCalleeLoadElimination): 86 (JSC::DFG::CSEPhase::checkExecutableElimination): 87 (JSC::DFG::CSEPhase::getMyScopeLoadElimination): 88 (JSC::DFG::CSEPhase::performNodeCSE): 89 * dfg/DFGCapabilities.cpp: 90 (JSC::DFG::mightInlineFunctionForClosureCall): 91 * dfg/DFGCapabilities.h: 92 (DFG): 93 (JSC::DFG::mightInlineFunctionForClosureCall): 94 (JSC::DFG::canInlineFunctionForClosureCall): 95 (JSC::DFG::canInlineFunctionFor): 96 * dfg/DFGNode.h: 97 (Node): 98 (JSC::DFG::Node::hasExecutable): 99 (JSC::DFG::Node::executable): 100 * dfg/DFGNodeType.h: 101 (DFG): 102 * dfg/DFGPredictionPropagationPhase.cpp: 103 (JSC::DFG::PredictionPropagationPhase::propagate): 104 * dfg/DFGSpeculativeJIT32_64.cpp: 105 (JSC::DFG::SpeculativeJIT::compile): 106 * dfg/DFGSpeculativeJIT64.cpp: 107 (JSC::DFG::SpeculativeJIT::compile): 108 * dfg/DFGVariableEventStream.cpp: 109 (JSC::DFG::VariableEventStream::reconstruct): 110 * runtime/Options.h: 111 (JSC): 112 1 113 2013-01-05 Filip Pizlo <fpizlo@apple.com> 2 114 -
trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.cpp
r138871 r138921 120 120 } 121 121 122 void CallLinkStatus::dump(PrintStream& out) 122 void CallLinkStatus::dump(PrintStream& out) const 123 123 { 124 124 if (!isSet()) { -
trunk/Source/JavaScriptCore/bytecode/CallLinkStatus.h
r138871 r138921 105 105 106 106 bool couldTakeSlowPath() const { return m_couldTakeSlowPath; } 107 bool isClosureCall() const { return !m_callTarget; }107 bool isClosureCall() const { return m_executable && !m_callTarget; } 108 108 109 109 JSValue callTarget() const { return m_callTarget; } … … 116 116 bool canOptimize() const { return (m_callTarget || m_executable) && !m_couldTakeSlowPath; } 117 117 118 void dump(PrintStream&) ;118 void dump(PrintStream&) const; 119 119 120 120 private: -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r138741 r138921 2934 2934 #endif 2935 2935 2936 JSGlobalObject* CodeBlock::globalObjectFor(CodeOrigin codeOrigin) 2937 { 2938 if (!codeOrigin.inlineCallFrame) 2939 return globalObject(); 2940 return jsCast<FunctionExecutable*>(codeOrigin.inlineCallFrame->executable.get())->generatedBytecode().globalObject(); 2941 } 2942 2936 2943 unsigned CodeBlock::reoptimizationRetryCounter() const 2937 2944 { -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.h
r138074 r138921 937 937 JSGlobalObject* globalObject() { return m_globalObject.get(); } 938 938 939 JSGlobalObject* globalObjectFor(CodeOrigin codeOrigin) 940 { 941 if (!codeOrigin.inlineCallFrame) 942 return globalObject(); 943 // FIXME: if we ever inline based on executable not function, this code will need to change. 944 return codeOrigin.inlineCallFrame->callee->scope()->globalObject(); 945 } 939 JSGlobalObject* globalObjectFor(CodeOrigin); 946 940 947 941 // Jump Tables -
trunk/Source/JavaScriptCore/bytecode/CodeOrigin.cpp
r138669 r138921 87 87 else 88 88 out.print(", closure call"); 89 out.print(", stack >= r", stackOffset); 89 90 out.print(">"); 90 91 } -
trunk/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
r137699 r138921 1383 1383 forNode(nodeIndex).set(SpecFunction); 1384 1384 break; 1385 1385 1386 case SetCallee: 1387 case SetMyScope: 1388 node.setCanExit(false); 1389 break; 1390 1391 case GetScope: // FIXME: We could get rid of these if we know that the JSFunction is a constant. https://bugs.webkit.org/show_bug.cgi?id=106202 1386 1392 case GetMyScope: 1387 1393 case SkipTopScope: … … 1456 1462 forNode(nodeIndex).set(SpecInt32); 1457 1463 break; 1464 1465 case CheckExecutable: { 1466 // FIXME: We could track executables in AbstractValue, which would allow us to get rid of these checks 1467 // more thoroughly. https://bugs.webkit.org/show_bug.cgi?id=106200 1468 // FIXME: We could eliminate these entirely if we know the exact value that flows into this. 1469 // https://bugs.webkit.org/show_bug.cgi?id=106201 1470 forNode(node.child1()).filter(SpecCell); 1471 node.setCanExit(true); 1472 break; 1473 } 1458 1474 1459 1475 case CheckStructure: -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r138871 r138921 160 160 // Handle calls. This resolves issues surrounding inlining and intrinsics. 161 161 void handleCall(Interpreter*, Instruction* currentInstruction, NodeType op, CodeSpecializationKind); 162 void emitFunctionCheck (JSFunction* expectedFunction, NodeIndex callTarget, int registerOffset, CodeSpecializationKind);162 void emitFunctionChecks(const CallLinkStatus&, NodeIndex callTarget, int registerOffset, CodeSpecializationKind); 163 163 // Handle inlining. Return true if it succeeded, false if we need to plant a call. 164 bool handleInlining(bool usesResult, NodeIndex callTargetNodeIndex, int resultOperand, bool certainAboutExpectedFunction, JSFunction*, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, CodeSpecializationKind);164 bool handleInlining(bool usesResult, NodeIndex callTargetNodeIndex, int resultOperand, const CallLinkStatus&, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, CodeSpecializationKind); 165 165 // Handle setting the result of an intrinsic. 166 166 void setIntrinsicResult(bool usesResult, int resultOperand, NodeIndex); … … 1330 1330 } 1331 1331 1332 JSFunction* expectedFunction = callLinkStatus.function();1333 if (!expectedFunction) {1334 // For now we have no way of reasoning about what it means to not have a specific function. This will1335 // change soon, though.1336 1337 addCall(interpreter, currentInstruction, op);1338 return;1339 }1340 1341 1332 Intrinsic intrinsic = callLinkStatus.intrinsicFor(kind); 1342 1333 if (intrinsic != NoIntrinsic) { 1343 if (!callLinkStatus.isProved()) 1344 emitFunctionCheck(expectedFunction, callTarget, registerOffset, kind); 1334 emitFunctionChecks(callLinkStatus, callTarget, registerOffset, kind); 1345 1335 1346 1336 if (handleIntrinsic(usesResult, resultOperand, intrinsic, registerOffset, argumentCountIncludingThis, prediction)) { … … 1351 1341 addToGraph(Phantom, callTarget); 1352 1342 } 1353 1343 1354 1344 return; 1355 1345 } 1356 } else if (handleInlining(usesResult, callTarget, resultOperand, callLinkStatus .isProved(), expectedFunction, registerOffset, argumentCountIncludingThis, nextOffset, kind))1346 } else if (handleInlining(usesResult, callTarget, resultOperand, callLinkStatus, registerOffset, argumentCountIncludingThis, nextOffset, kind)) 1357 1347 return; 1358 1348 … … 1360 1350 } 1361 1351 1362 void ByteCodeParser::emitFunctionCheck (JSFunction* expectedFunction, NodeIndex callTarget, int registerOffset, CodeSpecializationKind kind)1352 void ByteCodeParser::emitFunctionChecks(const CallLinkStatus& callLinkStatus, NodeIndex callTarget, int registerOffset, CodeSpecializationKind kind) 1363 1353 { 1354 if (callLinkStatus.isProved()) 1355 return; 1356 1357 ASSERT(callLinkStatus.canOptimize()); 1358 1364 1359 NodeIndex thisArgument; 1365 1360 if (kind == CodeForCall) … … 1367 1362 else 1368 1363 thisArgument = NoNode; 1369 addToGraph(CheckFunction, OpInfo(expectedFunction), callTarget, thisArgument); 1364 1365 if (JSFunction* function = callLinkStatus.function()) 1366 addToGraph(CheckFunction, OpInfo(function), callTarget, thisArgument); 1367 else { 1368 ASSERT(callLinkStatus.structure()); 1369 ASSERT(callLinkStatus.executable()); 1370 1371 addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(callLinkStatus.structure())), callTarget); 1372 addToGraph(CheckExecutable, OpInfo(callLinkStatus.executable()), callTarget, thisArgument); 1373 } 1370 1374 } 1371 1375 1372 bool ByteCodeParser::handleInlining(bool usesResult, NodeIndex callTargetNodeIndex, int resultOperand, bool certainAboutExpectedFunction, JSFunction* expectedFunction, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, CodeSpecializationKind kind)1376 bool ByteCodeParser::handleInlining(bool usesResult, NodeIndex callTargetNodeIndex, int resultOperand, const CallLinkStatus& callLinkStatus, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, CodeSpecializationKind kind) 1373 1377 { 1374 1378 // First, the really simple checks: do we have an actual JS function? 1375 if (! expectedFunction)1379 if (!callLinkStatus.executable()) 1376 1380 return false; 1377 if ( expectedFunction->isHostFunction())1381 if (callLinkStatus.executable()->isHostFunction()) 1378 1382 return false; 1379 1383 1380 FunctionExecutable* executable = expectedFunction->jsExecutable();1384 FunctionExecutable* executable = jsCast<FunctionExecutable*>(callLinkStatus.executable()); 1381 1385 1382 1386 // Does the number of arguments we're passing match the arity of the target? We currently … … 1407 1411 if (!codeBlock) 1408 1412 return false; 1409 if (!canInlineFunctionFor(codeBlock, kind ))1413 if (!canInlineFunctionFor(codeBlock, kind, callLinkStatus.isClosureCall())) 1410 1414 return false; 1411 1415 … … 1417 1421 // by checking the callee (if necessary) and making sure that arguments and the callee 1418 1422 // are flushed. 1419 if (!certainAboutExpectedFunction) 1420 emitFunctionCheck(expectedFunction, callTargetNodeIndex, registerOffset, kind); 1423 emitFunctionChecks(callLinkStatus, callTargetNodeIndex, registerOffset, kind); 1421 1424 1422 1425 // FIXME: Don't flush constants! … … 1440 1443 InlineStackEntry inlineStackEntry( 1441 1444 this, codeBlock, codeBlock, m_graph.m_blocks.size() - 1, 1442 expectedFunction, (VirtualRegister)m_inlineStackTop->remapOperand(1445 callLinkStatus.function(), (VirtualRegister)m_inlineStackTop->remapOperand( 1443 1446 usesResult ? resultOperand : InvalidVirtualRegister), 1444 1447 (VirtualRegister)inlineCallFrameStart, argumentCountIncludingThis, kind); … … 1451 1454 1452 1455 addToGraph(InlineStart, OpInfo(argumentPositionStart)); 1456 if (callLinkStatus.isClosureCall()) { 1457 addToGraph(SetCallee, callTargetNodeIndex); 1458 addToGraph(SetMyScope, addToGraph(GetScope, callTargetNodeIndex)); 1459 } 1453 1460 1454 1461 parseCodeBlock(); -
trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
r138669 r138921 90 90 } 91 91 92 enum InlineCallFrameRequirement { RequireSameInlineCallFrame, DoNotCareAboutInlineCallFrame }; 93 template<InlineCallFrameRequirement inlineCallFrameRequirement> 94 NodeIndex genericPureCSE(Node& node) 92 NodeIndex pureCSE(Node& node) 95 93 { 96 94 NodeIndex child1 = canonicalize(node.child1()); … … 111 109 112 110 if (node.arithNodeFlags() != otherNode.arithNodeFlags()) 113 continue;114 115 if (inlineCallFrameRequirement == RequireSameInlineCallFrame116 && node.codeOrigin.inlineCallFrame != otherNode.codeOrigin.inlineCallFrame)117 111 continue; 118 112 … … 140 134 } 141 135 142 NodeIndex pureCSE(Node& node)143 {144 return genericPureCSE<DoNotCareAboutInlineCallFrame>(node);145 }146 147 NodeIndex pureCSERequiringSameInlineCallFrame(Node& node)148 {149 return genericPureCSE<RequireSameInlineCallFrame>(node);150 }151 152 136 NodeIndex constantCSE(Node& node) 153 137 { … … 178 162 179 163 return index; 164 } 165 return NoNode; 166 } 167 168 NodeIndex getCalleeLoadElimination(InlineCallFrame* inlineCallFrame) 169 { 170 for (unsigned i = m_indexInBlock; i--;) { 171 NodeIndex index = m_currentBlock->at(i); 172 Node& node = m_graph[index]; 173 if (!node.shouldGenerate()) 174 continue; 175 if (node.codeOrigin.inlineCallFrame != inlineCallFrame) 176 continue; 177 switch (node.op()) { 178 case GetCallee: 179 return index; 180 case SetCallee: 181 return node.child1().index(); 182 default: 183 break; 184 } 180 185 } 181 186 return NoNode; … … 413 418 Node& node = m_graph[index]; 414 419 if (node.op() == CheckFunction && node.child1() == child1 && node.function() == function) 420 return true; 421 } 422 return false; 423 } 424 425 bool checkExecutableElimination(ExecutableBase* executable, NodeIndex child1) 426 { 427 for (unsigned i = endIndexForPureCSE(); i--;) { 428 NodeIndex index = m_currentBlock->at(i); 429 if (index == child1) 430 break; 431 432 Node& node = m_graph[index]; 433 if (node.op() == CheckExecutable && node.child1() == child1 && node.executable() == executable) 415 434 return true; 416 435 } … … 831 850 case GetMyScope: 832 851 return index; 852 case SetMyScope: 853 return node.child1().index(); 833 854 default: 834 855 break; … … 1145 1166 case SkipScope: 1146 1167 case GetScopeRegisters: 1168 case GetScope: 1147 1169 setReplacement(pureCSE(node)); 1148 1170 break; 1149 1171 1150 1172 case GetCallee: 1151 setReplacement( pureCSERequiringSameInlineCallFrame(node));1173 setReplacement(getCalleeLoadElimination(node.codeOrigin.inlineCallFrame)); 1152 1174 break; 1153 1175 … … 1352 1374 break; 1353 1375 1376 case CheckExecutable: 1377 if (checkExecutableElimination(node.executable(), node.child1().index())) 1378 eliminate(); 1379 break; 1380 1354 1381 case CheckArray: 1355 1382 if (checkArrayElimination(node.child1().index(), node.arrayMode())) -
trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp
r137094 r138921 54 54 { 55 55 return codeBlock->instructionCount() <= Options::maximumFunctionForCallInlineCandidateInstructionCount() 56 && !codeBlock->ownerExecutable()->needsActivation(); 57 } 58 bool mightInlineFunctionForClosureCall(CodeBlock* codeBlock) 59 { 60 return codeBlock->instructionCount() <= Options::maximumFunctionForClosureCallInlineCandidateInstructionCount() 56 61 && !codeBlock->ownerExecutable()->needsActivation(); 57 62 } -
trunk/Source/JavaScriptCore/dfg/DFGCapabilities.h
r138074 r138921 45 45 bool mightCompileFunctionForConstruct(CodeBlock*); 46 46 bool mightInlineFunctionForCall(CodeBlock*); 47 bool mightInlineFunctionForClosureCall(CodeBlock*); 47 48 bool mightInlineFunctionForConstruct(CodeBlock*); 48 49 … … 273 274 inline bool mightCompileFunctionForConstruct(CodeBlock*) { return false; } 274 275 inline bool mightInlineFunctionForCall(CodeBlock*) { return false; } 276 inline bool mightInlineFunctionForClosureCall(CodeBlock*) { return false; } 275 277 inline bool mightInlineFunctionForConstruct(CodeBlock*) { return false; } 276 278 … … 318 320 } 319 321 322 inline bool canInlineFunctionForClosureCall(CodeBlock* codeBlock) 323 { 324 return mightInlineFunctionForClosureCall(codeBlock) && canInlineOpcodes(codeBlock); 325 } 326 320 327 inline bool canInlineFunctionForConstruct(CodeBlock* codeBlock) 321 328 { … … 331 338 } 332 339 333 inline bool canInlineFunctionFor(CodeBlock* codeBlock, CodeSpecializationKind kind) 334 { 340 inline bool canInlineFunctionFor(CodeBlock* codeBlock, CodeSpecializationKind kind, bool isClosureCall) 341 { 342 if (isClosureCall) { 343 ASSERT(kind == CodeForCall); 344 return canInlineFunctionForClosureCall(codeBlock); 345 } 335 346 if (kind == CodeForCall) 336 347 return canInlineFunctionForCall(codeBlock); -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r136601 r138921 703 703 return result; 704 704 } 705 706 bool hasExecutable() 707 { 708 return op() == CheckExecutable; 709 } 710 711 ExecutableBase* executable() 712 { 713 return jsCast<ExecutableBase*>(reinterpret_cast<JSCell*>(m_opInfo)); 714 } 705 715 706 716 bool hasStructureTransitionData() -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r137699 r138921 53 53 macro(CreateThis, NodeResultJS) /* Note this is not MustGenerate since we're returning it anyway. */ \ 54 54 macro(GetCallee, NodeResultJS) \ 55 macro(SetCallee, NodeMustGenerate) \ 55 56 \ 56 57 /* Nodes for local variable access. These nodes are linked together using Phi nodes. */\ … … 125 126 macro(PutByIdDirect, NodeMustGenerate | NodeClobbersWorld) \ 126 127 macro(CheckStructure, NodeMustGenerate) \ 128 macro(CheckExecutable, NodeMustGenerate) \ 127 129 macro(ForwardCheckStructure, NodeMustGenerate) \ 128 130 /* Transition watchpoints are a contract between the party setting the watchpoint */\ … … 151 153 macro(PutByOffset, NodeMustGenerate) \ 152 154 macro(GetArrayLength, NodeResultInt32) \ 155 macro(GetScope, NodeResultJS) \ 153 156 macro(GetMyScope, NodeResultJS) \ 157 macro(SetMyScope, NodeMustGenerate) \ 154 158 macro(SkipTopScope, NodeResultJS) \ 155 159 macro(SkipScope, NodeResultJS) \ -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r137980 r138921 768 768 break; 769 769 770 case SetCallee: 771 case SetMyScope: 772 changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue); 773 break; 774 775 case GetScope: 776 changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue); 777 changed |= setPrediction(SpecCellOther); 778 break; 779 770 780 #ifndef NDEBUG 771 781 // These get ignored because they don't return anything. … … 778 788 case SetArgument: 779 789 case CheckStructure: 790 case CheckExecutable: 780 791 case ForwardCheckStructure: 781 792 case StructureTransitionWatchpoint: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r138871 r138921 3970 3970 } 3971 3971 3972 case SetCallee: { 3973 SpeculateCellOperand callee(this, node.child1()); 3974 m_jit.storePtr(callee.gpr(), JITCompiler::payloadFor(static_cast<VirtualRegister>(node.codeOrigin.stackOffset() + static_cast<int>(JSStack::Callee)))); 3975 noResult(m_compileIndex); 3976 break; 3977 } 3978 3979 case GetScope: { 3980 SpeculateCellOperand function(this, node.child1()); 3981 GPRTemporary result(this, function); 3982 m_jit.loadPtr(JITCompiler::Address(function.gpr(), JSFunction::offsetOfScopeChain()), result.gpr()); 3983 cellResult(result.gpr(), m_compileIndex); 3984 break; 3985 } 3986 3972 3987 case GetMyScope: { 3973 3988 GPRTemporary result(this); … … 3976 3991 m_jit.loadPtr(JITCompiler::payloadFor(static_cast<VirtualRegister>(node.codeOrigin.stackOffset() + static_cast<int>(JSStack::ScopeChain))), resultGPR); 3977 3992 cellResult(resultGPR, m_compileIndex); 3993 break; 3994 } 3995 3996 case SetMyScope: { 3997 SpeculateCellOperand callee(this, node.child1()); 3998 m_jit.storePtr(callee.gpr(), JITCompiler::payloadFor(static_cast<VirtualRegister>(node.codeOrigin.stackOffset() + static_cast<int>(JSStack::ScopeChain)))); 3999 noResult(m_compileIndex); 3978 4000 break; 3979 4001 } … … 4143 4165 } 4144 4166 4167 case CheckExecutable: { 4168 SpeculateCellOperand function(this, node.child1()); 4169 speculationCheck(BadExecutable, JSValueSource::unboxedCell(function.gpr()), node.child1(), m_jit.branchWeakPtr(JITCompiler::NotEqual, JITCompiler::Address(function.gpr(), JSFunction::offsetOfExecutable()), node.executable())); 4170 noResult(m_compileIndex); 4171 break; 4172 } 4173 4145 4174 case CheckStructure: 4146 4175 case ForwardCheckStructure: { -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r138871 r138921 3922 3922 } 3923 3923 3924 case SetCallee: { 3925 SpeculateCellOperand callee(this, node.child1()); 3926 m_jit.storePtr(callee.gpr(), JITCompiler::addressFor(static_cast<VirtualRegister>(node.codeOrigin.stackOffset() + static_cast<int>(JSStack::Callee)))); 3927 noResult(m_compileIndex); 3928 break; 3929 } 3930 3931 case GetScope: { 3932 SpeculateCellOperand function(this, node.child1()); 3933 GPRTemporary result(this, function); 3934 m_jit.loadPtr(JITCompiler::Address(function.gpr(), JSFunction::offsetOfScopeChain()), result.gpr()); 3935 cellResult(result.gpr(), m_compileIndex); 3936 break; 3937 } 3938 3924 3939 case GetMyScope: { 3925 3940 GPRTemporary result(this); … … 3928 3943 m_jit.loadPtr(JITCompiler::addressFor(static_cast<VirtualRegister>(node.codeOrigin.stackOffset() + static_cast<int>(JSStack::ScopeChain))), resultGPR); 3929 3944 cellResult(resultGPR, m_compileIndex); 3945 break; 3946 } 3947 3948 case SetMyScope: { 3949 SpeculateCellOperand callee(this, node.child1()); 3950 m_jit.storePtr(callee.gpr(), JITCompiler::addressFor(static_cast<VirtualRegister>(node.codeOrigin.stackOffset() + static_cast<int>(JSStack::ScopeChain)))); 3951 noResult(m_compileIndex); 3930 3952 break; 3931 3953 } … … 4081 4103 break; 4082 4104 } 4105 4106 case CheckExecutable: { 4107 SpeculateCellOperand function(this, node.child1()); 4108 speculationCheck(BadExecutable, JSValueRegs(function.gpr()), node.child1(), m_jit.branchWeakPtr(JITCompiler::NotEqual, JITCompiler::Address(function.gpr(), JSFunction::offsetOfExecutable()), node.executable())); 4109 noResult(m_compileIndex); 4110 break; 4111 } 4112 4083 4113 case CheckStructure: 4084 4114 case ForwardCheckStructure: { -
trunk/Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp
r135469 r138921 283 283 ValueRecovery::displacedInJSStack(static_cast<VirtualRegister>(info->u.virtualReg), info->format); 284 284 } 285 286 // Step 5: Make sure that for locals that coincide with true call frame headers, the exit compiler knows 287 // that those values don't have to be recovered. Signal this by using ValueRecovery::alreadyInJSStack() 288 for (InlineCallFrame* inlineCallFrame = codeOrigin.inlineCallFrame; inlineCallFrame; inlineCallFrame = inlineCallFrame->caller.inlineCallFrame) { 289 for (unsigned i = JSStack::CallFrameHeaderSize; i--;) 290 valueRecoveries.setLocal(inlineCallFrame->stackOffset - i - 1, ValueRecovery::alreadyInJSStack()); 291 } 285 292 } 286 293 -
trunk/Source/JavaScriptCore/runtime/Options.h
r138074 r138921 81 81 \ 82 82 v(unsigned, maximumFunctionForCallInlineCandidateInstructionCount, 180) \ 83 v(unsigned, maximumFunctionForClosureCallInlineCandidateInstructionCount, 100) \ 83 84 v(unsigned, maximumFunctionForConstructInlineCandidateInstructionCount, 100) \ 84 85 \
Note: See TracChangeset
for help on using the changeset viewer.