Title: [153133] trunk/Source/_javascript_Core
Revision
153133
Author
oli...@apple.com
Date
2013-07-24 20:59:06 -0700 (Wed, 24 Jul 2013)

Log Message

fourthTier: FTL should support double variables
https://bugs.webkit.org/show_bug.cgi?id=113624

Reviewed by Geoffrey Garen.

Made all of the operations that the FTL already supports, also support doubles.
OSR exit already basically had everything it needed, so no changes there. This
mostly just glues together bits of DFG IR to LLVM IR, in a straight-forward way.

* ftl/FTLAbbreviations.h:
(FTL):
(JSC::FTL::doubleType):
(JSC::FTL::constReal):
(JSC::FTL::buildPhi):
(JSC::FTL::addIncoming):
(JSC::FTL::buildFAdd):
(JSC::FTL::buildFSub):
(JSC::FTL::buildFMul):
(JSC::FTL::buildFNeg):
(JSC::FTL::buildSIToFP):
(JSC::FTL::buildUIToFP):
(JSC::FTL::buildBitCast):
(JSC::FTL::buildFCmp):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLCommonValues.cpp:
(JSC::FTL::CommonValues::CommonValues):
* ftl/FTLCommonValues.h:
(CommonValues):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::LowerDFGToLLVM):
(JSC::FTL::LowerDFGToLLVM::lower):
(JSC::FTL::LowerDFGToLLVM::compileGetLocal):
(JSC::FTL::LowerDFGToLLVM::compileSetLocal):
(JSC::FTL::LowerDFGToLLVM::compileAdd):
(JSC::FTL::LowerDFGToLLVM::compileArithSub):
(JSC::FTL::LowerDFGToLLVM::compileArithMul):
(JSC::FTL::LowerDFGToLLVM::compileArithNegate):
(JSC::FTL::LowerDFGToLLVM::compileUInt32ToNumber):
(JSC::FTL::LowerDFGToLLVM::compileGetByVal):
(JSC::FTL::LowerDFGToLLVM::compileCompareEq):
(JSC::FTL::LowerDFGToLLVM::compileCompareLess):
(JSC::FTL::LowerDFGToLLVM::lowDouble):
(LowerDFGToLLVM):
(JSC::FTL::LowerDFGToLLVM::lowJSValue):
(JSC::FTL::LowerDFGToLLVM::isCellOrMisc):
(JSC::FTL::LowerDFGToLLVM::unboxDouble):
(JSC::FTL::LowerDFGToLLVM::boxDouble):
(JSC::FTL::LowerDFGToLLVM::speculate):
(JSC::FTL::LowerDFGToLLVM::speculateNumber):
(JSC::FTL::LowerDFGToLLVM::speculateRealNumber):
(JSC::FTL::LowerDFGToLLVM::appendOSRExit):
(JSC::FTL::LowerDFGToLLVM::addExitArgumentForNode):
* ftl/FTLOutput.h:
(JSC::FTL::Output::constDouble):
(Output):
(JSC::FTL::Output::phi):
(JSC::FTL::Output::doubleAdd):
(JSC::FTL::Output::doubleSub):
(JSC::FTL::Output::doubleMul):
(JSC::FTL::Output::doubleNeg):
(JSC::FTL::Output::intToFP):
(JSC::FTL::Output::intToDouble):
(JSC::FTL::Output::unsignedToFP):
(JSC::FTL::Output::unsignedToDouble):
(JSC::FTL::Output::bitCast):
(JSC::FTL::Output::loadDouble):
(JSC::FTL::Output::storeDouble):
(JSC::FTL::Output::doubleEqual):
(JSC::FTL::Output::doubleNotEqualOrUnordered):
(JSC::FTL::Output::doubleLessThan):
(JSC::FTL::Output::doubleLessThanOrEqual):
(JSC::FTL::Output::doubleGreaterThan):
(JSC::FTL::Output::doubleGreaterThanOrEqual):
(JSC::FTL::Output::doubleEqualOrUnordered):
(JSC::FTL::Output::doubleNotEqual):
(JSC::FTL::Output::doubleLessThanOrUnordered):
(JSC::FTL::Output::doubleLessThanOrEqualOrUnordered):
(JSC::FTL::Output::doubleGreaterThanOrUnordered):
(JSC::FTL::Output::doubleGreaterThanOrEqualOrUnordered):
(JSC::FTL::Output::testIsZero64):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (153132 => 153133)


--- trunk/Source/_javascript_Core/ChangeLog	2013-07-25 03:59:04 UTC (rev 153132)
+++ trunk/Source/_javascript_Core/ChangeLog	2013-07-25 03:59:06 UTC (rev 153133)
@@ -1,5 +1,89 @@
 2013-04-27  Filip Pizlo  <fpi...@apple.com>
 
+        FTL should support double variables
+        https://bugs.webkit.org/show_bug.cgi?id=113624
+
+        Reviewed by Geoffrey Garen.
+        
+        Made all of the operations that the FTL already supports, also support doubles.
+        OSR exit already basically had everything it needed, so no changes there. This
+        mostly just glues together bits of DFG IR to LLVM IR, in a straight-forward way.
+
+        * ftl/FTLAbbreviations.h:
+        (FTL):
+        (JSC::FTL::doubleType):
+        (JSC::FTL::constReal):
+        (JSC::FTL::buildPhi):
+        (JSC::FTL::addIncoming):
+        (JSC::FTL::buildFAdd):
+        (JSC::FTL::buildFSub):
+        (JSC::FTL::buildFMul):
+        (JSC::FTL::buildFNeg):
+        (JSC::FTL::buildSIToFP):
+        (JSC::FTL::buildUIToFP):
+        (JSC::FTL::buildBitCast):
+        (JSC::FTL::buildFCmp):
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLCommonValues.cpp:
+        (JSC::FTL::CommonValues::CommonValues):
+        * ftl/FTLCommonValues.h:
+        (CommonValues):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::LowerDFGToLLVM::LowerDFGToLLVM):
+        (JSC::FTL::LowerDFGToLLVM::lower):
+        (JSC::FTL::LowerDFGToLLVM::compileGetLocal):
+        (JSC::FTL::LowerDFGToLLVM::compileSetLocal):
+        (JSC::FTL::LowerDFGToLLVM::compileAdd):
+        (JSC::FTL::LowerDFGToLLVM::compileArithSub):
+        (JSC::FTL::LowerDFGToLLVM::compileArithMul):
+        (JSC::FTL::LowerDFGToLLVM::compileArithNegate):
+        (JSC::FTL::LowerDFGToLLVM::compileUInt32ToNumber):
+        (JSC::FTL::LowerDFGToLLVM::compileGetByVal):
+        (JSC::FTL::LowerDFGToLLVM::compileCompareEq):
+        (JSC::FTL::LowerDFGToLLVM::compileCompareLess):
+        (JSC::FTL::LowerDFGToLLVM::lowDouble):
+        (LowerDFGToLLVM):
+        (JSC::FTL::LowerDFGToLLVM::lowJSValue):
+        (JSC::FTL::LowerDFGToLLVM::isCellOrMisc):
+        (JSC::FTL::LowerDFGToLLVM::unboxDouble):
+        (JSC::FTL::LowerDFGToLLVM::boxDouble):
+        (JSC::FTL::LowerDFGToLLVM::speculate):
+        (JSC::FTL::LowerDFGToLLVM::speculateNumber):
+        (JSC::FTL::LowerDFGToLLVM::speculateRealNumber):
+        (JSC::FTL::LowerDFGToLLVM::appendOSRExit):
+        (JSC::FTL::LowerDFGToLLVM::addExitArgumentForNode):
+        * ftl/FTLOutput.h:
+        (JSC::FTL::Output::constDouble):
+        (Output):
+        (JSC::FTL::Output::phi):
+        (JSC::FTL::Output::doubleAdd):
+        (JSC::FTL::Output::doubleSub):
+        (JSC::FTL::Output::doubleMul):
+        (JSC::FTL::Output::doubleNeg):
+        (JSC::FTL::Output::intToFP):
+        (JSC::FTL::Output::intToDouble):
+        (JSC::FTL::Output::unsignedToFP):
+        (JSC::FTL::Output::unsignedToDouble):
+        (JSC::FTL::Output::bitCast):
+        (JSC::FTL::Output::loadDouble):
+        (JSC::FTL::Output::storeDouble):
+        (JSC::FTL::Output::doubleEqual):
+        (JSC::FTL::Output::doubleNotEqualOrUnordered):
+        (JSC::FTL::Output::doubleLessThan):
+        (JSC::FTL::Output::doubleLessThanOrEqual):
+        (JSC::FTL::Output::doubleGreaterThan):
+        (JSC::FTL::Output::doubleGreaterThanOrEqual):
+        (JSC::FTL::Output::doubleEqualOrUnordered):
+        (JSC::FTL::Output::doubleNotEqual):
+        (JSC::FTL::Output::doubleLessThanOrUnordered):
+        (JSC::FTL::Output::doubleLessThanOrEqualOrUnordered):
+        (JSC::FTL::Output::doubleGreaterThanOrUnordered):
+        (JSC::FTL::Output::doubleGreaterThanOrEqualOrUnordered):
+        (JSC::FTL::Output::testIsZero64):
+
+2013-04-27  Filip Pizlo  <fpi...@apple.com>
+
         fourthTier: SymbolTable should be thread-safe
         https://bugs.webkit.org/show_bug.cgi?id=115301
 

Modified: trunk/Source/_javascript_Core/ftl/FTLAbbreviations.h (153132 => 153133)


--- trunk/Source/_javascript_Core/ftl/FTLAbbreviations.h	2013-07-25 03:59:04 UTC (rev 153132)
+++ trunk/Source/_javascript_Core/ftl/FTLAbbreviations.h	2013-07-25 03:59:06 UTC (rev 153133)
@@ -47,6 +47,7 @@
 typedef LLVMBuilderRef LBuilder;
 typedef LLVMCallConv LCallConv;
 typedef LLVMIntPredicate LIntPredicate;
+typedef LLVMRealPredicate LRealPredicate;
 typedef LLVMLinkage LLinkage;
 typedef LLVMModuleRef LModule;
 typedef LLVMTypeRef LType;
@@ -57,6 +58,7 @@
 static inline LType int32Type() { return LLVMInt32Type(); }
 static inline LType int64Type() { return LLVMInt64Type(); }
 static inline LType intPtrType() { return LLVMInt64Type(); }
+static inline LType doubleType() { return LLVMDoubleType(); }
 
 static inline LType pointerType(LType type) { return LLVMPointerType(type, 0); }
 
@@ -134,17 +136,58 @@
 
 enum BitExtension { ZeroExtend, SignExtend };
 static inline LValue constInt(LType type, unsigned long long value, BitExtension extension) { return LLVMConstInt(type, value, extension == SignExtend); }
+static inline LValue constReal(LType type, double value) { return LLVMConstReal(type, value); }
 static inline LValue constIntToPtr(LValue value, LType type) { return LLVMConstIntToPtr(value, type); }
 static inline LValue constBitCast(LValue value, LType type) { return LLVMConstBitCast(value, type); }
 
 static inline LBasicBlock appendBasicBlock(LValue function, const char* name = "") { return LLVMAppendBasicBlock(function, name); }
 static inline LBasicBlock insertBasicBlock(LBasicBlock beforeBasicBlock, const char* name = "") { return LLVMInsertBasicBlock(beforeBasicBlock, name); }
 
+static inline LValue buildPhi(LBuilder builder, LType type) { return LLVMBuildPhi(builder, type, ""); }
+static inline void addIncoming(LValue phi, const LValue* values, const LBasicBlock* blocks, unsigned numPredecessors)
+{
+    LLVMAddIncoming(phi, const_cast<LValue*>(values), const_cast<LBasicBlock*>(blocks), numPredecessors);
+}
+template<typename ValueVectorType, typename BlockVectorType>
+static inline void addIncoming(LValue phi, const ValueVectorType& values, const BlockVectorType& blocks)
+{
+    ASSERT(values.size() == blocks.size());
+    addIncoming(phi, values.begin(), blocks.begin(), values.size());
+}
+static inline void addIncoming(LValue phi, LValue value1, LBasicBlock block1)
+{
+    addIncoming(phi, &value1, &block1, 1);
+}
+static inline void addIncoming(LValue phi, LValue value1, LBasicBlock block1, LValue value2, LBasicBlock block2)
+{
+    LValue values[] = { value1, value2 };
+    LBasicBlock blocks[] = { block1, block2 };
+    addIncoming(phi, values, blocks, 2);
+}
+static inline LValue buildPhi(LBuilder builder, LType type, LValue value1, LBasicBlock block1)
+{
+    LValue result = buildPhi(builder, type);
+    addIncoming(result, value1, block1);
+    return result;
+}
+static inline LValue buildPhi(
+    LBuilder builder, LType type, LValue value1, LBasicBlock block1, LValue value2,
+    LBasicBlock block2)
+{
+    LValue result = buildPhi(builder, type);
+    addIncoming(result, value1, block1, value2, block2);
+    return result;
+}
+
 static inline LValue buildAlloca(LBuilder builder, LType type) { return LLVMBuildAlloca(builder, type, ""); }
 static inline LValue buildAdd(LBuilder builder, LValue left, LValue right) { return LLVMBuildAdd(builder, left, right, ""); }
 static inline LValue buildSub(LBuilder builder, LValue left, LValue right) { return LLVMBuildSub(builder, left, right, ""); }
 static inline LValue buildMul(LBuilder builder, LValue left, LValue right) { return LLVMBuildMul(builder, left, right, ""); }
 static inline LValue buildNeg(LBuilder builder, LValue value) { return LLVMBuildNeg(builder, value, ""); }
+static inline LValue buildFAdd(LBuilder builder, LValue left, LValue right) { return LLVMBuildFAdd(builder, left, right, ""); }
+static inline LValue buildFSub(LBuilder builder, LValue left, LValue right) { return LLVMBuildFSub(builder, left, right, ""); }
+static inline LValue buildFMul(LBuilder builder, LValue left, LValue right) { return LLVMBuildFMul(builder, left, right, ""); }
+static inline LValue buildFNeg(LBuilder builder, LValue value) { return LLVMBuildFNeg(builder, value, ""); }
 static inline LValue buildAnd(LBuilder builder, LValue left, LValue right) { return LLVMBuildAnd(builder, left, right, ""); }
 static inline LValue buildOr(LBuilder builder, LValue left, LValue right) { return LLVMBuildOr(builder, left, right, ""); }
 static inline LValue buildXor(LBuilder builder, LValue left, LValue right) { return LLVMBuildXor(builder, left, right, ""); }
@@ -154,10 +197,14 @@
 static inline LValue buildLoad(LBuilder builder, LValue pointer) { return LLVMBuildLoad(builder, pointer, ""); }
 static inline LValue buildStore(LBuilder builder, LValue value, LValue pointer) { return LLVMBuildStore(builder, value, pointer); }
 static inline LValue buildZExt(LBuilder builder, LValue value, LType type) { return LLVMBuildZExt(builder, value, type, ""); }
+static inline LValue buildSIToFP(LBuilder builder, LValue value, LType type) { return LLVMBuildSIToFP(builder, value, type, ""); }
+static inline LValue buildUIToFP(LBuilder builder, LValue value, LType type) { return LLVMBuildUIToFP(builder, value, type, ""); }
 static inline LValue buildIntCast(LBuilder builder, LValue value, LType type) { return LLVMBuildIntCast(builder, value, type, ""); }
 static inline LValue buildIntToPtr(LBuilder builder, LValue value, LType type) { return LLVMBuildIntToPtr(builder, value, type, ""); }
 static inline LValue buildPtrToInt(LBuilder builder, LValue value, LType type) { return LLVMBuildPtrToInt(builder, value, type, ""); }
+static inline LValue buildBitCast(LBuilder builder, LValue value, LType type) { return LLVMBuildBitCast(builder, value, type, ""); }
 static inline LValue buildICmp(LBuilder builder, LIntPredicate cond, LValue left, LValue right) { return LLVMBuildICmp(builder, cond, left, right, ""); }
+static inline LValue buildFCmp(LBuilder builder, LRealPredicate cond, LValue left, LValue right) { return LLVMBuildFCmp(builder, cond, left, right, ""); }
 static inline LValue buildCall(LBuilder builder, LValue function, const LValue* args, unsigned numArgs)
 {
     return LLVMBuildCall(builder, function, const_cast<LValue*>(args), numArgs, "");

Modified: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (153132 => 153133)


--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2013-07-25 03:59:04 UTC (rev 153132)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2013-07-25 03:59:06 UTC (rev 153133)
@@ -50,6 +50,9 @@
                 case UntypedUse:
                 case Int32Use:
                 case KnownInt32Use:
+                case NumberUse:
+                case KnownNumberUse:
+                case RealNumberUse:
                 case BooleanUse:
                 case CellUse:
                 case KnownCellUse:
@@ -90,22 +93,13 @@
             case PutByOffset:
             case GetGlobalVar:
             case PutGlobalVar:
-                // These are OK.
-                break;
             case ValueAdd:
             case ArithAdd:
             case ArithSub:
             case ArithMul:
-                if (node->binaryUseKind() == Int32Use)
-                    break;
-                return false;
             case ArithNegate:
-                if (node->child1().useKind() == Int32Use)
-                    break;
-                return false;
             case UInt32ToNumber:
-                if (!nodeCanSpeculateInteger(node->arithNodeFlags()))
-                    return false;
+                // These are OK.
                 break;
             case GetArrayLength:
                 switch (node->arrayMode().type()) {
@@ -120,6 +114,7 @@
             case GetByVal:
                 switch (node->arrayMode().type()) {
                 case Array::Int32:
+                case Array::Double:
                 case Array::Contiguous:
                     break;
                 default:
@@ -136,12 +131,16 @@
             case CompareEq:
                 if (node->isBinaryUseKind(Int32Use))
                     break;
+                if (node->isBinaryUseKind(NumberUse))
+                    break;
                 if (node->isBinaryUseKind(ObjectUse))
                     break;
                 return false;
             case CompareLess:
                 if (node->isBinaryUseKind(Int32Use))
                     break;
+                if (node->isBinaryUseKind(NumberUse))
+                    break;
                 return false;
             case Branch:
                 if (node->child1().useKind() == BooleanUse)

Modified: trunk/Source/_javascript_Core/ftl/FTLCommonValues.cpp (153132 => 153133)


--- trunk/Source/_javascript_Core/ftl/FTLCommonValues.cpp	2013-07-25 03:59:04 UTC (rev 153132)
+++ trunk/Source/_javascript_Core/ftl/FTLCommonValues.cpp	2013-07-25 03:59:06 UTC (rev 153133)
@@ -36,9 +36,11 @@
     , int32(int32Type())
     , int64(int64Type())
     , intPtr(intPtrType())
+    , doubleType(FTL::doubleType())
     , ref32(pointerType(int32))
     , ref64(pointerType(int64))
     , refPtr(pointerType(intPtr))
+    , refDouble(pointerType(doubleType))
     , booleanTrue(constInt(boolean, true, ZeroExtend))
     , booleanFalse(constInt(boolean, false, ZeroExtend))
     , int32Zero(constInt(int32, 0, SignExtend))
@@ -50,6 +52,7 @@
     , intPtrFour(constInt(intPtr, 4, SignExtend))
     , intPtrEight(constInt(intPtr, 8, SignExtend))
     , intPtrPtr(constInt(intPtr, sizeof(void*), SignExtend))
+    , doubleZero(constReal(doubleType, 0))
     , m_module(0)
 {
 }

Modified: trunk/Source/_javascript_Core/ftl/FTLCommonValues.h (153132 => 153133)


--- trunk/Source/_javascript_Core/ftl/FTLCommonValues.h	2013-07-25 03:59:04 UTC (rev 153132)
+++ trunk/Source/_javascript_Core/ftl/FTLCommonValues.h	2013-07-25 03:59:06 UTC (rev 153133)
@@ -48,9 +48,11 @@
     const LType int32;
     const LType int64;
     const LType intPtr;
+    const LType doubleType;
     const LType ref32;
     const LType ref64;
     const LType refPtr;
+    const LType refDouble;
     const LValue booleanTrue;
     const LValue booleanFalse;
     const LValue int32Zero;
@@ -62,6 +64,7 @@
     const LValue intPtrFour;
     const LValue intPtrEight;
     const LValue intPtrPtr;
+    const LValue doubleZero;
     
     LModule m_module;
 };

Modified: trunk/Source/_javascript_Core/ftl/FTLCompile.cpp (153132 => 153133)


--- trunk/Source/_javascript_Core/ftl/FTLCompile.cpp	2013-07-25 03:59:04 UTC (rev 153132)
+++ trunk/Source/_javascript_Core/ftl/FTLCompile.cpp	2013-07-25 03:59:06 UTC (rev 153133)
@@ -55,9 +55,10 @@
     char* error = 0;
     
     LLVMMCJITCompilerOptions options;
-    memset(&options, 0, sizeof(options));
+    LLVMInitializeMCJITCompilerOptions(&options, sizeof(options));
     options.OptLevel = Options::llvmOptimizationLevel();
     options.NoFramePointerElim = true;
+    options.CodeModel = LLVMCodeModelSmall;
     
     if (LLVMCreateMCJITCompilerForModule(&engine, state.module, &options, sizeof(options), &error)) {
         dataLog("FATAL: Could not create LLVM execution engine: ", error, "\n");

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp (153132 => 153133)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp	2013-07-25 03:59:04 UTC (rev 153132)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp	2013-07-25 03:59:06 UTC (rev 153133)
@@ -62,6 +62,7 @@
         , m_localsBoolean(OperandsLike, state.graph.m_blocks[0]->variablesAtHead)
         , m_locals32(OperandsLike, state.graph.m_blocks[0]->variablesAtHead)
         , m_locals64(OperandsLike, state.graph.m_blocks[0]->variablesAtHead)
+        , m_localsDouble(OperandsLike, state.graph.m_blocks[0]->variablesAtHead)
         , m_valueSources(OperandsLike, state.graph.m_blocks[0]->variablesAtHead)
         , m_lastSetOperand(std::numeric_limits<int>::max())
         , m_exitThunkGenerator(state)
@@ -86,6 +87,7 @@
             m_localsBoolean[index] = buildAlloca(m_out.m_builder, m_out.boolean);
             m_locals32[index] = buildAlloca(m_out.m_builder, m_out.int32);
             m_locals64[index] = buildAlloca(m_out.m_builder, m_out.int64);
+            m_localsDouble[index] = buildAlloca(m_out.m_builder, m_out.doubleType);
         }
         
         m_initialization = appendBasicBlock(m_ftlState.function);
@@ -422,9 +424,8 @@
         
         if (variable->shouldUnboxIfPossible()) {
             if (variable->shouldUseDoubleFormat()) {
-                // FIXME: implement doubles in FTL.
-                // https://bugs.webkit.org/show_bug.cgi?id=113624
-                RELEASE_ASSERT_NOT_REACHED();
+                m_doubleValues.add(m_node, m_out.get(m_localsDouble.operand(variable->local())));
+                return;
             }
             
             // Locals that are marked shouldUnboxIfPossible() that aren't also forced to
@@ -456,9 +457,12 @@
         
         if (variable->shouldUnboxIfPossible()) {
             if (variable->shouldUseDoubleFormat()) {
-                // FIXME: implement doubles in FTL.
-                // https://bugs.webkit.org/show_bug.cgi?id=113624
-                RELEASE_ASSERT_NOT_REACHED();
+                LValue value = lowDouble(m_node->child1());
+                m_out.set(value, m_localsDouble.operand(variable->local()));
+                if (needsFlushing) {
+                    m_out.storeDouble(value, addressFor(variable->local()));
+                    m_valueSources.operand(variable->local()) = ValueSource(DoubleInJSStack);
+                }
                 return;
             }
             
@@ -552,6 +556,13 @@
             break;
         }
             
+        case NumberUse: {
+            m_doubleValues.add(
+                m_node,
+                m_out.doubleAdd(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
+            break;
+        }
+            
         default:
             RELEASE_ASSERT_NOT_REACHED();
             break;
@@ -576,6 +587,13 @@
             break;
         }
             
+        case NumberUse: {
+            m_doubleValues.add(
+                m_node,
+                m_out.doubleSub(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
+            break;
+        }
+            
         default:
             RELEASE_ASSERT_NOT_REACHED();
             break;
@@ -613,6 +631,13 @@
             break;
         }
             
+        case NumberUse: {
+            m_doubleValues.add(
+                m_node,
+                m_out.doubleMul(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
+            break;
+        }
+            
         default:
             RELEASE_ASSERT_NOT_REACHED();
             break;
@@ -640,6 +665,11 @@
             break;
         }
             
+        case NumberUse: {
+            m_doubleValues.add(m_node, m_out.doubleNeg(lowDouble(m_node->child1())));
+            break;
+        }
+            
         default:
             RELEASE_ASSERT_NOT_REACHED();
             break;
@@ -693,15 +723,13 @@
     
     void compileUInt32ToNumber()
     {
+        LValue value = lowInt32(m_node->child1());
+
         if (!nodeCanSpeculateInteger(m_node->arithNodeFlags())) {
-            // FIXME: implement doubles in FTL.
-            // https://bugs.webkit.org/show_bug.cgi?id=113624
-            
-            RELEASE_ASSERT_NOT_REACHED();
+            m_doubleValues.add(m_node, m_out.unsignedToDouble(value));
             return;
         }
         
-        LValue value = lowInt32(m_node->child1());
         speculateForward(
             Overflow, noValue(), 0, m_out.lessThan(value, m_out.int32Zero),
             FormattedValue(ValueFormatUInt32, value));
@@ -821,6 +849,36 @@
             break;
         }
             
+        case Array::Double: {
+            if (m_node->arrayMode().isInBounds()) {
+                if (m_node->arrayMode().isSaneChain()) {
+                    // FIXME: Implement structure transition watchpoints.
+                    // https://bugs.webkit.org/show_bug.cgi?id=113647
+                }
+            
+                speculate(
+                    OutOfBounds, noValue(), 0,
+                    m_out.aboveOrEqual(
+                        index, m_out.load32(storage, m_heaps.Butterfly_publicLength)));
+                
+                LValue result = m_out.loadDouble(m_out.baseIndex(
+                    m_heaps.indexedDoubleProperties,
+                    storage, m_out.zeroExt(index, m_out.intPtr),
+                    m_state.forNode(m_node->child2()).m_value));
+                
+                if (!m_node->arrayMode().isSaneChain()) {
+                    speculate(
+                        LoadFromHole, noValue(), 0,
+                        m_out.doubleNotEqualOrUnordered(result, result));
+                }
+                m_doubleValues.add(m_node, result);
+                break;
+            }
+            
+            RELEASE_ASSERT_NOT_REACHED();
+            break;
+        }
+            
         default:
             RELEASE_ASSERT_NOT_REACHED();
             break;
@@ -874,6 +932,12 @@
             return;
         }
         
+        if (m_node->isBinaryUseKind(NumberUse)) {
+            m_booleanValues.add(
+                m_node,
+                m_out.doubleEqual(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
+        }
+        
         if (m_node->isBinaryUseKind(ObjectUse)) {
             m_booleanValues.add(
                 m_node,
@@ -893,6 +957,12 @@
             return;
         }
         
+        if (m_node->isBinaryUseKind(NumberUse)) {
+            m_booleanValues.add(
+                m_node,
+                m_out.doubleLessThan(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
+        }
+        
         RELEASE_ASSERT_NOT_REACHED();
     }
     
@@ -1042,6 +1112,57 @@
         return m_out.booleanFalse;
     }
     
+    LValue lowDouble(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
+    {
+        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || isDouble(edge.useKind()));
+        
+        if (LValue result = m_doubleValues.get(edge.node()))
+            return result;
+        
+        if (LValue intResult = m_int32Values.get(edge.node())) {
+            LValue result = m_out.intToDouble(intResult);
+            m_doubleValues.add(edge.node(), result);
+            return result;
+        }
+        
+        if (LValue boxedResult = m_jsValueValues.get(edge.node())) {
+            LBasicBlock intCase = FTL_NEW_BLOCK(m_out, ("Double unboxing int case"));
+            LBasicBlock doubleCase = FTL_NEW_BLOCK(m_out, ("Double unboxing double case"));
+            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Double unboxing continuation"));
+            
+            m_out.branch(isNotInt32(boxedResult), doubleCase, intCase);
+            
+            LBasicBlock lastNext = m_out.appendTo(intCase, doubleCase);
+            
+            LValue intToDouble = m_out.intToDouble(unboxInt32(boxedResult));
+            LBasicBlock intToDoubleBlock = m_out.m_block;
+            m_out.jump(continuation);
+            
+            m_out.appendTo(doubleCase, continuation);
+            
+            FTL_TYPE_CHECK(
+                jsValueValue(boxedResult), edge, SpecNumber, isCellOrMisc(boxedResult));
+            
+            LValue unboxedDouble = unboxDouble(boxedResult);
+            LBasicBlock unboxedDoubleBlock = m_out.m_block;
+            m_out.jump(continuation);
+            
+            m_out.appendTo(continuation, lastNext);
+            
+            LValue result = m_out.phi(
+                m_out.doubleType,
+                intToDouble, intToDoubleBlock,
+                unboxedDouble, unboxedDoubleBlock);
+            
+            m_doubleValues.add(edge.node(), result);
+            return result;
+        }
+        
+        RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecNumber));
+        terminate(Uncountable);
+        return m_out.doubleZero;
+    }
+    
     LValue lowJSValue(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
     {
         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == UntypedUse);
@@ -1061,6 +1182,12 @@
             return result;
         }
         
+        if (LValue unboxedResult = m_doubleValues.get(edge.node())) {
+            LValue result = boxDouble(unboxedResult);
+            m_jsValueValues.add(edge.node(), result);
+            return result;
+        }
+        
         RELEASE_ASSERT_NOT_REACHED();
         return 0;
     }
@@ -1088,6 +1215,19 @@
         return m_out.add(m_out.zeroExt(value, m_out.int64), m_tagTypeNumber);
     }
     
+    LValue isCellOrMisc(LValue jsValue)
+    {
+        return m_out.testIsZero64(jsValue, m_tagTypeNumber);
+    }
+    LValue unboxDouble(LValue jsValue)
+    {
+        return m_out.bitCast(m_out.add(jsValue, m_tagTypeNumber), m_out.doubleType);
+    }
+    LValue boxDouble(LValue doubleValue)
+    {
+        return m_out.sub(m_out.bitCast(doubleValue, m_out.int64), m_tagTypeNumber);
+    }
+    
     LValue isNotCell(LValue jsValue)
     {
         return m_out.testNonZero64(jsValue, m_tagMask);
@@ -1117,6 +1257,7 @@
         case UntypedUse:
             break;
         case KnownInt32Use:
+        case KnownNumberUse:
             ASSERT(!m_state.needsTypeCheck(edge));
             break;
         case Int32Use:
@@ -1131,6 +1272,12 @@
         case ObjectUse:
             speculateObject(edge);
             break;
+        case RealNumberUse:
+            speculateRealNumber(edge);
+            break;
+        case NumberUse:
+            speculateNumber(edge);
+            break;
         default:
             RELEASE_ASSERT_NOT_REACHED();
         }
@@ -1165,6 +1312,27 @@
         speculateObject(edge, lowCell(edge));
     }
     
+    void speculateNumber(Edge edge)
+    {
+        // Do an early return here because lowDouble() can create a lot of control flow.
+        if (!m_state.needsTypeCheck(edge))
+            return;
+        
+        lowDouble(edge);
+    }
+    
+    void speculateRealNumber(Edge edge)
+    {
+        // Do an early return here because lowDouble() can create a lot of control flow.
+        if (!m_state.needsTypeCheck(edge))
+            return;
+        
+        LValue value = lowDouble(edge);
+        FTL_TYPE_CHECK(
+            doubleValue(value), edge, SpecRealNumber,
+            m_out.doubleNotEqualOrUnordered(value, value));
+    }
+    
     bool isLive(Node* node)
     {
         HashMap<Node*, unsigned>::iterator iter = m_timeToLive.find(node);
@@ -1315,9 +1483,8 @@
                     exit, arguments, i, ValueFormatBoolean, m_out.get(m_localsBoolean[i]));
                 break;
             case DoubleInLocals:
-                // FIXME: implement doubles in FTL.
-                // https://bugs.webkit.org/show_bug.cgi?id=113624
-                RELEASE_ASSERT_NOT_REACHED();
+                addExitArgument(
+                    exit, arguments, i, ValueFormatDouble, m_out.get(m_localsDouble[i]));
                 break;
             case ArgumentsSource:
                 // FIXME: implement PhantomArguments.
@@ -1454,8 +1621,11 @@
             return;
         }
         
-        // FIXME: Implement doubles in the FTL.
-        // https://bugs.webkit.org/show_bug.cgi?id=113624
+        if (LValue result = m_doubleValues.get(node)) {
+            addExitArgument(exit, arguments, index, ValueFormatDouble, result);
+            return;
+        }
+
         RELEASE_ASSERT_NOT_REACHED();
     }
     
@@ -1600,11 +1770,13 @@
     HashMap<Node*, LValue> m_jsValueValues;
     HashMap<Node*, LValue> m_booleanValues;
     HashMap<Node*, LValue> m_storageValues;
+    HashMap<Node*, LValue> m_doubleValues;
     HashMap<Node*, unsigned> m_timeToLive;
     
     Operands<LValue> m_localsBoolean;
     Operands<LValue> m_locals32;
     Operands<LValue> m_locals64;
+    Operands<LValue> m_localsDouble;
     
     Operands<ValueSource> m_valueSources;
     int m_lastSetOperand;

Modified: trunk/Source/_javascript_Core/ftl/FTLOutput.h (153132 => 153133)


--- trunk/Source/_javascript_Core/ftl/FTLOutput.h	2013-07-25 03:59:04 UTC (rev 153132)
+++ trunk/Source/_javascript_Core/ftl/FTLOutput.h	2013-07-25 03:59:06 UTC (rev 153133)
@@ -109,11 +109,28 @@
     template<typename T>
     LValue constIntPtr(T value) { return constInt(intPtr, bitwise_cast<intptr_t>(value), SignExtend); }
     LValue constInt64(int64_t value) { return constInt(int64, value, SignExtend); }
+    LValue constDouble(double value) { return constReal(doubleType, value); }
     
+    LValue phi(LType type) { return buildPhi(m_builder, type); }
+    LValue phi(LType type, LValue value1, LBasicBlock block1)
+    {
+        return buildPhi(m_builder, type, value1, block1);
+    }
+    LValue phi(LType type, LValue value1, LBasicBlock block1, LValue value2, LBasicBlock block2)
+    {
+        return buildPhi(m_builder, type, value1, block1, value2, block2);
+    }
+    
     LValue add(LValue left, LValue right) { return buildAdd(m_builder, left, right); }
     LValue sub(LValue left, LValue right) { return buildSub(m_builder, left, right); }
     LValue mul(LValue left, LValue right) { return buildMul(m_builder, left, right); }
     LValue neg(LValue value) { return buildNeg(m_builder, value); }
+
+    LValue doubleAdd(LValue left, LValue right) { return buildFAdd(m_builder, left, right); }
+    LValue doubleSub(LValue left, LValue right) { return buildFSub(m_builder, left, right); }
+    LValue doubleMul(LValue left, LValue right) { return buildFMul(m_builder, left, right); }
+    LValue doubleNeg(LValue value) { return buildFNeg(m_builder, value); }
+
     LValue bitAnd(LValue left, LValue right) { return buildAnd(m_builder, left, right); }
     LValue bitOr(LValue left, LValue right) { return buildOr(m_builder, left, right); }
     LValue bitXor(LValue left, LValue right) { return buildXor(m_builder, left, right); }
@@ -135,9 +152,14 @@
     }
     
     LValue zeroExt(LValue value, LType type) { return buildZExt(m_builder, value, type); }
+    LValue intToFP(LValue value, LType type) { return buildSIToFP(m_builder, value, type); }
+    LValue intToDouble(LValue value) { return intToFP(value, doubleType); }
+    LValue unsignedToFP(LValue value, LType type) { return buildUIToFP(m_builder, value, type); }
+    LValue unsignedToDouble(LValue value) { return unsignedToFP(value, doubleType); }
     LValue intCast(LValue value, LType type) { return buildIntCast(m_builder, value, type); }
     LValue castToInt32(LValue value) { return intCast(value, int32); }
     LValue intToPtr(LValue value, LType type) { return buildIntToPtr(m_builder, value, type); }
+    LValue bitCast(LValue value, LType type) { return buildBitCast(m_builder, value, type); }
     
     LValue get(LValue reference) { return buildLoad(m_builder, reference); }
     LValue set(LValue value, LValue reference) { return buildStore(m_builder, value, reference); }
@@ -157,9 +179,11 @@
     LValue load32(TypedPointer pointer) { return load(pointer, ref32); }
     LValue load64(TypedPointer pointer) { return load(pointer, ref64); }
     LValue loadPtr(TypedPointer pointer) { return load(pointer, refPtr); }
+    LValue loadDouble(TypedPointer pointer) { return load(pointer, refDouble); }
     void store32(LValue value, TypedPointer pointer) { store(value, pointer, ref32); }
     void store64(LValue value, TypedPointer pointer) { store(value, pointer, ref64); }
     void storePtr(LValue value, TypedPointer pointer) { store(value, pointer, refPtr); }
+    void storeDouble(LValue value, TypedPointer pointer) { store(value, pointer, refDouble); }
 
     LValue addPtr(LValue value, ptrdiff_t immediate = 0)
     {
@@ -239,9 +263,23 @@
     LValue lessThan(LValue left, LValue right) { return buildICmp(m_builder, LLVMIntSLT, left, right); }
     LValue lessThanOrEqual(LValue left, LValue right) { return buildICmp(m_builder, LLVMIntSLE, left, right); }
     
+    LValue doubleEqual(LValue left, LValue right) { return buildFCmp(m_builder, LLVMRealOEQ, left, right); }
+    LValue doubleNotEqualOrUnordered(LValue left, LValue right) { return buildFCmp(m_builder, LLVMRealUNE, left, right); }
+    LValue doubleLessThan(LValue left, LValue right) { return buildFCmp(m_builder, LLVMRealOLT, left, right); }
+    LValue doubleLessThanOrEqual(LValue left, LValue right) { return buildFCmp(m_builder, LLVMRealOLE, left, right); }
+    LValue doubleGreaterThan(LValue left, LValue right) { return buildFCmp(m_builder, LLVMRealOGT, left, right); }
+    LValue doubleGreaterThanOrEqual(LValue left, LValue right) { return buildFCmp(m_builder, LLVMRealOGE, left, right); }
+    LValue doubleEqualOrUnordered(LValue left, LValue right) { return buildFCmp(m_builder, LLVMRealUEQ, left, right); }
+    LValue doubleNotEqual(LValue left, LValue right) { return buildFCmp(m_builder, LLVMRealONE, left, right); }
+    LValue doubleLessThanOrUnordered(LValue left, LValue right) { return buildFCmp(m_builder, LLVMRealULT, left, right); }
+    LValue doubleLessThanOrEqualOrUnordered(LValue left, LValue right) { return buildFCmp(m_builder, LLVMRealULE, left, right); }
+    LValue doubleGreaterThanOrUnordered(LValue left, LValue right) { return buildFCmp(m_builder, LLVMRealUGT, left, right); }
+    LValue doubleGreaterThanOrEqualOrUnordered(LValue left, LValue right) { return buildFCmp(m_builder, LLVMRealUGE, left, right); }
+    
     LValue isZero64(LValue value) { return equal(value, int64Zero); }
     LValue notZero64(LValue value) { return notEqual(value, int64Zero); }
     
+    LValue testIsZero64(LValue value, LValue mask) { return isZero64(bitAnd(value, mask)); }
     LValue testNonZero64(LValue value, LValue mask) { return notZero64(bitAnd(value, mask)); }
     
     LValue select(LValue value, LValue taken, LValue notTaken) { return buildSelect(m_builder, value, taken, notTaken); }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to