<!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>[214028] trunk</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/214028">214028</a></dd>
<dt>Author</dt> <dd>utatane.tea@gmail.com</dd>
<dt>Date</dt> <dd>2017-03-15 21:49:47 -0700 (Wed, 15 Mar 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>[DFG] ToString operation should have fixup for primitives to say this node does not have side effects
https://bugs.webkit.org/show_bug.cgi?id=169544

Reviewed by Saam Barati.

JSTests:

* microbenchmarks/template-string-array.js: Added.
(test):
* stress/to-string-non-cell-use.js: Added.
(shouldBe):
(shouldThrow):

Source/JavaScriptCore:

Our DFG ToString only considers well about String operands. While ToString(non cell operand) does not have
any side effect, it is not modeled well in DFG.

This patch introduces a fixup for ToString with NonCellUse edge. If this edge is set, ToString does not
clobber things (like ToLowerCase, producing String). And ToString(NonCellUse) allows us to perform CSE!

Our microbenchmark shows 32.9% improvement due to dropped GetButterfly and CSE for ToString().

                                    baseline                  patched

    template-string-array       12.6284+-0.2766     ^      9.4998+-0.2295        ^ definitely 1.3293x faster

And SixSpeed template_string.es6 shows 16.68x performance improvement due to LICM onto this non-side-effectful ToString().

                                  baseline                  patched

    template_string.es6     3229.7343+-40.5705    ^    193.6077+-36.3349       ^ definitely 16.6818x faster

* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupToStringOrCallStringConstructor):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileToStringOrCallStringConstructorOnCell):
(JSC::DFG::SpeculativeJIT::speculateNotCell):
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileToStringOrCallStringConstructor):
(JSC::FTL::DFG::LowerDFGToB3::lowNotCell):
(JSC::FTL::DFG::LowerDFGToB3::speculateNotCell):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<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="#trunkSourceJavaScriptCoredfgDFGClobberizeh">trunk/Source/JavaScriptCore/dfg/DFGClobberize.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITh">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestsmicrobenchmarkstemplatestringarrayjs">trunk/JSTests/microbenchmarks/template-string-array.js</a></li>
<li><a href="#trunkJSTestsstresstostringnoncellusejs">trunk/JSTests/stress/to-string-non-cell-use.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (214027 => 214028)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2017-03-16 04:10:53 UTC (rev 214027)
+++ trunk/JSTests/ChangeLog        2017-03-16 04:49:47 UTC (rev 214028)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2017-03-15  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
+
+        [DFG] ToString operation should have fixup for primitives to say this node does not have side effects
+        https://bugs.webkit.org/show_bug.cgi?id=169544
+
+        Reviewed by Saam Barati.
+
+        * microbenchmarks/template-string-array.js: Added.
+        (test):
+        * stress/to-string-non-cell-use.js: Added.
+        (shouldBe):
+        (shouldThrow):
+
</ins><span class="cx"> 2017-03-13  Commit Queue  &lt;commit-queue@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, rolling out r213856.
</span></span></pre></div>
<a id="trunkJSTestsmicrobenchmarkstemplatestringarrayjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/microbenchmarks/template-string-array.js (0 => 214028)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/microbenchmarks/template-string-array.js                                (rev 0)
+++ trunk/JSTests/microbenchmarks/template-string-array.js        2017-03-16 04:49:47 UTC (rev 214028)
</span><span class="lines">@@ -0,0 +1,9 @@
</span><ins>+var array = [1, 2, 3];
+function test()
+{
+    return `${array[0]}, ${array[1]}, ${array[2]}, ${array[0]}, ${array[1]}, ${array[2]}`;
+}
+noInline(test);
+
+for (var i = 0; i &lt; 1e5; ++i)
+    test();
</ins></span></pre></div>
<a id="trunkJSTestsstresstostringnoncellusejs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/to-string-non-cell-use.js (0 => 214028)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/to-string-non-cell-use.js                                (rev 0)
+++ trunk/JSTests/stress/to-string-non-cell-use.js        2017-03-16 04:49:47 UTC (rev 214028)
</span><span class="lines">@@ -0,0 +1,43 @@
</span><ins>+function shouldBe(actual, expected)
+{
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function shouldThrow(func, errorMessage)
+{
+    var errorThrown = false;
+    var error = null;
+    try {
+        func();
+    } catch (e) {
+        errorThrown = true;
+        error = e;
+    }
+    if (!errorThrown)
+        throw new Error('not thrown');
+    if (String(error) !== errorMessage)
+        throw new Error(`bad error: ${String(error)}`);
+}
+
+function toString(value)
+{
+    return `${value}`;
+}
+noInline(toString);
+
+for (var i = 0; i &lt; 1e4; ++i) {
+    shouldBe(toString(i), i + &quot;&quot;);
+    shouldBe(toString(null), &quot;null&quot;);
+    shouldBe(toString(undefined), &quot;undefined&quot;);
+    shouldBe(toString(10.5), &quot;10.5&quot;);
+    shouldBe(toString(-10.5), &quot;-10.5&quot;);
+    shouldBe(toString(true), &quot;true&quot;);
+    shouldBe(toString(false), &quot;false&quot;);
+    shouldBe(toString(0 / 0), &quot;NaN&quot;);
+}
+
+shouldBe(toString(&quot;HELLO&quot;), &quot;HELLO&quot;);
+shouldThrow(() =&gt; {
+    toString(Symbol(&quot;Cocoa&quot;));
+}, `TypeError: Cannot convert a symbol to a string`);
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (214027 => 214028)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2017-03-16 04:10:53 UTC (rev 214027)
+++ trunk/Source/JavaScriptCore/ChangeLog        2017-03-16 04:49:47 UTC (rev 214028)
</span><span class="lines">@@ -1,3 +1,47 @@
</span><ins>+2017-03-15  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
+
+        [DFG] ToString operation should have fixup for primitives to say this node does not have side effects
+        https://bugs.webkit.org/show_bug.cgi?id=169544
+
+        Reviewed by Saam Barati.
+
+        Our DFG ToString only considers well about String operands. While ToString(non cell operand) does not have
+        any side effect, it is not modeled well in DFG.
+
+        This patch introduces a fixup for ToString with NonCellUse edge. If this edge is set, ToString does not
+        clobber things (like ToLowerCase, producing String). And ToString(NonCellUse) allows us to perform CSE!
+
+        Our microbenchmark shows 32.9% improvement due to dropped GetButterfly and CSE for ToString().
+
+                                            baseline                  patched
+
+            template-string-array       12.6284+-0.2766     ^      9.4998+-0.2295        ^ definitely 1.3293x faster
+
+        And SixSpeed template_string.es6 shows 16.68x performance improvement due to LICM onto this non-side-effectful ToString().
+
+                                          baseline                  patched
+
+            template_string.es6     3229.7343+-40.5705    ^    193.6077+-36.3349       ^ definitely 16.6818x faster
+
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupToStringOrCallStringConstructor):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileToStringOrCallStringConstructorOnCell):
+        (JSC::DFG::SpeculativeJIT::speculateNotCell):
+        * dfg/DFGSpeculativeJIT.h:
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileToStringOrCallStringConstructor):
+        (JSC::FTL::DFG::LowerDFGToB3::lowNotCell):
+        (JSC::FTL::DFG::LowerDFGToB3::speculateNotCell):
+
</ins><span class="cx"> 2017-03-15  Ryan Haddad  &lt;ryanhaddad@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Revert part of r213978 to see if it resolves LayoutTest crashes.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (214027 => 214028)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2017-03-16 04:10:53 UTC (rev 214027)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2017-03-16 04:49:47 UTC (rev 214028)
</span><span class="lines">@@ -1858,6 +1858,7 @@
</span><span class="cx">                 m_graph.registerStructure(m_graph.globalObjectFor(node-&gt;origin.semantic)-&gt;stringObjectStructure()));
</span><span class="cx">             break;
</span><span class="cx">         case StringOrStringObjectUse:
</span><ins>+        case NotCellUse:
</ins><span class="cx">             break;
</span><span class="cx">         case CellUse:
</span><span class="cx">         case UntypedUse:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.h (214027 => 214028)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2017-03-16 04:10:53 UTC (rev 214027)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2017-03-16 04:49:47 UTC (rev 214028)
</span><span class="lines">@@ -1408,6 +1408,10 @@
</span><span class="cx">             read(World);
</span><span class="cx">             write(Heap);
</span><span class="cx">             return;
</span><ins>+
+        case NotCellUse:
+            def(PureValue(node));
+            return;
</ins><span class="cx">             
</span><span class="cx">         default:
</span><span class="cx">             RELEASE_ASSERT_NOT_REACHED();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (214027 => 214028)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2017-03-16 04:10:53 UTC (rev 214027)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2017-03-16 04:49:47 UTC (rev 214028)
</span><span class="lines">@@ -2235,6 +2235,16 @@
</span><span class="cx">             fixEdge&lt;CellUse&gt;(node-&gt;child1());
</span><span class="cx">             return;
</span><span class="cx">         }
</span><ins>+
+        // ToString(Symbol) throws an error. So if the child1 can include Symbols,
+        // we need to care about it in the clobberize. In the following case,
+        // since NotCellUse edge filter is used and this edge filters Symbols,
+        // we can say that ToString never throws an error!
+        if (node-&gt;child1()-&gt;shouldSpeculateNotCell()) {
+            fixEdge&lt;NotCellUse&gt;(node-&gt;child1());
+            node-&gt;clearFlags(NodeMustGenerate);
+            return;
+        }
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     bool attemptToMakeFastStringAdd(Node* node)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (214027 => 214028)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2017-03-16 04:10:53 UTC (rev 214027)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2017-03-16 04:49:47 UTC (rev 214028)
</span><span class="lines">@@ -7925,6 +7925,61 @@
</span><span class="cx"> 
</span><span class="cx"> void SpeculativeJIT::compileToStringOrCallStringConstructorOnCell(Node* node)
</span><span class="cx"> {
</span><ins>+    if (node-&gt;child1().useKind() == NotCellUse) {
+        JSValueOperand op1(this, node-&gt;child1(), ManualOperandSpeculation);
+        JSValueRegs op1Regs = op1.jsValueRegs();
+
+        GPRFlushedCallResult result(this);
+        GPRReg resultGPR = result.gpr();
+
+        speculateNotCell(node-&gt;child1(), op1Regs);
+
+        flushRegisters();
+
+        if (node-&gt;op() == ToString)
+            callOperation(operationToString, resultGPR, op1Regs);
+        else {
+            ASSERT(node-&gt;op() == CallStringConstructor);
+            callOperation(operationCallStringConstructor, resultGPR, op1Regs);
+        }
+        m_jit.exceptionCheck();
+        cellResult(resultGPR, node);
+        return;
+    }
+
+    if (node-&gt;child1().useKind() == UntypedUse) {
+        JSValueOperand op1(this, node-&gt;child1());
+        JSValueRegs op1Regs = op1.jsValueRegs();
+        GPRReg op1PayloadGPR = op1Regs.payloadGPR();
+
+        GPRFlushedCallResult result(this);
+        GPRReg resultGPR = result.gpr();
+
+        flushRegisters();
+
+        JITCompiler::Jump done;
+        if (node-&gt;child1()-&gt;prediction() &amp; SpecString) {
+            JITCompiler::Jump slowPath1 = m_jit.branchIfNotCell(op1.jsValueRegs());
+            JITCompiler::Jump slowPath2 = m_jit.branchIfNotString(op1PayloadGPR);
+            m_jit.move(op1PayloadGPR, resultGPR);
+            done = m_jit.jump();
+            slowPath1.link(&amp;m_jit);
+            slowPath2.link(&amp;m_jit);
+        }
+        if (node-&gt;op() == ToString)
+            callOperation(operationToString, resultGPR, op1Regs);
+        else {
+            ASSERT(node-&gt;op() == CallStringConstructor);
+            callOperation(operationCallStringConstructor, resultGPR, op1Regs);
+        }
+        m_jit.exceptionCheck();
+        if (done.isSet())
+            done.link(&amp;m_jit);
+        cellResult(resultGPR, node);
+        return;
+    }
+
+
</ins><span class="cx">     SpeculateCellOperand op1(this, node-&gt;child1());
</span><span class="cx">     GPRReg op1GPR = op1.gpr();
</span><span class="cx">     
</span><span class="lines">@@ -8533,6 +8588,11 @@
</span><span class="cx">     speculateSymbol(edge, operand.gpr());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SpeculativeJIT::speculateNotCell(Edge edge, JSValueRegs regs)
+{
+    DFG_TYPE_CHECK(regs, edge, ~SpecCell, m_jit.branchIfCell(regs));
+}
+
</ins><span class="cx"> void SpeculativeJIT::speculateNotCell(Edge edge)
</span><span class="cx"> {
</span><span class="cx">     if (!needsTypeCheck(edge, ~SpecCell))
</span><span class="lines">@@ -8539,7 +8599,7 @@
</span><span class="cx">         return;
</span><span class="cx">     
</span><span class="cx">     JSValueOperand operand(this, edge, ManualOperandSpeculation); 
</span><del>-    typeCheck(operand.jsValueRegs(), edge, ~SpecCell, m_jit.branchIfCell(operand.jsValueRegs()));
</del><ins>+    speculateNotCell(edge, operand.jsValueRegs());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SpeculativeJIT::speculateOther(Edge edge)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (214027 => 214028)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2017-03-16 04:10:53 UTC (rev 214027)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2017-03-16 04:49:47 UTC (rev 214028)
</span><span class="lines">@@ -1644,6 +1644,11 @@
</span><span class="cx">         m_jit.setupArgumentsWithExecState(arg1);
</span><span class="cx">         return appendCallSetResult(operation, result);
</span><span class="cx">     }
</span><ins>+    JITCompiler::Call callOperation(C_JITOperation_EJ operation, GPRReg result, JSValueRegs arg1)
+    {
+        m_jit.setupArgumentsWithExecState(arg1.gpr());
+        return appendCallSetResult(operation, result);
+    }
</ins><span class="cx">     JITCompiler::Call callOperation(C_JITOperation_EJJ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
</span><span class="cx">     {
</span><span class="cx">         m_jit.setupArgumentsWithExecState(arg1, arg2);
</span><span class="lines">@@ -2954,6 +2959,7 @@
</span><span class="cx">     void speculateStringOrStringObject(Edge);
</span><span class="cx">     void speculateSymbol(Edge, GPRReg cell);
</span><span class="cx">     void speculateSymbol(Edge);
</span><ins>+    void speculateNotCell(Edge, JSValueRegs);
</ins><span class="cx">     void speculateNotCell(Edge);
</span><span class="cx">     void speculateOther(Edge);
</span><span class="cx">     void speculateMisc(Edge, JSValueRegs);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (214027 => 214028)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2017-03-16 04:10:53 UTC (rev 214027)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2017-03-16 04:49:47 UTC (rev 214028)
</span><span class="lines">@@ -3769,38 +3769,6 @@
</span><span class="cx">         
</span><span class="cx">     case ToString:
</span><span class="cx">     case CallStringConstructor: {
</span><del>-        if (node-&gt;child1().useKind() == UntypedUse) {
-            JSValueOperand op1(this, node-&gt;child1());
-            GPRReg op1PayloadGPR = op1.payloadGPR();
-            JSValueRegs op1Regs = op1.jsValueRegs();
-            
-            GPRFlushedCallResult result(this);
-            GPRReg resultGPR = result.gpr();
-            
-            flushRegisters();
-            
-            JITCompiler::Jump done;
-            if (node-&gt;child1()-&gt;prediction() &amp; SpecString) {
-                JITCompiler::Jump slowPath1 = m_jit.branchIfNotCell(op1.jsValueRegs());
-                JITCompiler::Jump slowPath2 = m_jit.branchIfNotString(op1PayloadGPR);
-                m_jit.move(op1PayloadGPR, resultGPR);
-                done = m_jit.jump();
-                slowPath1.link(&amp;m_jit);
-                slowPath2.link(&amp;m_jit);
-            }
-            if (op == ToString)
-                callOperation(operationToString, resultGPR, op1Regs);
-            else {
-                ASSERT(op == CallStringConstructor);
-                callOperation(operationCallStringConstructor, resultGPR, op1Regs);
-            }
-            m_jit.exceptionCheck();
-            if (done.isSet())
-                done.link(&amp;m_jit);
-            cellResult(resultGPR, node);
-            break;
-        }
-        
</del><span class="cx">         compileToStringOrCallStringConstructorOnCell(node);
</span><span class="cx">         break;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (214027 => 214028)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2017-03-16 04:10:53 UTC (rev 214027)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2017-03-16 04:49:47 UTC (rev 214028)
</span><span class="lines">@@ -3739,37 +3739,6 @@
</span><span class="cx">         
</span><span class="cx">     case ToString:
</span><span class="cx">     case CallStringConstructor: {
</span><del>-        if (node-&gt;child1().useKind() == UntypedUse) {
-            JSValueOperand op1(this, node-&gt;child1());
-            GPRReg op1GPR = op1.gpr();
-            
-            GPRFlushedCallResult result(this);
-            GPRReg resultGPR = result.gpr();
-            
-            flushRegisters();
-            
-            JITCompiler::Jump done;
-            if (node-&gt;child1()-&gt;prediction() &amp; SpecString) {
-                JITCompiler::Jump slowPath1 = m_jit.branchIfNotCell(JSValueRegs(op1GPR));
-                JITCompiler::Jump slowPath2 = m_jit.branchIfNotString(op1GPR);
-                m_jit.move(op1GPR, resultGPR);
-                done = m_jit.jump();
-                slowPath1.link(&amp;m_jit);
-                slowPath2.link(&amp;m_jit);
-            }
-            if (op == ToString)
-                callOperation(operationToString, resultGPR, op1GPR);
-            else {
-                ASSERT(op == CallStringConstructor);
-                callOperation(operationCallStringConstructor, resultGPR, op1GPR);
-            }
-            m_jit.exceptionCheck();
-            if (done.isSet())
-                done.link(&amp;m_jit);
-            cellResult(resultGPR, node);
-            break;
-        }
-        
</del><span class="cx">         compileToStringOrCallStringConstructorOnCell(node);
</span><span class="cx">         break;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (214027 => 214028)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2017-03-16 04:10:53 UTC (rev 214027)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2017-03-16 04:49:47 UTC (rev 214028)
</span><span class="lines">@@ -4933,10 +4933,13 @@
</span><span class="cx">         }
</span><span class="cx">             
</span><span class="cx">         case CellUse:
</span><ins>+        case NotCellUse:
</ins><span class="cx">         case UntypedUse: {
</span><span class="cx">             LValue value;
</span><span class="cx">             if (m_node-&gt;child1().useKind() == CellUse)
</span><span class="cx">                 value = lowCell(m_node-&gt;child1());
</span><ins>+            else if (m_node-&gt;child1().useKind() == NotCellUse)
+                value = lowNotCell(m_node-&gt;child1());
</ins><span class="cx">             else
</span><span class="cx">                 value = lowJSValue(m_node-&gt;child1());
</span><span class="cx">             
</span><span class="lines">@@ -4947,6 +4950,8 @@
</span><span class="cx">             LValue isCellPredicate;
</span><span class="cx">             if (m_node-&gt;child1().useKind() == CellUse)
</span><span class="cx">                 isCellPredicate = m_out.booleanTrue;
</span><ins>+            else if (m_node-&gt;child1().useKind() == NotCellUse)
+                isCellPredicate = m_out.booleanFalse;
</ins><span class="cx">             else
</span><span class="cx">                 isCellPredicate = this-&gt;isCell(value, provenType(m_node-&gt;child1()));
</span><span class="cx">             m_out.branch(isCellPredicate, unsure(isCell), unsure(notString));
</span><span class="lines">@@ -12228,6 +12233,13 @@
</span><span class="cx">         DFG_CRASH(m_graph, m_node, &quot;Value not defined&quot;);
</span><span class="cx">         return 0;
</span><span class="cx">     }
</span><ins>+
+    LValue lowNotCell(Edge edge)
+    {
+        LValue result = lowJSValue(edge, ManualOperandSpeculation);
+        FTL_TYPE_CHECK(jsValueValue(result), edge, ~SpecCell, isCell(result));
+        return result;
+    }
</ins><span class="cx">     
</span><span class="cx">     LValue lowStorage(Edge edge)
</span><span class="cx">     {
</span><span class="lines">@@ -12632,6 +12644,13 @@
</span><span class="cx">     {
</span><span class="cx">         lowCell(edge);
</span><span class="cx">     }
</span><ins>+
+    void speculateNotCell(Edge edge)
+    {
+        if (!m_interpreter.needsTypeCheck(edge))
+            return;
+        lowNotCell(edge);
+    }
</ins><span class="cx">     
</span><span class="cx">     void speculateCellOrOther(Edge edge)
</span><span class="cx">     {
</span><span class="lines">@@ -13150,15 +13169,6 @@
</span><span class="cx">         m_out.appendTo(continuation, lastNext);
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    void speculateNotCell(Edge edge)
-    {
-        if (!m_interpreter.needsTypeCheck(edge))
-            return;
-        
-        LValue value = lowJSValue(edge, ManualOperandSpeculation);
-        typeCheck(jsValueValue(value), edge, ~SpecCell, isCell(value));
-    }
-    
</del><span class="cx">     void speculateOther(Edge edge)
</span><span class="cx">     {
</span><span class="cx">         if (!m_interpreter.needsTypeCheck(edge))
</span></span></pre>
</div>
</div>

</body>
</html>