Chromium Code Reviews| 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 { |