Title: [232567] trunk
Revision
232567
Author
utatane....@gmail.com
Date
2018-06-06 19:28:01 -0700 (Wed, 06 Jun 2018)

Log Message

[DFG] Compare operations do not respect negative zeros
https://bugs.webkit.org/show_bug.cgi?id=183729

Reviewed by Saam Barati.

JSTests:

* stress/comparison-ignore-negative-zero.js: Added.
(shouldBe):
(zero):
(negativeZero):
(object.valueOf):
(test):

Source/_javascript_Core:

Compare operations do not respect negative zeros. So propagating this can
reduce the size of the produced code for negative zero case. This pattern
can be seen in Kraken stanford-crypto-aes.

This also causes an existing bug which converts CompareEq(Int32Only, NonIntAsdouble) to false.
However, NonIntAsdouble includes negative zero, which can be equal to Int32 positive zero.
This issue is covered by fold-based-on-int32-proof-mul-branch.js, and we fix this.

* bytecode/SpeculatedType.cpp:
(JSC::leastUpperBoundOfStrictlyEquivalentSpeculations):
SpecNonIntAsDouble includes negative zero (-0.0), which can be equal to 0 and 0.0.
To emphasize this, we use SpecAnyIntAsDouble | SpecNonIntAsDouble directly instead of
SpecDoubleReal.

* dfg/DFGBackwardsPropagationPhase.cpp:
(JSC::DFG::BackwardsPropagationPhase::propagate):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (232566 => 232567)


--- trunk/JSTests/ChangeLog	2018-06-07 00:57:34 UTC (rev 232566)
+++ trunk/JSTests/ChangeLog	2018-06-07 02:28:01 UTC (rev 232567)
@@ -1,3 +1,17 @@
+2018-06-06  Yusuke Suzuki  <utatane....@gmail.com>
+
+        [DFG] Compare operations do not respect negative zeros
+        https://bugs.webkit.org/show_bug.cgi?id=183729
+
+        Reviewed by Saam Barati.
+
+        * stress/comparison-ignore-negative-zero.js: Added.
+        (shouldBe):
+        (zero):
+        (negativeZero):
+        (object.valueOf):
+        (test):
+
 2018-06-06  Saam Barati  <sbar...@apple.com>
 
         generateConditionsForInstanceOf needs to see if the object has a poly proto structure before assuming it has a constant prototype

Added: trunk/JSTests/stress/comparison-ignore-negative-zero.js (0 => 232567)


--- trunk/JSTests/stress/comparison-ignore-negative-zero.js	                        (rev 0)
+++ trunk/JSTests/stress/comparison-ignore-negative-zero.js	2018-06-07 02:28:01 UTC (rev 232567)
@@ -0,0 +1,65 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + String(actual) + ' ' + String(expected));
+}
+noInline(shouldBe);
+
+function zero()
+{
+    return 0;
+}
+noInline(zero);
+
+function negativeZero()
+{
+    return -0;
+}
+noInline(negativeZero);
+
+var object = {
+    valueOf()
+    {
+        return -0;
+    }
+};
+
+function test()
+{
+    shouldBe(0 < zero(), false);
+    shouldBe(0 < (-zero()), false);
+    shouldBe(0 <= zero(), true);
+    shouldBe(0 <= (-zero()), true);
+    shouldBe(0 > zero(), false);
+    shouldBe(0 > (-zero()), false);
+    shouldBe(0 >= zero(), true);
+    shouldBe(0 >= (-zero()), true);
+    shouldBe(0 == zero(), true);
+    shouldBe(0 == (-zero()), true);
+    shouldBe(0 === zero(), true);
+    shouldBe(0 === (-zero()), true);
+    shouldBe(0 != zero(), false);
+    shouldBe(0 != (-zero()), false);
+    shouldBe(0 !== zero(), false);
+    shouldBe(0 !== (-zero()), false);
+
+    shouldBe(0 < object, false);
+    shouldBe(0 < -object, false);
+    shouldBe(0 <= object, true);
+    shouldBe(0 <= -object, true);
+    shouldBe(0 > object, false);
+    shouldBe(0 > -object, false);
+    shouldBe(0 >= object, true);
+    shouldBe(0 >= -object, true);
+    shouldBe(0 == object, true);
+    shouldBe(0 == -object, true);
+    shouldBe(0 === object, false);
+    shouldBe(0 === -object, true);
+    shouldBe(0 != object, false);
+    shouldBe(0 != -object, false);
+    shouldBe(0 !== object, true);
+    shouldBe(0 !== -object, false);
+}
+noInline(test);
+
+for (var i = 0; i < 1e5; ++i)
+    test();

Modified: trunk/Source/_javascript_Core/ChangeLog (232566 => 232567)


--- trunk/Source/_javascript_Core/ChangeLog	2018-06-07 00:57:34 UTC (rev 232566)
+++ trunk/Source/_javascript_Core/ChangeLog	2018-06-07 02:28:01 UTC (rev 232567)
@@ -1,3 +1,27 @@
+2018-06-06  Yusuke Suzuki  <utatane....@gmail.com>
+
+        [DFG] Compare operations do not respect negative zeros
+        https://bugs.webkit.org/show_bug.cgi?id=183729
+
+        Reviewed by Saam Barati.
+
+        Compare operations do not respect negative zeros. So propagating this can
+        reduce the size of the produced code for negative zero case. This pattern
+        can be seen in Kraken stanford-crypto-aes.
+
+        This also causes an existing bug which converts CompareEq(Int32Only, NonIntAsdouble) to false.
+        However, NonIntAsdouble includes negative zero, which can be equal to Int32 positive zero.
+        This issue is covered by fold-based-on-int32-proof-mul-branch.js, and we fix this.
+
+        * bytecode/SpeculatedType.cpp:
+        (JSC::leastUpperBoundOfStrictlyEquivalentSpeculations):
+        SpecNonIntAsDouble includes negative zero (-0.0), which can be equal to 0 and 0.0.
+        To emphasize this, we use SpecAnyIntAsDouble | SpecNonIntAsDouble directly instead of
+        SpecDoubleReal.
+
+        * dfg/DFGBackwardsPropagationPhase.cpp:
+        (JSC::DFG::BackwardsPropagationPhase::propagate):
+
 2018-06-06  Saam Barati  <sbar...@apple.com>
 
         generateConditionsForInstanceOf needs to see if the object has a poly proto structure before assuming it has a constant prototype

Modified: trunk/Source/_javascript_Core/bytecode/SpeculatedType.cpp (232566 => 232567)


--- trunk/Source/_javascript_Core/bytecode/SpeculatedType.cpp	2018-06-07 00:57:34 UTC (rev 232566)
+++ trunk/Source/_javascript_Core/bytecode/SpeculatedType.cpp	2018-06-07 02:28:01 UTC (rev 232567)
@@ -567,8 +567,10 @@
 
 SpeculatedType leastUpperBoundOfStrictlyEquivalentSpeculations(SpeculatedType type)
 {
-    if (type & (SpecAnyInt | SpecAnyIntAsDouble))
-        type |= (SpecAnyInt | SpecAnyIntAsDouble);
+    // SpecNonIntAsDouble includes negative zero (-0.0), which can be equal to 0 and 0.0 in the context of == and ===.
+    if (type & (SpecAnyInt | SpecAnyIntAsDouble | SpecNonIntAsDouble))
+        type |= (SpecAnyInt | SpecAnyIntAsDouble | SpecNonIntAsDouble);
+
     if (type & SpecString)
         type |= SpecString;
     return type;

Modified: trunk/Source/_javascript_Core/dfg/DFGBackwardsPropagationPhase.cpp (232566 => 232567)


--- trunk/Source/_javascript_Core/dfg/DFGBackwardsPropagationPhase.cpp	2018-06-07 00:57:34 UTC (rev 232566)
+++ trunk/Source/_javascript_Core/dfg/DFGBackwardsPropagationPhase.cpp	2018-06-07 02:28:01 UTC (rev 232567)
@@ -388,6 +388,19 @@
             break;
         }
 
+        case CompareLess:
+        case CompareLessEq:
+        case CompareGreater:
+        case CompareGreaterEq:
+        case CompareBelow:
+        case CompareBelowEq:
+        case CompareEq:
+        case CompareStrictEq: {
+            node->child1()->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther);
+            node->child2()->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsOther);
+            break;
+        }
+
         case PutByValDirect:
         case PutByVal: {
             m_graph.varArgChild(node, 0)->mergeFlags(NodeBytecodeUsesAsValue);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to