<!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>[205828] 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/205828">205828</a></dd>
<dt>Author</dt> <dd>utatane.tea@gmail.com</dd>
<dt>Date</dt> <dd>2016-09-12 15:01:13 -0700 (Mon, 12 Sep 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>[DFG][FTL] Add ArithTan
https://bugs.webkit.org/show_bug.cgi?id=161857

Reviewed by Filip Pizlo.

JSTests:

* microbenchmarks/tan.js: Added.
* stress/arith-tan-on-various-types.js: Added.
(let.validInputTypedTestCases.validInputTestCases.map):
(isIdentical):
(opaqueTanNoArgument):
(testNoArgument):
(opaqueAllTypesTan):
(testAllTypesCall):
(testTangleTypeCall):
(testConstant):
(opaqueTanForSideEffects):
(testSideEffect.let.testObject.valueOf):
(testSideEffect):
(opaqueTanForCSE):
(testCSE.let.testObject.valueOf):
(testCSE):
(opaqueTanForDCE):
(testDCE.let.testObject.valueOf):
(testDCE):
(testException.opaqueTanWithException):
(testException):
* stress/ftl-arithtan.js: Added.
(foo):

Source/JavaScriptCore:

While ArithSin and ArithCos are supported, ArithTan is not supported yet.
And we also find that Math.tan is included in MotionMark's Multiply benchmark.

This patch adds ArithTan support in DFG and FTL. And it also cleans up the
existing ArithSin, ArithCos, and ArithLog compilations by unifying them.
The microbenchmark shows the 9% perf improvement.

    tan    322.4819+-0.3766     ^    295.8700+-0.3094        ^ definitely 1.0899x faster

* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleIntrinsicCall):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGNodeType.h:
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGPredictionPropagationPhase.cpp:
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileArithDoubleUnaryOp):
(JSC::DFG::SpeculativeJIT::compileArithCos):
(JSC::DFG::SpeculativeJIT::compileArithTan):
(JSC::DFG::SpeculativeJIT::compileArithSin):
(JSC::DFG::SpeculativeJIT::compileArithLog):
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileArithTan):
* ftl/FTLOutput.cpp:
(JSC::FTL::Output::doubleTan):
* ftl/FTLOutput.h:
* runtime/Intrinsic.h:
* runtime/MathObject.cpp:
(JSC::MathObject::finishCreation):</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="#trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp">trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGClobberizeh">trunk/Source/JavaScriptCore/dfg/DFGClobberize.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGDoesGCcpp">trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeTypeh">trunk/Source/JavaScriptCore/dfg/DFGNodeType.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationscpp">trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationsh">trunk/Source/JavaScriptCore/dfg/DFGOperations.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSafeToExecuteh">trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h</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="#trunkSourceJavaScriptCoreftlFTLCapabilitiescpp">trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLOutputcpp">trunk/Source/JavaScriptCore/ftl/FTLOutput.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLOutputh">trunk/Source/JavaScriptCore/ftl/FTLOutput.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeIntrinsich">trunk/Source/JavaScriptCore/runtime/Intrinsic.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeMathObjectcpp">trunk/Source/JavaScriptCore/runtime/MathObject.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestsmicrobenchmarkstanjs">trunk/JSTests/microbenchmarks/tan.js</a></li>
<li><a href="#trunkJSTestsstressarithtanonvarioustypesjs">trunk/JSTests/stress/arith-tan-on-various-types.js</a></li>
<li><a href="#trunkJSTestsstressftlarithtanjs">trunk/JSTests/stress/ftl-arithtan.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (205827 => 205828)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2016-09-12 21:46:49 UTC (rev 205827)
+++ trunk/JSTests/ChangeLog        2016-09-12 22:01:13 UTC (rev 205828)
</span><span class="lines">@@ -1,3 +1,34 @@
</span><ins>+2016-09-12  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
+
+        [DFG][FTL] Add ArithTan
+        https://bugs.webkit.org/show_bug.cgi?id=161857
+
+        Reviewed by Filip Pizlo.
+
+        * microbenchmarks/tan.js: Added.
+        * stress/arith-tan-on-various-types.js: Added.
+        (let.validInputTypedTestCases.validInputTestCases.map):
+        (isIdentical):
+        (opaqueTanNoArgument):
+        (testNoArgument):
+        (opaqueAllTypesTan):
+        (testAllTypesCall):
+        (testTangleTypeCall):
+        (testConstant):
+        (opaqueTanForSideEffects):
+        (testSideEffect.let.testObject.valueOf):
+        (testSideEffect):
+        (opaqueTanForCSE):
+        (testCSE.let.testObject.valueOf):
+        (testCSE):
+        (opaqueTanForDCE):
+        (testDCE.let.testObject.valueOf):
+        (testDCE):
+        (testException.opaqueTanWithException):
+        (testException):
+        * stress/ftl-arithtan.js: Added.
+        (foo):
+
</ins><span class="cx"> 2016-09-12  Saam Barati  &lt;sbarati@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         MapHash should do constant folding when it has a constant argument and its legal to hash that value
</span></span></pre></div>
<a id="trunkJSTestsmicrobenchmarkstanjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/microbenchmarks/tan.js (0 => 205828)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/microbenchmarks/tan.js                                (rev 0)
+++ trunk/JSTests/microbenchmarks/tan.js        2016-09-12 22:01:13 UTC (rev 205828)
</span><span class="lines">@@ -0,0 +1,7 @@
</span><ins>+(function() {
+    for (var i = 0; i &lt; 3000000; ++i)
+        x = Math.tan(i);
+
+    if (x != 1.8222665884307354)
+        throw &quot;Error: bad result: &quot; + x;
+})();
</ins></span></pre></div>
<a id="trunkJSTestsstressarithtanonvarioustypesjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/arith-tan-on-various-types.js (0 => 205828)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/arith-tan-on-various-types.js                                (rev 0)
+++ trunk/JSTests/stress/arith-tan-on-various-types.js        2016-09-12 22:01:13 UTC (rev 205828)
</span><span class="lines">@@ -0,0 +1,234 @@
</span><ins>+&quot;use strict&quot;;
+
+let tanOfFour = Math.tan(4);
+
+let validInputTestCases = [
+    // input as string, expected result as string.
+    [&quot;undefined&quot;, &quot;NaN&quot;],
+    [&quot;null&quot;, &quot;0&quot;],
+    [&quot;0&quot;, &quot;0&quot;],
+    [&quot;-0.&quot;, &quot;-0&quot;],
+    [&quot;4&quot;, &quot;&quot; + tanOfFour],
+    [&quot;Math.PI&quot;, &quot;&quot; + Math.tan(Math.PI)],
+    [&quot;Infinity&quot;, &quot;NaN&quot;],
+    [&quot;-Infinity&quot;, &quot;NaN&quot;],
+    [&quot;NaN&quot;, &quot;NaN&quot;],
+    [&quot;\&quot;WebKit\&quot;&quot;, &quot;NaN&quot;],
+    [&quot;\&quot;4\&quot;&quot;, &quot;&quot; + tanOfFour],
+    [&quot;{ valueOf: () =&gt; { return 4; } }&quot;, &quot;&quot; + tanOfFour],
+];
+
+let validInputTypedTestCases = validInputTestCases.map((element) =&gt; { return [eval(&quot;(&quot; + element[0] + &quot;)&quot;), eval(element[1])] });
+
+function isIdentical(result, expected)
+{
+    if (expected === expected) {
+        if (result !== expected)
+            return false;
+        if (!expected &amp;&amp; 1 / expected === -Infinity &amp;&amp; 1 / result !== -Infinity)
+            return false;
+
+        return true;
+    }
+    return result !== result;
+}
+
+
+// Test Math.tan() without arguments.
+function opaqueTanNoArgument() {
+    return Math.tan();
+}
+noInline(opaqueTanNoArgument);
+noOSRExitFuzzing(opaqueTanNoArgument);
+
+function testNoArgument() {
+    for (let i = 0; i &lt; 1e4; ++i) {
+        let output = opaqueTanNoArgument();
+        if (output === output) {
+            throw &quot;Failed opaqueTanNoArgument&quot;;
+        }
+    }
+    if (numberOfDFGCompiles(opaqueTanNoArgument) &gt; 1)
+        throw &quot;The call without arguments should never exit.&quot;;
+}
+testNoArgument();
+
+
+// Test Math.tan() with a very polymorphic input. All test cases are seen at each iteration.
+function opaqueAllTypesTan(argument) {
+    return Math.tan(argument);
+}
+noInline(opaqueAllTypesTan);
+noOSRExitFuzzing(opaqueAllTypesTan);
+
+function testAllTypesCall() {
+    for (let i = 0; i &lt; 1e3; ++i) {
+        for (let testCaseInput of validInputTypedTestCases) {
+            let output = opaqueAllTypesTan(testCaseInput[0]);
+            if (!isIdentical(output, testCaseInput[1]))
+                throw &quot;Failed testAllTypesCall for input &quot; + testCaseInput[0] + &quot; expected &quot; + testCaseInput[1] + &quot; got &quot; + output;
+        }
+    }
+    if (numberOfDFGCompiles(opaqueAllTypesTan) &gt; 2)
+        throw &quot;We should have detected tan() was polymorphic and generated a generic version.&quot;;
+}
+testAllTypesCall();
+
+
+// Test Math.tan() on a completely typed input. Every call see only one type.
+function testTangleTypeCall() {
+    for (let testCaseInput of validInputTestCases) {
+        eval(`
+            function opaqueTan(argument) {
+                return Math.tan(argument);
+            }
+            noInline(opaqueTan);
+            noOSRExitFuzzing(opaqueTan);
+
+            for (let i = 0; i &lt; 1e4; ++i) {
+                if (!isIdentical(opaqueTan(${testCaseInput[0]}), ${testCaseInput[1]})) {
+                    throw &quot;Failed testTangleTypeCall()&quot;;
+                }
+            }
+            if (numberOfDFGCompiles(opaqueTan) &gt; 1)
+                throw &quot;We should have compiled a tangle tan for the expected type.&quot;;
+        `);
+    }
+}
+testTangleTypeCall();
+
+
+// Test Math.tan() on constants
+function testConstant() {
+    for (let testCaseInput of validInputTestCases) {
+        eval(`
+            function opaqueTanOnConstant() {
+                return Math.tan(${testCaseInput[0]});
+            }
+            noInline(opaqueTanOnConstant);
+            noOSRExitFuzzing(opaqueTanOnConstant);
+
+            for (let i = 0; i &lt; 1e4; ++i) {
+                if (!isIdentical(opaqueTanOnConstant(), ${testCaseInput[1]})) {
+                    throw &quot;Failed testConstant()&quot;;
+                }
+            }
+            if (numberOfDFGCompiles(opaqueTanOnConstant) &gt; 1)
+                throw &quot;We should have compiled a tangle tan for the expected type.&quot;;
+        `);
+    }
+}
+testConstant();
+
+
+// Verify we call valueOf() exactly once per call.
+function opaqueTanForSideEffects(argument) {
+    return Math.tan(argument);
+}
+noInline(opaqueTanForSideEffects);
+noOSRExitFuzzing(opaqueTanForSideEffects);
+
+function testSideEffect() {
+    let testObject = {
+        counter: 0,
+        valueOf: function() { ++this.counter; return 16; }
+    };
+    let tan16 = Math.tan(16);
+    for (let i = 0; i &lt; 1e4; ++i) {
+        if (opaqueTanForSideEffects(testObject) !== tan16)
+            throw &quot;Incorrect result in testSideEffect()&quot;;
+    }
+    if (testObject.counter !== 1e4)
+        throw &quot;Failed testSideEffect()&quot;;
+    if (numberOfDFGCompiles(opaqueTanForSideEffects) &gt; 1)
+        throw &quot;opaqueTanForSideEffects() is predictable, it should only be compiled once.&quot;;
+}
+testSideEffect();
+
+
+// Verify tan() is not subject to CSE if the argument has side effects.
+function opaqueTanForCSE(argument) {
+    return Math.tan(argument) + Math.tan(argument) + Math.tan(argument);
+}
+noInline(opaqueTanForCSE);
+noOSRExitFuzzing(opaqueTanForCSE);
+
+function testCSE() {
+    let testObject = {
+        counter: 0,
+        valueOf: function() { ++this.counter; return 16; }
+    };
+    let tan16 = Math.tan(16);
+    let threeTan16 = tan16 + tan16 + tan16;
+    for (let i = 0; i &lt; 1e4; ++i) {
+        if (opaqueTanForCSE(testObject) !== threeTan16)
+            throw &quot;Incorrect result in testCSE()&quot;;
+    }
+    if (testObject.counter !== 3e4)
+        throw &quot;Failed testCSE()&quot;;
+    if (numberOfDFGCompiles(opaqueTanForCSE) &gt; 1)
+        throw &quot;opaqueTanForCSE() is predictable, it should only be compiled once.&quot;;
+}
+testCSE();
+
+
+// Verify tan() is not subject to DCE if the argument has side effects.
+function opaqueTanForDCE(argument) {
+    Math.tan(argument);
+}
+noInline(opaqueTanForDCE);
+noOSRExitFuzzing(opaqueTanForDCE);
+
+function testDCE() {
+    let testObject = {
+        counter: 0,
+        valueOf: function() { ++this.counter; return 16; }
+    };
+    for (let i = 0; i &lt; 1e4; ++i) {
+        opaqueTanForDCE(testObject);
+    }
+    if (testObject.counter !== 1e4)
+        throw &quot;Failed testDCE()&quot;;
+    if (numberOfDFGCompiles(opaqueTanForDCE) &gt; 1)
+        throw &quot;opaqueTanForDCE() is predictable, it should only be compiled once.&quot;;
+}
+testDCE();
+
+
+// Test exceptions in the argument.
+function testException() {
+    let counter = 0;
+    function opaqueTanWithException(argument) {
+        let result = Math.tan(argument);
+        ++counter;
+        return result;
+    }
+    noInline(opaqueTanWithException);
+
+    let testObject = { valueOf: () =&gt; {  return 64; } };
+    let tan64 = Math.tan(64);
+
+    // Warm up without exception.
+    for (let i = 0; i &lt; 1e3; ++i) {
+        if (opaqueTanWithException(testObject) !== tan64)
+            throw &quot;Incorrect result in opaqueTanWithException()&quot;;
+    }
+
+    let testThrowObject = { valueOf: () =&gt; { throw testObject; return 64; } };
+
+    for (let i = 0; i &lt; 1e2; ++i) {
+        try {
+            if (opaqueTanWithException(testThrowObject) !== 8)
+                throw &quot;This code should not be reached!!&quot;;
+        } catch (e) {
+            if (e !== testObject) {
+                throw &quot;Wrong object thrown from opaqueTanWithException.&quot;
+            }
+        }
+    }
+
+    if (counter !== 1e3) {
+        throw &quot;Invalid count in testException()&quot;;
+    }
+}
+testException();
</ins></span></pre></div>
<a id="trunkJSTestsstressftlarithtanjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/ftl-arithtan.js (0 => 205828)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/ftl-arithtan.js                                (rev 0)
+++ trunk/JSTests/stress/ftl-arithtan.js        2016-09-12 22:01:13 UTC (rev 205828)
</span><span class="lines">@@ -0,0 +1,13 @@
</span><ins>+function foo(x) {
+    return Math.tan(x);
+}
+
+noInline(foo);
+
+var j = 0;
+for (var i = 0; i &lt; 100000; ++i)
+    j = foo(i);
+
+if (-1.6871736258025631 != j){
+    throw `Error: ${j}`;
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (205827 => 205828)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-09-12 21:46:49 UTC (rev 205827)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-09-12 22:01:13 UTC (rev 205828)
</span><span class="lines">@@ -1,3 +1,58 @@
</span><ins>+2016-09-12  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
+
+        [DFG][FTL] Add ArithTan
+        https://bugs.webkit.org/show_bug.cgi?id=161857
+
+        Reviewed by Filip Pizlo.
+
+        While ArithSin and ArithCos are supported, ArithTan is not supported yet.
+        And we also find that Math.tan is included in MotionMark's Multiply benchmark.
+
+        This patch adds ArithTan support in DFG and FTL. And it also cleans up the
+        existing ArithSin, ArithCos, and ArithLog compilations by unifying them.
+        The microbenchmark shows the 9% perf improvement.
+
+            tan    322.4819+-0.3766     ^    295.8700+-0.3094        ^ definitely 1.0899x faster
+
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::handleIntrinsicCall):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGDoesGC.cpp:
+        (JSC::DFG::doesGC):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGNodeType.h:
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGOperations.h:
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::safeToExecute):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileArithDoubleUnaryOp):
+        (JSC::DFG::SpeculativeJIT::compileArithCos):
+        (JSC::DFG::SpeculativeJIT::compileArithTan):
+        (JSC::DFG::SpeculativeJIT::compileArithSin):
+        (JSC::DFG::SpeculativeJIT::compileArithLog):
+        * dfg/DFGSpeculativeJIT.h:
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+        (JSC::FTL::DFG::LowerDFGToB3::compileArithTan):
+        * ftl/FTLOutput.cpp:
+        (JSC::FTL::Output::doubleTan):
+        * ftl/FTLOutput.h:
+        * runtime/Intrinsic.h:
+        * runtime/MathObject.cpp:
+        (JSC::MathObject::finishCreation):
+
</ins><span class="cx"> 2016-09-12  Saam Barati  &lt;sbarati@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         MapHash should do constant folding when it has a constant argument and its legal to hash that value
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (205827 => 205828)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-09-12 21:46:49 UTC (rev 205827)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-09-12 22:01:13 UTC (rev 205828)
</span><span class="lines">@@ -959,6 +959,10 @@
</span><span class="cx">         executeDoubleUnaryOpEffects(node, cos);
</span><span class="cx">         break;
</span><span class="cx"> 
</span><ins>+    case ArithTan:
+        executeDoubleUnaryOpEffects(node, tan);
+        break;
+
</ins><span class="cx">     case ArithLog:
</span><span class="cx">         executeDoubleUnaryOpEffects(node, log);
</span><span class="cx">         break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (205827 => 205828)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2016-09-12 21:46:49 UTC (rev 205827)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2016-09-12 22:01:13 UTC (rev 205828)
</span><span class="lines">@@ -2155,7 +2155,8 @@
</span><span class="cx">     case FRoundIntrinsic:
</span><span class="cx">     case LogIntrinsic:
</span><span class="cx">     case SinIntrinsic:
</span><del>-    case SqrtIntrinsic: {
</del><ins>+    case SqrtIntrinsic:
+    case TanIntrinsic: {
</ins><span class="cx">         if (argumentCountIncludingThis == 1) {
</span><span class="cx">             insertChecks();
</span><span class="cx">             set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantNaN)));
</span><span class="lines">@@ -2179,6 +2180,9 @@
</span><span class="cx">         case SqrtIntrinsic:
</span><span class="cx">             nodeType = ArithSqrt;
</span><span class="cx">             break;
</span><ins>+        case TanIntrinsic:
+            nodeType = ArithTan;
+            break;
</ins><span class="cx">         default:
</span><span class="cx">             RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.h (205827 => 205828)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2016-09-12 21:46:49 UTC (rev 205827)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2016-09-12 22:01:13 UTC (rev 205828)
</span><span class="lines">@@ -188,6 +188,7 @@
</span><span class="cx">     case ArithLog:
</span><span class="cx">     case ArithSin:
</span><span class="cx">     case ArithSqrt:
</span><ins>+    case ArithTan:
</ins><span class="cx">         if (node-&gt;child1().useKind() == DoubleRepUse)
</span><span class="cx">             def(PureValue(node));
</span><span class="cx">         else {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDoesGCcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp (205827 => 205828)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2016-09-12 21:46:49 UTC (rev 205827)
+++ trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2016-09-12 22:01:13 UTC (rev 205828)
</span><span class="lines">@@ -94,6 +94,7 @@
</span><span class="cx">     case ArithFRound:
</span><span class="cx">     case ArithSin:
</span><span class="cx">     case ArithCos:
</span><ins>+    case ArithTan:
</ins><span class="cx">     case ArithLog:
</span><span class="cx">     case ValueAdd:
</span><span class="cx">     case TryGetById:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (205827 => 205828)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-09-12 21:46:49 UTC (rev 205827)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-09-12 22:01:13 UTC (rev 205828)
</span><span class="lines">@@ -401,7 +401,8 @@
</span><span class="cx">         case ArithFRound:
</span><span class="cx">         case ArithLog:
</span><span class="cx">         case ArithSin:
</span><del>-        case ArithSqrt: {
</del><ins>+        case ArithSqrt:
+        case ArithTan: {
</ins><span class="cx">             Edge&amp; child1 = node-&gt;child1();
</span><span class="cx">             if (child1-&gt;shouldSpeculateNotCell()) {
</span><span class="cx">                 fixDoubleOrBooleanEdge(child1);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNodeType.h (205827 => 205828)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2016-09-12 21:46:49 UTC (rev 205827)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2016-09-12 22:01:13 UTC (rev 205828)
</span><span class="lines">@@ -162,6 +162,7 @@
</span><span class="cx">     macro(ArithSqrt, NodeResultDouble | NodeMustGenerate) \
</span><span class="cx">     macro(ArithSin, NodeResultDouble | NodeMustGenerate) \
</span><span class="cx">     macro(ArithCos, NodeResultDouble | NodeMustGenerate) \
</span><ins>+    macro(ArithTan, NodeResultDouble | NodeMustGenerate) \
</ins><span class="cx">     macro(ArithLog, NodeResultDouble | NodeMustGenerate) \
</span><span class="cx">     \
</span><span class="cx">     /* Add of values may either be arithmetic, or result in string concatenation. */\
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp (205827 => 205828)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2016-09-12 21:46:49 UTC (rev 205827)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2016-09-12 22:01:13 UTC (rev 205828)
</span><span class="lines">@@ -429,6 +429,19 @@
</span><span class="cx">     return sqrt(a);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+double JIT_OPERATION operationArithTan(ExecState* exec, EncodedJSValue encodedOp1)
+{
+    VM* vm = &amp;exec-&gt;vm();
+    NativeCallFrameTracer tracer(vm, exec);
+    auto scope = DECLARE_THROW_SCOPE(*vm);
+
+    JSValue op1 = JSValue::decode(encodedOp1);
+    double a = op1.toNumber(exec);
+    if (UNLIKELY(scope.exception()))
+        return JSValue::encode(JSValue());
+    return tan(a);
+}
+
</ins><span class="cx"> static ALWAYS_INLINE EncodedJSValue getByVal(ExecState* exec, JSCell* base, uint32_t index)
</span><span class="cx"> {
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.h (205827 => 205828)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.h        2016-09-12 21:46:49 UTC (rev 205827)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.h        2016-09-12 22:01:13 UTC (rev 205828)
</span><span class="lines">@@ -56,6 +56,7 @@
</span><span class="cx"> double JIT_OPERATION operationArithAbs(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;
</span><span class="cx"> int32_t JIT_OPERATION operationArithClz32(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;
</span><span class="cx"> double JIT_OPERATION operationArithCos(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;
</span><ins>+double JIT_OPERATION operationArithTan(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;
</ins><span class="cx"> double JIT_OPERATION operationArithFRound(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;
</span><span class="cx"> double JIT_OPERATION operationArithLog(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;
</span><span class="cx"> double JIT_OPERATION operationArithSin(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (205827 => 205828)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2016-09-12 21:46:49 UTC (rev 205827)
+++ trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2016-09-12 22:01:13 UTC (rev 205828)
</span><span class="lines">@@ -561,6 +561,7 @@
</span><span class="cx">         case ArithSqrt:
</span><span class="cx">         case ArithCos:
</span><span class="cx">         case ArithSin:
</span><ins>+        case ArithTan:
</ins><span class="cx">         case ArithLog:
</span><span class="cx">             if (node-&gt;child1()-&gt;shouldSpeculateNumber())
</span><span class="cx">                 m_graph.voteNode(node-&gt;child1(), VoteDouble, weight);
</span><span class="lines">@@ -769,6 +770,7 @@
</span><span class="cx">         case ArithFRound:
</span><span class="cx">         case ArithSin:
</span><span class="cx">         case ArithCos:
</span><ins>+        case ArithTan:
</ins><span class="cx">         case ArithLog: {
</span><span class="cx">             setPrediction(SpecBytecodeDouble);
</span><span class="cx">             break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSafeToExecuteh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h (205827 => 205828)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2016-09-12 21:46:49 UTC (rev 205827)
+++ trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2016-09-12 22:01:13 UTC (rev 205828)
</span><span class="lines">@@ -191,6 +191,7 @@
</span><span class="cx">     case ArithTrunc:
</span><span class="cx">     case ArithSin:
</span><span class="cx">     case ArithCos:
</span><ins>+    case ArithTan:
</ins><span class="cx">     case ArithLog:
</span><span class="cx">     case ValueAdd:
</span><span class="cx">     case TryGetById:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (205827 => 205828)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-09-12 21:46:49 UTC (rev 205827)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-09-12 22:01:13 UTC (rev 205828)
</span><span class="lines">@@ -3951,7 +3951,7 @@
</span><span class="cx">     int32Result(resultReg, node);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::compileArithCos(Node* node)
</del><ins>+void SpeculativeJIT::compileArithDoubleUnaryOp(Node* node, double (*doubleFunction)(double), double (*operation)(ExecState*, EncodedJSValue))
</ins><span class="cx"> {
</span><span class="cx">     if (node-&gt;child1().useKind() == DoubleRepUse) {
</span><span class="cx">         SpeculateDoubleOperand op1(this, node-&gt;child1());
</span><span class="lines">@@ -3958,9 +3958,9 @@
</span><span class="cx">         FPRReg op1FPR = op1.fpr();
</span><span class="cx"> 
</span><span class="cx">         flushRegisters();
</span><del>-        
</del><ins>+
</ins><span class="cx">         FPRResult result(this);
</span><del>-        callOperation(cos, result.fpr(), op1FPR);
</del><ins>+        callOperation(doubleFunction, result.fpr(), op1FPR);
</ins><span class="cx">         doubleResult(result.fpr(), node);
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="lines">@@ -3969,11 +3969,21 @@
</span><span class="cx">     JSValueRegs op1Regs = op1.jsValueRegs();
</span><span class="cx">     flushRegisters();
</span><span class="cx">     FPRResult result(this);
</span><del>-    callOperation(operationArithCos, result.fpr(), op1Regs);
</del><ins>+    callOperation(operation, result.fpr(), op1Regs);
</ins><span class="cx">     m_jit.exceptionCheck();
</span><span class="cx">     doubleResult(result.fpr(), node);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SpeculativeJIT::compileArithCos(Node* node)
+{
+    compileArithDoubleUnaryOp(node, cos, operationArithCos);
+}
+
+void SpeculativeJIT::compileArithTan(Node* node)
+{
+    compileArithDoubleUnaryOp(node, tan, operationArithTan);
+}
+
</ins><span class="cx"> void SpeculativeJIT::compileArithSub(Node* node)
</span><span class="cx"> {
</span><span class="cx">     switch (node-&gt;binaryUseKind()) {
</span><span class="lines">@@ -4999,25 +5009,7 @@
</span><span class="cx"> 
</span><span class="cx"> void SpeculativeJIT::compileArithSin(Node* node)
</span><span class="cx"> {
</span><del>-    if (node-&gt;child1().useKind() == DoubleRepUse) {
-        SpeculateDoubleOperand op1(this, node-&gt;child1());
-        FPRReg op1FPR = op1.fpr();
-
-        flushRegisters();
-        
-        FPRResult result(this);
-        callOperation(sin, result.fpr(), op1FPR);
-        doubleResult(result.fpr(), node);
-        return;
-    }
-
-    JSValueOperand op1(this, node-&gt;child1());
-    JSValueRegs op1Regs = op1.jsValueRegs();
-    flushRegisters();
-    FPRResult result(this);
-    callOperation(operationArithSin, result.fpr(), op1Regs);
-    m_jit.exceptionCheck();
-    doubleResult(result.fpr(), node);
</del><ins>+    compileArithDoubleUnaryOp(node, sin, operationArithSin);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SpeculativeJIT::compileArithSqrt(Node* node)
</span><span class="lines">@@ -5198,23 +5190,7 @@
</span><span class="cx"> 
</span><span class="cx"> void SpeculativeJIT::compileArithLog(Node* node)
</span><span class="cx"> {
</span><del>-    if (node-&gt;child1().useKind() == DoubleRepUse) {
-        SpeculateDoubleOperand op1(this, node-&gt;child1());
-        FPRReg op1FPR = op1.fpr();
-        flushRegisters();
-        FPRResult result(this);
-        callOperation(log, result.fpr(), op1FPR);
-        doubleResult(result.fpr(), node);
-        return;
-    }
-
-    JSValueOperand op1(this, node-&gt;child1());
-    JSValueRegs op1Regs = op1.jsValueRegs();
-    flushRegisters();
-    FPRResult result(this);
-    callOperation(operationArithLog, result.fpr(), op1Regs);
-    m_jit.exceptionCheck();
-    doubleResult(result.fpr(), node);
</del><ins>+    compileArithDoubleUnaryOp(node, log, operationArithLog);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // Returns true if the compare is fused with a subsequent branch.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (205827 => 205828)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2016-09-12 21:46:49 UTC (rev 205827)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2016-09-12 22:01:13 UTC (rev 205828)
</span><span class="lines">@@ -2507,6 +2507,7 @@
</span><span class="cx">     template &lt;typename Generator, typename RepatchingFunction, typename NonRepatchingFunction&gt;
</span><span class="cx">     void compileMathIC(Node*, JITMathIC&lt;Generator&gt;*, bool needsScratchGPRReg, bool needsScratchFPRReg, RepatchingFunction, NonRepatchingFunction);
</span><span class="cx"> 
</span><ins>+    void compileArithDoubleUnaryOp(Node*, double (*doubleFunction)(double), double (*operation)(ExecState*, EncodedJSValue));
</ins><span class="cx">     void compileValueAdd(Node*);
</span><span class="cx">     void compileArithAdd(Node*);
</span><span class="cx">     void compileMakeRope(Node*);
</span><span class="lines">@@ -2513,6 +2514,7 @@
</span><span class="cx">     void compileArithAbs(Node*);
</span><span class="cx">     void compileArithClz32(Node*);
</span><span class="cx">     void compileArithCos(Node*);
</span><ins>+    void compileArithTan(Node*);
</ins><span class="cx">     void compileArithSub(Node*);
</span><span class="cx">     void compileArithNegate(Node*);
</span><span class="cx">     void compileArithMul(Node*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (205827 => 205828)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2016-09-12 21:46:49 UTC (rev 205827)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2016-09-12 22:01:13 UTC (rev 205828)
</span><span class="lines">@@ -2348,6 +2348,10 @@
</span><span class="cx">         compileArithCos(node);
</span><span class="cx">         break;
</span><span class="cx"> 
</span><ins>+    case ArithTan:
+        compileArithTan(node);
+        break;
+
</ins><span class="cx">     case ArithLog:
</span><span class="cx">         compileArithLog(node);
</span><span class="cx">         break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (205827 => 205828)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2016-09-12 21:46:49 UTC (rev 205827)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2016-09-12 22:01:13 UTC (rev 205828)
</span><span class="lines">@@ -2503,6 +2503,10 @@
</span><span class="cx">         compileArithCos(node);
</span><span class="cx">         break;
</span><span class="cx"> 
</span><ins>+    case ArithTan:
+        compileArithTan(node);
+        break;
+
</ins><span class="cx">     case ArithLog:
</span><span class="cx">         compileArithLog(node);
</span><span class="cx">         break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp (205827 => 205828)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2016-09-12 21:46:49 UTC (rev 205827)
+++ trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2016-09-12 22:01:13 UTC (rev 205828)
</span><span class="lines">@@ -94,6 +94,7 @@
</span><span class="cx">     case ArithAbs:
</span><span class="cx">     case ArithSin:
</span><span class="cx">     case ArithCos:
</span><ins>+    case ArithTan:
</ins><span class="cx">     case ArithPow:
</span><span class="cx">     case ArithRandom:
</span><span class="cx">     case ArithRound:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (205827 => 205828)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-09-12 21:46:49 UTC (rev 205827)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-09-12 22:01:13 UTC (rev 205828)
</span><span class="lines">@@ -541,6 +541,9 @@
</span><span class="cx">         case ArithCos:
</span><span class="cx">             compileArithCos();
</span><span class="cx">             break;
</span><ins>+        case ArithTan:
+            compileArithTan();
+            break;
</ins><span class="cx">         case ArithPow:
</span><span class="cx">             compileArithPow();
</span><span class="cx">             break;
</span><span class="lines">@@ -2066,6 +2069,17 @@
</span><span class="cx">         setDouble(result);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void compileArithTan()
+    {
+        if (m_node-&gt;child1().useKind() == DoubleRepUse) {
+            setDouble(m_out.doubleTan(lowDouble(m_node-&gt;child1())));
+            return;
+        }
+        LValue argument = lowJSValue(m_node-&gt;child1());
+        LValue result = vmCall(Double, m_out.operation(operationArithTan), m_callFrame, argument);
+        setDouble(result);
+    }
+
</ins><span class="cx">     void compileArithPow()
</span><span class="cx">     {
</span><span class="cx">         if (m_node-&gt;child2().useKind() == Int32Use)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLOutputcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLOutput.cpp (205827 => 205828)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLOutput.cpp        2016-09-12 21:46:49 UTC (rev 205827)
+++ trunk/Source/JavaScriptCore/ftl/FTLOutput.cpp        2016-09-12 22:01:13 UTC (rev 205828)
</span><span class="lines">@@ -299,6 +299,12 @@
</span><span class="cx">     return callWithoutSideEffects(B3::Double, cosDouble, value);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+LValue Output::doubleTan(LValue value)
+{
+    double (*tanDouble)(double) = tan;
+    return callWithoutSideEffects(B3::Double, tanDouble, value);
+}
+
</ins><span class="cx"> LValue Output::doublePow(LValue xOperand, LValue yOperand)
</span><span class="cx"> {
</span><span class="cx">     double (*powDouble)(double, double) = pow;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLOutputh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLOutput.h (205827 => 205828)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLOutput.h        2016-09-12 21:46:49 UTC (rev 205827)
+++ trunk/Source/JavaScriptCore/ftl/FTLOutput.h        2016-09-12 22:01:13 UTC (rev 205828)
</span><span class="lines">@@ -163,6 +163,7 @@
</span><span class="cx"> 
</span><span class="cx">     LValue doubleSin(LValue);
</span><span class="cx">     LValue doubleCos(LValue);
</span><ins>+    LValue doubleTan(LValue);
</ins><span class="cx"> 
</span><span class="cx">     LValue doublePow(LValue base, LValue exponent);
</span><span class="cx">     LValue doublePowi(LValue base, LValue exponent);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeIntrinsich"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Intrinsic.h (205827 => 205828)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Intrinsic.h        2016-09-12 21:46:49 UTC (rev 205827)
+++ trunk/Source/JavaScriptCore/runtime/Intrinsic.h        2016-09-12 22:01:13 UTC (rev 205828)
</span><span class="lines">@@ -38,6 +38,7 @@
</span><span class="cx">     SinIntrinsic,
</span><span class="cx">     Clz32Intrinsic,
</span><span class="cx">     CosIntrinsic,
</span><ins>+    TanIntrinsic,
</ins><span class="cx">     ArrayPushIntrinsic,
</span><span class="cx">     ArrayPopIntrinsic,
</span><span class="cx">     CharCodeAtIntrinsic,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeMathObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/MathObject.cpp (205827 => 205828)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/MathObject.cpp        2016-09-12 21:46:49 UTC (rev 205827)
+++ trunk/Source/JavaScriptCore/runtime/MathObject.cpp        2016-09-12 22:01:13 UTC (rev 205828)
</span><span class="lines">@@ -120,7 +120,7 @@
</span><span class="cx">     putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier::fromString(&amp;vm, &quot;sin&quot;), 1, mathProtoFuncSin, SinIntrinsic, DontEnum);
</span><span class="cx">     putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier::fromString(&amp;vm, &quot;sinh&quot;), 1, mathProtoFuncSinh, NoIntrinsic, DontEnum);
</span><span class="cx">     putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier::fromString(&amp;vm, &quot;sqrt&quot;), 1, mathProtoFuncSqrt, SqrtIntrinsic, DontEnum);
</span><del>-    putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier::fromString(&amp;vm, &quot;tan&quot;), 1, mathProtoFuncTan, NoIntrinsic, DontEnum);
</del><ins>+    putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier::fromString(&amp;vm, &quot;tan&quot;), 1, mathProtoFuncTan, TanIntrinsic, DontEnum);
</ins><span class="cx">     putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier::fromString(&amp;vm, &quot;tanh&quot;), 1, mathProtoFuncTanh, NoIntrinsic, DontEnum);
</span><span class="cx">     putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier::fromString(&amp;vm, &quot;trunc&quot;), 1, mathProtoFuncTrunc, TruncIntrinsic, DontEnum);
</span><span class="cx">     putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier::fromString(&amp;vm, &quot;imul&quot;), 2, mathProtoFuncIMul, IMulIntrinsic, DontEnum);
</span></span></pre>
</div>
</div>

</body>
</html>