Title: [155281] trunk/Source/_javascript_Core
Revision
155281
Author
[email protected]
Date
2013-09-07 21:08:01 -0700 (Sat, 07 Sep 2013)

Log Message

FTL should support typed array PutByVal
https://bugs.webkit.org/show_bug.cgi?id=120972

Reviewed by Oliver Hunt.

Due to increased FTL coverage, this revealed a bug in LICM where we were trying to
have AI execute the tail of a block that !cfaDidFinish. We don't need to execute AI
for such blocks since LICM will bail for them anyway, and AI asserts that cfaDidFinish
is true.

* dfg/DFGLICMPhase.cpp:
(JSC::DFG::LICMPhase::attemptHoist):
* ftl/FTLAbbreviations.h:
(JSC::FTL::buildFPToUI):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLIntrinsicRepository.h:
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compilePutByVal):
(JSC::FTL::LowerDFGToLLVM::doubleToInt32):
(JSC::FTL::LowerDFGToLLVM::doubleToUInt32):
* ftl/FTLOutput.h:
(JSC::FTL::Output::fpToUInt):
(JSC::FTL::Output::fpToUInt32):
(JSC::FTL::Output::store8):
(JSC::FTL::Output::store16):
(JSC::FTL::Output::storeFloat):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (155280 => 155281)


--- trunk/Source/_javascript_Core/ChangeLog	2013-09-08 03:46:22 UTC (rev 155280)
+++ trunk/Source/_javascript_Core/ChangeLog	2013-09-08 04:08:01 UTC (rev 155281)
@@ -1,5 +1,35 @@
 2013-09-07  Filip Pizlo  <[email protected]>
 
+        FTL should support typed array PutByVal
+        https://bugs.webkit.org/show_bug.cgi?id=120972
+
+        Reviewed by Oliver Hunt.
+
+        Due to increased FTL coverage, this revealed a bug in LICM where we were trying to
+        have AI execute the tail of a block that !cfaDidFinish. We don't need to execute AI
+        for such blocks since LICM will bail for them anyway, and AI asserts that cfaDidFinish
+        is true.
+
+        * dfg/DFGLICMPhase.cpp:
+        (JSC::DFG::LICMPhase::attemptHoist):
+        * ftl/FTLAbbreviations.h:
+        (JSC::FTL::buildFPToUI):
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLIntrinsicRepository.h:
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::LowerDFGToLLVM::compilePutByVal):
+        (JSC::FTL::LowerDFGToLLVM::doubleToInt32):
+        (JSC::FTL::LowerDFGToLLVM::doubleToUInt32):
+        * ftl/FTLOutput.h:
+        (JSC::FTL::Output::fpToUInt):
+        (JSC::FTL::Output::fpToUInt32):
+        (JSC::FTL::Output::store8):
+        (JSC::FTL::Output::store16):
+        (JSC::FTL::Output::storeFloat):
+
+2013-09-07  Filip Pizlo  <[email protected]>
+
         FTL should support basic closure operations
         https://bugs.webkit.org/show_bug.cgi?id=120987
 

Modified: trunk/Source/_javascript_Core/dfg/DFGLICMPhase.cpp (155280 => 155281)


--- trunk/Source/_javascript_Core/dfg/DFGLICMPhase.cpp	2013-09-08 03:46:22 UTC (rev 155280)
+++ trunk/Source/_javascript_Core/dfg/DFGLICMPhase.cpp	2013-09-08 04:08:01 UTC (rev 155281)
@@ -244,6 +244,8 @@
             if (!subLoop)
                 continue;
             BasicBlock* subPreHeader = m_data[subLoop->index()].preHeader;
+            if (!subPreHeader->cfaDidFinish)
+                continue;
             m_state.initializeTo(subPreHeader);
             m_interpreter.execute(node);
         }

Modified: trunk/Source/_javascript_Core/ftl/FTLAbbreviations.h (155280 => 155281)


--- trunk/Source/_javascript_Core/ftl/FTLAbbreviations.h	2013-09-08 03:46:22 UTC (rev 155280)
+++ trunk/Source/_javascript_Core/ftl/FTLAbbreviations.h	2013-09-08 04:08:01 UTC (rev 155281)
@@ -205,6 +205,7 @@
 static inline LValue buildSExt(LBuilder builder, LValue value, LType type) { return LLVMBuildSExt(builder, value, type, ""); }
 static inline LValue buildZExt(LBuilder builder, LValue value, LType type) { return LLVMBuildZExt(builder, value, type, ""); }
 static inline LValue buildFPToSI(LBuilder builder, LValue value, LType type) { return LLVMBuildFPToSI(builder, value, type, ""); }
+static inline LValue buildFPToUI(LBuilder builder, LValue value, LType type) { return LLVMBuildFPToUI(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, ""); }

Modified: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (155280 => 155281)


--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2013-09-08 03:46:22 UTC (rev 155280)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2013-09-08 04:08:01 UTC (rev 155281)
@@ -155,6 +155,8 @@
         case Array::Contiguous:
             break;
         default:
+            if (isTypedView(node->arrayMode().typedArrayType()))
+                return CanCompileAndOSREnter;
             return CannotCompile;
         }
         break;

Modified: trunk/Source/_javascript_Core/ftl/FTLIntrinsicRepository.h (155280 => 155281)


--- trunk/Source/_javascript_Core/ftl/FTLIntrinsicRepository.h	2013-09-08 03:46:22 UTC (rev 155280)
+++ trunk/Source/_javascript_Core/ftl/FTLIntrinsicRepository.h	2013-09-08 04:08:01 UTC (rev 155281)
@@ -49,7 +49,8 @@
     macro(J_DFGOperation_E, functionType(int64, intPtr)) \
     macro(P_DFGOperation_EC, functionType(intPtr, intPtr, intPtr)) \
     macro(V_DFGOperation_EOZD, functionType(voidType, intPtr, intPtr, int32, doubleType)) \
-    macro(V_DFGOperation_EOZJ, functionType(voidType, intPtr, intPtr, int32, int64))
+    macro(V_DFGOperation_EOZJ, functionType(voidType, intPtr, intPtr, int32, int64)) \
+    macro(Z_DFGOperation_D, functionType(int32, doubleType))
 
 class IntrinsicRepository : public CommonValues {
 public:

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp (155280 => 155281)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp	2013-09-08 03:46:22 UTC (rev 155280)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp	2013-09-08 04:08:01 UTC (rev 155281)
@@ -1423,72 +1423,203 @@
         LValue index = lowInt32(child2);
         LValue storage = lowStorage(child4);
         
-        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("PutByVal continuation"));
-        LBasicBlock outerLastNext = m_out.appendTo(m_out.m_block, continuation);
-            
         switch (m_node->arrayMode().type()) {
         case Array::Int32:
+        case Array::Double:
         case Array::Contiguous: {
-            LValue value = lowJSValue(child3, ManualOperandSpeculation);
+            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("PutByVal continuation"));
+            LBasicBlock outerLastNext = m_out.appendTo(m_out.m_block, continuation);
             
-            if (m_node->arrayMode().type() == Array::Int32)
-                FTL_TYPE_CHECK(jsValueValue(value), child3, SpecInt32, isNotInt32(value));
-            
-            TypedPointer elementPointer = m_out.baseIndex(
-                m_node->arrayMode().type() == Array::Int32 ?
-                m_heaps.indexedInt32Properties : m_heaps.indexedContiguousProperties,
-                storage, m_out.zeroExt(index, m_out.intPtr),
-                m_state.forNode(child2).m_value);
-            
-            if (m_node->op() == PutByValAlias) {
+            switch (m_node->arrayMode().type()) {
+            case Array::Int32:
+            case Array::Contiguous: {
+                LValue value = lowJSValue(child3, ManualOperandSpeculation);
+                
+                if (m_node->arrayMode().type() == Array::Int32)
+                    FTL_TYPE_CHECK(jsValueValue(value), child3, SpecInt32, isNotInt32(value));
+                
+                TypedPointer elementPointer = m_out.baseIndex(
+                    m_node->arrayMode().type() == Array::Int32 ?
+                    m_heaps.indexedInt32Properties : m_heaps.indexedContiguousProperties,
+                    storage, m_out.zeroExt(index, m_out.intPtr),
+                    m_state.forNode(child2).m_value);
+                
+                if (m_node->op() == PutByValAlias) {
+                    m_out.store64(value, elementPointer);
+                    break;
+                }
+                
+                contiguousPutByValOutOfBounds(
+                    codeBlock()->isStrictMode()
+                    ? operationPutByValBeyondArrayBoundsStrict
+                    : operationPutByValBeyondArrayBoundsNonStrict,
+                    base, storage, index, value, continuation);
+                
                 m_out.store64(value, elementPointer);
                 break;
             }
-            
-            contiguousPutByValOutOfBounds(
-                codeBlock()->isStrictMode()
-                    ? operationPutByValBeyondArrayBoundsStrict
-                    : operationPutByValBeyondArrayBoundsNonStrict,
-                base, storage, index, value, continuation);
-            
-            m_out.store64(value, elementPointer);
-            break;
-        }
-            
-        case Array::Double: {
-            LValue value = lowDouble(child3);
-            
-            FTL_TYPE_CHECK(
-                doubleValue(value), child3, SpecRealNumber,
-                m_out.doubleNotEqualOrUnordered(value, value));
-            
-            TypedPointer elementPointer = m_out.baseIndex(
-                m_heaps.indexedDoubleProperties,
-                storage, m_out.zeroExt(index, m_out.intPtr),
-                m_state.forNode(child2).m_value);
-
-            if (m_node->op() == PutByValAlias) {
+                
+            case Array::Double: {
+                LValue value = lowDouble(child3);
+                
+                FTL_TYPE_CHECK(
+                    doubleValue(value), child3, SpecRealNumber,
+                    m_out.doubleNotEqualOrUnordered(value, value));
+                
+                TypedPointer elementPointer = m_out.baseIndex(
+                    m_heaps.indexedDoubleProperties,
+                    storage, m_out.zeroExt(index, m_out.intPtr),
+                    m_state.forNode(child2).m_value);
+                
+                if (m_node->op() == PutByValAlias) {
+                    m_out.storeDouble(value, elementPointer);
+                    break;
+                }
+                
+                contiguousPutByValOutOfBounds(
+                    codeBlock()->isStrictMode()
+                    ? operationPutDoubleByValBeyondArrayBoundsStrict
+                    : operationPutDoubleByValBeyondArrayBoundsNonStrict,
+                    base, storage, index, value, continuation);
+                
                 m_out.storeDouble(value, elementPointer);
                 break;
             }
+                
+            default:
+                RELEASE_ASSERT_NOT_REACHED();
+            }
+
+            m_out.jump(continuation);
+            m_out.appendTo(continuation, outerLastNext);
+            return;
+        }
             
-            contiguousPutByValOutOfBounds(
-                codeBlock()->isStrictMode()
-                    ? operationPutDoubleByValBeyondArrayBoundsStrict
-                    : operationPutDoubleByValBeyondArrayBoundsNonStrict,
-                base, storage, index, value, continuation);
+        default:
+            TypedArrayType type = m_node->arrayMode().typedArrayType();
             
-            m_out.storeDouble(value, elementPointer);
-            break;
-        }
+            if (isTypedView(type)) {
+                if (m_node->op() == PutByVal) {
+                    speculate(
+                        OutOfBounds, noValue(), 0,
+                        m_out.aboveOrEqual(
+                            index, m_out.load32(base, m_heaps.JSArrayBufferView_length)));
+                }
+                
+                TypedPointer pointer = TypedPointer(
+                    m_heaps.typedArrayProperties,
+                    m_out.add(
+                        storage,
+                        m_out.shl(
+                            m_out.zeroExt(index, m_out.intPtr),
+                            m_out.constIntPtr(logElementSize(type)))));
+                
+                if (isInt(type)) {
+                    LValue intValue;
+                    switch (child3.useKind()) {
+                    case Int32Use: {
+                        intValue = lowInt32(child3);
+                        if (isClamped(type)) {
+                            ASSERT(elementSize(type) == 1);
+                            
+                            LBasicBlock atLeastZero = FTL_NEW_BLOCK(m_out, ("PutByVal int clamp atLeastZero"));
+                            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("PutByVal int clamp continuation"));
+                            
+                            Vector<ValueFromBlock, 2> intValues;
+                            intValues.append(m_out.anchor(m_out.int32Zero));
+                            m_out.branch(
+                                m_out.lessThan(intValue, m_out.int32Zero),
+                                continuation, atLeastZero);
+                            
+                            LBasicBlock lastNext = m_out.appendTo(atLeastZero, continuation);
+                            
+                            intValues.append(m_out.anchor(m_out.select(
+                                m_out.greaterThan(intValue, m_out.constInt32(255)),
+                                m_out.constInt32(255),
+                                intValue)));
+                            m_out.jump(continuation);
+                            
+                            m_out.appendTo(continuation, lastNext);
+                            intValue = m_out.phi(m_out.int32, intValues);
+                        }
+                        break;
+                    }
+                        
+                    case NumberUse: {
+                        LValue doubleValue = lowDouble(child3);
+                        
+                        if (isClamped(type)) {
+                            ASSERT(elementSize(type) == 1);
+                            
+                            LBasicBlock atLeastZero = FTL_NEW_BLOCK(m_out, ("PutByVal double clamp atLeastZero"));
+                            LBasicBlock withinRange = FTL_NEW_BLOCK(m_out, ("PutByVal double clamp withinRange"));
+                            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("PutByVal double clamp continuation"));
+                            
+                            Vector<ValueFromBlock, 3> intValues;
+                            intValues.append(m_out.anchor(m_out.int32Zero));
+                            m_out.branch(
+                                m_out.doubleLessThanOrUnordered(doubleValue, m_out.doubleZero),
+                                continuation, atLeastZero);
+                            
+                            LBasicBlock lastNext = m_out.appendTo(atLeastZero, withinRange);
+                            intValues.append(m_out.anchor(m_out.constInt32(255)));
+                            m_out.branch(
+                                m_out.doubleGreaterThan(doubleValue, m_out.constDouble(255)),
+                                continuation, withinRange);
+                            
+                            m_out.appendTo(withinRange, continuation);
+                            intValues.append(m_out.anchor(m_out.fpToInt32(doubleValue)));
+                            m_out.jump(continuation);
+                            
+                            m_out.appendTo(continuation, lastNext);
+                            intValue = m_out.phi(m_out.int32, intValues);
+                        } else if (isSigned(type))
+                            intValue = doubleToInt32(doubleValue);
+                        else
+                            intValue = doubleToUInt32(doubleValue);
+                        break;
+                    }
+                        
+                    default:
+                        RELEASE_ASSERT_NOT_REACHED();
+                    }
+                    
+                    switch (elementSize(type)) {
+                    case 1:
+                        m_out.store8(m_out.intCast(intValue, m_out.int8), pointer);
+                        break;
+                    case 2:
+                        m_out.store16(m_out.intCast(intValue, m_out.int16), pointer);
+                        break;
+                    case 4:
+                        m_out.store32(intValue, pointer);
+                        break;
+                    default:
+                        RELEASE_ASSERT_NOT_REACHED();
+                    }
+                    
+                    return;
+                }
+                
+                ASSERT(isFloat(type));
+                
+                LValue value = lowDouble(child3);
+                switch (type) {
+                case TypeFloat32:
+                    m_out.storeFloat(m_out.fpCast(value, m_out.floatType), pointer);
+                    break;
+                case TypeFloat64:
+                    m_out.storeDouble(value, pointer);
+                    break;
+                default:
+                    RELEASE_ASSERT_NOT_REACHED();
+                }
+                return;
+            }
             
-        default:
             RELEASE_ASSERT_NOT_REACHED();
             break;
         }
-
-        m_out.jump(continuation);
-        m_out.appendTo(continuation, outerLastNext);
     }
     
     void compileGetByOffset()
@@ -2093,6 +2224,55 @@
         m_out.switchInstruction(switchValue, cases, lowBlock(data->fallThrough));
     }
     
+    LValue doubleToInt32(LValue doubleValue, double low, double high, bool isSigned = true)
+    {
+        // FIXME: Optimize double-to-int conversions.
+        // <rdar://problem/14938465>
+        
+        LBasicBlock greatEnough = FTL_NEW_BLOCK(m_out, ("doubleToInt32 greatEnough"));
+        LBasicBlock withinRange = FTL_NEW_BLOCK(m_out, ("doubleToInt32 withinRange"));
+        LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("doubleToInt32 slowPath"));
+        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("doubleToInt32 continuation"));
+        
+        Vector<ValueFromBlock, 2> results;
+        
+        m_out.branch(
+            m_out.greaterThanOrEqual(doubleValue, m_out.constDouble(low)),
+            greatEnough, slowPath);
+        
+        LBasicBlock lastNext = m_out.appendTo(greatEnough, withinRange);
+        m_out.branch(
+            m_out.lessThanOrEqual(doubleValue, m_out.constDouble(high)),
+            withinRange, slowPath);
+        
+        m_out.appendTo(withinRange, slowPath);
+        LValue fastResult;
+        if (isSigned)
+            fastResult = m_out.fpToInt32(doubleValue);
+        else
+            fastResult = m_out.fpToUInt32(doubleValue);
+        results.append(m_out.anchor(fastResult));
+        m_out.jump(continuation);
+        
+        m_out.appendTo(slowPath, continuation);
+        results.append(m_out.anchor(m_out.call(m_out.operation(toInt32), doubleValue)));
+        m_out.jump(continuation);
+        
+        m_out.appendTo(continuation, lastNext);
+        return m_out.phi(m_out.int32, results);
+    }
+    
+    LValue doubleToInt32(LValue doubleValue)
+    {
+        double limit = pow(2, 31) - 1;
+        return doubleToInt32(doubleValue, -limit, limit);
+    }
+    
+    LValue doubleToUInt32(LValue doubleValue)
+    {
+        return doubleToInt32(doubleValue, 0, pow(2, 32) - 1, false);
+    }
+    
     void speculateBackward(
         ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition)
     {

Modified: trunk/Source/_javascript_Core/ftl/FTLOutput.h (155280 => 155281)


--- trunk/Source/_javascript_Core/ftl/FTLOutput.h	2013-09-08 03:46:22 UTC (rev 155280)
+++ trunk/Source/_javascript_Core/ftl/FTLOutput.h	2013-09-08 04:08:01 UTC (rev 155281)
@@ -174,7 +174,9 @@
     LValue signExt(LValue value, LType type) { return buildSExt(m_builder, value, type); }
     LValue zeroExt(LValue value, LType type) { return buildZExt(m_builder, value, type); }
     LValue fpToInt(LValue value, LType type) { return buildFPToSI(m_builder, value, type); }
+    LValue fpToUInt(LValue value, LType type) { return buildFPToUI(m_builder, value, type); }
     LValue fpToInt32(LValue value) { return fpToInt(value, int32); }
+    LValue fpToUInt32(LValue value) { return fpToUInt(value, int32); }
     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); }
@@ -207,9 +209,12 @@
     LValue loadPtr(TypedPointer pointer) { return load(pointer, refPtr); }
     LValue loadFloat(TypedPointer pointer) { return load(pointer, refFloat); }
     LValue loadDouble(TypedPointer pointer) { return load(pointer, refDouble); }
+    void store8(LValue value, TypedPointer pointer) { store(value, pointer, ref8); }
+    void store16(LValue value, TypedPointer pointer) { store(value, pointer, ref16); }
     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 storeFloat(LValue value, TypedPointer pointer) { store(value, pointer, refFloat); }
     void storeDouble(LValue value, TypedPointer pointer) { store(value, pointer, refDouble); }
 
     LValue addPtr(LValue value, ptrdiff_t immediate = 0)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to