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

Changeset 268783 in webkit


Ignore:
Timestamp:
Oct 20, 2020, 9:00:05 PM (6 years ago)
Author:
sbarati@apple.com
Message:

Don't OSR exit to bc#0 for FTL argument type checks during loop OSR entry
https://bugs.webkit.org/show_bug.cgi?id=217925
<rdar://problem/70369407>

Reviewed by Michael Saboff and Tadeu Zagallo.

JSTests:

  • stress/ftl-osr-entry-should-not-exit-to-bc-zero.js: Added.

Source/JavaScriptCore:

When the FTL was emitting type checks for the named arguments of a function,
it was always emitting these type checks with an exit origin of bc#0. It was
doing this even if we were an OSR entry compilation! This meant that type
checks for arguments that failed during loop OSR entry would incorrectly exit
back to bc#0.

This patch fixes this by having the OSR entry runtime code validate the
argument types before OSR entering. The current OSR entry compiled code in
the FTL is designed to only allow exiting after all ExtractOSREntryLocal and
MovHints have executed, so it is simpler to put the type checks in the runtime
instead of the compiled code.

This patch also makes it so we do exponential backoff when failing to OSR
enter. This is needed due to insufficient profiling where we never properly
profile the type of arguments. Before this, we'd OSR exit in the FTL code
itself, which does exponential backoff when recompiling. This patch builds
this same exponential backoff in for when we fail to OSR enter enough times
to give up on the OSR entry compilation.

  • ftl/FTLForOSREntryJITCode.h:
  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::lower):

  • ftl/FTLOSREntry.cpp:

(JSC::FTL::prepareOSREntry):

Location:
trunk
Files:
1 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r268773 r268783  
     12020-10-20  Saam Barati  <sbarati@apple.com>
     2
     3        Don't OSR exit to bc#0 for FTL argument type checks during loop OSR entry
     4        https://bugs.webkit.org/show_bug.cgi?id=217925
     5        <rdar://problem/70369407>
     6
     7        Reviewed by Michael Saboff and Tadeu Zagallo.
     8
     9        * stress/ftl-osr-entry-should-not-exit-to-bc-zero.js: Added.
     10
    1112020-10-20  Michael Saboff  <msaboff@apple.com>
    212
  • trunk/Source/JavaScriptCore/ChangeLog

    r268773 r268783  
     12020-10-20  Saam Barati  <sbarati@apple.com>
     2
     3        Don't OSR exit to bc#0 for FTL argument type checks during loop OSR entry
     4        https://bugs.webkit.org/show_bug.cgi?id=217925
     5        <rdar://problem/70369407>
     6
     7        Reviewed by Michael Saboff and Tadeu Zagallo.
     8
     9        When the FTL was emitting type checks for the named arguments of a function,
     10        it was always emitting these type checks with an exit origin of bc#0. It was
     11        doing this even if we were an OSR entry compilation! This meant that type
     12        checks for arguments that failed during loop OSR entry would incorrectly exit
     13        back to bc#0.
     14       
     15        This patch fixes this by having the OSR entry runtime code validate the
     16        argument types before OSR entering. The current OSR entry compiled code in
     17        the FTL is designed to only allow exiting after all ExtractOSREntryLocal and
     18        MovHints have executed, so it is simpler to put the type checks in the runtime
     19        instead of the compiled code.
     20       
     21        This patch also makes it so we do exponential backoff when failing to OSR
     22        enter. This is needed due to insufficient profiling where we never properly
     23        profile the type of arguments. Before this, we'd OSR exit in the FTL code
     24        itself, which does exponential backoff when recompiling. This patch builds
     25        this same exponential backoff in for when we fail to OSR enter enough times
     26        to give up on the OSR entry compilation.
     27
     28        * ftl/FTLForOSREntryJITCode.h:
     29        * ftl/FTLLowerDFGToB3.cpp:
     30        (JSC::FTL::DFG::LowerDFGToB3::lower):
     31        * ftl/FTLOSREntry.cpp:
     32        (JSC::FTL::prepareOSREntry):
     33
    1342020-10-20  Michael Saboff  <msaboff@apple.com>
    235
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r268385 r268783  
    37693769    }
    37703770
     3771    auto failedOSREntry = [&] (CodeBlock* entryBlock) {
     3772        FTL::ForOSREntryJITCode* entryCode = entryBlock->jitCode()->ftlForOSREntry();
     3773        entryCode->countEntryFailure();
     3774        if (entryCode->entryFailureCount() <
     3775            Options::ftlOSREntryFailureCountForReoptimization()) {
     3776            CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed"));
     3777            jitCode->setOptimizationThresholdBasedOnCompilationResult(
     3778                codeBlock, CompilationDeferred);
     3779            return nullptr;
     3780        }
     3781
     3782        CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed too many times"));
     3783        codeBlock->baselineVersion()->countReoptimization();
     3784        jitCode->clearOSREntryBlockAndResetThresholds(codeBlock);
     3785        return nullptr;
     3786    };
     3787
    37713788    // If we can OSR Enter, do it right away.
    37723789    if (canOSREnterHere) {
     
    37823799                    return tagCodePtrWithStackPointerForJITCall(untagCodePtr<char*, JSEntryPtrTag>(address), callFrame);
    37833800                }
     3801
     3802                return failedOSREntry(entryBlock);
    37843803            }
    37853804        }
     
    38233842        }
    38243843
    3825         FTL::ForOSREntryJITCode* entryCode = entryBlock->jitCode()->ftlForOSREntry();
    3826         entryCode->countEntryFailure();
    3827         if (entryCode->entryFailureCount() <
    3828             Options::ftlOSREntryFailureCountForReoptimization()) {
    3829             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed"));
    3830             jitCode->setOptimizationThresholdBasedOnCompilationResult(
    3831                 codeBlock, CompilationDeferred);
    3832             return nullptr;
    3833         }
    3834 
    3835         // OSR entry failed. Oh no! This implies that we need to retry. We retry
    3836         // without exponential backoff and we only do this for the entry code block.
    3837         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed too many times"));
    3838         jitCode->clearOSREntryBlockAndResetThresholds(codeBlock);
    3839         return nullptr;
     3844        return failedOSREntry(entryBlock);
    38403845    }
    38413846
     
    39343939    void* address = FTL::prepareOSREntry(vm, callFrame, codeBlock, jitCode->osrEntryBlock(), originBytecodeIndex, streamIndex);
    39353940    if (!address)
    3936         return nullptr;
     3941        return failedOSREntry(jitCode->osrEntryBlock());
    39373942    return tagCodePtrWithStackPointerForJITCall(untagCodePtr<char*, JSEntryPtrTag>(address), callFrame);
    39383943}
  • trunk/Source/JavaScriptCore/ftl/FTLForOSREntryJITCode.h

    r261567 r268783  
    5656   
    5757    ForOSREntryJITCode* ftlForOSREntry() final;
    58    
     58    Vector<DFG::FlushFormat>& argumentFlushFormats() { return m_argumentFlushFormats; }
     59
    5960private:
     61    Vector<DFG::FlushFormat> m_argumentFlushFormats;
    6062    ScratchBuffer* m_entryBuffer; // Only for OSR entry code blocks.
    6163    BytecodeIndex m_bytecodeIndex;
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r268656 r268783  
    359359            }
    360360
    361             for (unsigned i = codeBlock()->numParameters(); i--;) {
    362                 MethodOfGettingAValueProfile profile(&m_graph.m_profiledBlock->valueProfileForArgument(i));
    363                 VirtualRegister operand = virtualRegisterForArgumentIncludingThis(i);
    364                 LValue jsValue = m_out.load64(addressFor(operand));
    365                
    366                 switch (m_graph.m_argumentFormats[0][i]) {
    367                 case FlushedInt32:
    368                     speculate(BadType, jsValueValue(jsValue), profile, isNotInt32(jsValue));
    369                     break;
    370                 case FlushedBoolean:
    371                     speculate(BadType, jsValueValue(jsValue), profile, isNotBoolean(jsValue));
    372                     break;
    373                 case FlushedCell:
    374                     speculate(BadType, jsValueValue(jsValue), profile, isNotCell(jsValue));
    375                     break;
    376                 case FlushedJSValue:
    377                     break;
    378                 default:
    379                     DFG_CRASH(m_graph, nullptr, "Bad flush format for argument");
    380                     break;
     361            if (m_graph.m_plan.mode() == FTLForOSREntryMode) {
     362                auto* jitCode = m_ftlState.jitCode->ftlForOSREntry();
     363                jitCode->argumentFlushFormats().reserveInitialCapacity(codeBlock()->numParameters());
     364                for (unsigned i = codeBlock()->numParameters(); i--;)
     365                    jitCode->argumentFlushFormats().append(m_graph.m_argumentFormats[0][i]);
     366            } else {
     367                for (unsigned i = codeBlock()->numParameters(); i--;) {
     368                    MethodOfGettingAValueProfile profile(&m_graph.m_profiledBlock->valueProfileForArgument(i));
     369                    VirtualRegister operand = virtualRegisterForArgumentIncludingThis(i);
     370                    LValue jsValue = m_out.load64(addressFor(operand));
     371                   
     372                    switch (m_graph.m_argumentFormats[0][i]) {
     373                    case FlushedInt32:
     374                        speculate(BadType, jsValueValue(jsValue), profile, isNotInt32(jsValue));
     375                        break;
     376                    case FlushedBoolean:
     377                        speculate(BadType, jsValueValue(jsValue), profile, isNotBoolean(jsValue));
     378                        break;
     379                    case FlushedCell:
     380                        speculate(BadType, jsValueValue(jsValue), profile, isNotCell(jsValue));
     381                        break;
     382                    case FlushedJSValue:
     383                        break;
     384                    default:
     385                        DFG_CRASH(m_graph, nullptr, "Bad flush format for argument");
     386                        break;
     387                    }
    381388                }
    382389            }
     390
    383391            m_out.jump(firstDFGBasicBlock);
    384392        }
  • trunk/Source/JavaScriptCore/ftl/FTLOSREntry.cpp

    r264804 r268783  
    7575        JSValue valueOnStack = callFrame->r(virtualRegisterForArgumentIncludingThis(argument)).asanUnsafeJSValue();
    7676        Optional<JSValue> reconstructedValue = values.argument(argument);
     77        {
     78            JSValue valueToValidate = reconstructedValue ? *reconstructedValue : valueOnStack;
     79            auto flushFormat = entryCode->argumentFlushFormats()[argument];
     80            switch (flushFormat) {
     81            case DFG::FlushedInt32:
     82                if (!valueToValidate.isInt32())
     83                    return nullptr;
     84                break;
     85            case DFG::FlushedBoolean:
     86                if (!valueToValidate.isBoolean())
     87                    return nullptr;
     88                break;
     89            case DFG::FlushedCell:
     90                if (!valueToValidate.isCell())
     91                    return nullptr;
     92                break;
     93            case DFG::FlushedJSValue:
     94                break;
     95            default:
     96                dataLogLn("Unknown flush format for argument during FTL osr entry: ", flushFormat);
     97                RELEASE_ASSERT_NOT_REACHED();
     98                break;
     99            }
     100        }
     101
    77102        if (!argument) {
    78103            // |this| argument can be unboxed. We should store boxed value instead for loop OSR entry since FTL assumes that all arguments are flushed JSValue.
Note: See TracChangeset for help on using the changeset viewer.