summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/dfg/DFGAbstractState.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGAbstractState.h')
-rw-r--r--Source/JavaScriptCore/dfg/DFGAbstractState.h134
1 files changed, 75 insertions, 59 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.h b/Source/JavaScriptCore/dfg/DFGAbstractState.h
index 40dc50248..de1f17d1f 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractState.h
+++ b/Source/JavaScriptCore/dfg/DFGAbstractState.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -72,8 +72,8 @@ struct BasicBlock;
// AbstractState state(codeBlock, graph);
// state.beginBasicBlock(basicBlock);
// bool endReached = true;
-// for (NodeIndex idx = basicBlock.begin; idx < basicBlock.end; ++idx) {
-// if (!state.execute(idx))
+// for (unsigned i = 0; i < basicBlock->size(); ++i) {
+// if (!state.execute(i))
// break;
// }
// bool result = state.endBasicBlock(<either Merge or DontMerge>);
@@ -97,14 +97,14 @@ public:
~AbstractState();
- AbstractValue& forNode(NodeIndex nodeIndex)
+ AbstractValue& forNode(Node* node)
{
- return m_nodes[nodeIndex];
+ return node->value;
}
- AbstractValue& forNode(Edge nodeUse)
+ AbstractValue& forNode(Edge edge)
{
- return forNode(nodeUse.index());
+ return forNode(edge.node());
}
Operands<AbstractValue>& variables()
@@ -158,7 +158,53 @@ public:
// if execution should continue past this node. Notably, it will return true
// for block terminals, so long as those terminals are not Return or variants
// of Throw.
- bool execute(unsigned);
+ //
+ // This is guaranteed to be equivalent to doing:
+ //
+ // if (state.startExecuting(index)) {
+ // state.executeEdges(index);
+ // result = state.executeEffects(index);
+ // } else
+ // result = true;
+ bool execute(unsigned indexInBlock);
+
+ // Indicate the start of execution of the node. It resets any state in the node,
+ // that is progressively built up by executeEdges() and executeEffects(). In
+ // particular, this resets canExit(), so if you want to "know" between calls of
+ // startExecuting() and executeEdges()/Effects() whether the last run of the
+ // analysis concluded that the node can exit, you should probably set that
+ // information aside prior to calling startExecuting().
+ bool startExecuting(Node*);
+ bool startExecuting(unsigned indexInBlock);
+
+ // Abstractly execute the edges of the given node. This runs filterEdgeByUse()
+ // on all edges of the node. You can skip this step, if you have already used
+ // filterEdgeByUse() (or some equivalent) on each edge.
+ void executeEdges(Node*);
+ void executeEdges(unsigned indexInBlock);
+
+ ALWAYS_INLINE void filterEdgeByUse(Node* node, Edge& edge)
+ {
+#if !ASSERT_DISABLED
+ switch (edge.useKind()) {
+ case KnownInt32Use:
+ case KnownNumberUse:
+ case KnownCellUse:
+ case KnownStringUse:
+ ASSERT(!(forNode(edge).m_type & ~typeFilterFor(edge.useKind())));
+ break;
+ default:
+ break;
+ }
+#endif // !ASSERT_DISABLED
+
+ filterByType(node, edge, typeFilterFor(edge.useKind()));
+ }
+
+ // Abstractly execute the effects of the given node. This changes the abstract
+ // state assuming that edges have already been filtered.
+ bool executeEffects(unsigned indexInBlock);
+ bool executeEffects(unsigned indexInBlock, Node*);
// Did the last executed node clobber the world?
bool didClobber() const { return m_didClobber; }
@@ -187,62 +233,18 @@ private:
void clobberCapturedVars(const CodeOrigin&);
void clobberStructures(unsigned indexInBlock);
- bool mergeStateAtTail(AbstractValue& destination, AbstractValue& inVariable, NodeIndex);
-
- static bool mergeVariableBetweenBlocks(AbstractValue& destination, AbstractValue& source, NodeIndex destinationNodeIndex, NodeIndex sourceNodeIndex);
+ bool mergeStateAtTail(AbstractValue& destination, AbstractValue& inVariable, Node*);
- void speculateInt32Unary(Node& node, bool forceCanExit = false)
- {
- AbstractValue& childValue = forNode(node.child1());
- node.setCanExit(forceCanExit || !isInt32Speculation(childValue.m_type));
- childValue.filter(SpecInt32);
- }
-
- void speculateNumberUnary(Node& node)
- {
- AbstractValue& childValue = forNode(node.child1());
- node.setCanExit(!isNumberSpeculation(childValue.m_type));
- childValue.filter(SpecNumber);
- }
-
- void speculateBooleanUnary(Node& node)
- {
- AbstractValue& childValue = forNode(node.child1());
- node.setCanExit(!isBooleanSpeculation(childValue.m_type));
- childValue.filter(SpecBoolean);
- }
-
- void speculateInt32Binary(Node& node, bool forceCanExit = false)
- {
- AbstractValue& childValue1 = forNode(node.child1());
- AbstractValue& childValue2 = forNode(node.child2());
- node.setCanExit(
- forceCanExit
- || !isInt32Speculation(childValue1.m_type)
- || !isInt32Speculation(childValue2.m_type));
- childValue1.filter(SpecInt32);
- childValue2.filter(SpecInt32);
- }
-
- void speculateNumberBinary(Node& node)
- {
- AbstractValue& childValue1 = forNode(node.child1());
- AbstractValue& childValue2 = forNode(node.child2());
- node.setCanExit(
- !isNumberSpeculation(childValue1.m_type)
- || !isNumberSpeculation(childValue2.m_type));
- childValue1.filter(SpecNumber);
- childValue2.filter(SpecNumber);
- }
+ static bool mergeVariableBetweenBlocks(AbstractValue& destination, AbstractValue& source, Node* destinationNode, Node* sourceNode);
enum BooleanResult {
UnknownBooleanResult,
DefinitelyFalse,
DefinitelyTrue
};
- BooleanResult booleanResult(Node&, AbstractValue&);
+ BooleanResult booleanResult(Node*, AbstractValue&);
- bool trySetConstant(NodeIndex nodeIndex, JSValue value)
+ bool trySetConstant(Node* node, JSValue value)
{
// Make sure we don't constant fold something that will produce values that contravene
// predictions. If that happens then we know that the code will OSR exit, forcing
@@ -251,18 +253,32 @@ private:
// lot of subtle code that assumes that
// speculationFromValue(jsConstant) == jsConstant.prediction(). "Hardening" that code
// is probably less sane than just pulling back on constant folding.
- SpeculatedType oldType = m_graph[nodeIndex].prediction();
+ SpeculatedType oldType = node->prediction();
if (mergeSpeculations(speculationFromValue(value), oldType) != oldType)
return false;
- forNode(nodeIndex).set(value);
+ forNode(node).set(value);
return true;
}
+ ALWAYS_INLINE void filterByType(Node* node, Edge& edge, SpeculatedType type)
+ {
+ AbstractValue& value = forNode(edge);
+ if (value.m_type & ~type) {
+ node->setCanExit(true);
+ edge.setProofStatus(NeedsCheck);
+ } else
+ edge.setProofStatus(IsProved);
+
+ value.filter(type);
+ }
+
+ void verifyEdge(Node*, Edge);
+ void verifyEdges(Node*);
+
CodeBlock* m_codeBlock;
Graph& m_graph;
- Vector<AbstractValue, 64> m_nodes;
Operands<AbstractValue> m_variables;
BasicBlock* m_block;
bool m_haveStructures;