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());