Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (188746 => 188747)
--- trunk/Source/_javascript_Core/ChangeLog 2015-08-21 03:12:25 UTC (rev 188746)
+++ trunk/Source/_javascript_Core/ChangeLog 2015-08-21 03:59:33 UTC (rev 188747)
@@ -1,5 +1,43 @@
2015-08-20 Filip Pizlo <[email protected]>
+ DFG should have a KnownBooleanUse for cases where we are required to know that the child is a boolean and it's not OK to speculate
+ https://bugs.webkit.org/show_bug.cgi?id=148286
+
+ Reviewed by Benjamin Poulain.
+
+ This enables us to ensure that the Branch or LogicalNot after an effectful CompareXYZ can
+ be marked as !mayExit(). I need that for https://bugs.webkit.org/show_bug.cgi?id=145204.
+
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::fixupNode):
+ (JSC::DFG::FixupPhase::observeUseKindOnNode):
+ * dfg/DFGSafeToExecute.h:
+ (JSC::DFG::SafeToExecuteEdge::operator()):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::speculate):
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculateBooleanOperand::SpeculateBooleanOperand):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::fillSpeculateBoolean):
+ (JSC::DFG::SpeculativeJIT::compileLogicalNot):
+ (JSC::DFG::SpeculativeJIT::emitBranch):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::fillSpeculateBoolean):
+ (JSC::DFG::SpeculativeJIT::compileLogicalNot):
+ (JSC::DFG::SpeculativeJIT::emitBranch):
+ * dfg/DFGUseKind.cpp:
+ (WTF::printInternal):
+ * dfg/DFGUseKind.h:
+ (JSC::DFG::typeFilterFor):
+ (JSC::DFG::shouldNotHaveTypeCheck):
+ * ftl/FTLCapabilities.cpp:
+ (JSC::FTL::canCompile):
+ * ftl/FTLLowerDFGToLLVM.cpp:
+ (JSC::FTL::DFG::LowerDFGToLLVM::boolify):
+ (JSC::FTL::DFG::LowerDFGToLLVM::lowBoolean):
+
+2015-08-20 Filip Pizlo <[email protected]>
+
Overflow check elimination fails for a simple test case
https://bugs.webkit.org/show_bug.cgi?id=147387
Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (188746 => 188747)
--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2015-08-21 03:12:25 UTC (rev 188746)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2015-08-21 03:59:33 UTC (rev 188747)
@@ -356,9 +356,19 @@
}
case LogicalNot: {
- if (node->child1()->shouldSpeculateBoolean())
- fixEdge<BooleanUse>(node->child1());
- else if (node->child1()->shouldSpeculateObjectOrOther())
+ if (node->child1()->shouldSpeculateBoolean()) {
+ if (node->child1()->result() == NodeResultBoolean) {
+ // This is necessary in case we have a bytecode instruction implemented by:
+ //
+ // a: CompareEq(...)
+ // b: LogicalNot(@a)
+ //
+ // In that case, CompareEq might have a side-effect. Then, we need to make
+ // sure that we know that Branch does not exit.
+ fixEdge<KnownBooleanUse>(node->child1());
+ } else
+ fixEdge<BooleanUse>(node->child1());
+ } else if (node->child1()->shouldSpeculateObjectOrOther())
fixEdge<ObjectOrOtherUse>(node->child1());
else if (node->child1()->shouldSpeculateInt32OrBoolean())
fixIntOrBooleanEdge(node->child1());
@@ -819,9 +829,19 @@
}
case Branch: {
- if (node->child1()->shouldSpeculateBoolean())
- fixEdge<BooleanUse>(node->child1());
- else if (node->child1()->shouldSpeculateObjectOrOther())
+ if (node->child1()->shouldSpeculateBoolean()) {
+ if (node->child1()->result() == NodeResultBoolean) {
+ // This is necessary in case we have a bytecode instruction implemented by:
+ //
+ // a: CompareEq(...)
+ // b: Branch(@a)
+ //
+ // In that case, CompareEq might have a side-effect. Then, we need to make
+ // sure that we know that Branch does not exit.
+ fixEdge<KnownBooleanUse>(node->child1());
+ } else
+ fixEdge<BooleanUse>(node->child1());
+ } else if (node->child1()->shouldSpeculateObjectOrOther())
fixEdge<ObjectOrOtherUse>(node->child1());
else if (node->child1()->shouldSpeculateInt32OrBoolean())
fixIntOrBooleanEdge(node->child1());
@@ -1777,6 +1797,7 @@
VariableAccessData* variable = node->variableAccessData();
switch (useKind) {
case Int32Use:
+ case KnownInt32Use:
if (alwaysUnboxSimplePrimitives()
|| isInt32Speculation(variable->prediction()))
m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
@@ -1789,6 +1810,7 @@
m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
break;
case BooleanUse:
+ case KnownBooleanUse:
if (alwaysUnboxSimplePrimitives()
|| isBooleanSpeculation(variable->prediction()))
m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
Modified: trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h (188746 => 188747)
--- trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2015-08-21 03:12:25 UTC (rev 188746)
+++ trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2015-08-21 03:59:33 UTC (rev 188747)
@@ -74,6 +74,11 @@
if (m_state.forNode(edge).m_type & ~SpecInt32)
m_result = false;
return;
+
+ case KnownBooleanUse:
+ if (m_state.forNode(edge).m_type & ~SpecBoolean)
+ m_result = false;
+ return;
case KnownCellUse:
if (m_state.forNode(edge).m_type & ~SpecCell)
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (188746 => 188747)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2015-08-21 03:12:25 UTC (rev 188746)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2015-08-21 03:59:33 UTC (rev 188747)
@@ -5908,6 +5908,9 @@
case BooleanUse:
speculateBoolean(edge);
break;
+ case KnownBooleanUse:
+ ASSERT(!needsTypeCheck(edge, SpecBoolean));
+ break;
case CellUse:
speculateCell(edge);
break;
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (188746 => 188747)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2015-08-21 03:12:25 UTC (rev 188746)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2015-08-21 03:59:33 UTC (rev 188747)
@@ -3245,7 +3245,7 @@
, m_gprOrInvalid(InvalidGPRReg)
{
ASSERT(m_jit);
- ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == BooleanUse);
+ ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == BooleanUse || edge.useKind() == KnownBooleanUse);
if (jit->isFilled(node()))
gpr();
}
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (188746 => 188747)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2015-08-21 03:12:25 UTC (rev 188746)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2015-08-21 03:59:33 UTC (rev 188747)
@@ -1033,6 +1033,7 @@
{
AbstractValue& value = m_state.forNode(edge);
SpeculatedType type = value.m_type;
+ ASSERT(edge.useKind() != KnownBooleanUse || !(value.m_type & ~SpecBoolean));
m_interpreter.filter(value, SpecBoolean);
if (value.isClear()) {
@@ -1463,7 +1464,8 @@
void SpeculativeJIT::compileLogicalNot(Node* node)
{
switch (node->child1().useKind()) {
- case BooleanUse: {
+ case BooleanUse:
+ case KnownBooleanUse: {
SpeculateBooleanOperand value(this, node->child1());
GPRTemporary result(this, Reuse, value);
m_jit.xor32(TrustedImm32(1), value.gpr(), result.gpr());
@@ -1582,7 +1584,8 @@
BasicBlock* notTaken = node->branchData()->notTaken.block;
switch (node->child1().useKind()) {
- case BooleanUse: {
+ case BooleanUse:
+ case KnownBooleanUse: {
SpeculateBooleanOperand value(this, node->child1());
MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (188746 => 188747)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2015-08-21 03:12:25 UTC (rev 188746)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2015-08-21 03:59:33 UTC (rev 188747)
@@ -1139,6 +1139,7 @@
{
AbstractValue& value = m_state.forNode(edge);
SpeculatedType type = value.m_type;
+ ASSERT(edge.useKind() != KnownBooleanUse || !(value.m_type & ~SpecBoolean));
m_interpreter.filter(value, SpecBoolean);
if (value.isClear()) {
@@ -1617,7 +1618,8 @@
return;
}
- case BooleanUse: {
+ case BooleanUse:
+ case KnownBooleanUse: {
if (!needsTypeCheck(node->child1(), SpecBoolean)) {
SpeculateBooleanOperand value(this, node->child1());
GPRTemporary result(this, Reuse, value);
@@ -1769,11 +1771,12 @@
}
case UntypedUse:
- case BooleanUse: {
+ case BooleanUse:
+ case KnownBooleanUse: {
JSValueOperand value(this, node->child1(), ManualOperandSpeculation);
GPRReg valueGPR = value.gpr();
- if (node->child1().useKind() == BooleanUse) {
+ if (node->child1().useKind() == BooleanUse || node->child1().useKind() == KnownBooleanUse) {
if (!needsTypeCheck(node->child1(), SpecBoolean)) {
MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
Modified: trunk/Source/_javascript_Core/dfg/DFGUseKind.cpp (188746 => 188747)
--- trunk/Source/_javascript_Core/dfg/DFGUseKind.cpp 2015-08-21 03:12:25 UTC (rev 188746)
+++ trunk/Source/_javascript_Core/dfg/DFGUseKind.cpp 2015-08-21 03:59:33 UTC (rev 188747)
@@ -70,6 +70,9 @@
case BooleanUse:
out.print("Boolean");
return;
+ case KnownBooleanUse:
+ out.print("KnownBoolean");
+ return;
case CellUse:
out.print("Cell");
return;
Modified: trunk/Source/_javascript_Core/dfg/DFGUseKind.h (188746 => 188747)
--- trunk/Source/_javascript_Core/dfg/DFGUseKind.h 2015-08-21 03:12:25 UTC (rev 188746)
+++ trunk/Source/_javascript_Core/dfg/DFGUseKind.h 2015-08-21 03:59:33 UTC (rev 188747)
@@ -48,6 +48,7 @@
NumberUse,
RealNumberUse,
BooleanUse,
+ KnownBooleanUse,
CellUse,
KnownCellUse,
ObjectUse,
@@ -101,6 +102,7 @@
case DoubleRepMachineIntUse:
return SpecInt52AsDouble;
case BooleanUse:
+ case KnownBooleanUse:
return SpecBoolean;
case CellUse:
case KnownCellUse:
@@ -145,6 +147,7 @@
case KnownInt32Use:
case KnownCellUse:
case KnownStringUse:
+ case KnownBooleanUse:
case Int52RepUse:
case DoubleRepUse:
return true;
Modified: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (188746 => 188747)
--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2015-08-21 03:12:25 UTC (rev 188746)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2015-08-21 03:59:33 UTC (rev 188747)
@@ -412,6 +412,7 @@
case DoubleRepUse:
case DoubleRepRealUse:
case BooleanUse:
+ case KnownBooleanUse:
case CellUse:
case KnownCellUse:
case ObjectUse:
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp (188746 => 188747)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2015-08-21 03:12:25 UTC (rev 188746)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2015-08-21 03:59:33 UTC (rev 188747)
@@ -6130,6 +6130,7 @@
{
switch (edge.useKind()) {
case BooleanUse:
+ case KnownBooleanUse:
return lowBoolean(edge);
case Int32Use:
return m_out.notZero32(lowInt32(edge));
@@ -7120,7 +7121,7 @@
LValue lowBoolean(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
{
- ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == BooleanUse);
+ ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == BooleanUse || edge.useKind() == KnownBooleanUse);
if (edge->hasConstant()) {
JSValue value = edge->asJSValue();