diff options
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGAbstractState.h')
-rw-r--r-- | Source/JavaScriptCore/dfg/DFGAbstractState.h | 134 |
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; |