<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[163517] trunk/Source/JavaScriptCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/163517">163517</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2014-02-05 23:11:48 -0800 (Wed, 05 Feb 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Make FTL OSR entry something we only try after we've already compiled the function with the FTL and it still got stuck in a loop after that without ever returning like a sensible function oughta have
https://bugs.webkit.org/show_bug.cgi?id=128234

Reviewed by Geoffrey Garen.
        
Use DFG::JITCode::osrEntryRetry as a counter to decide when to invoke OSR entry. That
comes into play only after we've done a replacement compile.
        
This appears to still give us a speed-up on the kinds of things that OSR entry is good
for, while also eliminating pointless OSR entry compilations on other things.

* dfg/DFGJITCode.cpp:
(JSC::DFG::JITCode::JITCode):
* dfg/DFGJITCode.h:
* dfg/DFGOperations.cpp:
* dfg/DFGToFTLForOSREntryDeferredCompilationCallback.cpp:
(JSC::DFG::ToFTLForOSREntryDeferredCompilationCallback::compilationDidComplete):
* runtime/Options.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGJITCodecpp">trunk/Source/JavaScriptCore/dfg/DFGJITCode.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGJITCodeh">trunk/Source/JavaScriptCore/dfg/DFGJITCode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationscpp">trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGToFTLForOSREntryDeferredCompilationCallbackcpp">trunk/Source/JavaScriptCore/dfg/DFGToFTLForOSREntryDeferredCompilationCallback.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeOptionsh">trunk/Source/JavaScriptCore/runtime/Options.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (163516 => 163517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2014-02-06 06:55:20 UTC (rev 163516)
+++ trunk/Source/JavaScriptCore/ChangeLog        2014-02-06 07:11:48 UTC (rev 163517)
</span><span class="lines">@@ -1,5 +1,26 @@
</span><span class="cx"> 2014-02-04  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Make FTL OSR entry something we only try after we've already compiled the function with the FTL and it still got stuck in a loop after that without ever returning like a sensible function oughta have
+        https://bugs.webkit.org/show_bug.cgi?id=128234
+
+        Reviewed by Geoffrey Garen.
+        
+        Use DFG::JITCode::osrEntryRetry as a counter to decide when to invoke OSR entry. That
+        comes into play only after we've done a replacement compile.
+        
+        This appears to still give us a speed-up on the kinds of things that OSR entry is good
+        for, while also eliminating pointless OSR entry compilations on other things.
+
+        * dfg/DFGJITCode.cpp:
+        (JSC::DFG::JITCode::JITCode):
+        * dfg/DFGJITCode.h:
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGToFTLForOSREntryDeferredCompilationCallback.cpp:
+        (JSC::DFG::ToFTLForOSREntryDeferredCompilationCallback::compilationDidComplete):
+        * runtime/Options.h:
+
+2014-02-04  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
</ins><span class="cx">         Don't speculate on ToThis if we already know that arg0 has a questionable record with structure checks
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=128229
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGJITCodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGJITCode.cpp (163516 => 163517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGJITCode.cpp        2014-02-06 06:55:20 UTC (rev 163516)
+++ trunk/Source/JavaScriptCore/dfg/DFGJITCode.cpp        2014-02-06 07:11:48 UTC (rev 163517)
</span><span class="lines">@@ -34,6 +34,10 @@
</span><span class="cx"> 
</span><span class="cx"> JITCode::JITCode()
</span><span class="cx">     : DirectJITCode(DFGJIT)
</span><ins>+#if ENABLE(FTL_JIT)
+    , osrEntryRetry(0)
+    , abandonOSREntry(false)
+#endif // ENABLE(FTL_JIT)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGJITCodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGJITCode.h (163516 => 163517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGJITCode.h        2014-02-06 06:55:20 UTC (rev 163516)
+++ trunk/Source/JavaScriptCore/dfg/DFGJITCode.h        2014-02-06 07:11:48 UTC (rev 163517)
</span><span class="lines">@@ -125,6 +125,8 @@
</span><span class="cx"> #if ENABLE(FTL_JIT)
</span><span class="cx">     ExecutionCounter tierUpCounter;
</span><span class="cx">     RefPtr&lt;CodeBlock&gt; osrEntryBlock;
</span><ins>+    unsigned osrEntryRetry;
+    bool abandonOSREntry;
</ins><span class="cx"> #endif // ENABLE(FTL_JIT)
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp (163516 => 163517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2014-02-06 06:55:20 UTC (rev 163516)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2014-02-06 07:11:48 UTC (rev 163517)
</span><span class="lines">@@ -1113,21 +1113,8 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(FTL_JIT)
</span><del>-void JIT_OPERATION triggerTierUpNow(ExecState* exec)
</del><ins>+static void triggerFTLReplacementCompile(VM* vm, CodeBlock* codeBlock, JITCode* jitCode)
</ins><span class="cx"> {
</span><del>-    VM* vm = &amp;exec-&gt;vm();
-    NativeCallFrameTracer tracer(vm, exec);
-    DeferGC deferGC(vm-&gt;heap);
-    CodeBlock* codeBlock = exec-&gt;codeBlock();
-    
-    JITCode* jitCode = codeBlock-&gt;jitCode()-&gt;dfg();
-    
-    if (Options::verboseOSR()) {
-        dataLog(
-            *codeBlock, &quot;: Entered triggerTierUpNow with executeCounter = &quot;,
-            jitCode-&gt;tierUpCounter, &quot;\n&quot;);
-    }
-    
</del><span class="cx">     if (codeBlock-&gt;baselineVersion()-&gt;m_didFailFTLCompilation) {
</span><span class="cx">         if (Options::verboseOSR())
</span><span class="cx">             dataLog(&quot;Deferring FTL-optimization of &quot;, *codeBlock, &quot; indefinitely because there was an FTL failure.\n&quot;);
</span><span class="lines">@@ -1175,6 +1162,24 @@
</span><span class="cx">         Operands&lt;JSValue&gt;(), ToFTLDeferredCompilationCallback::create(codeBlock));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void JIT_OPERATION triggerTierUpNow(ExecState* exec)
+{
+    VM* vm = &amp;exec-&gt;vm();
+    NativeCallFrameTracer tracer(vm, exec);
+    DeferGC deferGC(vm-&gt;heap);
+    CodeBlock* codeBlock = exec-&gt;codeBlock();
+    
+    JITCode* jitCode = codeBlock-&gt;jitCode()-&gt;dfg();
+    
+    if (Options::verboseOSR()) {
+        dataLog(
+            *codeBlock, &quot;: Entered triggerTierUpNow with executeCounter = &quot;,
+            jitCode-&gt;tierUpCounter, &quot;\n&quot;);
+    }
+    
+    triggerFTLReplacementCompile(vm, codeBlock, jitCode);
+}
+
</ins><span class="cx"> char* JIT_OPERATION triggerOSREntryNow(
</span><span class="cx">     ExecState* exec, int32_t bytecodeIndex, int32_t streamIndex)
</span><span class="cx"> {
</span><span class="lines">@@ -1191,57 +1196,47 @@
</span><span class="cx">             jitCode-&gt;tierUpCounter, &quot;\n&quot;);
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    if (codeBlock-&gt;baselineVersion()-&gt;m_didFailFTLCompilation) {
-        if (Options::verboseOSR())
-            dataLog(&quot;Deferring FTL-optimization of &quot;, *codeBlock, &quot; indefinitely because there was an FTL failure.\n&quot;);
-        jitCode-&gt;dontOptimizeAnytimeSoon(codeBlock);
</del><ins>+    // - If we don't have an FTL code block, then try to compile one.
+    // - If we do have an FTL code block, then try to enter for a while.
+    // - If we couldn't enter for a while, then trigger OSR entry.
+    
+    triggerFTLReplacementCompile(vm, codeBlock, jitCode);
+
+    if (!codeBlock-&gt;hasOptimizedReplacement())
</ins><span class="cx">         return 0;
</span><del>-    }
</del><span class="cx">     
</span><del>-    if (!jitCode-&gt;checkIfOptimizationThresholdReached(codeBlock)) {
-        if (Options::verboseOSR())
-            dataLog(&quot;Choosing not to FTL-optimize &quot;, *codeBlock, &quot; yet.\n&quot;);
</del><ins>+    if (jitCode-&gt;osrEntryRetry &lt; Options::ftlOSREntryRetryThreshold()) {
+        jitCode-&gt;osrEntryRetry++;
</ins><span class="cx">         return 0;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    Worklist* worklist = existingGlobalFTLWorklistOrNull();
-
</del><ins>+    // It's time to try to compile code for OSR entry.
</ins><span class="cx">     Worklist::State worklistState;
</span><del>-    if (worklist) {
</del><ins>+    if (Worklist* worklist = existingGlobalFTLWorklistOrNull()) {
</ins><span class="cx">         worklistState = worklist-&gt;completeAllReadyPlansForVM(
</span><span class="cx">             *vm, CompilationKey(codeBlock-&gt;baselineVersion(), FTLForOSREntryMode));
</span><span class="cx">     } else
</span><span class="cx">         worklistState = Worklist::NotKnown;
</span><span class="cx">     
</span><del>-    if (worklistState == Worklist::Compiling) {
-        ASSERT(!jitCode-&gt;osrEntryBlock);
-        jitCode-&gt;setOptimizationThresholdBasedOnCompilationResult(
-            codeBlock, CompilationDeferred);
</del><ins>+    if (worklistState == Worklist::Compiling)
</ins><span class="cx">         return 0;
</span><del>-    }
</del><span class="cx">     
</span><span class="cx">     if (CodeBlock* entryBlock = jitCode-&gt;osrEntryBlock.get()) {
</span><span class="cx">         void* address = FTL::prepareOSREntry(
</span><span class="cx">             exec, codeBlock, entryBlock, bytecodeIndex, streamIndex);
</span><del>-        if (address) {
-            jitCode-&gt;optimizeSoon(codeBlock);
</del><ins>+        if (address)
</ins><span class="cx">             return static_cast&lt;char*&gt;(address);
</span><del>-        }
</del><span class="cx">         
</span><span class="cx">         FTL::ForOSREntryJITCode* entryCode = entryBlock-&gt;jitCode()-&gt;ftlForOSREntry();
</span><span class="cx">         entryCode-&gt;countEntryFailure();
</span><span class="cx">         if (entryCode-&gt;entryFailureCount() &lt;
</span><del>-            Options::ftlOSREntryFailureCountForReoptimization()) {
-            
-            jitCode-&gt;optimizeSoon(codeBlock);
</del><ins>+            Options::ftlOSREntryFailureCountForReoptimization())
</ins><span class="cx">             return 0;
</span><del>-        }
</del><span class="cx">         
</span><span class="cx">         // OSR entry failed. Oh no! This implies that we need to retry. We retry
</span><span class="cx">         // without exponential backoff and we only do this for the entry code block.
</span><span class="cx">         jitCode-&gt;osrEntryBlock.clear();
</span><del>-        
-        jitCode-&gt;optimizeAfterWarmUp(codeBlock);
</del><ins>+        jitCode-&gt;osrEntryRetry = 0;
</ins><span class="cx">         return 0;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -1252,7 +1247,8 @@
</span><span class="cx">         return 0;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // The first order of business is to trigger a for-entry compile.
</del><ins>+    // We aren't compiling and haven't compiled anything for OSR entry. So, try to compile
+    // something.
</ins><span class="cx">     Operands&lt;JSValue&gt; mustHandleValues;
</span><span class="cx">     jitCode-&gt;reconstruct(
</span><span class="cx">         exec, codeBlock, CodeOrigin(bytecodeIndex), streamIndex, mustHandleValues);
</span><span class="lines">@@ -1260,24 +1256,6 @@
</span><span class="cx">         *vm, codeBlock-&gt;newReplacement().get(), codeBlock, FTLForOSREntryMode, bytecodeIndex,
</span><span class="cx">         mustHandleValues, ToFTLForOSREntryDeferredCompilationCallback::create(codeBlock));
</span><span class="cx">     
</span><del>-    // But we also want to trigger a replacement compile. Of course, we don't want to
-    // trigger it if we don't need to. Note that this is kind of weird because we might
-    // have just finished an FTL compile and that compile failed or was invalidated.
-    // But this seems uncommon enough that we sort of don't care. It's certainly sound
-    // to fire off another compile right now so long as we're not already compiling and
-    // we don't already have an optimized replacement. Note, we don't do this for
-    // obviously bad cases like global code, where we know that there is a slim chance
-    // of this code being invoked ever again.
-    CompilationKey keyForReplacement(codeBlock-&gt;baselineVersion(), FTLMode);
-    if (codeBlock-&gt;codeType() != GlobalCode
-        &amp;&amp; !codeBlock-&gt;hasOptimizedReplacement()
-        &amp;&amp; (!worklist
-            || worklist-&gt;compilationState(keyForReplacement) == Worklist::NotKnown)) {
-        compile(
-            *vm, codeBlock-&gt;newReplacement().get(), codeBlock, FTLMode, UINT_MAX,
-            Operands&lt;JSValue&gt;(), ToFTLDeferredCompilationCallback::create(codeBlock));
-    }
-    
</del><span class="cx">     if (forEntryResult != CompilationSuccessful)
</span><span class="cx">         return 0;
</span><span class="cx">     
</span><span class="lines">@@ -1286,10 +1264,6 @@
</span><span class="cx">     // We signal to try again after a while if that happens.
</span><span class="cx">     void* address = FTL::prepareOSREntry(
</span><span class="cx">         exec, codeBlock, jitCode-&gt;osrEntryBlock.get(), bytecodeIndex, streamIndex);
</span><del>-    if (address)
-        jitCode-&gt;optimizeSoon(codeBlock);
-    else
-        jitCode-&gt;optimizeAfterWarmUp(codeBlock);
</del><span class="cx">     return static_cast&lt;char*&gt;(address);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGToFTLForOSREntryDeferredCompilationCallbackcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGToFTLForOSREntryDeferredCompilationCallback.cpp (163516 => 163517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGToFTLForOSREntryDeferredCompilationCallback.cpp        2014-02-06 06:55:20 UTC (rev 163516)
+++ trunk/Source/JavaScriptCore/dfg/DFGToFTLForOSREntryDeferredCompilationCallback.cpp        2014-02-06 07:11:48 UTC (rev 163517)
</span><span class="lines">@@ -73,13 +73,24 @@
</span><span class="cx">             &quot;) result: &quot;, result, &quot;\n&quot;);
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    if (result == CompilationSuccessful)
-        m_dfgCodeBlock-&gt;jitCode()-&gt;dfg()-&gt;osrEntryBlock = codeBlock;
</del><ins>+    JITCode* jitCode = m_dfgCodeBlock-&gt;jitCode()-&gt;dfg();
+        
+    switch (result) {
+    case CompilationSuccessful:
+        jitCode-&gt;osrEntryBlock = codeBlock;
+        return;
+    case CompilationFailed:
+        jitCode-&gt;osrEntryRetry = 0;
+        jitCode-&gt;abandonOSREntry = true;
+        return;
+    case CompilationDeferred:
+        return;
+    case CompilationInvalidated:
+        jitCode-&gt;osrEntryRetry = 0;
+        return;
+    }
</ins><span class="cx">     
</span><del>-    // FIXME: if we failed, we might want to just turn off OSR entry rather than
-    // totally turning off tier-up.
-    m_dfgCodeBlock-&gt;jitCode()-&gt;dfg()-&gt;setOptimizationThresholdBasedOnCompilationResult(
-        m_dfgCodeBlock.get(), result);
</del><ins>+    RELEASE_ASSERT_NOT_REACHED();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } } // JSC::DFG
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Options.h (163516 => 163517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Options.h        2014-02-06 06:55:20 UTC (rev 163516)
+++ trunk/Source/JavaScriptCore/runtime/Options.h        2014-02-06 07:11:48 UTC (rev 163517)
</span><span class="lines">@@ -197,6 +197,7 @@
</span><span class="cx">     v(int32, ftlTierUpCounterIncrementForLoop, 1) \
</span><span class="cx">     v(int32, ftlTierUpCounterIncrementForReturn, 15) \
</span><span class="cx">     v(unsigned, ftlOSREntryFailureCountForReoptimization, 15) \
</span><ins>+    v(unsigned, ftlOSREntryRetryThreshold, 100) \
</ins><span class="cx">     \
</span><span class="cx">     v(int32, evalThresholdMultiplier, 10) \
</span><span class="cx">     \
</span></span></pre>
</div>
</div>

</body>
</html>