Chromium Code Reviews| 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); |
| }; |