⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 210971 in webkit


Ignore:
Timestamp:
Jan 20, 2017, 10:10:55 AM (10 years ago)
Author:
sbarati@apple.com
Message:

We should flash a safepoint before each DFG/FTL phase
https://bugs.webkit.org/show_bug.cgi?id=167234

Reviewed by Filip Pizlo.

The recent GC changes caused us to regress Kraken because of a
longstanding issue that happened to be hit with higher frequency because
of a change in timing between when a particular GC was happening and
when a particular FTL compilation was happening. The regression is caused
by the GC was waiting for a large function to make it through the DFG portion
of an FTL compilation. This was taking 20ms-30ms and started happened during a
particular test with much higher frequency.

This means that anytime the GC waits for this compilation, the test ran at least
~20ms slower because the GC waits for the compiler threads the mutator is stopped.

It's good that we have such an easily reproducible case of this performance
issue because it will effect many real JS programs, especially ones with
large functions that get hot.

The most straight forward solution to fix this is to flash a safepoint before
each phase, allowing the GC to suspend the compiler if needed. In my testing,
this progresses Kraken in the browser, and doesn't regress anything else. This
solution also makes the most sense. I did some analysis on the compilation time
of this function that took ~20-30ms to pass through the DFG phases, and
the phase times were mostly evenly distributed. Some took longer than others,
but no phase was longer than 3ms. Most were in the 0.25ms to 1.5ms range.

  • dfg/DFGPlan.cpp:

(JSC::DFG::Plan::compileInThreadImpl):

  • dfg/DFGSafepoint.cpp:

(JSC::DFG::Safepoint::begin):

  • runtime/Options.h:
Location:
trunk/Source/JavaScriptCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r210958 r210971  
     12017-01-20  Saam Barati  <sbarati@apple.com>
     2
     3        We should flash a safepoint before each DFG/FTL phase
     4        https://bugs.webkit.org/show_bug.cgi?id=167234
     5
     6        Reviewed by Filip Pizlo.
     7
     8        The recent GC changes caused us to regress Kraken because of a
     9        longstanding issue that happened to be hit with higher frequency because
     10        of a change in timing between when a particular GC was happening and
     11        when a particular FTL compilation was happening. The regression is caused
     12        by the GC was waiting for a large function to make it through the DFG portion
     13        of an FTL compilation. This was taking 20ms-30ms and started happened during a
     14        particular test with much higher frequency.
     15       
     16        This means that anytime the GC waits for this compilation, the test ran at least
     17        ~20ms slower because the GC waits for the compiler threads the mutator is stopped.
     18       
     19        It's good that we have such an easily reproducible case of this performance
     20        issue because it will effect many real JS programs, especially ones with
     21        large functions that get hot.
     22       
     23        The most straight forward solution to fix this is to flash a safepoint before
     24        each phase, allowing the GC to suspend the compiler if needed. In my testing,
     25        this progresses Kraken in the browser, and doesn't regress anything else. This
     26        solution also makes the most sense. I did some analysis on the compilation time
     27        of this function that took ~20-30ms to pass through the DFG phases, and
     28        the phase times were mostly evenly distributed. Some took longer than others,
     29        but no phase was longer than 3ms. Most were in the 0.25ms to 1.5ms range.
     30
     31        * dfg/DFGPlan.cpp:
     32        (JSC::DFG::Plan::compileInThreadImpl):
     33        * dfg/DFGSafepoint.cpp:
     34        (JSC::DFG::Safepoint::begin):
     35        * runtime/Options.h:
     36
    1372017-01-20  Skachkov Oleksandr  <gskachkov@gmail.com>
    238
  • trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp

    r210521 r210971  
    255255
    256256    codeBlock->setCalleeSaveRegisters(RegisterSet::dfgCalleeSaveRegisters());
     257
     258    bool changed = false;
     259
     260#define RUN_PHASE(phase)                                         \
     261    do {                                                         \
     262        if (Options::safepointBeforeEachPhase()) {               \
     263            Safepoint::Result safepointResult;                   \
     264            {                                                    \
     265                GraphSafepoint safepoint(dfg, safepointResult);  \
     266            }                                                    \
     267            if (safepointResult.didGetCancelled())               \
     268                return CancelPath;                               \
     269        }                                                        \
     270        changed |= phase(dfg);                                   \
     271    } while (false);                                             \
     272
    257273   
    258274    // By this point the DFG bytecode parser will have potentially mutated various tables
     
    270286    }
    271287
    272     performLiveCatchVariablePreservationPhase(dfg);
     288    RUN_PHASE(performLiveCatchVariablePreservationPhase);
    273289
    274290    if (Options::useMaximalFlushInsertionPhase())
    275         performMaximalFlushInsertion(dfg);
    276    
    277     performCPSRethreading(dfg);
    278     performUnification(dfg);
    279     performPredictionInjection(dfg);
    280    
    281     performStaticExecutionCountEstimation(dfg);
     291        RUN_PHASE(performMaximalFlushInsertion);
     292   
     293    RUN_PHASE(performCPSRethreading);
     294    RUN_PHASE(performUnification);
     295    RUN_PHASE(performPredictionInjection);
     296   
     297    RUN_PHASE(performStaticExecutionCountEstimation);
    282298   
    283299    if (mode == FTLForOSREntryMode) {
     
    287303            return FailPath;
    288304        }
    289         performCPSRethreading(dfg);
     305        RUN_PHASE(performCPSRethreading);
    290306    }
    291307   
     
    293309        validate(dfg);
    294310   
    295     performBackwardsPropagation(dfg);
    296     performPredictionPropagation(dfg);
    297     performFixup(dfg);
    298     performStructureRegistration(dfg);
    299     performInvalidationPointInjection(dfg);
    300     performTypeCheckHoisting(dfg);
     311    RUN_PHASE(performBackwardsPropagation);
     312    RUN_PHASE(performPredictionPropagation);
     313    RUN_PHASE(performFixup);
     314    RUN_PHASE(performStructureRegistration);
     315    RUN_PHASE(performInvalidationPointInjection);
     316    RUN_PHASE(performTypeCheckHoisting);
    301317   
    302318    dfg.m_fixpointState = FixpointNotConverged;
     
    310326        validate(dfg);
    311327       
    312     performStrengthReduction(dfg);
    313     performCPSRethreading(dfg);
    314     performCFA(dfg);
    315     performConstantFolding(dfg);
    316     bool changed = false;
    317     changed |= performCFGSimplification(dfg);
    318     changed |= performLocalCSE(dfg);
     328    RUN_PHASE(performStrengthReduction);
     329    RUN_PHASE(performCPSRethreading);
     330    RUN_PHASE(performCFA);
     331    RUN_PHASE(performConstantFolding);
     332    changed = false;
     333    RUN_PHASE(performCFGSimplification);
     334    RUN_PHASE(performLocalCSE);
    319335   
    320336    if (validationEnabled())
    321337        validate(dfg);
    322338   
    323     performCPSRethreading(dfg);
     339    RUN_PHASE(performCPSRethreading);
    324340    if (!isFTL(mode)) {
    325341        // Only run this if we're not FTLing, because currently for a LoadVarargs that is forwardable and
     
    342358        // pathology.
    343359       
    344         changed |= performVarargsForwarding(dfg); // Do this after CFG simplification and CPS rethreading.
     360        RUN_PHASE(performVarargsForwarding); // Do this after CFG simplification and CPS rethreading.
    345361    }
    346362    if (changed) {
    347         performCFA(dfg);
    348         performConstantFolding(dfg);
     363        RUN_PHASE(performCFA);
     364        RUN_PHASE(performConstantFolding);
    349365    }
    350366   
     
    361377        dfg.m_fixpointState = FixpointConverged;
    362378   
    363         performTierUpCheckInjection(dfg);
    364 
    365         performFastStoreBarrierInsertion(dfg);
    366         performStoreBarrierClustering(dfg);
    367         performCleanUp(dfg);
    368         performCPSRethreading(dfg);
    369         performDCE(dfg);
    370         performPhantomInsertion(dfg);
    371         performStackLayout(dfg);
    372         performVirtualRegisterAllocation(dfg);
    373         performWatchpointCollection(dfg);
     379        RUN_PHASE(performTierUpCheckInjection);
     380
     381        RUN_PHASE(performFastStoreBarrierInsertion);
     382        RUN_PHASE(performStoreBarrierClustering);
     383        RUN_PHASE(performCleanUp);
     384        RUN_PHASE(performCPSRethreading);
     385        RUN_PHASE(performDCE);
     386        RUN_PHASE(performPhantomInsertion);
     387        RUN_PHASE(performStackLayout);
     388        RUN_PHASE(performVirtualRegisterAllocation);
     389        RUN_PHASE(performWatchpointCollection);
    374390        dumpAndVerifyGraph(dfg, "Graph after optimization:");
    375391       
     
    391407        }
    392408       
    393         performCleanUp(dfg); // Reduce the graph size a bit.
    394         performCriticalEdgeBreaking(dfg);
     409        RUN_PHASE(performCleanUp); // Reduce the graph size a bit.
     410        RUN_PHASE(performCriticalEdgeBreaking);
    395411        if (Options::createPreHeaders())
    396             performLoopPreHeaderCreation(dfg);
    397         performCPSRethreading(dfg);
    398         performSSAConversion(dfg);
    399         performSSALowering(dfg);
     412            RUN_PHASE(performLoopPreHeaderCreation);
     413        RUN_PHASE(performCPSRethreading);
     414        RUN_PHASE(performSSAConversion);
     415        RUN_PHASE(performSSALowering);
    400416       
    401417        // Ideally, these would be run to fixpoint with the object allocation sinking phase.
    402         performArgumentsElimination(dfg);
     418        RUN_PHASE(performArgumentsElimination);
    403419        if (Options::usePutStackSinking())
    404             performPutStackSinking(dfg);
    405        
    406         performConstantHoisting(dfg);
    407         performGlobalCSE(dfg);
    408         performLivenessAnalysis(dfg);
    409         performCFA(dfg);
    410         performConstantFolding(dfg);
    411         performCleanUp(dfg); // Reduce the graph size a lot.
     420            RUN_PHASE(performPutStackSinking);
     421       
     422        RUN_PHASE(performConstantHoisting);
     423        RUN_PHASE(performGlobalCSE);
     424        RUN_PHASE(performLivenessAnalysis);
     425        RUN_PHASE(performCFA);
     426        RUN_PHASE(performConstantFolding);
     427        RUN_PHASE(performCleanUp); // Reduce the graph size a lot.
    412428        changed = false;
    413         changed |= performStrengthReduction(dfg);
     429        RUN_PHASE(performStrengthReduction);
    414430        if (Options::useObjectAllocationSinking()) {
    415             changed |= performCriticalEdgeBreaking(dfg);
    416             changed |= performObjectAllocationSinking(dfg);
     431            RUN_PHASE(performCriticalEdgeBreaking);
     432            RUN_PHASE(performObjectAllocationSinking);
    417433        }
    418434        if (changed) {
    419435            // State-at-tail and state-at-head will be invalid if we did strength reduction since
    420436            // it might increase live ranges.
    421             performLivenessAnalysis(dfg);
    422             performCFA(dfg);
    423             performConstantFolding(dfg);
     437            RUN_PHASE(performLivenessAnalysis);
     438            RUN_PHASE(performCFA);
     439            RUN_PHASE(performConstantFolding);
    424440        }
    425441       
     
    429445        // Alternatively, we could run loop pre-header creation after SSA conversion - but if we did that
    430446        // then we'd need to do some simple SSA fix-up.
    431         performLivenessAnalysis(dfg);
    432         performCFA(dfg);
    433         performLICM(dfg);
     447        RUN_PHASE(performLivenessAnalysis);
     448        RUN_PHASE(performCFA);
     449        RUN_PHASE(performLICM);
    434450
    435451        // FIXME: Currently: IntegerRangeOptimization *must* be run after LICM.
     
    440456        //
    441457        // Ideally, the dependencies should be explicit. See https://bugs.webkit.org/show_bug.cgi?id=157534.
    442         performLivenessAnalysis(dfg);
    443         performIntegerRangeOptimization(dfg);
    444        
    445         performCleanUp(dfg);
    446         performIntegerCheckCombining(dfg);
    447         performGlobalCSE(dfg);
     458        RUN_PHASE(performLivenessAnalysis);
     459        RUN_PHASE(performIntegerRangeOptimization);
     460       
     461        RUN_PHASE(performCleanUp);
     462        RUN_PHASE(performIntegerCheckCombining);
     463        RUN_PHASE(performGlobalCSE);
    448464       
    449465        // At this point we're not allowed to do any further code motion because our reasoning
     
    451467        dfg.m_fixpointState = FixpointConverged;
    452468       
    453         performLivenessAnalysis(dfg);
    454         performCFA(dfg);
    455         performGlobalStoreBarrierInsertion(dfg);
    456         performStoreBarrierClustering(dfg);
     469        RUN_PHASE(performLivenessAnalysis);
     470        RUN_PHASE(performCFA);
     471        RUN_PHASE(performGlobalStoreBarrierInsertion);
     472        RUN_PHASE(performStoreBarrierClustering);
    457473        if (Options::useMovHintRemoval())
    458             performMovHintRemoval(dfg);
    459         performCleanUp(dfg);
    460         performDCE(dfg); // We rely on this to kill dead code that won't be recognized as dead by B3.
    461         performStackLayout(dfg);
    462         performLivenessAnalysis(dfg);
    463         performOSRAvailabilityAnalysis(dfg);
    464         performWatchpointCollection(dfg);
     474            RUN_PHASE(performMovHintRemoval);
     475        RUN_PHASE(performCleanUp);
     476        RUN_PHASE(performDCE); // We rely on this to kill dead code that won't be recognized as dead by B3.
     477        RUN_PHASE(performStackLayout);
     478        RUN_PHASE(performLivenessAnalysis);
     479        RUN_PHASE(performOSRAvailabilityAnalysis);
     480        RUN_PHASE(performWatchpointCollection);
    465481       
    466482        if (FTL::canCompile(dfg) == FTL::CannotCompile) {
     
    522538        return FailPath;
    523539    }
     540
     541#undef RUN_PHASE
    524542}
    525543
  • trunk/Source/JavaScriptCore/dfg/DFGSafepoint.cpp

    r200933 r210971  
    11/*
    2  * Copyright (C) 2014, 2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2014-2017 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    8181        RELEASE_ASSERT(!data->m_safepoint);
    8282        data->m_safepoint = this;
    83         data->m_rightToRun.unlock();
     83        data->m_rightToRun.unlockFairly();
    8484    }
    8585}
  • trunk/Source/JavaScriptCore/runtime/Options.h

    r210521 r210971  
    159159    v(bool, dumpAirGraphAtEachPhase, false, Normal, "dumps the Air graph at each phase of compilation") \
    160160    v(bool, verboseDFGByteCodeParsing, false, Normal, nullptr) \
     161    v(bool, safepointBeforeEachPhase, true, Normal, nullptr) \
    161162    v(bool, verboseCompilation, false, Normal, nullptr) \
    162163    v(bool, verboseFTLCompilation, false, Normal, nullptr) \
Note: See TracChangeset for help on using the changeset viewer.