[JSC] Int52Rep(DoubleRepAnyIntUse) should not call operation function
authorysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 22 Sep 2019 09:57:48 +0000 (09:57 +0000)
committerysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 22 Sep 2019 09:57:48 +0000 (09:57 +0000)
https://bugs.webkit.org/show_bug.cgi?id=202072

Reviewed by Mark Lam.

JSTests:

* stress/int52rep-with-double-checks-int52-range.js: Added.
(shouldBe):
(test):

Source/JavaScriptCore:

Inline doubleToStrictInt52 in FTL since it is very simple function.
This change improves JetStream2/stanford-crypto-sha256 by ~5%.

* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::doubleToStrictInt52):
* ftl/FTLOutput.cpp:
(JSC::FTL::Output::doubleToInt64):
* ftl/FTLOutput.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@250200 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JSTests/ChangeLog
JSTests/stress/int52rep-with-double-checks-int52-range-simple.js [new file with mode: 0644]
JSTests/stress/int52rep-with-double-checks-int52-range.js [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
Source/JavaScriptCore/ftl/FTLOutput.cpp
Source/JavaScriptCore/ftl/FTLOutput.h

index 0c7089c..bd77a22 100644 (file)
@@ -1,3 +1,14 @@
+2019-09-22  Yusuke Suzuki  <ysuzuki@apple.com>
+
+        [JSC] Int52Rep(DoubleRepAnyIntUse) should not call operation function
+        https://bugs.webkit.org/show_bug.cgi?id=202072
+
+        Reviewed by Mark Lam.
+
+        * stress/int52rep-with-double-checks-int52-range.js: Added.
+        (shouldBe):
+        (test):
+
 2019-09-21  Caio Lima  <ticaiolima@gmail.com>
 
         stress/test-out-of-memory.js is not throwing OOM into ARMv7 and MIPS
 2019-09-21  Caio Lima  <ticaiolima@gmail.com>
 
         stress/test-out-of-memory.js is not throwing OOM into ARMv7 and MIPS
diff --git a/JSTests/stress/int52rep-with-double-checks-int52-range-simple.js b/JSTests/stress/int52rep-with-double-checks-int52-range-simple.js
new file mode 100644 (file)
index 0000000..cd3e5e7
--- /dev/null
@@ -0,0 +1,35 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+var doubleArray = [3, 1, 2, 3, 4, 5.5];
+doubleArray[0] = 3; // Break CoW.
+
+function test(array)
+{
+    return fiatInt52(array[0]);
+}
+noInline(test);
+
+for (var i = 0; i < 1e7; ++i)
+    shouldBe(test(doubleArray), 3);
+doubleArray[0] = 0x7ffffffffffff;
+shouldBe(test(doubleArray), 0x7ffffffffffff);
+doubleArray[0] = 0x8000000000000;
+shouldBe(test(doubleArray), 0x8000000000000);
+doubleArray[0] = -0x8000000000000;
+shouldBe(test(doubleArray), -0x8000000000000);
+doubleArray[0] = -0x8000000000001;
+shouldBe(test(doubleArray), -0x8000000000001);
+doubleArray[0] = 1.3;
+shouldBe(test(doubleArray), 1.3);
+doubleArray[0] = Number.NaN;
+shouldBe(Number.isNaN(test(doubleArray)), true);
+doubleArray[0] = Number.POSITIVE_INFINITY;
+shouldBe(test(doubleArray), Number.POSITIVE_INFINITY);
+doubleArray[0] = Number.NEGATIVE_INFINITY;
+shouldBe(test(doubleArray), Number.NEGATIVE_INFINITY);
+
+doubleArray[0] = 3;
+shouldBe(test(doubleArray), 3);
diff --git a/JSTests/stress/int52rep-with-double-checks-int52-range.js b/JSTests/stress/int52rep-with-double-checks-int52-range.js
new file mode 100644 (file)
index 0000000..c64aece
--- /dev/null
@@ -0,0 +1,35 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+var doubleArray = [3, 1, 2, 3, 4, 5.5];
+doubleArray[0] = 3; // Break CoW.
+
+function test(array)
+{
+    return fiatInt52(array[0]) + 0xffffffff;
+}
+noInline(test);
+
+for (var i = 0; i < 1e6; ++i)
+    shouldBe(test(doubleArray), 0xffffffff + 3);
+doubleArray[0] = 0x7ffffffffffff;
+shouldBe(test(doubleArray), 0x80000fffffffe);
+doubleArray[0] = 0x8000000000000;
+shouldBe(test(doubleArray), 0x80000ffffffff);
+doubleArray[0] = -0x8000000000000;
+shouldBe(test(doubleArray), -0x7ffff00000001);
+doubleArray[0] = -0x8000000000001;
+shouldBe(test(doubleArray), -0x7ffff00000002);
+doubleArray[0] = 1.3;
+shouldBe(test(doubleArray), 4294967296.3);
+doubleArray[0] = Number.NaN;
+shouldBe(Number.isNaN(test(doubleArray)), true);
+doubleArray[0] = Number.POSITIVE_INFINITY;
+shouldBe(test(doubleArray), Number.POSITIVE_INFINITY);
+doubleArray[0] = Number.NEGATIVE_INFINITY;
+shouldBe(test(doubleArray), Number.NEGATIVE_INFINITY);
+
+doubleArray[0] = 3;
+shouldBe(test(doubleArray), 0xffffffff + 3);
index 126e443..c3d9d36 100644 (file)
@@ -1,5 +1,21 @@
 2019-09-22  Yusuke Suzuki  <ysuzuki@apple.com>
 
 2019-09-22  Yusuke Suzuki  <ysuzuki@apple.com>
 
+        [JSC] Int52Rep(DoubleRepAnyIntUse) should not call operation function
+        https://bugs.webkit.org/show_bug.cgi?id=202072
+
+        Reviewed by Mark Lam.
+
+        Inline doubleToStrictInt52 in FTL since it is very simple function.
+        This change improves JetStream2/stanford-crypto-sha256 by ~5%.
+
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::doubleToStrictInt52):
+        * ftl/FTLOutput.cpp:
+        (JSC::FTL::Output::doubleToInt64):
+        * ftl/FTLOutput.h:
+
+2019-09-22  Yusuke Suzuki  <ysuzuki@apple.com>
+
         Unreviewed, follow-up change after r250198
         https://bugs.webkit.org/show_bug.cgi?id=201633
 
         Unreviewed, follow-up change after r250198
         https://bugs.webkit.org/show_bug.cgi?id=201633
 
index f1f7dc3..a140b0b 100644 (file)
@@ -15885,16 +15885,33 @@ private:
             
         return m_out.phi(Int64, intToInt52, doubleToInt52);
     }
             
         return m_out.phi(Int64, intToInt52, doubleToInt52);
     }
-    
+
     LValue doubleToStrictInt52(Edge edge, LValue value)
     {
     LValue doubleToStrictInt52(Edge edge, LValue value)
     {
-        LValue possibleResult = m_out.call(
-            Int64, m_out.operation(operationConvertDoubleToInt52), value);
-        FTL_TYPE_CHECK_WITH_EXIT_KIND(Int52Overflow,
-            doubleValue(value), edge, SpecAnyIntAsDouble,
-            m_out.equal(possibleResult, m_out.constInt64(JSValue::notInt52)));
-        
-        return possibleResult;
+        LValue integerValue = m_out.doubleToInt64(value);
+        LValue integerValueConvertedToDouble = m_out.intToDouble(integerValue);
+        LValue valueNotConvertibleToInteger = m_out.doubleNotEqualOrUnordered(value, integerValueConvertedToDouble);
+        speculate(Int52Overflow, doubleValue(value), edge.node(), valueNotConvertibleToInteger);
+
+        LBasicBlock valueIsZero = m_out.newBlock();
+        LBasicBlock valueIsNotZero = m_out.newBlock();
+        LBasicBlock continuation = m_out.newBlock();
+        m_out.branch(m_out.isZero64(integerValue), unsure(valueIsZero), unsure(valueIsNotZero));
+
+        LBasicBlock lastNext = m_out.appendTo(valueIsZero, valueIsNotZero);
+        LValue doubleBitcastToInt64 = m_out.bitCast(value, Int64);
+        LValue signBitSet = m_out.lessThan(doubleBitcastToInt64, m_out.constInt64(0));
+        speculate(Int52Overflow, doubleValue(value), edge.node(), signBitSet);
+        m_out.jump(continuation);
+
+        m_out.appendTo(valueIsNotZero, continuation);
+        speculate(Int52Overflow, doubleValue(value), edge.node(), m_out.greaterThanOrEqual(integerValue, m_out.constInt64(static_cast<int64_t>(1) << (JSValue::numberOfInt52Bits - 1))));
+        speculate(Int52Overflow, doubleValue(value), edge.node(), m_out.lessThan(integerValue, m_out.constInt64(-(static_cast<int64_t>(1) << (JSValue::numberOfInt52Bits - 1)))));
+        m_out.jump(continuation);
+
+        m_out.appendTo(continuation, lastNext);
+        m_interpreter.filter(edge, SpecAnyIntAsDouble);
+        return integerValue;
     }
 
     LValue convertDoubleToInt32(LValue value, bool shouldCheckNegativeZero)
     }
 
     LValue convertDoubleToInt32(LValue value, bool shouldCheckNegativeZero)
index cc4bb39..74933dc 100644 (file)
@@ -333,6 +333,18 @@ LValue Output::doubleToInt(LValue value)
     return result;
 }
 
     return result;
 }
 
+LValue Output::doubleToInt64(LValue value)
+{
+    PatchpointValue* result = patchpoint(Int64);
+    result->append(value, ValueRep::SomeRegister);
+    result->setGenerator(
+        [] (CCallHelpers& jit, const StackmapGenerationParams& params) {
+            jit.truncateDoubleToInt64(params[1].fpr(), params[0].gpr());
+        });
+    result->effects = Effects::none();
+    return result;
+}
+
 LValue Output::doubleToUInt(LValue value)
 {
     PatchpointValue* result = patchpoint(Int32);
 LValue Output::doubleToUInt(LValue value)
 {
     PatchpointValue* result = patchpoint(Int32);
index a15cce4..45db1d9 100644 (file)
@@ -188,6 +188,7 @@ public:
     LValue doubleLog(LValue);
 
     LValue doubleToInt(LValue);
     LValue doubleLog(LValue);
 
     LValue doubleToInt(LValue);
+    LValue doubleToInt64(LValue);
     LValue doubleToUInt(LValue);
 
     LValue signExt32To64(LValue);
     LValue doubleToUInt(LValue);
 
     LValue signExt32To64(LValue);