| Index: src/cfg.cc
|
| ===================================================================
|
| --- src/cfg.cc (revision 2994)
|
| +++ src/cfg.cc (working copy)
|
| @@ -1,758 +0,0 @@
|
| -// Copyright 2009 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 "v8.h"
|
| -
|
| -#include "bootstrapper.h"
|
| -#include "cfg.h"
|
| -#include "scopeinfo.h"
|
| -#include "scopes.h"
|
| -
|
| -namespace v8 {
|
| -namespace internal {
|
| -
|
| -
|
| -CfgGlobals* CfgGlobals::top_ = NULL;
|
| -
|
| -
|
| -CfgGlobals::CfgGlobals(FunctionLiteral* fun)
|
| - : global_fun_(fun),
|
| - global_exit_(new ExitNode()),
|
| - nowhere_(new Nowhere()),
|
| -#ifdef DEBUG
|
| - node_counter_(0),
|
| - temp_counter_(0),
|
| -#endif
|
| - previous_(top_) {
|
| - top_ = this;
|
| -}
|
| -
|
| -
|
| -#define BAILOUT(reason) \
|
| - do { return NULL; } while (false)
|
| -
|
| -Cfg* Cfg::Build() {
|
| - FunctionLiteral* fun = CfgGlobals::current()->fun();
|
| - if (fun->scope()->num_heap_slots() > 0) {
|
| - BAILOUT("function has context slots");
|
| - }
|
| - if (fun->scope()->num_stack_slots() > kBitsPerPointer) {
|
| - BAILOUT("function has too many locals");
|
| - }
|
| - if (fun->scope()->num_parameters() > kBitsPerPointer - 1) {
|
| - BAILOUT("function has too many parameters");
|
| - }
|
| - if (fun->scope()->arguments() != NULL) {
|
| - BAILOUT("function uses .arguments");
|
| - }
|
| -
|
| - ZoneList<Statement*>* body = fun->body();
|
| - if (body->is_empty()) {
|
| - BAILOUT("empty function body");
|
| - }
|
| -
|
| - StatementCfgBuilder builder;
|
| - builder.VisitStatements(body);
|
| - Cfg* graph = builder.graph();
|
| - if (graph == NULL) {
|
| - BAILOUT("unsupported statement type");
|
| - }
|
| - if (graph->is_empty()) {
|
| - BAILOUT("function body produces empty cfg");
|
| - }
|
| - if (graph->has_exit()) {
|
| - BAILOUT("control path without explicit return");
|
| - }
|
| - graph->PrependEntryNode();
|
| - return graph;
|
| -}
|
| -
|
| -#undef BAILOUT
|
| -
|
| -
|
| -void Cfg::PrependEntryNode() {
|
| - ASSERT(!is_empty());
|
| - entry_ = new EntryNode(InstructionBlock::cast(entry()));
|
| -}
|
| -
|
| -
|
| -void Cfg::Append(Instruction* instr) {
|
| - ASSERT(is_empty() || has_exit());
|
| - if (is_empty()) {
|
| - entry_ = exit_ = new InstructionBlock();
|
| - }
|
| - InstructionBlock::cast(exit_)->Append(instr);
|
| -}
|
| -
|
| -
|
| -void Cfg::AppendReturnInstruction(Value* value) {
|
| - Append(new ReturnInstr(value));
|
| - ExitNode* global_exit = CfgGlobals::current()->exit();
|
| - InstructionBlock::cast(exit_)->set_successor(global_exit);
|
| - exit_ = NULL;
|
| -}
|
| -
|
| -
|
| -void Cfg::Concatenate(Cfg* other) {
|
| - ASSERT(is_empty() || has_exit());
|
| - if (other->is_empty()) return;
|
| -
|
| - if (is_empty()) {
|
| - entry_ = other->entry();
|
| - exit_ = other->exit();
|
| - } else {
|
| - // We have a pair of nonempty fragments and this has an available exit.
|
| - // Destructively glue the fragments together.
|
| - InstructionBlock* first = InstructionBlock::cast(exit_);
|
| - InstructionBlock* second = InstructionBlock::cast(other->entry());
|
| - first->instructions()->AddAll(*second->instructions());
|
| - if (second->successor() != NULL) {
|
| - first->set_successor(second->successor());
|
| - exit_ = other->exit();
|
| - }
|
| - }
|
| -}
|
| -
|
| -
|
| -void InstructionBlock::Unmark() {
|
| - if (is_marked_) {
|
| - is_marked_ = false;
|
| - successor_->Unmark();
|
| - }
|
| -}
|
| -
|
| -
|
| -void EntryNode::Unmark() {
|
| - if (is_marked_) {
|
| - is_marked_ = false;
|
| - successor_->Unmark();
|
| - }
|
| -}
|
| -
|
| -
|
| -void ExitNode::Unmark() {
|
| - is_marked_ = false;
|
| -}
|
| -
|
| -
|
| -Handle<Code> Cfg::Compile(Handle<Script> script) {
|
| - const int kInitialBufferSize = 4 * KB;
|
| - MacroAssembler* masm = new MacroAssembler(NULL, kInitialBufferSize);
|
| - entry()->Compile(masm);
|
| - entry()->Unmark();
|
| - CodeDesc desc;
|
| - masm->GetCode(&desc);
|
| - FunctionLiteral* fun = CfgGlobals::current()->fun();
|
| - ZoneScopeInfo info(fun->scope());
|
| - InLoopFlag in_loop = fun->loop_nesting() ? IN_LOOP : NOT_IN_LOOP;
|
| - Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, in_loop);
|
| - Handle<Code> code = Factory::NewCode(desc, &info, flags, masm->CodeObject());
|
| -
|
| - // Add unresolved entries in the code to the fixup list.
|
| - Bootstrapper::AddFixup(*code, masm);
|
| -
|
| -#ifdef ENABLE_DISASSEMBLER
|
| - if (FLAG_print_code) {
|
| - // Print the source code if available.
|
| - if (!script->IsUndefined() && !script->source()->IsUndefined()) {
|
| - PrintF("--- Raw source ---\n");
|
| - StringInputBuffer stream(String::cast(script->source()));
|
| - stream.Seek(fun->start_position());
|
| - // fun->end_position() points to the last character in the
|
| - // stream. We need to compensate by adding one to calculate the
|
| - // length.
|
| - int source_len = fun->end_position() - fun->start_position() + 1;
|
| - for (int i = 0; i < source_len; i++) {
|
| - if (stream.has_more()) PrintF("%c", stream.GetNext());
|
| - }
|
| - PrintF("\n\n");
|
| - }
|
| - PrintF("--- Code ---\n");
|
| - code->Disassemble(*fun->name()->ToCString());
|
| - }
|
| -#endif
|
| -
|
| - return code;
|
| -}
|
| -
|
| -
|
| -void ZeroOperandInstruction::FastAllocate(TempLocation* temp) {
|
| - temp->set_where(TempLocation::STACK);
|
| -}
|
| -
|
| -
|
| -void OneOperandInstruction::FastAllocate(TempLocation* temp) {
|
| - temp->set_where((temp == value_)
|
| - ? TempLocation::ACCUMULATOR
|
| - : TempLocation::STACK);
|
| -}
|
| -
|
| -
|
| -void TwoOperandInstruction::FastAllocate(TempLocation* temp) {
|
| - temp->set_where((temp == value0_ || temp == value1_)
|
| - ? TempLocation::ACCUMULATOR
|
| - : TempLocation::STACK);
|
| -}
|
| -
|
| -
|
| -void PositionInstr::Compile(MacroAssembler* masm) {
|
| - if (FLAG_debug_info && pos_ != RelocInfo::kNoPosition) {
|
| - masm->RecordStatementPosition(pos_);
|
| - masm->RecordPosition(pos_);
|
| - }
|
| -}
|
| -
|
| -
|
| -void MoveInstr::Compile(MacroAssembler* masm) {
|
| - location()->Move(masm, value());
|
| -}
|
| -
|
| -
|
| -// The expression builder should not be used for declarations or statements.
|
| -void ExpressionCfgBuilder::VisitDeclaration(Declaration* decl) {
|
| - UNREACHABLE();
|
| -}
|
| -
|
| -#define DEFINE_VISIT(type) \
|
| - void ExpressionCfgBuilder::Visit##type(type* stmt) { UNREACHABLE(); }
|
| -STATEMENT_NODE_LIST(DEFINE_VISIT)
|
| -#undef DEFINE_VISIT
|
| -
|
| -
|
| -// Macros (temporarily) handling unsupported expression types.
|
| -#define BAILOUT(reason) \
|
| - do { \
|
| - graph_ = NULL; \
|
| - return; \
|
| - } while (false)
|
| -
|
| -void ExpressionCfgBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
|
| - BAILOUT("FunctionLiteral");
|
| -}
|
| -
|
| -
|
| -void ExpressionCfgBuilder::VisitFunctionBoilerplateLiteral(
|
| - FunctionBoilerplateLiteral* expr) {
|
| - BAILOUT("FunctionBoilerplateLiteral");
|
| -}
|
| -
|
| -
|
| -void ExpressionCfgBuilder::VisitConditional(Conditional* expr) {
|
| - BAILOUT("Conditional");
|
| -}
|
| -
|
| -
|
| -void ExpressionCfgBuilder::VisitSlot(Slot* expr) {
|
| - BAILOUT("Slot");
|
| -}
|
| -
|
| -
|
| -void ExpressionCfgBuilder::VisitVariableProxy(VariableProxy* expr) {
|
| - Expression* rewrite = expr->var()->rewrite();
|
| - if (rewrite == NULL || rewrite->AsSlot() == NULL) {
|
| - BAILOUT("unsupported variable (not a slot)");
|
| - }
|
| - Slot* slot = rewrite->AsSlot();
|
| - if (slot->type() != Slot::PARAMETER && slot->type() != Slot::LOCAL) {
|
| - BAILOUT("unsupported slot type (not a parameter or local)");
|
| - }
|
| - // Ignore the passed destination.
|
| - value_ = new SlotLocation(slot->type(), slot->index());
|
| -}
|
| -
|
| -
|
| -void ExpressionCfgBuilder::VisitLiteral(Literal* expr) {
|
| - // Ignore the passed destination.
|
| - value_ = new Constant(expr->handle());
|
| -}
|
| -
|
| -
|
| -void ExpressionCfgBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
|
| - BAILOUT("RegExpLiteral");
|
| -}
|
| -
|
| -
|
| -void ExpressionCfgBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
|
| - BAILOUT("ObjectLiteral");
|
| -}
|
| -
|
| -
|
| -void ExpressionCfgBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
|
| - BAILOUT("ArrayLiteral");
|
| -}
|
| -
|
| -
|
| -void ExpressionCfgBuilder::VisitCatchExtensionObject(
|
| - CatchExtensionObject* expr) {
|
| - BAILOUT("CatchExtensionObject");
|
| -}
|
| -
|
| -
|
| -void ExpressionCfgBuilder::VisitAssignment(Assignment* expr) {
|
| - if (expr->op() != Token::ASSIGN && expr->op() != Token::INIT_VAR) {
|
| - BAILOUT("unsupported compound assignment");
|
| - }
|
| - Expression* lhs = expr->target();
|
| - if (lhs->AsProperty() != NULL) {
|
| - BAILOUT("unsupported property assignment");
|
| - }
|
| -
|
| - Variable* var = lhs->AsVariableProxy()->AsVariable();
|
| - if (var == NULL) {
|
| - BAILOUT("unsupported invalid left-hand side");
|
| - }
|
| - if (var->is_global()) {
|
| - BAILOUT("unsupported global variable");
|
| - }
|
| - Slot* slot = var->slot();
|
| - ASSERT(slot != NULL);
|
| - if (slot->type() != Slot::PARAMETER && slot->type() != Slot::LOCAL) {
|
| - BAILOUT("unsupported slot lhs (not a parameter or local)");
|
| - }
|
| -
|
| - // Parameter and local slot assignments.
|
| - ExpressionCfgBuilder builder;
|
| - SlotLocation* loc = new SlotLocation(slot->type(), slot->index());
|
| - builder.Build(expr->value(), loc);
|
| - if (builder.graph() == NULL) {
|
| - BAILOUT("unsupported expression in assignment");
|
| - }
|
| - // If the expression did not come back in the slot location, append
|
| - // a move to the CFG.
|
| - graph_ = builder.graph();
|
| - if (builder.value() != loc) {
|
| - graph()->Append(new MoveInstr(loc, builder.value()));
|
| - }
|
| - // Record the assignment.
|
| - assigned_vars_.AddElement(loc);
|
| - // Ignore the destination passed to us.
|
| - value_ = loc;
|
| -}
|
| -
|
| -
|
| -void ExpressionCfgBuilder::VisitThrow(Throw* expr) {
|
| - BAILOUT("Throw");
|
| -}
|
| -
|
| -
|
| -void ExpressionCfgBuilder::VisitProperty(Property* expr) {
|
| - ExpressionCfgBuilder object, key;
|
| - object.Build(expr->obj(), NULL);
|
| - if (object.graph() == NULL) {
|
| - BAILOUT("unsupported object subexpression in propload");
|
| - }
|
| - key.Build(expr->key(), NULL);
|
| - if (key.graph() == NULL) {
|
| - BAILOUT("unsupported key subexpression in propload");
|
| - }
|
| -
|
| - if (destination_ == NULL) destination_ = new TempLocation();
|
| -
|
| - graph_ = object.graph();
|
| - // Insert a move to a fresh temporary if the object value is in a slot
|
| - // that's assigned in the key.
|
| - Location* temp = NULL;
|
| - if (object.value()->is_slot() &&
|
| - key.assigned_vars()->Contains(SlotLocation::cast(object.value()))) {
|
| - temp = new TempLocation();
|
| - graph()->Append(new MoveInstr(temp, object.value()));
|
| - }
|
| - graph()->Concatenate(key.graph());
|
| - graph()->Append(new PropLoadInstr(destination_,
|
| - temp == NULL ? object.value() : temp,
|
| - key.value()));
|
| -
|
| - assigned_vars_ = *object.assigned_vars();
|
| - assigned_vars()->Union(key.assigned_vars());
|
| -
|
| - value_ = destination_;
|
| -}
|
| -
|
| -
|
| -void ExpressionCfgBuilder::VisitCall(Call* expr) {
|
| - BAILOUT("Call");
|
| -}
|
| -
|
| -
|
| -void ExpressionCfgBuilder::VisitCallNew(CallNew* expr) {
|
| - BAILOUT("CallNew");
|
| -}
|
| -
|
| -
|
| -void ExpressionCfgBuilder::VisitCallRuntime(CallRuntime* expr) {
|
| - BAILOUT("CallRuntime");
|
| -}
|
| -
|
| -
|
| -void ExpressionCfgBuilder::VisitUnaryOperation(UnaryOperation* expr) {
|
| - BAILOUT("UnaryOperation");
|
| -}
|
| -
|
| -
|
| -void ExpressionCfgBuilder::VisitCountOperation(CountOperation* expr) {
|
| - BAILOUT("CountOperation");
|
| -}
|
| -
|
| -
|
| -void ExpressionCfgBuilder::VisitBinaryOperation(BinaryOperation* expr) {
|
| - Token::Value op = expr->op();
|
| - switch (op) {
|
| - case Token::COMMA:
|
| - case Token::OR:
|
| - case Token::AND:
|
| - BAILOUT("unsupported binary operation");
|
| -
|
| - 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: {
|
| - ExpressionCfgBuilder left, right;
|
| - left.Build(expr->left(), NULL);
|
| - if (left.graph() == NULL) {
|
| - BAILOUT("unsupported left subexpression in binop");
|
| - }
|
| - right.Build(expr->right(), NULL);
|
| - if (right.graph() == NULL) {
|
| - BAILOUT("unsupported right subexpression in binop");
|
| - }
|
| -
|
| - if (destination_ == NULL) destination_ = new TempLocation();
|
| -
|
| - graph_ = left.graph();
|
| - // Insert a move to a fresh temporary if the left value is in a
|
| - // slot that's assigned on the right.
|
| - Location* temp = NULL;
|
| - if (left.value()->is_slot() &&
|
| - right.assigned_vars()->Contains(SlotLocation::cast(left.value()))) {
|
| - temp = new TempLocation();
|
| - graph()->Append(new MoveInstr(temp, left.value()));
|
| - }
|
| - graph()->Concatenate(right.graph());
|
| - graph()->Append(new BinaryOpInstr(destination_, op,
|
| - temp == NULL ? left.value() : temp,
|
| - right.value()));
|
| -
|
| - assigned_vars_ = *left.assigned_vars();
|
| - assigned_vars()->Union(right.assigned_vars());
|
| -
|
| - value_ = destination_;
|
| - return;
|
| - }
|
| -
|
| - default:
|
| - UNREACHABLE();
|
| - }
|
| -}
|
| -
|
| -
|
| -void ExpressionCfgBuilder::VisitCompareOperation(CompareOperation* expr) {
|
| - BAILOUT("CompareOperation");
|
| -}
|
| -
|
| -
|
| -void ExpressionCfgBuilder::VisitThisFunction(ThisFunction* expr) {
|
| - BAILOUT("ThisFunction");
|
| -}
|
| -
|
| -#undef BAILOUT
|
| -
|
| -
|
| -// Macros (temporarily) handling unsupported statement types.
|
| -#define BAILOUT(reason) \
|
| - do { \
|
| - graph_ = NULL; \
|
| - return; \
|
| - } while (false)
|
| -
|
| -#define CHECK_BAILOUT() \
|
| - if (graph() == NULL) { return; } else {}
|
| -
|
| -void StatementCfgBuilder::VisitStatements(ZoneList<Statement*>* stmts) {
|
| - for (int i = 0, len = stmts->length(); i < len; i++) {
|
| - Visit(stmts->at(i));
|
| - CHECK_BAILOUT();
|
| - if (!graph()->has_exit()) return;
|
| - }
|
| -}
|
| -
|
| -
|
| -// The statement builder should not be used for declarations or expressions.
|
| -void StatementCfgBuilder::VisitDeclaration(Declaration* decl) { UNREACHABLE(); }
|
| -
|
| -#define DEFINE_VISIT(type) \
|
| - void StatementCfgBuilder::Visit##type(type* expr) { UNREACHABLE(); }
|
| -EXPRESSION_NODE_LIST(DEFINE_VISIT)
|
| -#undef DEFINE_VISIT
|
| -
|
| -
|
| -void StatementCfgBuilder::VisitBlock(Block* stmt) {
|
| - VisitStatements(stmt->statements());
|
| -}
|
| -
|
| -
|
| -void StatementCfgBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
|
| - ExpressionCfgBuilder builder;
|
| - builder.Build(stmt->expression(), CfgGlobals::current()->nowhere());
|
| - if (builder.graph() == NULL) {
|
| - BAILOUT("unsupported expression in expression statement");
|
| - }
|
| - graph()->Append(new PositionInstr(stmt->statement_pos()));
|
| - graph()->Concatenate(builder.graph());
|
| -}
|
| -
|
| -
|
| -void StatementCfgBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
|
| - // Nothing to do.
|
| -}
|
| -
|
| -
|
| -void StatementCfgBuilder::VisitIfStatement(IfStatement* stmt) {
|
| - BAILOUT("IfStatement");
|
| -}
|
| -
|
| -
|
| -void StatementCfgBuilder::VisitContinueStatement(ContinueStatement* stmt) {
|
| - BAILOUT("ContinueStatement");
|
| -}
|
| -
|
| -
|
| -void StatementCfgBuilder::VisitBreakStatement(BreakStatement* stmt) {
|
| - BAILOUT("BreakStatement");
|
| -}
|
| -
|
| -
|
| -void StatementCfgBuilder::VisitReturnStatement(ReturnStatement* stmt) {
|
| - ExpressionCfgBuilder builder;
|
| - builder.Build(stmt->expression(), NULL);
|
| - if (builder.graph() == NULL) {
|
| - BAILOUT("unsupported expression in return statement");
|
| - }
|
| -
|
| - graph()->Append(new PositionInstr(stmt->statement_pos()));
|
| - graph()->Concatenate(builder.graph());
|
| - graph()->AppendReturnInstruction(builder.value());
|
| -}
|
| -
|
| -
|
| -void StatementCfgBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) {
|
| - BAILOUT("WithEnterStatement");
|
| -}
|
| -
|
| -
|
| -void StatementCfgBuilder::VisitWithExitStatement(WithExitStatement* stmt) {
|
| - BAILOUT("WithExitStatement");
|
| -}
|
| -
|
| -
|
| -void StatementCfgBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
|
| - BAILOUT("SwitchStatement");
|
| -}
|
| -
|
| -
|
| -void StatementCfgBuilder::VisitLoopStatement(LoopStatement* stmt) {
|
| - BAILOUT("LoopStatement");
|
| -}
|
| -
|
| -
|
| -void StatementCfgBuilder::VisitForInStatement(ForInStatement* stmt) {
|
| - BAILOUT("ForInStatement");
|
| -}
|
| -
|
| -
|
| -void StatementCfgBuilder::VisitTryCatch(TryCatch* stmt) {
|
| - BAILOUT("TryCatch");
|
| -}
|
| -
|
| -
|
| -void StatementCfgBuilder::VisitTryFinally(TryFinally* stmt) {
|
| - BAILOUT("TryFinally");
|
| -}
|
| -
|
| -
|
| -void StatementCfgBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
|
| - BAILOUT("DebuggerStatement");
|
| -}
|
| -
|
| -
|
| -#ifdef DEBUG
|
| -// CFG printing support (via depth-first, preorder block traversal).
|
| -
|
| -void Cfg::Print() {
|
| - entry_->Print();
|
| - entry_->Unmark();
|
| -}
|
| -
|
| -
|
| -void Constant::Print() {
|
| - PrintF("Constant ");
|
| - handle_->Print();
|
| -}
|
| -
|
| -
|
| -void Nowhere::Print() {
|
| - PrintF("Nowhere");
|
| -}
|
| -
|
| -
|
| -void SlotLocation::Print() {
|
| - PrintF("Slot ");
|
| - switch (type_) {
|
| - case Slot::PARAMETER:
|
| - PrintF("(PARAMETER, %d)", index_);
|
| - break;
|
| - case Slot::LOCAL:
|
| - PrintF("(LOCAL, %d)", index_);
|
| - break;
|
| - default:
|
| - UNREACHABLE();
|
| - }
|
| -}
|
| -
|
| -
|
| -void TempLocation::Print() {
|
| - PrintF("Temp %d", number());
|
| -}
|
| -
|
| -
|
| -void OneOperandInstruction::Print() {
|
| - PrintF("(");
|
| - location()->Print();
|
| - PrintF(", ");
|
| - value_->Print();
|
| - PrintF(")");
|
| -}
|
| -
|
| -
|
| -void TwoOperandInstruction::Print() {
|
| - PrintF("(");
|
| - location()->Print();
|
| - PrintF(", ");
|
| - value0_->Print();
|
| - PrintF(", ");
|
| - value1_->Print();
|
| - PrintF(")");
|
| -}
|
| -
|
| -
|
| -void MoveInstr::Print() {
|
| - PrintF("Move ");
|
| - OneOperandInstruction::Print();
|
| - PrintF("\n");
|
| -}
|
| -
|
| -
|
| -void PropLoadInstr::Print() {
|
| - PrintF("PropLoad ");
|
| - TwoOperandInstruction::Print();
|
| - PrintF("\n");
|
| -}
|
| -
|
| -
|
| -void BinaryOpInstr::Print() {
|
| - switch (op()) {
|
| - case Token::OR:
|
| - // Two character operand.
|
| - PrintF("BinaryOp[OR] ");
|
| - break;
|
| - case Token::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:
|
| - // Three character operands.
|
| - PrintF("BinaryOp[%s] ", Token::Name(op()));
|
| - break;
|
| - case Token::COMMA:
|
| - // Five character operand.
|
| - PrintF("BinaryOp[COMMA] ");
|
| - break;
|
| - case Token::BIT_OR:
|
| - // Six character operand.
|
| - PrintF("BinaryOp[BIT_OR] ");
|
| - break;
|
| - case Token::BIT_XOR:
|
| - case Token::BIT_AND:
|
| - // Seven character operands.
|
| - PrintF("BinaryOp[%s] ", Token::Name(op()));
|
| - break;
|
| - default:
|
| - UNREACHABLE();
|
| - }
|
| - TwoOperandInstruction::Print();
|
| - PrintF("\n");
|
| -}
|
| -
|
| -
|
| -void ReturnInstr::Print() {
|
| - PrintF("Return ");
|
| - OneOperandInstruction::Print();
|
| - PrintF("\n");
|
| -}
|
| -
|
| -
|
| -void InstructionBlock::Print() {
|
| - if (!is_marked_) {
|
| - is_marked_ = true;
|
| - PrintF("L%d:\n", number());
|
| - for (int i = 0, len = instructions_.length(); i < len; i++) {
|
| - instructions_[i]->Print();
|
| - }
|
| - PrintF("Goto L%d\n\n", successor_->number());
|
| - successor_->Print();
|
| - }
|
| -}
|
| -
|
| -
|
| -void EntryNode::Print() {
|
| - if (!is_marked_) {
|
| - is_marked_ = true;
|
| - successor_->Print();
|
| - }
|
| -}
|
| -
|
| -
|
| -void ExitNode::Print() {
|
| - if (!is_marked_) {
|
| - is_marked_ = true;
|
| - PrintF("L%d:\nExit\n\n", number());
|
| - }
|
| -}
|
| -
|
| -#endif // DEBUG
|
| -
|
| -} } // namespace v8::internal
|
|
|