Changeset 197159 in webkit


Ignore:
Timestamp:
Feb 25, 2016, 9:59:48 PM (9 years ago)
Author:
commit-queue@webkit.org
Message:

[JSC] Be aggressive with OSR Entry to FTL if the DFG function was only used for OSR Entry itself
https://bugs.webkit.org/show_bug.cgi?id=154575

Patch by Benjamin Poulain <bpoulain@apple.com> on 2016-02-25
Reviewed by Filip Pizlo.

I noticed that imaging-gaussian-blur spends most of its
samples in DFG code despite executing most of the loop
iterations in FTL.

On this particular test, the main function is only entered
once and have a very heavy loop there. What happens is DFG
starts by compiling the full function in FTL. That takes about
8 to 10 milliseconds during which the DFG code makes very little
progress. The calls to triggerOSREntryNow() try to OSR Enter
for a while then finally start compiling something. By the time
the function is ready, we have wasted a lot of time in DFG code.

What this patch does is set a flag when a DFG function is entered.
If we try to triggerOSREntryNow() and the flag was never set,
we start compiling both the full function and the one for OSR Entry.

  • dfg/DFGJITCode.h:
  • dfg/DFGJITCompiler.cpp:

(JSC::DFG::JITCompiler::compileEntryExecutionFlag):
(JSC::DFG::JITCompiler::compile):
(JSC::DFG::JITCompiler::compileFunction):

  • dfg/DFGJITCompiler.h:
  • dfg/DFGOperations.cpp:
  • dfg/DFGPlan.cpp:

(JSC::DFG::Plan::Plan): Deleted.

  • dfg/DFGPlan.h:
  • dfg/DFGTierUpCheckInjectionPhase.cpp:

(JSC::DFG::TierUpCheckInjectionPhase::run):

Location:
trunk/Source/JavaScriptCore
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r197155 r197159  
     12016-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
    1372016-02-25  Benjamin Poulain  <benjamin@webkit.org>
    238
  • trunk/Source/JavaScriptCore/dfg/DFGJITCode.h

    r195865 r197159  
    140140#if ENABLE(FTL_JIT)
    141141    uint8_t nestedTriggerIsSet { 0 };
     142    uint8_t neverExecutedEntry { 1 };
    142143    UpperTierExecutionCounter tierUpCounter;
    143144    WriteBarrier<CodeBlock> m_osrEntryBlock;
  • trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp

    r195865 r197159  
    112112}
    113113
     114void 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
    114122void JITCompiler::compileBody()
    115123{
     
    327335    checkStackPointerAlignment();
    328336    compileSetupRegistersForEntry();
     337    compileEntryExecutionFlag();
    329338    compileBody();
    330339    setEndOfMainPath();
     
    393402
    394403    compileSetupRegistersForEntry();
     404    compileEntryExecutionFlag();
    395405
    396406    // === Function body code generation ===
  • trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h

    r195865 r197159  
    265265    void compileEntry();
    266266    void compileSetupRegistersForEntry();
     267    void compileEntryExecutionFlag();
    267268    void compileBody();
    268269    void link(LinkBuffer&);
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r196868 r197159  
    14331433
    14341434#if ENABLE(FTL_JIT)
    1435 static void triggerFTLReplacementCompile(VM* vm, CodeBlock* codeBlock, JITCode* jitCode)
     1435static bool shouldTriggerFTLCompile(CodeBlock* codeBlock, JITCode* jitCode)
    14361436{
    14371437    if (codeBlock->baselineVersion()->m_didFailFTLCompilation) {
     
    14391439            dataLog("Deferring FTL-optimization of ", *codeBlock, " indefinitely because there was an FTL failure.\n");
    14401440        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)) {
    14451446        if (Options::verboseOSR())
    14461447            dataLog("Choosing not to FTL-optimize ", *codeBlock, " yet.\n");
    1447         return;
    1448     }
    1449    
     1448        return false;
     1449    }
     1450    return true;
     1451}
     1452
     1453static void triggerFTLReplacementCompile(VM* vm, CodeBlock* codeBlock, JITCode* jitCode)
     1454{
    14501455    Worklist::State worklistState;
    14511456    if (Worklist* worklist = existingGlobalFTLWorklistOrNull()) {
     
    14801485        *vm, codeBlock->newReplacement(), codeBlock, FTLMode, UINT_MAX,
    14811486        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);
    14821491}
    14831492
     
    15041513        jitCode->nestedTriggerIsSet = 1;
    15051514
    1506     triggerFTLReplacementCompile(vm, codeBlock, jitCode);
     1515    if (shouldTriggerFTLCompile(codeBlock, jitCode))
     1516        triggerFTLReplacementCompile(vm, codeBlock, jitCode);
    15071517}
    15081518
     
    15421552    // - If we do have an FTL code block, then try to enter for a while.
    15431553    // - 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;
    15531563    }
    15541564   
     
    15611571        worklistState = Worklist::NotKnown;
    15621572   
    1563     if (worklistState == Worklist::Compiling)
    1564         return 0;
     1573    if (worklistState == Worklist::Compiling) {
     1574        jitCode->setOptimizationThresholdBasedOnCompilationResult(
     1575            codeBlock, CompilationDeferred);
     1576        return nullptr;
     1577    }
    15651578   
    15661579    if (CodeBlock* entryBlock = jitCode->osrEntryBlock()) {
     
    15691582        if (address)
    15701583            return static_cast<char*>(address);
    1571        
     1584
     1585        if (jitCode->osrEntryRetry < Options::ftlOSREntryRetryThreshold()) {
     1586            jitCode->osrEntryRetry++;
     1587            return nullptr;
     1588        }
     1589
    15721590        FTL::ForOSREntryJITCode* entryCode = entryBlock->jitCode()->ftlForOSREntry();
    15731591        entryCode->countEntryFailure();
    15741592        if (entryCode->entryFailureCount() <
    1575             Options::ftlOSREntryFailureCountForReoptimization())
    1576             return 0;
     1593            Options::ftlOSREntryFailureCountForReoptimization()) {
     1594            jitCode->optimizeSoon(codeBlock);
     1595            return nullptr;
     1596        }
    15771597       
    15781598        // OSR entry failed. Oh no! This implies that we need to retry. We retry
     
    15801600        jitCode->clearOSREntryBlock();
    15811601        jitCode->osrEntryRetry = 0;
    1582         return 0;
     1602        return nullptr;
    15831603    }
    15841604   
     
    15871607        if (Options::verboseOSR())
    15881608            dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
    1589         return 0;
     1609        return nullptr;
    15901610    }
    15911611
     
    15991619        *vm, replacementCodeBlock, codeBlock, FTLForOSREntryMode, bytecodeIndex,
    16001620        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    }
    16041630
    16051631    // It's possible that the for-entry compile already succeeded. In that case OSR
     
    16101636    return static_cast<char*>(address);
    16111637}
     1638
    16121639#endif // ENABLE(FTL_JIT)
    16131640
  • trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp

    r196756 r197159  
    145145    , identifiers(codeBlock)
    146146    , weakReferences(codeBlock)
    147     , willTryToTierUp(false)
    148147    , stage(Preparing)
    149148{
  • trunk/Source/JavaScriptCore/dfg/DFGPlan.h

    r190827 r197159  
    9999    DesiredTransitions transitions;
    100100   
    101     bool willTryToTierUp;
     101    bool willTryToTierUp { false };
     102    bool canTierUpAndOSREnter { false };
    102103
    103104    enum Stage { Preparing, Compiling, Compiled, Ready, Cancelled };
  • trunk/Source/JavaScriptCore/dfg/DFGTierUpCheckInjectionPhase.cpp

    r195622 r197159  
    7272
    7373        HashSet<const NaturalLoop*> loopsContainingLoopHintWithoutOSREnter = findLoopsContainingLoopHintWithoutOSREnter(naturalLoops, level);
     74
     75        bool canTierUpAndOSREnter = false;
    7476       
    7577        InsertionSet insertionSet(m_graph);
     
    8688                NodeOrigin origin = node->origin;
    8789                if (canOSREnterAtLoopHint(level, block, nodeIndex)) {
     90                    canTierUpAndOSREnter = true;
    8891                    const NaturalLoop* loop = naturalLoops.innerMostLoopOf(block);
    8992                    if (loop && loopsContainingLoopHintWithoutOSREnter.contains(loop))
     
    104107            insertionSet.execute(block);
    105108        }
    106        
     109
     110        m_graph.m_plan.canTierUpAndOSREnter = canTierUpAndOSREnter;
    107111        m_graph.m_plan.willTryToTierUp = true;
    108112        return true;
Note: See TracChangeset for help on using the changeset viewer.