| 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
|
|
|