<!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>[200325] 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/200325">200325</a></dd>
<dt>Author</dt> <dd>keith_miller@apple.com</dd>
<dt>Date</dt> <dd>2016-05-02 10:38:15 -0700 (Mon, 02 May 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>ToThis should be able to be eliminated in Constant Folding
https://bugs.webkit.org/show_bug.cgi?id=157213

Reviewed by Saam Barati.

This patch enables eliminating the ToThis value when we have abstract interpreter
indicates the node is not needed. Since there are Objects that override their
ToThis behavior we first check if we can eliminate the node by looking at its
speculated type. If the function is in strict mode then we can eliminate ToThis as
long as the speculated type is not SpecObjectOther since that contains objects
that may set OverridesToThis. If the function is not in strict mode then we can
eliminate ToThis as long is the speculated type is an object that is not SpecObjectOther.

If we can't eliminate with type information we can still eliminate the ToThis node with
the proven structure set. When ToThis only sees structures that do not set OverridesToThis
it can be eliminated. Additionally, if the function is in strict mode then we can eliminate
ToThis as long as all only the object structures don't set OverridesToThis.

* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::isToThisAnIdentity):
(JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
* dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupToThis):
* tests/stress/to-this-global-object.js: Added.
(test):
(test2):
(get for):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstresstothisglobalobjectjs">trunk/Source/JavaScriptCore/tests/stress/to-this-global-object.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (200324 => 200325)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-05-02 16:21:33 UTC (rev 200324)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-05-02 17:38:15 UTC (rev 200325)
</span><span class="lines">@@ -1,3 +1,35 @@
</span><ins>+2016-05-02  Keith Miller  &lt;keith_miller@apple.com&gt;
+
+        ToThis should be able to be eliminated in Constant Folding
+        https://bugs.webkit.org/show_bug.cgi?id=157213
+
+        Reviewed by Saam Barati.
+
+        This patch enables eliminating the ToThis value when we have abstract interpreter
+        indicates the node is not needed. Since there are Objects that override their
+        ToThis behavior we first check if we can eliminate the node by looking at its
+        speculated type. If the function is in strict mode then we can eliminate ToThis as
+        long as the speculated type is not SpecObjectOther since that contains objects
+        that may set OverridesToThis. If the function is not in strict mode then we can
+        eliminate ToThis as long is the speculated type is an object that is not SpecObjectOther.
+
+        If we can't eliminate with type information we can still eliminate the ToThis node with
+        the proven structure set. When ToThis only sees structures that do not set OverridesToThis
+        it can be eliminated. Additionally, if the function is in strict mode then we can eliminate
+        ToThis as long as all only the object structures don't set OverridesToThis.
+
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::isToThisAnIdentity):
+        (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
+        * dfg/DFGConstantFoldingPhase.cpp:
+        (JSC::DFG::ConstantFoldingPhase::foldConstants):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupToThis):
+        * tests/stress/to-this-global-object.js: Added.
+        (test):
+        (test2):
+        (get for):
+
</ins><span class="cx"> 2016-05-01  Skachkov Oleksandr  &lt;gskachkov@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Class contructor and methods shouldn't have &quot;arguments&quot; and &quot;caller&quot;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (200324 => 200325)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-05-02 16:21:33 UTC (rev 200324)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-05-02 17:38:15 UTC (rev 200325)
</span><span class="lines">@@ -142,6 +142,36 @@
</span><span class="cx">     DFG_NODE_DO_TO_CHILDREN(m_graph, node, verifyEdge);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline bool isToThisAnIdentity(bool isStrictMode, AbstractValue&amp; valueForNode)
+{
+    // We look at the type first since that will cover most cases and does not require iterating all the structures.
+    if (isStrictMode) {
+        if (valueForNode.m_type &amp;&amp; !(valueForNode.m_type &amp; SpecObjectOther))
+            return true;
+    } else {
+        if (valueForNode.m_type &amp;&amp; !(valueForNode.m_type &amp; (~SpecObject | SpecObjectOther)))
+            return true;
+    }
+
+    if ((isStrictMode || (valueForNode.m_type &amp;&amp; !(valueForNode.m_type &amp; ~SpecObject))) &amp;&amp; valueForNode.m_structure.isFinite()) {
+        bool overridesToThis = false;
+        valueForNode.m_structure.forEach([&amp;](Structure* structure) {
+            TypeInfo type = structure-&gt;typeInfo();
+            ASSERT(type.isObject() || type.type() == StringType || type.type() == SymbolType);
+            if (!isStrictMode)
+                ASSERT(type.isObject());
+            // We don't need to worry about strings/symbols here since either:
+            // 1) We are in strict mode and strings/symbols are not wrapped
+            // 2) The AI has proven that the type of this is a subtype of object
+            if (type.isObject() &amp;&amp; type.overridesToThis())
+                overridesToThis = true;
+        });
+        return overridesToThis;
+    }
+
+    return false;
+}
+
</ins><span class="cx"> template&lt;typename AbstractStateType&gt;
</span><span class="cx"> bool AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects(unsigned clobberLimit, Node* node)
</span><span class="cx"> {
</span><span class="lines">@@ -1847,21 +1877,17 @@
</span><span class="cx">     case ToThis: {
</span><span class="cx">         AbstractValue&amp; source = forNode(node-&gt;child1());
</span><span class="cx">         AbstractValue&amp; destination = forNode(node);
</span><ins>+        bool strictMode = m_graph.executableFor(node-&gt;origin.semantic)-&gt;isStrictMode();
</ins><span class="cx"> 
</span><del>-        if (source.m_type == SpecStringObject) {
</del><ins>+        if (isToThisAnIdentity(strictMode, source)) {
</ins><span class="cx">             m_state.setFoundConstants(true);
</span><span class="cx">             destination = source;
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (m_graph.executableFor(node-&gt;origin.semantic)-&gt;isStrictMode()) {
-            if (!(source.m_type &amp; ~(SpecFullNumber | SpecBoolean | SpecString | SpecSymbol))) {
-                m_state.setFoundConstants(true);
-                destination = source;
-                break;
-            }
</del><ins>+        if (strictMode)
</ins><span class="cx">             destination.makeHeapTop();
</span><del>-        } else {
</del><ins>+        else {
</ins><span class="cx">             destination = source;
</span><span class="cx">             destination.merge(SpecObject);
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp (200324 => 200325)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp        2016-05-02 16:21:33 UTC (rev 200324)
+++ trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp        2016-05-02 17:38:15 UTC (rev 200325)
</span><span class="lines">@@ -557,6 +557,15 @@
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx"> 
</span><ins>+            case ToThis: {
+                if (!isToThisAnIdentity(m_graph.executableFor(node-&gt;origin.semantic)-&gt;isStrictMode(), m_state.forNode(node-&gt;child1())))
+                    break;
+
+                node-&gt;convertToIdentity();
+                changed = true;
+                break;
+            }
+
</ins><span class="cx">             case Check: {
</span><span class="cx">                 alreadyHandled = true;
</span><span class="cx">                 m_interpreter.execute(indexInBlock);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (200324 => 200325)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-05-02 16:21:33 UTC (rev 200324)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-05-02 17:38:15 UTC (rev 200325)
</span><span class="lines">@@ -1728,6 +1728,9 @@
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        // FIXME: This should cover other use cases but we don't have use kinds for them. It's not critical,
+        // however, since we cover all the missing cases in constant folding.
+        // https://bugs.webkit.org/show_bug.cgi?id=157213
</ins><span class="cx">         if (node-&gt;child1()-&gt;shouldSpeculateStringObject()) {
</span><span class="cx">             fixEdge&lt;StringObjectUse&gt;(node-&gt;child1());
</span><span class="cx">             node-&gt;convertToIdentity();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresstothisglobalobjectjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/to-this-global-object.js (0 => 200325)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/to-this-global-object.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/to-this-global-object.js        2016-05-02 17:38:15 UTC (rev 200325)
</span><span class="lines">@@ -0,0 +1,25 @@
</span><ins>+function test() {
+    return this.f;
+}
+noInline(test);
+
+function test2() {
+    &quot;use strict&quot;;
+    return this.f;
+}
+noInline(test2);
+
+f = 42;
+
+let get = eval;
+let global = get(&quot;this&quot;);
+
+for (var i = 0; i &lt; 10000; ++i) {
+    let result = test.call(global);
+    if (result !== 42)
+        throw new Error(&quot;bad this value: &quot; + result);
+
+    result = test2.call(global);
+    if (result !== 42)
+        throw new Error(&quot;bad this value: &quot; + result);
+}
</ins></span></pre>
</div>
</div>

</body>
</html>