blob: 07851768b3d432bbc91dc65b6aa3b3aee8b3a8e4 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// Copyright 2013 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/compiler/graph-visualizer.h"
6
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007#include <sstream>
8#include <string>
9
10#include "src/code-stubs.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011#include "src/compiler/all-nodes.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012#include "src/compiler/graph.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013#include "src/compiler/node.h"
14#include "src/compiler/node-properties.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015#include "src/compiler/opcodes.h"
16#include "src/compiler/operator.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017#include "src/compiler/operator-properties.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018#include "src/compiler/register-allocator.h"
19#include "src/compiler/schedule.h"
20#include "src/compiler/scheduler.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021#include "src/interpreter/bytecodes.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022#include "src/ostreams.h"
23
24namespace v8 {
25namespace internal {
26namespace compiler {
27
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000028
29FILE* OpenVisualizerLogFile(CompilationInfo* info, const char* phase,
30 const char* suffix, const char* mode) {
31 EmbeddedVector<char, 256> filename(0);
32 base::SmartArrayPointer<char> debug_name = info->GetDebugName();
33 if (strlen(debug_name.get()) > 0) {
34 SNPrintF(filename, "turbo-%s", debug_name.get());
35 } else if (info->has_shared_info()) {
36 SNPrintF(filename, "turbo-%p", static_cast<void*>(info));
37 } else {
38 SNPrintF(filename, "turbo-none-%s", phase);
39 }
40 std::replace(filename.start(), filename.start() + filename.length(), ' ',
41 '_');
42
43 EmbeddedVector<char, 256> full_filename;
44 if (phase == nullptr) {
45 SNPrintF(full_filename, "%s.%s", filename.start(), suffix);
46 } else {
47 SNPrintF(full_filename, "%s-%s.%s", filename.start(), phase, suffix);
48 }
49 return base::OS::FOpen(full_filename.start(), mode);
50}
51
52
53static int SafeId(Node* node) { return node == nullptr ? -1 : node->id(); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040054static const char* SafeMnemonic(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000055 return node == nullptr ? "null" : node->op()->mnemonic();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040056}
57
Ben Murdochb8a8cc12014-11-26 15:28:44 +000058#define DEAD_COLOR "#999999"
59
Emily Bernierd0a1eb72015-03-24 16:35:39 -040060class Escaped {
61 public:
62 explicit Escaped(const std::ostringstream& os,
63 const char* escaped_chars = "<>|{}")
64 : str_(os.str()), escaped_chars_(escaped_chars) {}
65
66 friend std::ostream& operator<<(std::ostream& os, const Escaped& e) {
67 for (std::string::const_iterator i = e.str_.begin(); i != e.str_.end();
68 ++i) {
69 if (e.needs_escape(*i)) os << "\\";
70 os << *i;
71 }
72 return os;
73 }
74
75 private:
76 bool needs_escape(char ch) const {
77 for (size_t i = 0; i < strlen(escaped_chars_); ++i) {
78 if (ch == escaped_chars_[i]) return true;
79 }
80 return false;
81 }
82
83 const std::string str_;
84 const char* const escaped_chars_;
85};
86
87class JSONGraphNodeWriter {
88 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000089 JSONGraphNodeWriter(std::ostream& os, Zone* zone, const Graph* graph,
90 const SourcePositionTable* positions)
91 : os_(os), all_(zone, graph), positions_(positions), first_node_(true) {}
Emily Bernierd0a1eb72015-03-24 16:35:39 -040092
93 void Print() {
94 for (Node* const node : all_.live) PrintNode(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000095 os_ << "\n";
Emily Bernierd0a1eb72015-03-24 16:35:39 -040096 }
97
98 void PrintNode(Node* node) {
99 if (first_node_) {
100 first_node_ = false;
101 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000102 os_ << ",\n";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400103 }
104 std::ostringstream label;
105 label << *node->op();
106 os_ << "{\"id\":" << SafeId(node) << ",\"label\":\"" << Escaped(label, "\"")
107 << "\"";
108 IrOpcode::Value opcode = node->opcode();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000109 if (IrOpcode::IsPhiOpcode(opcode)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400110 os_ << ",\"rankInputs\":[0," << NodeProperties::FirstControlIndex(node)
111 << "]";
112 os_ << ",\"rankWithInput\":[" << NodeProperties::FirstControlIndex(node)
113 << "]";
114 } else if (opcode == IrOpcode::kIfTrue || opcode == IrOpcode::kIfFalse ||
115 opcode == IrOpcode::kLoop) {
116 os_ << ",\"rankInputs\":[" << NodeProperties::FirstControlIndex(node)
117 << "]";
118 }
119 if (opcode == IrOpcode::kBranch) {
120 os_ << ",\"rankInputs\":[0]";
121 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000122 SourcePosition position = positions_->GetSourcePosition(node);
123 if (position.IsKnown()) {
124 os_ << ",\"pos\":" << position.raw();
125 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400126 os_ << ",\"opcode\":\"" << IrOpcode::Mnemonic(node->opcode()) << "\"";
127 os_ << ",\"control\":" << (NodeProperties::IsControl(node) ? "true"
128 : "false");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000129 if (NodeProperties::IsTyped(node)) {
130 Type* type = NodeProperties::GetType(node);
131 std::ostringstream type_out;
132 type->PrintTo(type_out);
133 os_ << ",\"type\":\"" << Escaped(type_out, "\"") << "\"";
134 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400135 os_ << "}";
136 }
137
138 private:
139 std::ostream& os_;
140 AllNodes all_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000141 const SourcePositionTable* positions_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400142 bool first_node_;
143
144 DISALLOW_COPY_AND_ASSIGN(JSONGraphNodeWriter);
145};
146
147
148class JSONGraphEdgeWriter {
149 public:
150 JSONGraphEdgeWriter(std::ostream& os, Zone* zone, const Graph* graph)
151 : os_(os), all_(zone, graph), first_edge_(true) {}
152
153 void Print() {
154 for (Node* const node : all_.live) PrintEdges(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000155 os_ << "\n";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400156 }
157
158 void PrintEdges(Node* node) {
159 for (int i = 0; i < node->InputCount(); i++) {
160 Node* input = node->InputAt(i);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000161 if (input == nullptr) continue;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400162 PrintEdge(node, i, input);
163 }
164 }
165
166 void PrintEdge(Node* from, int index, Node* to) {
167 if (first_edge_) {
168 first_edge_ = false;
169 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000170 os_ << ",\n";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400171 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000172 const char* edge_type = nullptr;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400173 if (index < NodeProperties::FirstValueIndex(from)) {
174 edge_type = "unknown";
175 } else if (index < NodeProperties::FirstContextIndex(from)) {
176 edge_type = "value";
177 } else if (index < NodeProperties::FirstFrameStateIndex(from)) {
178 edge_type = "context";
179 } else if (index < NodeProperties::FirstEffectIndex(from)) {
180 edge_type = "frame-state";
181 } else if (index < NodeProperties::FirstControlIndex(from)) {
182 edge_type = "effect";
183 } else {
184 edge_type = "control";
185 }
186 os_ << "{\"source\":" << SafeId(to) << ",\"target\":" << SafeId(from)
187 << ",\"index\":" << index << ",\"type\":\"" << edge_type << "\"}";
188 }
189
190 private:
191 std::ostream& os_;
192 AllNodes all_;
193 bool first_edge_;
194
195 DISALLOW_COPY_AND_ASSIGN(JSONGraphEdgeWriter);
196};
197
198
199std::ostream& operator<<(std::ostream& os, const AsJSON& ad) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000200 Zone tmp_zone;
201 os << "{\n\"nodes\":[";
202 JSONGraphNodeWriter(os, &tmp_zone, &ad.graph, ad.positions).Print();
203 os << "],\n\"edges\":[";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400204 JSONGraphEdgeWriter(os, &tmp_zone, &ad.graph).Print();
205 os << "]}";
206 return os;
207}
208
209
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400210class GraphC1Visualizer {
211 public:
212 GraphC1Visualizer(std::ostream& os, Zone* zone); // NOLINT
213
214 void PrintCompilation(const CompilationInfo* info);
215 void PrintSchedule(const char* phase, const Schedule* schedule,
216 const SourcePositionTable* positions,
217 const InstructionSequence* instructions);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000218 void PrintLiveRanges(const char* phase, const RegisterAllocationData* data);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400219 Zone* zone() const { return zone_; }
220
221 private:
222 void PrintIndent();
223 void PrintStringProperty(const char* name, const char* value);
224 void PrintLongProperty(const char* name, int64_t value);
225 void PrintIntProperty(const char* name, int value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000226 void PrintBlockProperty(const char* name, int rpo_number);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400227 void PrintNodeId(Node* n);
228 void PrintNode(Node* n);
229 void PrintInputs(Node* n);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000230 template <typename InputIterator>
231 void PrintInputs(InputIterator* i, int count, const char* prefix);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400232 void PrintType(Node* node);
233
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000234 void PrintLiveRange(LiveRange* range, const char* type, int vreg);
235 void PrintLiveRangeChain(TopLevelLiveRange* range, const char* type);
236
237 class Tag final BASE_EMBEDDED {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400238 public:
239 Tag(GraphC1Visualizer* visualizer, const char* name) {
240 name_ = name;
241 visualizer_ = visualizer;
242 visualizer->PrintIndent();
243 visualizer_->os_ << "begin_" << name << "\n";
244 visualizer->indent_++;
245 }
246
247 ~Tag() {
248 visualizer_->indent_--;
249 visualizer_->PrintIndent();
250 visualizer_->os_ << "end_" << name_ << "\n";
251 DCHECK(visualizer_->indent_ >= 0);
252 }
253
254 private:
255 GraphC1Visualizer* visualizer_;
256 const char* name_;
257 };
258
259 std::ostream& os_;
260 int indent_;
261 Zone* zone_;
262
263 DISALLOW_COPY_AND_ASSIGN(GraphC1Visualizer);
264};
265
266
267void GraphC1Visualizer::PrintIndent() {
268 for (int i = 0; i < indent_; i++) {
269 os_ << " ";
270 }
271}
272
273
274GraphC1Visualizer::GraphC1Visualizer(std::ostream& os, Zone* zone)
275 : os_(os), indent_(0), zone_(zone) {}
276
277
278void GraphC1Visualizer::PrintStringProperty(const char* name,
279 const char* value) {
280 PrintIndent();
281 os_ << name << " \"" << value << "\"\n";
282}
283
284
285void GraphC1Visualizer::PrintLongProperty(const char* name, int64_t value) {
286 PrintIndent();
287 os_ << name << " " << static_cast<int>(value / 1000) << "\n";
288}
289
290
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000291void GraphC1Visualizer::PrintBlockProperty(const char* name, int rpo_number) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400292 PrintIndent();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000293 os_ << name << " \"B" << rpo_number << "\"\n";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400294}
295
296
297void GraphC1Visualizer::PrintIntProperty(const char* name, int value) {
298 PrintIndent();
299 os_ << name << " " << value << "\n";
300}
301
302
303void GraphC1Visualizer::PrintCompilation(const CompilationInfo* info) {
304 Tag tag(this, "compilation");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000305 base::SmartArrayPointer<char> name = info->GetDebugName();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400306 if (info->IsOptimizing()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000307 PrintStringProperty("name", name.get());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400308 PrintIndent();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000309 os_ << "method \"" << name.get() << ":" << info->optimization_id()
310 << "\"\n";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400311 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000312 PrintStringProperty("name", name.get());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400313 PrintStringProperty("method", "stub");
314 }
315 PrintLongProperty("date",
316 static_cast<int64_t>(base::OS::TimeCurrentMillis()));
317}
318
319
320void GraphC1Visualizer::PrintNodeId(Node* n) { os_ << "n" << SafeId(n); }
321
322
323void GraphC1Visualizer::PrintNode(Node* n) {
324 PrintNodeId(n);
325 os_ << " " << *n->op() << " ";
326 PrintInputs(n);
327}
328
329
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000330template <typename InputIterator>
331void GraphC1Visualizer::PrintInputs(InputIterator* i, int count,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400332 const char* prefix) {
333 if (count > 0) {
334 os_ << prefix;
335 }
336 while (count > 0) {
337 os_ << " ";
338 PrintNodeId(**i);
339 ++(*i);
340 count--;
341 }
342}
343
344
345void GraphC1Visualizer::PrintInputs(Node* node) {
346 auto i = node->inputs().begin();
347 PrintInputs(&i, node->op()->ValueInputCount(), " ");
348 PrintInputs(&i, OperatorProperties::GetContextInputCount(node->op()),
349 " Ctx:");
350 PrintInputs(&i, OperatorProperties::GetFrameStateInputCount(node->op()),
351 " FS:");
352 PrintInputs(&i, node->op()->EffectInputCount(), " Eff:");
353 PrintInputs(&i, node->op()->ControlInputCount(), " Ctrl:");
354}
355
356
357void GraphC1Visualizer::PrintType(Node* node) {
358 if (NodeProperties::IsTyped(node)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000359 Type* type = NodeProperties::GetType(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400360 os_ << " type:";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000361 type->PrintTo(os_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400362 }
363}
364
365
366void GraphC1Visualizer::PrintSchedule(const char* phase,
367 const Schedule* schedule,
368 const SourcePositionTable* positions,
369 const InstructionSequence* instructions) {
370 Tag tag(this, "cfg");
371 PrintStringProperty("name", phase);
372 const BasicBlockVector* rpo = schedule->rpo_order();
373 for (size_t i = 0; i < rpo->size(); i++) {
374 BasicBlock* current = (*rpo)[i];
375 Tag block_tag(this, "block");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000376 PrintBlockProperty("name", current->rpo_number());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400377 PrintIntProperty("from_bci", -1);
378 PrintIntProperty("to_bci", -1);
379
380 PrintIndent();
381 os_ << "predecessors";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000382 for (BasicBlock* predecessor : current->predecessors()) {
383 os_ << " \"B" << predecessor->rpo_number() << "\"";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400384 }
385 os_ << "\n";
386
387 PrintIndent();
388 os_ << "successors";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000389 for (BasicBlock* successor : current->successors()) {
390 os_ << " \"B" << successor->rpo_number() << "\"";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400391 }
392 os_ << "\n";
393
394 PrintIndent();
395 os_ << "xhandlers\n";
396
397 PrintIndent();
398 os_ << "flags\n";
399
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000400 if (current->dominator() != nullptr) {
401 PrintBlockProperty("dominator", current->dominator()->rpo_number());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400402 }
403
404 PrintIntProperty("loop_depth", current->loop_depth());
405
406 const InstructionBlock* instruction_block =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000407 instructions->InstructionBlockAt(
408 RpoNumber::FromInt(current->rpo_number()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400409 if (instruction_block->code_start() >= 0) {
410 int first_index = instruction_block->first_instruction_index();
411 int last_index = instruction_block->last_instruction_index();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000412 PrintIntProperty(
413 "first_lir_id",
414 LifetimePosition::GapFromInstructionIndex(first_index).value());
415 PrintIntProperty("last_lir_id",
416 LifetimePosition::InstructionFromInstructionIndex(
417 last_index).value());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400418 }
419
420 {
421 Tag states_tag(this, "states");
422 Tag locals_tag(this, "locals");
423 int total = 0;
424 for (BasicBlock::const_iterator i = current->begin(); i != current->end();
425 ++i) {
426 if ((*i)->opcode() == IrOpcode::kPhi) total++;
427 }
428 PrintIntProperty("size", total);
429 PrintStringProperty("method", "None");
430 int index = 0;
431 for (BasicBlock::const_iterator i = current->begin(); i != current->end();
432 ++i) {
433 if ((*i)->opcode() != IrOpcode::kPhi) continue;
434 PrintIndent();
435 os_ << index << " ";
436 PrintNodeId(*i);
437 os_ << " [";
438 PrintInputs(*i);
439 os_ << "]\n";
440 index++;
441 }
442 }
443
444 {
445 Tag HIR_tag(this, "HIR");
446 for (BasicBlock::const_iterator i = current->begin(); i != current->end();
447 ++i) {
448 Node* node = *i;
449 if (node->opcode() == IrOpcode::kPhi) continue;
450 int uses = node->UseCount();
451 PrintIndent();
452 os_ << "0 " << uses << " ";
453 PrintNode(node);
454 if (FLAG_trace_turbo_types) {
455 os_ << " ";
456 PrintType(node);
457 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000458 if (positions != nullptr) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400459 SourcePosition position = positions->GetSourcePosition(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000460 if (position.IsKnown()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400461 os_ << " pos:" << position.raw();
462 }
463 }
464 os_ << " <|@\n";
465 }
466
467 BasicBlock::Control control = current->control();
468 if (control != BasicBlock::kNone) {
469 PrintIndent();
470 os_ << "0 0 ";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000471 if (current->control_input() != nullptr) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400472 PrintNode(current->control_input());
473 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000474 os_ << -1 - current->rpo_number() << " Goto";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400475 }
476 os_ << " ->";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000477 for (BasicBlock* successor : current->successors()) {
478 os_ << " B" << successor->rpo_number();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400479 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000480 if (FLAG_trace_turbo_types && current->control_input() != nullptr) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400481 os_ << " ";
482 PrintType(current->control_input());
483 }
484 os_ << " <|@\n";
485 }
486 }
487
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000488 if (instructions != nullptr) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400489 Tag LIR_tag(this, "LIR");
490 for (int j = instruction_block->first_instruction_index();
491 j <= instruction_block->last_instruction_index(); j++) {
492 PrintIndent();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000493 PrintableInstruction printable = {
494 RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN),
495 instructions->InstructionAt(j)};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400496 os_ << j << " " << printable << " <|@\n";
497 }
498 }
499 }
500}
501
502
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000503void GraphC1Visualizer::PrintLiveRanges(const char* phase,
504 const RegisterAllocationData* data) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400505 Tag tag(this, "intervals");
506 PrintStringProperty("name", phase);
507
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000508 for (auto range : data->fixed_double_live_ranges()) {
509 PrintLiveRangeChain(range, "fixed");
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400510 }
511
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000512 for (auto range : data->fixed_live_ranges()) {
513 PrintLiveRangeChain(range, "fixed");
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400514 }
515
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000516 for (auto range : data->live_ranges()) {
517 PrintLiveRangeChain(range, "object");
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400518 }
519}
520
521
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000522void GraphC1Visualizer::PrintLiveRangeChain(TopLevelLiveRange* range,
523 const char* type) {
524 if (range == nullptr || range->IsEmpty()) return;
525 int vreg = range->vreg();
526 for (LiveRange* child = range; child != nullptr; child = child->next()) {
527 PrintLiveRange(child, type, vreg);
528 }
529}
530
531
532void GraphC1Visualizer::PrintLiveRange(LiveRange* range, const char* type,
533 int vreg) {
534 if (range != nullptr && !range->IsEmpty()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400535 PrintIndent();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000536 os_ << vreg << ":" << range->relative_id() << " " << type;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400537 if (range->HasRegisterAssigned()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000538 AllocatedOperand op = AllocatedOperand::cast(range->GetAssignedOperand());
539 if (op.IsDoubleRegister()) {
540 DoubleRegister assigned_reg = op.GetDoubleRegister();
541 os_ << " \"" << assigned_reg.ToString() << "\"";
542 } else {
543 DCHECK(op.IsRegister());
544 Register assigned_reg = op.GetRegister();
545 os_ << " \"" << assigned_reg.ToString() << "\"";
546 }
547 } else if (range->spilled()) {
548 auto top = range->TopLevel();
549 int index = -1;
550 if (top->HasSpillRange()) {
551 index = kMaxInt; // This hasn't been set yet.
552 } else if (top->GetSpillOperand()->IsConstant()) {
553 os_ << " \"const(nostack):"
554 << ConstantOperand::cast(top->GetSpillOperand())->virtual_register()
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400555 << "\"";
556 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000557 index = AllocatedOperand::cast(top->GetSpillOperand())->index();
558 if (top->kind() == DOUBLE_REGISTERS) {
559 os_ << " \"double_stack:" << index << "\"";
560 } else if (top->kind() == GENERAL_REGISTERS) {
561 os_ << " \"stack:" << index << "\"";
562 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400563 }
564 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000565
566 os_ << " " << vreg;
567 for (auto interval = range->first_interval(); interval != nullptr;
568 interval = interval->next()) {
569 os_ << " [" << interval->start().value() << ", "
570 << interval->end().value() << "[";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400571 }
572
573 UsePosition* current_pos = range->first_pos();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000574 while (current_pos != nullptr) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400575 if (current_pos->RegisterIsBeneficial() || FLAG_trace_all_uses) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000576 os_ << " " << current_pos->pos().value() << " M";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400577 }
578 current_pos = current_pos->next();
579 }
580
581 os_ << " \"\"\n";
582 }
583}
584
585
586std::ostream& operator<<(std::ostream& os, const AsC1VCompilation& ac) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000587 Zone tmp_zone;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400588 GraphC1Visualizer(os, &tmp_zone).PrintCompilation(ac.info_);
589 return os;
590}
591
592
593std::ostream& operator<<(std::ostream& os, const AsC1V& ac) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000594 Zone tmp_zone;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400595 GraphC1Visualizer(os, &tmp_zone)
596 .PrintSchedule(ac.phase_, ac.schedule_, ac.positions_, ac.instructions_);
597 return os;
598}
599
600
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000601std::ostream& operator<<(std::ostream& os,
602 const AsC1VRegisterAllocationData& ac) {
603 Zone tmp_zone;
604 GraphC1Visualizer(os, &tmp_zone).PrintLiveRanges(ac.phase_, ac.data_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400605 return os;
606}
607
608const int kUnvisited = 0;
609const int kOnStack = 1;
610const int kVisited = 2;
611
612std::ostream& operator<<(std::ostream& os, const AsRPO& ar) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000613 Zone local_zone;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400614 ZoneVector<byte> state(ar.graph.NodeCount(), kUnvisited, &local_zone);
615 ZoneStack<Node*> stack(&local_zone);
616
617 stack.push(ar.graph.end());
618 state[ar.graph.end()->id()] = kOnStack;
619 while (!stack.empty()) {
620 Node* n = stack.top();
621 bool pop = true;
622 for (Node* const i : n->inputs()) {
623 if (state[i->id()] == kUnvisited) {
624 state[i->id()] = kOnStack;
625 stack.push(i);
626 pop = false;
627 break;
628 }
629 }
630 if (pop) {
631 state[n->id()] = kVisited;
632 stack.pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000633 os << "#" << n->id() << ":" << *n->op() << "(";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400634 int j = 0;
635 for (Node* const i : n->inputs()) {
636 if (j++ > 0) os << ", ";
637 os << "#" << SafeId(i) << ":" << SafeMnemonic(i);
638 }
639 os << ")" << std::endl;
640 }
641 }
642 return os;
643}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000644} // namespace compiler
645} // namespace internal
646} // namespace v8