Changeset 197159 in webkit
- Timestamp:
- Feb 25, 2016, 9:59:48 PM (9 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r197155 r197159 1 2016-02-25 Benjamin Poulain <bpoulain@apple.com> 2 3 [JSC] Be aggressive with OSR Entry to FTL if the DFG function was only used for OSR Entry itself 4 https://bugs.webkit.org/show_bug.cgi?id=154575 5 6 Reviewed by Filip Pizlo. 7 8 I noticed that imaging-gaussian-blur spends most of its 9 samples in DFG code despite executing most of the loop 10 iterations in FTL. 11 12 On this particular test, the main function is only entered 13 once and have a very heavy loop there. What happens is DFG 14 starts by compiling the full function in FTL. That takes about 15 8 to 10 milliseconds during which the DFG code makes very little 16 progress. The calls to triggerOSREntryNow() try to OSR Enter 17 for a while then finally start compiling something. By the time 18 the function is ready, we have wasted a lot of time in DFG code. 19 20 What this patch does is set a flag when a DFG function is entered. 21 If we try to triggerOSREntryNow() and the flag was never set, 22 we start compiling both the full function and the one for OSR Entry. 23 24 * dfg/DFGJITCode.h: 25 * dfg/DFGJITCompiler.cpp: 26 (JSC::DFG::JITCompiler::compileEntryExecutionFlag): 27 (JSC::DFG::JITCompiler::compile): 28 (JSC::DFG::JITCompiler::compileFunction): 29 * dfg/DFGJITCompiler.h: 30 * dfg/DFGOperations.cpp: 31 * dfg/DFGPlan.cpp: 32 (JSC::DFG::Plan::Plan): Deleted. 33 * dfg/DFGPlan.h: 34 * dfg/DFGTierUpCheckInjectionPhase.cpp: 35 (JSC::DFG::TierUpCheckInjectionPhase::run): 36 1 37 2016-02-25 Benjamin Poulain <benjamin@webkit.org> 2 38 -
trunk/Source/JavaScriptCore/dfg/DFGJITCode.h
r195865 r197159 140 140 #if ENABLE(FTL_JIT) 141 141 uint8_t nestedTriggerIsSet { 0 }; 142 uint8_t neverExecutedEntry { 1 }; 142 143 UpperTierExecutionCounter tierUpCounter; 143 144 WriteBarrier<CodeBlock> m_osrEntryBlock; -
trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
r195865 r197159 112 112 } 113 113 114 void JITCompiler::compileEntryExecutionFlag() 115 { 116 #if ENABLE(FTL_JIT) 117 if (m_graph.m_plan.canTierUpAndOSREnter) 118 store8(TrustedImm32(0), &m_jitCode->neverExecutedEntry); 119 #endif // ENABLE(FTL_JIT) 120 } 121 114 122 void JITCompiler::compileBody() 115 123 { … … 327 335 checkStackPointerAlignment(); 328 336 compileSetupRegistersForEntry(); 337 compileEntryExecutionFlag(); 329 338 compileBody(); 330 339 setEndOfMainPath(); … … 393 402 394 403 compileSetupRegistersForEntry(); 404 compileEntryExecutionFlag(); 395 405 396 406 // === Function body code generation === -
trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h
r195865 r197159 265 265 void compileEntry(); 266 266 void compileSetupRegistersForEntry(); 267 void compileEntryExecutionFlag(); 267 268 void compileBody(); 268 269 void link(LinkBuffer&); -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r196868 r197159 1433 1433 1434 1434 #if ENABLE(FTL_JIT) 1435 static void triggerFTLReplacementCompile(VM* vm,CodeBlock* codeBlock, JITCode* jitCode)1435 static bool shouldTriggerFTLCompile(CodeBlock* codeBlock, JITCode* jitCode) 1436 1436 { 1437 1437 if (codeBlock->baselineVersion()->m_didFailFTLCompilation) { … … 1439 1439 dataLog("Deferring FTL-optimization of ", *codeBlock, " indefinitely because there was an FTL failure.\n"); 1440 1440 jitCode->dontOptimizeAnytimeSoon(codeBlock); 1441 return; 1442 } 1443 1444 if (!jitCode->checkIfOptimizationThresholdReached(codeBlock)) { 1441 return false; 1442 } 1443 1444 if (!codeBlock->hasOptimizedReplacement() 1445 && !jitCode->checkIfOptimizationThresholdReached(codeBlock)) { 1445 1446 if (Options::verboseOSR()) 1446 1447 dataLog("Choosing not to FTL-optimize ", *codeBlock, " yet.\n"); 1447 return; 1448 } 1449 1448 return false; 1449 } 1450 return true; 1451 } 1452 1453 static void triggerFTLReplacementCompile(VM* vm, CodeBlock* codeBlock, JITCode* jitCode) 1454 { 1450 1455 Worklist::State worklistState; 1451 1456 if (Worklist* worklist = existingGlobalFTLWorklistOrNull()) { … … 1480 1485 *vm, codeBlock->newReplacement(), codeBlock, FTLMode, UINT_MAX, 1481 1486 Operands<JSValue>(), ToFTLDeferredCompilationCallback::create()); 1487 1488 // If we reached here, the counter has not be reset. Do that now. 1489 jitCode->setOptimizationThresholdBasedOnCompilationResult( 1490 codeBlock, CompilationDeferred); 1482 1491 } 1483 1492 … … 1504 1513 jitCode->nestedTriggerIsSet = 1; 1505 1514 1506 triggerFTLReplacementCompile(vm, codeBlock, jitCode); 1515 if (shouldTriggerFTLCompile(codeBlock, jitCode)) 1516 triggerFTLReplacementCompile(vm, codeBlock, jitCode); 1507 1517 } 1508 1518 … … 1542 1552 // - If we do have an FTL code block, then try to enter for a while. 1543 1553 // - If we couldn't enter for a while, then trigger OSR entry. 1544 1545 triggerFTLReplacementCompile(vm, codeBlock, jitCode);1546 1547 if (!codeBlock->hasOptimizedReplacement()) 1548 return 0;1549 1550 if (jitCode->osrEntryRetry < Options::ftlOSREntryRetryThreshold()) { 1551 jitCode->osrEntryRetry++;1552 return 0;1554 1555 if (!shouldTriggerFTLCompile(codeBlock, jitCode)) 1556 return nullptr; 1557 1558 if (!jitCode->neverExecutedEntry) { 1559 triggerFTLReplacementCompile(vm, codeBlock, jitCode); 1560 1561 if (!codeBlock->hasOptimizedReplacement()) 1562 return nullptr; 1553 1563 } 1554 1564 … … 1561 1571 worklistState = Worklist::NotKnown; 1562 1572 1563 if (worklistState == Worklist::Compiling) 1564 return 0; 1573 if (worklistState == Worklist::Compiling) { 1574 jitCode->setOptimizationThresholdBasedOnCompilationResult( 1575 codeBlock, CompilationDeferred); 1576 return nullptr; 1577 } 1565 1578 1566 1579 if (CodeBlock* entryBlock = jitCode->osrEntryBlock()) { … … 1569 1582 if (address) 1570 1583 return static_cast<char*>(address); 1571 1584 1585 if (jitCode->osrEntryRetry < Options::ftlOSREntryRetryThreshold()) { 1586 jitCode->osrEntryRetry++; 1587 return nullptr; 1588 } 1589 1572 1590 FTL::ForOSREntryJITCode* entryCode = entryBlock->jitCode()->ftlForOSREntry(); 1573 1591 entryCode->countEntryFailure(); 1574 1592 if (entryCode->entryFailureCount() < 1575 Options::ftlOSREntryFailureCountForReoptimization()) 1576 return 0; 1593 Options::ftlOSREntryFailureCountForReoptimization()) { 1594 jitCode->optimizeSoon(codeBlock); 1595 return nullptr; 1596 } 1577 1597 1578 1598 // OSR entry failed. Oh no! This implies that we need to retry. We retry … … 1580 1600 jitCode->clearOSREntryBlock(); 1581 1601 jitCode->osrEntryRetry = 0; 1582 return 0;1602 return nullptr; 1583 1603 } 1584 1604 … … 1587 1607 if (Options::verboseOSR()) 1588 1608 dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n"); 1589 return 0;1609 return nullptr; 1590 1610 } 1591 1611 … … 1599 1619 *vm, replacementCodeBlock, codeBlock, FTLForOSREntryMode, bytecodeIndex, 1600 1620 mustHandleValues, ToFTLForOSREntryDeferredCompilationCallback::create()); 1601 1602 if (forEntryResult != CompilationSuccessful) 1603 return 0; 1621 1622 if (jitCode->neverExecutedEntry) 1623 triggerFTLReplacementCompile(vm, codeBlock, jitCode); 1624 1625 if (forEntryResult != CompilationSuccessful) { 1626 jitCode->setOptimizationThresholdBasedOnCompilationResult( 1627 codeBlock, CompilationDeferred); 1628 return nullptr; 1629 } 1604 1630 1605 1631 // It's possible that the for-entry compile already succeeded. In that case OSR … … 1610 1636 return static_cast<char*>(address); 1611 1637 } 1638 1612 1639 #endif // ENABLE(FTL_JIT) 1613 1640 -
trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp
r196756 r197159 145 145 , identifiers(codeBlock) 146 146 , weakReferences(codeBlock) 147 , willTryToTierUp(false)148 147 , stage(Preparing) 149 148 { -
trunk/Source/JavaScriptCore/dfg/DFGPlan.h
r190827 r197159 99 99 DesiredTransitions transitions; 100 100 101 bool willTryToTierUp; 101 bool willTryToTierUp { false }; 102 bool canTierUpAndOSREnter { false }; 102 103 103 104 enum Stage { Preparing, Compiling, Compiled, Ready, Cancelled }; -
trunk/Source/JavaScriptCore/dfg/DFGTierUpCheckInjectionPhase.cpp
r195622 r197159 72 72 73 73 HashSet<const NaturalLoop*> loopsContainingLoopHintWithoutOSREnter = findLoopsContainingLoopHintWithoutOSREnter(naturalLoops, level); 74 75 bool canTierUpAndOSREnter = false; 74 76 75 77 InsertionSet insertionSet(m_graph); … … 86 88 NodeOrigin origin = node->origin; 87 89 if (canOSREnterAtLoopHint(level, block, nodeIndex)) { 90 canTierUpAndOSREnter = true; 88 91 const NaturalLoop* loop = naturalLoops.innerMostLoopOf(block); 89 92 if (loop && loopsContainingLoopHintWithoutOSREnter.contains(loop)) … … 104 107 insertionSet.execute(block); 105 108 } 106 109 110 m_graph.m_plan.canTierUpAndOSREnter = canTierUpAndOSREnter; 107 111 m_graph.m_plan.willTryToTierUp = true; 108 112 return true;
Note:
See TracChangeset
for help on using the changeset viewer.