Index: src/flow-graph.cc |
=================================================================== |
--- src/flow-graph.cc (revision 5322) |
+++ src/flow-graph.cc (working copy) |
@@ -1,763 +0,0 @@ |
-// 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" |
-#include "scopes.h" |
- |
-namespace v8 { |
-namespace internal { |
- |
-void BasicBlock::BuildTraversalOrder(ZoneList<BasicBlock*>* preorder, |
- ZoneList<BasicBlock*>* postorder, |
- bool mark) { |
- if (mark_ == mark) return; |
- mark_ = mark; |
- preorder->Add(this); |
- if (right_successor_ != NULL) { |
- right_successor_->BuildTraversalOrder(preorder, postorder, mark); |
- } |
- if (left_successor_ != NULL) { |
- left_successor_->BuildTraversalOrder(preorder, postorder, mark); |
- } |
- postorder->Add(this); |
-} |
- |
- |
-FlowGraph* FlowGraphBuilder::Build(FunctionLiteral* lit) { |
- // Create new entry and exit nodes. These will not change during |
- // construction. |
- entry_ = new BasicBlock(NULL); |
- exit_ = new BasicBlock(NULL); |
- // Begin accumulating instructions in the entry block. |
- current_ = entry_; |
- |
- VisitDeclarations(lit->scope()->declarations()); |
- VisitStatements(lit->body()); |
- // In the event of stack overflow or failure to handle a syntactic |
- // construct, return an invalid flow graph. |
- if (HasStackOverflow()) return new FlowGraph(NULL, NULL); |
- |
- // If current is not the exit, add a link to the exit. |
- if (current_ != exit_) { |
- // If current already has a successor (i.e., will be a branch node) and |
- // if the exit already has a predecessor, insert an empty block to |
- // maintain edge split form. |
- if (current_->HasSuccessor() && exit_->HasPredecessor()) { |
- current_ = new BasicBlock(current_); |
- } |
- Literal* undefined = new Literal(Factory::undefined_value()); |
- current_->AddInstruction(new ReturnStatement(undefined)); |
- exit_->AddPredecessor(current_); |
- } |
- |
- FlowGraph* graph = new FlowGraph(entry_, exit_); |
- bool mark = !entry_->GetMark(); |
- entry_->BuildTraversalOrder(graph->preorder(), graph->postorder(), mark); |
- |
-#ifdef DEBUG |
- // Number the nodes in reverse postorder. |
- int n = 0; |
- for (int i = graph->postorder()->length() - 1; i >= 0; --i) { |
- graph->postorder()->at(i)->set_number(n++); |
- } |
-#endif |
- |
- return graph; |
-} |
- |
- |
-void FlowGraphBuilder::VisitDeclaration(Declaration* decl) { |
- Variable* var = decl->proxy()->AsVariable(); |
- Slot* slot = var->slot(); |
- // We allow only declarations that do not require code generation. |
- // The following all require code generation: global variables and |
- // functions, variables with slot type LOOKUP, declarations with |
- // mode CONST, and functions. |
- |
- if (var->is_global() || |
- (slot != NULL && slot->type() == Slot::LOOKUP) || |
- decl->mode() == Variable::CONST || |
- decl->fun() != NULL) { |
- // Here and in the rest of the flow graph builder we indicate an |
- // unsupported syntactic construct by setting the stack overflow |
- // flag on the visitor. This causes bailout of the visitor. |
- SetStackOverflow(); |
- } |
-} |
- |
- |
-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) { |
- // Build a diamond in the flow graph. First accumulate the instructions |
- // of the test in the current basic block. |
- Visit(stmt->condition()); |
- |
- // Remember the branch node and accumulate the true branch as its left |
- // successor. This relies on the successors being added left to right. |
- BasicBlock* branch = current_; |
- current_ = new BasicBlock(branch); |
- Visit(stmt->then_statement()); |
- |
- // Construct a join node and then accumulate the false branch in a fresh |
- // successor of the branch node. |
- BasicBlock* join = new BasicBlock(current_); |
- current_ = new BasicBlock(branch); |
- Visit(stmt->else_statement()); |
- join->AddPredecessor(current_); |
- |
- current_ = join; |
-} |
- |
- |
-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) { |
- // Build a loop in the flow graph. First accumulate the instructions of |
- // the initializer in the current basic block. |
- if (stmt->init() != NULL) Visit(stmt->init()); |
- |
- // Create a new basic block for the test. This will be the join node. |
- BasicBlock* join = new BasicBlock(current_); |
- current_ = join; |
- if (stmt->cond() != NULL) Visit(stmt->cond()); |
- |
- // The current node is the branch node. Create a new basic block to begin |
- // the body. |
- BasicBlock* branch = current_; |
- current_ = new BasicBlock(branch); |
- Visit(stmt->body()); |
- if (stmt->next() != NULL) Visit(stmt->next()); |
- |
- // Add the backward edge from the end of the body and continue with the |
- // false arm of the branch. |
- join->AddPredecessor(current_); |
- current_ = new BasicBlock(branch); |
-} |
- |
- |
-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) { |
- // Slots do not appear in the AST. |
- UNREACHABLE(); |
-} |
- |
- |
-void FlowGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
- current_->AddInstruction(expr); |
-} |
- |
- |
-void FlowGraphBuilder::VisitLiteral(Literal* expr) { |
- current_->AddInstruction(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) { |
- // There are three basic kinds of assignment: variable assignments, |
- // property assignments, and invalid left-hand sides (which are translated |
- // to "throw ReferenceError" by the parser). |
- Variable* var = expr->target()->AsVariableProxy()->AsVariable(); |
- Property* prop = expr->target()->AsProperty(); |
- ASSERT(var == NULL || prop == NULL); |
- if (var != NULL) { |
- if (expr->is_compound() && !expr->target()->IsTrivial()) { |
- Visit(expr->target()); |
- } |
- if (!expr->value()->IsTrivial()) Visit(expr->value()); |
- current_->AddInstruction(expr); |
- |
- } else if (prop != NULL) { |
- if (!prop->obj()->IsTrivial()) Visit(prop->obj()); |
- if (!prop->key()->IsPropertyName() && !prop->key()->IsTrivial()) { |
- Visit(prop->key()); |
- } |
- if (!expr->value()->IsTrivial()) Visit(expr->value()); |
- current_->AddInstruction(expr); |
- |
- } else { |
- Visit(expr->target()); |
- } |
-} |
- |
- |
-void FlowGraphBuilder::VisitThrow(Throw* expr) { |
- SetStackOverflow(); |
-} |
- |
- |
-void FlowGraphBuilder::VisitProperty(Property* expr) { |
- if (!expr->obj()->IsTrivial()) Visit(expr->obj()); |
- if (!expr->key()->IsPropertyName() && !expr->key()->IsTrivial()) { |
- Visit(expr->key()); |
- } |
- current_->AddInstruction(expr); |
-} |
- |
- |
-void FlowGraphBuilder::VisitCall(Call* expr) { |
- Visit(expr->expression()); |
- VisitExpressions(expr->arguments()); |
- current_->AddInstruction(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()); |
- current_->AddInstruction(expr); |
- break; |
- |
- default: |
- UNREACHABLE(); |
- } |
-} |
- |
- |
-void FlowGraphBuilder::VisitCountOperation(CountOperation* expr) { |
- Visit(expr->expression()); |
- current_->AddInstruction(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::SAR: |
- case Token::SHR: |
- case Token::ADD: |
- case Token::SUB: |
- case Token::MUL: |
- case Token::DIV: |
- case Token::MOD: |
- if (!expr->left()->IsTrivial()) Visit(expr->left()); |
- if (!expr->right()->IsTrivial()) Visit(expr->right()); |
- current_->AddInstruction(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: |
- if (!expr->left()->IsTrivial()) Visit(expr->left()); |
- if (!expr->right()->IsTrivial()) Visit(expr->right()); |
- current_->AddInstruction(expr); |
- break; |
- |
- default: |
- UNREACHABLE(); |
- } |
-} |
- |
- |
-void FlowGraphBuilder::VisitThisFunction(ThisFunction* expr) { |
- SetStackOverflow(); |
-} |
- |
- |
-#ifdef DEBUG |
- |
-// Print a textual representation of an instruction in a flow graph. |
-class InstructionPrinter: public AstVisitor { |
- public: |
- InstructionPrinter() {} |
- |
- private: |
- // Overridden from the base class. |
- virtual void VisitExpressions(ZoneList<Expression*>* exprs); |
- |
- // AST node visit functions. |
-#define DECLARE_VISIT(type) virtual void Visit##type(type* node); |
- AST_NODE_LIST(DECLARE_VISIT) |
-#undef DECLARE_VISIT |
- |
- DISALLOW_COPY_AND_ASSIGN(InstructionPrinter); |
-}; |
- |
- |
-static void PrintSubexpression(Expression* expr) { |
- if (!expr->IsTrivial()) { |
- PrintF("@%d", expr->num()); |
- } else if (expr->AsLiteral() != NULL) { |
- expr->AsLiteral()->handle()->Print(); |
- } else if (expr->AsVariableProxy() != NULL) { |
- PrintF("%s", *expr->AsVariableProxy()->name()->ToCString()); |
- } else { |
- UNREACHABLE(); |
- } |
-} |
- |
- |
-void InstructionPrinter::VisitExpressions(ZoneList<Expression*>* exprs) { |
- for (int i = 0; i < exprs->length(); ++i) { |
- if (i != 0) PrintF(", "); |
- PrintF("@%d", exprs->at(i)->num()); |
- } |
-} |
- |
- |
-// We only define printing functions for the node types that can occur as |
-// instructions in a flow graph. The rest are unreachable. |
-void InstructionPrinter::VisitDeclaration(Declaration* decl) { |
- UNREACHABLE(); |
-} |
- |
- |
-void InstructionPrinter::VisitBlock(Block* stmt) { |
- UNREACHABLE(); |
-} |
- |
- |
-void InstructionPrinter::VisitExpressionStatement(ExpressionStatement* stmt) { |
- UNREACHABLE(); |
-} |
- |
- |
-void InstructionPrinter::VisitEmptyStatement(EmptyStatement* stmt) { |
- UNREACHABLE(); |
-} |
- |
- |
-void InstructionPrinter::VisitIfStatement(IfStatement* stmt) { |
- UNREACHABLE(); |
-} |
- |
- |
-void InstructionPrinter::VisitContinueStatement(ContinueStatement* stmt) { |
- UNREACHABLE(); |
-} |
- |
- |
-void InstructionPrinter::VisitBreakStatement(BreakStatement* stmt) { |
- UNREACHABLE(); |
-} |
- |
- |
-void InstructionPrinter::VisitReturnStatement(ReturnStatement* stmt) { |
- PrintF("return "); |
- PrintSubexpression(stmt->expression()); |
-} |
- |
- |
-void InstructionPrinter::VisitWithEnterStatement(WithEnterStatement* stmt) { |
- UNREACHABLE(); |
-} |
- |
- |
-void InstructionPrinter::VisitWithExitStatement(WithExitStatement* stmt) { |
- UNREACHABLE(); |
-} |
- |
- |
-void InstructionPrinter::VisitSwitchStatement(SwitchStatement* stmt) { |
- UNREACHABLE(); |
-} |
- |
- |
-void InstructionPrinter::VisitDoWhileStatement(DoWhileStatement* stmt) { |
- UNREACHABLE(); |
-} |
- |
- |
-void InstructionPrinter::VisitWhileStatement(WhileStatement* stmt) { |
- UNREACHABLE(); |
-} |
- |
- |
-void InstructionPrinter::VisitForStatement(ForStatement* stmt) { |
- UNREACHABLE(); |
-} |
- |
- |
-void InstructionPrinter::VisitForInStatement(ForInStatement* stmt) { |
- UNREACHABLE(); |
-} |
- |
- |
-void InstructionPrinter::VisitTryCatchStatement(TryCatchStatement* stmt) { |
- UNREACHABLE(); |
-} |
- |
- |
-void InstructionPrinter::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
- UNREACHABLE(); |
-} |
- |
- |
-void InstructionPrinter::VisitDebuggerStatement(DebuggerStatement* stmt) { |
- UNREACHABLE(); |
-} |
- |
- |
-void InstructionPrinter::VisitFunctionLiteral(FunctionLiteral* expr) { |
- UNREACHABLE(); |
-} |
- |
- |
-void InstructionPrinter::VisitSharedFunctionInfoLiteral( |
- SharedFunctionInfoLiteral* expr) { |
- UNREACHABLE(); |
-} |
- |
- |
-void InstructionPrinter::VisitConditional(Conditional* expr) { |
- UNREACHABLE(); |
-} |
- |
- |
-void InstructionPrinter::VisitSlot(Slot* expr) { |
- UNREACHABLE(); |
-} |
- |
- |
-void InstructionPrinter::VisitVariableProxy(VariableProxy* expr) { |
- Variable* var = expr->AsVariable(); |
- if (var != NULL) { |
- PrintF("%s", *var->name()->ToCString()); |
- } else { |
- ASSERT(expr->AsProperty() != NULL); |
- Visit(expr->AsProperty()); |
- } |
-} |
- |
- |
-void InstructionPrinter::VisitLiteral(Literal* expr) { |
- expr->handle()->Print(); |
-} |
- |
- |
-void InstructionPrinter::VisitRegExpLiteral(RegExpLiteral* expr) { |
- UNREACHABLE(); |
-} |
- |
- |
-void InstructionPrinter::VisitObjectLiteral(ObjectLiteral* expr) { |
- UNREACHABLE(); |
-} |
- |
- |
-void InstructionPrinter::VisitArrayLiteral(ArrayLiteral* expr) { |
- UNREACHABLE(); |
-} |
- |
- |
-void InstructionPrinter::VisitCatchExtensionObject( |
- CatchExtensionObject* expr) { |
- UNREACHABLE(); |
-} |
- |
- |
-void InstructionPrinter::VisitAssignment(Assignment* expr) { |
- Variable* var = expr->target()->AsVariableProxy()->AsVariable(); |
- Property* prop = expr->target()->AsProperty(); |
- |
- // Print the left-hand side. |
- Visit(expr->target()); |
- if (var == NULL && prop == NULL) return; // Throw reference error. |
- PrintF(" = "); |
- // For compound assignments, print the left-hand side again and the |
- // corresponding binary operator. |
- if (expr->is_compound()) { |
- PrintSubexpression(expr->target()); |
- PrintF(" %s ", Token::String(expr->binary_op())); |
- } |
- |
- // Print the right-hand side. |
- PrintSubexpression(expr->value()); |
-} |
- |
- |
-void InstructionPrinter::VisitThrow(Throw* expr) { |
- UNREACHABLE(); |
-} |
- |
- |
-void InstructionPrinter::VisitProperty(Property* expr) { |
- PrintSubexpression(expr->obj()); |
- if (expr->key()->IsPropertyName()) { |
- PrintF("."); |
- ASSERT(expr->key()->AsLiteral() != NULL); |
- expr->key()->AsLiteral()->handle()->Print(); |
- } else { |
- PrintF("["); |
- PrintSubexpression(expr->key()); |
- PrintF("]"); |
- } |
-} |
- |
- |
-void InstructionPrinter::VisitCall(Call* expr) { |
- PrintF("@%d(", expr->expression()->num()); |
- VisitExpressions(expr->arguments()); |
- PrintF(")"); |
-} |
- |
- |
-void InstructionPrinter::VisitCallNew(CallNew* expr) { |
- UNREACHABLE(); |
-} |
- |
- |
-void InstructionPrinter::VisitCallRuntime(CallRuntime* expr) { |
- UNREACHABLE(); |
-} |
- |
- |
-void InstructionPrinter::VisitUnaryOperation(UnaryOperation* expr) { |
- PrintF("%s(@%d)", Token::String(expr->op()), expr->expression()->num()); |
-} |
- |
- |
-void InstructionPrinter::VisitCountOperation(CountOperation* expr) { |
- if (expr->is_prefix()) { |
- PrintF("%s@%d", Token::String(expr->op()), expr->expression()->num()); |
- } else { |
- PrintF("@%d%s", expr->expression()->num(), Token::String(expr->op())); |
- } |
-} |
- |
- |
-void InstructionPrinter::VisitBinaryOperation(BinaryOperation* expr) { |
- PrintSubexpression(expr->left()); |
- PrintF(" %s ", Token::String(expr->op())); |
- PrintSubexpression(expr->right()); |
-} |
- |
- |
-void InstructionPrinter::VisitCompareOperation(CompareOperation* expr) { |
- PrintSubexpression(expr->left()); |
- PrintF(" %s ", Token::String(expr->op())); |
- PrintSubexpression(expr->right()); |
-} |
- |
- |
-void InstructionPrinter::VisitThisFunction(ThisFunction* expr) { |
- UNREACHABLE(); |
-} |
- |
- |
-int BasicBlock::PrintAsText(int instruction_number) { |
- // Print a label for all blocks except the entry. |
- if (HasPredecessor()) { |
- PrintF("L%d:", number()); |
- } |
- |
- // Number and print the instructions. Since AST child nodes are visited |
- // before their parents, the parent nodes can refer to them by number. |
- InstructionPrinter printer; |
- for (int i = 0; i < instructions_.length(); ++i) { |
- PrintF("\n%d ", instruction_number); |
- instructions_[i]->set_num(instruction_number++); |
- instructions_[i]->Accept(&printer); |
- } |
- |
- // If this is the exit, print "exit". If there is a single successor, |
- // print "goto" successor on a separate line. If there are two |
- // successors, print "goto" successor on the same line as the last |
- // instruction in the block. There is a blank line between blocks (and |
- // after the last one). |
- if (left_successor_ == NULL) { |
- PrintF("\nexit\n\n"); |
- } else if (right_successor_ == NULL) { |
- PrintF("\ngoto L%d\n\n", left_successor_->number()); |
- } else { |
- PrintF(", goto (L%d, L%d)\n\n", |
- left_successor_->number(), |
- right_successor_->number()); |
- } |
- |
- return instruction_number; |
-} |
- |
- |
-void FlowGraph::PrintAsText(Handle<String> name) { |
- PrintF("\n==== name = \"%s\" ====\n", *name->ToCString()); |
- // Print nodes in reverse postorder. Note that AST node numbers are used |
- // during printing of instructions and thus their current values are |
- // destroyed. |
- int number = 0; |
- for (int i = postorder_.length() - 1; i >= 0; --i) { |
- number = postorder_[i]->PrintAsText(number); |
- } |
-} |
- |
-#endif // DEBUG |
- |
- |
-} } // namespace v8::internal |