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):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@188747 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
index 98b009e..ff675d9 100644
--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
@@ -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);
diff --git a/Source/JavaScriptCore/dfg/DFGSafeToExecute.h b/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
index b1fc5fb..7869b2c 100644
--- a/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
+++ b/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
@@ -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)
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
index 71fa605b..9a30b2a 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
@@ -5908,6 +5908,9 @@
case BooleanUse:
speculateBoolean(edge);
break;
+ case KnownBooleanUse:
+ ASSERT(!needsTypeCheck(edge, SpecBoolean));
+ break;
case CellUse:
speculateCell(edge);
break;
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
index b2008a1..d1229ef 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
@@ -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();
}
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
index c8e4f79..e85d36f 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
@@ -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;
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
index 2fa615f..4fc6069 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
@@ -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;
diff --git a/Source/JavaScriptCore/dfg/DFGUseKind.cpp b/Source/JavaScriptCore/dfg/DFGUseKind.cpp
index 936ef55..3442341 100644
--- a/Source/JavaScriptCore/dfg/DFGUseKind.cpp
+++ b/Source/JavaScriptCore/dfg/DFGUseKind.cpp
@@ -70,6 +70,9 @@
case BooleanUse:
out.print("Boolean");
return;
+ case KnownBooleanUse:
+ out.print("KnownBoolean");
+ return;
case CellUse:
out.print("Cell");
return;
diff --git a/Source/JavaScriptCore/dfg/DFGUseKind.h b/Source/JavaScriptCore/dfg/DFGUseKind.h
index 289b783..14c1e95 100644
--- a/Source/JavaScriptCore/dfg/DFGUseKind.h
+++ b/Source/JavaScriptCore/dfg/DFGUseKind.h
@@ -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;