<!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>[204995] 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/204995">204995</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2016-08-25 16:02:52 -0700 (Thu, 25 Aug 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>[JSC] Clean up the abstract interpreter for cos/sin/sqrt/fround/log
https://bugs.webkit.org/show_bug.cgi?id=161181

Patch by Benjamin Poulain &lt;bpoulain@apple.com&gt; on 2016-08-25
Reviewed by Geoffrey Garen.

JSTests:

Extend the tests to constants.
Add no-argument cases where needed.

* stress/arith-cos-on-various-types.js:
* stress/arith-fround-on-various-types.js:
* stress/arith-log-on-various-types.js:
* stress/arith-sin-on-various-types.js:
* stress/arith-sqrt-on-various-types.js:

Source/JavaScriptCore:

All the nodes are doing the exact same thing with a single
difference: how to process constants. I made that into a separate
function called from each node.

I also generalized the constant-to-number code of DoubleRep
to make it available for all those nodes.

* dfg/DFGAbstractInterpreter.h:
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
(JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeDoubleUnaryOpEffects):
* runtime/JSCJSValue.cpp:
(JSC::JSValue::toNumberFromPrimitive):
* runtime/JSCJSValue.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkJSTestsstressarithcosonvarioustypesjs">trunk/JSTests/stress/arith-cos-on-various-types.js</a></li>
<li><a href="#trunkJSTestsstressarithfroundonvarioustypesjs">trunk/JSTests/stress/arith-fround-on-various-types.js</a></li>
<li><a href="#trunkJSTestsstressarithlogonvarioustypesjs">trunk/JSTests/stress/arith-log-on-various-types.js</a></li>
<li><a href="#trunkJSTestsstressarithsinonvarioustypesjs">trunk/JSTests/stress/arith-sin-on-various-types.js</a></li>
<li><a href="#trunkJSTestsstressarithsqrtonvarioustypesjs">trunk/JSTests/stress/arith-sqrt-on-various-types.js</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSCJSValuecpp">trunk/Source/JavaScriptCore/runtime/JSCJSValue.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSCJSValueh">trunk/Source/JavaScriptCore/runtime/JSCJSValue.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (204994 => 204995)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2016-08-25 22:55:10 UTC (rev 204994)
+++ trunk/JSTests/ChangeLog        2016-08-25 23:02:52 UTC (rev 204995)
</span><span class="lines">@@ -1,3 +1,19 @@
</span><ins>+2016-08-25  Benjamin Poulain  &lt;bpoulain@apple.com&gt;
+
+        [JSC] Clean up the abstract interpreter for cos/sin/sqrt/fround/log
+        https://bugs.webkit.org/show_bug.cgi?id=161181
+
+        Reviewed by Geoffrey Garen.
+
+        Extend the tests to constants.
+        Add no-argument cases where needed.
+
+        * stress/arith-cos-on-various-types.js:
+        * stress/arith-fround-on-various-types.js:
+        * stress/arith-log-on-various-types.js:
+        * stress/arith-sin-on-various-types.js:
+        * stress/arith-sqrt-on-various-types.js:
+
</ins><span class="cx"> 2016-08-25  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [DFG][FTL] Implement ES6 Generators in DFG / FTL
</span></span></pre></div>
<a id="trunkJSTestsstressarithcosonvarioustypesjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/stress/arith-cos-on-various-types.js (204994 => 204995)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/arith-cos-on-various-types.js        2016-08-25 22:55:10 UTC (rev 204994)
+++ trunk/JSTests/stress/arith-cos-on-various-types.js        2016-08-25 23:02:52 UTC (rev 204995)
</span><span class="lines">@@ -34,6 +34,26 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+// Test Math.cos() without arguments.
+function opaqueCosNoArgument() {
+    return Math.cos();
+}
+noInline(opaqueCosNoArgument);
+noOSRExitFuzzing(opaqueCosNoArgument);
+
+function testNoArgument() {
+    for (let i = 0; i &lt; 1e4; ++i) {
+        let output = opaqueCosNoArgument();
+        if (output === output) {
+            throw &quot;Failed opaqueCosNoArgument&quot;;
+        }
+    }
+    if (numberOfDFGCompiles(opaqueCosNoArgument) &gt; 1)
+        throw &quot;The call without arguments should never exit.&quot;;
+}
+testNoArgument();
+
+
</ins><span class="cx"> // Test Math.cos() with a very polymorphic input. All test cases are seen at each iteration.
</span><span class="cx"> function opaqueAllTypesCos(argument) {
</span><span class="cx">     return Math.cos(argument);
</span><span class="lines">@@ -78,6 +98,29 @@
</span><span class="cx"> testSingleTypeCall();
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+// Test Math.cos() on constants
+function testConstant() {
+    for (let testCaseInput of validInputTestCases) {
+        eval(`
+            function opaqueCosOnConstant() {
+                return Math.cos(${testCaseInput[0]});
+            }
+            noInline(opaqueCosOnConstant);
+            noOSRExitFuzzing(opaqueCosOnConstant);
+
+            for (let i = 0; i &lt; 1e4; ++i) {
+                if (!isIdentical(opaqueCosOnConstant(), ${testCaseInput[1]})) {
+                    throw &quot;Failed testConstant()&quot;;
+                }
+            }
+            if (numberOfDFGCompiles(opaqueCosOnConstant) &gt; 1)
+                throw &quot;We should have compiled a single cos for the expected type.&quot;;
+        `);
+    }
+}
+testConstant();
+
+
</ins><span class="cx"> // Verify we call valueOf() exactly once per call.
</span><span class="cx"> function opaqueCosForSideEffects(argument) {
</span><span class="cx">     return Math.cos(argument);
</span></span></pre></div>
<a id="trunkJSTestsstressarithfroundonvarioustypesjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/stress/arith-fround-on-various-types.js (204994 => 204995)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/arith-fround-on-various-types.js        2016-08-25 22:55:10 UTC (rev 204994)
+++ trunk/JSTests/stress/arith-fround-on-various-types.js        2016-08-25 23:02:52 UTC (rev 204995)
</span><span class="lines">@@ -100,6 +100,29 @@
</span><span class="cx"> testSingleTypeCall();
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+// Test Math.fround() on constants
+function testConstant() {
+    for (let testCaseInput of validInputTestCases) {
+        eval(`
+            function opaqueFroundOnConstant() {
+                return Math.fround(${testCaseInput[0]});
+            }
+            noInline(opaqueFroundOnConstant);
+            noOSRExitFuzzing(opaqueFroundOnConstant);
+
+            for (let i = 0; i &lt; 1e4; ++i) {
+                if (!isIdentical(opaqueFroundOnConstant(), ${testCaseInput[1]})) {
+                    throw &quot;Failed testConstant()&quot;;
+                }
+            }
+            if (numberOfDFGCompiles(opaqueFroundOnConstant) &gt; 1)
+                throw &quot;We should have compiled a single fround for the expected type.&quot;;
+        `);
+    }
+}
+testConstant();
+
+
</ins><span class="cx"> // Verify we call valueOf() exactly once per call.
</span><span class="cx"> function opaqueFroundForSideEffects(argument) {
</span><span class="cx">     return Math.fround(argument);
</span></span></pre></div>
<a id="trunkJSTestsstressarithlogonvarioustypesjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/stress/arith-log-on-various-types.js (204994 => 204995)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/arith-log-on-various-types.js        2016-08-25 22:55:10 UTC (rev 204994)
+++ trunk/JSTests/stress/arith-log-on-various-types.js        2016-08-25 23:02:52 UTC (rev 204995)
</span><span class="lines">@@ -37,6 +37,26 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+// Test Math.log() without arguments.
+function opaqueLogNoArgument() {
+    return Math.log();
+}
+noInline(opaqueLogNoArgument);
+noOSRExitFuzzing(opaqueLogNoArgument);
+
+function testNoArgument() {
+    for (let i = 0; i &lt; 1e4; ++i) {
+        let output = opaqueLogNoArgument();
+        if (output === output) {
+            throw &quot;Failed opaqueLogNoArgument&quot;;
+        }
+    }
+    if (numberOfDFGCompiles(opaqueLogNoArgument) &gt; 1)
+        throw &quot;The call without arguments should never exit.&quot;;
+}
+testNoArgument();
+
+
</ins><span class="cx"> // Test Math.log() with a very polymorphic input. All test cases are seen at each iteration.
</span><span class="cx"> function opaqueAllTypesLog(argument) {
</span><span class="cx">     return Math.log(argument);
</span><span class="lines">@@ -81,6 +101,29 @@
</span><span class="cx"> testSingleTypeCall();
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+// Test Math.log() on constants
+function testConstant() {
+    for (let testCaseInput of validInputTestCases) {
+        eval(`
+            function opaqueLogOnConstant() {
+                return Math.log(${testCaseInput[0]});
+            }
+            noInline(opaqueLogOnConstant);
+            noOSRExitFuzzing(opaqueLogOnConstant);
+
+            for (let i = 0; i &lt; 1e4; ++i) {
+                if (!isIdentical(opaqueLogOnConstant(), ${testCaseInput[1]})) {
+                    throw &quot;Failed testConstant()&quot;;
+                }
+            }
+            if (numberOfDFGCompiles(opaqueLogOnConstant) &gt; 1)
+                throw &quot;We should have compiled a single log for the expected type.&quot;;
+        `);
+    }
+}
+testConstant();
+
+
</ins><span class="cx"> // Verify we call valueOf() exactly once per call.
</span><span class="cx"> function opaqueLogForSideEffects(argument) {
</span><span class="cx">     return Math.log(argument);
</span></span></pre></div>
<a id="trunkJSTestsstressarithsinonvarioustypesjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/stress/arith-sin-on-various-types.js (204994 => 204995)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/arith-sin-on-various-types.js        2016-08-25 22:55:10 UTC (rev 204994)
+++ trunk/JSTests/stress/arith-sin-on-various-types.js        2016-08-25 23:02:52 UTC (rev 204995)
</span><span class="lines">@@ -34,6 +34,26 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+// Test Math.sin() without arguments.
+function opaqueSinNoArgument() {
+    return Math.sin();
+}
+noInline(opaqueSinNoArgument);
+noOSRExitFuzzing(opaqueSinNoArgument);
+
+function testNoArgument() {
+    for (let i = 0; i &lt; 1e4; ++i) {
+        let output = opaqueSinNoArgument();
+        if (output === output) {
+            throw &quot;Failed opaqueSinNoArgument&quot;;
+        }
+    }
+    if (numberOfDFGCompiles(opaqueSinNoArgument) &gt; 1)
+        throw &quot;The call without arguments should never exit.&quot;;
+}
+testNoArgument();
+
+
</ins><span class="cx"> // Test Math.sin() with a very polymorphic input. All test cases are seen at each iteration.
</span><span class="cx"> function opaqueAllTypesSin(argument) {
</span><span class="cx">     return Math.sin(argument);
</span><span class="lines">@@ -78,6 +98,29 @@
</span><span class="cx"> testSingleTypeCall();
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+// Test Math.sin() on constants
+function testConstant() {
+    for (let testCaseInput of validInputTestCases) {
+        eval(`
+            function opaqueSinOnConstant() {
+                return Math.sin(${testCaseInput[0]});
+            }
+            noInline(opaqueSinOnConstant);
+            noOSRExitFuzzing(opaqueSinOnConstant);
+
+            for (let i = 0; i &lt; 1e4; ++i) {
+                if (!isIdentical(opaqueSinOnConstant(), ${testCaseInput[1]})) {
+                    throw &quot;Failed testConstant()&quot;;
+                }
+            }
+            if (numberOfDFGCompiles(opaqueSinOnConstant) &gt; 1)
+                throw &quot;We should have compiled a single sin for the expected type.&quot;;
+        `);
+    }
+}
+testConstant();
+
+
</ins><span class="cx"> // Verify we call valueOf() exactly once per call.
</span><span class="cx"> function opaqueSinForSideEffects(argument) {
</span><span class="cx">     return Math.sin(argument);
</span></span></pre></div>
<a id="trunkJSTestsstressarithsqrtonvarioustypesjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/stress/arith-sqrt-on-various-types.js (204994 => 204995)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/arith-sqrt-on-various-types.js        2016-08-25 22:55:10 UTC (rev 204994)
+++ trunk/JSTests/stress/arith-sqrt-on-various-types.js        2016-08-25 23:02:52 UTC (rev 204995)
</span><span class="lines">@@ -32,6 +32,26 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+// Test Math.sqrt() without arguments.
+function opaqueSqrtNoArgument() {
+    return Math.sqrt();
+}
+noInline(opaqueSqrtNoArgument);
+noOSRExitFuzzing(opaqueSqrtNoArgument);
+
+function testNoArgument() {
+    for (let i = 0; i &lt; 1e4; ++i) {
+        let output = opaqueSqrtNoArgument();
+        if (output === output) {
+            throw &quot;Failed opaqueSqrtNoArgument&quot;;
+        }
+    }
+    if (numberOfDFGCompiles(opaqueSqrtNoArgument) &gt; 1)
+        throw &quot;The call without arguments should never exit.&quot;;
+}
+testNoArgument();
+
+
</ins><span class="cx"> // Test Math.sqrt() with a very polymorphic input. All test cases are seen at each iteration.
</span><span class="cx"> function opaqueAllTypesSqrt(argument) {
</span><span class="cx">     return Math.sqrt(argument);
</span><span class="lines">@@ -76,6 +96,29 @@
</span><span class="cx"> testSingleTypeCall();
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+// Test Math.sqrt() on constants
+function testConstant() {
+    for (let testCaseInput of validInputTestCases) {
+        eval(`
+            function opaqueSqrtOnConstant() {
+                return Math.sqrt(${testCaseInput[0]});
+            }
+            noInline(opaqueSqrtOnConstant);
+            noOSRExitFuzzing(opaqueSqrtOnConstant);
+
+            for (let i = 0; i &lt; 1e4; ++i) {
+                if (!isIdentical(opaqueSqrtOnConstant(), ${testCaseInput[1]})) {
+                    throw &quot;Failed testConstant()&quot;;
+                }
+            }
+            if (numberOfDFGCompiles(opaqueSqrtOnConstant) &gt; 1)
+                throw &quot;We should have compiled a single sqrt for the expected type.&quot;;
+        `);
+    }
+}
+testConstant();
+
+
</ins><span class="cx"> // Verify we call valueOf() exactly once per call.
</span><span class="cx"> function opaqueSqrtForSideEffects(argument) {
</span><span class="cx">     return Math.sqrt(argument);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (204994 => 204995)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-08-25 22:55:10 UTC (rev 204994)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-08-25 23:02:52 UTC (rev 204995)
</span><span class="lines">@@ -1,3 +1,25 @@
</span><ins>+2016-08-25  Benjamin Poulain  &lt;bpoulain@apple.com&gt;
+
+        [JSC] Clean up the abstract interpreter for cos/sin/sqrt/fround/log
+        https://bugs.webkit.org/show_bug.cgi?id=161181
+
+        Reviewed by Geoffrey Garen.
+
+        All the nodes are doing the exact same thing with a single
+        difference: how to process constants. I made that into a separate
+        function called from each node.
+
+        I also generalized the constant-to-number code of DoubleRep
+        to make it available for all those nodes.
+
+        * dfg/DFGAbstractInterpreter.h:
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
+        (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeDoubleUnaryOpEffects):
+        * runtime/JSCJSValue.cpp:
+        (JSC::JSValue::toNumberFromPrimitive):
+        * runtime/JSCJSValue.h:
+
</ins><span class="cx"> 2016-08-25  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [DFG][FTL] Implement ES6 Generators in DFG / FTL
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h (204994 => 204995)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h        2016-08-25 22:55:10 UTC (rev 204994)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h        2016-08-25 23:02:52 UTC (rev 204995)
</span><span class="lines">@@ -186,6 +186,7 @@
</span><span class="cx">     
</span><span class="cx">     void verifyEdge(Node*, Edge);
</span><span class="cx">     void verifyEdges(Node*);
</span><ins>+    void executeDoubleUnaryOpEffects(Node*, double(*equivalentFunction)(double));
</ins><span class="cx">     
</span><span class="cx">     CodeBlock* m_codeBlock;
</span><span class="cx">     Graph&amp; m_graph;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (204994 => 204995)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-08-25 22:55:10 UTC (rev 204994)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-08-25 23:02:52 UTC (rev 204995)
</span><span class="lines">@@ -433,23 +433,9 @@
</span><span class="cx">         
</span><span class="cx">     case DoubleRep: {
</span><span class="cx">         JSValue child = forNode(node-&gt;child1()).value();
</span><del>-        if (child) {
-            if (child.isNumber()) {
-                setConstant(node, jsDoubleNumber(child.asNumber()));
-                break;
-            }
-            if (child.isUndefined()) {
-                setConstant(node, jsDoubleNumber(PNaN));
-                break;
-            }
-            if (child.isNull() || child.isFalse()) {
-                setConstant(node, jsDoubleNumber(0));
-                break;
-            }
-            if (child.isTrue()) {
-                setConstant(node, jsDoubleNumber(1));
-                break;
-            }
</del><ins>+        if (Optional&lt;double&gt; number = child.toNumberFromPrimitive()) {
+            setConstant(node, jsDoubleNumber(*number));
+            break;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         SpeculatedType type = forNode(node-&gt;child1()).m_type;
</span><span class="lines">@@ -955,70 +941,25 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">             
</span><del>-    case ArithSqrt: {
-        JSValue child = forNode(node-&gt;child1()).value();
-        if (child &amp;&amp; child.isNumber()) {
-            setConstant(node, jsDoubleNumber(sqrt(child.asNumber())));
-            break;
-        }
-        SpeculatedType sqrtType = SpecFullNumber;
-        if (node-&gt;child1().useKind() == DoubleRepUse)
-            sqrtType = typeOfDoubleUnaryOp(forNode(node-&gt;child1()).m_type);
-        forNode(node).setType(sqrtType);
</del><ins>+    case ArithSqrt:
+        executeDoubleUnaryOpEffects(node, sqrt);
</ins><span class="cx">         break;
</span><del>-    }
-        
-    case ArithFRound: {
-        JSValue child = forNode(node-&gt;child1()).value();
-        if (child &amp;&amp; child.isNumber()) {
-            setConstant(node, jsDoubleNumber(static_cast&lt;float&gt;(child.asNumber())));
-            break;
-        }
-        SpeculatedType froundType = SpecFullNumber;
-        if (node-&gt;child1().useKind() == DoubleRepUse)
-            froundType = typeOfDoubleUnaryOp(forNode(node-&gt;child1()).m_type);
-        forNode(node).setType(froundType);
</del><ins>+
+    case ArithFRound:
+        executeDoubleUnaryOpEffects(node, [](double value) -&gt; double { return static_cast&lt;float&gt;(value); });
</ins><span class="cx">         break;
</span><del>-    }
</del><span class="cx">         
</span><del>-    case ArithSin: {
-        JSValue child = forNode(node-&gt;child1()).value();
-        if (child &amp;&amp; child.isNumber()) {
-            setConstant(node, jsDoubleNumber(sin(child.asNumber())));
-            break;
-        }
-        SpeculatedType sinType = SpecFullNumber;
-        if (node-&gt;child1().useKind() == DoubleRepUse)
-            sinType = typeOfDoubleUnaryOp(forNode(node-&gt;child1()).m_type);
-        forNode(node).setType(sinType);
</del><ins>+    case ArithSin:
+        executeDoubleUnaryOpEffects(node, sin);
</ins><span class="cx">         break;
</span><del>-    }
</del><span class="cx">     
</span><del>-    case ArithCos: {
-        JSValue child = forNode(node-&gt;child1()).value();
-        if (child &amp;&amp; child.isNumber()) {
-            setConstant(node, jsDoubleNumber(cos(child.asNumber())));
-            break;
-        }
-        SpeculatedType cosType = SpecFullNumber;
-        if (node-&gt;child1().useKind() == DoubleRepUse)
-            cosType = typeOfDoubleUnaryOp(forNode(node-&gt;child1()).m_type);
-        forNode(node).setType(cosType);
</del><ins>+    case ArithCos:
+        executeDoubleUnaryOpEffects(node, cos);
</ins><span class="cx">         break;
</span><del>-    }
</del><span class="cx"> 
</span><del>-    case ArithLog: {
-        JSValue child = forNode(node-&gt;child1()).value();
-        if (child &amp;&amp; child.isNumber()) {
-            setConstant(node, jsDoubleNumber(log(child.asNumber())));
-            break;
-        }
-        SpeculatedType logType = SpecFullNumber;
-        if (node-&gt;child1().useKind() == DoubleRepUse)
-            logType = typeOfDoubleUnaryOp(forNode(node-&gt;child1()).m_type);
-        forNode(node).setType(logType);
</del><ins>+    case ArithLog:
+        executeDoubleUnaryOpEffects(node, log);
</ins><span class="cx">         break;
</span><del>-    }
</del><span class="cx">             
</span><span class="cx">     case LogicalNot: {
</span><span class="cx">         switch (booleanResult(node, forNode(node-&gt;child1()))) {
</span><span class="lines">@@ -3102,6 +3043,20 @@
</span><span class="cx">     return Contradiction;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template&lt;typename AbstractStateType&gt;
+void AbstractInterpreter&lt;AbstractStateType&gt;::executeDoubleUnaryOpEffects(Node* node, double(*equivalentFunction)(double))
+{
+    JSValue child = forNode(node-&gt;child1()).value();
+    if (Optional&lt;double&gt; number = child.toNumberFromPrimitive()) {
+        setConstant(node, jsDoubleNumber(equivalentFunction(*number)));
+        return;
+    }
+    SpeculatedType type = SpecFullNumber;
+    if (node-&gt;child1().useKind() == DoubleRepUse)
+        type = typeOfDoubleUnaryOp(forNode(node-&gt;child1()).m_type);
+    forNode(node).setType(type);
+}
+
</ins><span class="cx"> } } // namespace JSC::DFG
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(DFG_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSCJSValuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSCJSValue.cpp (204994 => 204995)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSCJSValue.cpp        2016-08-25 22:55:10 UTC (rev 204994)
+++ trunk/Source/JavaScriptCore/runtime/JSCJSValue.cpp        2016-08-25 23:02:52 UTC (rev 204995)
</span><span class="lines">@@ -77,6 +77,21 @@
</span><span class="cx">     return isUndefined() ? PNaN : 0; // null and false both convert to 0.
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Optional&lt;double&gt; JSValue::toNumberFromPrimitive() const
+{
+    if (isEmpty())
+        return Nullopt;
+    if (isNumber())
+        return asNumber();
+    if (isBoolean())
+        return asBoolean();
+    if (isUndefined())
+        return PNaN;
+    if (isNull())
+        return 0;
+    return Nullopt;
+}
+
</ins><span class="cx"> JSObject* JSValue::toObjectSlowCase(ExecState* exec, JSGlobalObject* globalObject) const
</span><span class="cx"> {
</span><span class="cx">     ASSERT(!isCell());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSCJSValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSCJSValue.h (204994 => 204995)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSCJSValue.h        2016-08-25 22:55:10 UTC (rev 204994)
+++ trunk/Source/JavaScriptCore/runtime/JSCJSValue.h        2016-08-25 23:02:52 UTC (rev 204995)
</span><span class="lines">@@ -261,6 +261,10 @@
</span><span class="cx">     // toNumber conversion is expected to be side effect free if an exception has
</span><span class="cx">     // been set in the ExecState already.
</span><span class="cx">     double toNumber(ExecState*) const;
</span><ins>+
+    // toNumber conversion if it can be done without side effects.
+    Optional&lt;double&gt; toNumberFromPrimitive() const;
+
</ins><span class="cx">     JSString* toString(ExecState*) const; // On exception, this returns the empty string.
</span><span class="cx">     JSString* toStringOrNull(ExecState*) const; // On exception, this returns null, to make exception checks faster.
</span><span class="cx">     Identifier toPropertyKey(ExecState*) const;
</span></span></pre>
</div>
</div>

</body>
</html>