Title: [121511] trunk/Source/_javascript_Core
Revision
121511
Author
[email protected]
Date
2012-06-28 19:40:14 -0700 (Thu, 28 Jun 2012)

Log Message

DFG recompilation heuristics should be based on count, not rate
https://bugs.webkit.org/show_bug.cgi?id=90146

Reviewed by Oliver Hunt.
        
This removes a bunch of code that was previously trying to prevent spurious
reoptimizations if a large enough majority of executions of a code block did
not result in OSR exit. It turns out that this code was purely harmful. This
patch removes all of that logic and replaces it with a dead-simple
heuristic: if you exit more than N times (where N is an exponential function
of the number of times the code block has already been recompiled) then we
will recompile.
        
This appears to be a broad ~1% win on many benchmarks large and small.

* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::CodeBlock):
* bytecode/CodeBlock.h:
(JSC::CodeBlock::osrExitCounter):
(JSC::CodeBlock::countOSRExit):
(CodeBlock):
(JSC::CodeBlock::addressOfOSRExitCounter):
(JSC::CodeBlock::offsetOfOSRExitCounter):
(JSC::CodeBlock::adjustedExitCountThreshold):
(JSC::CodeBlock::exitCountThresholdForReoptimization):
(JSC::CodeBlock::exitCountThresholdForReoptimizationFromLoop):
(JSC::CodeBlock::shouldReoptimizeNow):
(JSC::CodeBlock::shouldReoptimizeFromLoopNow):
* bytecode/ExecutionCounter.cpp:
(JSC::ExecutionCounter::setThreshold):
* bytecode/ExecutionCounter.h:
(ExecutionCounter):
(JSC::ExecutionCounter::clippedThreshold):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::compileBody):
* dfg/DFGOSRExit.cpp:
(JSC::DFG::OSRExit::considerAddingAsFrequentExitSiteSlow):
* dfg/DFGOSRExitCompiler.cpp:
(JSC::DFG::OSRExitCompiler::handleExitCounts):
* dfg/DFGOperations.cpp:
* jit/JITStubs.cpp:
(JSC::DEFINE_STUB_FUNCTION):
* runtime/Options.cpp:
(Options):
(JSC::Options::initializeOptions):
* runtime/Options.h:
(Options):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (121510 => 121511)


--- trunk/Source/_javascript_Core/ChangeLog	2012-06-29 02:37:43 UTC (rev 121510)
+++ trunk/Source/_javascript_Core/ChangeLog	2012-06-29 02:40:14 UTC (rev 121511)
@@ -1,3 +1,53 @@
+2012-06-28  Filip Pizlo  <[email protected]>
+
+        DFG recompilation heuristics should be based on count, not rate
+        https://bugs.webkit.org/show_bug.cgi?id=90146
+
+        Reviewed by Oliver Hunt.
+        
+        This removes a bunch of code that was previously trying to prevent spurious
+        reoptimizations if a large enough majority of executions of a code block did
+        not result in OSR exit. It turns out that this code was purely harmful. This
+        patch removes all of that logic and replaces it with a dead-simple
+        heuristic: if you exit more than N times (where N is an exponential function
+        of the number of times the code block has already been recompiled) then we
+        will recompile.
+        
+        This appears to be a broad ~1% win on many benchmarks large and small.
+
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::CodeBlock):
+        * bytecode/CodeBlock.h:
+        (JSC::CodeBlock::osrExitCounter):
+        (JSC::CodeBlock::countOSRExit):
+        (CodeBlock):
+        (JSC::CodeBlock::addressOfOSRExitCounter):
+        (JSC::CodeBlock::offsetOfOSRExitCounter):
+        (JSC::CodeBlock::adjustedExitCountThreshold):
+        (JSC::CodeBlock::exitCountThresholdForReoptimization):
+        (JSC::CodeBlock::exitCountThresholdForReoptimizationFromLoop):
+        (JSC::CodeBlock::shouldReoptimizeNow):
+        (JSC::CodeBlock::shouldReoptimizeFromLoopNow):
+        * bytecode/ExecutionCounter.cpp:
+        (JSC::ExecutionCounter::setThreshold):
+        * bytecode/ExecutionCounter.h:
+        (ExecutionCounter):
+        (JSC::ExecutionCounter::clippedThreshold):
+        * dfg/DFGJITCompiler.cpp:
+        (JSC::DFG::JITCompiler::compileBody):
+        * dfg/DFGOSRExit.cpp:
+        (JSC::DFG::OSRExit::considerAddingAsFrequentExitSiteSlow):
+        * dfg/DFGOSRExitCompiler.cpp:
+        (JSC::DFG::OSRExitCompiler::handleExitCounts):
+        * dfg/DFGOperations.cpp:
+        * jit/JITStubs.cpp:
+        (JSC::DEFINE_STUB_FUNCTION):
+        * runtime/Options.cpp:
+        (Options):
+        (JSC::Options::initializeOptions):
+        * runtime/Options.h:
+        (Options):
+
 2012-06-28  Mark Lam  <[email protected]>
 
         Adding a commenting utility to record BytecodeGenerator comments

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (121510 => 121511)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2012-06-29 02:37:43 UTC (rev 121510)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2012-06-29 02:40:14 UTC (rev 121511)
@@ -1691,9 +1691,7 @@
     , m_functionDecls(other.m_functionDecls)
     , m_functionExprs(other.m_functionExprs)
     , m_symbolTable(symTab)
-    , m_speculativeSuccessCounter(0)
-    , m_speculativeFailCounter(0)
-    , m_forcedOSRExitCounter(0)
+    , m_osrExitCounter(0)
     , m_optimizationDelayCounter(0)
     , m_reoptimizationRetryCounter(0)
     , m_lineInfo(other.m_lineInfo)
@@ -1748,8 +1746,7 @@
 #endif
     , m_symbolTable(symTab)
     , m_alternative(alternative)
-    , m_speculativeSuccessCounter(0)
-    , m_speculativeFailCounter(0)
+    , m_osrExitCounter(0)
     , m_optimizationDelayCounter(0)
     , m_reoptimizationRetryCounter(0)
 #if ENABLE(BYTECODE_COMMENTS)

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.h (121510 => 121511)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.h	2012-06-29 02:37:43 UTC (rev 121510)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.h	2012-06-29 02:40:14 UTC (rev 121511)
@@ -1078,59 +1078,48 @@
             m_jitExecuteCounter.setNewThreshold(Options::thresholdForOptimizeSoon << reoptimizationRetryCounter(), this);
         }
         
-        // The speculative JIT tracks its success rate, so that we can
-        // decide when to reoptimize. It's interesting to note that these
-        // counters may overflow without any protection. The success
-        // counter will overflow before the fail one does, becuase the
-        // fail one is used as a trigger to reoptimize. So the worst case
-        // is that the success counter overflows and we reoptimize without
-        // needing to. But this is harmless. If a method really did
-        // execute 2^32 times then compiling it again probably won't hurt
-        // anyone.
+        uint32_t osrExitCounter() const { return m_osrExitCounter; }
         
-        void countSpeculationSuccess()
+        void countOSRExit() { m_osrExitCounter++; }
+        
+        uint32_t* addressOfOSRExitCounter() { return &m_osrExitCounter; }
+        
+        static ptrdiff_t offsetOfOSRExitCounter() { return OBJECT_OFFSETOF(CodeBlock, m_osrExitCounter); }
+
+#if ENABLE(JIT)
+        uint32_t adjustedExitCountThreshold(uint32_t desiredThreshold)
         {
-            m_speculativeSuccessCounter++;
+            ASSERT(getJITType() == JITCode::DFGJIT);
+            // Compute this the lame way so we don't saturate. This is called infrequently
+            // enough that this loop won't hurt us.
+            unsigned result = desiredThreshold;
+            for (unsigned n = baselineVersion()->reoptimizationRetryCounter(); n--;) {
+                unsigned newResult = result << 1;
+                if (newResult < result)
+                    return std::numeric_limits<uint32_t>::max();
+                result = newResult;
+            }
+            return result;
         }
         
-        void countSpeculationFailure()
+        uint32_t exitCountThresholdForReoptimization()
         {
-            m_speculativeFailCounter++;
+            return adjustedExitCountThreshold(Options::osrExitCountForReoptimization);
         }
         
-        uint32_t speculativeSuccessCounter() const { return m_speculativeSuccessCounter; }
-        uint32_t speculativeFailCounter() const { return m_speculativeFailCounter; }
-        uint32_t forcedOSRExitCounter() const { return m_forcedOSRExitCounter; }
-        
-        uint32_t* addressOfSpeculativeSuccessCounter() { return &m_speculativeSuccessCounter; }
-        uint32_t* addressOfSpeculativeFailCounter() { return &m_speculativeFailCounter; }
-        uint32_t* addressOfForcedOSRExitCounter() { return &m_forcedOSRExitCounter; }
-        
-        static ptrdiff_t offsetOfSpeculativeSuccessCounter() { return OBJECT_OFFSETOF(CodeBlock, m_speculativeSuccessCounter); }
-        static ptrdiff_t offsetOfSpeculativeFailCounter() { return OBJECT_OFFSETOF(CodeBlock, m_speculativeFailCounter); }
-        static ptrdiff_t offsetOfForcedOSRExitCounter() { return OBJECT_OFFSETOF(CodeBlock, m_forcedOSRExitCounter); }
+        uint32_t exitCountThresholdForReoptimizationFromLoop()
+        {
+            return adjustedExitCountThreshold(Options::osrExitCountForReoptimizationFromLoop);
+        }
 
-#if ENABLE(JIT)
-        // The number of failures that triggers the use of the ratio.
-        unsigned largeFailCountThreshold() { return Options::largeFailCountThresholdBase << baselineVersion()->reoptimizationRetryCounter(); }
-        unsigned largeFailCountThresholdForLoop() { return Options::largeFailCountThresholdBaseForLoop << baselineVersion()->reoptimizationRetryCounter(); }
-
         bool shouldReoptimizeNow()
         {
-            return (Options::desiredSpeculativeSuccessFailRatio *
-                        speculativeFailCounter() >= speculativeSuccessCounter()
-                    && speculativeFailCounter() >= largeFailCountThreshold())
-                || forcedOSRExitCounter() >=
-                       Options::forcedOSRExitCountForReoptimization;
+            return osrExitCounter() >= exitCountThresholdForReoptimization();
         }
-
+        
         bool shouldReoptimizeFromLoopNow()
         {
-            return (Options::desiredSpeculativeSuccessFailRatio *
-                        speculativeFailCounter() >= speculativeSuccessCounter()
-                    && speculativeFailCounter() >= largeFailCountThresholdForLoop())
-                || forcedOSRExitCounter() >=
-                       Options::forcedOSRExitCountForReoptimization;
+            return osrExitCounter() >= exitCountThresholdForReoptimizationFromLoop();
         }
 #endif
 
@@ -1331,9 +1320,7 @@
         
         ExecutionCounter m_jitExecuteCounter;
         int32_t m_totalJITExecutions;
-        uint32_t m_speculativeSuccessCounter;
-        uint32_t m_speculativeFailCounter;
-        uint32_t m_forcedOSRExitCounter;
+        uint32_t m_osrExitCounter;
         uint16_t m_optimizationDelayCounter;
         uint16_t m_reoptimizationRetryCounter;
 

Modified: trunk/Source/_javascript_Core/bytecode/ExecutionCounter.cpp (121510 => 121511)


--- trunk/Source/_javascript_Core/bytecode/ExecutionCounter.cpp	2012-06-29 02:37:43 UTC (rev 121510)
+++ trunk/Source/_javascript_Core/bytecode/ExecutionCounter.cpp	2012-06-29 02:40:14 UTC (rev 121511)
@@ -144,13 +144,7 @@
         return true;
     }
 
-    int32_t maxThreshold;
-    if (Options::randomizeExecutionCountsBetweenCheckpoints)
-        maxThreshold = codeBlock->globalObject()->weakRandomInteger() % Options::maximumExecutionCountsBetweenCheckpoints;
-    else
-        maxThreshold = Options::maximumExecutionCountsBetweenCheckpoints;
-    if (threshold > maxThreshold)
-        threshold = maxThreshold;
+    threshold = clippedThreshold(codeBlock->globalObject(), threshold);
     
     m_counter = static_cast<int32_t>(-threshold);
         

Modified: trunk/Source/_javascript_Core/bytecode/ExecutionCounter.h (121510 => 121511)


--- trunk/Source/_javascript_Core/bytecode/ExecutionCounter.h	2012-06-29 02:37:43 UTC (rev 121510)
+++ trunk/Source/_javascript_Core/bytecode/ExecutionCounter.h	2012-06-29 02:40:14 UTC (rev 121511)
@@ -26,6 +26,8 @@
 #ifndef ExecutionCounter_h
 #define ExecutionCounter_h
 
+#include "JSGlobalObject.h"
+#include "Options.h"
 #include <wtf/SimpleStats.h>
 
 namespace JSC {
@@ -42,6 +44,18 @@
     const char* status() const;
     static double applyMemoryUsageHeuristics(int32_t value, CodeBlock*);
     static int32_t applyMemoryUsageHeuristicsAndConvertToInt(int32_t value, CodeBlock*);
+    template<typename T>
+    static T clippedThreshold(JSGlobalObject* globalObject, T threshold)
+    {
+        int32_t maxThreshold;
+        if (Options::randomizeExecutionCountsBetweenCheckpoints)
+            maxThreshold = globalObject->weakRandomInteger() % Options::maximumExecutionCountsBetweenCheckpoints;
+        else
+            maxThreshold = Options::maximumExecutionCountsBetweenCheckpoints;
+        if (threshold > maxThreshold)
+            threshold = maxThreshold;
+        return threshold;
+    }
 
     static int32_t formattedTotalCount(float value)
     {

Modified: trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp (121510 => 121511)


--- trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp	2012-06-29 02:37:43 UTC (rev 121510)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp	2012-06-29 02:40:14 UTC (rev 121511)
@@ -88,8 +88,6 @@
     breakpoint();
 #endif
     
-    addPtr(TrustedImm32(1), AbsoluteAddress(codeBlock()->addressOfSpeculativeSuccessCounter()));
-
     bool compiledSpeculative = speculative.compile();
     ASSERT_UNUSED(compiledSpeculative, compiledSpeculative);
 }

Modified: trunk/Source/_javascript_Core/dfg/DFGOSRExit.cpp (121510 => 121511)


--- trunk/Source/_javascript_Core/dfg/DFGOSRExit.cpp	2012-06-29 02:37:43 UTC (rev 121510)
+++ trunk/Source/_javascript_Core/dfg/DFGOSRExit.cpp	2012-06-29 02:40:14 UTC (rev 121511)
@@ -76,7 +76,7 @@
 
 bool OSRExit::considerAddingAsFrequentExitSiteSlow(CodeBlock* dfgCodeBlock, CodeBlock* profiledCodeBlock)
 {
-    if (static_cast<double>(m_count) / dfgCodeBlock->speculativeFailCounter() <= Options::osrExitProminenceForFrequentExitSite)
+    if (static_cast<double>(m_count) / dfgCodeBlock->osrExitCounter() <= Options::osrExitProminenceForFrequentExitSite)
         return false;
     
     FrequentExitSite exitSite;

Modified: trunk/Source/_javascript_Core/dfg/DFGOSRExitCompiler.cpp (121510 => 121511)


--- trunk/Source/_javascript_Core/dfg/DFGOSRExitCompiler.cpp	2012-06-29 02:37:43 UTC (rev 121510)
+++ trunk/Source/_javascript_Core/dfg/DFGOSRExitCompiler.cpp	2012-06-29 02:40:14 UTC (rev 121511)
@@ -104,42 +104,14 @@
     
     m_jit.move(AssemblyHelpers::TrustedImmPtr(m_jit.codeBlock()), GPRInfo::regT0);
     
-    AssemblyHelpers::JumpList tooFewFails;
+    AssemblyHelpers::Jump tooFewFails;
     
-    if (exit.m_kind == InadequateCoverage) {
-        // Proceed based on the assumption that we can profitably optimize this code once
-        // it has executed enough times.
-        
-        m_jit.load32(AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfForcedOSRExitCounter()), GPRInfo::regT2);
-        m_jit.load32(AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeSuccessCounter()), GPRInfo::regT1);
-        m_jit.add32(AssemblyHelpers::TrustedImm32(1), GPRInfo::regT2);
-        m_jit.add32(AssemblyHelpers::TrustedImm32(-1), GPRInfo::regT1);
-        m_jit.store32(GPRInfo::regT2, AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfForcedOSRExitCounter()));
-        m_jit.store32(GPRInfo::regT1, AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeSuccessCounter()));
-        
-        m_jit.move(AssemblyHelpers::TrustedImmPtr(m_jit.baselineCodeBlock()), GPRInfo::regT0);
-
-        tooFewFails.append(m_jit.branch32(AssemblyHelpers::BelowOrEqual, GPRInfo::regT2, AssemblyHelpers::TrustedImm32(Options::forcedOSRExitCountForReoptimization)));
-
-    } else {
-        // Proceed based on the assumption that we can handle these exits so long as they
-        // don't get too frequent.
-        
-        m_jit.load32(AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeFailCounter()), GPRInfo::regT2);
-        m_jit.load32(AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeSuccessCounter()), GPRInfo::regT1);
-        m_jit.add32(AssemblyHelpers::TrustedImm32(1), GPRInfo::regT2);
-        m_jit.add32(AssemblyHelpers::TrustedImm32(-1), GPRInfo::regT1);
-        m_jit.store32(GPRInfo::regT2, AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeFailCounter()));
-        m_jit.store32(GPRInfo::regT1, AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeSuccessCounter()));
+    m_jit.load32(AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfOSRExitCounter()), GPRInfo::regT2);
+    m_jit.add32(AssemblyHelpers::TrustedImm32(1), GPRInfo::regT2);
+    m_jit.store32(GPRInfo::regT2, AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfOSRExitCounter()));
+    m_jit.move(AssemblyHelpers::TrustedImmPtr(m_jit.baselineCodeBlock()), GPRInfo::regT0);
+    tooFewFails = m_jit.branch32(AssemblyHelpers::BelowOrEqual, GPRInfo::regT2, AssemblyHelpers::TrustedImm32(m_jit.codeBlock()->exitCountThresholdForReoptimization()));
     
-        m_jit.move(AssemblyHelpers::TrustedImmPtr(m_jit.baselineCodeBlock()), GPRInfo::regT0);
-    
-        tooFewFails.append(m_jit.branch32(AssemblyHelpers::BelowOrEqual, GPRInfo::regT2, AssemblyHelpers::TrustedImm32(m_jit.codeBlock()->largeFailCountThreshold())));
-        m_jit.mul32(AssemblyHelpers::TrustedImm32(Options::desiredSpeculativeSuccessFailRatio), GPRInfo::regT2, GPRInfo::regT2);
-    
-        tooFewFails.append(m_jit.branch32(AssemblyHelpers::BelowOrEqual, GPRInfo::regT2, GPRInfo::regT1));
-    }
-
     // Reoptimize as soon as possible.
 #if !NUMBER_OF_ARGUMENT_REGISTERS
     m_jit.poke(GPRInfo::regT0);
@@ -159,6 +131,7 @@
             m_jit.baselineCodeBlock()->counterValueForOptimizeAfterLongWarmUp(),
             m_jit.baselineCodeBlock());
     m_jit.store32(AssemblyHelpers::TrustedImm32(-targetValue), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecuteCounter()));
+    targetValue = ExecutionCounter::clippedThreshold(m_jit.codeBlock()->globalObject(), targetValue);
     m_jit.store32(AssemblyHelpers::TrustedImm32(targetValue), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecutionActiveThreshold()));
     m_jit.store32(AssemblyHelpers::TrustedImm32(ExecutionCounter::formattedTotalCount(targetValue)), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecutionTotalCount()));
     

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (121510 => 121511)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2012-06-29 02:37:43 UTC (rev 121510)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2012-06-29 02:40:14 UTC (rev 121511)
@@ -1250,15 +1250,13 @@
     CodeBlock* alternative = codeBlock->alternative();
     dataLog("Speculation failure in %p at @%u with executeCounter = %s, "
             "reoptimizationRetryCounter = %u, optimizationDelayCounter = %u, "
-            "success/fail %u/(%u+%u)\n",
+            "osrExitCounter = %u\n",
             codeBlock,
             debugInfo->nodeIndex,
             alternative ? alternative->jitExecuteCounter().status() : 0,
             alternative ? alternative->reoptimizationRetryCounter() : 0,
             alternative ? alternative->optimizationDelayCounter() : 0,
-            codeBlock->speculativeSuccessCounter(),
-            codeBlock->speculativeFailCounter(),
-            codeBlock->forcedOSRExitCounter());
+            codeBlock->osrExitCounter());
 }
 #endif
 

Modified: trunk/Source/_javascript_Core/jit/JITStubs.cpp (121510 => 121511)


--- trunk/Source/_javascript_Core/jit/JITStubs.cpp	2012-06-29 02:37:43 UTC (rev 121510)
+++ trunk/Source/_javascript_Core/jit/JITStubs.cpp	2012-06-29 02:40:14 UTC (rev 121511)
@@ -1928,7 +1928,12 @@
     unsigned bytecodeIndex = stackFrame.args[0].int32();
 
 #if ENABLE(JIT_VERBOSE_OSR)
-    dataLog("%p: Entered optimize with bytecodeIndex = %u, executeCounter = %s, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u\n", codeBlock, bytecodeIndex, codeBlock->jitExecuteCounter().status(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter());
+    dataLog("%p: Entered optimize with bytecodeIndex = %u, executeCounter = %s, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u, exitCounter = ", codeBlock, bytecodeIndex, codeBlock->jitExecuteCounter().status(), codeBlock->reoptimizationRetryCounter(), codeBlock->optimizationDelayCounter());
+    if (codeBlock->hasOptimizedReplacement())
+        dataLog("%u", codeBlock->replacement()->osrExitCounter());
+    else
+        dataLog("N/A");
+    dataLog("\n");
 #endif
 
     if (!codeBlock->checkIfOptimizationThresholdReached()) {
@@ -1938,8 +1943,21 @@
 
     if (codeBlock->hasOptimizedReplacement()) {
 #if ENABLE(JIT_VERBOSE_OSR)
-        dataLog("Considering OSR into %p(%p) with success/fail %u/%u.\n", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter());
+        dataLog("Considering OSR into %p(%p).\n", codeBlock, codeBlock->replacement());
 #endif
+        // If we have an optimized replacement, then it must be the case that we entered
+        // cti_optimize from a loop. That's because is there's an optimized replacement,
+        // then all calls to this function will be relinked to the replacement and so
+        // the prologue OSR will never fire.
+        
+        // This is an interesting threshold check. Consider that a function OSR exits
+        // in the middle of a loop, while having a relatively low exit count. The exit
+        // will reset the execution counter to some target threshold, meaning that this
+        // code won't be reached until that loop heats up for >=1000 executions. But then
+        // we do a second check here, to see if we should either reoptimize, or just
+        // attempt OSR entry. Hence it might even be correct for
+        // shouldReoptimizeFromLoopNow() to always return true. But we make it do some
+        // additional checking anyway, to reduce the amount of recompilation thrashing.
         if (codeBlock->replacement()->shouldReoptimizeFromLoopNow()) {
 #if ENABLE(JIT_VERBOSE_OSR)
             dataLog("Triggering reoptimization of %p(%p) (in loop).\n", codeBlock, codeBlock->replacement());
@@ -1985,7 +2003,6 @@
 #endif
 
         codeBlock->optimizeSoon();
-        optimizedCodeBlock->countSpeculationSuccess();
         STUB_SET_RETURN_ADDRESS(address);
         return;
     }
@@ -1996,10 +2013,10 @@
 
     // Count the OSR failure as a speculation failure. If this happens a lot, then
     // reoptimize.
-    optimizedCodeBlock->countSpeculationFailure();
+    optimizedCodeBlock->countOSRExit();
     
 #if ENABLE(JIT_VERBOSE_OSR)
-    dataLog("Encountered OSR failure into %p(%p) with success/fail %u/%u.\n", codeBlock, codeBlock->replacement(), codeBlock->replacement()->speculativeSuccessCounter(), codeBlock->replacement()->speculativeFailCounter());
+    dataLog("Encountered OSR failure into %p(%p).\n", codeBlock, codeBlock->replacement());
 #endif
 
     // We are a lot more conservative about triggering reoptimization after OSR failure than

Modified: trunk/Source/_javascript_Core/runtime/Options.cpp (121510 => 121511)


--- trunk/Source/_javascript_Core/runtime/Options.cpp	2012-06-29 02:37:43 UTC (rev 121510)
+++ trunk/Source/_javascript_Core/runtime/Options.cpp	2012-06-29 02:40:14 UTC (rev 121511)
@@ -70,19 +70,15 @@
 bool randomizeExecutionCountsBetweenCheckpoints;
 int32_t maximumExecutionCountsBetweenCheckpoints;
 
-unsigned desiredSpeculativeSuccessFailRatio;
-
 double likelyToTakeSlowCaseThreshold;
 double couldTakeSlowCaseThreshold;
 unsigned likelyToTakeSlowCaseMinimumCount;
 unsigned couldTakeSlowCaseMinimumCount;
 
 double osrExitProminenceForFrequentExitSite;
+unsigned osrExitCountForReoptimization;
+unsigned osrExitCountForReoptimizationFromLoop;
 
-unsigned largeFailCountThresholdBase;
-unsigned largeFailCountThresholdBaseForLoop;
-unsigned forcedOSRExitCountForReoptimization;
-
 unsigned reoptimizationRetryCounterMax;
 unsigned reoptimizationRetryCounterStep;
 
@@ -194,19 +190,15 @@
     SET(randomizeExecutionCountsBetweenCheckpoints, false);
     SET(maximumExecutionCountsBetweenCheckpoints, 1000);
 
-    SET(desiredSpeculativeSuccessFailRatio, 6);
-    
     SET(likelyToTakeSlowCaseThreshold,    0.15);
     SET(couldTakeSlowCaseThreshold,       0.05); // Shouldn't be zero because some ops will spuriously take slow case, for example for linking or caching.
     SET(likelyToTakeSlowCaseMinimumCount, 100);
     SET(couldTakeSlowCaseMinimumCount,    10);
     
-    SET(osrExitProminenceForFrequentExitSite, 0.3);
+    SET(osrExitProminenceForFrequentExitSite,  0.3);
+    SET(osrExitCountForReoptimization,         100);
+    SET(osrExitCountForReoptimizationFromLoop, 5);
 
-    SET(largeFailCountThresholdBase,         20);
-    SET(largeFailCountThresholdBaseForLoop,  1);
-    SET(forcedOSRExitCountForReoptimization, 250);
-
     SET(reoptimizationRetryCounterStep, 1);
 
     SET(minimumOptimizationDelay,   1);

Modified: trunk/Source/_javascript_Core/runtime/Options.h (121510 => 121511)


--- trunk/Source/_javascript_Core/runtime/Options.h	2012-06-29 02:37:43 UTC (rev 121510)
+++ trunk/Source/_javascript_Core/runtime/Options.h	2012-06-29 02:40:14 UTC (rev 121511)
@@ -56,19 +56,15 @@
 extern bool randomizeExecutionCountsBetweenCheckpoints;
 extern int32_t maximumExecutionCountsBetweenCheckpoints;
 
-extern unsigned desiredSpeculativeSuccessFailRatio;
-
 extern double likelyToTakeSlowCaseThreshold;
 extern double couldTakeSlowCaseThreshold;
 extern unsigned likelyToTakeSlowCaseMinimumCount;
 extern unsigned couldTakeSlowCaseMinimumCount;
 
 extern double osrExitProminenceForFrequentExitSite;
+extern unsigned osrExitCountForReoptimization;
+extern unsigned osrExitCountForReoptimizationFromLoop;
 
-extern unsigned largeFailCountThresholdBase;
-extern unsigned largeFailCountThresholdBaseForLoop;
-extern unsigned forcedOSRExitCountForReoptimization;
-
 extern unsigned reoptimizationRetryCounterMax;
 extern unsigned reoptimizationRetryCounterStep;
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to