Title: [243277] trunk
Revision
243277
Author
[email protected]
Date
2019-03-20 22:41:21 -0700 (Wed, 20 Mar 2019)

Log Message

typeOfDoubleSum is wrong for when NaN can be produced
https://bugs.webkit.org/show_bug.cgi?id=196030

Reviewed by Filip Pizlo.

JSTests:

* stress/double-add-sub-mul-can-produce-nan.js: Added.
(assert):
(noInline.sub):
(noInline):
(assert.mul):
(assert.add):

Source/_javascript_Core:

We were using typeOfDoubleSum(SpeculatedType, SpeculatedType) for add/sub/mul.
It assumed that the only way the resulting type could be NaN is if one of
the inputs were NaN. However, this is wrong. NaN can be produced in at least
these cases:
  Infinity - Infinity
  Infinity + (-Infinity)
  Infinity * 0

* bytecode/SpeculatedType.cpp:
(JSC::typeOfDoubleSumOrDifferenceOrProduct):
(JSC::typeOfDoubleSum):
(JSC::typeOfDoubleDifference):
(JSC::typeOfDoubleProduct):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (243276 => 243277)


--- trunk/JSTests/ChangeLog	2019-03-21 04:38:29 UTC (rev 243276)
+++ trunk/JSTests/ChangeLog	2019-03-21 05:41:21 UTC (rev 243277)
@@ -1,3 +1,17 @@
+2019-03-20  Saam Barati  <[email protected]>
+
+        typeOfDoubleSum is wrong for when NaN can be produced
+        https://bugs.webkit.org/show_bug.cgi?id=196030
+
+        Reviewed by Filip Pizlo.
+
+        * stress/double-add-sub-mul-can-produce-nan.js: Added.
+        (assert):
+        (noInline.sub):
+        (noInline):
+        (assert.mul):
+        (assert.add):
+
 2019-03-20  Yusuke Suzuki  <[email protected]>
 
         Update the test to ensure OutOfMemoryError is thrown as intended

Added: trunk/JSTests/stress/double-add-sub-mul-can-produce-nan.js (0 => 243277)


--- trunk/JSTests/stress/double-add-sub-mul-can-produce-nan.js	                        (rev 0)
+++ trunk/JSTests/stress/double-add-sub-mul-can-produce-nan.js	2019-03-21 05:41:21 UTC (rev 243277)
@@ -0,0 +1,77 @@
+"use strict";
+
+function assert(b) {
+    if (!b)
+        throw new Error;
+}
+noInline(assert);
+
+{
+    function sub(arr, b, c) {
+        let x = b - c;
+        arr[0] = x;
+    }
+    noInline(sub);
+
+
+    for (let i = 0; i < 10000; ++i) {
+        let arr = [];
+        arr.length = 2;
+        arr[1] = 10.5;
+        sub(arr, 10.5, 20.5);
+        assert(0 in arr);
+    }
+
+    let arr = [];
+    arr.length = 2;
+    arr[1] = 10.5;
+    sub(arr, Infinity, Infinity);
+    assert(typeof arr[0] === "number" && isNaN(arr[0]));
+    assert(0 in arr);
+}
+
+{
+    function mul(arr, b, c) {
+        let x = b * c;
+        arr[0] = x;
+    }
+    noInline(mul);
+
+    for (let i = 0; i < 10000; ++i) {
+        let arr = [];
+        arr.length = 2;
+        arr[1] = 10.5;
+        mul(arr, 10.5, 20.5);
+        assert(0 in arr);
+    }
+
+    let arr = [];
+    arr.length = 2;
+    arr[1] = 10.5;
+    mul(arr, Infinity, 0);
+    assert(typeof arr[0] === "number" && isNaN(arr[0]));
+    assert(0 in arr);
+}
+
+{
+    function add(arr, b, c) {
+        let x = b + c;
+        arr[0] = x;
+    }
+    noInline(add);
+
+    for (let i = 0; i < 10000; ++i) {
+        let arr = [];
+        arr.length = 2;
+        arr[1] = 10.5;
+        add(arr, 10.5, 20.5);
+        assert(0 in arr);
+    }
+
+    let arr = [];
+    arr.length = 2;
+    arr[1] = 10.5;
+    add(arr, Infinity, -Infinity);
+    assert(typeof arr[0] === "number" && isNaN(arr[0]));
+    assert(0 in arr);
+}

Modified: trunk/Source/_javascript_Core/ChangeLog (243276 => 243277)


--- trunk/Source/_javascript_Core/ChangeLog	2019-03-21 04:38:29 UTC (rev 243276)
+++ trunk/Source/_javascript_Core/ChangeLog	2019-03-21 05:41:21 UTC (rev 243277)
@@ -1,3 +1,24 @@
+2019-03-20  Saam Barati  <[email protected]>
+
+        typeOfDoubleSum is wrong for when NaN can be produced
+        https://bugs.webkit.org/show_bug.cgi?id=196030
+
+        Reviewed by Filip Pizlo.
+
+        We were using typeOfDoubleSum(SpeculatedType, SpeculatedType) for add/sub/mul.
+        It assumed that the only way the resulting type could be NaN is if one of
+        the inputs were NaN. However, this is wrong. NaN can be produced in at least
+        these cases:
+          Infinity - Infinity
+          Infinity + (-Infinity)
+          Infinity * 0
+
+        * bytecode/SpeculatedType.cpp:
+        (JSC::typeOfDoubleSumOrDifferenceOrProduct):
+        (JSC::typeOfDoubleSum):
+        (JSC::typeOfDoubleDifference):
+        (JSC::typeOfDoubleProduct):
+
 2019-03-20  Simon Fraser  <[email protected]>
 
         Rename ENABLE_ACCELERATED_OVERFLOW_SCROLLING macro to ENABLE_OVERFLOW_SCROLLING_TOUCH

Modified: trunk/Source/_javascript_Core/bytecode/SpeculatedType.cpp (243276 => 243277)


--- trunk/Source/_javascript_Core/bytecode/SpeculatedType.cpp	2019-03-21 04:38:29 UTC (rev 243276)
+++ trunk/Source/_javascript_Core/bytecode/SpeculatedType.cpp	2019-03-21 05:41:21 UTC (rev 243277)
@@ -612,9 +612,18 @@
     return !!(a & b);
 }
 
-SpeculatedType typeOfDoubleSum(SpeculatedType a, SpeculatedType b)
+static SpeculatedType typeOfDoubleSumOrDifferenceOrProduct(SpeculatedType a, SpeculatedType b)
 {
     SpeculatedType result = a | b;
+
+    if (result & SpecNonIntAsDouble) {
+        // NaN can be produced by:
+        // Infinity - Infinity
+        // Infinity + (-Infinity)
+        // Infinity * 0
+        result |= SpecDoublePureNaN;
+    }
+
     // Impure NaN could become pure NaN during addition because addition may clear bits.
     if (result & SpecDoubleImpureNaN)
         result |= SpecDoublePureNaN;
@@ -624,14 +633,19 @@
     return result;
 }
 
+SpeculatedType typeOfDoubleSum(SpeculatedType a, SpeculatedType b)
+{
+    return typeOfDoubleSumOrDifferenceOrProduct(a, b);
+}
+
 SpeculatedType typeOfDoubleDifference(SpeculatedType a, SpeculatedType b)
 {
-    return typeOfDoubleSum(a, b);
+    return typeOfDoubleSumOrDifferenceOrProduct(a, b);
 }
 
 SpeculatedType typeOfDoubleProduct(SpeculatedType a, SpeculatedType b)
 {
-    return typeOfDoubleSum(a, b);
+    return typeOfDoubleSumOrDifferenceOrProduct(a, b);
 }
 
 static SpeculatedType polluteDouble(SpeculatedType value)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to