<!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>[200208] trunk/Source/JavaScriptCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/200208">200208</a></dd>
<dt>Author</dt> <dd>benjamin@webkit.org</dd>
<dt>Date</dt> <dd>2016-04-28 13:50:08 -0700 (Thu, 28 Apr 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>[JSC] Unify Math.pow() accross all tiers
https://bugs.webkit.org/show_bug.cgi?id=157121

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

My previous optimizations of DFG compile time have slowly
regressed Sunspider's math-partial-sums.

What is happenning is baseline used a thunk for Math.pow()
that has a special case for an exponent of -0.5, while
DFG/FTL have other special cases for other exponents.
The faster we get to DFG, the less time we spend in that fast
case for -0.5.

While looking into this, I discovered some correctness issues. Baseline
optimizes y=-0.5 by turning it into 1/sqrt(). DFG/FTL optimize constant
y=0.5 by turning it into sqrt(). The problem is sqrt() behaves differently
for -0 and -Infinity. With sqrt(), negative numbers are undefined,
and the result is NaN. With pow(), they have a result.

Something else that has bothered me for a while is that Math.pow()
with the same arguments give you different results in LLINT, Baseline,
and DFG/FTL. This seems a bit dangerous for numerical stability.

With this patch, I unify the behaviors for all tiers while keeping
the &quot;special cases&quot;.

We have pow() that is super slow, but most callers don't need the
full power. We have:
-pow() with an exponent between 0 and 1000 is a fast path implemented
 by multiplication only.
-pow(x, 0.5) is sqrt with special checks for negative values.
-pow(x, -0.5) is sqrt with special checks for negative values.

The C++ implementation handles all those optimizations too. This ensure
you get the same results from LLINT to FTL.

The thunk is eliminated, it was producing incorrect results and only
optimized Sunspider's partial-sums.

DFG gets the optimized integer, 0.5 and -0.5 cases since those are important
for somewhat-hot code. DFG falls back to the C++ code for any non-obvious case.

FTL gets the full C++ implementation inlined in B3. B3 knows how to eliminate
all the dead cases so you get the best if your code is hot enough to reach FTL.

* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode): Deleted.
* dfg/DFGNode.h:
(JSC::DFG::Node::convertToArithSqrt): Deleted.
* dfg/DFGNodeType.h:
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::compileArithPowIntegerFastPath):
(JSC::DFG::SpeculativeJIT::compileArithPow):
* dfg/DFGStrengthReductionPhase.cpp:
(JSC::DFG::StrengthReductionPhase::handleNode):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileArithPow):
* jit/ThunkGenerators.cpp:
(JSC::powThunkGenerator): Deleted.
* jit/ThunkGenerators.h:
* runtime/MathCommon.cpp:
(JSC::operationMathPow):
* runtime/MathCommon.h:
* runtime/VM.cpp:
(JSC::thunkGeneratorForIntrinsic): Deleted.
* tests/stress/math-pow-stable-results.js: Added.
Getting consistent results when tiering up is new.
This test verify that results always remains the same as LLINT.

* tests/stress/math-pow-with-constants.js:
(testPowUsedAsSqrt):
(powUsedAsOneOverSqrt):
(testPowUsedAsOneOverSqrt):
(powUsedAsSquare):
(testPowUsedAsSquare):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeh">trunk/Source/JavaScriptCore/dfg/DFGNode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeTypeh">trunk/Source/JavaScriptCore/dfg/DFGNodeType.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGStrengthReductionPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitThunkGeneratorscpp">trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitThunkGeneratorsh">trunk/Source/JavaScriptCore/jit/ThunkGenerators.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeMathCommoncpp">trunk/Source/JavaScriptCore/runtime/MathCommon.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeMathCommonh">trunk/Source/JavaScriptCore/runtime/MathCommon.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMcpp">trunk/Source/JavaScriptCore/runtime/VM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressmathpowwithconstantsjs">trunk/Source/JavaScriptCore/tests/stress/math-pow-with-constants.js</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstressmathpowstableresultsjs">trunk/Source/JavaScriptCore/tests/stress/math-pow-stable-results.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (200207 => 200208)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-04-28 20:31:12 UTC (rev 200207)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-04-28 20:50:08 UTC (rev 200208)
</span><span class="lines">@@ -1,3 +1,82 @@
</span><ins>+2016-04-28  Benjamin Poulain  &lt;bpoulain@apple.com&gt;
+
+        [JSC] Unify Math.pow() accross all tiers
+        https://bugs.webkit.org/show_bug.cgi?id=157121
+
+        Reviewed by Geoffrey Garen.
+
+        My previous optimizations of DFG compile time have slowly
+        regressed Sunspider's math-partial-sums.
+
+        What is happenning is baseline used a thunk for Math.pow()
+        that has a special case for an exponent of -0.5, while
+        DFG/FTL have other special cases for other exponents.
+        The faster we get to DFG, the less time we spend in that fast
+        case for -0.5.
+
+        While looking into this, I discovered some correctness issues. Baseline
+        optimizes y=-0.5 by turning it into 1/sqrt(). DFG/FTL optimize constant
+        y=0.5 by turning it into sqrt(). The problem is sqrt() behaves differently
+        for -0 and -Infinity. With sqrt(), negative numbers are undefined,
+        and the result is NaN. With pow(), they have a result.
+
+        Something else that has bothered me for a while is that Math.pow()
+        with the same arguments give you different results in LLINT, Baseline,
+        and DFG/FTL. This seems a bit dangerous for numerical stability.
+
+        With this patch, I unify the behaviors for all tiers while keeping
+        the &quot;special cases&quot;.
+
+        We have pow() that is super slow, but most callers don't need the
+        full power. We have:
+        -pow() with an exponent between 0 and 1000 is a fast path implemented
+         by multiplication only.
+        -pow(x, 0.5) is sqrt with special checks for negative values.
+        -pow(x, -0.5) is sqrt with special checks for negative values.
+
+        The C++ implementation handles all those optimizations too. This ensure
+        you get the same results from LLINT to FTL.
+
+        The thunk is eliminated, it was producing incorrect results and only
+        optimized Sunspider's partial-sums.
+
+        DFG gets the optimized integer, 0.5 and -0.5 cases since those are important
+        for somewhat-hot code. DFG falls back to the C++ code for any non-obvious case.
+
+        FTL gets the full C++ implementation inlined in B3. B3 knows how to eliminate
+        all the dead cases so you get the best if your code is hot enough to reach FTL.
+
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode): Deleted.
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::convertToArithSqrt): Deleted.
+        * dfg/DFGNodeType.h:
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::compileArithPowIntegerFastPath):
+        (JSC::DFG::SpeculativeJIT::compileArithPow):
+        * dfg/DFGStrengthReductionPhase.cpp:
+        (JSC::DFG::StrengthReductionPhase::handleNode):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileArithPow):
+        * jit/ThunkGenerators.cpp:
+        (JSC::powThunkGenerator): Deleted.
+        * jit/ThunkGenerators.h:
+        * runtime/MathCommon.cpp:
+        (JSC::operationMathPow):
+        * runtime/MathCommon.h:
+        * runtime/VM.cpp:
+        (JSC::thunkGeneratorForIntrinsic): Deleted.
+        * tests/stress/math-pow-stable-results.js: Added.
+        Getting consistent results when tiering up is new.
+        This test verify that results always remains the same as LLINT.
+
+        * tests/stress/math-pow-with-constants.js:
+        (testPowUsedAsSqrt):
+        (powUsedAsOneOverSqrt):
+        (testPowUsedAsOneOverSqrt):
+        (powUsedAsSquare):
+        (testPowUsedAsSquare):
+
</ins><span class="cx"> 2016-04-28  Mark Lam  &lt;mark.lam@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         DebuggerScope::className() should not assert scope-&gt;isValid().
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (200207 => 200208)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-04-28 20:31:12 UTC (rev 200207)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-04-28 20:50:08 UTC (rev 200208)
</span><span class="lines">@@ -349,7 +349,6 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         case ArithPow: {
</span><del>-            node-&gt;setResult(NodeResultDouble);
</del><span class="cx">             if (node-&gt;child2()-&gt;shouldSpeculateInt32OrBooleanForArithmetic()) {
</span><span class="cx">                 fixDoubleOrBooleanEdge(node-&gt;child1());
</span><span class="cx">                 fixIntOrBooleanEdge(node-&gt;child2());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNode.h (200207 => 200208)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNode.h        2016-04-28 20:31:12 UTC (rev 200207)
+++ trunk/Source/JavaScriptCore/dfg/DFGNode.h        2016-04-28 20:50:08 UTC (rev 200208)
</span><span class="lines">@@ -633,13 +633,6 @@
</span><span class="cx">         m_op = ToString;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void convertToArithSqrt()
-    {
-        ASSERT(m_op == ArithPow);
-        child2() = Edge();
-        m_op = ArithSqrt;
-    }
-
</del><span class="cx">     void convertToArithNegate()
</span><span class="cx">     {
</span><span class="cx">         ASSERT(m_op == ArithAbs &amp;&amp; child1().useKind() == Int32Use);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNodeType.h (200207 => 200208)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2016-04-28 20:31:12 UTC (rev 200207)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2016-04-28 20:50:08 UTC (rev 200208)
</span><span class="lines">@@ -153,7 +153,7 @@
</span><span class="cx">     macro(ArithMin, NodeResultNumber) \
</span><span class="cx">     macro(ArithMax, NodeResultNumber) \
</span><span class="cx">     macro(ArithFRound, NodeResultNumber) \
</span><del>-    macro(ArithPow, NodeResultNumber) \
</del><ins>+    macro(ArithPow, NodeResultDouble) \
</ins><span class="cx">     macro(ArithRandom, NodeResultDouble | NodeMustGenerate) \
</span><span class="cx">     macro(ArithRound, NodeResultNumber) \
</span><span class="cx">     macro(ArithFloor, NodeResultNumber) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (200207 => 200208)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-04-28 20:31:12 UTC (rev 200207)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-04-28 20:50:08 UTC (rev 200208)
</span><span class="lines">@@ -4722,7 +4722,7 @@
</span><span class="cx"> static MacroAssembler::Jump compileArithPowIntegerFastPath(JITCompiler&amp; assembler, FPRReg xOperand, GPRReg yOperand, FPRReg result)
</span><span class="cx"> {
</span><span class="cx">     MacroAssembler::JumpList skipFastPath;
</span><del>-    skipFastPath.append(assembler.branch32(MacroAssembler::Above, yOperand, MacroAssembler::TrustedImm32(1000)));
</del><ins>+    skipFastPath.append(assembler.branch32(MacroAssembler::Above, yOperand, MacroAssembler::TrustedImm32(maxExponentForIntegerMathPow)));
</ins><span class="cx"> 
</span><span class="cx">     static const double oneConstant = 1.0;
</span><span class="cx">     assembler.loadDouble(MacroAssembler::TrustedImmPtr(&amp;oneConstant), result);
</span><span class="lines">@@ -4772,6 +4772,69 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    if (node-&gt;child2()-&gt;isDoubleConstant()) {
+        double exponent = node-&gt;child2()-&gt;asNumber();
+        static const double infinityConstant = std::numeric_limits&lt;double&gt;::infinity();
+        static const double minusInfinityConstant = -std::numeric_limits&lt;double&gt;::infinity();
+        if (exponent == 0.5) {
+            SpeculateDoubleOperand xOperand(this, node-&gt;child1());
+            FPRTemporary result(this);
+            FPRReg xOperandFpr = xOperand.fpr();
+            FPRReg resultFpr = result.fpr();
+
+            m_jit.moveZeroToDouble(resultFpr);
+            MacroAssembler::Jump xIsZeroOrNegativeZero = m_jit.branchDouble(MacroAssembler::DoubleEqual, xOperandFpr, resultFpr);
+
+            m_jit.loadDouble(TrustedImmPtr(&amp;minusInfinityConstant), resultFpr);
+            MacroAssembler::Jump xIsMinusInfinity = m_jit.branchDouble(MacroAssembler::DoubleEqual, xOperandFpr, resultFpr);
+            m_jit.sqrtDouble(xOperandFpr, resultFpr);
+            MacroAssembler::Jump doneWithSqrt = m_jit.jump();
+
+            xIsMinusInfinity.link(&amp;m_jit);
+            if (isX86())
+                m_jit.loadDouble(TrustedImmPtr(&amp;infinityConstant), resultFpr);
+            else
+                m_jit.absDouble(resultFpr, resultFpr);
+
+            xIsZeroOrNegativeZero.link(&amp;m_jit);
+            doneWithSqrt.link(&amp;m_jit);
+            doubleResult(resultFpr, node);
+            return;
+        }
+        if (exponent == -0.5) {
+            SpeculateDoubleOperand xOperand(this, node-&gt;child1());
+            FPRTemporary scratch(this);
+            FPRTemporary result(this);
+            FPRReg xOperandFpr = xOperand.fpr();
+            FPRReg scratchFPR = scratch.fpr();
+            FPRReg resultFpr = result.fpr();
+
+            m_jit.moveZeroToDouble(resultFpr);
+            MacroAssembler::Jump xIsZeroOrNegativeZero = m_jit.branchDouble(MacroAssembler::DoubleEqual, xOperandFpr, resultFpr);
+
+            m_jit.loadDouble(TrustedImmPtr(&amp;minusInfinityConstant), resultFpr);
+            MacroAssembler::Jump xIsMinusInfinity = m_jit.branchDouble(MacroAssembler::DoubleEqual, xOperandFpr, resultFpr);
+
+            static const double oneConstant = 1.;
+            m_jit.loadDouble(TrustedImmPtr(&amp;oneConstant), resultFpr);
+            m_jit.sqrtDouble(xOperandFpr, scratchFPR);
+            m_jit.divDouble(resultFpr, scratchFPR, resultFpr);
+            MacroAssembler::Jump doneWithSqrt = m_jit.jump();
+
+            xIsZeroOrNegativeZero.link(&amp;m_jit);
+            m_jit.loadDouble(TrustedImmPtr(&amp;infinityConstant), resultFpr);
+            MacroAssembler::Jump doneWithBaseZero = m_jit.jump();
+
+            xIsMinusInfinity.link(&amp;m_jit);
+            m_jit.moveZeroToDouble(resultFpr);
+
+            doneWithBaseZero.link(&amp;m_jit);
+            doneWithSqrt.link(&amp;m_jit);
+            doubleResult(resultFpr, node);
+            return;
+        }
+    }
+
</ins><span class="cx">     SpeculateDoubleOperand xOperand(this, node-&gt;child1());
</span><span class="cx">     SpeculateDoubleOperand yOperand(this, node-&gt;child2());
</span><span class="cx">     FPRReg xOperandfpr = xOperand.fpr();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGStrengthReductionPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp (200207 => 200208)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp        2016-04-28 20:31:12 UTC (rev 200207)
+++ trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp        2016-04-28 20:50:08 UTC (rev 200208)
</span><span class="lines">@@ -170,10 +170,11 @@
</span><span class="cx">                 double yOperandValue = m_node-&gt;child2()-&gt;asNumber();
</span><span class="cx">                 if (yOperandValue == 1) {
</span><span class="cx">                     convertToIdentityOverChild1();
</span><del>-                } else if (yOperandValue == 0.5) {
-                    m_insertionSet.insertCheck(m_nodeIndex, m_node);
-                    m_node-&gt;convertToArithSqrt();
</del><span class="cx">                     m_changed = true;
</span><ins>+                } else if (yOperandValue == 2) {
+                    m_node-&gt;setOp(ArithMul);
+                    m_node-&gt;child2() = m_node-&gt;child1();
+                    m_changed = true;
</ins><span class="cx">                 }
</span><span class="cx">             }
</span><span class="cx">             break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (200207 => 200208)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-04-28 20:31:12 UTC (rev 200207)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-04-28 20:50:08 UTC (rev 200208)
</span><span class="lines">@@ -1859,8 +1859,19 @@
</span><span class="cx">             LBasicBlock integerExponentIsSmallBlock = m_out.newBlock();
</span><span class="cx">             LBasicBlock integerExponentPowBlock = m_out.newBlock();
</span><span class="cx">             LBasicBlock doubleExponentPowBlockEntry = m_out.newBlock();
</span><ins>+            LBasicBlock nanExceptionBaseIsOne = m_out.newBlock();
</ins><span class="cx">             LBasicBlock nanExceptionExponentIsInfinity = m_out.newBlock();
</span><del>-            LBasicBlock nanExceptionBaseIsOne = m_out.newBlock();
</del><ins>+            LBasicBlock testExponentIsOneHalf = m_out.newBlock();
+            LBasicBlock handleBaseZeroExponentIsOneHalf = m_out.newBlock();
+            LBasicBlock handleInfinityForExponentIsOneHalf = m_out.newBlock();
+            LBasicBlock exponentIsOneHalfNormal = m_out.newBlock();
+            LBasicBlock exponentIsOneHalfInfinity = m_out.newBlock();
+            LBasicBlock testExponentIsNegativeOneHalf = m_out.newBlock();
+            LBasicBlock testBaseZeroExponentIsNegativeOneHalf = m_out.newBlock();
+            LBasicBlock handleBaseZeroExponentIsNegativeOneHalf = m_out.newBlock();
+            LBasicBlock handleInfinityForExponentIsNegativeOneHalf = m_out.newBlock();
+            LBasicBlock exponentIsNegativeOneHalfNormal = m_out.newBlock();
+            LBasicBlock exponentIsNegativeOneHalfInfinity = m_out.newBlock();
</ins><span class="cx">             LBasicBlock powBlock = m_out.newBlock();
</span><span class="cx">             LBasicBlock nanExceptionResultIsNaN = m_out.newBlock();
</span><span class="cx">             LBasicBlock continuation = m_out.newBlock();
</span><span class="lines">@@ -1871,34 +1882,96 @@
</span><span class="cx">             m_out.branch(exponentIsInteger, unsure(integerExponentIsSmallBlock), unsure(doubleExponentPowBlockEntry));
</span><span class="cx"> 
</span><span class="cx">             LBasicBlock lastNext = m_out.appendTo(integerExponentIsSmallBlock, integerExponentPowBlock);
</span><del>-            LValue integerExponentBelow1000 = m_out.below(integerExponent, m_out.constInt32(1000));
-            m_out.branch(integerExponentBelow1000, usually(integerExponentPowBlock), rarely(doubleExponentPowBlockEntry));
</del><ins>+            LValue integerExponentBelowMax = m_out.belowOrEqual(integerExponent, m_out.constInt32(maxExponentForIntegerMathPow));
+            m_out.branch(integerExponentBelowMax, usually(integerExponentPowBlock), rarely(doubleExponentPowBlockEntry));
</ins><span class="cx"> 
</span><span class="cx">             m_out.appendTo(integerExponentPowBlock, doubleExponentPowBlockEntry);
</span><span class="cx">             ValueFromBlock powDoubleIntResult = m_out.anchor(m_out.doublePowi(base, integerExponent));
</span><span class="cx">             m_out.jump(continuation);
</span><span class="cx"> 
</span><span class="cx">             // If y is NaN, the result is NaN.
</span><del>-            m_out.appendTo(doubleExponentPowBlockEntry, nanExceptionExponentIsInfinity);
</del><ins>+            m_out.appendTo(doubleExponentPowBlockEntry, nanExceptionBaseIsOne);
</ins><span class="cx">             LValue exponentIsNaN;
</span><span class="cx">             if (provenType(m_node-&gt;child2()) &amp; SpecDoubleNaN)
</span><span class="cx">                 exponentIsNaN = m_out.doubleNotEqualOrUnordered(exponent, exponent);
</span><span class="cx">             else
</span><span class="cx">                 exponentIsNaN = m_out.booleanFalse;
</span><del>-            m_out.branch(exponentIsNaN, rarely(nanExceptionResultIsNaN), usually(nanExceptionExponentIsInfinity));
</del><ins>+            m_out.branch(exponentIsNaN, rarely(nanExceptionResultIsNaN), usually(nanExceptionBaseIsOne));
</ins><span class="cx"> 
</span><span class="cx">             // If abs(x) is 1 and y is +infinity, the result is NaN.
</span><span class="cx">             // If abs(x) is 1 and y is -infinity, the result is NaN.
</span><del>-            m_out.appendTo(nanExceptionExponentIsInfinity, nanExceptionBaseIsOne);
-            LValue absoluteExponent = m_out.doubleAbs(exponent);
-            LValue absoluteExponentIsInfinity = m_out.doubleEqual(absoluteExponent, m_out.constDouble(std::numeric_limits&lt;double&gt;::infinity()));
-            m_out.branch(absoluteExponentIsInfinity, rarely(nanExceptionBaseIsOne), usually(powBlock));
</del><span class="cx"> 
</span><del>-            m_out.appendTo(nanExceptionBaseIsOne, powBlock);
</del><ins>+            //     Test if base == 1.
+            m_out.appendTo(nanExceptionBaseIsOne, nanExceptionExponentIsInfinity);
</ins><span class="cx">             LValue absoluteBase = m_out.doubleAbs(base);
</span><span class="cx">             LValue absoluteBaseIsOne = m_out.doubleEqual(absoluteBase, m_out.constDouble(1));
</span><del>-            m_out.branch(absoluteBaseIsOne, unsure(nanExceptionResultIsNaN), unsure(powBlock));
</del><ins>+            m_out.branch(absoluteBaseIsOne, rarely(nanExceptionExponentIsInfinity), usually(testExponentIsOneHalf));
</ins><span class="cx"> 
</span><ins>+            //     Test if abs(y) == Infinity.
+            m_out.appendTo(nanExceptionExponentIsInfinity, testExponentIsOneHalf);
+            LValue absoluteExponent = m_out.doubleAbs(exponent);
+            LValue absoluteExponentIsInfinity = m_out.doubleEqual(absoluteExponent, m_out.constDouble(std::numeric_limits&lt;double&gt;::infinity()));
+            m_out.branch(absoluteExponentIsInfinity, rarely(nanExceptionResultIsNaN), usually(testExponentIsOneHalf));
+
+            // If y == 0.5 or y == -0.5, handle it through SQRT.
+            // We have be carefuly with -0 and -Infinity.
+
+            //     Test if y == 0.5
+            m_out.appendTo(testExponentIsOneHalf, handleBaseZeroExponentIsOneHalf);
+            LValue exponentIsOneHalf = m_out.doubleEqual(exponent, m_out.constDouble(0.5));
+            m_out.branch(exponentIsOneHalf, rarely(handleBaseZeroExponentIsOneHalf), usually(testExponentIsNegativeOneHalf));
+
+            //     Handle x == -0.
+            m_out.appendTo(handleBaseZeroExponentIsOneHalf, handleInfinityForExponentIsOneHalf);
+            LValue baseIsZeroExponentIsOneHalf = m_out.doubleEqual(base, m_out.doubleZero);
+            ValueFromBlock zeroResultExponentIsOneHalf = m_out.anchor(m_out.doubleZero);
+            m_out.branch(baseIsZeroExponentIsOneHalf, rarely(continuation), usually(handleInfinityForExponentIsOneHalf));
+
+            //     Test if abs(x) == Infinity.
+            m_out.appendTo(handleInfinityForExponentIsOneHalf, exponentIsOneHalfNormal);
+            LValue absoluteBaseIsInfinityOneHalf = m_out.doubleEqual(absoluteBase, m_out.constDouble(std::numeric_limits&lt;double&gt;::infinity()));
+            m_out.branch(absoluteBaseIsInfinityOneHalf, rarely(exponentIsOneHalfInfinity), usually(exponentIsOneHalfNormal));
+
+            //     The exponent is 0.5, the base is finite or NaN, we can use SQRT.
+            m_out.appendTo(exponentIsOneHalfNormal, exponentIsOneHalfInfinity);
+            ValueFromBlock sqrtResult = m_out.anchor(m_out.doubleSqrt(base));
+            m_out.jump(continuation);
+
+            //     The exponent is 0.5, the base is infinite, the result is always infinite.
+            m_out.appendTo(exponentIsOneHalfInfinity, testExponentIsNegativeOneHalf);
+            ValueFromBlock sqrtInfinityResult = m_out.anchor(m_out.constDouble(std::numeric_limits&lt;double&gt;::infinity()));
+            m_out.jump(continuation);
+
+            //     Test if y == -0.5
+            m_out.appendTo(testExponentIsNegativeOneHalf, testBaseZeroExponentIsNegativeOneHalf);
+            LValue exponentIsNegativeOneHalf = m_out.doubleEqual(exponent, m_out.constDouble(-0.5));
+            m_out.branch(exponentIsNegativeOneHalf, rarely(testBaseZeroExponentIsNegativeOneHalf), usually(powBlock));
+
+            //     Handle x == -0.
+            m_out.appendTo(testBaseZeroExponentIsNegativeOneHalf, handleBaseZeroExponentIsNegativeOneHalf);
+            LValue baseIsZeroExponentIsNegativeOneHalf = m_out.doubleEqual(base, m_out.doubleZero);
+            m_out.branch(baseIsZeroExponentIsNegativeOneHalf, rarely(handleBaseZeroExponentIsNegativeOneHalf), usually(handleInfinityForExponentIsNegativeOneHalf));
+
+            m_out.appendTo(handleBaseZeroExponentIsNegativeOneHalf, handleInfinityForExponentIsNegativeOneHalf);
+            ValueFromBlock oneOverSqrtZeroResult = m_out.anchor(m_out.constDouble(std::numeric_limits&lt;double&gt;::infinity()));
+            m_out.jump(continuation);
+
+            //     Test if abs(x) == Infinity.
+            m_out.appendTo(handleInfinityForExponentIsNegativeOneHalf, exponentIsNegativeOneHalfNormal);
+            LValue absoluteBaseIsInfinityNegativeOneHalf = m_out.doubleEqual(absoluteBase, m_out.constDouble(std::numeric_limits&lt;double&gt;::infinity()));
+            m_out.branch(absoluteBaseIsInfinityNegativeOneHalf, rarely(exponentIsNegativeOneHalfInfinity), usually(exponentIsNegativeOneHalfNormal));
+
+            //     The exponent is -0.5, the base is finite or NaN, we can use 1/SQRT.
+            m_out.appendTo(exponentIsNegativeOneHalfNormal, exponentIsNegativeOneHalfInfinity);
+            LValue sqrtBase = m_out.doubleSqrt(base);
+            ValueFromBlock oneOverSqrtResult = m_out.anchor(m_out.div(m_out.constDouble(1.), sqrtBase));
+            m_out.jump(continuation);
+
+            //     The exponent is -0.5, the base is infinite, the result is always zero.
+            m_out.appendTo(exponentIsNegativeOneHalfInfinity, powBlock);
+            ValueFromBlock oneOverSqrtInfinityResult = m_out.anchor(m_out.doubleZero);
+            m_out.jump(continuation);
+
</ins><span class="cx">             m_out.appendTo(powBlock, nanExceptionResultIsNaN);
</span><span class="cx">             ValueFromBlock powResult = m_out.anchor(m_out.doublePow(base, exponent));
</span><span class="cx">             m_out.jump(continuation);
</span><span class="lines">@@ -1908,7 +1981,7 @@
</span><span class="cx">             m_out.jump(continuation);
</span><span class="cx"> 
</span><span class="cx">             m_out.appendTo(continuation, lastNext);
</span><del>-            setDouble(m_out.phi(m_out.doubleType, powDoubleIntResult, powResult, pureNan));
</del><ins>+            setDouble(m_out.phi(m_out.doubleType, powDoubleIntResult, zeroResultExponentIsOneHalf, sqrtResult, sqrtInfinityResult, oneOverSqrtZeroResult, oneOverSqrtResult, oneOverSqrtInfinityResult, powResult, pureNan));
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitThunkGeneratorscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp (200207 => 200208)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp        2016-04-28 20:31:12 UTC (rev 200207)
+++ trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp        2016-04-28 20:50:08 UTC (rev 200208)
</span><span class="lines">@@ -782,8 +782,6 @@
</span><span class="cx"> defineUnaryDoubleOpWrapper(ceil);
</span><span class="cx"> defineUnaryDoubleOpWrapper(trunc);
</span><span class="cx"> 
</span><del>-static const double oneConstant = 1.0;
-static const double negativeHalfConstant = -0.5;
</del><span class="cx"> static const double halfConstant = 0.5;
</span><span class="cx">     
</span><span class="cx"> MacroAssemblerCodeRef floorThunkGenerator(VM* vm)
</span><span class="lines">@@ -992,58 +990,6 @@
</span><span class="cx">     return jit.finalize(vm-&gt;jitStubs-&gt;ctiNativeTailCall(vm), &quot;abs&quot;);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MacroAssemblerCodeRef powThunkGenerator(VM* vm)
-{
-    SpecializedThunkJIT jit(vm, 2);
-    if (!jit.supportsFloatingPoint())
-        return MacroAssemblerCodeRef::createSelfManagedCodeRef(vm-&gt;jitStubs-&gt;ctiNativeCall(vm));
-
-    jit.loadDouble(MacroAssembler::TrustedImmPtr(&amp;oneConstant), SpecializedThunkJIT::fpRegT1);
-    jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
-    MacroAssembler::Jump nonIntExponent;
-    jit.loadInt32Argument(1, SpecializedThunkJIT::regT0, nonIntExponent);
-    jit.appendFailure(jit.branch32(MacroAssembler::LessThan, SpecializedThunkJIT::regT0, MacroAssembler::TrustedImm32(0)));
-    
-    MacroAssembler::Jump exponentIsZero = jit.branchTest32(MacroAssembler::Zero, SpecializedThunkJIT::regT0);
-    MacroAssembler::Label startLoop(jit.label());
-
-    MacroAssembler::Jump exponentIsEven = jit.branchTest32(MacroAssembler::Zero, SpecializedThunkJIT::regT0, MacroAssembler::TrustedImm32(1));
-    jit.mulDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT1);
-    exponentIsEven.link(&amp;jit);
-    jit.mulDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT0);
-    jit.rshift32(MacroAssembler::TrustedImm32(1), SpecializedThunkJIT::regT0);
-    jit.branchTest32(MacroAssembler::NonZero, SpecializedThunkJIT::regT0).linkTo(startLoop, &amp;jit);
-
-    exponentIsZero.link(&amp;jit);
-
-    {
-        SpecializedThunkJIT::JumpList doubleResult;
-        jit.branchConvertDoubleToInt32(SpecializedThunkJIT::fpRegT1, SpecializedThunkJIT::regT0, doubleResult, SpecializedThunkJIT::fpRegT0);
-        jit.returnInt32(SpecializedThunkJIT::regT0);
-        doubleResult.link(&amp;jit);
-        jit.returnDouble(SpecializedThunkJIT::fpRegT1);
-    }
-
-    if (jit.supportsFloatingPointSqrt()) {
-        nonIntExponent.link(&amp;jit);
-        jit.loadDouble(MacroAssembler::TrustedImmPtr(&amp;negativeHalfConstant), SpecializedThunkJIT::fpRegT3);
-        jit.loadDoubleArgument(1, SpecializedThunkJIT::fpRegT2, SpecializedThunkJIT::regT0);
-        jit.appendFailure(jit.branchDouble(MacroAssembler::DoubleLessThanOrEqual, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT1));
-        jit.appendFailure(jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, SpecializedThunkJIT::fpRegT2, SpecializedThunkJIT::fpRegT3));
-        jit.sqrtDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT0);
-        jit.divDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT1);
-
-        SpecializedThunkJIT::JumpList doubleResult;
-        jit.branchConvertDoubleToInt32(SpecializedThunkJIT::fpRegT1, SpecializedThunkJIT::regT0, doubleResult, SpecializedThunkJIT::fpRegT0);
-        jit.returnInt32(SpecializedThunkJIT::regT0);
-        doubleResult.link(&amp;jit);
-        jit.returnDouble(SpecializedThunkJIT::fpRegT1);
-    } else
-        jit.appendFailure(nonIntExponent);
-
-    return jit.finalize(vm-&gt;jitStubs-&gt;ctiNativeTailCall(vm), &quot;pow&quot;);
-}
-
</del><span class="cx"> MacroAssemblerCodeRef imulThunkGenerator(VM* vm)
</span><span class="cx"> {
</span><span class="cx">     SpecializedThunkJIT jit(vm, 2);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitThunkGeneratorsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/ThunkGenerators.h (200207 => 200208)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/ThunkGenerators.h        2016-04-28 20:31:12 UTC (rev 200207)
+++ trunk/Source/JavaScriptCore/jit/ThunkGenerators.h        2016-04-28 20:50:08 UTC (rev 200208)
</span><span class="lines">@@ -61,7 +61,6 @@
</span><span class="cx"> MacroAssemblerCodeRef logThunkGenerator(VM*);
</span><span class="cx"> MacroAssemblerCodeRef roundThunkGenerator(VM*);
</span><span class="cx"> MacroAssemblerCodeRef sqrtThunkGenerator(VM*);
</span><del>-MacroAssemblerCodeRef powThunkGenerator(VM*);
</del><span class="cx"> MacroAssemblerCodeRef imulThunkGenerator(VM*);
</span><span class="cx"> MacroAssemblerCodeRef randomThunkGenerator(VM*);
</span><span class="cx"> MacroAssemblerCodeRef truncThunkGenerator(VM*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeMathCommoncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/MathCommon.cpp (200207 => 200208)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/MathCommon.cpp        2016-04-28 20:31:12 UTC (rev 200207)
+++ trunk/Source/JavaScriptCore/runtime/MathCommon.cpp        2016-04-28 20:50:08 UTC (rev 200208)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -414,21 +414,40 @@
</span><span class="cx"> {
</span><span class="cx">     if (std::isnan(y))
</span><span class="cx">         return PNaN;
</span><del>-    if (std::isinf(y) &amp;&amp; fabs(x) == 1)
</del><ins>+    double absoluteBase = fabs(x);
+    if (absoluteBase == 1 &amp;&amp; std::isinf(y))
</ins><span class="cx">         return PNaN;
</span><ins>+
+    if (y == 0.5) {
+        if (!absoluteBase)
+            return 0;
+        if (absoluteBase == std::numeric_limits&lt;double&gt;::infinity())
+            return std::numeric_limits&lt;double&gt;::infinity();
+        return sqrt(x);
+    }
+
+    if (y == -0.5) {
+        if (!absoluteBase)
+            return std::numeric_limits&lt;double&gt;::infinity();
+        if (absoluteBase == std::numeric_limits&lt;double&gt;::infinity())
+            return 0.;
+        return 1. / sqrt(x);
+    }
+
</ins><span class="cx">     int32_t yAsInt = y;
</span><del>-    if (static_cast&lt;double&gt;(yAsInt) != y || yAsInt &lt; 0)
-        return mathPowInternal(x, y);
</del><ins>+    if (static_cast&lt;double&gt;(yAsInt) == y &amp;&amp; yAsInt &gt; 0 &amp;&amp; yAsInt &lt;= maxExponentForIntegerMathPow) {
+        // If the exponent is a small positive int32 integer, we do a fast exponentiation
+        double result = 1;
+        while (yAsInt) {
+            if (yAsInt &amp; 1)
+                result *= x;
+            x *= x;
+            yAsInt &gt;&gt;= 1;
+        }
+        return result;
</ins><span class="cx"> 
</span><del>-    // If the exponent is a positive int32 integer, we do a fast exponentiation
-    double result = 1;
-    while (yAsInt) {
-        if (yAsInt &amp; 1)
-            result *= x;
-        x *= x;
-        yAsInt &gt;&gt;= 1;
</del><span class="cx">     }
</span><del>-    return result;
</del><ins>+    return mathPowInternal(x, y);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> extern &quot;C&quot; {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeMathCommonh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/MathCommon.h (200207 => 200208)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/MathCommon.h        2016-04-28 20:31:12 UTC (rev 200207)
+++ trunk/Source/JavaScriptCore/runtime/MathCommon.h        2016-04-28 20:50:08 UTC (rev 200208)
</span><span class="lines">@@ -35,6 +35,8 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><ins>+
+const int32_t maxExponentForIntegerMathPow = 1000;
</ins><span class="cx"> double JIT_OPERATION operationMathPow(double x, double y) WTF_INTERNAL;
</span><span class="cx"> 
</span><span class="cx"> inline int clz32(uint32_t number)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.cpp (200207 => 200208)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.cpp        2016-04-28 20:31:12 UTC (rev 200207)
+++ trunk/Source/JavaScriptCore/runtime/VM.cpp        2016-04-28 20:50:08 UTC (rev 200208)
</span><span class="lines">@@ -474,8 +474,6 @@
</span><span class="cx">         return fromCharCodeThunkGenerator;
</span><span class="cx">     case SqrtIntrinsic:
</span><span class="cx">         return sqrtThunkGenerator;
</span><del>-    case PowIntrinsic:
-        return powThunkGenerator;
</del><span class="cx">     case AbsIntrinsic:
</span><span class="cx">         return absThunkGenerator;
</span><span class="cx">     case FloorIntrinsic:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressmathpowstableresultsjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/math-pow-stable-results.js (0 => 200208)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/math-pow-stable-results.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/math-pow-stable-results.js        2016-04-28 20:50:08 UTC (rev 200208)
</span><span class="lines">@@ -0,0 +1,85 @@
</span><ins>+// This test verify the results of Math.pow() do not change as we change optimization tier.
+
+function opaquePow(a, b)
+{
+    return Math.pow(a, b);
+}
+noInline(opaquePow);
+
+
+let caseStrings = [
+    &quot;0&quot;,
+    &quot;-0.&quot;,
+    &quot;0.5&quot;,
+    &quot;1&quot;,
+    &quot;2&quot;,
+    &quot;-0.5&quot;,
+    &quot;-1&quot;,
+    &quot;999&quot;,
+    &quot;1000&quot;,
+    &quot;1001&quot;,
+    &quot;NaN&quot;,
+    &quot;Infinity&quot;,
+    &quot;-Infinity&quot;,
+    &quot;Math.PI&quot;,
+    &quot;Math.LN2&quot;,
+    &quot;Math.LN10&quot;,
+    &quot;Math.E&quot;,
+    &quot;Math.LOG10E&quot;,
+    &quot;Math.LOG2E&quot;,
+    &quot;Math.SQRT2&quot;
+];
+let cases = [];
+for (let caseString of caseStrings) {
+    cases.push(eval(caseString));
+}
+
+let expectedResults = [];
+let constantBaseFunctions = [];
+let constantExponentFunctions = [];
+for (let i = 0; i &lt; cases.length; ++i) {
+    let base = cases[i];
+
+    expectedResults[i] = [];
+    for (let j = 0; j &lt; cases.length; ++j) {
+        let exponent = cases[j];
+        expectedResults[i][j] = Math.pow(base, exponent);
+    }
+
+    eval(&quot;constantBaseFunctions[i] = function (exponent) { return Math.pow(&quot; + caseStrings[i] + &quot;, exponent); }&quot;);
+    eval(&quot;constantExponentFunctions[i] = function (base) { return Math.pow(base, &quot; + caseStrings[i] + &quot;); }&quot;);
+}
+
+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;
+}
+
+for (let tierUpLoopCounter = 0; tierUpLoopCounter &lt; 1e3; ++tierUpLoopCounter) {
+    for (let i = 0; i &lt; cases.length; ++i) {
+        let base = cases[i];
+        for (let j = 0; j &lt; cases.length; ++j) {
+            let exponent = cases[j];
+            let expectedResult = expectedResults[i][j];
+            let result = opaquePow(base, exponent);
+            if (!isIdentical(result, expectedResult))
+                throw &quot;Failed opaquePow with base = &quot; + base + &quot; exponent = &quot; + exponent;
+
+            result = constantBaseFunctions[i](exponent);
+            if (!isIdentical(result, expectedResult))
+                throw &quot;Failed constantBaseFunctions with base = &quot; + base + &quot; exponent = &quot; + exponent;
+
+            result = constantExponentFunctions[j](base);
+            if (!isIdentical(result, expectedResult))
+                throw &quot;Failed constantExponentFunctions with base = &quot; + base + &quot; exponent = &quot; + exponent;
+        }
+    }
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressmathpowwithconstantsjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/tests/stress/math-pow-with-constants.js (200207 => 200208)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/math-pow-with-constants.js        2016-04-28 20:31:12 UTC (rev 200207)
+++ trunk/Source/JavaScriptCore/tests/stress/math-pow-with-constants.js        2016-04-28 20:50:08 UTC (rev 200208)
</span><span class="lines">@@ -44,21 +44,91 @@
</span><span class="cx"> noInline(powUsedAsSqrt);
</span><span class="cx"> 
</span><span class="cx"> function testPowUsedAsSqrt() {
</span><del>-    for (var i = 0; i &lt; 10000; ++i) {
-        var result = powUsedAsSqrt(4);
</del><ins>+    for (let i = 0; i &lt; 1e4; ++i) {
+        let result = powUsedAsSqrt(4);
</ins><span class="cx">         if (result !== Math.sqrt(4))
</span><span class="cx">             throw &quot;Error: powUsedAsSqrt(4) should be 2, was = &quot; + result;
</span><del>-    }
-    for (var i = 0; i &lt; 10000; ++i) {
-        var result = powUsedAsSqrt(4.4);
</del><ins>+        result = powUsedAsSqrt(4.4);
</ins><span class="cx">         if (result !== Math.sqrt(4.4))
</span><span class="cx">             throw &quot;Error: powUsedAsSqrt(4) should be &quot; + Math.sqrt(4.4) + &quot;, was = &quot; + result;
</span><ins>+        if (powUsedAsSqrt(Infinity) !== Infinity)
+            throw &quot;Failed powUsedAsSqrt(Infinity)&quot;;
+        if (powUsedAsSqrt(-Infinity) !== Infinity)
+            throw &quot;Failed powUsedAsSqrt(-Infinity)&quot;;
+        let nanResult = powUsedAsSqrt(NaN)
+        if (nanResult === nanResult)
+            throw &quot;Failed powUsedAsSqrt(NaN)&quot;;
+        let zeroResult = powUsedAsSqrt(0.)
+        if (zeroResult || (1 / zeroResult) !== Infinity)
+            throw &quot;Failed powUsedAsSqrt(0.)&quot;;
+        let negativeZeroResult = powUsedAsSqrt(-0)
+        if (negativeZeroResult || (1 / negativeZeroResult) !== Infinity)
+            throw &quot;Failed powUsedAsSqrt(-0)&quot;;
</ins><span class="cx">     }
</span><del>-
</del><span class="cx"> }
</span><span class="cx"> testPowUsedAsSqrt();
</span><span class="cx"> 
</span><ins>+function powUsedAsOneOverSqrt(x) {
+    return Math.pow(x, -0.5);
+}
+noInline(powUsedAsOneOverSqrt);
</ins><span class="cx"> 
</span><ins>+function testPowUsedAsOneOverSqrt() {
+    for (let i = 0; i &lt; 1e4; ++i) {
+        let result = powUsedAsOneOverSqrt(4);
+        if (result !== 0.5)
+            throw &quot;Error: powUsedAsOneOverSqrt(4) should be 0.5, was = &quot; + result;
+        result = powUsedAsOneOverSqrt(4.4);
+        if (result !== 1/Math.sqrt(4.4))
+            throw &quot;Error: powUsedAsOneOverSqrt(4) should be &quot; + 1/Math.sqrt(4.4) + &quot;, was = &quot; + result;
+        if (powUsedAsOneOverSqrt(Infinity) !== 0)
+            throw &quot;Failed powUsedAsOneOverSqrt(Infinity)&quot;;
+        if (powUsedAsOneOverSqrt(-Infinity) !== 0)
+            throw &quot;Failed powUsedAsOneOverSqrt(-Infinity)&quot;;
+        let nanResult = powUsedAsOneOverSqrt(NaN)
+        if (nanResult === nanResult)
+            throw &quot;Failed powUsedAsOneOverSqrt(NaN)&quot;;
+        if (powUsedAsOneOverSqrt(0) !== Infinity)
+            throw &quot;Failed powUsedAsOneOverSqrt(0)&quot;;
+        if (powUsedAsOneOverSqrt(-0.) !== Infinity)
+            throw &quot;Failed powUsedAsOneOverSqrt(-0.)&quot;;
+    }
+}
+testPowUsedAsOneOverSqrt();
+
+function powUsedAsSquare(x) {
+    return Math.pow(x, 2);
+}
+noInline(powUsedAsSquare);
+
+function testPowUsedAsSquare() {
+    for (let i = 0; i &lt; 1e4; ++i) {
+        let result = powUsedAsSquare(2);
+        if (result !== 4)
+            throw &quot;Error: powUsedAsSquare(4) should be 2, was = &quot; + result;
+        result = powUsedAsSquare(4.4);
+        if (result !== 19.360000000000003)
+            throw &quot;Error: powUsedAsSquare(4) should be &quot; + 19.360000000000003 + &quot;, was = &quot; + result;
+        result = powUsedAsSquare(Math.PI);
+        if (result !== 9.869604401089358)
+            throw &quot;Error: powUsedAsSquare(4) should be &quot; + 9.869604401089358 + &quot;, was = &quot; + result;
+        if (powUsedAsSquare(Infinity) !== Infinity)
+            throw &quot;Failed powUsedAsSquare(Infinity)&quot;;
+        if (powUsedAsSquare(-Infinity) !== Infinity)
+            throw &quot;Failed powUsedAsSquare(-Infinity)&quot;;
+        let nanResult = powUsedAsSquare(NaN)
+        if (nanResult === nanResult)
+            throw &quot;Failed powUsedAsSquare(NaN)&quot;;
+        let zeroResult = powUsedAsSquare(0.)
+        if (zeroResult || (1 / zeroResult) !== Infinity)
+            throw &quot;Failed powUsedAsSquare(0.)&quot;;
+        let negativeZeroResult = powUsedAsSquare(-0)
+        if (negativeZeroResult || (1 / negativeZeroResult) !== Infinity)
+            throw &quot;Failed powUsedAsSquare(-0)&quot;;
+    }
+}
+testPowUsedAsSquare();
+
</ins><span class="cx"> function intIntConstantsSmallNumbers() {
</span><span class="cx">     return Math.pow(42, 3);
</span><span class="cx"> }
</span></span></pre>
</div>
</div>

</body>
</html>