Diff
Modified: branches/dfgFourthTier/Source/_javascript_Core/ChangeLog (149889 => 149890)
--- branches/dfgFourthTier/Source/_javascript_Core/ChangeLog 2013-05-10 17:48:09 UTC (rev 149889)
+++ branches/dfgFourthTier/Source/_javascript_Core/ChangeLog 2013-05-10 18:12:36 UTC (rev 149890)
@@ -1,3 +1,43 @@
+2013-05-10 Filip Pizlo <[email protected]>
+
+ fourthTier: FTL CompareEq ObjectUse should handle masquerading
+ https://bugs.webkit.org/show_bug.cgi?id=115920
+
+ Reviewed by Mark Hahnenberg.
+
+ We don't yet support watchpoints, but this does all the wiring right up to the
+ part where we would have emitted watchpoints. I've also written this in a way that
+ makes it easy to use the case where you would have anyway speculated non-masquerading
+ even if the watchpoint was invalidated.
+
+ This is inherently racy, of course: but the only race here is that you might first
+ set the watchpoint, and then the watchpoint is invalidated, and then you compile rest
+ of the code in a way that doesn't need the watchpoint. That's fine, since the FTL
+ will remember that it had set the watchpoint and then cancel the compilation.
+
+ * ftl/FTLAbbreviations.h:
+ (JSC::FTL::int8Type):
+ * ftl/FTLAbstractHeapRepository.h:
+ (FTL):
+ * ftl/FTLCommonValues.cpp:
+ (JSC::FTL::CommonValues::CommonValues):
+ * ftl/FTLCommonValues.h:
+ (CommonValues):
+ * ftl/FTLLowerDFGToLLVM.cpp:
+ (JSC::FTL::LowerDFGToLLVM::compileCompareEq):
+ (JSC::FTL::LowerDFGToLLVM::lowNonNullObject):
+ (LowerDFGToLLVM):
+ (JSC::FTL::LowerDFGToLLVM::speculateNonNullObject):
+ (JSC::FTL::LowerDFGToLLVM::masqueradesAsUndefinedWatchpointIsStillValid):
+ (JSC::FTL::LowerDFGToLLVM::masqueradesAsUndefinedWatchpointIfIsStillValid):
+ * ftl/FTLOutput.h:
+ (JSC::FTL::Output::constInt8):
+ (JSC::FTL::Output::load8):
+ (JSC::FTL::Output::isZero8):
+ (JSC::FTL::Output::notZero8):
+ (JSC::FTL::Output::testIsZero8):
+ (JSC::FTL::Output::testNonZero8):
+
2013-05-09 Filip Pizlo <[email protected]>
fourthTier: DFG shouldn't allocate in the GC heap
Modified: branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLAbbreviations.h (149889 => 149890)
--- branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLAbbreviations.h 2013-05-10 17:48:09 UTC (rev 149889)
+++ branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLAbbreviations.h 2013-05-10 18:12:36 UTC (rev 149890)
@@ -55,6 +55,7 @@
static inline LType voidType() { return LLVMVoidType(); }
static inline LType int1Type() { return LLVMInt1Type(); }
+static inline LType int8Type() { return LLVMInt8Type(); }
static inline LType int32Type() { return LLVMInt32Type(); }
static inline LType int64Type() { return LLVMInt64Type(); }
static inline LType intPtrType() { return LLVMInt64Type(); }
Modified: branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h (149889 => 149890)
--- branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h 2013-05-10 17:48:09 UTC (rev 149889)
+++ branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h 2013-05-10 18:12:36 UTC (rev 149890)
@@ -41,7 +41,8 @@
#define FOR_EACH_ABSTRACT_FIELD(macro) \
macro(JSCell_structure, JSCell::structureOffset()) \
macro(JSObject_butterfly, JSObject::butterflyOffset()) \
- macro(Butterfly_publicLength, Butterfly::offsetOfPublicLength())
+ macro(Butterfly_publicLength, Butterfly::offsetOfPublicLength()) \
+ macro(Structure_typeInfoFlags, Structure::typeInfoFlagsOffset())
#define FOR_EACH_INDEXED_ABSTRACT_HEAP(macro) \
macro(variables, sizeof(Register)) \
Modified: branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLCommonValues.cpp (149889 => 149890)
--- branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLCommonValues.cpp 2013-05-10 17:48:09 UTC (rev 149889)
+++ branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLCommonValues.cpp 2013-05-10 18:12:36 UTC (rev 149890)
@@ -33,16 +33,19 @@
CommonValues::CommonValues()
: voidType(FTL::voidType())
, boolean(int1Type())
+ , int8(int8Type())
, int32(int32Type())
, int64(int64Type())
, intPtr(intPtrType())
, doubleType(FTL::doubleType())
+ , ref8(pointerType(int8))
, ref32(pointerType(int32))
, ref64(pointerType(int64))
, refPtr(pointerType(intPtr))
, refDouble(pointerType(doubleType))
, booleanTrue(constInt(boolean, true, ZeroExtend))
, booleanFalse(constInt(boolean, false, ZeroExtend))
+ , int8Zero(constInt(int8, 0, SignExtend))
, int32Zero(constInt(int32, 0, SignExtend))
, int64Zero(constInt(int64, 0, SignExtend))
, intPtrZero(constInt(intPtr, 0, SignExtend))
Modified: branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLCommonValues.h (149889 => 149890)
--- branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLCommonValues.h 2013-05-10 17:48:09 UTC (rev 149889)
+++ branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLCommonValues.h 2013-05-10 18:12:36 UTC (rev 149890)
@@ -45,16 +45,19 @@
const LType voidType;
const LType boolean;
+ const LType int8;
const LType int32;
const LType int64;
const LType intPtr;
const LType doubleType;
+ const LType ref8;
const LType ref32;
const LType ref64;
const LType refPtr;
const LType refDouble;
const LValue booleanTrue;
const LValue booleanFalse;
+ const LValue int8Zero;
const LValue int32Zero;
const LValue int64Zero;
const LValue intPtrZero;
Modified: branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp (149889 => 149890)
--- branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2013-05-10 17:48:09 UTC (rev 149889)
+++ branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2013-05-10 18:12:36 UTC (rev 149890)
@@ -939,9 +939,12 @@
}
if (m_node->isBinaryUseKind(ObjectUse)) {
+ masqueradesAsUndefinedWatchpointIfIsStillValid();
m_booleanValues.add(
m_node,
- m_out.equal(lowObject(m_node->child1()), lowObject(m_node->child2())));
+ m_out.equal(
+ lowNonNullObject(m_node->child1()),
+ lowNonNullObject(m_node->child2())));
return;
}
@@ -1092,6 +1095,15 @@
return result;
}
+ LValue lowNonNullObject(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
+ {
+ ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == ObjectUse);
+
+ LValue result = lowCell(edge, mode);
+ speculateNonNullObject(edge, result);
+ return result;
+ }
+
LValue lowBoolean(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
{
ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == BooleanUse);
@@ -1312,6 +1324,22 @@
speculateObject(edge, lowCell(edge));
}
+ void speculateNonNullObject(Edge edge, LValue cell)
+ {
+ LValue structure = m_out.loadPtr(cell, m_heaps.JSCell_structure);
+ FTL_TYPE_CHECK(
+ jsValueValue(cell), edge, SpecObject,
+ m_out.equal(structure, m_out.constIntPtr(vm().stringStructure.get())));
+ if (masqueradesAsUndefinedWatchpointIsStillValid())
+ return;
+
+ speculate(
+ BadType, jsValueValue(cell), edge.node(),
+ m_out.testNonZero8(
+ m_out.load8(structure, m_heaps.Structure_typeInfoFlags),
+ m_out.constInt8(MasqueradesAsUndefined)));
+ }
+
void speculateNumber(Edge edge)
{
// Do an early return here because lowDouble() can create a lot of control flow.
@@ -1332,7 +1360,21 @@
doubleValue(value), edge, SpecRealNumber,
m_out.doubleNotEqualOrUnordered(value, value));
}
+
+ bool masqueradesAsUndefinedWatchpointIsStillValid()
+ {
+ return m_graph.masqueradesAsUndefinedWatchpointIsStillValid(m_node->codeOrigin);
+ }
+ void masqueradesAsUndefinedWatchpointIfIsStillValid()
+ {
+ if (!masqueradesAsUndefinedWatchpointIsStillValid())
+ return;
+
+ // FIXME: Implement masquerades-as-undefined watchpoints.
+ // https://bugs.webkit.org/show_bug.cgi?id=113647
+ }
+
bool isLive(Node* node)
{
HashMap<Node*, unsigned>::iterator iter = m_timeToLive.find(node);
Modified: branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLOutput.h (149889 => 149890)
--- branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLOutput.h 2013-05-10 17:48:09 UTC (rev 149889)
+++ branches/dfgFourthTier/Source/_javascript_Core/ftl/FTLOutput.h 2013-05-10 18:12:36 UTC (rev 149890)
@@ -105,6 +105,7 @@
LValue param(unsigned index) { return getParam(m_function, index); }
LValue constBool(bool value) { return constInt(boolean, value, ZeroExtend); }
+ LValue constInt8(int8_t value) { return constInt(int8, value, SignExtend); }
LValue constInt32(int32_t value) { return constInt(int32, value, SignExtend); }
template<typename T>
LValue constIntPtr(T value) { return constInt(intPtr, bitwise_cast<intptr_t>(value), SignExtend); }
@@ -176,6 +177,7 @@
pointer.heap().decorateInstruction(result, *m_heaps);
}
+ LValue load8(TypedPointer pointer) { return load(pointer, ref8); }
LValue load32(TypedPointer pointer) { return load(pointer, ref32); }
LValue load64(TypedPointer pointer) { return load(pointer, ref64); }
LValue loadPtr(TypedPointer pointer) { return load(pointer, refPtr); }
@@ -245,6 +247,7 @@
return TypedPointer(m_heaps->absolute[address], constIntPtr(address));
}
+ LValue load8(LValue base, const AbstractField& field) { return load8(address(base, field)); }
LValue load32(LValue base, const AbstractField& field) { return load32(address(base, field)); }
LValue load64(LValue base, const AbstractField& field) { return load64(address(base, field)); }
LValue loadPtr(LValue base, const AbstractField& field) { return loadPtr(address(base, field)); }
@@ -276,9 +279,13 @@
LValue doubleGreaterThanOrUnordered(LValue left, LValue right) { return buildFCmp(m_builder, LLVMRealUGT, left, right); }
LValue doubleGreaterThanOrEqualOrUnordered(LValue left, LValue right) { return buildFCmp(m_builder, LLVMRealUGE, left, right); }
+ LValue isZero8(LValue value) { return equal(value, int8Zero); }
+ LValue notZero8(LValue value) { return notEqual(value, int8Zero); }
LValue isZero64(LValue value) { return equal(value, int64Zero); }
LValue notZero64(LValue value) { return notEqual(value, int64Zero); }
+ LValue testIsZero8(LValue value, LValue mask) { return isZero8(bitAnd(value, mask)); }
+ LValue testNonZero8(LValue value, LValue mask) { return notZero8(bitAnd(value, mask)); }
LValue testIsZero64(LValue value, LValue mask) { return isZero64(bitAnd(value, mask)); }
LValue testNonZero64(LValue value, LValue mask) { return notZero64(bitAnd(value, mask)); }