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

Unified Diff: src/flow-graph.cc

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/flow-graph.h ('k') | tools/gyp/v8.gyp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/flow-graph.cc
diff --git a/src/flow-graph.cc b/src/flow-graph.cc
new file mode 100644
index 0000000000000000000000000000000000000000..bd9602f84054a426411444026889ab544892332a
--- /dev/null
+++ b/src/flow-graph.cc
@@ -0,0 +1,588 @@
+// 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.
+
+#include "flow-graph.h"
+
+namespace v8 {
+namespace internal {
+
+void FlowGraph::AppendInstruction(AstNode* instruction) {
+ // Add a (non-null) AstNode to the end of the graph fragment.
+ ASSERT(instruction != NULL);
+ if (exit()->IsExitNode()) return;
+ if (!exit()->IsBlockNode()) AppendNode(new BlockNode());
+ BlockNode::cast(exit())->AddInstruction(instruction);
+}
+
+
+void FlowGraph::AppendNode(Node* node) {
+ // Add a node to the end of the graph. An empty block is added to
+ // maintain edge-split form (that no join nodes or exit nodes as
+ // successors to branch nodes).
+ ASSERT(node != NULL);
+ if (exit()->IsExitNode()) return;
+ if (exit()->IsBranchNode() && (node->IsJoinNode() || node->IsExitNode())) {
+ AppendNode(new BlockNode());
+ }
+ exit()->AddSuccessor(node);
+ node->AddPredecessor(exit());
+ exit_ = node;
+}
+
+
+void FlowGraph::AppendGraph(FlowGraph* graph) {
+ // Add a flow graph fragment to the end of this one. An empty block is
+ // added to maintain edge-split form (that no join nodes or exit nodes as
+ // successors to branch nodes).
+ ASSERT(graph != NULL);
+ if (exit()->IsExitNode()) return;
+ Node* node = graph->entry();
+ if (exit()->IsBranchNode() && (node->IsJoinNode() || node->IsExitNode())) {
+ AppendNode(new BlockNode());
+ }
+ exit()->AddSuccessor(node);
+ node->AddPredecessor(exit());
+ exit_ = graph->exit();
+}
+
+
+void FlowGraph::Split(BranchNode* branch,
+ FlowGraph* left,
+ FlowGraph* right,
+ JoinNode* join) {
+ // Add the branch node, left flowgraph, join node.
+ AppendNode(branch);
+ AppendGraph(left);
+ AppendNode(join);
+
+ // Splice in the right flowgraph.
+ right->AppendNode(join);
+ branch->AddSuccessor(right->entry());
+ right->entry()->AddPredecessor(branch);
+}
+
+
+void FlowGraph::Loop(JoinNode* join,
+ FlowGraph* condition,
+ BranchNode* branch,
+ FlowGraph* body) {
+ // Add the join, condition and branch. Add join's predecessors in
+ // left-to-right order.
+ AppendNode(join);
+ body->AppendNode(join);
+ AppendGraph(condition);
+ AppendNode(branch);
+
+ // Splice in the body flowgraph.
+ branch->AddSuccessor(body->entry());
+ body->entry()->AddPredecessor(branch);
+}
+
+
+void ExitNode::Traverse(bool mark,
+ ZoneList<Node*>* preorder,
+ ZoneList<Node*>* postorder) {
+ preorder->Add(this);
+ postorder->Add(this);
+}
+
+
+void BlockNode::Traverse(bool mark,
+ ZoneList<Node*>* preorder,
+ ZoneList<Node*>* postorder) {
+ ASSERT(successor_ != NULL);
+ preorder->Add(this);
+ if (!successor_->IsMarkedWith(mark)) {
+ successor_->MarkWith(mark);
+ successor_->Traverse(mark, preorder, postorder);
+ }
+ postorder->Add(this);
+}
+
+
+void BranchNode::Traverse(bool mark,
+ ZoneList<Node*>* preorder,
+ ZoneList<Node*>* postorder) {
+ ASSERT(successor0_ != NULL && successor1_ != NULL);
+ preorder->Add(this);
+ if (!successor1_->IsMarkedWith(mark)) {
+ successor1_->MarkWith(mark);
+ successor1_->Traverse(mark, preorder, postorder);
+ }
+ if (!successor0_->IsMarkedWith(mark)) {
+ successor0_->MarkWith(mark);
+ successor0_->Traverse(mark, preorder, postorder);
+ }
+ postorder->Add(this);
+}
+
+
+void JoinNode::Traverse(bool mark,
+ ZoneList<Node*>* preorder,
+ ZoneList<Node*>* postorder) {
+ ASSERT(successor_ != NULL);
+ preorder->Add(this);
+ if (!successor_->IsMarkedWith(mark)) {
+ successor_->MarkWith(mark);
+ successor_->Traverse(mark, preorder, postorder);
+ }
+ postorder->Add(this);
+}
+
+
+void FlowGraphBuilder::Build(FunctionLiteral* lit) {
+ global_exit_ = new ExitNode();
+ VisitStatements(lit->body());
+
+ if (HasStackOverflow()) return;
+
+ // The graph can end with a branch node (if the function ended with a
+ // loop). Maintain edge-split form (no join nodes or exit nodes as
+ // successors to branch nodes).
+ if (graph_.exit()->IsBranchNode()) graph_.AppendNode(new BlockNode());
+ graph_.AppendNode(global_exit_);
+
+ // Build preorder and postorder traversal orders. All the nodes in
+ // the graph have the same mark flag. For the traversal, use that
+ // flag's negation. Traversal will flip all the flags.
+ bool mark = graph_.entry()->IsMarkedWith(false);
+ graph_.entry()->MarkWith(mark);
+ graph_.entry()->Traverse(mark, &preorder_, &postorder_);
+}
+
+
+// This function peels off one iteration of a for-loop. The return value
+// is either a block statement containing the peeled loop or NULL in case
+// there is a stack overflow.
+static Statement* PeelForLoop(ForStatement* stmt) {
+ // Mark this for-statement as processed.
+ stmt->set_peel_this_loop(false);
+
+ // Create new block containing the init statement of the for-loop and
+ // an if-statement containing the peeled iteration and the original
+ // loop without the init-statement.
+ Block* block = new Block(NULL, 2, false);
+ if (stmt->init() != NULL) {
+ Statement* init = stmt->init();
+ // The init statement gets the statement position of the for-loop
+ // to make debugging of peeled loops possible.
+ init->set_statement_pos(stmt->statement_pos());
+ block->AddStatement(init);
+ }
+
+ // Copy the condition.
+ CopyAstVisitor copy_visitor;
+ Expression* cond_copy = stmt->cond() != NULL
+ ? copy_visitor.DeepCopyExpr(stmt->cond())
+ : new Literal(Factory::true_value());
+ if (copy_visitor.HasStackOverflow()) return NULL;
+
+ // Construct a block with the peeled body and the rest of the for-loop.
+ Statement* body_copy = copy_visitor.DeepCopyStmt(stmt->body());
+ if (copy_visitor.HasStackOverflow()) return NULL;
+
+ Statement* next_copy = stmt->next() != NULL
+ ? copy_visitor.DeepCopyStmt(stmt->next())
+ : new EmptyStatement();
+ if (copy_visitor.HasStackOverflow()) return NULL;
+
+ Block* peeled_body = new Block(NULL, 3, false);
+ peeled_body->AddStatement(body_copy);
+ peeled_body->AddStatement(next_copy);
+ peeled_body->AddStatement(stmt);
+
+ // Remove the duplicated init statement from the for-statement.
+ stmt->set_init(NULL);
+
+ // Create new test at the top and add it to the newly created block.
+ IfStatement* test = new IfStatement(cond_copy,
+ peeled_body,
+ new EmptyStatement());
+ block->AddStatement(test);
+ return block;
+}
+
+
+void FlowGraphBuilder::VisitStatements(ZoneList<Statement*>* stmts) {
+ for (int i = 0, len = stmts->length(); i < len; i++) {
+ stmts->at(i) = ProcessStatement(stmts->at(i));
+ }
+}
+
+
+Statement* FlowGraphBuilder::ProcessStatement(Statement* stmt) {
+ if (FLAG_loop_peeling &&
+ stmt->AsForStatement() != NULL &&
+ stmt->AsForStatement()->peel_this_loop()) {
+ Statement* tmp_stmt = PeelForLoop(stmt->AsForStatement());
+ if (tmp_stmt == NULL) {
+ SetStackOverflow();
+ } else {
+ stmt = tmp_stmt;
+ }
+ }
+ Visit(stmt);
+ return stmt;
+}
+
+
+void FlowGraphBuilder::VisitDeclaration(Declaration* decl) {
+ UNREACHABLE();
+}
+
+
+void FlowGraphBuilder::VisitBlock(Block* stmt) {
+ VisitStatements(stmt->statements());
+}
+
+
+void FlowGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
+ Visit(stmt->expression());
+}
+
+
+void FlowGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
+ // Nothing to do.
+}
+
+
+void FlowGraphBuilder::VisitIfStatement(IfStatement* stmt) {
+ Visit(stmt->condition());
+
+ BranchNode* branch = new BranchNode();
+ FlowGraph original = graph_;
+ graph_ = FlowGraph::Empty();
+ stmt->set_then_statement(ProcessStatement(stmt->then_statement()));
+
+ FlowGraph left = graph_;
+ graph_ = FlowGraph::Empty();
+ stmt->set_else_statement(ProcessStatement(stmt->else_statement()));
+
+ if (HasStackOverflow()) return;
+ JoinNode* join = new JoinNode();
+ original.Split(branch, &left, &graph_, join);
+ graph_ = original;
+}
+
+
+void FlowGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) {
+ SetStackOverflow();
+}
+
+
+void FlowGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
+ SetStackOverflow();
+}
+
+
+void FlowGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
+ SetStackOverflow();
+}
+
+
+void FlowGraphBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) {
+ SetStackOverflow();
+}
+
+
+void FlowGraphBuilder::VisitWithExitStatement(WithExitStatement* stmt) {
+ SetStackOverflow();
+}
+
+
+void FlowGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
+ SetStackOverflow();
+}
+
+
+void FlowGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
+ SetStackOverflow();
+}
+
+
+void FlowGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
+ SetStackOverflow();
+}
+
+
+void FlowGraphBuilder::VisitForStatement(ForStatement* stmt) {
+ if (stmt->init() != NULL) stmt->set_init(ProcessStatement(stmt->init()));
+
+ JoinNode* join = new JoinNode();
+ FlowGraph original = graph_;
+ graph_ = FlowGraph::Empty();
+ if (stmt->cond() != NULL) Visit(stmt->cond());
+
+ BranchNode* branch = new BranchNode();
+ FlowGraph condition = graph_;
+ graph_ = FlowGraph::Empty();
+ stmt->set_body(ProcessStatement(stmt->body()));
+
+ if (stmt->next() != NULL) stmt->set_next(ProcessStatement(stmt->next()));
+
+ if (HasStackOverflow()) return;
+ original.Loop(join, &condition, branch, &graph_);
+ graph_ = original;
+}
+
+
+void FlowGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
+ SetStackOverflow();
+}
+
+
+void FlowGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
+ SetStackOverflow();
+}
+
+
+void FlowGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
+ SetStackOverflow();
+}
+
+
+void FlowGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
+ SetStackOverflow();
+}
+
+
+void FlowGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
+ SetStackOverflow();
+}
+
+
+void FlowGraphBuilder::VisitSharedFunctionInfoLiteral(
+ SharedFunctionInfoLiteral* expr) {
+ SetStackOverflow();
+}
+
+
+void FlowGraphBuilder::VisitConditional(Conditional* expr) {
+ SetStackOverflow();
+}
+
+
+void FlowGraphBuilder::VisitSlot(Slot* expr) {
+ UNREACHABLE();
+}
+
+
+void FlowGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
+ graph_.AppendInstruction(expr);
+}
+
+
+void FlowGraphBuilder::VisitLiteral(Literal* expr) {
+ graph_.AppendInstruction(expr);
+}
+
+
+void FlowGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
+ SetStackOverflow();
+}
+
+
+void FlowGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
+ SetStackOverflow();
+}
+
+
+void FlowGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
+ SetStackOverflow();
+}
+
+
+void FlowGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) {
+ SetStackOverflow();
+}
+
+
+void FlowGraphBuilder::VisitAssignment(Assignment* expr) {
+ Variable* var = expr->target()->AsVariableProxy()->AsVariable();
+ Property* prop = expr->target()->AsProperty();
+ // Left-hand side can be a variable or property (or reference error) but
+ // not both.
+ ASSERT(var == NULL || prop == NULL);
+ if (var != NULL) {
+ if (expr->is_compound()) Visit(expr->target());
+ Visit(expr->value());
+ if (var->IsStackAllocated()) {
+ // The first definition in the body is numbered n, where n is the
+ // number of parameters and stack-allocated locals.
+ expr->set_num(body_definitions_.length() + variable_count_);
+ body_definitions_.Add(expr);
+ }
+
+ } else if (prop != NULL) {
+ Visit(prop->obj());
+ if (!prop->key()->IsPropertyName()) Visit(prop->key());
+ Visit(expr->value());
+ }
+
+ if (HasStackOverflow()) return;
+ graph_.AppendInstruction(expr);
+}
+
+
+void FlowGraphBuilder::VisitThrow(Throw* expr) {
+ SetStackOverflow();
+}
+
+
+void FlowGraphBuilder::VisitProperty(Property* expr) {
+ Visit(expr->obj());
+ if (!expr->key()->IsPropertyName()) Visit(expr->key());
+
+ if (HasStackOverflow()) return;
+ graph_.AppendInstruction(expr);
+}
+
+
+void FlowGraphBuilder::VisitCall(Call* expr) {
+ Visit(expr->expression());
+ ZoneList<Expression*>* arguments = expr->arguments();
+ for (int i = 0, len = arguments->length(); i < len; i++) {
+ Visit(arguments->at(i));
+ }
+
+ if (HasStackOverflow()) return;
+ graph_.AppendInstruction(expr);
+}
+
+
+void FlowGraphBuilder::VisitCallNew(CallNew* expr) {
+ SetStackOverflow();
+}
+
+
+void FlowGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
+ SetStackOverflow();
+}
+
+
+void FlowGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
+ switch (expr->op()) {
+ case Token::NOT:
+ case Token::BIT_NOT:
+ case Token::DELETE:
+ case Token::TYPEOF:
+ case Token::VOID:
+ SetStackOverflow();
+ break;
+
+ case Token::ADD:
+ case Token::SUB:
+ Visit(expr->expression());
+ if (HasStackOverflow()) return;
+ graph_.AppendInstruction(expr);
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+}
+
+
+void FlowGraphBuilder::VisitCountOperation(CountOperation* expr) {
+ Visit(expr->expression());
+ Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
+ if (var != NULL && var->IsStackAllocated()) {
+ // The first definition in the body is numbered n, where n is the number
+ // of parameters and stack-allocated locals.
+ expr->set_num(body_definitions_.length() + variable_count_);
+ body_definitions_.Add(expr);
+ }
+
+ if (HasStackOverflow()) return;
+ graph_.AppendInstruction(expr);
+}
+
+
+void FlowGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
+ switch (expr->op()) {
+ case Token::COMMA:
+ case Token::OR:
+ case Token::AND:
+ SetStackOverflow();
+ break;
+
+ case Token::BIT_OR:
+ case Token::BIT_XOR:
+ case Token::BIT_AND:
+ case Token::SHL:
+ case Token::SHR:
+ case Token::ADD:
+ case Token::SUB:
+ case Token::MUL:
+ case Token::DIV:
+ case Token::MOD:
+ case Token::SAR:
+ Visit(expr->left());
+ Visit(expr->right());
+ if (HasStackOverflow()) return;
+ graph_.AppendInstruction(expr);
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+}
+
+
+void FlowGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
+ switch (expr->op()) {
+ case Token::EQ:
+ case Token::NE:
+ case Token::EQ_STRICT:
+ case Token::NE_STRICT:
+ case Token::INSTANCEOF:
+ case Token::IN:
+ SetStackOverflow();
+ break;
+
+ case Token::LT:
+ case Token::GT:
+ case Token::LTE:
+ case Token::GTE:
+ Visit(expr->left());
+ Visit(expr->right());
+ if (HasStackOverflow()) return;
+ graph_.AppendInstruction(expr);
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+}
+
+
+void FlowGraphBuilder::VisitThisFunction(ThisFunction* expr) {
+ SetStackOverflow();
+}
+
+
+} } // namespace v8::internal
« no previous file with comments | « src/flow-graph.h ('k') | tools/gyp/v8.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698