Index: src/compiler/graph-visualizer.cc |
diff --git a/src/compiler/graph-visualizer.cc b/src/compiler/graph-visualizer.cc |
index 5bd8de7aafb82e5a66e69936aa39c02f8ad52f38..4340c250b5159f947be30c54fcf649d99a9d3d90 100644 |
--- a/src/compiler/graph-visualizer.cc |
+++ b/src/compiler/graph-visualizer.cc |
@@ -17,6 +17,9 @@ |
#include "src/compiler/node-properties-inl.h" |
#include "src/compiler/opcodes.h" |
#include "src/compiler/operator.h" |
+#include "src/compiler/register-allocator.h" |
+#include "src/compiler/schedule.h" |
+#include "src/compiler/scheduler.h" |
#include "src/ostreams.h" |
namespace v8 { |
@@ -389,6 +392,395 @@ std::ostream& operator<<(std::ostream& os, const AsDOT& ad) { |
GraphVisualizer(os, &tmp_zone, &ad.graph).Print(); |
return os; |
} |
+ |
+ |
+class GraphC1Visualizer { |
+ public: |
+ GraphC1Visualizer(std::ostream& os, Zone* zone); // NOLINT |
+ |
+ void PrintCompilation(const CompilationInfo* info); |
+ void PrintSchedule(const char* phase, const Schedule* schedule, |
+ const SourcePositionTable* positions, |
+ const InstructionSequence* instructions); |
+ void PrintAllocator(const char* phase, const RegisterAllocator* allocator); |
+ Zone* zone() const { return zone_; } |
+ |
+ private: |
+ void PrintIndent(); |
+ void PrintStringProperty(const char* name, const char* value); |
+ void PrintLongProperty(const char* name, int64_t value); |
+ void PrintIntProperty(const char* name, int value); |
+ void PrintBlockProperty(const char* name, BasicBlock::Id block_id); |
+ void PrintNodeId(Node* n); |
+ void PrintNode(Node* n); |
+ void PrintInputs(Node* n); |
+ void PrintInputs(InputIter* i, int count, const char* prefix); |
+ void PrintType(Node* node); |
+ |
+ void PrintLiveRange(LiveRange* range, const char* type); |
+ class Tag FINAL BASE_EMBEDDED { |
+ public: |
+ Tag(GraphC1Visualizer* visualizer, const char* name) { |
+ name_ = name; |
+ visualizer_ = visualizer; |
+ visualizer->PrintIndent(); |
+ visualizer_->os_ << "begin_" << name << "\n"; |
+ visualizer->indent_++; |
+ } |
+ |
+ ~Tag() { |
+ visualizer_->indent_--; |
+ visualizer_->PrintIndent(); |
+ visualizer_->os_ << "end_" << name_ << "\n"; |
+ DCHECK(visualizer_->indent_ >= 0); |
+ } |
+ |
+ private: |
+ GraphC1Visualizer* visualizer_; |
+ const char* name_; |
+ }; |
+ |
+ std::ostream& os_; |
+ int indent_; |
+ Zone* zone_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(GraphC1Visualizer); |
+}; |
+ |
+ |
+void GraphC1Visualizer::PrintIndent() { |
+ for (int i = 0; i < indent_; i++) { |
+ os_ << " "; |
+ } |
+} |
+ |
+ |
+GraphC1Visualizer::GraphC1Visualizer(std::ostream& os, Zone* zone) |
+ : os_(os), indent_(0), zone_(zone) {} |
+ |
+ |
+void GraphC1Visualizer::PrintStringProperty(const char* name, |
+ const char* value) { |
+ PrintIndent(); |
+ os_ << name << " \"" << value << "\"\n"; |
+} |
+ |
+ |
+void GraphC1Visualizer::PrintLongProperty(const char* name, int64_t value) { |
+ PrintIndent(); |
+ os_ << name << " " << static_cast<int>(value / 1000) << "\n"; |
+} |
+ |
+ |
+void GraphC1Visualizer::PrintBlockProperty(const char* name, |
+ BasicBlock::Id block_id) { |
+ PrintIndent(); |
+ os_ << name << " \"B" << block_id << "\"\n"; |
+} |
+ |
+ |
+void GraphC1Visualizer::PrintIntProperty(const char* name, int value) { |
+ PrintIndent(); |
+ os_ << name << " " << value << "\n"; |
+} |
+ |
+ |
+void GraphC1Visualizer::PrintCompilation(const CompilationInfo* info) { |
+ Tag tag(this, "compilation"); |
+ if (info->IsOptimizing()) { |
+ Handle<String> name = info->function()->debug_name(); |
+ PrintStringProperty("name", name->ToCString().get()); |
+ PrintIndent(); |
+ os_ << "method \"" << name->ToCString().get() << ":" |
+ << info->optimization_id() << "\"\n"; |
+ } else { |
+ CodeStub::Major major_key = info->code_stub()->MajorKey(); |
+ PrintStringProperty("name", CodeStub::MajorName(major_key, false)); |
+ PrintStringProperty("method", "stub"); |
+ } |
+ PrintLongProperty("date", |
+ static_cast<int64_t>(base::OS::TimeCurrentMillis())); |
+} |
+ |
+ |
+void GraphC1Visualizer::PrintNodeId(Node* n) { os_ << "n" << n->id(); } |
+ |
+ |
+void GraphC1Visualizer::PrintNode(Node* n) { |
+ PrintNodeId(n); |
+ os_ << " " << *n->op() << " "; |
+ PrintInputs(n); |
+} |
+ |
+ |
+void GraphC1Visualizer::PrintInputs(InputIter* i, int count, |
+ const char* prefix) { |
+ if (count > 0) { |
+ os_ << prefix; |
+ } |
+ while (count > 0) { |
+ os_ << " "; |
+ PrintNodeId(**i); |
+ ++(*i); |
+ count--; |
+ } |
+} |
+ |
+ |
+void GraphC1Visualizer::PrintInputs(Node* node) { |
+ InputIter i = node->inputs().begin(); |
+ PrintInputs(&i, OperatorProperties::GetValueInputCount(node->op()), " "); |
+ PrintInputs(&i, OperatorProperties::GetContextInputCount(node->op()), |
+ " Ctx:"); |
+ PrintInputs(&i, OperatorProperties::GetFrameStateInputCount(node->op()), |
+ " FS:"); |
+ PrintInputs(&i, OperatorProperties::GetEffectInputCount(node->op()), " Eff:"); |
+ PrintInputs(&i, OperatorProperties::GetControlInputCount(node->op()), |
+ " Ctrl:"); |
+} |
+ |
+ |
+void GraphC1Visualizer::PrintType(Node* node) { |
+ Bounds bounds = NodeProperties::GetBounds(node); |
+ os_ << " type:"; |
+ bounds.upper->PrintTo(os_); |
+ os_ << ".."; |
+ bounds.lower->PrintTo(os_); |
+} |
+ |
+ |
+void GraphC1Visualizer::PrintSchedule(const char* phase, |
+ const Schedule* schedule, |
+ const SourcePositionTable* positions, |
+ const InstructionSequence* instructions) { |
+ Tag tag(this, "cfg"); |
+ PrintStringProperty("name", phase); |
+ const BasicBlockVector* rpo = schedule->rpo_order(); |
+ for (size_t i = 0; i < rpo->size(); i++) { |
+ BasicBlock* current = (*rpo)[i]; |
+ Tag block_tag(this, "block"); |
+ PrintBlockProperty("name", current->id()); |
+ PrintIntProperty("from_bci", -1); |
+ PrintIntProperty("to_bci", -1); |
+ |
+ PrintIndent(); |
+ os_ << "predecessors"; |
+ for (BasicBlock::Predecessors::iterator j = current->predecessors_begin(); |
+ j != current->predecessors_end(); ++j) { |
+ os_ << " \"B" << (*j)->id() << "\""; |
+ } |
+ os_ << "\n"; |
+ |
+ PrintIndent(); |
+ os_ << "successors"; |
+ for (BasicBlock::Successors::iterator j = current->successors_begin(); |
+ j != current->successors_end(); ++j) { |
+ os_ << " \"B" << (*j)->id() << "\""; |
+ } |
+ os_ << "\n"; |
+ |
+ PrintIndent(); |
+ os_ << "xhandlers\n"; |
+ |
+ PrintIndent(); |
+ os_ << "flags\n"; |
+ |
+ if (current->dominator() != NULL) { |
+ PrintBlockProperty("dominator", current->dominator()->id()); |
+ } |
+ |
+ PrintIntProperty("loop_depth", current->loop_depth()); |
+ |
+ if (current->code_start() >= 0) { |
+ int first_index = current->first_instruction_index(); |
+ int last_index = current->last_instruction_index(); |
+ PrintIntProperty("first_lir_id", LifetimePosition::FromInstructionIndex( |
+ first_index).Value()); |
+ PrintIntProperty("last_lir_id", LifetimePosition::FromInstructionIndex( |
+ last_index).Value()); |
+ } |
+ |
+ { |
+ Tag states_tag(this, "states"); |
+ Tag locals_tag(this, "locals"); |
+ int total = 0; |
+ for (BasicBlock::const_iterator i = current->begin(); i != current->end(); |
+ ++i) { |
+ if ((*i)->opcode() == IrOpcode::kPhi) total++; |
+ } |
+ PrintIntProperty("size", total); |
+ PrintStringProperty("method", "None"); |
+ int index = 0; |
+ for (BasicBlock::const_iterator i = current->begin(); i != current->end(); |
+ ++i) { |
+ if ((*i)->opcode() != IrOpcode::kPhi) continue; |
+ PrintIndent(); |
+ os_ << index << " "; |
+ PrintNodeId(*i); |
+ os_ << " ["; |
+ PrintInputs(*i); |
+ os_ << "]\n"; |
+ index++; |
+ } |
+ } |
+ |
+ { |
+ Tag HIR_tag(this, "HIR"); |
+ for (BasicBlock::const_iterator i = current->begin(); i != current->end(); |
+ ++i) { |
+ Node* node = *i; |
+ if (node->opcode() == IrOpcode::kPhi) continue; |
+ int uses = node->UseCount(); |
+ PrintIndent(); |
+ os_ << "0 " << uses << " "; |
+ PrintNode(node); |
+ if (FLAG_trace_turbo_types) { |
+ os_ << " "; |
+ PrintType(node); |
+ } |
+ if (positions != NULL) { |
+ SourcePosition position = positions->GetSourcePosition(node); |
+ if (!position.IsUnknown()) { |
+ DCHECK(!position.IsInvalid()); |
+ os_ << " pos:" << position.raw(); |
+ } |
+ } |
+ os_ << " <|@\n"; |
+ } |
+ |
+ BasicBlock::Control control = current->control(); |
+ if (control != BasicBlock::kNone) { |
+ PrintIndent(); |
+ os_ << "0 0 "; |
+ if (current->control_input() != NULL) { |
+ PrintNode(current->control_input()); |
+ } else { |
+ os_ << -1 - current->id().ToInt() << " Goto"; |
+ } |
+ os_ << " ->"; |
+ for (BasicBlock::Successors::iterator j = current->successors_begin(); |
+ j != current->successors_end(); ++j) { |
+ os_ << " B" << (*j)->id(); |
+ } |
+ if (FLAG_trace_turbo_types && current->control_input() != NULL) { |
+ os_ << " "; |
+ PrintType(current->control_input()); |
+ } |
+ os_ << " <|@\n"; |
+ } |
+ } |
+ |
+ if (instructions != NULL) { |
+ Tag LIR_tag(this, "LIR"); |
+ for (int j = current->first_instruction_index(); |
+ j <= current->last_instruction_index(); j++) { |
+ PrintIndent(); |
+ os_ << j << " " << *instructions->InstructionAt(j) << " <|@\n"; |
+ } |
+ } |
+ } |
+} |
+ |
+ |
+void GraphC1Visualizer::PrintAllocator(const char* phase, |
+ const RegisterAllocator* allocator) { |
+ Tag tag(this, "intervals"); |
+ PrintStringProperty("name", phase); |
+ |
+ const Vector<LiveRange*>* fixed_d = allocator->fixed_double_live_ranges(); |
+ for (int i = 0; i < fixed_d->length(); ++i) { |
+ PrintLiveRange(fixed_d->at(i), "fixed"); |
+ } |
+ |
+ const Vector<LiveRange*>* fixed = allocator->fixed_live_ranges(); |
+ for (int i = 0; i < fixed->length(); ++i) { |
+ PrintLiveRange(fixed->at(i), "fixed"); |
+ } |
+ |
+ const ZoneList<LiveRange*>* live_ranges = allocator->live_ranges(); |
+ for (int i = 0; i < live_ranges->length(); ++i) { |
+ PrintLiveRange(live_ranges->at(i), "object"); |
+ } |
+} |
+ |
+ |
+void GraphC1Visualizer::PrintLiveRange(LiveRange* range, const char* type) { |
+ if (range != NULL && !range->IsEmpty()) { |
+ PrintIndent(); |
+ os_ << range->id() << " " << type; |
+ if (range->HasRegisterAssigned()) { |
+ InstructionOperand* op = range->CreateAssignedOperand(zone()); |
+ int assigned_reg = op->index(); |
+ if (op->IsDoubleRegister()) { |
+ os_ << " \"" << DoubleRegister::AllocationIndexToString(assigned_reg) |
+ << "\""; |
+ } else { |
+ DCHECK(op->IsRegister()); |
+ os_ << " \"" << Register::AllocationIndexToString(assigned_reg) << "\""; |
+ } |
+ } else if (range->IsSpilled()) { |
+ InstructionOperand* op = range->TopLevel()->GetSpillOperand(); |
+ if (op->IsDoubleStackSlot()) { |
+ os_ << " \"double_stack:" << op->index() << "\""; |
+ } else if (op->IsStackSlot()) { |
+ os_ << " \"stack:" << op->index() << "\""; |
+ } else { |
+ DCHECK(op->IsConstant()); |
+ os_ << " \"const(nostack):" << op->index() << "\""; |
+ } |
+ } |
+ int parent_index = -1; |
+ if (range->IsChild()) { |
+ parent_index = range->parent()->id(); |
+ } else { |
+ parent_index = range->id(); |
+ } |
+ InstructionOperand* op = range->FirstHint(); |
+ int hint_index = -1; |
+ if (op != NULL && op->IsUnallocated()) { |
+ hint_index = UnallocatedOperand::cast(op)->virtual_register(); |
+ } |
+ os_ << " " << parent_index << " " << hint_index; |
+ UseInterval* cur_interval = range->first_interval(); |
+ while (cur_interval != NULL && range->Covers(cur_interval->start())) { |
+ os_ << " [" << cur_interval->start().Value() << ", " |
+ << cur_interval->end().Value() << "["; |
+ cur_interval = cur_interval->next(); |
+ } |
+ |
+ UsePosition* current_pos = range->first_pos(); |
+ while (current_pos != NULL) { |
+ if (current_pos->RegisterIsBeneficial() || FLAG_trace_all_uses) { |
+ os_ << " " << current_pos->pos().Value() << " M"; |
+ } |
+ current_pos = current_pos->next(); |
+ } |
+ |
+ os_ << " \"\"\n"; |
+ } |
+} |
+ |
+ |
+std::ostream& operator<<(std::ostream& os, const AsC1VCompilation& ac) { |
+ Zone tmp_zone(ac.info_->isolate()); |
+ GraphC1Visualizer(os, &tmp_zone).PrintCompilation(ac.info_); |
+ return os; |
+} |
+ |
+ |
+std::ostream& operator<<(std::ostream& os, const AsC1V& ac) { |
+ Zone tmp_zone(ac.schedule_->zone()->isolate()); |
+ GraphC1Visualizer(os, &tmp_zone) |
+ .PrintSchedule(ac.phase_, ac.schedule_, ac.positions_, ac.instructions_); |
+ return os; |
+} |
+ |
+ |
+std::ostream& operator<<(std::ostream& os, const AsC1VAllocator& ac) { |
+ Zone tmp_zone(ac.allocator_->code()->zone()->isolate()); |
+ GraphC1Visualizer(os, &tmp_zone).PrintAllocator(ac.phase_, ac.allocator_); |
+ return os; |
+} |
} |
} |
} // namespace v8::internal::compiler |