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)