Ignore:
Timestamp:
Jun 22, 2012, 4:32:59 PM (13 years ago)
Author:
[email protected]
Message:

DFG tier-up should happen in prologues, not epilogues
https://bugs.webkit.org/show_bug.cgi?id=89752

Reviewed by Geoffrey Garen.

This change has two outcomes:

1) Slightly reduces the likelihood that a function will be optimized both
standalone and via inlining. Previously, if you had a call sequence like foo()
calls bar() exactly once, and nobody else calls bar(), then bar() would get
optimized first (because it returns first) and then foo() gets optimized. If foo()
can inline bar() then that means that bar() gets optimized twice. But now, if we
optimize in prologues, then foo() will be optimized first. If it inlines bar(),
that means that there will no longer be any calls to bar().

2) It lets us kill some code in JITStubs. Epilogue tier-up was very different from
loop tier-up, since epilogue tier-up should not attempt OSR. But prologue tier-up
requires OSR (albeit really easy OSR since it's the top of the compilation unit),
so it becomes just like loop tier-up. As a result, we now have one optimization
hook (cti_optimize) instead of two (cti_optimize_from_loop and
cti_optimize_from_ret).

As a consequence of not having an optimization check in epilogues, the OSR exit
code must now trigger reoptimization itself instead of just signaling the epilogue
check to fire.

This also adds the ability to count the number of DFG compilations, which was
useful for debugging this patch and might be useful for other things in the future.

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::reoptimize):
(JSC):

  • bytecode/CodeBlock.h:

(CodeBlock):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::parseCodeBlock):

  • dfg/DFGDriver.cpp:

(DFG):
(JSC::DFG::getNumCompilations):
(JSC::DFG::compile):

  • dfg/DFGDriver.h:

(DFG):

  • dfg/DFGOSRExitCompiler.cpp:

(JSC::DFG::OSRExitCompiler::handleExitCounts):

  • dfg/DFGOperations.cpp:
  • dfg/DFGOperations.h:
  • jit/JIT.cpp:

(JSC::JIT::emitOptimizationCheck):

  • jit/JIT.h:
  • jit/JITCall32_64.cpp:

(JSC::JIT::emit_op_ret):
(JSC::JIT::emit_op_ret_object_or_this):

  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_ret):
(JSC::JIT::emit_op_ret_object_or_this):
(JSC::JIT::emit_op_enter):

  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::emit_op_enter):

  • jit/JITStubs.cpp:

(JSC::DEFINE_STUB_FUNCTION):

  • jit/JITStubs.h:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/jit/JITStubs.cpp

    r120499 r121073  
    19201920
    19211921#if ENABLE(DFG_JIT)
    1922 DEFINE_STUB_FUNCTION(void, optimize_from_loop)
     1922DEFINE_STUB_FUNCTION(void, optimize)
    19231923{
    19241924    STUB_INIT_STACK_FRAME(stackFrame);
     
    19261926    CallFrame* callFrame = stackFrame.callFrame;
    19271927    CodeBlock* codeBlock = callFrame->codeBlock();
    1928 
    19291928    unsigned bytecodeIndex = stackFrame.args[0].int32();
    1930    
     1929
    19311930#if ENABLE(JIT_VERBOSE_OSR)
    1932     dataLog("%p: Entered optimize_from_loop with executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock, codeBlock->jitExecuteCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter());
     1931    dataLog("%p: Entered optimize with bytecodeIndex = %u, executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock, bytecodeIndex, codeBlock->jitExecuteCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter());
    19331932#endif
    19341933
     
    19381937    if (codeBlock->hasOptimizedReplacement()) {
    19391938#if ENABLE(JIT_VERBOSE_OSR)
    1940         dataLog("Considering loop OSR into %p(%p) with success/fail %u/%u.\n", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter());
     1939        dataLog("Considering OSR into %p(%p) with success/fail %u/%u.\n", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter());
    19411940#endif
    19421941        if (codeBlock->replacement()->shouldReoptimizeFromLoopNow()) {
     
    19601959#if ENABLE(JIT_VERBOSE_OSR)
    19611960        if (error)
    1962             dataLog("WARNING: optimized compilation from loop failed.\n");
     1961            dataLog("WARNING: optimized compilation failed.\n");
    19631962#else
    19641963        UNUSED_PARAM(error);
     
    19671966        if (codeBlock->replacement() == codeBlock) {
    19681967#if ENABLE(JIT_VERBOSE_OSR)
    1969             dataLog("Optimizing %p from loop failed.\n", codeBlock);
     1968            dataLog("Optimizing %p failed.\n", codeBlock);
    19701969#endif
    19711970           
     
    19811980    if (void* address = DFG::prepareOSREntry(callFrame, optimizedCodeBlock, bytecodeIndex)) {
    19821981#if ENABLE(JIT_VERBOSE_OSR)
    1983         dataLog("Optimizing %p from loop succeeded, performing OSR after a delay of %u.\n", codeBlock, codeBlock->optimizationDelayCounter());
     1982        dataLog("Optimizing %p succeeded, performing OSR after a delay of %u.\n", codeBlock, codeBlock->optimizationDelayCounter());
    19841983#endif
    19851984
     
    19911990   
    19921991#if ENABLE(JIT_VERBOSE_OSR)
    1993     dataLog("Optimizing %p from loop succeeded, OSR failed, after a delay of %u.\n", codeBlock, codeBlock->optimizationDelayCounter());
     1992    dataLog("Optimizing %p succeeded, OSR failed, after a delay of %u.\n", codeBlock, codeBlock->optimizationDelayCounter());
    19941993#endif
    19951994
     
    19991998   
    20001999#if ENABLE(JIT_VERBOSE_OSR)
    2001     dataLog("Encountered loop OSR failure into %p(%p) with success/fail %u/%u.\n", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter());
     2000    dataLog("Encountered OSR failure into %p(%p) with success/fail %u/%u.\n", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter());
    20022001#endif
    20032002
     
    20122011    if (optimizedCodeBlock->shouldReoptimizeNow()) {
    20132012#if ENABLE(JIT_VERBOSE_OSR)
    2014         dataLog("Triggering reoptimization of %p(%p) (in loop after OSR fail).\n", codeBlock, codeBlock->replacement());
     2013        dataLog("Triggering reoptimization of %p(%p) (after OSR fail).\n", codeBlock, codeBlock->replacement());
    20152014#endif
    20162015        codeBlock->reoptimize();
     
    20212020    // longer and then try again.
    20222021    codeBlock->optimizeAfterWarmUp();
    2023 }
    2024 
    2025 DEFINE_STUB_FUNCTION(void, optimize_from_ret)
    2026 {
    2027     STUB_INIT_STACK_FRAME(stackFrame);
    2028    
    2029     CallFrame* callFrame = stackFrame.callFrame;
    2030     CodeBlock* codeBlock = callFrame->codeBlock();
    2031    
    2032 #if ENABLE(JIT_VERBOSE_OSR)
    2033     dataLog("Entered optimize_from_ret with executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock->jitExecuteCounter(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter());
    2034 #endif
    2035 
    2036     if (!codeBlock->checkIfOptimizationThresholdReached())
    2037         return;
    2038 
    2039     if (codeBlock->hasOptimizedReplacement()) {
    2040 #if ENABLE(JIT_VERBOSE_OSR)
    2041         dataLog("Returning from old JIT call frame with optimized replacement %p(%p), with success/fail %u/%u", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter());
    2042         CallFrame* callerFrame = callFrame->callerFrame();
    2043         if (callerFrame)
    2044             dataLog(", callerFrame = %p, returnPC = %p, caller code block = %p", callerFrame, callFrame->returnPC().value(), callerFrame->codeBlock());
    2045         dataLog("\n");
    2046 #endif
    2047         if (codeBlock->replacement()->shouldReoptimizeNow()) {
    2048 #if ENABLE(JIT_VERBOSE_OSR)
    2049             dataLog("Triggering reoptimization of %p(%p) (in return).\n", codeBlock, codeBlock->replacement());
    2050 #endif
    2051             codeBlock->reoptimize();
    2052         }
    2053        
    2054         codeBlock->optimizeSoon();
    2055         return;
    2056     }
    2057    
    2058     if (!codeBlock->shouldOptimizeNow()) {
    2059 #if ENABLE(JIT_VERBOSE_OSR)
    2060         dataLog("Delaying optimization for %p (in return) because of insufficient profiling.\n", codeBlock);
    2061 #endif
    2062         return;
    2063     }
    2064    
    2065     ScopeChainNode* scopeChain = callFrame->scopeChain();
    2066 
    2067     JSObject* error = codeBlock->compileOptimized(callFrame, scopeChain);
    2068     if (error)
    2069         dataLog("WARNING: optimized compilation from ret failed.\n");
    2070    
    2071     if (codeBlock->replacement() == codeBlock) {
    2072 #if ENABLE(JIT_VERBOSE_OSR)
    2073         dataLog("Optimizing %p from return failed.\n", codeBlock);
    2074 #endif
    2075 
    2076         ASSERT(codeBlock->getJITType() == JITCode::BaselineJIT);
    2077         codeBlock->dontOptimizeAnytimeSoon();
    2078         return;
    2079     }
    2080    
    2081     ASSERT(codeBlock->replacement()->getJITType() == JITCode::DFGJIT);
    2082 
    2083 #if ENABLE(JIT_VERBOSE_OSR)
    2084     dataLog("Optimizing %p from return succeeded after a delay of %u.\n", codeBlock, codeBlock->optimizationDelayCounter());
    2085 #endif
    2086    
    2087     codeBlock->optimizeSoon();
    20882022}
    20892023#endif // ENABLE(DFG_JIT)
Note: See TracChangeset for help on using the changeset viewer.