Title: [264575] trunk
Revision
264575
Author
[email protected]
Date
2020-07-18 21:24:20 -0700 (Sat, 18 Jul 2020)

Log Message

Fixed regression due to r264507: Math.{min|max} inequality test should use DoubleNotEqualOrUnordered instead DoubleNotEqualAndOrdered.
https://bugs.webkit.org/show_bug.cgi?id=214526
<rdar://problem/65778061>

Reviewed by Yusuke Suzuki.

JSTests:

* stress/math-max-min.js: Added.
(isNegativeZero):
(numberAsString):
(testMax):
(testMin):
(assertEq):

Source/_javascript_Core:

This bug resulted in NaNs being handled by the "equal" case in some scenarios,
which resulted in an assertion failure in a ValueRep on an internal test.

* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileArithMinMax):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (264574 => 264575)


--- trunk/JSTests/ChangeLog	2020-07-18 23:09:56 UTC (rev 264574)
+++ trunk/JSTests/ChangeLog	2020-07-19 04:24:20 UTC (rev 264575)
@@ -1,3 +1,18 @@
+2020-07-18  Mark Lam  <[email protected]>
+
+        Fixed regression due to r264507: Math.{min|max} inequality test should use DoubleNotEqualOrUnordered instead DoubleNotEqualAndOrdered.
+        https://bugs.webkit.org/show_bug.cgi?id=214526
+        <rdar://problem/65778061>
+
+        Reviewed by Yusuke Suzuki.
+
+        * stress/math-max-min.js: Added.
+        (isNegativeZero):
+        (numberAsString):
+        (testMax):
+        (testMin):
+        (assertEq):
+
 2020-07-18  Alexey Shvayka  <[email protected]>
 
         Redefining a property should not change its insertion index (Object.keys order)

Added: trunk/JSTests/stress/math-max-min.js (0 => 264575)


--- trunk/JSTests/stress/math-max-min.js	                        (rev 0)
+++ trunk/JSTests/stress/math-max-min.js	2020-07-19 04:24:20 UTC (rev 264575)
@@ -0,0 +1,118 @@
+//@ runDefault("--useConcurrentJIT=false")
+
+let operands = [
+    0,
+    -0,
+    1,
+    -1,
+    42,
+    -42,
+    -Number.EPSILON,
+    Number.EPSILON,
+    -Number.MIN_VALUE,
+    Number.MIN_VALUE,
+    -Number.MAX_VALUE,
+    Number.MAX_VALUE,
+    Number.MIN_SAFE_INTEGER,
+    Number.MAX_SAFE_INTEGER,
+    Number.NEGATIVE_INFINITY,
+    Number.POSITIVE_INFINITY,
+    Number.NaN,
+];
+
+function isNegativeZero(x) {
+    if (x != 0)
+        return false;
+    return (1/x == Number.NEGATIVE_INFINITY);
+}
+
+let expectedMaxResults = [];
+for (i in operands) {
+    expectedMaxResults[i] = [];
+    for (j in operands) {
+        let x = operands[i];
+        let y = operands[j];
+        let result;
+        if (Number.isNaN(x) || Number.isNaN(y))
+            result = Number.NaN;
+        else if (x == y)
+            result = isNegativeZero(x) ? y : x;
+        else 
+            result = (x > y) ? x : y;
+        expectedMaxResults[i][j] = result;
+    }
+}
+
+let expectedMinResults = [];
+for (i in operands) {
+    expectedMinResults[i] = [];
+    for (j in operands) {
+        let x = operands[i];
+        let y = operands[j];
+        let result;
+        if (Number.isNaN(x) || Number.isNaN(y))
+            result = Number.NaN;
+        else if (x == y)
+            result = isNegativeZero(x) ? x : y;
+        else 
+            result = (x < y) ? x : y;
+        expectedMinResults[i][j] = result;
+    }
+}
+
+function numberAsString(x) {
+    if (x == 0 && isNegativeZero(x))
+        return "-0";
+    return x;
+}
+
+function testMax(x, y) {
+    return Math.max(x, y);
+}
+noInline(testMax);
+
+function testMin(x, y) {
+    return Math.min(x, y);
+}
+noInline(testMin);
+
+let numberOfFailures = 0;
+
+function assertEq(label, x, y, expected, actual) {
+    if (Number.isNaN(expected) && Number.isNaN(actual))
+        return;
+
+    if ((actual == expected) && (actual == 0)) {
+        if (isNegativeZero(expected) != isNegativeZero(actual)) {
+            print("FAIL " + label + ": comparing " + numberAsString(x) + " and " + numberAsString(y) + ": expected: " + numberAsString(expected) + " actual: " + numberAsString(actual));
+            numberOfFailures++;
+            return;
+        }
+    }
+
+    if (expected !== actual) {
+        print("FAIL " + label + ": comparing " + numberAsString(x) + " and " + numberAsString(y) + ": expected: " + numberAsString(expected) + " actual: " + numberAsString(actual));
+        numberOfFailures++;
+        return;
+    }
+}
+
+for (var iteration = 0; iteration < 1000; ++iteration) {
+    for (i in operands) {
+        for (j in operands) {
+            let x = operands[i];
+            let y = operands[j];
+
+            let maxResult = testMax(x, y);
+            let expectedMaxResult = expectedMaxResults[i][j];
+            assertEq("Math.max", x, y, expectedMaxResult, maxResult);
+
+            let minResult = testMin(x, y);
+            let expectedMinResult = expectedMinResults[i][j];
+            assertEq("Math.min", x, y, expectedMinResult, minResult);
+        }
+    }
+}
+
+if (numberOfFailures > 0)
+    throw "FAILED";

Modified: trunk/Source/_javascript_Core/ChangeLog (264574 => 264575)


--- trunk/Source/_javascript_Core/ChangeLog	2020-07-18 23:09:56 UTC (rev 264574)
+++ trunk/Source/_javascript_Core/ChangeLog	2020-07-19 04:24:20 UTC (rev 264575)
@@ -1,3 +1,17 @@
+2020-07-18  Mark Lam  <[email protected]>
+
+        Fixed regression due to r264507: Math.{min|max} inequality test should use DoubleNotEqualOrUnordered instead DoubleNotEqualAndOrdered.
+        https://bugs.webkit.org/show_bug.cgi?id=214526
+        <rdar://problem/65778061>
+
+        Reviewed by Yusuke Suzuki.
+
+        This bug resulted in NaNs being handled by the "equal" case in some scenarios,
+        which resulted in an assertion failure in a ValueRep on an internal test.
+
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileArithMinMax):
+
 2020-07-18  Alexey Shvayka  <[email protected]>
 
         Redefining a property should not change its insertion index (Object.keys order)

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (264574 => 264575)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2020-07-18 23:09:56 UTC (rev 264574)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2020-07-19 04:24:20 UTC (rev 264575)
@@ -6181,7 +6181,7 @@
         MacroAssembler::JumpList done;
 
         MacroAssembler::Jump op1Less = m_jit.branchDouble(node->op() == ArithMin ? MacroAssembler::DoubleLessThanAndOrdered : MacroAssembler::DoubleGreaterThanAndOrdered, op1FPR, op2FPR);
-        MacroAssembler::Jump opNotEqual = m_jit.branchDouble(MacroAssembler::DoubleNotEqualAndOrdered, op1FPR, op2FPR);
+        MacroAssembler::Jump opNotEqualOrUnordered = m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, op1FPR, op2FPR);
 
         // The spec for Math.min and Math.max states that +0 is considered to be larger than -0.
         if (node->op() == ArithMin)
@@ -6191,11 +6191,11 @@
 
         done.append(m_jit.jump());
 
-        opNotEqual.link(&m_jit);
+        opNotEqualOrUnordered.link(&m_jit);
         // op2 is either the lesser one or one of then is NaN
         MacroAssembler::Jump op2Less = m_jit.branchDouble(node->op() == ArithMin ? MacroAssembler::DoubleGreaterThanAndOrdered : MacroAssembler::DoubleLessThanAndOrdered, op1FPR, op2FPR);
 
-        // Unordered case. We don't know which of op1, op2 is NaN. Manufacture NaN by adding 
+        // Unordered case. We don't know which of op1, op2 is NaN. Manufacture NaN by adding
         // op1 + op2 and putting it into result.
         m_jit.addDouble(op1FPR, op2FPR, resultFPR);
         done.append(m_jit.jump());
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to