Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(162)

Unified Diff: src/flow-graph.h

Issue 1530003: Rework flow graph construction. (Closed)
Patch Set: Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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);
};

Powered by Google App Engine
This is Rietveld 408576698