Index: src/data-flow.h |
diff --git a/src/data-flow.h b/src/data-flow.h |
index f6767e0a462f475365b4fc930408ca35bbfa81c0..905256e6faf9a00c47746dd96aa5de1f09a23a13 100644 |
--- a/src/data-flow.h |
+++ b/src/data-flow.h |
@@ -95,6 +95,299 @@ class BitVector { |
}; |
+// Forward declarations of Node types. |
+class Node; |
+class BranchNode; |
+class JoinNode; |
+ |
+// Flow graphs have a single entry and single exit. The empty flowgraph is |
+// represented by both entry and exit being NULL. |
+class FlowGraph BASE_EMBEDDED { |
+ public: |
+ FlowGraph() : entry_(NULL), exit_(NULL) {} |
+ |
+ static FlowGraph Empty() { return FlowGraph(); } |
+ |
+ bool is_empty() const { return entry_ == NULL; } |
+ Node* entry() const { return entry_; } |
+ Node* exit() const { return exit_; } |
+ |
+ // Add a single instruction to the end of this flowgraph. |
+ void Append(AstNode* instruction); |
fschneider
2010/03/08 12:14:27
I'm not sure if overloading the name Append helps
|
+ |
+ // Add a single node to the end of this flow graph. |
+ void Append(Node* node); |
+ |
+ // Add a flow graph fragment to the end of this one. |
+ void Append(FlowGraph* graph); |
+ |
+ // Concatenate an if-then-else flow-graph to this one. Control is split |
+ // and merged, so the graph remains single-entry, single-exit. |
fschneider
2010/03/08 12:14:27
Maybe mentions that left is always the true-branch
|
+ void Split(BranchNode* branch, |
+ FlowGraph* left, |
+ FlowGraph* right, |
+ JoinNode* merge); |
+ |
+ // Concatenate a forward loop (e.g., while or for loop) flow-graph to this |
+ // one. Control is split by the condition and merged back from the back |
+ // edge at end of the body to the beginning of the condition. The single |
+ // (free) exit of the result graph is the right (false) arm of the branch |
+ // node. |
+ void Loop(JoinNode* merge, |
+ FlowGraph* condition, |
+ BranchNode* branch, |
+ FlowGraph* body); |
+ |
+#ifdef DEBUG |
+ void PrintText(ZoneList<Node*>* postorder); |
+#endif |
+ |
+ private: |
+ Node* entry_; |
+ Node* exit_; |
+}; |
+ |
+ |
+// Flow-graph nodes. |
+class Node: public ZoneObject { |
+ public: |
+ Node() : number_(-1), mark_(false) {} |
+ |
+ virtual ~Node() {} |
+ |
+ virtual bool IsBlockNode() { return false; } |
+ virtual bool IsJoinNode() { return false; } |
+ |
+ virtual void AddPredecessor(Node* predecessor) = 0; |
+ virtual void AddSuccessor(Node* successor) = 0; |
+ |
+ bool IsMarkedWith(bool mark) { return mark_ == mark; } |
+ void MarkWith(bool mark) { mark_ = mark; } |
fschneider
2010/03/08 12:14:27
Name this functions consistently with other access
|
+ |
+ // Perform a depth first search and record preorder and postorder |
+ // traversal orders. |
+ virtual void Traverse(bool mark, |
+ ZoneList<Node*>* preorder, |
+ ZoneList<Node*>* postorder) = 0; |
+ |
+ int number() { return number_; } |
+ void set_number(int number) { number_ = number; } |
+ |
+#ifdef DEBUG |
+ virtual void AssignNumbers(); |
+ virtual void PrintText() = 0; |
+#endif |
+ |
+ private: |
+ int number_; |
+ bool mark_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(Node); |
+}; |
+ |
+ |
+// An entry node has no predecessors and a single successor. |
+class EntryNode: public Node { |
+ public: |
+ EntryNode() : successor_(NULL) {} |
+ |
+ void AddPredecessor(Node* predecessor) { UNREACHABLE(); } |
+ |
+ void AddSuccessor(Node* successor) { |
+ ASSERT(successor_ == NULL && successor != NULL); |
+ successor_ = successor; |
+ } |
+ |
+ void Traverse(bool mark, |
+ ZoneList<Node*>* preorder, |
+ ZoneList<Node*>* postorder); |
+ |
+#ifdef DEBUG |
+ void PrintText(); |
+#endif |
+ |
+ private: |
+ Node* successor_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(EntryNode); |
+}; |
+ |
+ |
+// An exit node has a arbitrarily many predecessors and no successors. |
+class ExitNode: public Node { |
+ public: |
+ ExitNode() : predecessors_(4) {} |
+ |
+ void AddPredecessor(Node* predecessor) { |
+ ASSERT(predecessor != NULL); |
+ predecessors_.Add(predecessor); |
+ } |
+ |
+ void AddSuccessor(Node* successor) { /* Do nothing. */ } |
+ |
+ void Traverse(bool mark, |
+ ZoneList<Node*>* preorder, |
+ ZoneList<Node*>* postorder); |
+ |
+#ifdef DEBUG |
+ void PrintText(); |
+#endif |
+ |
+ private: |
+ ZoneList<Node*> predecessors_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ExitNode); |
+}; |
+ |
+ |
+// Block nodes have a single successor and predecessor and a list of |
+// instructions. |
+class BlockNode: public Node { |
+ public: |
+ BlockNode() : predecessor_(NULL), successor_(NULL), instructions_(4) {} |
+ |
+ static BlockNode* cast(Node* node) { |
+ ASSERT(node->IsBlockNode()); |
+ return reinterpret_cast<BlockNode*>(node); |
+ } |
+ |
+ bool IsBlockNode() { return true; } |
+ |
+ void AddPredecessor(Node* predecessor) { |
+ ASSERT(predecessor_ == NULL && predecessor != NULL); |
+ predecessor_ = predecessor; |
+ } |
+ |
+ void AddSuccessor(Node* successor) { |
+ ASSERT(successor_ == NULL && successor != NULL); |
+ successor_ = successor; |
+ } |
+ |
+ void AddInstruction(AstNode* instruction) { |
+ instructions_.Add(instruction); |
+ } |
+ |
+ void Traverse(bool mark, |
+ ZoneList<Node*>* preorder, |
+ ZoneList<Node*>* postorder); |
+ |
+#ifdef DEBUG |
+ void AssignNumbers(); |
+ void PrintText(); |
+#endif |
+ |
+ private: |
+ Node* predecessor_; |
+ Node* successor_; |
+ ZoneList<AstNode*> instructions_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(BlockNode); |
+}; |
+ |
+ |
+// Branch nodes have a single predecessor and a pair of successors. |
+class BranchNode: public Node { |
+ public: |
+ BranchNode() : predecessor_(NULL), successor0_(NULL), successor1_(NULL) {} |
+ |
+ void AddPredecessor(Node* predecessor) { |
+ ASSERT(predecessor_ == NULL && predecessor != NULL); |
+ predecessor_ = predecessor; |
+ } |
+ |
+ void AddSuccessor(Node* successor) { |
+ ASSERT(successor1_ == NULL && successor != NULL); |
+ if (successor0_ == NULL) { |
+ successor0_ = successor; |
+ } else { |
+ successor1_ = successor; |
+ } |
+ } |
+ |
+ void Traverse(bool mark, |
+ ZoneList<Node*>* preorder, |
+ ZoneList<Node*>* postorder); |
+ |
+#ifdef DEBUG |
+ void PrintText(); |
+#endif |
+ |
+ private: |
+ Node* predecessor_; |
+ Node* successor0_; |
+ Node* successor1_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(BranchNode); |
+}; |
+ |
+ |
+// Join nodes have arbitrarily many predecessors and a single successor. |
+class JoinNode: public Node { |
+ public: |
+ JoinNode() : predecessors_(2), successor_(NULL) {} |
+ |
+ static JoinNode* cast(Node* node) { |
+ ASSERT(node->IsJoinNode()); |
+ return reinterpret_cast<JoinNode*>(node); |
+ } |
+ |
+ bool IsJoinNode() { return true; } |
+ |
+ void AddPredecessor(Node* predecessor) { |
+ ASSERT(predecessor != NULL); |
+ predecessors_.Add(predecessor); |
+ } |
+ |
+ void AddSuccessor(Node* successor) { |
+ ASSERT(successor_ == NULL && successor != NULL); |
+ successor_ = successor; |
+ } |
+ |
+ void Traverse(bool mark, |
+ ZoneList<Node*>* preorder, |
+ ZoneList<Node*>* postorder); |
+ |
+#ifdef DEBUG |
+ void PrintText(); |
+#endif |
+ |
+ private: |
+ ZoneList<Node*> predecessors_; |
+ Node* successor_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(JoinNode); |
+}; |
+ |
+ |
+// Construct a flow graph from a function literal. Build pre- and postorder |
+// traversal orders as a byproduct. |
+class FlowGraphBuilder: public AstVisitor { |
+ public: |
+ FlowGraphBuilder() : global_exit_(NULL), preorder_(4), postorder_(4) {} |
+ |
+ void Build(FunctionLiteral* lit); |
+ |
+ FlowGraph* graph() { return &graph_; } |
+ |
+ ZoneList<Node*>* postorder() { return &postorder_; } |
+ |
+ private: |
+ ExitNode* global_exit() { return global_exit_; } |
+ |
+ // AST node visit functions. |
+#define DECLARE_VISIT(type) virtual void Visit##type(type* node); |
+ AST_NODE_LIST(DECLARE_VISIT) |
+#undef DECLARE_VISIT |
+ |
+ FlowGraph graph_; |
+ ExitNode* global_exit_; |
+ ZoneList<Node*> preorder_; |
+ ZoneList<Node*> postorder_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(FlowGraphBuilder); |
+}; |
+ |
+ |
// This class is used to number all expressions in the AST according to |
// their evaluation order (post-order left-to-right traversal). |
class AstLabeler: public AstVisitor { |