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); }