blob: 2e397648423635896aa29e289ac88197d4bef139 [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 Murdochc5610432016-08-08 18:44:38 +010028base::SmartArrayPointer<const char> GetVisualizerLogFileName(
29 CompilationInfo* info, const char* phase, const char* suffix) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000030 EmbeddedVector<char, 256> filename(0);
31 base::SmartArrayPointer<char> debug_name = info->GetDebugName();
32 if (strlen(debug_name.get()) > 0) {
33 SNPrintF(filename, "turbo-%s", debug_name.get());
34 } else if (info->has_shared_info()) {
35 SNPrintF(filename, "turbo-%p", static_cast<void*>(info));
36 } else {
37 SNPrintF(filename, "turbo-none-%s", phase);
38 }
Ben Murdoch61f157c2016-09-16 13:49:30 +010039 EmbeddedVector<char, 256> source_file(0);
40 bool source_available = false;
41 if (FLAG_trace_file_names && info->parse_info()) {
42 Object* source_name = info->script()->name();
43 if (source_name->IsString()) {
44 String* str = String::cast(source_name);
45 if (str->length() > 0) {
46 SNPrintF(source_file, "%s", str->ToCString().get());
47 std::replace(source_file.start(),
48 source_file.start() + source_file.length(), '/', '_');
49 source_available = true;
50 }
51 }
52 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000053 std::replace(filename.start(), filename.start() + filename.length(), ' ',
54 '_');
55
56 EmbeddedVector<char, 256> full_filename;
Ben Murdoch61f157c2016-09-16 13:49:30 +010057 if (phase == nullptr && !source_available) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000058 SNPrintF(full_filename, "%s.%s", filename.start(), suffix);
Ben Murdoch61f157c2016-09-16 13:49:30 +010059 } else if (phase != nullptr && !source_available) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000060 SNPrintF(full_filename, "%s-%s.%s", filename.start(), phase, suffix);
Ben Murdoch61f157c2016-09-16 13:49:30 +010061 } else if (phase == nullptr && source_available) {
62 SNPrintF(full_filename, "%s_%s.%s", filename.start(), source_file.start(),
63 suffix);
64 } else {
65 SNPrintF(full_filename, "%s_%s-%s.%s", filename.start(),
66 source_file.start(), phase, suffix);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000067 }
Ben Murdochc5610432016-08-08 18:44:38 +010068
69 char* buffer = new char[full_filename.length() + 1];
70 memcpy(buffer, full_filename.start(), full_filename.length());
71 buffer[full_filename.length()] = '\0';
72 return base::SmartArrayPointer<const char>(buffer);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000073}
74
75
76static int SafeId(Node* node) { return node == nullptr ? -1 : node->id(); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040077static const char* SafeMnemonic(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000078 return node == nullptr ? "null" : node->op()->mnemonic();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040079}
80
Ben Murdochb8a8cc12014-11-26 15:28:44 +000081#define DEAD_COLOR "#999999"
82
Emily Bernierd0a1eb72015-03-24 16:35:39 -040083class Escaped {
84 public:
85 explicit Escaped(const std::ostringstream& os,
86 const char* escaped_chars = "<>|{}")
87 : str_(os.str()), escaped_chars_(escaped_chars) {}
88
89 friend std::ostream& operator<<(std::ostream& os, const Escaped& e) {
90 for (std::string::const_iterator i = e.str_.begin(); i != e.str_.end();
91 ++i) {
92 if (e.needs_escape(*i)) os << "\\";
93 os << *i;
94 }
95 return os;
96 }
97
98 private:
99 bool needs_escape(char ch) const {
100 for (size_t i = 0; i < strlen(escaped_chars_); ++i) {
101 if (ch == escaped_chars_[i]) return true;
102 }
103 return false;
104 }
105
106 const std::string str_;
107 const char* const escaped_chars_;
108};
109
110class JSONGraphNodeWriter {
111 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000112 JSONGraphNodeWriter(std::ostream& os, Zone* zone, const Graph* graph,
113 const SourcePositionTable* positions)
114 : os_(os), all_(zone, graph), positions_(positions), first_node_(true) {}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400115
116 void Print() {
117 for (Node* const node : all_.live) PrintNode(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000118 os_ << "\n";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400119 }
120
121 void PrintNode(Node* node) {
122 if (first_node_) {
123 first_node_ = false;
124 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000125 os_ << ",\n";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400126 }
127 std::ostringstream label;
128 label << *node->op();
129 os_ << "{\"id\":" << SafeId(node) << ",\"label\":\"" << Escaped(label, "\"")
130 << "\"";
131 IrOpcode::Value opcode = node->opcode();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000132 if (IrOpcode::IsPhiOpcode(opcode)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400133 os_ << ",\"rankInputs\":[0," << NodeProperties::FirstControlIndex(node)
134 << "]";
135 os_ << ",\"rankWithInput\":[" << NodeProperties::FirstControlIndex(node)
136 << "]";
137 } else if (opcode == IrOpcode::kIfTrue || opcode == IrOpcode::kIfFalse ||
138 opcode == IrOpcode::kLoop) {
139 os_ << ",\"rankInputs\":[" << NodeProperties::FirstControlIndex(node)
140 << "]";
141 }
142 if (opcode == IrOpcode::kBranch) {
143 os_ << ",\"rankInputs\":[0]";
144 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000145 SourcePosition position = positions_->GetSourcePosition(node);
146 if (position.IsKnown()) {
147 os_ << ",\"pos\":" << position.raw();
148 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400149 os_ << ",\"opcode\":\"" << IrOpcode::Mnemonic(node->opcode()) << "\"";
150 os_ << ",\"control\":" << (NodeProperties::IsControl(node) ? "true"
151 : "false");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000152 if (NodeProperties::IsTyped(node)) {
153 Type* type = NodeProperties::GetType(node);
154 std::ostringstream type_out;
155 type->PrintTo(type_out);
156 os_ << ",\"type\":\"" << Escaped(type_out, "\"") << "\"";
157 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400158 os_ << "}";
159 }
160
161 private:
162 std::ostream& os_;
163 AllNodes all_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000164 const SourcePositionTable* positions_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400165 bool first_node_;
166
167 DISALLOW_COPY_AND_ASSIGN(JSONGraphNodeWriter);
168};
169
170
171class JSONGraphEdgeWriter {
172 public:
173 JSONGraphEdgeWriter(std::ostream& os, Zone* zone, const Graph* graph)
174 : os_(os), all_(zone, graph), first_edge_(true) {}
175
176 void Print() {
177 for (Node* const node : all_.live) PrintEdges(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000178 os_ << "\n";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400179 }
180
181 void PrintEdges(Node* node) {
182 for (int i = 0; i < node->InputCount(); i++) {
183 Node* input = node->InputAt(i);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000184 if (input == nullptr) continue;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400185 PrintEdge(node, i, input);
186 }
187 }
188
189 void PrintEdge(Node* from, int index, Node* to) {
190 if (first_edge_) {
191 first_edge_ = false;
192 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000193 os_ << ",\n";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400194 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000195 const char* edge_type = nullptr;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400196 if (index < NodeProperties::FirstValueIndex(from)) {
197 edge_type = "unknown";
198 } else if (index < NodeProperties::FirstContextIndex(from)) {
199 edge_type = "value";
200 } else if (index < NodeProperties::FirstFrameStateIndex(from)) {
201 edge_type = "context";
202 } else if (index < NodeProperties::FirstEffectIndex(from)) {
203 edge_type = "frame-state";
204 } else if (index < NodeProperties::FirstControlIndex(from)) {
205 edge_type = "effect";
206 } else {
207 edge_type = "control";
208 }
209 os_ << "{\"source\":" << SafeId(to) << ",\"target\":" << SafeId(from)
210 << ",\"index\":" << index << ",\"type\":\"" << edge_type << "\"}";
211 }
212
213 private:
214 std::ostream& os_;
215 AllNodes all_;
216 bool first_edge_;
217
218 DISALLOW_COPY_AND_ASSIGN(JSONGraphEdgeWriter);
219};
220
221
222std::ostream& operator<<(std::ostream& os, const AsJSON& ad) {
Ben Murdochda12d292016-06-02 14:46:10 +0100223 base::AccountingAllocator allocator;
224 Zone tmp_zone(&allocator);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000225 os << "{\n\"nodes\":[";
226 JSONGraphNodeWriter(os, &tmp_zone, &ad.graph, ad.positions).Print();
227 os << "],\n\"edges\":[";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400228 JSONGraphEdgeWriter(os, &tmp_zone, &ad.graph).Print();
229 os << "]}";
230 return os;
231}
232
233
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400234class GraphC1Visualizer {
235 public:
236 GraphC1Visualizer(std::ostream& os, Zone* zone); // NOLINT
237
238 void PrintCompilation(const CompilationInfo* info);
239 void PrintSchedule(const char* phase, const Schedule* schedule,
240 const SourcePositionTable* positions,
241 const InstructionSequence* instructions);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000242 void PrintLiveRanges(const char* phase, const RegisterAllocationData* data);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400243 Zone* zone() const { return zone_; }
244
245 private:
246 void PrintIndent();
247 void PrintStringProperty(const char* name, const char* value);
248 void PrintLongProperty(const char* name, int64_t value);
249 void PrintIntProperty(const char* name, int value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000250 void PrintBlockProperty(const char* name, int rpo_number);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400251 void PrintNodeId(Node* n);
252 void PrintNode(Node* n);
253 void PrintInputs(Node* n);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000254 template <typename InputIterator>
255 void PrintInputs(InputIterator* i, int count, const char* prefix);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400256 void PrintType(Node* node);
257
Ben Murdochda12d292016-06-02 14:46:10 +0100258 void PrintLiveRange(const LiveRange* range, const char* type, int vreg);
259 void PrintLiveRangeChain(const TopLevelLiveRange* range, const char* type);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000260
261 class Tag final BASE_EMBEDDED {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400262 public:
263 Tag(GraphC1Visualizer* visualizer, const char* name) {
264 name_ = name;
265 visualizer_ = visualizer;
266 visualizer->PrintIndent();
267 visualizer_->os_ << "begin_" << name << "\n";
268 visualizer->indent_++;
269 }
270
271 ~Tag() {
272 visualizer_->indent_--;
273 visualizer_->PrintIndent();
274 visualizer_->os_ << "end_" << name_ << "\n";
275 DCHECK(visualizer_->indent_ >= 0);
276 }
277
278 private:
279 GraphC1Visualizer* visualizer_;
280 const char* name_;
281 };
282
283 std::ostream& os_;
284 int indent_;
285 Zone* zone_;
286
287 DISALLOW_COPY_AND_ASSIGN(GraphC1Visualizer);
288};
289
290
291void GraphC1Visualizer::PrintIndent() {
292 for (int i = 0; i < indent_; i++) {
293 os_ << " ";
294 }
295}
296
297
298GraphC1Visualizer::GraphC1Visualizer(std::ostream& os, Zone* zone)
299 : os_(os), indent_(0), zone_(zone) {}
300
301
302void GraphC1Visualizer::PrintStringProperty(const char* name,
303 const char* value) {
304 PrintIndent();
305 os_ << name << " \"" << value << "\"\n";
306}
307
308
309void GraphC1Visualizer::PrintLongProperty(const char* name, int64_t value) {
310 PrintIndent();
311 os_ << name << " " << static_cast<int>(value / 1000) << "\n";
312}
313
314
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000315void GraphC1Visualizer::PrintBlockProperty(const char* name, int rpo_number) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400316 PrintIndent();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000317 os_ << name << " \"B" << rpo_number << "\"\n";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400318}
319
320
321void GraphC1Visualizer::PrintIntProperty(const char* name, int value) {
322 PrintIndent();
323 os_ << name << " " << value << "\n";
324}
325
326
327void GraphC1Visualizer::PrintCompilation(const CompilationInfo* info) {
328 Tag tag(this, "compilation");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000329 base::SmartArrayPointer<char> name = info->GetDebugName();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400330 if (info->IsOptimizing()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000331 PrintStringProperty("name", name.get());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400332 PrintIndent();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000333 os_ << "method \"" << name.get() << ":" << info->optimization_id()
334 << "\"\n";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400335 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000336 PrintStringProperty("name", name.get());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400337 PrintStringProperty("method", "stub");
338 }
339 PrintLongProperty("date",
340 static_cast<int64_t>(base::OS::TimeCurrentMillis()));
341}
342
343
344void GraphC1Visualizer::PrintNodeId(Node* n) { os_ << "n" << SafeId(n); }
345
346
347void GraphC1Visualizer::PrintNode(Node* n) {
348 PrintNodeId(n);
349 os_ << " " << *n->op() << " ";
350 PrintInputs(n);
351}
352
353
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000354template <typename InputIterator>
355void GraphC1Visualizer::PrintInputs(InputIterator* i, int count,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400356 const char* prefix) {
357 if (count > 0) {
358 os_ << prefix;
359 }
360 while (count > 0) {
361 os_ << " ";
362 PrintNodeId(**i);
363 ++(*i);
364 count--;
365 }
366}
367
368
369void GraphC1Visualizer::PrintInputs(Node* node) {
370 auto i = node->inputs().begin();
371 PrintInputs(&i, node->op()->ValueInputCount(), " ");
372 PrintInputs(&i, OperatorProperties::GetContextInputCount(node->op()),
373 " Ctx:");
374 PrintInputs(&i, OperatorProperties::GetFrameStateInputCount(node->op()),
375 " FS:");
376 PrintInputs(&i, node->op()->EffectInputCount(), " Eff:");
377 PrintInputs(&i, node->op()->ControlInputCount(), " Ctrl:");
378}
379
380
381void GraphC1Visualizer::PrintType(Node* node) {
382 if (NodeProperties::IsTyped(node)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000383 Type* type = NodeProperties::GetType(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400384 os_ << " type:";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000385 type->PrintTo(os_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400386 }
387}
388
389
390void GraphC1Visualizer::PrintSchedule(const char* phase,
391 const Schedule* schedule,
392 const SourcePositionTable* positions,
393 const InstructionSequence* instructions) {
394 Tag tag(this, "cfg");
395 PrintStringProperty("name", phase);
396 const BasicBlockVector* rpo = schedule->rpo_order();
397 for (size_t i = 0; i < rpo->size(); i++) {
398 BasicBlock* current = (*rpo)[i];
399 Tag block_tag(this, "block");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000400 PrintBlockProperty("name", current->rpo_number());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400401 PrintIntProperty("from_bci", -1);
402 PrintIntProperty("to_bci", -1);
403
404 PrintIndent();
405 os_ << "predecessors";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000406 for (BasicBlock* predecessor : current->predecessors()) {
407 os_ << " \"B" << predecessor->rpo_number() << "\"";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400408 }
409 os_ << "\n";
410
411 PrintIndent();
412 os_ << "successors";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000413 for (BasicBlock* successor : current->successors()) {
414 os_ << " \"B" << successor->rpo_number() << "\"";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400415 }
416 os_ << "\n";
417
418 PrintIndent();
419 os_ << "xhandlers\n";
420
421 PrintIndent();
422 os_ << "flags\n";
423
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000424 if (current->dominator() != nullptr) {
425 PrintBlockProperty("dominator", current->dominator()->rpo_number());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400426 }
427
428 PrintIntProperty("loop_depth", current->loop_depth());
429
430 const InstructionBlock* instruction_block =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000431 instructions->InstructionBlockAt(
432 RpoNumber::FromInt(current->rpo_number()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400433 if (instruction_block->code_start() >= 0) {
434 int first_index = instruction_block->first_instruction_index();
435 int last_index = instruction_block->last_instruction_index();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000436 PrintIntProperty(
437 "first_lir_id",
438 LifetimePosition::GapFromInstructionIndex(first_index).value());
439 PrintIntProperty("last_lir_id",
440 LifetimePosition::InstructionFromInstructionIndex(
441 last_index).value());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400442 }
443
444 {
445 Tag states_tag(this, "states");
446 Tag locals_tag(this, "locals");
447 int total = 0;
448 for (BasicBlock::const_iterator i = current->begin(); i != current->end();
449 ++i) {
450 if ((*i)->opcode() == IrOpcode::kPhi) total++;
451 }
452 PrintIntProperty("size", total);
453 PrintStringProperty("method", "None");
454 int index = 0;
455 for (BasicBlock::const_iterator i = current->begin(); i != current->end();
456 ++i) {
457 if ((*i)->opcode() != IrOpcode::kPhi) continue;
458 PrintIndent();
459 os_ << index << " ";
460 PrintNodeId(*i);
461 os_ << " [";
462 PrintInputs(*i);
463 os_ << "]\n";
464 index++;
465 }
466 }
467
468 {
469 Tag HIR_tag(this, "HIR");
470 for (BasicBlock::const_iterator i = current->begin(); i != current->end();
471 ++i) {
472 Node* node = *i;
473 if (node->opcode() == IrOpcode::kPhi) continue;
474 int uses = node->UseCount();
475 PrintIndent();
476 os_ << "0 " << uses << " ";
477 PrintNode(node);
478 if (FLAG_trace_turbo_types) {
479 os_ << " ";
480 PrintType(node);
481 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000482 if (positions != nullptr) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400483 SourcePosition position = positions->GetSourcePosition(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000484 if (position.IsKnown()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400485 os_ << " pos:" << position.raw();
486 }
487 }
488 os_ << " <|@\n";
489 }
490
491 BasicBlock::Control control = current->control();
492 if (control != BasicBlock::kNone) {
493 PrintIndent();
494 os_ << "0 0 ";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000495 if (current->control_input() != nullptr) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400496 PrintNode(current->control_input());
497 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000498 os_ << -1 - current->rpo_number() << " Goto";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400499 }
500 os_ << " ->";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000501 for (BasicBlock* successor : current->successors()) {
502 os_ << " B" << successor->rpo_number();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400503 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000504 if (FLAG_trace_turbo_types && current->control_input() != nullptr) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400505 os_ << " ";
506 PrintType(current->control_input());
507 }
508 os_ << " <|@\n";
509 }
510 }
511
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000512 if (instructions != nullptr) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400513 Tag LIR_tag(this, "LIR");
514 for (int j = instruction_block->first_instruction_index();
515 j <= instruction_block->last_instruction_index(); j++) {
516 PrintIndent();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100517 PrintableInstruction printable = {RegisterConfiguration::Turbofan(),
518 instructions->InstructionAt(j)};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400519 os_ << j << " " << printable << " <|@\n";
520 }
521 }
522 }
523}
524
525
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000526void GraphC1Visualizer::PrintLiveRanges(const char* phase,
527 const RegisterAllocationData* data) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400528 Tag tag(this, "intervals");
529 PrintStringProperty("name", phase);
530
Ben Murdochda12d292016-06-02 14:46:10 +0100531 for (const TopLevelLiveRange* range : data->fixed_double_live_ranges()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000532 PrintLiveRangeChain(range, "fixed");
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400533 }
534
Ben Murdochda12d292016-06-02 14:46:10 +0100535 for (const TopLevelLiveRange* range : data->fixed_live_ranges()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000536 PrintLiveRangeChain(range, "fixed");
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400537 }
538
Ben Murdochda12d292016-06-02 14:46:10 +0100539 for (const TopLevelLiveRange* range : data->live_ranges()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000540 PrintLiveRangeChain(range, "object");
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400541 }
542}
543
Ben Murdochda12d292016-06-02 14:46:10 +0100544void GraphC1Visualizer::PrintLiveRangeChain(const TopLevelLiveRange* range,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000545 const char* type) {
546 if (range == nullptr || range->IsEmpty()) return;
547 int vreg = range->vreg();
Ben Murdochda12d292016-06-02 14:46:10 +0100548 for (const LiveRange* child = range; child != nullptr;
549 child = child->next()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000550 PrintLiveRange(child, type, vreg);
551 }
552}
553
Ben Murdochda12d292016-06-02 14:46:10 +0100554void GraphC1Visualizer::PrintLiveRange(const LiveRange* range, const char* type,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000555 int vreg) {
556 if (range != nullptr && !range->IsEmpty()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400557 PrintIndent();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000558 os_ << vreg << ":" << range->relative_id() << " " << type;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400559 if (range->HasRegisterAssigned()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000560 AllocatedOperand op = AllocatedOperand::cast(range->GetAssignedOperand());
Ben Murdoch61f157c2016-09-16 13:49:30 +0100561 const auto config = RegisterConfiguration::Turbofan();
562 if (op.IsRegister()) {
563 os_ << " \"" << config->GetGeneralRegisterName(op.register_code())
564 << "\"";
565 } else if (op.IsDoubleRegister()) {
566 os_ << " \"" << config->GetDoubleRegisterName(op.register_code())
567 << "\"";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000568 } else {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100569 DCHECK(op.IsFloatRegister());
570 os_ << " \"" << config->GetFloatRegisterName(op.register_code())
571 << "\"";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000572 }
573 } else if (range->spilled()) {
Ben Murdochda12d292016-06-02 14:46:10 +0100574 const TopLevelLiveRange* top = range->TopLevel();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000575 int index = -1;
576 if (top->HasSpillRange()) {
577 index = kMaxInt; // This hasn't been set yet.
578 } else if (top->GetSpillOperand()->IsConstant()) {
579 os_ << " \"const(nostack):"
580 << ConstantOperand::cast(top->GetSpillOperand())->virtual_register()
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400581 << "\"";
582 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000583 index = AllocatedOperand::cast(top->GetSpillOperand())->index();
Ben Murdochc5610432016-08-08 18:44:38 +0100584 if (top->kind() == FP_REGISTERS) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000585 os_ << " \"double_stack:" << index << "\"";
586 } else if (top->kind() == GENERAL_REGISTERS) {
587 os_ << " \"stack:" << index << "\"";
588 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400589 }
590 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000591
592 os_ << " " << vreg;
Ben Murdochda12d292016-06-02 14:46:10 +0100593 for (const UseInterval* interval = range->first_interval();
594 interval != nullptr; interval = interval->next()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000595 os_ << " [" << interval->start().value() << ", "
596 << interval->end().value() << "[";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400597 }
598
599 UsePosition* current_pos = range->first_pos();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000600 while (current_pos != nullptr) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400601 if (current_pos->RegisterIsBeneficial() || FLAG_trace_all_uses) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000602 os_ << " " << current_pos->pos().value() << " M";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400603 }
604 current_pos = current_pos->next();
605 }
606
607 os_ << " \"\"\n";
608 }
609}
610
611
612std::ostream& operator<<(std::ostream& os, const AsC1VCompilation& ac) {
Ben Murdochda12d292016-06-02 14:46:10 +0100613 base::AccountingAllocator allocator;
614 Zone tmp_zone(&allocator);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400615 GraphC1Visualizer(os, &tmp_zone).PrintCompilation(ac.info_);
616 return os;
617}
618
619
620std::ostream& operator<<(std::ostream& os, const AsC1V& ac) {
Ben Murdochda12d292016-06-02 14:46:10 +0100621 base::AccountingAllocator allocator;
622 Zone tmp_zone(&allocator);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400623 GraphC1Visualizer(os, &tmp_zone)
624 .PrintSchedule(ac.phase_, ac.schedule_, ac.positions_, ac.instructions_);
625 return os;
626}
627
628
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000629std::ostream& operator<<(std::ostream& os,
630 const AsC1VRegisterAllocationData& ac) {
Ben Murdochda12d292016-06-02 14:46:10 +0100631 base::AccountingAllocator allocator;
632 Zone tmp_zone(&allocator);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000633 GraphC1Visualizer(os, &tmp_zone).PrintLiveRanges(ac.phase_, ac.data_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400634 return os;
635}
636
637const int kUnvisited = 0;
638const int kOnStack = 1;
639const int kVisited = 2;
640
641std::ostream& operator<<(std::ostream& os, const AsRPO& ar) {
Ben Murdochda12d292016-06-02 14:46:10 +0100642 base::AccountingAllocator allocator;
643 Zone local_zone(&allocator);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100644
645 // Do a post-order depth-first search on the RPO graph. For every node,
646 // print:
647 //
648 // - the node id
649 // - the operator mnemonic
650 // - in square brackets its parameter (if present)
651 // - in parentheses the list of argument ids and their mnemonics
652 // - the node type (if it is typed)
653
654 // Post-order guarantees that all inputs of a node will be printed before
655 // the node itself, if there are no cycles. Any cycles are broken
656 // arbitrarily.
657
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400658 ZoneVector<byte> state(ar.graph.NodeCount(), kUnvisited, &local_zone);
659 ZoneStack<Node*> stack(&local_zone);
660
661 stack.push(ar.graph.end());
662 state[ar.graph.end()->id()] = kOnStack;
663 while (!stack.empty()) {
664 Node* n = stack.top();
665 bool pop = true;
666 for (Node* const i : n->inputs()) {
667 if (state[i->id()] == kUnvisited) {
668 state[i->id()] = kOnStack;
669 stack.push(i);
670 pop = false;
671 break;
672 }
673 }
674 if (pop) {
675 state[n->id()] = kVisited;
676 stack.pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000677 os << "#" << n->id() << ":" << *n->op() << "(";
Ben Murdoch61f157c2016-09-16 13:49:30 +0100678 // Print the inputs.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400679 int j = 0;
680 for (Node* const i : n->inputs()) {
681 if (j++ > 0) os << ", ";
682 os << "#" << SafeId(i) << ":" << SafeMnemonic(i);
683 }
Ben Murdochc5610432016-08-08 18:44:38 +0100684 os << ")";
Ben Murdoch61f157c2016-09-16 13:49:30 +0100685 // Print the node type, if any.
Ben Murdochc5610432016-08-08 18:44:38 +0100686 if (NodeProperties::IsTyped(n)) {
687 os << " [Type: ";
688 NodeProperties::GetType(n)->PrintTo(os);
689 os << "]";
690 }
691 os << std::endl;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400692 }
693 }
694 return os;
695}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000696} // namespace compiler
697} // namespace internal
698} // namespace v8