Title: [231285] trunk/Source/_javascript_Core
Revision
231285
Author
[email protected]
Date
2018-05-02 17:46:09 -0700 (Wed, 02 May 2018)

Log Message

[JSC] Add compareDouble and compareFloat for ARM64, X86, and X86_64
https://bugs.webkit.org/show_bug.cgi?id=185192

Reviewed by Mark Lam.

Now Object.is starts using compareDouble. So we would like to have
efficient implementation for compareDouble and compareFloat for
major architectures, ARM64, X86, and X86_64.

This patch adds compareDouble and compareFloat implementations for
these architectures. And generic implementation is moved to each
architecture's MacroAssembler implementation.

We also add tests for them in testmasm. To implement this test
easily, we also add loadFloat(TrustedImmPtr, FPRegisterID) for the
major architectures.

* assembler/MacroAssembler.h:
(JSC::MacroAssembler::compareDouble): Deleted.
(JSC::MacroAssembler::compareFloat): Deleted.
* assembler/MacroAssemblerARM.h:
(JSC::MacroAssemblerARM::compareDouble):
* assembler/MacroAssemblerARM64.h:
(JSC::MacroAssemblerARM64::compareDouble):
(JSC::MacroAssemblerARM64::compareFloat):
(JSC::MacroAssemblerARM64::loadFloat):
(JSC::MacroAssemblerARM64::floatingPointCompare):
* assembler/MacroAssemblerARMv7.h:
(JSC::MacroAssemblerARMv7::compareDouble):
* assembler/MacroAssemblerMIPS.h:
(JSC::MacroAssemblerMIPS::compareDouble):
* assembler/MacroAssemblerX86Common.h:
(JSC::MacroAssemblerX86Common::loadFloat):
(JSC::MacroAssemblerX86Common::compareDouble):
(JSC::MacroAssemblerX86Common::compareFloat):
(JSC::MacroAssemblerX86Common::floatingPointCompare):
* assembler/X86Assembler.h:
(JSC::X86Assembler::movss_mr):
(JSC::X86Assembler::movss_rm):
* assembler/testmasm.cpp:
(JSC::floatOperands):
(JSC::testCompareFloat):
(JSC::run):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (231284 => 231285)


--- trunk/Source/_javascript_Core/ChangeLog	2018-05-03 00:42:12 UTC (rev 231284)
+++ trunk/Source/_javascript_Core/ChangeLog	2018-05-03 00:46:09 UTC (rev 231285)
@@ -1,5 +1,51 @@
 2018-05-02  Yusuke Suzuki  <[email protected]>
 
+        [JSC] Add compareDouble and compareFloat for ARM64, X86, and X86_64
+        https://bugs.webkit.org/show_bug.cgi?id=185192
+
+        Reviewed by Mark Lam.
+
+        Now Object.is starts using compareDouble. So we would like to have
+        efficient implementation for compareDouble and compareFloat for
+        major architectures, ARM64, X86, and X86_64.
+
+        This patch adds compareDouble and compareFloat implementations for
+        these architectures. And generic implementation is moved to each
+        architecture's MacroAssembler implementation.
+
+        We also add tests for them in testmasm. To implement this test
+        easily, we also add loadFloat(TrustedImmPtr, FPRegisterID) for the
+        major architectures.
+
+        * assembler/MacroAssembler.h:
+        (JSC::MacroAssembler::compareDouble): Deleted.
+        (JSC::MacroAssembler::compareFloat): Deleted.
+        * assembler/MacroAssemblerARM.h:
+        (JSC::MacroAssemblerARM::compareDouble):
+        * assembler/MacroAssemblerARM64.h:
+        (JSC::MacroAssemblerARM64::compareDouble):
+        (JSC::MacroAssemblerARM64::compareFloat):
+        (JSC::MacroAssemblerARM64::loadFloat):
+        (JSC::MacroAssemblerARM64::floatingPointCompare):
+        * assembler/MacroAssemblerARMv7.h:
+        (JSC::MacroAssemblerARMv7::compareDouble):
+        * assembler/MacroAssemblerMIPS.h:
+        (JSC::MacroAssemblerMIPS::compareDouble):
+        * assembler/MacroAssemblerX86Common.h:
+        (JSC::MacroAssemblerX86Common::loadFloat):
+        (JSC::MacroAssemblerX86Common::compareDouble):
+        (JSC::MacroAssemblerX86Common::compareFloat):
+        (JSC::MacroAssemblerX86Common::floatingPointCompare):
+        * assembler/X86Assembler.h:
+        (JSC::X86Assembler::movss_mr):
+        (JSC::X86Assembler::movss_rm):
+        * assembler/testmasm.cpp:
+        (JSC::floatOperands):
+        (JSC::testCompareFloat):
+        (JSC::run):
+
+2018-05-02  Yusuke Suzuki  <[email protected]>
+
         Unreviewed, fix 32bit DFG code
         https://bugs.webkit.org/show_bug.cgi?id=185065
 

Modified: trunk/Source/_javascript_Core/assembler/MacroAssembler.h (231284 => 231285)


--- trunk/Source/_javascript_Core/assembler/MacroAssembler.h	2018-05-03 00:42:12 UTC (rev 231284)
+++ trunk/Source/_javascript_Core/assembler/MacroAssembler.h	2018-05-03 00:46:09 UTC (rev 231285)
@@ -1462,26 +1462,6 @@
     // We should implement this the right way eventually, but for now, it's fine because it arises so
     // infrequently.
 
-#if !CPU(X86) && !CPU(X86_64)
-    void compareDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right, RegisterID dest)
-    {
-        move(TrustedImm32(0), dest);
-        Jump falseCase = branchDouble(invert(cond), left, right);
-        move(TrustedImm32(1), dest);
-        falseCase.link(this);
-    }
-#endif
-
-#if ENABLE(B3_JIT)
-    void compareFloat(DoubleCondition cond, FPRegisterID left, FPRegisterID right, RegisterID dest)
-    {
-        move(TrustedImm32(0), dest);
-        Jump falseCase = branchFloat(invert(cond), left, right);
-        move(TrustedImm32(1), dest);
-        falseCase.link(this);
-    }
-#endif
-
     void lea32(Address address, RegisterID dest)
     {
         add32(TrustedImm32(address.offset), address.base, dest);

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerARM.h (231284 => 231285)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerARM.h	2018-05-03 00:42:12 UTC (rev 231284)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerARM.h	2018-05-03 00:46:09 UTC (rev 231285)
@@ -1432,6 +1432,14 @@
         return Jump(m_assembler.jmp(static_cast<ARMAssembler::Condition>(cond & ~DoubleConditionMask)));
     }
 
+    void compareDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right, RegisterID dest)
+    {
+        move(TrustedImm32(0), dest);
+        Jump falseCase = branchDouble(invert(cond), left, right);
+        move(TrustedImm32(1), dest);
+        falseCase.link(this);
+    }
+
     // Truncates 'src' to an integer, and places the resulting 'dest'.
     // If the result is not representable as a 32 bit value, branch.
     // May also branch for some values that are representable in 32 bits

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h (231284 => 231285)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h	2018-05-03 00:42:12 UTC (rev 231284)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h	2018-05-03 00:46:09 UTC (rev 231285)
@@ -1697,6 +1697,20 @@
         return jumpAfterFloatingPointCompare(cond);
     }
 
+    void compareDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right, RegisterID dest)
+    {
+        floatingPointCompare(cond, left, right, dest, [this] (FPRegisterID arg1, FPRegisterID arg2) {
+            m_assembler.fcmp<64>(arg1, arg2);
+        });
+    }
+
+    void compareFloat(DoubleCondition cond, FPRegisterID left, FPRegisterID right, RegisterID dest)
+    {
+        floatingPointCompare(cond, left, right, dest, [this] (FPRegisterID arg1, FPRegisterID arg2) {
+            m_assembler.fcmp<32>(arg1, arg2);
+        });
+    }
+
     Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID)
     {
         m_assembler.fcmp_0<64>(reg);
@@ -1849,6 +1863,12 @@
         m_assembler.ldr<32>(dest, address.base, memoryTempRegister);
     }
 
+    void loadFloat(TrustedImmPtr address, FPRegisterID dest)
+    {
+        moveToCachedReg(address, cachedMemoryTempRegister());
+        m_assembler.ldr<32>(dest, memoryTempRegister, ARM64Registers::zr);
+    }
+
     void moveDouble(FPRegisterID src, FPRegisterID dest)
     {
         m_assembler.fmov<64>(dest, src);
@@ -4453,6 +4473,31 @@
         return makeBranch(cond);
     }
 
+    template<typename Function>
+    void floatingPointCompare(DoubleCondition cond, FPRegisterID left, FPRegisterID right, RegisterID dest, Function compare)
+    {
+        if (cond == DoubleNotEqual) {
+            // ConditionNE sets 1 if NotEqual *or* unordered - force the unordered cases not to set 1.
+            move(TrustedImm32(0), dest);
+            compare(left, right);
+            Jump unordered = makeBranch(Assembler::ConditionVS);
+            m_assembler.cset<32>(dest, Assembler::ConditionNE);
+            unordered.link(this);
+            return;
+        }
+        if (cond == DoubleEqualOrUnordered) {
+            // ConditionEQ sets 1 only if Equal - force the unordered cases to set 1 too.
+            move(TrustedImm32(1), dest);
+            compare(left, right);
+            Jump unordered = makeBranch(Assembler::ConditionVS);
+            m_assembler.cset<32>(dest, Assembler::ConditionEQ);
+            unordered.link(this);
+            return;
+        }
+        compare(left, right);
+        m_assembler.cset<32>(dest, ARM64Condition(cond));
+    }
+
     friend class LinkBuffer;
 
     template<PtrTag tag>

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerARMv7.h (231284 => 231285)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerARMv7.h	2018-05-03 00:42:12 UTC (rev 231284)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerARMv7.h	2018-05-03 00:46:09 UTC (rev 231285)
@@ -1197,6 +1197,14 @@
         return makeBranch(cond);
     }
 
+    void compareDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right, RegisterID dest)
+    {
+        move(TrustedImm32(0), dest);
+        Jump falseCase = branchDouble(invert(cond), left, right);
+        move(TrustedImm32(1), dest);
+        falseCase.link(this);
+    }
+
     enum BranchTruncateType { BranchIfTruncateFailed, BranchIfTruncateSuccessful };
     Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
     {

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerMIPS.h (231284 => 231285)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerMIPS.h	2018-05-03 00:42:12 UTC (rev 231284)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerMIPS.h	2018-05-03 00:46:09 UTC (rev 231285)
@@ -3307,6 +3307,14 @@
         return Jump();
     }
 
+    void compareDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right, RegisterID dest)
+    {
+        move(TrustedImm32(0), dest);
+        Jump falseCase = branchDouble(invert(cond), left, right);
+        move(TrustedImm32(1), dest);
+        falseCase.link(this);
+    }
+
     // Truncates 'src' to an integer, and places the resulting 'dest'.
     // If the result is not representable as a 32 bit value, branch.
     enum BranchTruncateType { BranchIfTruncateFailed, BranchIfTruncateSuccessful };

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h (231284 => 231285)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h	2018-05-03 00:42:12 UTC (rev 231284)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h	2018-05-03 00:46:09 UTC (rev 231285)
@@ -1455,6 +1455,17 @@
         m_assembler.movsd_mr(address.offset, address.base, address.index, address.scale, dest);
     }
 
+    void loadFloat(TrustedImmPtr address, FPRegisterID dest)
+    {
+#if CPU(X86)
+        ASSERT(isSSE2Present());
+        m_assembler.movss_mr(address.asPtr(), dest);
+#else
+        move(address, scratchRegister());
+        loadFloat(scratchRegister(), dest);
+#endif
+    }
+
     void loadFloat(ImplicitAddress address, FPRegisterID dest)
     {
         ASSERT(isSSE2Present());
@@ -2016,44 +2027,18 @@
 
     void compareDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right, RegisterID dest)
     {
-        if (cond & DoubleConditionBitSpecial) {
-            ASSERT(!(cond & DoubleConditionBitInvert));
-            if (cond == DoubleEqual) {
-                if (left == right) {
-                    m_assembler.ucomisd_rr(right, left);
-                    set32(X86Assembler::ConditionNP, dest);
-                    return;
-                }
+        ASSERT(isSSE2Present());
+        floatingPointCompare(cond, left, right, dest, [this] (FPRegisterID arg1, FPRegisterID arg2) {
+            m_assembler.ucomisd_rr(arg1, arg2);
+        });
+    }
 
-                move(TrustedImm32(0), dest);
-                m_assembler.ucomisd_rr(right, left);
-                Jump isUnordered = m_assembler.jp();
-                set32(X86Assembler::ConditionE, dest);
-                isUnordered.link(this);
-                return;
-            }
-            if (cond == DoubleNotEqualOrUnordered) {
-                if (left == right) {
-                    m_assembler.ucomisd_rr(right, left);
-                    set32(X86Assembler::ConditionP, dest);
-                    return;
-                }
-
-                move(TrustedImm32(1), dest);
-                m_assembler.ucomisd_rr(right, left);
-                Jump isUnordered = m_assembler.jp();
-                set32(X86Assembler::ConditionNE, dest);
-                isUnordered.link(this);
-                return;
-            }
-            return;
-        }
-
-        if (cond & DoubleConditionBitInvert)
-            m_assembler.ucomisd_rr(left, right);
-        else
-            m_assembler.ucomisd_rr(right, left);
-        set32(static_cast<X86Assembler::Condition>(cond & ~DoubleConditionBits), dest);
+    void compareFloat(DoubleCondition cond, FPRegisterID left, FPRegisterID right, RegisterID dest)
+    {
+        ASSERT(isSSE2Present());
+        floatingPointCompare(cond, left, right, dest, [this] (FPRegisterID arg1, FPRegisterID arg2) {
+            m_assembler.ucomiss_rr(arg1, arg2);
+        });
     }
 
     // Truncates 'src' to an integer, and places the resulting 'dest'.
@@ -4141,6 +4126,51 @@
         skipNonZeroCase.link(this);
     }
 
+    template<typename Function>
+    void floatingPointCompare(DoubleCondition cond, FPRegisterID left, FPRegisterID right, RegisterID dest, Function compare)
+    {
+        if (cond & DoubleConditionBitSpecial) {
+            ASSERT(!(cond & DoubleConditionBitInvert));
+            if (cond == DoubleEqual) {
+                if (left == right) {
+                    compare(right, left);
+                    set32(X86Assembler::ConditionNP, dest);
+                    return;
+                }
+
+                move(TrustedImm32(0), dest);
+                compare(right, left);
+                Jump isUnordered = m_assembler.jp();
+                set32(X86Assembler::ConditionE, dest);
+                isUnordered.link(this);
+                return;
+            }
+            if (cond == DoubleNotEqualOrUnordered) {
+                if (left == right) {
+                    compare(right, left);
+                    set32(X86Assembler::ConditionP, dest);
+                    return;
+                }
+
+                move(TrustedImm32(1), dest);
+                compare(right, left);
+                Jump isUnordered = m_assembler.jp();
+                set32(X86Assembler::ConditionNE, dest);
+                isUnordered.link(this);
+                return;
+            }
+
+            RELEASE_ASSERT_NOT_REACHED();
+            return;
+        }
+
+        if (cond & DoubleConditionBitInvert)
+            compare(left, right);
+        else
+            compare(right, left);
+        set32(static_cast<X86Assembler::Condition>(cond & ~DoubleConditionBits), dest);
+    }
+
     Jump jumpAfterFloatingPointCompare(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
     {
         if (cond == DoubleEqual) {

Modified: trunk/Source/_javascript_Core/assembler/X86Assembler.h (231284 => 231285)


--- trunk/Source/_javascript_Core/assembler/X86Assembler.h	2018-05-03 00:42:12 UTC (rev 231284)
+++ trunk/Source/_javascript_Core/assembler/X86Assembler.h	2018-05-03 00:46:09 UTC (rev 231285)
@@ -3161,6 +3161,16 @@
         m_formatter.prefix(PRE_SSE_F2);
         m_formatter.twoByteOpAddr(OP2_MOVSD_WsdVsd, (RegisterID)src, bitwise_cast<uint32_t>(address));
     }
+    void movss_mr(const void* address, XMMRegisterID dst)
+    {
+        m_formatter.prefix(PRE_SSE_F3);
+        m_formatter.twoByteOpAddr(OP2_MOVSD_VsdWsd, (RegisterID)dst, bitwise_cast<uint32_t>(address));
+    }
+    void movss_rm(XMMRegisterID src, const void* address)
+    {
+        m_formatter.prefix(PRE_SSE_F3);
+        m_formatter.twoByteOpAddr(OP2_MOVSD_WsdVsd, (RegisterID)src, bitwise_cast<uint32_t>(address));
+    }
 #endif
 
     void mulsd_rr(XMMRegisterID src, XMMRegisterID dst)

Modified: trunk/Source/_javascript_Core/assembler/testmasm.cpp (231284 => 231285)


--- trunk/Source/_javascript_Core/assembler/testmasm.cpp	2018-05-03 00:42:12 UTC (rev 231284)
+++ trunk/Source/_javascript_Core/assembler/testmasm.cpp	2018-05-03 00:46:09 UTC (rev 231285)
@@ -246,6 +246,25 @@
 }
 
 
+static Vector<float> floatOperands()
+{
+    return Vector<float> {
+        0,
+        -0,
+        1,
+        -1,
+        42,
+        -42,
+        std::numeric_limits<float>::max(),
+        std::numeric_limits<float>::min(),
+        std::numeric_limits<float>::lowest(),
+        std::numeric_limits<float>::quiet_NaN(),
+        std::numeric_limits<float>::infinity(),
+        -std::numeric_limits<float>::infinity(),
+    };
+}
+
+
 void testCompareDouble(MacroAssembler::DoubleCondition condition)
 {
     double arg1 = 0;
@@ -287,7 +306,49 @@
     }
 }
 
+#if CPU(X86) || CPU(X86_64) || CPU(ARM64)
+void testCompareFloat(MacroAssembler::DoubleCondition condition)
+{
+    float arg1 = 0;
+    float arg2 = 0;
 
+    auto compareFloat = compile([&, condition] (CCallHelpers& jit) {
+        jit.emitFunctionPrologue();
+
+        jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
+        jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg2), FPRInfo::fpRegT1);
+        jit.move(CCallHelpers::TrustedImm32(-1), GPRInfo::returnValueGPR);
+        jit.compareFloat(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT1, GPRInfo::returnValueGPR);
+
+        jit.emitFunctionEpilogue();
+        jit.ret();
+    });
+
+    auto compareFloatGeneric = compile([&, condition] (CCallHelpers& jit) {
+        jit.emitFunctionPrologue();
+
+        jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
+        jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg2), FPRInfo::fpRegT1);
+        jit.move(CCallHelpers::TrustedImm32(1), GPRInfo::returnValueGPR);
+        auto jump = jit.branchFloat(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT1);
+        jit.move(CCallHelpers::TrustedImm32(0), GPRInfo::returnValueGPR);
+        jump.link(&jit);
+
+        jit.emitFunctionEpilogue();
+        jit.ret();
+    });
+
+    auto operands = floatOperands();
+    for (auto a : operands) {
+        for (auto b : operands) {
+            arg1 = a;
+            arg2 = b;
+            CHECK_EQ(invoke<int>(compareFloat), invoke<int>(compareFloatGeneric));
+        }
+    }
+}
+#endif
+
 #if ENABLE(MASM_PROBE)
 void testProbeReadsArgumentRegisters()
 {
@@ -861,6 +922,21 @@
     RUN(testCompareDouble(MacroAssembler::DoubleLessThanOrUnordered));
     RUN(testCompareDouble(MacroAssembler::DoubleLessThanOrEqualOrUnordered));
 
+#if CPU(X86) || CPU(X86_64) || CPU(ARM64)
+    RUN(testCompareFloat(MacroAssembler::DoubleEqual));
+    RUN(testCompareFloat(MacroAssembler::DoubleNotEqual));
+    RUN(testCompareFloat(MacroAssembler::DoubleGreaterThan));
+    RUN(testCompareFloat(MacroAssembler::DoubleGreaterThanOrEqual));
+    RUN(testCompareFloat(MacroAssembler::DoubleLessThan));
+    RUN(testCompareFloat(MacroAssembler::DoubleLessThanOrEqual));
+    RUN(testCompareFloat(MacroAssembler::DoubleEqualOrUnordered));
+    RUN(testCompareFloat(MacroAssembler::DoubleNotEqualOrUnordered));
+    RUN(testCompareFloat(MacroAssembler::DoubleGreaterThanOrUnordered));
+    RUN(testCompareFloat(MacroAssembler::DoubleGreaterThanOrEqualOrUnordered));
+    RUN(testCompareFloat(MacroAssembler::DoubleLessThanOrUnordered));
+    RUN(testCompareFloat(MacroAssembler::DoubleLessThanOrEqualOrUnordered));
+#endif
+
 #if ENABLE(MASM_PROBE)
     RUN(testProbeReadsArgumentRegisters());
     RUN(testProbeWritesArgumentRegisters());
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to