Title: [155260] trunk/Source/_javascript_Core
Revision
155260
Author
[email protected]
Date
2013-09-07 14:13:55 -0700 (Sat, 07 Sep 2013)

Log Message

FTL should support typed array GetByVal and related ops
https://bugs.webkit.org/show_bug.cgi?id=120965

Reviewed by Oliver Hunt.
        
This adds support for typed array instantiations of the following DFG IR ops:
        
- GetByVal
        
- GetIndexedPropertyStorage
        
- CheckArray
        
- GetArrayLength
        
This also adds CheckArray for Int32/Double/Contiguous arrays.

* dfg/DFGArrayMode.cpp:
(JSC::DFG::toIndexingShape):
* dfg/DFGArrayMode.h:
(JSC::DFG::ArrayMode::shapeMask):
* ftl/FTLAbbreviations.h:
(JSC::FTL::floatType):
(JSC::FTL::buildSExt):
(JSC::FTL::buildFPCast):
* ftl/FTLAbstractHeapRepository.h:
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLCommonValues.cpp:
(JSC::FTL::CommonValues::CommonValues):
* ftl/FTLCommonValues.h:
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileNode):
(JSC::FTL::LowerDFGToLLVM::compileGetIndexedPropertyStorage):
(JSC::FTL::LowerDFGToLLVM::compileCheckArray):
(JSC::FTL::LowerDFGToLLVM::compileGetArrayLength):
(JSC::FTL::LowerDFGToLLVM::compileGetByVal):
(JSC::FTL::LowerDFGToLLVM::isArrayType):
(JSC::FTL::LowerDFGToLLVM::hasClassInfo):
* ftl/FTLOutput.h:
(JSC::FTL::Output::constIntPtr):
(JSC::FTL::Output::signExt):
(JSC::FTL::Output::fpCast):
(JSC::FTL::Output::loadFloat):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (155259 => 155260)


--- trunk/Source/_javascript_Core/ChangeLog	2013-09-07 19:46:57 UTC (rev 155259)
+++ trunk/Source/_javascript_Core/ChangeLog	2013-09-07 21:13:55 UTC (rev 155260)
@@ -1,3 +1,50 @@
+2013-09-07  Filip Pizlo  <[email protected]>
+
+        FTL should support typed array GetByVal and related ops
+        https://bugs.webkit.org/show_bug.cgi?id=120965
+
+        Reviewed by Oliver Hunt.
+        
+        This adds support for typed array instantiations of the following DFG IR ops:
+        
+        - GetByVal
+        
+        - GetIndexedPropertyStorage
+        
+        - CheckArray
+        
+        - GetArrayLength
+        
+        This also adds CheckArray for Int32/Double/Contiguous arrays.
+
+        * dfg/DFGArrayMode.cpp:
+        (JSC::DFG::toIndexingShape):
+        * dfg/DFGArrayMode.h:
+        (JSC::DFG::ArrayMode::shapeMask):
+        * ftl/FTLAbbreviations.h:
+        (JSC::FTL::floatType):
+        (JSC::FTL::buildSExt):
+        (JSC::FTL::buildFPCast):
+        * ftl/FTLAbstractHeapRepository.h:
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLCommonValues.cpp:
+        (JSC::FTL::CommonValues::CommonValues):
+        * ftl/FTLCommonValues.h:
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::LowerDFGToLLVM::compileNode):
+        (JSC::FTL::LowerDFGToLLVM::compileGetIndexedPropertyStorage):
+        (JSC::FTL::LowerDFGToLLVM::compileCheckArray):
+        (JSC::FTL::LowerDFGToLLVM::compileGetArrayLength):
+        (JSC::FTL::LowerDFGToLLVM::compileGetByVal):
+        (JSC::FTL::LowerDFGToLLVM::isArrayType):
+        (JSC::FTL::LowerDFGToLLVM::hasClassInfo):
+        * ftl/FTLOutput.h:
+        (JSC::FTL::Output::constIntPtr):
+        (JSC::FTL::Output::signExt):
+        (JSC::FTL::Output::fpCast):
+        (JSC::FTL::Output::loadFloat):
+
 2013-09-07  Anders Carlsson  <[email protected]>
 
         VectorMover should use std::move

Modified: trunk/Source/_javascript_Core/dfg/DFGArrayMode.cpp (155259 => 155260)


--- trunk/Source/_javascript_Core/dfg/DFGArrayMode.cpp	2013-09-07 19:46:57 UTC (rev 155259)
+++ trunk/Source/_javascript_Core/dfg/DFGArrayMode.cpp	2013-09-07 21:13:55 UTC (rev 155260)
@@ -458,6 +458,24 @@
     }
 }
 
+IndexingType toIndexingShape(Array::Type type)
+{
+    switch (type) {
+    case Array::Int32:
+        return Int32Shape;
+    case Array::Double:
+        return DoubleShape;
+    case Array::Contiguous:
+        return ContiguousShape;
+    case Array::ArrayStorage:
+        return ArrayStorageShape;
+    case Array::SlowPutArrayStorage:
+        return SlowPutArrayStorageShape;
+    default:
+        return NoIndexingShape;
+    }
+}
+
 TypedArrayType toTypedArrayType(Array::Type type)
 {
     switch (type) {

Modified: trunk/Source/_javascript_Core/dfg/DFGArrayMode.h (155259 => 155260)


--- trunk/Source/_javascript_Core/dfg/DFGArrayMode.h	2013-09-07 19:46:57 UTC (rev 155259)
+++ trunk/Source/_javascript_Core/dfg/DFGArrayMode.h	2013-09-07 21:13:55 UTC (rev 155260)
@@ -104,6 +104,8 @@
 const char* arraySpeculationToString(Array::Speculation);
 const char* arrayConversionToString(Array::Conversion);
 
+IndexingType toIndexingShape(Array::Type);
+
 TypedArrayType toTypedArrayType(Array::Type);
 Array::Type toArrayType(TypedArrayType);
 
@@ -383,6 +385,11 @@
         return type() == Array::String;
     }
     
+    IndexingType shapeMask() const
+    {
+        return toIndexingShape(type());
+    }
+    
     TypedArrayType typedArrayType() const
     {
         return toTypedArrayType(type());

Modified: trunk/Source/_javascript_Core/ftl/FTLAbbreviations.h (155259 => 155260)


--- trunk/Source/_javascript_Core/ftl/FTLAbbreviations.h	2013-09-07 19:46:57 UTC (rev 155259)
+++ trunk/Source/_javascript_Core/ftl/FTLAbbreviations.h	2013-09-07 21:13:55 UTC (rev 155260)
@@ -53,6 +53,7 @@
 static inline LType int32Type(LContext context) { return LLVMInt32TypeInContext(context); }
 static inline LType int64Type(LContext context) { return LLVMInt64TypeInContext(context); }
 static inline LType intPtrType(LContext context) { return LLVMInt64TypeInContext(context); }
+static inline LType floatType(LContext context) { return LLVMFloatTypeInContext(context); }
 static inline LType doubleType(LContext context) { return LLVMDoubleTypeInContext(context); }
 
 static inline LType pointerType(LType type) { return LLVMPointerType(type, 0); }
@@ -201,11 +202,13 @@
 static inline LValue buildNot(LBuilder builder, LValue value) { return LLVMBuildNot(builder, value, ""); }
 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 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 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 buildFPCast(LBuilder builder, LValue value, LType type) { return LLVMBuildFPCast(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, ""); }

Modified: trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h (155259 => 155260)


--- trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h	2013-09-07 19:46:57 UTC (rev 155259)
+++ trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h	2013-09-07 21:13:55 UTC (rev 155260)
@@ -41,13 +41,18 @@
 #define FOR_EACH_ABSTRACT_FIELD(macro) \
     macro(Butterfly_publicLength, Butterfly::offsetOfPublicLength()) \
     macro(Butterfly_vectorLength, Butterfly::offsetOfVectorLength()) \
+    macro(JSArrayBufferView_length, JSArrayBufferView::offsetOfLength()) \
+    macro(JSArrayBufferView_mode, JSArrayBufferView::offsetOfMode()) \
+    macro(JSArrayBufferView_vector, JSArrayBufferView::offsetOfVector()) \
     macro(JSCell_structure, JSCell::structureOffset()) \
     macro(JSObject_butterfly, JSObject::butterflyOffset()) \
     macro(JSString_length, JSString::offsetOfLength()) \
     macro(JSString_value, JSString::offsetOfValue()) \
     macro(StringImpl_data, StringImpl::dataOffset()) \
     macro(StringImpl_hashAndFlags, StringImpl::flagsOffset()) \
+    macro(Structure_classInfo, Structure::classInfoOffset()) \
     macro(Structure_globalObject, Structure::globalObjectOffset()) \
+    macro(Structure_indexingType, Structure::indexingTypeOffset()) \
     macro(Structure_typeInfoFlags, Structure::typeInfoFlagsOffset())
 
 #define FOR_EACH_INDEXED_ABSTRACT_HEAP(macro) \

Modified: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (155259 => 155260)


--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2013-09-07 19:46:57 UTC (rev 155259)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2013-09-07 21:13:55 UTC (rev 155260)
@@ -91,6 +91,22 @@
     case GlobalVarWatchpoint:
         // These are OK.
         break;
+    case GetIndexedPropertyStorage:
+        if (isTypedView(node->arrayMode().typedArrayType()))
+            break;
+        return CannotCompile;
+    case CheckArray:
+        switch (node->arrayMode().type()) {
+        case Array::Int32:
+        case Array::Double:
+        case Array::Contiguous:
+            break;
+        default:
+            if (isTypedView(node->arrayMode().typedArrayType()))
+                break;
+            return CannotCompile;
+        }
+        break;
     case GetArrayLength:
         switch (node->arrayMode().type()) {
         case Array::Int32:
@@ -98,6 +114,8 @@
         case Array::Contiguous:
             break;
         default:
+            if (isTypedView(node->arrayMode().typedArrayType()))
+                break;
             return CannotCompile;
         }
         break;
@@ -110,6 +128,8 @@
         case Array::Contiguous:
             break;
         default:
+            if (isTypedView(node->arrayMode().typedArrayType()))
+                return CanCompileAndOSREnter;
             return CannotCompile;
         }
         switch (node->arrayMode().speculation()) {

Modified: trunk/Source/_javascript_Core/ftl/FTLCommonValues.cpp (155259 => 155260)


--- trunk/Source/_javascript_Core/ftl/FTLCommonValues.cpp	2013-09-07 19:46:57 UTC (rev 155259)
+++ trunk/Source/_javascript_Core/ftl/FTLCommonValues.cpp	2013-09-07 21:13:55 UTC (rev 155260)
@@ -38,12 +38,14 @@
     , int32(int32Type(context))
     , int64(int64Type(context))
     , intPtr(intPtrType(context))
+    , floatType(FTL::floatType(context))
     , doubleType(FTL::doubleType(context))
     , ref8(pointerType(int8))
     , ref16(pointerType(int16))
     , ref32(pointerType(int32))
     , ref64(pointerType(int64))
     , refPtr(pointerType(intPtr))
+    , refFloat(pointerType(floatType))
     , refDouble(pointerType(doubleType))
     , booleanTrue(constInt(boolean, true, ZeroExtend))
     , booleanFalse(constInt(boolean, false, ZeroExtend))

Modified: trunk/Source/_javascript_Core/ftl/FTLCommonValues.h (155259 => 155260)


--- trunk/Source/_javascript_Core/ftl/FTLCommonValues.h	2013-09-07 19:46:57 UTC (rev 155259)
+++ trunk/Source/_javascript_Core/ftl/FTLCommonValues.h	2013-09-07 21:13:55 UTC (rev 155260)
@@ -50,12 +50,14 @@
     const LType int32;
     const LType int64;
     const LType intPtr;
+    const LType floatType;
     const LType doubleType;
     const LType ref8;
     const LType ref16;
     const LType ref32;
     const LType ref64;
     const LType refPtr;
+    const LType refFloat;
     const LType refDouble;
     const LValue booleanTrue;
     const LValue booleanFalse;

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp (155259 => 155260)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp	2013-09-07 19:46:57 UTC (rev 155259)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp	2013-09-07 21:13:55 UTC (rev 155260)
@@ -341,6 +341,12 @@
         case GetButterfly:
             compileGetButterfly();
             break;
+        case GetIndexedPropertyStorage:
+            compileGetIndexedPropertyStorage();
+            break;
+        case CheckArray:
+            compileCheckArray();
+            break;
         case GetArrayLength:
             compileGetArrayLength();
             break;
@@ -1203,6 +1209,24 @@
         setStorage(m_out.loadPtr(lowCell(m_node->child1()), m_heaps.JSObject_butterfly));
     }
     
+    void compileGetIndexedPropertyStorage()
+    {
+        setStorage(m_out.loadPtr(lowCell(m_node->child1()), m_heaps.JSArrayBufferView_vector));
+    }
+    
+    void compileCheckArray()
+    {
+        Edge edge = m_node->child1();
+        LValue cell = lowCell(edge);
+        
+        if (m_node->arrayMode().alreadyChecked(m_graph, m_node, m_state.forNode(edge)))
+            return;
+        
+        speculate(
+            BadIndexingType, jsValueValue(cell), 0,
+            m_out.bitNot(isArrayType(cell, m_node->arrayMode())));
+    }
+    
     void compileGetArrayLength()
     {
         switch (m_node->arrayMode().type()) {
@@ -1210,12 +1234,18 @@
         case Array::Double:
         case Array::Contiguous: {
             setInt32(m_out.load32(lowStorage(m_node->child2()), m_heaps.Butterfly_publicLength));
-            break;
+            return;
         }
             
         default:
+            if (isTypedView(m_node->arrayMode().typedArrayType())) {
+                setInt32(
+                    m_out.load32(lowCell(m_node->child1()), m_heaps.JSArrayBufferView_length));
+                return;
+            }
+            
             RELEASE_ASSERT_NOT_REACHED();
-            break;
+            return;
         }
     }
     
@@ -1281,10 +1311,90 @@
             return;
         }
             
-        default:
+        default: {
+            TypedArrayType type = m_node->arrayMode().typedArrayType();
+            
+            if (isTypedView(type)) {
+                LValue array = lowCell(m_node->child1());
+                
+                speculate(
+                    OutOfBounds, noValue(), 0,
+                    m_out.aboveOrEqual(
+                        index, m_out.load32(array, 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 result;
+                    switch (elementSize(type)) {
+                    case 1:
+                        result = m_out.load8(pointer);
+                        break;
+                    case 2:
+                        result = m_out.load16(pointer);
+                        break;
+                    case 4:
+                        result = m_out.load32(pointer);
+                        break;
+                    default:
+                        RELEASE_ASSERT_NOT_REACHED();
+                    }
+                    
+                    if (elementSize(type) < 4) {
+                        if (isSigned(type))
+                            result = m_out.signExt(result, m_out.int32);
+                        else
+                            result = m_out.zeroExt(result, m_out.int32);
+                        setInt32(result);
+                        return;
+                    }
+                    
+                    if (isSigned(type)) {
+                        setInt32(result);
+                        return;
+                    }
+                    
+                    if (m_node->shouldSpeculateInteger()) {
+                        speculateForward(
+                            Overflow, noValue(), 0, m_out.lessThan(result, m_out.int32Zero),
+                            uInt32Value(result));
+                        setInt32(result);
+                        return;
+                    }
+                    
+                    setDouble(m_out.unsignedToFP(result, m_out.doubleType));
+                    return;
+                }
+            
+                ASSERT(isFloat(type));
+                
+                LValue result;
+                switch (type) {
+                case TypeFloat32:
+                    result = m_out.fpCast(m_out.loadFloat(pointer), m_out.doubleType);
+                    break;
+                case TypeFloat64:
+                    result = m_out.loadDouble(pointer);
+                    break;
+                default:
+                    RELEASE_ASSERT_NOT_REACHED();
+                }
+                
+                result = m_out.select(
+                    m_out.doubleEqual(result, result), result, m_out.constDouble(QNaN));
+                setDouble(result);
+                return;
+            }
+            
             RELEASE_ASSERT_NOT_REACHED();
             return;
-        }
+        } }
     }
     
     void compilePutByVal()
@@ -2319,6 +2429,47 @@
         return isString(cell);
     }
     
+    LValue isArrayType(LValue cell, ArrayMode arrayMode)
+    {
+        switch (arrayMode.type()) {
+        case Array::Int32:
+        case Array::Double:
+        case Array::Contiguous: {
+            LValue indexingType = m_out.load8(
+                m_out.loadPtr(cell, m_heaps.JSCell_structure),
+                m_heaps.Structure_indexingType);
+            
+            switch (arrayMode.arrayClass()) {
+            case Array::OriginalArray:
+                RELEASE_ASSERT_NOT_REACHED();
+                return 0;
+                
+            case Array::Array:
+                return m_out.equal(
+                    m_out.bitAnd(indexingType, m_out.constInt8(IsArray | IndexingShapeMask)),
+                    m_out.constInt8(IsArray | arrayMode.shapeMask()));
+                
+            default:
+                return m_out.equal(
+                    m_out.bitAnd(indexingType, m_out.constInt8(IndexingShapeMask)),
+                    m_out.constInt8(arrayMode.shapeMask()));
+            }
+        }
+            
+        default:
+            return hasClassInfo(cell, classInfoForType(arrayMode.typedArrayType()));
+        }
+    }
+    
+    LValue hasClassInfo(LValue cell, const ClassInfo* classInfo)
+    {
+        return m_out.equal(
+            m_out.loadPtr(
+                m_out.loadPtr(cell, m_heaps.JSCell_structure),
+                m_heaps.Structure_classInfo),
+            m_out.constIntPtr(classInfo));
+    }
+    
     void speculateObject(Edge edge, LValue cell)
     {
         FTL_TYPE_CHECK(jsValueValue(cell), edge, SpecObject, isNotObject(cell));

Modified: trunk/Source/_javascript_Core/ftl/FTLOutput.h (155259 => 155260)


--- trunk/Source/_javascript_Core/ftl/FTLOutput.h	2013-09-07 19:46:57 UTC (rev 155259)
+++ trunk/Source/_javascript_Core/ftl/FTLOutput.h	2013-09-07 21:13:55 UTC (rev 155260)
@@ -108,7 +108,9 @@
     LValue constInt8(int8_t value) { return constInt(int8, value); }
     LValue constInt32(int32_t value) { return constInt(int32, value); }
     template<typename T>
-    LValue constIntPtr(T value) { return constInt(intPtr, bitwise_cast<intptr_t>(value)); }
+    LValue constIntPtr(T* value) { return constInt(intPtr, bitwise_cast<intptr_t>(value)); }
+    template<typename T>
+    LValue constIntPtr(T value) { return constInt(intPtr, static_cast<intptr_t>(value)); }
     LValue constInt64(int64_t value) { return constInt(int64, value); }
     LValue constDouble(double value) { return constReal(doubleType, value); }
     
@@ -169,6 +171,7 @@
         return call(doubleAbsIntrinsic(), value);
     }
     
+    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 fpToInt32(LValue value) { return fpToInt(value, int32); }
@@ -178,6 +181,7 @@
     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 fpCast(LValue value, LType type) { return buildFPCast(m_builder, value, type); }
     LValue intToPtr(LValue value, LType type) { return buildIntToPtr(m_builder, value, type); }
     LValue bitCast(LValue value, LType type) { return buildBitCast(m_builder, value, type); }
     
@@ -201,6 +205,7 @@
     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 loadFloat(TypedPointer pointer) { return load(pointer, refFloat); }
     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); }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to