fourthTier: don't insert ForceOSRExits except for inadequate coverage
https://bugs.webkit.org/show_bug.cgi?id=117363
Source/JavaScriptCore:
Reviewed by Mark Hahnenberg.
Previously (in http://trac.webkit.org/changeset/151303) I made it so that we
inserted ForceOSRExits more eagerly. I now think it's better to have
contradictions execute normally and exit with full OSR exit profiling. It's
better at catching the few cases where the DFG will end up with different
types than the baseline engines.
This simplifies a bunch of code. For example it gets rid of
ConstantFoldingPhase::paintUnreachableCode().
You can think of this as a partial roll-out of r151303, except that it uses
the facilities introduced by that patch to give us run-time assertions that
check the CFA's correctness: if the CFA thought that something was a
contradiction but the code didn't exit, we'll now trap.
* dfg/DFGAbstractState.cpp:
(JSC::DFG::AbstractState::AbstractState):
(JSC::DFG::AbstractState::startExecuting):
(JSC::DFG::AbstractState::executeEffects):
(JSC::DFG::AbstractState::execute):
(JSC::DFG::AbstractState::filter):
(JSC::DFG::AbstractState::filterArrayModes):
(JSC::DFG::AbstractState::filterByValue):
(DFG):
* dfg/DFGAbstractState.h:
(AbstractState):
(JSC::DFG::AbstractState::filter):
(JSC::DFG::AbstractState::filterArrayModes):
(JSC::DFG::AbstractState::filterByValue):
* dfg/DFGCFAPhase.cpp:
(JSC::DFG::CFAPhase::performBlockCFA):
* dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::run):
(JSC::DFG::ConstantFoldingPhase::foldConstants):
(ConstantFoldingPhase):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileNode):
LayoutTests:
Reviewed by Mark Hahnenberg.
Convert this test, since this was the test originally added for
ConstantFoldingPhase::paintUnreachableCode(). I wanted to make sure that I had good coverage
for this since I am removing that method.
* fast/js/dfg-force-exit-then-sparse-conditional-constant-prop-in-loop-expected.txt:
* fast/js/script-tests/dfg-force-exit-then-sparse-conditional-constant-prop-in-loop.js:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@153215 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
index a2b1f63..ba7f74a 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
+++ b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
@@ -43,7 +43,6 @@
, m_variables(m_codeBlock->numParameters(), graph.m_localVars)
, m_block(0)
, m_currentNode(0)
- , m_executionMode(CleanFiltration)
{
}
@@ -233,7 +232,7 @@
return UnknownBooleanResult;
}
-bool AbstractState::startExecuting(Node* node, ExecutionMode executionMode)
+bool AbstractState::startExecuting(Node* node)
{
ASSERT(m_block);
ASSERT(m_isValid);
@@ -244,18 +243,16 @@
if (!node->shouldGenerate()) {
m_currentNode = 0;
- m_executionMode = CleanFiltration;
return false;
}
m_currentNode = node;
- m_executionMode = executionMode;
return true;
}
-bool AbstractState::startExecuting(unsigned indexInBlock, ExecutionMode executionMode)
+bool AbstractState::startExecuting(unsigned indexInBlock)
{
- return startExecuting(m_block->at(indexInBlock), executionMode);
+ return startExecuting(m_block->at(indexInBlock));
}
void AbstractState::executeEdges(Node* node)
@@ -1105,8 +1102,7 @@
// structure.
filter(
node->child1(),
- m_graph.globalObjectFor(node->codeOrigin)->stringObjectStructure(),
- NotStringObject);
+ m_graph.globalObjectFor(node->codeOrigin)->stringObjectStructure());
node->setCanExit(true); // We could be more precise but it's likely not worth it.
break;
case StringOrStringObjectUse:
@@ -1325,7 +1321,7 @@
forNode(node).set(m_graph, status.specificValue());
else
forNode(node).makeTop();
- filter(node->child1(), status.structureSet(), BadCache);
+ filter(node->child1(), status.structureSet());
m_foundConstants = true;
break;
@@ -1363,12 +1359,6 @@
break;
}
- ExitKind exitKind;
- if (node->child1()->op() == WeakJSConstant)
- exitKind = BadWeakConstantCache;
- else
- exitKind = BadCache;
-
node->setCanExit(true);
// If this structure check is attempting to prove knowledge already held in
@@ -1377,11 +1367,11 @@
if (value.m_futurePossibleStructure.isSubsetOf(set)
&& value.m_futurePossibleStructure.hasSingleton()) {
m_foundConstants = true;
- filter(value, value.m_futurePossibleStructure.singleton(), exitKind);
+ filter(value, value.m_futurePossibleStructure.singleton());
break;
}
- filter(value, set, exitKind);
+ filter(value, set);
m_haveStructures = true;
break;
}
@@ -1390,12 +1380,6 @@
case ForwardStructureTransitionWatchpoint: {
AbstractValue& value = forNode(node->child1());
- ExitKind exitKind;
- if (node->child1()->op() == WeakJSConstant)
- exitKind = BadWeakConstantCache;
- else
- exitKind = BadCache;
-
// It's only valid to issue a structure transition watchpoint if we already
// know that the watchpoint covers a superset of the structures known to
// belong to the set of future structures that this value may have.
@@ -1406,7 +1390,7 @@
value.m_futurePossibleStructure.isSubsetOf(StructureSet(node->structure()))
|| m_graph.watchpoints().shouldAssumeMixedState(node->structure()->transitionWatchpointSet()));
- filter(value, node->structure(), exitKind);
+ filter(value, node->structure());
m_haveStructures = true;
node->setCanExit(true);
break;
@@ -1501,7 +1485,7 @@
m_foundConstants = true;
node->setCanExit(true);
clobberStructures(indexInBlock);
- filter(value, set, BadIndexingType);
+ filter(value, set);
m_haveStructures = true;
break;
}
@@ -1527,7 +1511,7 @@
}
node->setCanExit(true); // Lies! We can do better.
- filterByValue(node->child1(), node->function(), BadFunction);
+ filterByValue(node->child1(), node->function());
break;
}
@@ -1542,7 +1526,7 @@
m_graph.identifiers()[node->identifierNumber()],
node->op() == PutByIdDirect);
if (status.isSimpleReplace()) {
- filter(node->child1(), structure, BadCache);
+ filter(node->child1(), structure);
m_foundConstants = true;
break;
}
@@ -1631,10 +1615,10 @@
return executeEffects(indexInBlock, m_block->at(indexInBlock));
}
-bool AbstractState::execute(unsigned indexInBlock, ExecutionMode executionMode)
+bool AbstractState::execute(unsigned indexInBlock)
{
Node* node = m_block->at(indexInBlock);
- if (!startExecuting(node, executionMode))
+ if (!startExecuting(node))
return true;
executeEdges(node);
@@ -1868,61 +1852,39 @@
}
}
-FiltrationResult AbstractState::filter(
- AbstractValue& value, const StructureSet& set, ExitKind exitKind)
+FiltrationResult AbstractState::filter(AbstractValue& value, const StructureSet& set)
{
if (value.filter(m_graph, set) == FiltrationOK)
return FiltrationOK;
- bail(exitKind);
+ m_isValid = false;
return Contradiction;
}
-FiltrationResult AbstractState::filterArrayModes(
- AbstractValue& value, ArrayModes arrayModes, ExitKind exitKind)
+FiltrationResult AbstractState::filterArrayModes(AbstractValue& value, ArrayModes arrayModes)
{
if (value.filterArrayModes(arrayModes) == FiltrationOK)
return FiltrationOK;
- bail(exitKind);
+ m_isValid = false;
return Contradiction;
}
-FiltrationResult AbstractState::filter(
- AbstractValue& value, SpeculatedType type, ExitKind exitKind)
+FiltrationResult AbstractState::filter(AbstractValue& value, SpeculatedType type)
{
if (value.filter(type) == FiltrationOK)
return FiltrationOK;
- bail(exitKind);
+ m_isValid = false;
return Contradiction;
}
FiltrationResult AbstractState::filterByValue(
- AbstractValue& abstractValue, JSValue concreteValue, ExitKind exitKind)
+ AbstractValue& abstractValue, JSValue concreteValue)
{
if (abstractValue.filterByValue(concreteValue) == FiltrationOK)
return FiltrationOK;
- bail(exitKind);
+ m_isValid = false;
return Contradiction;
}
-void AbstractState::bail(ExitKind exitKind)
-{
- ASSERT(m_currentNode);
- m_isValid = false;
- switch (m_executionMode) {
- case StillConverging:
- return;
- case AfterConvergence: {
- m_graph.baselineCodeBlockFor(m_currentNode->codeOrigin)->addFrequentExitSite(
- FrequentExitSite(m_currentNode->codeOrigin.bytecodeIndex, exitKind));
- return;
- }
- case CleanFiltration:
- RELEASE_ASSERT_NOT_REACHED();
- return;
- }
- RELEASE_ASSERT_NOT_REACHED();
-}
-
} } // namespace JSC::DFG
#endif // ENABLE(DFG_JIT)