Improve float array support in the DFG JIT
authoroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 3 Dec 2011 01:47:27 +0000 (01:47 +0000)
committeroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 3 Dec 2011 01:47:27 +0000 (01:47 +0000)
https://bugs.webkit.org/show_bug.cgi?id=73722

Reviewed by Gavin Barraclough.

Add basic support for float typed arrays in JSC.  This is currently
less optimal than it could be in the following ways:
 * float32Array1[0] = float32Array2[0] (eg. an element by element copy)
   promotes float to double and then back to float.
 * float64Array[0] will always perform NaN tests in order to prevent
   signalling NaNs from entering the engine.

We also don't support Float32Array on ARMv7

* assembler/MacroAssemblerARMv7.h:
(JSC::MacroAssemblerARMv7::loadDouble):
(JSC::MacroAssemblerARMv7::loadFloat):
(JSC::MacroAssemblerARMv7::storeDouble):
(JSC::MacroAssemblerARMv7::storeFloat):
(JSC::MacroAssemblerARMv7::convertFloatToDouble):
(JSC::MacroAssemblerARMv7::convertDoubleToFloat):
* assembler/MacroAssemblerX86Common.h:
(JSC::MacroAssemblerX86Common::loadDouble):
(JSC::MacroAssemblerX86Common::loadFloat):
(JSC::MacroAssemblerX86Common::storeDouble):
(JSC::MacroAssemblerX86Common::storeFloat):
(JSC::MacroAssemblerX86Common::convertDoubleToFloat):
(JSC::MacroAssemblerX86Common::convertFloatToDouble):
* assembler/X86Assembler.h:
(JSC::X86Assembler::cvtsd2ss_rr):
(JSC::X86Assembler::cvtss2sd_rr):
(JSC::X86Assembler::movsd_rm):
(JSC::X86Assembler::movss_rm):
(JSC::X86Assembler::movsd_mr):
(JSC::X86Assembler::movss_mr):
* dfg/DFGAbstractState.cpp:
(JSC::DFG::AbstractState::execute):
* dfg/DFGNode.h:
(JSC::DFG::Node::shouldSpeculateFloat32Array):
* dfg/DFGPropagator.cpp:
(JSC::DFG::Propagator::propagateNodePredictions):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray):
(JSC::DFG::SpeculativeJIT::compileGetByValOnFloatTypedArray):
(JSC::DFG::SpeculativeJIT::compilePutByValForFloatTypedArray):
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::fillSpeculateIntInternal):
(JSC::DFG::SpeculativeJIT::compile):

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

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h
Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h
Source/JavaScriptCore/assembler/X86Assembler.h
Source/JavaScriptCore/dfg/DFGAbstractState.cpp
Source/JavaScriptCore/dfg/DFGNode.h
Source/JavaScriptCore/dfg/DFGPropagator.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

index 01a8aa018a763f05a433350d46a5d7cfd12661f4..9afa96768573b73dbae1832cbf15047e518bc247 100644 (file)
@@ -1,3 +1,57 @@
+2011-12-02  Oliver Hunt  <oliver@apple.com>
+
+        Improve float array support in the DFG JIT
+        https://bugs.webkit.org/show_bug.cgi?id=73722
+
+        Reviewed by Gavin Barraclough.
+
+        Add basic support for float typed arrays in JSC.  This is currently
+        less optimal than it could be in the following ways:
+         * float32Array1[0] = float32Array2[0] (eg. an element by element copy) 
+           promotes float to double and then back to float.
+         * float64Array[0] will always perform NaN tests in order to prevent
+           signalling NaNs from entering the engine.
+
+        We also don't support Float32Array on ARMv7
+
+        * assembler/MacroAssemblerARMv7.h:
+        (JSC::MacroAssemblerARMv7::loadDouble):
+        (JSC::MacroAssemblerARMv7::loadFloat):
+        (JSC::MacroAssemblerARMv7::storeDouble):
+        (JSC::MacroAssemblerARMv7::storeFloat):
+        (JSC::MacroAssemblerARMv7::convertFloatToDouble):
+        (JSC::MacroAssemblerARMv7::convertDoubleToFloat):
+        * assembler/MacroAssemblerX86Common.h:
+        (JSC::MacroAssemblerX86Common::loadDouble):
+        (JSC::MacroAssemblerX86Common::loadFloat):
+        (JSC::MacroAssemblerX86Common::storeDouble):
+        (JSC::MacroAssemblerX86Common::storeFloat):
+        (JSC::MacroAssemblerX86Common::convertDoubleToFloat):
+        (JSC::MacroAssemblerX86Common::convertFloatToDouble):
+        * assembler/X86Assembler.h:
+        (JSC::X86Assembler::cvtsd2ss_rr):
+        (JSC::X86Assembler::cvtss2sd_rr):
+        (JSC::X86Assembler::movsd_rm):
+        (JSC::X86Assembler::movss_rm):
+        (JSC::X86Assembler::movsd_mr):
+        (JSC::X86Assembler::movss_mr):
+        * dfg/DFGAbstractState.cpp:
+        (JSC::DFG::AbstractState::execute):
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::shouldSpeculateFloat32Array):
+        * dfg/DFGPropagator.cpp:
+        (JSC::DFG::Propagator::propagateNodePredictions):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray):
+        (JSC::DFG::SpeculativeJIT::compileGetByValOnFloatTypedArray):
+        (JSC::DFG::SpeculativeJIT::compilePutByValForFloatTypedArray):
+        * dfg/DFGSpeculativeJIT.h:
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::fillSpeculateIntInternal):
+        (JSC::DFG::SpeculativeJIT::compile):
+
 2011-12-02  Sheriff Bot  <webkit.review.bot@gmail.com>
 
         Unreviewed, rolling out r101801.
index 92060350f3910edeee7099dd512d578ada4819c6..da9bbbb8f27049a68fff1a1f4b1b43a7648d2123 100644 (file)
@@ -711,6 +711,16 @@ public:
         m_assembler.vldr(dest, base, offset);
     }
 
+    void loadDouble(BaseIndex address, FPRegisterID dest)
+    {
+        ASSERT_NOT_REACHED();
+    }
+    
+    void loadFloat(BaseIndex address, FPRegisterID dest)
+    {
+        ASSERT_NOT_REACHED();
+    }
+
     void moveDouble(FPRegisterID src, FPRegisterID dest)
     {
         if (src != dest)
@@ -744,6 +754,20 @@ public:
         storeDouble(src, addressTempRegister);
     }
 
+    void storeDouble(FPRegisterID src, BaseIndex address)
+    {
+        move(address.index, addressTempRegister);
+        mul32(TrustedImm32(address.scale), addressTempRegister, addressTempRegister);
+        storeDouble(src, Address(addressTempRegister, address.offset));
+    }
+    
+    void storeFloat(FPRegisterID src, BaseIndex address)
+    {
+        move(address.index, addressTempRegister);
+        mul32(TrustedImm32(address.scale), addressTempRegister, addressTempRegister);
+        storeDouble(ARMRegisters::asSingle(src), Address(addressTempRegister, address.offset));
+    }
+
     void addDouble(FPRegisterID src, FPRegisterID dest)
     {
         m_assembler.vadd(dest, dest, src);
@@ -839,6 +863,16 @@ public:
         m_assembler.vmov(fpTempRegisterAsSingle(), dataTempRegister);
         m_assembler.vcvt_signedToFloatingPoint(dest, fpTempRegisterAsSingle());
     }
+    
+    void convertFloatToDouble(FPRegisterID src, FPRegisterID dst)
+    {
+        ASSERT_NOT_REACHED();
+    }
+    
+    void convertDoubleToFloat(FPRegisterID src, FPRegisterID dst)
+    {
+        ASSERT_NOT_REACHED();
+    }
 
     Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
     {
index 1ad434647734f84154e2de0373305df281186edc..dea724e4d95ebd0dddb08c0cc364915cdd986bed 100644 (file)
@@ -600,12 +600,47 @@ public:
         ASSERT(isSSE2Present());
         m_assembler.movsd_mr(address.offset, address.base, dest);
     }
+    
+    void loadDouble(BaseIndex address, FPRegisterID dest)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.movsd_mr(address.offset, address.base, address.index, address.scale, dest);
+    }
+    void loadFloat(BaseIndex address, FPRegisterID dest)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.movss_mr(address.offset, address.base, address.index, address.scale, dest);
+    }
 
     void storeDouble(FPRegisterID src, ImplicitAddress address)
     {
         ASSERT(isSSE2Present());
         m_assembler.movsd_rm(src, address.offset, address.base);
     }
+    
+    void storeDouble(FPRegisterID src, BaseIndex address)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.movsd_rm(src, address.offset, address.base, address.index, address.scale);
+    }
+    
+    void storeFloat(FPRegisterID src, BaseIndex address)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.movss_rm(src, address.offset, address.base, address.index, address.scale);
+    }
+    
+    void convertDoubleToFloat(FPRegisterID src, FPRegisterID dst)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.cvtsd2ss_rr(src, dst);
+    }
+
+    void convertFloatToDouble(FPRegisterID src, FPRegisterID dst)
+    {
+        ASSERT(isSSE2Present());
+        m_assembler.cvtss2sd_rr(src, dst);
+    }
 
     void addDouble(FPRegisterID src, FPRegisterID dest)
     {
index 079c190e340ad5398bcd14e1354b2c0125296f7d..55286a85d844de70489ebb184e24c0dc8d71c8e3 100644 (file)
@@ -155,6 +155,7 @@ private:
         OP_CALL_rel32                   = 0xE8,
         OP_JMP_rel32                    = 0xE9,
         PRE_SSE_F2                      = 0xF2,
+        PRE_SSE_F3                      = 0xF3,
         OP_HLT                          = 0xF4,
         OP_GROUP3_EbIb                  = 0xF6,
         OP_GROUP3_Ev                    = 0xF7,
@@ -165,11 +166,15 @@ private:
     typedef enum {
         OP2_MOVSD_VsdWsd    = 0x10,
         OP2_MOVSD_WsdVsd    = 0x11,
+        OP2_MOVSS_VsdWsd    = 0x10,
+        OP2_MOVSS_WsdVsd    = 0x11,
         OP2_CVTSI2SD_VsdEd  = 0x2A,
         OP2_CVTTSD2SI_GdWsd = 0x2C,
         OP2_UCOMISD_VsdWsd  = 0x2E,
         OP2_ADDSD_VsdWsd    = 0x58,
         OP2_MULSD_VsdWsd    = 0x59,
+        OP2_CVTSD2SS_VsdWsd = 0x5A,
+        OP2_CVTSS2SD_VsdWsd = 0x5A,
         OP2_SUBSD_VsdWsd    = 0x5C,
         OP2_DIVSD_VsdWsd    = 0x5E,
         OP2_SQRTSD_VsdWsd   = 0x51,
@@ -1435,6 +1440,18 @@ public:
         m_formatter.prefix(PRE_SSE_F2);
         m_formatter.twoByteOp(OP2_CVTTSD2SI_GdWsd, dst, (RegisterID)src);
     }
+
+    void cvtsd2ss_rr(XMMRegisterID src, XMMRegisterID dst)
+    {
+        m_formatter.prefix(PRE_SSE_F2);
+        m_formatter.twoByteOp(OP2_CVTSD2SS_VsdWsd, dst, (RegisterID)src);
+    }
+
+    void cvtss2sd_rr(XMMRegisterID src, XMMRegisterID dst)
+    {
+        m_formatter.prefix(PRE_SSE_F3);
+        m_formatter.twoByteOp(OP2_CVTSS2SD_VsdWsd, dst, (RegisterID)src);
+    }
     
 #if CPU(X86_64)
     void cvttsd2siq_rr(XMMRegisterID src, RegisterID dst)
@@ -1481,13 +1498,37 @@ public:
         m_formatter.prefix(PRE_SSE_F2);
         m_formatter.twoByteOp(OP2_MOVSD_WsdVsd, (RegisterID)src, base, offset);
     }
-
+    
+    void movsd_rm(XMMRegisterID src, int offset, RegisterID base, RegisterID index, int scale)
+    {
+        m_formatter.prefix(PRE_SSE_F2);
+        m_formatter.twoByteOp(OP2_MOVSD_WsdVsd, (RegisterID)src, base, index, scale, offset);
+    }
+    
+    void movss_rm(XMMRegisterID src, int offset, RegisterID base, RegisterID index, int scale)
+    {
+        m_formatter.prefix(PRE_SSE_F3);
+        m_formatter.twoByteOp(OP2_MOVSD_WsdVsd, (RegisterID)src, base, index, scale, offset);
+    }
+    
     void movsd_mr(int offset, RegisterID base, XMMRegisterID dst)
     {
         m_formatter.prefix(PRE_SSE_F2);
         m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, base, offset);
     }
 
+    void movsd_mr(int offset, RegisterID base, RegisterID index, int scale, XMMRegisterID dst)
+    {
+        m_formatter.prefix(PRE_SSE_F2);
+        m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, dst, base, index, scale, offset);
+    }
+    
+    void movss_mr(int offset, RegisterID base, RegisterID index, int scale, XMMRegisterID dst)
+    {
+        m_formatter.prefix(PRE_SSE_F3);
+        m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, dst, base, index, scale, offset);
+    }
+
 #if !CPU(X86_64)
     void movsd_mr(const void* address, XMMRegisterID dst)
     {
index 41761292f5051ebfb8b501a9c787dc163bdba630..373a0e0cb4685b00a5217421ccb98c854cccf765 100644 (file)
@@ -467,6 +467,18 @@ bool AbstractState::execute(NodeIndex nodeIndex)
             forNode(nodeIndex).set(PredictDouble);
             break;
         }
+        if (m_graph[node.child1()].shouldSpeculateFloat32Array()) {
+            forNode(node.child1()).filter(PredictFloat32Array);
+            forNode(node.child2()).filter(PredictInt32);
+            forNode(nodeIndex).set(PredictDouble);
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateFloat64Array()) {
+            forNode(node.child1()).filter(PredictFloat64Array);
+            forNode(node.child2()).filter(PredictInt32);
+            forNode(nodeIndex).set(PredictDouble);
+            break;
+        }
         forNode(node.child1()).filter(PredictArray);
         forNode(node.child2()).filter(PredictInt32);
         forNode(nodeIndex).makeTop();
@@ -524,6 +536,18 @@ bool AbstractState::execute(NodeIndex nodeIndex)
             forNode(node.child3()).filter(PredictNumber);
             break;
         }
+        if (m_graph[node.child1()].shouldSpeculateFloat32Array()) {
+            forNode(node.child1()).filter(PredictFloat32Array);
+            forNode(node.child2()).filter(PredictInt32);
+            forNode(node.child3()).filter(PredictNumber);
+            break;
+        }
+        if (m_graph[node.child1()].shouldSpeculateFloat64Array()) {
+            forNode(node.child1()).filter(PredictFloat64Array);
+            forNode(node.child2()).filter(PredictInt32);
+            forNode(node.child3()).filter(PredictNumber);
+            break;
+        }
             
         forNode(node.child1()).filter(PredictArray);
         forNode(node.child2()).filter(PredictInt32);
index 1d33b7b75d90e34685ba42a36b3e4b472fffd722..a82798384dd3a49a14dd7cb30d66e1ed85c9c6ee 100644 (file)
@@ -954,7 +954,11 @@ struct Node {
     
     bool shouldSpeculateFloat32Array()
     {
-        return prediction() == PredictFloat32Array;
+#if CPU(X86) || CPU(X86_64)
+        return !!(prediction() & PredictFloat32Array);
+#else
+        return false;
+#endif
     }
     
     bool shouldSpeculateFloat64Array()
index 9b7999ec6e26835dec789f2082f0edc07cd3fd82..43625e3884051247829d6c0d3bb265b6e0639871 100644 (file)
@@ -465,7 +465,7 @@ private:
         }
             
         case GetByVal: {
-            if (m_graph[node.child1()].shouldSpeculateUint32Array())
+            if (m_graph[node.child1()].shouldSpeculateUint32Array() || m_graph[node.child1()].shouldSpeculateFloat32Array() || m_graph[node.child1()].shouldSpeculateFloat64Array())
                 changed |= mergePrediction(PredictDouble);
             else if (node.getHeapPrediction())
                 changed |= mergePrediction(node.getHeapPrediction());
index d825e294bf0d8635e7716c9219e881fe8b73bdf2..d68457fbae91167ceb31a0cb5434f2378803814f 100644 (file)
@@ -1675,10 +1675,16 @@ void SpeculativeJIT::compilePutByValForIntTypedArray(const TypedArrayDescriptor&
         GPRTemporary result(this);
         FPRReg fpr = valueOp.fpr();
         GPRReg gpr = result.gpr();
+        MacroAssembler::Jump notNaN = m_jit.branchDouble(MacroAssembler::DoubleEqual, fpr, fpr);
+        m_jit.xorPtr(gpr, gpr);
+        MacroAssembler::Jump fixed = m_jit.jump();
+        notNaN.link(&m_jit);
+    
         if (signedness == SignedTypedArray)
             m_jit.truncateDoubleToInt32(fpr, gpr);
         else
             m_jit.truncateDoubleToUint32(fpr, gpr);
+        fixed.link(&m_jit);
         value.adopt(result);
         valueGPR = gpr;
     }
@@ -1710,6 +1716,87 @@ void SpeculativeJIT::compilePutByValForIntTypedArray(const TypedArrayDescriptor&
     noResult(m_compileIndex);
 }
 
+void SpeculativeJIT::compileGetByValOnFloatTypedArray(const TypedArrayDescriptor& descriptor, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements)
+{
+    ASSERT(node.child3() == NoNode);
+    SpeculateCellOperand base(this, node.child1());
+    SpeculateStrictInt32Operand property(this, node.child2());
+    GPRReg baseReg = base.gpr();
+    GPRReg propertyReg = property.gpr();
+    
+    if (speculationRequirements != NoTypedArrayTypeSpecCheck)
+        speculationCheck(JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(descriptor.m_vptr)));
+    
+    // Load the character into scratchReg
+    GPRTemporary storage(this);
+    GPRReg storageReg = storage.gpr();
+    m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
+    FPRTemporary result(this);
+    FPRReg resultReg = result.fpr();
+    ASSERT(speculationRequirements != NoTypedArraySpecCheck);
+    MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(baseReg, descriptor.m_lengthOffset));
+    m_jit.breakpoint();
+    MacroAssembler::Jump outOfBounds = m_jit.jump();
+    inBounds.link(&m_jit);
+    switch (elementSize) {
+    case 4:
+        m_jit.loadFloat(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesFour), resultReg);
+        m_jit.convertFloatToDouble(resultReg, resultReg);
+        break;
+    case 8: {
+        m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
+        MacroAssembler::Jump notNaN = m_jit.branchDouble(MacroAssembler::DoubleEqual, resultReg, resultReg);
+        static const double NaN = std::numeric_limits<double>::quiet_NaN();
+        m_jit.loadDouble(&NaN, resultReg);
+        notNaN.link(&m_jit);
+        break;
+    }
+    default:
+        ASSERT_NOT_REACHED();
+    }
+    outOfBounds.link(&m_jit);
+    doubleResult(resultReg, m_compileIndex);
+}
+
+void SpeculativeJIT::compilePutByValForFloatTypedArray(const TypedArrayDescriptor& descriptor, GPRReg base, GPRReg property, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements)
+{
+    NodeIndex baseIndex = node.child1();
+    NodeIndex valueIndex = node.child3();
+    
+    SpeculateDoubleOperand valueOp(this, valueIndex);
+    
+    if (speculationRequirements != NoTypedArrayTypeSpecCheck)
+        speculationCheck(JSValueSource::unboxedCell(base), baseIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base), MacroAssembler::TrustedImmPtr(descriptor.m_vptr)));
+    
+    GPRTemporary result(this);
+    
+    GPRTemporary storage(this);
+    GPRReg storageReg = storage.gpr();
+    
+    m_jit.loadPtr(MacroAssembler::Address(base, descriptor.m_storageOffset), storageReg);
+    MacroAssembler::Jump outOfBounds;
+    if (speculationRequirements != NoTypedArraySpecCheck)
+        outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, property, MacroAssembler::Address(base, descriptor.m_lengthOffset));
+    
+    switch (elementSize) {
+    case 4: {
+        FPRTemporary scratch(this);
+        m_jit.moveDouble(valueOp.fpr(), scratch.fpr());
+        m_jit.convertDoubleToFloat(valueOp.fpr(), scratch.fpr());
+        m_jit.storeFloat(scratch.fpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesFour));
+        break;
+    }
+    case 8:
+        m_jit.storeDouble(valueOp.fpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesEight));
+        break;
+    default:
+        ASSERT_NOT_REACHED();
+    }
+    if (speculationRequirements != NoTypedArraySpecCheck)
+        outOfBounds.link(&m_jit);
+    noResult(m_compileIndex);
+}
+
 void SpeculativeJIT::compileInstanceOfForObject(Node&, GPRReg valueReg, GPRReg prototypeReg, GPRReg scratchReg)
 {
     // Check that prototype is an object.
index d8affb3dfb63a7e2466469a93ef3e260932ffb85..1ad49045b8193cc1e6f223f7f31dfb6924647dc7 100644 (file)
@@ -1962,6 +1962,8 @@ private:
     };
     void compileGetByValOnIntTypedArray(const TypedArrayDescriptor&, Node&, size_t elementSize, TypedArraySpeculationRequirements, TypedArraySignedness);
     void compilePutByValForIntTypedArray(const TypedArrayDescriptor&, GPRReg base, GPRReg property, Node&, size_t elementSize, TypedArraySpeculationRequirements, TypedArraySignedness);
+    void compileGetByValOnFloatTypedArray(const TypedArrayDescriptor&, Node&, size_t elementSize, TypedArraySpeculationRequirements);
+    void compilePutByValForFloatTypedArray(const TypedArrayDescriptor&, GPRReg base, GPRReg property, Node&, size_t elementSize, TypedArraySpeculationRequirements);
     
     // It is acceptable to have structure be equal to scratch, so long as you're fine
     // with the structure GPR being clobbered.
index bfe3529fe5139b2c9a6f0ef343331571d8a762d1..80c922d907b5e61404c8524db83b44835254f441 100644 (file)
@@ -2681,6 +2681,20 @@ void SpeculativeJIT::compile(Node& node)
                 return;
             break;            
         }
+        
+        if (at(node.child1()).shouldSpeculateFloat32Array()) {
+            compileGetByValOnFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), node, sizeof(float), isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateFloat64Array()) {
+            compileGetByValOnFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), node, sizeof(double), isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
 
         ASSERT(node.child3() == NoNode);
         SpeculateCellOperand base(this, node.child1());
@@ -2787,6 +2801,20 @@ void SpeculativeJIT::compile(Node& node)
                 return;
             break;            
         }
+        
+        if (at(node.child1()).shouldSpeculateFloat32Array()) {
+            compilePutByValForFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(float), isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateFloat64Array()) {
+            compilePutByValForFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(double), isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
 
         JSValueOperand value(this, node.child3());
         GPRTemporary scratch(this);
@@ -2899,6 +2927,20 @@ void SpeculativeJIT::compile(Node& node)
                 return;
             break;            
         }
+        
+        if (at(node.child1()).shouldSpeculateFloat32Array()) {
+            compilePutByValForFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(float), NoTypedArraySpecCheck);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateFloat64Array()) {
+            compilePutByValForFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(double), NoTypedArraySpecCheck);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
 
         JSValueOperand value(this, node.child3());
         GPRTemporary scratch(this, base);
index c85da1b2570d218faaa2d9cf81ca73aabd8b5ebd..a4bcdd86da7bc4f3602f58b6d89f3625e549a3a7 100644 (file)
@@ -1389,9 +1389,17 @@ GPRReg SpeculativeJIT::fillSpeculateIntInternal(NodeIndex nodeIndex, DataFormat&
     }
 
     case DataFormatDouble:
+    case DataFormatJSDouble: {
+        if (node.hasConstant() && isInt32Constant(nodeIndex)) {
+            GPRReg gpr = allocate();
+            ASSERT(isInt32Constant(nodeIndex));
+            m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);
+            returnFormat = DataFormatInteger;
+            return gpr;
+        }
+    }
     case DataFormatCell:
     case DataFormatBoolean:
-    case DataFormatJSDouble:
     case DataFormatJSCell:
     case DataFormatJSBoolean: {
         terminateSpeculativeExecution(JSValueRegs(), NoNode);
@@ -2676,6 +2684,20 @@ void SpeculativeJIT::compile(Node& node)
                 return;
             break;            
         }
+        
+        if (at(node.child1()).shouldSpeculateFloat32Array()) {
+            compileGetByValOnFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), node, sizeof(float), isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateFloat64Array()) {
+            compileGetByValOnFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), node, sizeof(double), isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
 
         ASSERT(node.child3() == NoNode);
         SpeculateCellOperand base(this, node.child1());
@@ -2775,6 +2797,20 @@ void SpeculativeJIT::compile(Node& node)
                 return;
             break;            
         }
+        
+        if (at(node.child1()).shouldSpeculateFloat32Array()) {
+            compilePutByValForFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(float), isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateFloat64Array()) {
+            compilePutByValForFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(double), isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
 
         JSValueOperand value(this, node.child3());
         GPRTemporary scratch(this);
@@ -2887,6 +2923,20 @@ void SpeculativeJIT::compile(Node& node)
                 return;
             break;            
         }
+        
+        if (at(node.child1()).shouldSpeculateFloat32Array()) {
+            compilePutByValForFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(float), NoTypedArraySpecCheck);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
+        
+        if (at(node.child1()).shouldSpeculateFloat64Array()) {
+            compilePutByValForFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(double), NoTypedArraySpecCheck);
+            if (!m_compileOkay)
+                return;
+            break;            
+        }
 
         JSValueOperand value(this, node.child3());
         GPRTemporary scratch(this);