<!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>[161705] branches/jsCStack/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/161705">161705</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2014-01-10 17:29:24 -0800 (Fri, 10 Jan 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>It should be easier to diagnose FTL performance issues due to register preservation thunks
https://bugs.webkit.org/show_bug.cgi?id=126798

Not yet reviewed.
        
You can now use --verboseFTLToJSThunk=true --verboseFTLFailure=true to figure out
which code blocks are rejected by the FTL and yet get called from functions that
were FTL compiled. Any such rejections in major benchmarks should be fixed.

* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::CodeBlock):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::verboseCapabilities):
(JSC::FTL::canCompile):
* jit/RegisterPreservationWrapperGenerator.cpp:
(JSC::generateRegisterPreservationWrapper):
* runtime/Executable.cpp:
(JSC::ExecutableBase::dump):
* runtime/Executable.h:
* runtime/Options.cpp:
(JSC::Options::initialize):
* runtime/Options.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#branchesjsCStackSourceJavaScriptCoreChangeLog">branches/jsCStack/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCorebytecodeCodeBlockcpp">branches/jsCStack/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreftlFTLCapabilitiescpp">branches/jsCStack/Source/JavaScriptCore/ftl/FTLCapabilities.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCorejitRegisterPreservationWrapperGeneratorcpp">branches/jsCStack/Source/JavaScriptCore/jit/RegisterPreservationWrapperGenerator.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreruntimeExecutablecpp">branches/jsCStack/Source/JavaScriptCore/runtime/Executable.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreruntimeExecutableh">branches/jsCStack/Source/JavaScriptCore/runtime/Executable.h</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreruntimeOptionscpp">branches/jsCStack/Source/JavaScriptCore/runtime/Options.cpp</a></li>
<li><a href="#branchesjsCStackSourceJavaScriptCoreruntimeOptionsh">branches/jsCStack/Source/JavaScriptCore/runtime/Options.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchesjsCStackSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/ChangeLog (161704 => 161705)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ChangeLog        2014-01-11 01:26:40 UTC (rev 161704)
+++ branches/jsCStack/Source/JavaScriptCore/ChangeLog        2014-01-11 01:29:24 UTC (rev 161705)
</span><span class="lines">@@ -1,5 +1,30 @@
</span><span class="cx"> 2014-01-10  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        It should be easier to diagnose FTL performance issues due to register preservation thunks
+        https://bugs.webkit.org/show_bug.cgi?id=126798
+
+        Not yet reviewed.
+        
+        You can now use --verboseFTLToJSThunk=true --verboseFTLFailure=true to figure out
+        which code blocks are rejected by the FTL and yet get called from functions that
+        were FTL compiled. Any such rejections in major benchmarks should be fixed.
+
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::CodeBlock):
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::verboseCapabilities):
+        (JSC::FTL::canCompile):
+        * jit/RegisterPreservationWrapperGenerator.cpp:
+        (JSC::generateRegisterPreservationWrapper):
+        * runtime/Executable.cpp:
+        (JSC::ExecutableBase::dump):
+        * runtime/Executable.h:
+        * runtime/Options.cpp:
+        (JSC::Options::initialize):
+        * runtime/Options.h:
+
+2014-01-10  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
</ins><span class="cx">         Unreviewed, add a test for the case where LLVM finds a constant folding
</span><span class="cx">         opportunity that the DFG missed, and it involves a large constant, and then we
</span><span class="cx">         exit with the large constant folded into a stackmap for an OSR exit.
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/bytecode/CodeBlock.cpp (161704 => 161705)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2014-01-11 01:26:40 UTC (rev 161704)
+++ branches/jsCStack/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2014-01-11 01:29:24 UTC (rev 161705)
</span><span class="lines">@@ -1843,18 +1843,7 @@
</span><span class="cx"> 
</span><span class="cx">     // If the concurrent thread will want the code block's hash, then compute it here
</span><span class="cx">     // synchronously.
</span><del>-    if (Options::showDisassembly()
-        || Options::showDFGDisassembly()
-        || Options::dumpBytecodeAtDFGTime()
-        || Options::dumpGraphAtEachPhase()
-        || Options::verboseCompilation()
-        || Options::logCompilationChanges()
-        || Options::validateGraph()
-        || Options::validateGraphAtEachPhase()
-        || Options::verboseOSR()
-        || Options::verboseCompilationQueue()
-        || Options::reportCompileTimes()
-        || Options::verboseCFA())
</del><ins>+    if (Options::alwaysComputeHash())
</ins><span class="cx">         hash();
</span><span class="cx"> 
</span><span class="cx">     if (Options::dumpGeneratedBytecodes())
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreftlFTLCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/ftl/FTLCapabilities.cpp (161704 => 161705)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2014-01-11 01:26:40 UTC (rev 161704)
+++ branches/jsCStack/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2014-01-11 01:29:24 UTC (rev 161705)
</span><span class="lines">@@ -32,6 +32,11 @@
</span><span class="cx"> 
</span><span class="cx"> using namespace DFG;
</span><span class="cx"> 
</span><ins>+static bool verboseCapabilities()
+{
+    return verboseCompilationEnabled() || Options::verboseFTLFailure();
+}
+
</ins><span class="cx"> inline CapabilityLevel canCompile(Node* node)
</span><span class="cx"> {
</span><span class="cx">     // NOTE: If we ever have phantom arguments, we can compile them but we cannot
</span><span class="lines">@@ -234,8 +239,8 @@
</span><span class="cx"> CapabilityLevel canCompile(Graph&amp; graph)
</span><span class="cx"> {
</span><span class="cx">     if (graph.m_codeBlock-&gt;codeType() != FunctionCode) {
</span><del>-        if (verboseCompilationEnabled())
-            dataLog(&quot;FTL rejecting code block that doesn't belong to a function.\n&quot;);
</del><ins>+        if (verboseCapabilities())
+            dataLog(&quot;FTL rejecting &quot;, *graph.m_codeBlock, &quot; because it doesn't belong to a function.\n&quot;);
</ins><span class="cx">         return CannotCompile;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -243,8 +248,8 @@
</span><span class="cx">         // Need this because although we also don't support
</span><span class="cx">         // CreateActivation/TearOffActivation, we might not see those nodes in case of
</span><span class="cx">         // OSR entry.
</span><del>-        if (verboseCompilationEnabled())
-            dataLog(&quot;FTL rejecting code block that uses activations.\n&quot;);
</del><ins>+        if (verboseCapabilities())
+            dataLog(&quot;FTL rejecting &quot;, *graph.m_codeBlock, &quot; because it uses activations.\n&quot;);
</ins><span class="cx">         return CannotCompile;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -285,8 +290,8 @@
</span><span class="cx">                     break;
</span><span class="cx">                 default:
</span><span class="cx">                     // Don't know how to handle anything else.
</span><del>-                    if (verboseCompilationEnabled()) {
-                        dataLog(&quot;FTL rejecting node because of bad use kind: &quot;, edge.useKind(), &quot; in node:\n&quot;);
</del><ins>+                    if (verboseCapabilities()) {
+                        dataLog(&quot;FTL rejecting node in &quot;, *graph.m_codeBlock, &quot; because of bad use kind: &quot;, edge.useKind(), &quot; in node:\n&quot;);
</ins><span class="cx">                         graph.dump(WTF::dataFile(), &quot;    &quot;, node);
</span><span class="cx">                     }
</span><span class="cx">                     return CannotCompile;
</span><span class="lines">@@ -295,8 +300,8 @@
</span><span class="cx">             
</span><span class="cx">             switch (canCompile(node)) {
</span><span class="cx">             case CannotCompile: 
</span><del>-                if (verboseCompilationEnabled()) {
-                    dataLog(&quot;FTL rejecting node:\n&quot;);
</del><ins>+                if (verboseCapabilities()) {
+                    dataLog(&quot;FTL rejecting node in &quot;, *graph.m_codeBlock, &quot;:\n&quot;);
</ins><span class="cx">                     graph.dump(WTF::dataFile(), &quot;    &quot;, node);
</span><span class="cx">                 }
</span><span class="cx">                 return CannotCompile;
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCorejitRegisterPreservationWrapperGeneratorcpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/jit/RegisterPreservationWrapperGenerator.cpp (161704 => 161705)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/jit/RegisterPreservationWrapperGenerator.cpp        2014-01-11 01:26:40 UTC (rev 161704)
+++ branches/jsCStack/Source/JavaScriptCore/jit/RegisterPreservationWrapperGenerator.cpp        2014-01-11 01:29:24 UTC (rev 161705)
</span><span class="lines">@@ -116,6 +116,9 @@
</span><span class="cx">     
</span><span class="cx">     LinkBuffer linkBuffer(vm, &amp;jit, GLOBAL_THUNK_ID);
</span><span class="cx">     linkBuffer.link(call, CodeLocationLabel(target));
</span><ins>+
+    if (Options::verboseFTLToJSThunk())
+        dataLog(&quot;Need a thunk for calls from FTL to non-FTL version of &quot;, *executable, &quot;\n&quot;);
</ins><span class="cx">     
</span><span class="cx">     return FINALIZE_DFG_CODE(linkBuffer, (&quot;Register preservation wrapper for %s/%s, %p&quot;, toCString(executable-&gt;hashFor(CodeForCall)).data(), toCString(executable-&gt;hashFor(CodeForConstruct)).data(), target.executableAddress()));
</span><span class="cx"> #else // ENABLE(FTL_JIT)
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreruntimeExecutablecpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/runtime/Executable.cpp (161704 => 161705)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/runtime/Executable.cpp        2014-01-11 01:26:40 UTC (rev 161704)
+++ branches/jsCStack/Source/JavaScriptCore/runtime/Executable.cpp        2014-01-11 01:29:24 UTC (rev 161705)
</span><span class="lines">@@ -606,6 +606,46 @@
</span><span class="cx">     return m_unlinkedExecutable-&gt;paramString();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void ExecutableBase::dump(PrintStream&amp; out) const
+{
+    ExecutableBase* realThis = const_cast&lt;ExecutableBase*&gt;(this);
+    
+    if (classInfo() == NativeExecutable::info()) {
+        NativeExecutable* native = jsCast&lt;NativeExecutable*&gt;(realThis);
+        out.print(&quot;NativeExecutable:&quot;, RawPointer(bitwise_cast&lt;void*&gt;(native-&gt;function())), &quot;/&quot;, RawPointer(bitwise_cast&lt;void*&gt;(native-&gt;constructor())));
+        return;
+    }
+    
+    if (classInfo() == EvalExecutable::info()) {
+        EvalExecutable* eval = jsCast&lt;EvalExecutable*&gt;(realThis);
+        if (CodeBlock* codeBlock = eval-&gt;codeBlock())
+            out.print(*codeBlock);
+        else
+            out.print(&quot;EvalExecutable w/o CodeBlock&quot;);
+        return;
+    }
+    
+    if (classInfo() == ProgramExecutable::info()) {
+        ProgramExecutable* eval = jsCast&lt;ProgramExecutable*&gt;(realThis);
+        if (CodeBlock* codeBlock = eval-&gt;codeBlock())
+            out.print(*codeBlock);
+        else
+            out.print(&quot;ProgramExecutable w/o CodeBlock&quot;);
+        return;
+    }
+    
+    FunctionExecutable* function = jsCast&lt;FunctionExecutable*&gt;(realThis);
+    if (!function-&gt;eitherCodeBlock())
+        out.print(&quot;FunctionExecutable w/o CodeBlock&quot;);
+    else {
+        CommaPrinter comma(&quot;/&quot;);
+        if (function-&gt;codeBlockForCall())
+            out.print(comma, *function-&gt;codeBlockForCall());
+        if (function-&gt;codeBlockForConstruct())
+            out.print(comma, *function-&gt;codeBlockForConstruct());
+    }
+}
+
</ins><span class="cx"> CodeBlockHash ExecutableBase::hashFor(CodeSpecializationKind kind) const
</span><span class="cx"> {
</span><span class="cx">     if (this-&gt;classInfo() == NativeExecutable::info())
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreruntimeExecutableh"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/runtime/Executable.h (161704 => 161705)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/runtime/Executable.h        2014-01-11 01:26:40 UTC (rev 161704)
+++ branches/jsCStack/Source/JavaScriptCore/runtime/Executable.h        2014-01-11 01:29:24 UTC (rev 161705)
</span><span class="lines">@@ -269,6 +269,8 @@
</span><span class="cx">             return intrinsic();
</span><span class="cx">         return NoIntrinsic;
</span><span class="cx">     }
</span><ins>+    
+    void dump(PrintStream&amp;) const;
</ins><span class="cx">         
</span><span class="cx"> protected:
</span><span class="cx">     ExecutableBase* m_prev;
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreruntimeOptionscpp"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/runtime/Options.cpp (161704 => 161705)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/runtime/Options.cpp        2014-01-11 01:26:40 UTC (rev 161704)
+++ branches/jsCStack/Source/JavaScriptCore/runtime/Options.cpp        2014-01-11 01:29:24 UTC (rev 161705)
</span><span class="lines">@@ -211,7 +211,22 @@
</span><span class="cx"> #if !ENABLE(YARR_JIT)
</span><span class="cx">     useRegExpJIT() = false;
</span><span class="cx"> #endif
</span><del>-
</del><ins>+    
+    if (showDisassembly()
+        || showDFGDisassembly()
+        || dumpBytecodeAtDFGTime()
+        || dumpGraphAtEachPhase()
+        || verboseCompilation()
+        || logCompilationChanges()
+        || validateGraph()
+        || validateGraphAtEachPhase()
+        || verboseOSR()
+        || verboseCompilationQueue()
+        || reportCompileTimes()
+        || verboseCFA()
+        || verboseFTLFailure())
+        alwaysComputeHash() = true;
+    
</ins><span class="cx">     // Do range checks where needed and make corrections to the options:
</span><span class="cx">     ASSERT(thresholdForOptimizeAfterLongWarmUp() &gt;= thresholdForOptimizeAfterWarmUp());
</span><span class="cx">     ASSERT(thresholdForOptimizeAfterWarmUp() &gt;= thresholdForOptimizeSoon());
</span></span></pre></div>
<a id="branchesjsCStackSourceJavaScriptCoreruntimeOptionsh"></a>
<div class="modfile"><h4>Modified: branches/jsCStack/Source/JavaScriptCore/runtime/Options.h (161704 => 161705)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsCStack/Source/JavaScriptCore/runtime/Options.h        2014-01-11 01:26:40 UTC (rev 161704)
+++ branches/jsCStack/Source/JavaScriptCore/runtime/Options.h        2014-01-11 01:29:24 UTC (rev 161705)
</span><span class="lines">@@ -124,6 +124,9 @@
</span><span class="cx">     v(bool, verboseCompilationQueue, false) \
</span><span class="cx">     v(bool, reportCompileTimes, false) \
</span><span class="cx">     v(bool, verboseCFA, false) \
</span><ins>+    v(bool, verboseFTLToJSThunk, false) \
+    v(bool, verboseFTLFailure, false) \
+    v(bool, alwaysComputeHash, false) \
</ins><span class="cx">     \
</span><span class="cx">     v(bool, enableOSREntryToDFG, true) \
</span><span class="cx">     \
</span></span></pre>
</div>
</div>

</body>
</html>