Title: [187497] trunk/Source/_javascript_Core
- Revision
- 187497
- Author
- [email protected]
- Date
- 2015-07-28 11:51:27 -0700 (Tue, 28 Jul 2015)
Log Message
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):
Modified Paths
Added Paths
Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (187496 => 187497)
--- trunk/Source/_javascript_Core/ChangeLog 2015-07-28 18:47:14 UTC (rev 187496)
+++ trunk/Source/_javascript_Core/ChangeLog 2015-07-28 18:51:27 UTC (rev 187497)
@@ -1,3 +1,30 @@
+2015-07-28 Basile Clement <[email protected]>
+
+ 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):
+
2015-07-28 Joseph Pecoraro <[email protected]>
Web Inspector: Show Pseudo Elements in DOM Tree
Modified: trunk/Source/_javascript_Core/runtime/MathCommon.cpp (187496 => 187497)
--- trunk/Source/_javascript_Core/runtime/MathCommon.cpp 2015-07-28 18:47:14 UTC (rev 187496)
+++ trunk/Source/_javascript_Core/runtime/MathCommon.cpp 2015-07-28 18:51:27 UTC (rev 187497)
@@ -417,7 +417,19 @@
return PNaN;
if (std::isinf(y) && fabs(x) == 1)
return PNaN;
- return mathPowInternal(x, y);
+ int32_t yAsInt = y;
+ if (static_cast<double>(yAsInt) != y || yAsInt < 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 & 1)
+ result *= x;
+ x *= x;
+ yAsInt >>= 1;
+ }
+ return result;
}
extern "C" {
Added: trunk/Source/_javascript_Core/tests/stress/math-pow-coherency.js (0 => 187497)
--- trunk/Source/_javascript_Core/tests/stress/math-pow-coherency.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/math-pow-coherency.js 2015-07-28 18:51:27 UTC (rev 187497)
@@ -0,0 +1,93 @@
+// 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("42 (as double) should be === to 42 (as int)");
+
+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 < 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) > 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 + " was not compiled to " + tier);
+ else if (!(name in valuesFor))
+ valuesFor[name] = { value: result[name], tiers: [tier] };
+ else if (result[name] !== valuesFor[name].value)
+ errors.push(name + " has different results in " + tier + " (" + result[name] + ") and " + valuesFor[name].tiers + " (" + valuesFor[name].value + ")");
+ 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 + " (" + valuesFor[name].value + ") and " + reference + " (" + result + ") have different results");
+}
+
+if (errors.length > 0)
+ throw new Error(errors.join('\n'));
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes