<!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>[187497] 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/187497">187497</a></dd>
<dt>Author</dt> <dd>basile_clement@apple.com</dd>
<dt>Date</dt> <dd>2015-07-28 11:51:27 -0700 (Tue, 28 Jul 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>stress/math-pow-with-constants.js fails in cloop
https://bugs.webkit.org/show_bug.cgi?id=147167

Reviewed by Geoffrey Garen.

Baseline JIT, DFG and FTL are using a fast exponentiation fast path
when computing Math.pow() with an integer exponent that is not taken in
the LLInt (or the DFG abstract interpreter). This leads to the result
of pow changing depending on the compilation tier or the fact that
constant propagation kicks in, which is undesirable.

This patch adds the fast path to the slow operationMathPow in order to
maintain an illusion of consistency.

* runtime/MathCommon.cpp:
(JSC::operationMathPow):
* tests/stress/math-pow-coherency.js: Added.
(pow42):
(build42AsDouble.opaqueAdd):
(build42AsDouble):
(powDouble42):
(clobber):
(pow42NoConstantFolding):
(powDouble42NoConstantFolding):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeMathCommoncpp">trunk/Source/JavaScriptCore/runtime/MathCommon.cpp</a></li>
</ul>

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

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (187496 => 187497)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-07-28 18:47:14 UTC (rev 187496)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-07-28 18:51:27 UTC (rev 187497)
</span><span class="lines">@@ -1,3 +1,30 @@
</span><ins>+2015-07-28  Basile Clement  &lt;basile_clement@apple.com&gt;
+
+        stress/math-pow-with-constants.js fails in cloop
+        https://bugs.webkit.org/show_bug.cgi?id=147167
+
+        Reviewed by Geoffrey Garen.
+
+        Baseline JIT, DFG and FTL are using a fast exponentiation fast path
+        when computing Math.pow() with an integer exponent that is not taken in
+        the LLInt (or the DFG abstract interpreter). This leads to the result
+        of pow changing depending on the compilation tier or the fact that
+        constant propagation kicks in, which is undesirable.
+
+        This patch adds the fast path to the slow operationMathPow in order to
+        maintain an illusion of consistency.
+
+        * runtime/MathCommon.cpp:
+        (JSC::operationMathPow):
+        * tests/stress/math-pow-coherency.js: Added.
+        (pow42):
+        (build42AsDouble.opaqueAdd):
+        (build42AsDouble):
+        (powDouble42):
+        (clobber):
+        (pow42NoConstantFolding):
+        (powDouble42NoConstantFolding):
+
</ins><span class="cx"> 2015-07-28  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: Show Pseudo Elements in DOM Tree
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeMathCommoncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/MathCommon.cpp (187496 => 187497)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/MathCommon.cpp        2015-07-28 18:47:14 UTC (rev 187496)
+++ trunk/Source/JavaScriptCore/runtime/MathCommon.cpp        2015-07-28 18:51:27 UTC (rev 187497)
</span><span class="lines">@@ -417,7 +417,19 @@
</span><span class="cx">         return PNaN;
</span><span class="cx">     if (std::isinf(y) &amp;&amp; fabs(x) == 1)
</span><span class="cx">         return PNaN;
</span><del>-    return mathPowInternal(x, y);
</del><ins>+    int32_t yAsInt = y;
+    if (static_cast&lt;double&gt;(yAsInt) != y || yAsInt &lt; 0)
+        return mathPowInternal(x, y);
+
+    // 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;
+    }
+    return result;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> extern &quot;C&quot; {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressmathpowcoherencyjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/math-pow-coherency.js (0 => 187497)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/math-pow-coherency.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/math-pow-coherency.js        2015-07-28 18:51:27 UTC (rev 187497)
</span><span class="lines">@@ -0,0 +1,93 @@
</span><ins>+// This test checks that the pow function returns coherent results:
+// (a) Across different compilation tiers
+// (b) With integer exponents represented as int32 or as double
+
+function pow42() {
+    return { value: Math.pow(2.1, 42), ftl: isFinalTier() };
+}
+
+function build42AsDouble() {
+    function opaqueAdd(x, y) { return x + y; }
+    return opaqueAdd(42 - 0.123, 0.123);
+}
+
+var double42 = build42AsDouble();
+
+if (double42 !== 42)
+    throw new Error(&quot;42 (as double) should be === to 42 (as int)&quot;);
+
+function powDouble42() {
+    return { value: Math.pow(2.1, double42), ftl: isFinalTier() };
+}
+
+function clobber() { }
+noInline(clobber);
+
+function pow42NoConstantFolding() {
+    var obj = { x: 2.1, y: 42 };
+    clobber(obj);
+    return { value: Math.pow(obj.x, obj.y), ftl: isFinalTier() };
+}
+
+function powDouble42NoConstantFolding() {
+    var obj = { x: 2.1, y: double42 };
+    clobber(obj);
+    return { value: Math.pow(obj.x, obj.y), ftl: isFinalTier() };
+}
+
+var results = { 'jit': {}, 'dfg': {}, 'ftl': {} };
+var funs = [
+    [ 'pow42', pow42 ],
+    [ 'powDouble42', powDouble42 ],
+    [ 'pow42NoConstantFolding', pow42NoConstantFolding ],
+    [ 'powDouble42NoConstantFolding', powDouble42NoConstantFolding ]
+];
+var tiers = ['jit', 'dfg', 'ftl'];
+
+for (var i = 0; i &lt; 1000000; ++i) {
+    for (var j in funs) {
+        var name = funs[j][0];
+        var fun = funs[j][1];
+        var result = fun();
+        if (result.ftl)
+            results['ftl'][name] = result.value;
+        else if (numberOfDFGCompiles(fun) &gt; 0)
+            results['dfg'][name] = result.value;
+        else
+            results['jit'][name] = result.value;
+    }
+}
+
+var errors = [];
+var valuesFor = {};
+for (var i in tiers) {
+    var tier = tiers[i];
+    var result = results[tier];
+    // We don't have this tier
+    if (Object.keys(result).length === 0)
+        continue;
+
+    for (var j in funs) {
+        var name = funs[j][0];
+        if (!(name in result))
+            errors.push(name + &quot; was not compiled to &quot; + tier);
+        else if (!(name in valuesFor))
+            valuesFor[name] = { value: result[name], tiers: [tier] };
+        else if (result[name] !== valuesFor[name].value)
+            errors.push(name + &quot; has different results in &quot; + tier + &quot; (&quot; + result[name] + &quot;) and &quot; + valuesFor[name].tiers + &quot; (&quot; + valuesFor[name].value + &quot;)&quot;);
+        else
+            valuesFor[name].tiers.push(tier);
+    }
+}
+
+var reference = funs[0][0];
+var result = valuesFor[reference].value;
+
+for (var j in funs) {
+    var name = funs[j][0];
+    if (valuesFor[name].value !== result)
+        errors.push(name + &quot; (&quot; + valuesFor[name].value + &quot;) and &quot; + reference + &quot; (&quot; + result + &quot;) have different results&quot;);
+}
+
+if (errors.length &gt; 0)
+    throw new Error(errors.join('\n'));
</ins></span></pre>
</div>
</div>

</body>
</html>