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

Unified Diff: src/flow-graph.h

Issue 1253009: Move flow graph and helper classes to their own file. (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
« no previous file with comments | « src/data-flow.cc ('k') | src/flow-graph.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/flow-graph.h
diff --git a/src/flow-graph.h b/src/flow-graph.h
new file mode 100644
index 0000000000000000000000000000000000000000..183b71d5b08082f068365f47519e276d615820fb
--- /dev/null
+++ b/src/flow-graph.h
@@ -0,0 +1,379 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_FLOW_GRAPH_H_
+#define V8_FLOW_GRAPH_H_
+
+#include "v8.h"
+
+#include "data-flow.h"
+#include "zone.h"
+
+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 {
+ public:
+ ExitNode() : predecessors_(4) {}
+
+ virtual bool IsExitNode() { return true; }
+
+ virtual void AddPredecessor(Node* predecessor) {
+ ASSERT(predecessor != NULL);
+ predecessors_.Add(predecessor);
+ }
+
+ 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;
+ }
+
+ void AddInstruction(AstNode* instruction) {
+ 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);
+
+#ifdef DEBUG
+ virtual 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) {}
+
+ 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;
+ } else {
+ successor1_ = 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);
+
+ virtual void ComputeRDOut(BitVector* result);
+ virtual void UpdateRDIn(WorkList<Node>* worklist, bool mark);
+
+#ifdef DEBUG
+ virtual void PrintText();
+#endif
+
+ private:
+ ZoneList<Node*> predecessors_;
+ Node* successor_;
+
+ DISALLOW_COPY_AND_ASSIGN(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:
+ static FlowGraph Empty() {
+ FlowGraph graph;
+ graph.entry_ = new BlockNode();
+ graph.exit_ = graph.entry_;
+ return graph;
+ }
+
+ 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);
+
+#ifdef DEBUG
+ void PrintText(FunctionLiteral* fun, ZoneList<Node*>* postorder);
+#endif
+
+ private:
+ FlowGraph() : entry_(NULL), exit_(NULL) {}
+
+ Node* entry_;
+ Node* exit_;
+};
+
+
+// Construct a flow graph from a function literal. Build pre- and postorder
+// traversal orders as a byproduct.
+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);
+
+ FlowGraph* graph() { return &graph_; }
+ ZoneList<Node*>* preorder() { return &preorder_; }
+ ZoneList<Node*>* postorder() { return &postorder_; }
+ ZoneList<Expression*>* body_definitions() { return &body_definitions_; }
+
+ 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_;
+
+ DISALLOW_COPY_AND_ASSIGN(FlowGraphBuilder);
+};
+
+
+} } // namespace v8::internal
+
+#endif // V8_FLOW_GRAPH_H_
« no previous file with comments | « src/data-flow.cc ('k') | src/flow-graph.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698