Title: [194062] trunk/Source/_javascript_Core
Revision
194062
Author
[email protected]
Date
2015-12-14 14:44:22 -0800 (Mon, 14 Dec 2015)

Log Message

[JSC] Add ceil() support for x86 and expose it to B3
https://bugs.webkit.org/show_bug.cgi?id=152231

Patch by Benjamin Poulain <[email protected]> on 2015-12-14
Reviewed by Geoffrey Garen.

Most x86 CPUs we care about support ceil() natively
with the round instruction.

This patch expose that behind a runtime flag, use it
in the Math.ceil() thunk and expose it to B3.

* assembler/MacroAssemblerARM64.h:
(JSC::MacroAssemblerARM64::supportsFloatingPointCeil):
* assembler/MacroAssemblerARMv7.h:
(JSC::MacroAssemblerARMv7::supportsFloatingPointCeil):
* assembler/MacroAssemblerMIPS.h:
(JSC::MacroAssemblerMIPS::supportsFloatingPointCeil):
* assembler/MacroAssemblerSH4.h:
(JSC::MacroAssemblerSH4::supportsFloatingPointCeil):
* assembler/MacroAssemblerX86Common.cpp:
* assembler/MacroAssemblerX86Common.h:
(JSC::MacroAssemblerX86Common::ceilDouble):
(JSC::MacroAssemblerX86Common::ceilFloat):
(JSC::MacroAssemblerX86Common::supportsFloatingPointCeil):
(JSC::MacroAssemblerX86Common::supportsLZCNT):
* assembler/X86Assembler.h:
(JSC::X86Assembler::roundss_rr):
(JSC::X86Assembler::roundss_mr):
(JSC::X86Assembler::roundsd_rr):
(JSC::X86Assembler::roundsd_mr):
(JSC::X86Assembler::mfence):
(JSC::X86Assembler::X86InstructionFormatter::threeByteOp):
* b3/B3ConstDoubleValue.cpp:
(JSC::B3::ConstDoubleValue::ceilConstant):
* b3/B3ConstDoubleValue.h:
* b3/B3ConstFloatValue.cpp:
(JSC::B3::ConstFloatValue::ceilConstant):
* b3/B3ConstFloatValue.h:
* b3/B3LowerMacrosAfterOptimizations.cpp:
* b3/B3LowerToAir.cpp:
(JSC::B3::Air::LowerToAir::lower):
* b3/B3Opcode.cpp:
(WTF::printInternal):
* b3/B3Opcode.h:
* b3/B3ReduceDoubleToFloat.cpp:
* b3/B3ReduceStrength.cpp:
* b3/B3Validate.cpp:
* b3/B3Value.cpp:
(JSC::B3::Value::ceilConstant):
(JSC::B3::Value::effects):
(JSC::B3::Value::key):
(JSC::B3::Value::typeFor):
* b3/B3Value.h:
* b3/air/AirOpcode.opcodes:
* b3/testb3.cpp:
(JSC::B3::testCeilArg):
(JSC::B3::testCeilImm):
(JSC::B3::testCeilMem):
(JSC::B3::testCeilCeilArg):
(JSC::B3::testCeilIToD64):
(JSC::B3::testCeilIToD32):
(JSC::B3::testCeilArgWithUselessDoubleConversion):
(JSC::B3::testCeilArgWithEffectfulDoubleConversion):
(JSC::B3::populateWithInterestingValues):
(JSC::B3::run):
* ftl/FTLB3Output.h:
(JSC::FTL::Output::ceil64):
* jit/ThunkGenerators.cpp:
(JSC::ceilThunkGenerator):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (194061 => 194062)


--- trunk/Source/_javascript_Core/ChangeLog	2015-12-14 22:26:40 UTC (rev 194061)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-12-14 22:44:22 UTC (rev 194062)
@@ -1,3 +1,75 @@
+2015-12-14  Benjamin Poulain  <[email protected]>
+
+        [JSC] Add ceil() support for x86 and expose it to B3
+        https://bugs.webkit.org/show_bug.cgi?id=152231
+
+        Reviewed by Geoffrey Garen.
+
+        Most x86 CPUs we care about support ceil() natively
+        with the round instruction.
+
+        This patch expose that behind a runtime flag, use it
+        in the Math.ceil() thunk and expose it to B3.
+
+        * assembler/MacroAssemblerARM64.h:
+        (JSC::MacroAssemblerARM64::supportsFloatingPointCeil):
+        * assembler/MacroAssemblerARMv7.h:
+        (JSC::MacroAssemblerARMv7::supportsFloatingPointCeil):
+        * assembler/MacroAssemblerMIPS.h:
+        (JSC::MacroAssemblerMIPS::supportsFloatingPointCeil):
+        * assembler/MacroAssemblerSH4.h:
+        (JSC::MacroAssemblerSH4::supportsFloatingPointCeil):
+        * assembler/MacroAssemblerX86Common.cpp:
+        * assembler/MacroAssemblerX86Common.h:
+        (JSC::MacroAssemblerX86Common::ceilDouble):
+        (JSC::MacroAssemblerX86Common::ceilFloat):
+        (JSC::MacroAssemblerX86Common::supportsFloatingPointCeil):
+        (JSC::MacroAssemblerX86Common::supportsLZCNT):
+        * assembler/X86Assembler.h:
+        (JSC::X86Assembler::roundss_rr):
+        (JSC::X86Assembler::roundss_mr):
+        (JSC::X86Assembler::roundsd_rr):
+        (JSC::X86Assembler::roundsd_mr):
+        (JSC::X86Assembler::mfence):
+        (JSC::X86Assembler::X86InstructionFormatter::threeByteOp):
+        * b3/B3ConstDoubleValue.cpp:
+        (JSC::B3::ConstDoubleValue::ceilConstant):
+        * b3/B3ConstDoubleValue.h:
+        * b3/B3ConstFloatValue.cpp:
+        (JSC::B3::ConstFloatValue::ceilConstant):
+        * b3/B3ConstFloatValue.h:
+        * b3/B3LowerMacrosAfterOptimizations.cpp:
+        * b3/B3LowerToAir.cpp:
+        (JSC::B3::Air::LowerToAir::lower):
+        * b3/B3Opcode.cpp:
+        (WTF::printInternal):
+        * b3/B3Opcode.h:
+        * b3/B3ReduceDoubleToFloat.cpp:
+        * b3/B3ReduceStrength.cpp:
+        * b3/B3Validate.cpp:
+        * b3/B3Value.cpp:
+        (JSC::B3::Value::ceilConstant):
+        (JSC::B3::Value::effects):
+        (JSC::B3::Value::key):
+        (JSC::B3::Value::typeFor):
+        * b3/B3Value.h:
+        * b3/air/AirOpcode.opcodes:
+        * b3/testb3.cpp:
+        (JSC::B3::testCeilArg):
+        (JSC::B3::testCeilImm):
+        (JSC::B3::testCeilMem):
+        (JSC::B3::testCeilCeilArg):
+        (JSC::B3::testCeilIToD64):
+        (JSC::B3::testCeilIToD32):
+        (JSC::B3::testCeilArgWithUselessDoubleConversion):
+        (JSC::B3::testCeilArgWithEffectfulDoubleConversion):
+        (JSC::B3::populateWithInterestingValues):
+        (JSC::B3::run):
+        * ftl/FTLB3Output.h:
+        (JSC::FTL::Output::ceil64):
+        * jit/ThunkGenerators.cpp:
+        (JSC::ceilThunkGenerator):
+
 2015-12-14  Andreas Kling  <[email protected]>
 
         ResourceUsageOverlay should show GC timers.

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h (194061 => 194062)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h	2015-12-14 22:26:40 UTC (rev 194061)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h	2015-12-14 22:44:22 UTC (rev 194062)
@@ -1199,6 +1199,7 @@
     static bool supportsFloatingPointTruncate() { return true; }
     static bool supportsFloatingPointSqrt() { return true; }
     static bool supportsFloatingPointAbs() { return true; }
+    static bool supportsFloatingPointCeil() { return true; }
 
     enum BranchTruncateType { BranchIfTruncateFailed, BranchIfTruncateSuccessful };
 

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerARMv7.h (194061 => 194062)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerARMv7.h	2015-12-14 22:26:40 UTC (rev 194061)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerARMv7.h	2015-12-14 22:44:22 UTC (rev 194062)
@@ -856,6 +856,7 @@
     static bool supportsFloatingPointTruncate() { return true; }
     static bool supportsFloatingPointSqrt() { return true; }
     static bool supportsFloatingPointAbs() { return true; }
+    static bool supportsFloatingPointCeil() { return false; }
 
     void loadDouble(ImplicitAddress address, FPRegisterID dest)
     {
@@ -1046,6 +1047,12 @@
         m_assembler.vneg(dest, src);
     }
 
+    NO_RETURN_DUE_TO_CRASH void ceilDouble(FPRegisterID, FPRegisterID)
+    {
+        ASSERT(!supportsFloatingPointCeil());
+        CRASH();
+    }
+
     void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
     {
         m_assembler.vmov(fpTempRegister, src, src);

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerMIPS.h (194061 => 194062)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerMIPS.h	2015-12-14 22:26:40 UTC (rev 194061)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerMIPS.h	2015-12-14 22:44:22 UTC (rev 194062)
@@ -625,6 +625,12 @@
         RELEASE_ASSERT_NOT_REACHED();
     }
 
+    NO_RETURN_DUE_TO_CRASH void ceilDouble(FPRegisterID, FPRegisterID)
+    {
+        ASSERT(!supportsFloatingPointCeil());
+        CRASH();
+    }
+
     ConvertibleLoadLabel convertibleLoadPtr(Address address, RegisterID dest)
     {
         ConvertibleLoadLabel result(this);
@@ -1209,6 +1215,7 @@
 #endif
     }
     static bool supportsFloatingPointAbs() { return false; }
+    static bool supportsFloatingPointCeil() { return false; }
 
     // Stack manipulation operations:
     //

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerSH4.h (194061 => 194062)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerSH4.h	2015-12-14 22:26:40 UTC (rev 194061)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerSH4.h	2015-12-14 22:44:22 UTC (rev 194062)
@@ -1091,6 +1091,7 @@
     static bool supportsFloatingPointTruncate() { return true; }
     static bool supportsFloatingPointSqrt() { return true; }
     static bool supportsFloatingPointAbs() { return true; }
+    static bool supportsFloatingPointCeil() { return false; }
 
     void moveDoubleToInts(FPRegisterID src, RegisterID dest1, RegisterID dest2)
     {
@@ -1574,6 +1575,12 @@
         m_assembler.dabs(dest);
     }
 
+    NO_RETURN_DUE_TO_CRASH void ceilDouble(FPRegisterID, FPRegisterID)
+    {
+        ASSERT(!supportsFloatingPointCeil());
+        CRASH();
+    }
+
     Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
     {
         RegisterID addressTempRegister = claimScratch();

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.cpp (194061 => 194062)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.cpp	2015-12-14 22:26:40 UTC (rev 194061)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.cpp	2015-12-14 22:44:22 UTC (rev 194062)
@@ -552,7 +552,8 @@
 MacroAssemblerX86Common::SSE2CheckState MacroAssemblerX86Common::s_sse2CheckState = NotCheckedSSE2;
 #endif
 
-MacroAssemblerX86Common::LZCNTCheckState MacroAssemblerX86Common::s_lzcntCheckState = LZCNTCheckState::NotChecked;
+MacroAssemblerX86Common::CPUIDCheckState MacroAssemblerX86Common::s_sse4_1CheckState = CPUIDCheckState::NotChecked;
+MacroAssemblerX86Common::CPUIDCheckState MacroAssemblerX86Common::s_lzcntCheckState = CPUIDCheckState::NotChecked;
 
 } // namespace JSC
 

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h (194061 => 194062)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h	2015-12-14 22:26:40 UTC (rev 194061)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h	2015-12-14 22:44:22 UTC (rev 194062)
@@ -570,7 +570,26 @@
         m_assembler.xorpd_rr(src, dst);
     }
 
+    void ceilDouble(FPRegisterID src, FPRegisterID dst)
+    {
+        m_assembler.roundsd_rr(src, dst, X86Assembler::RoundingType::TowardInfiniti);
+    }
 
+    void ceilDouble(Address src, FPRegisterID dst)
+    {
+        m_assembler.roundsd_mr(src.offset, src.base, dst, X86Assembler::RoundingType::TowardInfiniti);
+    }
+
+    void ceilFloat(FPRegisterID src, FPRegisterID dst)
+    {
+        m_assembler.roundss_rr(src, dst, X86Assembler::RoundingType::TowardInfiniti);
+    }
+
+    void ceilFloat(Address src, FPRegisterID dst)
+    {
+        m_assembler.roundss_mr(src.offset, src.base, dst, X86Assembler::RoundingType::TowardInfiniti);
+    }
+
     // Memory access operations:
     //
     // Loads are of the form load(address, destination) and stores of the form
@@ -1797,6 +1816,42 @@
         return X86Assembler::maxJumpReplacementSize();
     }
 
+    static bool supportsFloatingPointCeil()
+    {
+        if (s_sse4_1CheckState == CPUIDCheckState::NotChecked) {
+            int flags = 0;
+#if COMPILER(MSVC)
+            int cpuInfo[4];
+            __cpuid(cpuInfo, 0x1);
+            flags = cpuInfo[2];
+#elif COMPILER(GCC_OR_CLANG)
+#if CPU(X86_64)
+            asm (
+                "movl $0x1, %%eax;"
+                "cpuid;"
+                "movl %%ecx, %0;"
+                : "=g" (flags)
+                :
+                : "%eax", "%ebx", "%ecx", "%edx"
+                );
+#else
+            asm (
+                "movl $0x1, %%eax;"
+                "pushl %%ebx;"
+                "cpuid;"
+                "popl %%ebx;"
+                "movl %%ecx, %0;"
+                : "=g" (flags)
+                :
+                : "%eax", "%ecx", "%edx"
+                );
+#endif
+#endif // COMPILER(GCC_OR_CLANG)
+            s_sse4_1CheckState = (flags & (1 << 19)) ? CPUIDCheckState::Set : CPUIDCheckState::Clear;
+        }
+        return s_sse4_1CheckState == CPUIDCheckState::Set;
+    }
+
 #if ENABLE(MASM_PROBE)
     void probe(ProbeFunction, void* arg1, void* arg2);
 #endif // ENABLE(MASM_PROBE)
@@ -1837,10 +1892,10 @@
         m_assembler.cmovl_rr(cond, src, dest);
 #endif
     }
-    
+
     static bool supportsLZCNT()
     {
-        if (s_lzcntCheckState == LZCNTCheckState::NotChecked) {
+        if (s_lzcntCheckState == CPUIDCheckState::NotChecked) {
             int flags = 0;
 #if COMPILER(MSVC)
             int cpuInfo[4];
@@ -1869,9 +1924,9 @@
                 );
 #endif
 #endif // COMPILER(GCC_OR_CLANG)
-            s_lzcntCheckState = (flags & 0x20) ? LZCNTCheckState::Set : LZCNTCheckState::Clear;
+            s_lzcntCheckState = (flags & 0x20) ? CPUIDCheckState::Set : CPUIDCheckState::Clear;
         }
-        return s_lzcntCheckState == LZCNTCheckState::Set;
+        return s_lzcntCheckState == CPUIDCheckState::Set;
     }
 
 private:
@@ -2041,12 +2096,13 @@
 
 #endif
 
-    enum class LZCNTCheckState {
+    enum class CPUIDCheckState {
         NotChecked,
         Clear,
         Set
     };
-    static LZCNTCheckState s_lzcntCheckState;
+    static CPUIDCheckState s_sse4_1CheckState;
+    static CPUIDCheckState s_lzcntCheckState;
 };
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/assembler/X86Assembler.h (194061 => 194062)


--- trunk/Source/_javascript_Core/assembler/X86Assembler.h	2015-12-14 22:26:40 UTC (rev 194061)
+++ trunk/Source/_javascript_Core/assembler/X86Assembler.h	2015-12-14 22:44:22 UTC (rev 194062)
@@ -264,6 +264,7 @@
         OP2_CVTSI2SD_VsdEd  = 0x2A,
         OP2_CVTTSD2SI_GdWsd = 0x2C,
         OP2_UCOMISD_VsdWsd  = 0x2E,
+        OP2_3BYTE_ESCAPE_3A = 0x3A,
         OP2_CMOVCC          = 0x40,
         OP2_ADDSD_VsdWsd    = 0x58,
         OP2_MULSD_VsdWsd    = 0x59,
@@ -280,7 +281,7 @@
         OP2_MOVD_EdVd       = 0x7E,
         OP2_JCC_rel32       = 0x80,
         OP_SETCC            = 0x90,
-        OP2_3BYTE_ESCAPE    = 0xAE,
+        OP2_3BYTE_ESCAPE_AE = 0xAE,
         OP2_IMUL_GvEv       = 0xAF,
         OP2_MOVZX_GvEb      = 0xB6,
         OP2_BSR             = 0xBD,
@@ -295,7 +296,9 @@
     } TwoByteOpcodeID;
     
     typedef enum {
-        OP3_MFENCE          = 0xF0,
+        OP3_ROUNDSS_VssWssIb = 0x0A,
+        OP3_ROUNDSD_VsdWsdIb = 0x0B,
+        OP3_MFENCE           = 0xF0,
     } ThreeByteOpcodeID;
 
     
@@ -2349,6 +2352,41 @@
         m_formatter.twoByteOp(OP2_SQRTSD_VsdWsd, (RegisterID)dst, base, offset);
     }
 
+    enum class RoundingType : uint8_t {
+        ToNearestWithTiesToEven = 0,
+        TowardNegativeInfiniti = 1,
+        TowardInfiniti = 2,
+        TowardZero = 3
+    };
+
+    void roundss_rr(XMMRegisterID src, XMMRegisterID dst, RoundingType rounding)
+    {
+        m_formatter.prefix(PRE_SSE_66);
+        m_formatter.threeByteOp(OP2_3BYTE_ESCAPE_3A, OP3_ROUNDSS_VssWssIb, (RegisterID)dst, (RegisterID)src);
+        m_formatter.immediate8(static_cast<uint8_t>(rounding));
+    }
+
+    void roundss_mr(int offset, RegisterID base, XMMRegisterID dst, RoundingType rounding)
+    {
+        m_formatter.prefix(PRE_SSE_66);
+        m_formatter.threeByteOp(OP2_3BYTE_ESCAPE_3A, OP3_ROUNDSS_VssWssIb, (RegisterID)dst, base, offset);
+        m_formatter.immediate8(static_cast<uint8_t>(rounding));
+    }
+
+    void roundsd_rr(XMMRegisterID src, XMMRegisterID dst, RoundingType rounding)
+    {
+        m_formatter.prefix(PRE_SSE_66);
+        m_formatter.threeByteOp(OP2_3BYTE_ESCAPE_3A, OP3_ROUNDSD_VsdWsdIb, (RegisterID)dst, (RegisterID)src);
+        m_formatter.immediate8(static_cast<uint8_t>(rounding));
+    }
+
+    void roundsd_mr(int offset, RegisterID base, XMMRegisterID dst, RoundingType rounding)
+    {
+        m_formatter.prefix(PRE_SSE_66);
+        m_formatter.threeByteOp(OP2_3BYTE_ESCAPE_3A, OP3_ROUNDSD_VsdWsdIb, (RegisterID)dst, base, offset);
+        m_formatter.immediate8(static_cast<uint8_t>(rounding));
+    }
+
     // Misc instructions:
 
     void int3()
@@ -2368,7 +2406,7 @@
     
     void mfence()
     {
-        m_formatter.threeByteOp(OP3_MFENCE);
+        m_formatter.threeByteOp(OP2_3BYTE_ESCAPE_AE, OP3_MFENCE);
     }
 
     // Assembler admin methods:
@@ -2847,14 +2885,34 @@
         }
 #endif
 
-        void threeByteOp(ThreeByteOpcodeID opcode)
+        void threeByteOp(TwoByteOpcodeID twoBytePrefix, ThreeByteOpcodeID opcode)
         {
             m_buffer.ensureSpace(maxInstructionSize);
             m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
-            m_buffer.putByteUnchecked(OP2_3BYTE_ESCAPE);
+            m_buffer.putByteUnchecked(twoBytePrefix);
             m_buffer.putByteUnchecked(opcode);
         }
 
+        void threeByteOp(TwoByteOpcodeID twoBytePrefix, ThreeByteOpcodeID opcode, int reg, RegisterID rm)
+        {
+            m_buffer.ensureSpace(maxInstructionSize);
+            emitRexIfNeeded(reg, 0, rm);
+            m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
+            m_buffer.putByteUnchecked(twoBytePrefix);
+            m_buffer.putByteUnchecked(opcode);
+            registerModRM(reg, rm);
+        }
+
+        void threeByteOp(TwoByteOpcodeID twoBytePrefix, ThreeByteOpcodeID opcode, int reg, RegisterID base, int displacement)
+        {
+            m_buffer.ensureSpace(maxInstructionSize);
+            emitRexIfNeeded(reg, 0, base);
+            m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
+            m_buffer.putByteUnchecked(twoBytePrefix);
+            m_buffer.putByteUnchecked(opcode);
+            memoryModRM(reg, base, displacement);
+        }
+
 #if CPU(X86_64)
         // Quad-word-sized operands:
         //

Modified: trunk/Source/_javascript_Core/b3/B3ConstDoubleValue.cpp (194061 => 194062)


--- trunk/Source/_javascript_Core/b3/B3ConstDoubleValue.cpp	2015-12-14 22:26:40 UTC (rev 194061)
+++ trunk/Source/_javascript_Core/b3/B3ConstDoubleValue.cpp	2015-12-14 22:44:22 UTC (rev 194062)
@@ -92,6 +92,11 @@
     return proc.add<ConstDoubleValue>(origin(), fabs(m_value));
 }
 
+Value* ConstDoubleValue::ceilConstant(Procedure& proc) const
+{
+    return proc.add<ConstDoubleValue>(origin(), ceil(m_value));
+}
+
 Value* ConstDoubleValue::sqrtConstant(Procedure& proc) const
 {
     return proc.add<ConstDoubleValue>(origin(), sqrt(m_value));

Modified: trunk/Source/_javascript_Core/b3/B3ConstDoubleValue.h (194061 => 194062)


--- trunk/Source/_javascript_Core/b3/B3ConstDoubleValue.h	2015-12-14 22:26:40 UTC (rev 194061)
+++ trunk/Source/_javascript_Core/b3/B3ConstDoubleValue.h	2015-12-14 22:44:22 UTC (rev 194062)
@@ -51,6 +51,7 @@
     Value* bitwiseCastConstant(Procedure&) const override;
     Value* doubleToFloatConstant(Procedure&) const override;
     Value* absConstant(Procedure&) const override;
+    Value* ceilConstant(Procedure&) const override;
     Value* sqrtConstant(Procedure&) const override;
 
     TriState equalConstant(const Value* other) const override;

Modified: trunk/Source/_javascript_Core/b3/B3ConstFloatValue.cpp (194061 => 194062)


--- trunk/Source/_javascript_Core/b3/B3ConstFloatValue.cpp	2015-12-14 22:26:40 UTC (rev 194061)
+++ trunk/Source/_javascript_Core/b3/B3ConstFloatValue.cpp	2015-12-14 22:44:22 UTC (rev 194062)
@@ -92,6 +92,11 @@
     return proc.add<ConstFloatValue>(origin(), static_cast<float>(fabs(m_value)));
 }
 
+Value* ConstFloatValue::ceilConstant(Procedure& proc) const
+{
+    return proc.add<ConstFloatValue>(origin(), ceilf(m_value));
+}
+
 Value* ConstFloatValue::sqrtConstant(Procedure& proc) const
 {
     return proc.add<ConstFloatValue>(origin(), static_cast<float>(sqrt(m_value)));

Modified: trunk/Source/_javascript_Core/b3/B3ConstFloatValue.h (194061 => 194062)


--- trunk/Source/_javascript_Core/b3/B3ConstFloatValue.h	2015-12-14 22:26:40 UTC (rev 194061)
+++ trunk/Source/_javascript_Core/b3/B3ConstFloatValue.h	2015-12-14 22:44:22 UTC (rev 194062)
@@ -50,6 +50,7 @@
     Value* bitwiseCastConstant(Procedure&) const override;
     Value* floatToDoubleConstant(Procedure&) const override;
     Value* absConstant(Procedure&) const override;
+    Value* ceilConstant(Procedure&) const override;
     Value* sqrtConstant(Procedure&) const override;
 
     TriState equalConstant(const Value* other) const override;

Modified: trunk/Source/_javascript_Core/b3/B3LowerMacrosAfterOptimizations.cpp (194061 => 194062)


--- trunk/Source/_javascript_Core/b3/B3LowerMacrosAfterOptimizations.cpp	2015-12-14 22:26:40 UTC (rev 194061)
+++ trunk/Source/_javascript_Core/b3/B3LowerMacrosAfterOptimizations.cpp	2015-12-14 22:44:22 UTC (rev 194062)
@@ -30,8 +30,10 @@
 
 #include "B3BasicBlockInlines.h"
 #include "B3BlockInsertionSet.h"
+#include "B3CCallValue.h"
 #include "B3ConstDoubleValue.h"
 #include "B3ConstFloatValue.h"
+#include "B3ConstPtrValue.h"
 #include "B3InsertionSetInlines.h"
 #include "B3PhaseScope.h"
 
@@ -85,6 +87,27 @@
                 m_value->replaceWithIdentity(result);
                 break;
             }
+            case Ceil: {
+                if (MacroAssembler::supportsFloatingPointCeil())
+                    break;
+
+                Value* functionAddress = nullptr;
+                if (m_value->type() == Double)
+                    functionAddress = m_insertionSet.insert<ConstPtrValue>(m_index, m_origin, ceil);
+                else if (m_value->type() == Float)
+                    functionAddress = m_insertionSet.insert<ConstPtrValue>(m_index, m_origin, ceilf);
+                else
+                    RELEASE_ASSERT_NOT_REACHED();
+
+                Value* result = m_insertionSet.insert<CCallValue>(m_index,
+                    m_value->type(),
+                    m_origin,
+                    Effects::none(),
+                    functionAddress,
+                    m_value->child(0));
+                m_value->replaceWithIdentity(result);
+                break;
+            }
             default:
                 break;
             }

Modified: trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp (194061 => 194062)


--- trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp	2015-12-14 22:26:40 UTC (rev 194061)
+++ trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp	2015-12-14 22:44:22 UTC (rev 194062)
@@ -1654,6 +1654,11 @@
             return;
         }
 
+        case Ceil: {
+            appendUnOp<Air::Oops, Air::Oops, CeilDouble, CeilFloat>(m_value->child(0));
+            return;
+        }
+
         case Sqrt: {
             appendUnOp<Air::Oops, Air::Oops, SqrtDouble, SqrtFloat>(m_value->child(0));
             return;

Modified: trunk/Source/_javascript_Core/b3/B3Opcode.cpp (194061 => 194062)


--- trunk/Source/_javascript_Core/b3/B3Opcode.cpp	2015-12-14 22:26:40 UTC (rev 194061)
+++ trunk/Source/_javascript_Core/b3/B3Opcode.cpp	2015-12-14 22:44:22 UTC (rev 194062)
@@ -149,6 +149,9 @@
     case Abs:
         out.print("Abs");
         return;
+    case Ceil:
+        out.print("Ceil");
+        return;
     case Sqrt:
         out.print("Sqrt");
         return;

Modified: trunk/Source/_javascript_Core/b3/B3Opcode.h (194061 => 194062)


--- trunk/Source/_javascript_Core/b3/B3Opcode.h	2015-12-14 22:26:40 UTC (rev 194061)
+++ trunk/Source/_javascript_Core/b3/B3Opcode.h	2015-12-14 22:44:22 UTC (rev 194062)
@@ -86,6 +86,7 @@
 
     // Floating point math.
     Abs,
+    Ceil,
     Sqrt,
 
     // Casts and such.

Modified: trunk/Source/_javascript_Core/b3/B3ReduceDoubleToFloat.cpp (194061 => 194062)


--- trunk/Source/_javascript_Core/b3/B3ReduceDoubleToFloat.cpp	2015-12-14 22:26:40 UTC (rev 194061)
+++ trunk/Source/_javascript_Core/b3/B3ReduceDoubleToFloat.cpp	2015-12-14 22:44:22 UTC (rev 194062)
@@ -49,6 +49,7 @@
         }
         break;
     case Abs:
+    case Ceil:
     case Sqrt:
         if (candidate->child(0)->opcode() == FloatToDouble) {
             candidate->child(0) = candidate->child(0)->child(0);

Modified: trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp (194061 => 194062)


--- trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp	2015-12-14 22:26:40 UTC (rev 194061)
+++ trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp	2015-12-14 22:44:22 UTC (rev 194062)
@@ -564,6 +564,32 @@
             }
             break;
 
+        case Ceil:
+            // Turn this: Ceil(constant)
+            // Into this: ceil<value->type()>(constant)
+            if (Value* constant = m_value->child(0)->ceilConstant(m_proc)) {
+                replaceWithNewValue(constant);
+                break;
+            }
+
+            // Turn this: Ceil(Ceil(value))
+            // Into this: Ceil(value)
+            if (m_value->child(0)->opcode() == Ceil) {
+                m_value->replaceWithIdentity(m_value->child(0));
+                break;
+            }
+
+            // Turn this: Ceil(IToD(value))
+            // Into this: IToD(value)
+            //
+            // That works for Int64 because both ARM64 and x86_64
+            // perform rounding when converting a 64bit integer to double.
+            if (m_value->child(0)->opcode() == IToD) {
+                m_value->replaceWithIdentity(m_value->child(0));
+                break;
+            }
+            break;
+
         case Sqrt:
             // Turn this: Sqrt(constant)
             // Into this: sqrt<value->type()>(constant)

Modified: trunk/Source/_javascript_Core/b3/B3Validate.cpp (194061 => 194062)


--- trunk/Source/_javascript_Core/b3/B3Validate.cpp	2015-12-14 22:26:40 UTC (rev 194061)
+++ trunk/Source/_javascript_Core/b3/B3Validate.cpp	2015-12-14 22:44:22 UTC (rev 194062)
@@ -210,6 +210,7 @@
                 VALIDATE(value->type() == Int32, ("At ", *value));
                 break;
             case Abs:
+            case Ceil:
             case Sqrt:
                 VALIDATE(value->numChildren() == 1, ("At ", *value));
                 VALIDATE(isFloat(value->child(0)->type()), ("At ", *value));

Modified: trunk/Source/_javascript_Core/b3/B3Value.cpp (194061 => 194062)


--- trunk/Source/_javascript_Core/b3/B3Value.cpp	2015-12-14 22:26:40 UTC (rev 194061)
+++ trunk/Source/_javascript_Core/b3/B3Value.cpp	2015-12-14 22:44:22 UTC (rev 194062)
@@ -226,6 +226,11 @@
     return nullptr;
 }
 
+Value* Value::ceilConstant(Procedure&) const
+{
+    return nullptr;
+}
+
 Value* Value::sqrtConstant(Procedure&) const
 {
     return nullptr;
@@ -363,6 +368,7 @@
     case ZShr:
     case Clz:
     case Abs:
+    case Ceil:
     case Sqrt:
     case BitwiseCast:
     case SExt8:
@@ -442,6 +448,7 @@
         return ValueKey(opcode(), type());
     case Identity:
     case Abs:
+    case Ceil:
     case Sqrt:
     case SExt8:
     case SExt16:
@@ -549,6 +556,7 @@
     case ZShr:
     case Clz:
     case Abs:
+    case Ceil:
     case Sqrt:
     case CheckAdd:
     case CheckSub:

Modified: trunk/Source/_javascript_Core/b3/B3Value.h (194061 => 194062)


--- trunk/Source/_javascript_Core/b3/B3Value.h	2015-12-14 22:26:40 UTC (rev 194061)
+++ trunk/Source/_javascript_Core/b3/B3Value.h	2015-12-14 22:44:22 UTC (rev 194062)
@@ -132,6 +132,7 @@
     virtual Value* doubleToFloatConstant(Procedure&) const;
     virtual Value* floatToDoubleConstant(Procedure&) const;
     virtual Value* absConstant(Procedure&) const;
+    virtual Value* ceilConstant(Procedure&) const;
     virtual Value* sqrtConstant(Procedure&) const;
 
     virtual TriState equalConstant(const Value* other) const;

Modified: trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes (194061 => 194062)


--- trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes	2015-12-14 22:26:40 UTC (rev 194061)
+++ trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes	2015-12-14 22:44:22 UTC (rev 194062)
@@ -275,6 +275,14 @@
     Tmp
     x86: Addr
 
+CeilDouble U:F, UD:F
+    Tmp, Tmp
+    Addr, Tmp
+
+CeilFloat U:F, UD:F
+    Tmp, Tmp
+    Addr, Tmp
+
 SqrtDouble U:F, UD:F
     Tmp, Tmp
     x86: Addr, Tmp

Modified: trunk/Source/_javascript_Core/b3/testb3.cpp (194061 => 194062)


--- trunk/Source/_javascript_Core/b3/testb3.cpp	2015-12-14 22:26:40 UTC (rev 194061)
+++ trunk/Source/_javascript_Core/b3/testb3.cpp	2015-12-14 22:44:22 UTC (rev 194062)
@@ -3235,6 +3235,175 @@
     CHECK(isIdentical(effect, fabs(a)));
 }
 
+void testCeilArg(double a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    root->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        root->appendNew<Value>(
+            proc, Ceil, Origin(),
+                root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0)));
+
+    CHECK(isIdentical(compileAndRun<double>(proc, a), ceil(a)));
+}
+
+void testCeilImm(double a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
+    root->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        root->appendNew<Value>(proc, Ceil, Origin(), argument));
+
+    CHECK(isIdentical(compileAndRun<double>(proc), ceil(a)));
+}
+
+void testCeilMem(double a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+    MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address);
+    root->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        root->appendNew<Value>(proc, Ceil, Origin(), loadDouble));
+
+    CHECK(isIdentical(compileAndRun<double>(proc, &a), ceil(a)));
+}
+
+void testCeilCeilArg(double a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* firstCeil = root->appendNew<Value>(proc, Ceil, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0));
+    Value* secondCeil = root->appendNew<Value>(proc, Ceil, Origin(), firstCeil);
+    root->appendNew<ControlValue>(proc, Return, Origin(), secondCeil);
+
+    CHECK(isIdentical(compileAndRun<double>(proc, a), ceil(a)));
+}
+
+void testCeilIToD64(int64_t a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+    Value* argumentAsDouble = root->appendNew<Value>(proc, IToD, Origin(), argument);
+
+    root->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        root->appendNew<Value>(proc, Ceil, Origin(), argumentAsDouble));
+
+    CHECK(isIdentical(compileAndRun<double>(proc, a), ceil(static_cast<double>(a))));
+}
+
+void testCeilIToD32(int64_t a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argumentAsDouble = root->appendNew<Value>(proc, IToD, Origin(), argument);
+
+    root->appendNew<ControlValue>(
+        proc, Return, Origin(),
+        root->appendNew<Value>(proc, Ceil, Origin(), argumentAsDouble));
+
+    CHECK(isIdentical(compileAndRun<double>(proc, a), ceil(static_cast<double>(a))));
+}
+
+void testCeilArg(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
+    Value* result = root->appendNew<Value>(proc, Ceil, Origin(), argument);
+    Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
+    root->appendNew<ControlValue>(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(ceilf(a))));
+}
+
+void testCeilImm(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument = root->appendNew<ConstFloatValue>(proc, Origin(), a);
+    Value* result = root->appendNew<Value>(proc, Ceil, Origin(), argument);
+    Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
+    root->appendNew<ControlValue>(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(ceilf(a))));
+}
+
+void testCeilMem(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+    MemoryValue* loadFloat = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), address);
+    Value* result = root->appendNew<Value>(proc, Ceil, Origin(), loadFloat);
+    Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
+    root->appendNew<ControlValue>(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun<int32_t>(proc, &a), bitwise_cast<int32_t>(ceilf(a))));
+}
+
+void testCeilCeilArg(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
+    Value* firstCeil = root->appendNew<Value>(proc, Ceil, Origin(), argument);
+    Value* secondCeil = root->appendNew<Value>(proc, Ceil, Origin(), firstCeil);
+    root->appendNew<ControlValue>(proc, Return, Origin(), secondCeil);
+
+    CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), ceilf(a)));
+}
+
+void testCeilArgWithUselessDoubleConversion(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
+    Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
+    Value* result = root->appendNew<Value>(proc, Ceil, Origin(), asDouble);
+    Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
+    Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
+    root->appendNew<ControlValue>(proc, Return, Origin(), result32);
+
+    CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(ceilf(a))));
+}
+
+void testCeilArgWithEffectfulDoubleConversion(float a)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
+    Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
+    Value* result = root->appendNew<Value>(proc, Ceil, Origin(), asDouble);
+    Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
+    Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
+    Value* doubleAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
+    root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleAddress);
+    root->appendNew<ControlValue>(proc, Return, Origin(), result32);
+
+    double effect = 0;
+    int32_t resultValue = compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), &effect);
+    CHECK(isIdentical(resultValue, bitwise_cast<int32_t>(ceilf(a))));
+    CHECK(isIdentical(effect, ceilf(a)));
+}
+
 void testSqrtArg(double a)
 {
     Procedure proc;
@@ -8008,6 +8177,12 @@
 {
     operands.append({ "0.", static_cast<FloatType>(0.) });
     operands.append({ "-0.", static_cast<FloatType>(-0.) });
+    operands.append({ "0.4", static_cast<FloatType>(0.5) });
+    operands.append({ "-0.4", static_cast<FloatType>(-0.5) });
+    operands.append({ "0.5", static_cast<FloatType>(0.5) });
+    operands.append({ "-0.5", static_cast<FloatType>(-0.5) });
+    operands.append({ "0.6", static_cast<FloatType>(0.5) });
+    operands.append({ "-0.6", static_cast<FloatType>(-0.5) });
     operands.append({ "1.", static_cast<FloatType>(1.) });
     operands.append({ "-1.", static_cast<FloatType>(-1.) });
     operands.append({ "2.", static_cast<FloatType>(2.) });
@@ -8638,6 +8813,19 @@
     RUN_UNARY(testAbsArgWithUselessDoubleConversion, floatingPointOperands<float>());
     RUN_UNARY(testAbsArgWithEffectfulDoubleConversion, floatingPointOperands<float>());
 
+    RUN_UNARY(testCeilArg, floatingPointOperands<double>());
+    RUN_UNARY(testCeilImm, floatingPointOperands<double>());
+    RUN_UNARY(testCeilMem, floatingPointOperands<double>());
+    RUN_UNARY(testCeilCeilArg, floatingPointOperands<double>());
+    RUN_UNARY(testCeilIToD64, int64Operands());
+    RUN_UNARY(testCeilIToD32, int32Operands());
+    RUN_UNARY(testCeilArg, floatingPointOperands<float>());
+    RUN_UNARY(testCeilImm, floatingPointOperands<float>());
+    RUN_UNARY(testCeilMem, floatingPointOperands<float>());
+    RUN_UNARY(testCeilCeilArg, floatingPointOperands<float>());
+    RUN_UNARY(testCeilArgWithUselessDoubleConversion, floatingPointOperands<float>());
+    RUN_UNARY(testCeilArgWithEffectfulDoubleConversion, floatingPointOperands<float>());
+
     RUN_UNARY(testSqrtArg, floatingPointOperands<double>());
     RUN_UNARY(testSqrtImm, floatingPointOperands<double>());
     RUN_UNARY(testSqrtMem, floatingPointOperands<double>());

Modified: trunk/Source/_javascript_Core/ftl/FTLB3Output.h (194061 => 194062)


--- trunk/Source/_javascript_Core/ftl/FTLB3Output.h	2015-12-14 22:26:40 UTC (rev 194061)
+++ trunk/Source/_javascript_Core/ftl/FTLB3Output.h	2015-12-14 22:44:22 UTC (rev 194062)
@@ -154,7 +154,7 @@
     LValue lShr(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::ZShr, origin(), left, castToInt32(right)); }
     LValue bitNot(LValue);
 
-    LValue ceil64(LValue operand) { CRASH(); }
+    LValue ceil64(LValue operand) { return m_block->appendNew<B3::Value>(m_proc, B3::Ceil, origin(), value); }
     LValue ctlz32(LValue operand) { return m_block->appendNew<B3::Value>(m_proc, B3::Clz, origin(), operand); }
     LValue addWithOverflow32(LValue left, LValue right) { CRASH(); }
     LValue subWithOverflow32(LValue left, LValue right) { CRASH(); }

Modified: trunk/Source/_javascript_Core/jit/ThunkGenerators.cpp (194061 => 194062)


--- trunk/Source/_javascript_Core/jit/ThunkGenerators.cpp	2015-12-14 22:26:40 UTC (rev 194061)
+++ trunk/Source/_javascript_Core/jit/ThunkGenerators.cpp	2015-12-14 22:44:22 UTC (rev 194062)
@@ -828,11 +828,11 @@
     jit.returnInt32(SpecializedThunkJIT::regT0);
     nonIntJump.link(&jit);
     jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
-#if CPU(ARM64)
-    jit.ceilDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT0);
-#else
-    jit.callDoubleToDoublePreservingReturn(UnaryDoubleOpWrapper(ceil));
-#endif // CPU(ARM64)
+    if (jit.supportsFloatingPointCeil())
+        jit.ceilDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT0);
+    else
+        jit.callDoubleToDoublePreservingReturn(UnaryDoubleOpWrapper(ceil));
+
     SpecializedThunkJIT::JumpList doubleResult;
     jit.branchConvertDoubleToInt32(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0, doubleResult, SpecializedThunkJIT::fpRegT1);
     jit.returnInt32(SpecializedThunkJIT::regT0);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to