1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2013 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/graph-visualizer.h" 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/generic-algorithm.h" 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/generic-node.h" 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/generic-node-inl.h" 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/graph.h" 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/graph-inl.h" 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/node.h" 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/node-properties.h" 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/node-properties-inl.h" 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/opcodes.h" 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/operator.h" 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ostreams.h" 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace compiler { 22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define DEAD_COLOR "#999999" 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass GraphVisualizer : public NullNodeVisitor { 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GraphVisualizer(OStream& os, Zone* zone, const Graph* graph); // NOLINT 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Print(); 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenericGraphVisit::Control Pre(Node* node); 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenericGraphVisit::Control PreEdge(Node* from, int index, Node* to); 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void AnnotateNode(Node* node); 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void PrintEdge(Node::Edge edge); 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Zone* zone_; 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NodeSet all_nodes_; 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NodeSet white_nodes_; 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool use_to_def_; 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OStream& os_; 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Graph* const graph_; 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DISALLOW_COPY_AND_ASSIGN(GraphVisualizer); 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic Node* GetControlCluster(Node* node) { 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (OperatorProperties::IsBasicBlockBegin(node->op())) { 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return node; 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (OperatorProperties::GetControlInputCount(node->op()) == 1) { 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* control = NodeProperties::GetControlInput(node, 0); 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return OperatorProperties::IsBasicBlockBegin(control->op()) ? control 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : NULL; 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return NULL; 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochGenericGraphVisit::Control GraphVisualizer::Pre(Node* node) { 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (all_nodes_.count(node) == 0) { 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* control_cluster = GetControlCluster(node); 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (control_cluster != NULL) { 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os_ << " subgraph cluster_BasicBlock" << control_cluster->id() << " {\n"; 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os_ << " ID" << node->id() << " [\n"; 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AnnotateNode(node); 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os_ << " ]\n"; 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (control_cluster != NULL) os_ << " }\n"; 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch all_nodes_.insert(node); 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (use_to_def_) white_nodes_.insert(node); 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return GenericGraphVisit::CONTINUE; 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochGenericGraphVisit::Control GraphVisualizer::PreEdge(Node* from, int index, 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* to) { 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (use_to_def_) return GenericGraphVisit::CONTINUE; 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // When going from def to use, only consider white -> other edges, which are 83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the dead nodes that use live nodes. We're probably not interested in 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // dead nodes that only use other dead nodes. 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (white_nodes_.count(from) > 0) return GenericGraphVisit::CONTINUE; 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return GenericGraphVisit::SKIP; 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass Escaped { 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit Escaped(const OStringStream& os) : str_(os.c_str()) {} 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch friend OStream& operator<<(OStream& os, const Escaped& e) { 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (const char* s = e.str_; *s != '\0'; ++s) { 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (needs_escape(*s)) os << "\\"; 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os << *s; 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return os; 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool needs_escape(char ch) { 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (ch) { 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case '>': 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case '<': 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case '|': 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case '}': 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case '{': 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return true; 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* const str_; 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic bool IsLikelyBackEdge(Node* from, int index, Node* to) { 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (from->opcode() == IrOpcode::kPhi || 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch from->opcode() == IrOpcode::kEffectPhi) { 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* control = NodeProperties::GetControlInput(from, 0); 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return control->opcode() != IrOpcode::kMerge && control != to && index != 0; 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (from->opcode() == IrOpcode::kLoop) { 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return index != 0; 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid GraphVisualizer::AnnotateNode(Node* node) { 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!use_to_def_) { 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os_ << " style=\"filled\"\n" 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch << " fillcolor=\"" DEAD_COLOR "\"\n"; 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os_ << " shape=\"record\"\n"; 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (node->opcode()) { 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case IrOpcode::kEnd: 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case IrOpcode::kDead: 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case IrOpcode::kStart: 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os_ << " style=\"diagonals\"\n"; 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case IrOpcode::kMerge: 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case IrOpcode::kIfTrue: 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case IrOpcode::kIfFalse: 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case IrOpcode::kLoop: 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os_ << " style=\"rounded\"\n"; 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OStringStream label; 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch label << *node->op(); 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os_ << " label=\"{{#" << node->id() << ":" << Escaped(label); 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InputIter i = node->inputs().begin(); 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int j = OperatorProperties::GetValueInputCount(node->op()); j > 0; 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++i, j--) { 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os_ << "|<I" << i.index() << ">#" << (*i)->id(); 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int j = OperatorProperties::GetContextInputCount(node->op()); j > 0; 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++i, j--) { 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os_ << "|<I" << i.index() << ">X #" << (*i)->id(); 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int j = OperatorProperties::GetFrameStateInputCount(node->op()); j > 0; 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++i, j--) { 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os_ << "|<I" << i.index() << ">F #" << (*i)->id(); 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int j = OperatorProperties::GetEffectInputCount(node->op()); j > 0; 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++i, j--) { 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os_ << "|<I" << i.index() << ">E #" << (*i)->id(); 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!use_to_def_ || OperatorProperties::IsBasicBlockBegin(node->op()) || 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GetControlCluster(node) == NULL) { 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int j = OperatorProperties::GetControlInputCount(node->op()); j > 0; 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++i, j--) { 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os_ << "|<I" << i.index() << ">C #" << (*i)->id(); 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os_ << "}"; 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_trace_turbo_types && !NodeProperties::IsControl(node)) { 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Bounds bounds = NodeProperties::GetBounds(node); 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OStringStream upper; 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bounds.upper->PrintTo(upper); 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OStringStream lower; 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bounds.lower->PrintTo(lower); 193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os_ << "|" << Escaped(upper) << "|" << Escaped(lower); 194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os_ << "}\"\n"; 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid GraphVisualizer::PrintEdge(Node::Edge edge) { 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* from = edge.from(); 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int index = edge.index(); 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node* to = edge.to(); 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool unconstrained = IsLikelyBackEdge(from, index, to); 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os_ << " ID" << from->id(); 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (all_nodes_.count(to) == 0) { 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os_ << ":I" << index << ":n -> DEAD_INPUT"; 207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (OperatorProperties::IsBasicBlockBegin(from->op()) || 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GetControlCluster(from) == NULL || 209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (OperatorProperties::GetControlInputCount(from->op()) > 0 && 210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NodeProperties::GetControlInput(from) != to)) { 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os_ << ":I" << index << ":n -> ID" << to->id() << ":s" 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch << "[" << (unconstrained ? "constraint=false, " : "") 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch << (NodeProperties::IsControlEdge(edge) ? "style=bold, " : "") 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch << (NodeProperties::IsEffectEdge(edge) ? "style=dotted, " : "") 215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch << (NodeProperties::IsContextEdge(edge) ? "style=dashed, " : "") << "]"; 216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os_ << " -> ID" << to->id() << ":s [color=transparent, " 218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch << (unconstrained ? "constraint=false, " : "") 219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch << (NodeProperties::IsControlEdge(edge) ? "style=dashed, " : "") << "]"; 220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os_ << "\n"; 222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid GraphVisualizer::Print() { 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os_ << "digraph D {\n" 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch << " node [fontsize=8,height=0.25]\n" 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch << " rankdir=\"BT\"\n" 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch << " ranksep=\"1.2 equally\"\n" 230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch << " overlap=\"false\"\n" 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch << " splines=\"true\"\n" 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch << " concentrate=\"true\"\n" 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch << " \n"; 234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Make sure all nodes have been output before writing out the edges. 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch use_to_def_ = true; 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(svenpanne) Remove the need for the const_casts. 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const_cast<Graph*>(graph_)->VisitNodeInputsFromEnd(this); 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch white_nodes_.insert(const_cast<Graph*>(graph_)->start()); 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Visit all uses of white nodes. 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch use_to_def_ = false; 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenericGraphVisit::Visit<GraphVisualizer, NodeUseIterationTraits<Node> >( 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const_cast<Graph*>(graph_), zone_, white_nodes_.begin(), 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch white_nodes_.end(), this); 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os_ << " DEAD_INPUT [\n" 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch << " style=\"filled\" \n" 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch << " fillcolor=\"" DEAD_COLOR "\"\n" 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch << " ]\n" 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch << "\n"; 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // With all the nodes written, add the edges. 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (NodeSetIter i = all_nodes_.begin(); i != all_nodes_.end(); ++i) { 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Node::Inputs inputs = (*i)->inputs(); 256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (Node::Inputs::iterator iter(inputs.begin()); iter != inputs.end(); 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++iter) { 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrintEdge(iter.edge()); 259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os_ << "}\n"; 262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochGraphVisualizer::GraphVisualizer(OStream& os, Zone* zone, 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Graph* graph) // NOLINT 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : zone_(zone), 268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch all_nodes_(NodeSet::key_compare(), NodeSet::allocator_type(zone)), 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch white_nodes_(NodeSet::key_compare(), NodeSet::allocator_type(zone)), 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch use_to_def_(true), 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch os_(os), 272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch graph_(graph) {} 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochOStream& operator<<(OStream& os, const AsDOT& ad) { 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Zone tmp_zone(ad.graph.zone()->isolate()); 277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GraphVisualizer(os, &tmp_zone, &ad.graph).Print(); 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return os; 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} // namespace v8::internal::compiler 283