<!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>[184288] 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/184288">184288</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2015-05-13 10:39:02 -0700 (Wed, 13 May 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>REGRESSION(<a href="http://trac.webkit.org/projects/webkit/changeset/184260">r184260</a>): arguments elimination has stopped working because of Check(UntypedUse:) from SSAConversionPhase
https://bugs.webkit.org/show_bug.cgi?id=144951

Reviewed by Michael Saboff.
        
There were two issues here:
        
- In <a href="http://trac.webkit.org/projects/webkit/changeset/184260">r184260</a> we expected a small number of possible use kinds in Check nodes, and
  UntypedUse was not one of them. That seemed like a sensible assumption because we don't
  create Check nodes unless it's to have a check. But, SSAConversionPhase was creating a
  Check that could have UntypedUse. I fixed this. It's cleaner for SSAConversionPhase to
  follow the same idiom as everyone else and not create tautological checks.
        
- It's clearly not very robust to assume that Checks will not be used tautologically. So,
  this changes how we validate Checks in the escape analyses. We now use willHaveCheck,
  which catches cases that AI would have already marked as unnecessary. It then also uses
  a new helper called alreadyChecked(), which allows us to just ask if the check is
  unnecessary for objects. That's a good fall-back in case AI hadn't run yet.

* dfg/DFGArgumentsEliminationPhase.cpp:
* dfg/DFGMayExit.cpp:
* dfg/DFGObjectAllocationSinkingPhase.cpp:
(JSC::DFG::ObjectAllocationSinkingPhase::handleNode):
* dfg/DFGSSAConversionPhase.cpp:
(JSC::DFG::SSAConversionPhase::run):
* dfg/DFGUseKind.h:
(JSC::DFG::alreadyChecked):
* dfg/DFGVarargsForwardingPhase.cpp:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGArgumentsEliminationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGMayExitcpp">trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGObjectAllocationSinkingPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSSAConversionPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGUseKindh">trunk/Source/JavaScriptCore/dfg/DFGUseKind.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGVarargsForwardingPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (184287 => 184288)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-05-13 16:48:33 UTC (rev 184287)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-05-13 17:39:02 UTC (rev 184288)
</span><span class="lines">@@ -1,3 +1,35 @@
</span><ins>+2015-05-13  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        REGRESSION(r184260): arguments elimination has stopped working because of Check(UntypedUse:) from SSAConversionPhase
+        https://bugs.webkit.org/show_bug.cgi?id=144951
+
+        Reviewed by Michael Saboff.
+        
+        There were two issues here:
+        
+        - In r184260 we expected a small number of possible use kinds in Check nodes, and
+          UntypedUse was not one of them. That seemed like a sensible assumption because we don't
+          create Check nodes unless it's to have a check. But, SSAConversionPhase was creating a
+          Check that could have UntypedUse. I fixed this. It's cleaner for SSAConversionPhase to
+          follow the same idiom as everyone else and not create tautological checks.
+        
+        - It's clearly not very robust to assume that Checks will not be used tautologically. So,
+          this changes how we validate Checks in the escape analyses. We now use willHaveCheck,
+          which catches cases that AI would have already marked as unnecessary. It then also uses
+          a new helper called alreadyChecked(), which allows us to just ask if the check is
+          unnecessary for objects. That's a good fall-back in case AI hadn't run yet.
+
+        * dfg/DFGArgumentsEliminationPhase.cpp:
+        * dfg/DFGMayExit.cpp:
+        * dfg/DFGObjectAllocationSinkingPhase.cpp:
+        (JSC::DFG::ObjectAllocationSinkingPhase::handleNode):
+        * dfg/DFGSSAConversionPhase.cpp:
+        (JSC::DFG::SSAConversionPhase::run):
+        * dfg/DFGUseKind.h:
+        (JSC::DFG::alreadyChecked):
+        * dfg/DFGVarargsForwardingPhase.cpp:
+
+k
</ins><span class="cx"> 2015-05-13  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [ES6] Implement String.raw
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGArgumentsEliminationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp (184287 => 184288)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp        2015-05-13 16:48:33 UTC (rev 184287)
+++ trunk/Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp        2015-05-13 17:39:02 UTC (rev 184288)
</span><span class="lines">@@ -63,6 +63,11 @@
</span><span class="cx">         // version over LoadStore.
</span><span class="cx">         DFG_ASSERT(m_graph, nullptr, m_graph.m_form == SSA);
</span><span class="cx">         
</span><ins>+        if (verbose) {
+            dataLog(&quot;Graph before arguments elimination:\n&quot;);
+            m_graph.dump();
+        }
+        
</ins><span class="cx">         identifyCandidates();
</span><span class="cx">         if (m_candidates.isEmpty())
</span><span class="cx">             return false;
</span><span class="lines">@@ -169,15 +174,13 @@
</span><span class="cx">                     m_graph.doToChildren(
</span><span class="cx">                         node,
</span><span class="cx">                         [&amp;] (Edge edge) {
</span><del>-                            switch (edge.useKind()) {
-                            case CellUse:
-                            case ObjectUse:
-                                break;
-                                
-                            default:
-                                escape(edge);
-                                break;
-                            }
</del><ins>+                            if (edge.willNotHaveCheck())
+                                return;
+                            
+                            if (alreadyChecked(edge.useKind(), SpecObject))
+                                return;
+                            
+                            escape(edge);
</ins><span class="cx">                         });
</span><span class="cx">                     break;
</span><span class="cx">                     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGMayExitcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp (184287 => 184288)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp        2015-05-13 16:48:33 UTC (rev 184287)
+++ trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp        2015-05-13 17:39:02 UTC (rev 184288)
</span><span class="lines">@@ -51,12 +51,21 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         switch (edge.useKind()) {
</span><ins>+        // These are shady because nodes that have these use kinds will typically exit for
+        // unrelated reasons. For example CompareEq doesn't usually exit, but if it uses ObjectUse
+        // then it will.
</ins><span class="cx">         case ObjectUse:
</span><span class="cx">         case ObjectOrOtherUse:
</span><ins>+            m_result = true;
+            break;
+            
+        // These are shady because they check the structure even if the type of the child node
+        // passes the StringObject type filter.
</ins><span class="cx">         case StringObjectUse:
</span><span class="cx">         case StringOrStringObjectUse:
</span><span class="cx">             m_result = true;
</span><span class="cx">             break;
</span><ins>+            
</ins><span class="cx">         default:
</span><span class="cx">             break;
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGObjectAllocationSinkingPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp (184287 => 184288)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp        2015-05-13 16:48:33 UTC (rev 184287)
+++ trunk/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp        2015-05-13 17:39:02 UTC (rev 184288)
</span><span class="lines">@@ -841,28 +841,13 @@
</span><span class="cx">             m_graph.doToChildren(
</span><span class="cx">                 node,
</span><span class="cx">                 [&amp;] (Edge edge) {
</span><del>-                    bool ok = true;
-
-                    switch (edge.useKind()) {
-                    case KnownCellUse:
-                    case CellUse:
-                    case ObjectUse:
-                        // All of our allocations will pass this.
-                        break;
-                        
-                    case FunctionUse:
-                        // Function allocations will pass this.
-                        if (edge-&gt;op() != NewFunction)
-                            ok = false;
-                        break;
-                        
-                    default:
-                        ok = false;
-                        break;
-                    }
</del><ins>+                    if (edge.willNotHaveCheck())
+                        return;
</ins><span class="cx">                     
</span><del>-                    if (!ok)
-                        escape(edge.node());
</del><ins>+                    if (alreadyChecked(edge.useKind(), SpecObject))
+                        return;
+                    
+                    escape(edge.node());
</ins><span class="cx">                 });
</span><span class="cx">             break;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSSAConversionPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp (184287 => 184288)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp        2015-05-13 16:48:33 UTC (rev 184287)
+++ trunk/Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp        2015-05-13 17:39:02 UTC (rev 184288)
</span><span class="lines">@@ -276,17 +276,18 @@
</span><span class="cx">                     
</span><span class="cx">                 case SetLocal: {
</span><span class="cx">                     VariableAccessData* variable = node-&gt;variableAccessData();
</span><ins>+                    Node* child = node-&gt;child1().node();
</ins><span class="cx">                     
</span><span class="cx">                     if (!!(node-&gt;flags() &amp; NodeIsFlushed)) {
</span><span class="cx">                         node-&gt;convertToPutStack(
</span><span class="cx">                             m_graph.m_stackAccessData.add(
</span><span class="cx">                                 variable-&gt;local(), variable-&gt;flushFormat()));
</span><span class="cx">                     } else
</span><del>-                        node-&gt;setOpAndDefaultFlags(Check);
</del><ins>+                        node-&gt;remove();
</ins><span class="cx">                     
</span><span class="cx">                     if (verbose)
</span><del>-                        dataLog(&quot;Mapping: &quot;, variable-&gt;local(), &quot; -&gt; &quot;, node-&gt;child1().node(), &quot;\n&quot;);
-                    valueForOperand.operand(variable-&gt;local()) = node-&gt;child1().node();
</del><ins>+                        dataLog(&quot;Mapping: &quot;, variable-&gt;local(), &quot; -&gt; &quot;, child, &quot;\n&quot;);
+                    valueForOperand.operand(variable-&gt;local()) = child;
</ins><span class="cx">                     break;
</span><span class="cx">                 }
</span><span class="cx">                     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGUseKindh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGUseKind.h (184287 => 184288)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGUseKind.h        2015-05-13 16:48:33 UTC (rev 184287)
+++ trunk/Source/JavaScriptCore/dfg/DFGUseKind.h        2015-05-13 17:39:02 UTC (rev 184288)
</span><span class="lines">@@ -213,6 +213,17 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+// Returns true if we've already guaranteed the type 
+inline bool alreadyChecked(UseKind kind, SpeculatedType type)
+{
+    // If the check involves the structure then we need to know more than just the type to be sure
+    // that the check is done.
+    if (usesStructure(kind))
+        return false;
+    
+    return !(type &amp; ~typeFilterFor(kind));
+}
+
</ins><span class="cx"> inline UseKind useKindForResult(NodeFlags result)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(!(result &amp; ~NodeResultMask));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGVarargsForwardingPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp (184287 => 184288)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp        2015-05-13 16:48:33 UTC (rev 184287)
+++ trunk/Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp        2015-05-13 17:39:02 UTC (rev 184288)
</span><span class="lines">@@ -109,16 +109,16 @@
</span><span class="cx">                 m_graph.doToChildren(
</span><span class="cx">                     node,
</span><span class="cx">                     [&amp;] (Edge edge) {
</span><del>-                        switch (edge.useKind()) {
-                        case CellUse:
-                        case ObjectUse:
-                            if (edge == candidate)
-                                lastUserIndex = nodeIndex;
-                            break;
-                        default:
-                            sawEscape = true;
-                            break;
-                        }  
</del><ins>+                        if (edge == candidate)
+                            lastUserIndex = nodeIndex;
+                        
+                        if (edge.willNotHaveCheck())
+                            return;
+                        
+                        if (alreadyChecked(edge.useKind(), SpecObject))
+                            return;
+                        
+                        sawEscape = true;
</ins><span class="cx">                     });
</span><span class="cx">                 if (sawEscape) {
</span><span class="cx">                     if (verbose)
</span></span></pre>
</div>
</div>

</body>
</html>