Index: src/flow-graph.h |
diff --git a/src/flow-graph.h b/src/flow-graph.h |
index 183b71d5b08082f068365f47519e276d615820fb..81a883ca995a7dd91a25d3d42ce8c4c862b957e6 100644 |
--- a/src/flow-graph.h |
+++ b/src/flow-graph.h |
@@ -36,339 +36,140 @@ |
namespace v8 { |
namespace internal { |
-// Flow-graph nodes. |
-class Node: public ZoneObject { |
- public: |
- Node() : number_(-1), mark_(false) {} |
- |
- virtual ~Node() {} |
- |
- virtual bool IsExitNode() { return false; } |
- virtual bool IsBlockNode() { return false; } |
- virtual bool IsBranchNode() { 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; } |
- |
- // 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; } |
- |
- // Functions used by data-flow analyses. |
- virtual void InitializeReachingDefinitions(int definition_count, |
- List<BitVector*>* variables, |
- WorkList<Node>* worklist, |
- bool mark); |
- virtual void ComputeRDOut(BitVector* result) = 0; |
- virtual void UpdateRDIn(WorkList<Node>* worklist, bool mark) = 0; |
- virtual void PropagateReachingDefinitions(List<BitVector*>* variables); |
- |
- // Functions used by dead-code elimination. |
- virtual void MarkCriticalInstructions( |
- List<AstNode*>* stack, |
- ZoneList<Expression*>* body_definitions, |
- int variable_count); |
- |
-#ifdef DEBUG |
- void AssignNodeNumber(); |
- void PrintReachingDefinitions(); |
- virtual void PrintText() = 0; |
-#endif |
- |
- protected: |
- ReachingDefinitionsData rd_; |
- |
- private: |
- int number_; |
- bool mark_; |
- |
- DISALLOW_COPY_AND_ASSIGN(Node); |
-}; |
- |
- |
-// An exit node has a arbitrarily many predecessors and no successors. |
-class ExitNode: public Node { |
+// The nodes of a flow graph are basic blocks. Basic blocks consist of |
+// instructions represented as pointers to AST nodes in the order that they |
+// would be visited by the code generator. A block can have arbitrarily many |
+// (even zero) predecessors and up to two successors. Blocks with multiple |
+// predecessors are "join nodes" and blocks with multiple successors are |
+// "branch nodes". A block can be both a branch and a join node. |
+// |
+// Flow graphs are in edge split form: a branch node is never the |
+// predecessor of a merge node. Empty basic blocks are inserted to maintain |
+// edge split form. |
+class BasicBlock: public ZoneObject { |
public: |
- ExitNode() : predecessors_(4) {} |
+ // Construct a basic block with a given predecessor. NULL indicates no |
+ // predecessor or that the predecessor will be set later. |
+ BasicBlock(BasicBlock* predecessor) |
fschneider
2010/03/29 13:49:59
explicit for 1-argument constructors?
Kevin Millikin (Chromium)
2010/03/29 14:22:53
Done.
|
+ : predecessors_(2), |
+ instructions_(8), |
+ left_successor_(NULL), |
+ right_successor_(NULL), |
+ mark_(false) { |
+ if (predecessor != NULL) AddPredecessor(predecessor); |
+ } |
- virtual bool IsExitNode() { return true; } |
+ bool HasPredecessor() { return !predecessors_.is_empty(); } |
+ bool HasSuccessor() { return left_successor_ != NULL; } |
- virtual void AddPredecessor(Node* predecessor) { |
+ // Add a given basic block as a predecessor of this block. This function |
+ // also adds this block as a successor of the given block. |
+ void AddPredecessor(BasicBlock* predecessor) { |
ASSERT(predecessor != NULL); |
predecessors_.Add(predecessor); |
+ predecessor->AddSuccessor(this); |
} |
- virtual void AddSuccessor(Node* successor) { UNREACHABLE(); } |
- |
- virtual void Traverse(bool mark, |
- ZoneList<Node*>* preorder, |
- ZoneList<Node*>* postorder); |
- |
- virtual void ComputeRDOut(BitVector* result); |
- virtual void UpdateRDIn(WorkList<Node>* worklist, bool mark); |
- |
-#ifdef DEBUG |
- virtual 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); |
- } |
- |
- virtual bool IsBlockNode() { return true; } |
- |
- bool is_empty() { return instructions_.is_empty(); } |
- |
- ZoneList<AstNode*>* instructions() { return &instructions_; } |
- |
- virtual void AddPredecessor(Node* predecessor) { |
- ASSERT(predecessor_ == NULL && predecessor != NULL); |
- predecessor_ = predecessor; |
- } |
- |
- virtual void AddSuccessor(Node* successor) { |
- ASSERT(successor_ == NULL && successor != NULL); |
- successor_ = successor; |
- } |
- |
+ // Add an instruction to the end of this block. The block must be "open" |
+ // by not having a successor yet. |
void AddInstruction(AstNode* instruction) { |
+ ASSERT(!HasSuccessor() && instruction != NULL); |
instructions_.Add(instruction); |
} |
- virtual void Traverse(bool mark, |
- ZoneList<Node*>* preorder, |
- ZoneList<Node*>* postorder); |
- |
- virtual void InitializeReachingDefinitions(int definition_count, |
- List<BitVector*>* variables, |
- WorkList<Node>* worklist, |
- bool mark); |
- virtual void ComputeRDOut(BitVector* result); |
- virtual void UpdateRDIn(WorkList<Node>* worklist, bool mark); |
- virtual void PropagateReachingDefinitions(List<BitVector*>* variables); |
- |
- virtual void MarkCriticalInstructions( |
- List<AstNode*>* stack, |
- ZoneList<Expression*>* body_definitions, |
- int variable_count); |
+ // Perform a depth-first traversal of graph rooted at this node, |
+ // accumulating pre- and postorder traversal orders. Visited nodes are |
+ // marked with mark. |
+ void BuildTraversalOrder(ZoneList<BasicBlock*>* preorder, |
+ ZoneList<BasicBlock*>* postorder, |
+ bool mark); |
+ bool GetMark() { return mark_; } |
#ifdef DEBUG |
- virtual void PrintText(); |
+ // In debug mode, blocks are numbered in reverse postorder to help with |
+ // printing. |
+ int number() { return number_; } |
+ void set_number(int n) { number_ = n; } |
+ |
+ // Print a basic block, given the number of the first instruction. |
+ // Returns the next number after the number of the last instruction. |
+ int PrintAsText(int instruction_number); |
#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) {} |
- |
- virtual bool IsBranchNode() { return true; } |
- |
- virtual void AddPredecessor(Node* predecessor) { |
- ASSERT(predecessor_ == NULL && predecessor != NULL); |
- predecessor_ = predecessor; |
- } |
- |
- virtual void AddSuccessor(Node* successor) { |
- ASSERT(successor1_ == NULL && successor != NULL); |
- if (successor0_ == NULL) { |
- successor0_ = successor; |
+ // Add a given basic block as successor to this block. This function does |
+ // not add this block as a predecessor of the given block so as to avoid |
+ // circularity. |
+ void AddSuccessor(BasicBlock* successor) { |
+ ASSERT(right_successor_ == NULL && successor != NULL); |
+ if (HasSuccessor()) { |
+ right_successor_ = successor; |
} else { |
- successor1_ = successor; |
+ left_successor_ = successor; |
} |
} |
- virtual void Traverse(bool mark, |
- ZoneList<Node*>* preorder, |
- ZoneList<Node*>* postorder); |
- |
- virtual void ComputeRDOut(BitVector* result); |
- virtual void UpdateRDIn(WorkList<Node>* worklist, bool mark); |
- |
-#ifdef DEBUG |
- virtual 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); |
- } |
- |
- virtual bool IsJoinNode() { return true; } |
- |
- virtual void AddPredecessor(Node* predecessor) { |
- ASSERT(predecessor != NULL); |
- predecessors_.Add(predecessor); |
- } |
- |
- virtual void AddSuccessor(Node* successor) { |
- ASSERT(successor_ == NULL && successor != NULL); |
- successor_ = successor; |
- } |
- |
- virtual void Traverse(bool mark, |
- ZoneList<Node*>* preorder, |
- ZoneList<Node*>* postorder); |
+ ZoneList<BasicBlock*> predecessors_; |
+ ZoneList<AstNode*> instructions_; |
fschneider
2010/03/29 13:49:59
We probably need an accessor for instructions_. Bu
|
+ BasicBlock* left_successor_; |
+ BasicBlock* right_successor_; |
- virtual void ComputeRDOut(BitVector* result); |
- virtual void UpdateRDIn(WorkList<Node>* worklist, bool mark); |
+ // Support for graph traversal. Before traversal, all nodes in the graph |
+ // have the same mark (true or false). Traversal marks already-visited |
+ // nodes with the opposite mark. After traversal, all nodes again have |
+ // the same mark. Traversal of the same graph is not reentrant. |
+ bool mark_; |
#ifdef DEBUG |
- virtual void PrintText(); |
+ int number_; |
#endif |
- private: |
- ZoneList<Node*> predecessors_; |
- Node* successor_; |
- |
- DISALLOW_COPY_AND_ASSIGN(JoinNode); |
+ DISALLOW_COPY_AND_ASSIGN(BasicBlock); |
}; |
-// 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 { |
+// A flow graph has distinguished entry and exit blocks. The entry block is |
+// the only one with no predecessors and the exit block is the only one with |
+// no successors. |
+class FlowGraph: public ZoneObject { |
public: |
- static FlowGraph Empty() { |
- FlowGraph graph; |
- graph.entry_ = new BlockNode(); |
- graph.exit_ = graph.entry_; |
- return graph; |
+ FlowGraph(BasicBlock* entry, BasicBlock* exit) |
+ : entry_(entry), exit_(exit), preorder_(8), postorder_(8) { |
} |
- bool is_empty() const { |
- return entry_ == exit_ && BlockNode::cast(entry_)->is_empty(); |
- } |
- Node* entry() const { return entry_; } |
- Node* exit() const { return exit_; } |
- |
- // Add a single instruction to the end of this flowgraph. |
- void AppendInstruction(AstNode* instruction); |
- |
- // Add a single node to the end of this flow graph. |
- void AppendNode(Node* node); |
- |
- // Add a flow graph fragment to the end of this one. |
- void AppendGraph(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. |
- 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); |
+ ZoneList<BasicBlock*>* preorder() { return &preorder_; } |
+ ZoneList<BasicBlock*>* postorder() { return &postorder_; } |
#ifdef DEBUG |
- void PrintText(FunctionLiteral* fun, ZoneList<Node*>* postorder); |
+ void PrintAsText(Handle<String> name); |
#endif |
private: |
- FlowGraph() : entry_(NULL), exit_(NULL) {} |
- |
- Node* entry_; |
- Node* exit_; |
+ BasicBlock* entry_; |
+ BasicBlock* exit_; |
+ ZoneList<BasicBlock*> preorder_; |
+ ZoneList<BasicBlock*> postorder_; |
}; |
-// Construct a flow graph from a function literal. Build pre- and postorder |
-// traversal orders as a byproduct. |
+// The flow graph builder walks the AST adding reachable AST nodes to the |
+// flow graph as instructions. It remembers the entry and exit nodes of the |
+// graph, and keeps a pointer to the current block being constructed. |
class FlowGraphBuilder: public AstVisitor { |
public: |
- explicit FlowGraphBuilder(int variable_count) |
- : graph_(FlowGraph::Empty()), |
- global_exit_(NULL), |
- preorder_(4), |
- postorder_(4), |
- variable_count_(variable_count), |
- body_definitions_(4) { |
- } |
- |
- void Build(FunctionLiteral* lit); |
+ FlowGraphBuilder() {} |
- FlowGraph* graph() { return &graph_; } |
- ZoneList<Node*>* preorder() { return &preorder_; } |
- ZoneList<Node*>* postorder() { return &postorder_; } |
- ZoneList<Expression*>* body_definitions() { return &body_definitions_; } |
+ FlowGraph* Build(FunctionLiteral* lit); |
private: |
- ExitNode* global_exit() { return global_exit_; } |
- |
- // Helpers to allow tranforming the ast during flow graph construction. |
- void VisitStatements(ZoneList<Statement*>* stmts); |
- Statement* ProcessStatement(Statement* stmt); |
- |
// 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_; |
- |
- // The flow graph builder collects a list of explicit definitions |
- // (assignments and count operations) to stack-allocated variables to use |
- // for reaching definitions analysis. It does not count the implicit |
- // definition at function entry. AST node numbers in the AST are used to |
- // refer into this list. |
- int variable_count_; |
- ZoneList<Expression*> body_definitions_; |
+ BasicBlock* entry_; |
+ BasicBlock* exit_; |
+ BasicBlock* current_; |
DISALLOW_COPY_AND_ASSIGN(FlowGraphBuilder); |
}; |