blob: 301e3900e1c052fb61f6dd8486d1121721d631ee [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 Murdochda12d292016-06-02 14:46:10 +0100200 base::AccountingAllocator allocator;
201 Zone tmp_zone(&allocator);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000202 os << "{\n\"nodes\":[";
203 JSONGraphNodeWriter(os, &tmp_zone, &ad.graph, ad.positions).Print();
204 os << "],\n\"edges\":[";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400205 JSONGraphEdgeWriter(os, &tmp_zone, &ad.graph).Print();
206 os << "]}";
207 return os;
208}
209
210
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400211class GraphC1Visualizer {
212 public:
213 GraphC1Visualizer(std::ostream& os, Zone* zone); // NOLINT
214
215 void PrintCompilation(const CompilationInfo* info);
216 void PrintSchedule(const char* phase, const Schedule* schedule,
217 const SourcePositionTable* positions,
218 const InstructionSequence* instructions);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000219 void PrintLiveRanges(const char* phase, const RegisterAllocationData* data);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400220 Zone* zone() const { return zone_; }
221
222 private:
223 void PrintIndent();
224 void PrintStringProperty(const char* name, const char* value);
225 void PrintLongProperty(const char* name, int64_t value);
226 void PrintIntProperty(const char* name, int value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000227 void PrintBlockProperty(const char* name, int rpo_number);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400228 void PrintNodeId(Node* n);
229 void PrintNode(Node* n);
230 void PrintInputs(Node* n);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000231 template <typename InputIterator>
232 void PrintInputs(InputIterator* i, int count, const char* prefix);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400233 void PrintType(Node* node);
234
Ben Murdochda12d292016-06-02 14:46:10 +0100235 void PrintLiveRange(const LiveRange* range, const char* type, int vreg);
236 void PrintLiveRangeChain(const TopLevelLiveRange* range, const char* type);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000237
238 class Tag final BASE_EMBEDDED {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400239 public:
240 Tag(GraphC1Visualizer* visualizer, const char* name) {
241 name_ = name;
242 visualizer_ = visualizer;
243 visualizer->PrintIndent();
244 visualizer_->os_ << "begin_" << name << "\n";
245 visualizer->indent_++;
246 }
247
248 ~Tag() {
249 visualizer_->indent_--;
250 visualizer_->PrintIndent();
251 visualizer_->os_ << "end_" << name_ << "\n";
252 DCHECK(visualizer_->indent_ >= 0);
253 }
254
255 private:
256 GraphC1Visualizer* visualizer_;
257 const char* name_;
258 };
259
260 std::ostream& os_;
261 int indent_;
262 Zone* zone_;
263
264 DISALLOW_COPY_AND_ASSIGN(GraphC1Visualizer);
265};
266
267
268void GraphC1Visualizer::PrintIndent() {
269 for (int i = 0; i < indent_; i++) {
270 os_ << " ";
271 }
272}
273
274
275GraphC1Visualizer::GraphC1Visualizer(std::ostream& os, Zone* zone)
276 : os_(os), indent_(0), zone_(zone) {}
277
278
279void GraphC1Visualizer::PrintStringProperty(const char* name,
280 const char* value) {
281 PrintIndent();
282 os_ << name << " \"" << value << "\"\n";
283}
284
285
286void GraphC1Visualizer::PrintLongProperty(const char* name, int64_t value) {
287 PrintIndent();
288 os_ << name << " " << static_cast<int>(value / 1000) << "\n";
289}
290
291
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000292void GraphC1Visualizer::PrintBlockProperty(const char* name, int rpo_number) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400293 PrintIndent();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000294 os_ << name << " \"B" << rpo_number << "\"\n";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400295}
296
297
298void GraphC1Visualizer::PrintIntProperty(const char* name, int value) {
299 PrintIndent();
300 os_ << name << " " << value << "\n";
301}
302
303
304void GraphC1Visualizer::PrintCompilation(const CompilationInfo* info) {
305 Tag tag(this, "compilation");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000306 base::SmartArrayPointer<char> name = info->GetDebugName();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400307 if (info->IsOptimizing()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000308 PrintStringProperty("name", name.get());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400309 PrintIndent();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000310 os_ << "method \"" << name.get() << ":" << info->optimization_id()
311 << "\"\n";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400312 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000313 PrintStringProperty("name", name.get());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400314 PrintStringProperty("method", "stub");
315 }
316 PrintLongProperty("date",
317 static_cast<int64_t>(base::OS::TimeCurrentMillis()));
318}
319
320
321void GraphC1Visualizer::PrintNodeId(Node* n) { os_ << "n" << SafeId(n); }
322
323
324void GraphC1Visualizer::PrintNode(Node* n) {
325 PrintNodeId(n);
326 os_ << " " << *n->op() << " ";
327 PrintInputs(n);
328}
329
330
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000331template <typename InputIterator>
332void GraphC1Visualizer::PrintInputs(InputIterator* i, int count,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400333 const char* prefix) {
334 if (count > 0) {
335 os_ << prefix;
336 }
337 while (count > 0) {
338 os_ << " ";
339 PrintNodeId(**i);
340 ++(*i);
341 count--;
342 }
343}
344
345
346void GraphC1Visualizer::PrintInputs(Node* node) {
347 auto i = node->inputs().begin();
348 PrintInputs(&i, node->op()->ValueInputCount(), " ");
349 PrintInputs(&i, OperatorProperties::GetContextInputCount(node->op()),
350 " Ctx:");
351 PrintInputs(&i, OperatorProperties::GetFrameStateInputCount(node->op()),
352 " FS:");
353 PrintInputs(&i, node->op()->EffectInputCount(), " Eff:");
354 PrintInputs(&i, node->op()->ControlInputCount(), " Ctrl:");
355}
356
357
358void GraphC1Visualizer::PrintType(Node* node) {
359 if (NodeProperties::IsTyped(node)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000360 Type* type = NodeProperties::GetType(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400361 os_ << " type:";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000362 type->PrintTo(os_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400363 }
364}
365
366
367void GraphC1Visualizer::PrintSchedule(const char* phase,
368 const Schedule* schedule,
369 const SourcePositionTable* positions,
370 const InstructionSequence* instructions) {
371 Tag tag(this, "cfg");
372 PrintStringProperty("name", phase);
373 const BasicBlockVector* rpo = schedule->rpo_order();
374 for (size_t i = 0; i < rpo->size(); i++) {
375 BasicBlock* current = (*rpo)[i];
376 Tag block_tag(this, "block");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000377 PrintBlockProperty("name", current->rpo_number());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400378 PrintIntProperty("from_bci", -1);
379 PrintIntProperty("to_bci", -1);
380
381 PrintIndent();
382 os_ << "predecessors";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000383 for (BasicBlock* predecessor : current->predecessors()) {
384 os_ << " \"B" << predecessor->rpo_number() << "\"";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400385 }
386 os_ << "\n";
387
388 PrintIndent();
389 os_ << "successors";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000390 for (BasicBlock* successor : current->successors()) {
391 os_ << " \"B" << successor->rpo_number() << "\"";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400392 }
393 os_ << "\n";
394
395 PrintIndent();
396 os_ << "xhandlers\n";
397
398 PrintIndent();
399 os_ << "flags\n";
400
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000401 if (current->dominator() != nullptr) {
402 PrintBlockProperty("dominator", current->dominator()->rpo_number());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400403 }
404
405 PrintIntProperty("loop_depth", current->loop_depth());
406
407 const InstructionBlock* instruction_block =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000408 instructions->InstructionBlockAt(
409 RpoNumber::FromInt(current->rpo_number()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400410 if (instruction_block->code_start() >= 0) {
411 int first_index = instruction_block->first_instruction_index();
412 int last_index = instruction_block->last_instruction_index();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000413 PrintIntProperty(
414 "first_lir_id",
415 LifetimePosition::GapFromInstructionIndex(first_index).value());
416 PrintIntProperty("last_lir_id",
417 LifetimePosition::InstructionFromInstructionIndex(
418 last_index).value());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400419 }
420
421 {
422 Tag states_tag(this, "states");
423 Tag locals_tag(this, "locals");
424 int total = 0;
425 for (BasicBlock::const_iterator i = current->begin(); i != current->end();
426 ++i) {
427 if ((*i)->opcode() == IrOpcode::kPhi) total++;
428 }
429 PrintIntProperty("size", total);
430 PrintStringProperty("method", "None");
431 int index = 0;
432 for (BasicBlock::const_iterator i = current->begin(); i != current->end();
433 ++i) {
434 if ((*i)->opcode() != IrOpcode::kPhi) continue;
435 PrintIndent();
436 os_ << index << " ";
437 PrintNodeId(*i);
438 os_ << " [";
439 PrintInputs(*i);
440 os_ << "]\n";
441 index++;
442 }
443 }
444
445 {
446 Tag HIR_tag(this, "HIR");
447 for (BasicBlock::const_iterator i = current->begin(); i != current->end();
448 ++i) {
449 Node* node = *i;
450 if (node->opcode() == IrOpcode::kPhi) continue;
451 int uses = node->UseCount();
452 PrintIndent();
453 os_ << "0 " << uses << " ";
454 PrintNode(node);
455 if (FLAG_trace_turbo_types) {
456 os_ << " ";
457 PrintType(node);
458 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000459 if (positions != nullptr) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400460 SourcePosition position = positions->GetSourcePosition(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000461 if (position.IsKnown()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400462 os_ << " pos:" << position.raw();
463 }
464 }
465 os_ << " <|@\n";
466 }
467
468 BasicBlock::Control control = current->control();
469 if (control != BasicBlock::kNone) {
470 PrintIndent();
471 os_ << "0 0 ";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000472 if (current->control_input() != nullptr) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400473 PrintNode(current->control_input());
474 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000475 os_ << -1 - current->rpo_number() << " Goto";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400476 }
477 os_ << " ->";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000478 for (BasicBlock* successor : current->successors()) {
479 os_ << " B" << successor->rpo_number();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400480 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000481 if (FLAG_trace_turbo_types && current->control_input() != nullptr) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400482 os_ << " ";
483 PrintType(current->control_input());
484 }
485 os_ << " <|@\n";
486 }
487 }
488
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000489 if (instructions != nullptr) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400490 Tag LIR_tag(this, "LIR");
491 for (int j = instruction_block->first_instruction_index();
492 j <= instruction_block->last_instruction_index(); j++) {
493 PrintIndent();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000494 PrintableInstruction printable = {
495 RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN),
496 instructions->InstructionAt(j)};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400497 os_ << j << " " << printable << " <|@\n";
498 }
499 }
500 }
501}
502
503
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000504void GraphC1Visualizer::PrintLiveRanges(const char* phase,
505 const RegisterAllocationData* data) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400506 Tag tag(this, "intervals");
507 PrintStringProperty("name", phase);
508
Ben Murdochda12d292016-06-02 14:46:10 +0100509 for (const TopLevelLiveRange* range : data->fixed_double_live_ranges()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000510 PrintLiveRangeChain(range, "fixed");
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400511 }
512
Ben Murdochda12d292016-06-02 14:46:10 +0100513 for (const TopLevelLiveRange* range : data->fixed_live_ranges()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000514 PrintLiveRangeChain(range, "fixed");
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400515 }
516
Ben Murdochda12d292016-06-02 14:46:10 +0100517 for (const TopLevelLiveRange* range : data->live_ranges()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000518 PrintLiveRangeChain(range, "object");
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400519 }
520}
521
Ben Murdochda12d292016-06-02 14:46:10 +0100522void GraphC1Visualizer::PrintLiveRangeChain(const TopLevelLiveRange* range,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000523 const char* type) {
524 if (range == nullptr || range->IsEmpty()) return;
525 int vreg = range->vreg();
Ben Murdochda12d292016-06-02 14:46:10 +0100526 for (const LiveRange* child = range; child != nullptr;
527 child = child->next()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000528 PrintLiveRange(child, type, vreg);
529 }
530}
531
Ben Murdochda12d292016-06-02 14:46:10 +0100532void GraphC1Visualizer::PrintLiveRange(const LiveRange* range, const char* type,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000533 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()) {
Ben Murdochda12d292016-06-02 14:46:10 +0100548 const TopLevelLiveRange* top = range->TopLevel();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000549 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;
Ben Murdochda12d292016-06-02 14:46:10 +0100567 for (const UseInterval* interval = range->first_interval();
568 interval != nullptr; interval = interval->next()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000569 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 Murdochda12d292016-06-02 14:46:10 +0100587 base::AccountingAllocator allocator;
588 Zone tmp_zone(&allocator);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400589 GraphC1Visualizer(os, &tmp_zone).PrintCompilation(ac.info_);
590 return os;
591}
592
593
594std::ostream& operator<<(std::ostream& os, const AsC1V& ac) {
Ben Murdochda12d292016-06-02 14:46:10 +0100595 base::AccountingAllocator allocator;
596 Zone tmp_zone(&allocator);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400597 GraphC1Visualizer(os, &tmp_zone)
598 .PrintSchedule(ac.phase_, ac.schedule_, ac.positions_, ac.instructions_);
599 return os;
600}
601
602
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000603std::ostream& operator<<(std::ostream& os,
604 const AsC1VRegisterAllocationData& ac) {
Ben Murdochda12d292016-06-02 14:46:10 +0100605 base::AccountingAllocator allocator;
606 Zone tmp_zone(&allocator);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000607 GraphC1Visualizer(os, &tmp_zone).PrintLiveRanges(ac.phase_, ac.data_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400608 return os;
609}
610
611const int kUnvisited = 0;
612const int kOnStack = 1;
613const int kVisited = 2;
614
615std::ostream& operator<<(std::ostream& os, const AsRPO& ar) {
Ben Murdochda12d292016-06-02 14:46:10 +0100616 base::AccountingAllocator allocator;
617 Zone local_zone(&allocator);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400618 ZoneVector<byte> state(ar.graph.NodeCount(), kUnvisited, &local_zone);
619 ZoneStack<Node*> stack(&local_zone);
620
621 stack.push(ar.graph.end());
622 state[ar.graph.end()->id()] = kOnStack;
623 while (!stack.empty()) {
624 Node* n = stack.top();
625 bool pop = true;
626 for (Node* const i : n->inputs()) {
627 if (state[i->id()] == kUnvisited) {
628 state[i->id()] = kOnStack;
629 stack.push(i);
630 pop = false;
631 break;
632 }
633 }
634 if (pop) {
635 state[n->id()] = kVisited;
636 stack.pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000637 os << "#" << n->id() << ":" << *n->op() << "(";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400638 int j = 0;
639 for (Node* const i : n->inputs()) {
640 if (j++ > 0) os << ", ";
641 os << "#" << SafeId(i) << ":" << SafeMnemonic(i);
642 }
643 os << ")" << std::endl;
644 }
645 }
646 return os;
647}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000648} // namespace compiler
649} // namespace internal
650} // namespace v8