Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(257)

Side by Side Diff: src/compiler/graph-visualizer.cc

Issue 426233002: Land the Fan (disabled) (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Review feedback, rebase and "git cl format" Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/compiler/graph-visualizer.h ('k') | src/compiler/ia32/code-generator-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // 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
7 #include "src/compiler/generic-algorithm.h"
8 #include "src/compiler/generic-node.h"
9 #include "src/compiler/generic-node-inl.h"
10 #include "src/compiler/graph.h"
11 #include "src/compiler/graph-inl.h"
12 #include "src/compiler/node.h"
13 #include "src/compiler/node-properties.h"
14 #include "src/compiler/node-properties-inl.h"
15 #include "src/compiler/opcodes.h"
16 #include "src/compiler/operator.h"
17 #include "src/ostreams.h"
18
19 namespace v8 {
20 namespace internal {
21 namespace compiler {
22
23 #define DEAD_COLOR "#999999"
24
25 class GraphVisualizer : public NullNodeVisitor {
26 public:
27 GraphVisualizer(OStream& os, const Graph* graph); // NOLINT
28
29 void Print();
30
31 GenericGraphVisit::Control Pre(Node* node);
32 GenericGraphVisit::Control PreEdge(Node* from, int index, Node* to);
33
34 private:
35 void AnnotateNode(Node* node);
36 void PrintEdge(Node* from, int index, Node* to);
37
38 NodeSet all_nodes_;
39 NodeSet white_nodes_;
40 bool use_to_def_;
41 OStream& os_;
42 const Graph* const graph_;
43
44 DISALLOW_COPY_AND_ASSIGN(GraphVisualizer);
45 };
46
47
48 static Node* GetControlCluster(Node* node) {
49 if (NodeProperties::IsBasicBlockBegin(node)) {
50 return node;
51 } else if (NodeProperties::GetControlInputCount(node) == 1) {
52 Node* control = NodeProperties::GetControlInput(node, 0);
53 return NodeProperties::IsBasicBlockBegin(control) ? control : NULL;
54 } else {
55 return NULL;
56 }
57 }
58
59
60 GenericGraphVisit::Control GraphVisualizer::Pre(Node* node) {
61 if (all_nodes_.count(node) == 0) {
62 Node* control_cluster = GetControlCluster(node);
63 if (control_cluster != NULL) {
64 os_ << " subgraph cluster_BasicBlock" << control_cluster->id() << " {\n";
65 }
66 os_ << " ID" << node->id() << " [\n";
67 AnnotateNode(node);
68 os_ << " ]\n";
69 if (control_cluster != NULL) os_ << " }\n";
70 all_nodes_.insert(node);
71 if (use_to_def_) white_nodes_.insert(node);
72 }
73 return GenericGraphVisit::CONTINUE;
74 }
75
76
77 GenericGraphVisit::Control GraphVisualizer::PreEdge(Node* from, int index,
78 Node* to) {
79 if (use_to_def_) return GenericGraphVisit::CONTINUE;
80 // When going from def to use, only consider white -> other edges, which are
81 // the dead nodes that use live nodes. We're probably not interested in
82 // dead nodes that only use other dead nodes.
83 if (white_nodes_.count(from) > 0) return GenericGraphVisit::CONTINUE;
84 return GenericGraphVisit::SKIP;
85 }
86
87
88 class Escaped {
89 public:
90 explicit Escaped(const OStringStream& os) : str_(os.c_str()) {}
91
92 friend OStream& operator<<(OStream& os, const Escaped& e) {
93 for (const char* s = e.str_; *s != '\0'; ++s) {
94 if (needs_escape(*s)) os << "\\";
95 os << *s;
96 }
97 return os;
98 }
99
100 private:
101 static bool needs_escape(char ch) {
102 switch (ch) {
103 case '>':
104 case '<':
105 case '|':
106 case '}':
107 case '{':
108 return true;
109 default:
110 return false;
111 }
112 }
113
114 const char* const str_;
115 };
116
117
118 static bool IsLikelyBackEdge(Node* from, int index, Node* to) {
119 if (from->opcode() == IrOpcode::kPhi ||
120 from->opcode() == IrOpcode::kEffectPhi) {
121 Node* control = NodeProperties::GetControlInput(from, 0);
122 return control->opcode() != IrOpcode::kMerge && control != to && index != 0;
123 } else if (from->opcode() == IrOpcode::kLoop) {
124 return index != 0;
125 } else {
126 return false;
127 }
128 }
129
130
131 void GraphVisualizer::AnnotateNode(Node* node) {
132 if (!use_to_def_) {
133 os_ << " style=\"filled\"\n"
134 << " fillcolor=\"" DEAD_COLOR "\"\n";
135 }
136
137 os_ << " shape=\"record\"\n";
138 switch (node->opcode()) {
139 case IrOpcode::kEnd:
140 case IrOpcode::kDead:
141 case IrOpcode::kStart:
142 os_ << " style=\"diagonals\"\n";
143 break;
144 case IrOpcode::kMerge:
145 case IrOpcode::kIfTrue:
146 case IrOpcode::kIfFalse:
147 case IrOpcode::kLoop:
148 os_ << " style=\"rounded\"\n";
149 break;
150 default:
151 break;
152 }
153
154 OStringStream label;
155 label << *node->op();
156 os_ << " label=\"{{#" << node->id() << ":" << Escaped(label);
157
158 InputIter i = node->inputs().begin();
159 for (int j = NodeProperties::GetValueInputCount(node); j > 0; ++i, j--) {
160 os_ << "|<I" << i.index() << ">#" << (*i)->id();
161 }
162 for (int j = NodeProperties::GetContextInputCount(node); j > 0; ++i, j--) {
163 os_ << "|<I" << i.index() << ">X #" << (*i)->id();
164 }
165 for (int j = NodeProperties::GetEffectInputCount(node); j > 0; ++i, j--) {
166 os_ << "|<I" << i.index() << ">E #" << (*i)->id();
167 }
168
169 if (!use_to_def_ || NodeProperties::IsBasicBlockBegin(node) ||
170 GetControlCluster(node) == NULL) {
171 for (int j = NodeProperties::GetControlInputCount(node); j > 0; ++i, j--) {
172 os_ << "|<I" << i.index() << ">C #" << (*i)->id();
173 }
174 }
175 os_ << "}";
176
177 if (FLAG_trace_turbo_types && !NodeProperties::IsControl(node)) {
178 Bounds bounds = NodeProperties::GetBounds(node);
179 OStringStream upper;
180 bounds.upper->PrintTo(upper);
181 OStringStream lower;
182 bounds.lower->PrintTo(lower);
183 os_ << "|" << Escaped(upper) << "|" << Escaped(lower);
184 }
185 os_ << "}\"\n";
186 }
187
188
189 void GraphVisualizer::PrintEdge(Node* from, int index, Node* to) {
190 bool unconstrained = IsLikelyBackEdge(from, index, to);
191 os_ << " ID" << from->id();
192 if (all_nodes_.count(to) == 0) {
193 os_ << ":I" << index << ":n -> DEAD_INPUT";
194 } else if (NodeProperties::IsBasicBlockBegin(from) ||
195 GetControlCluster(from) == NULL ||
196 (NodeProperties::GetControlInputCount(from) > 0 &&
197 NodeProperties::GetControlInput(from) != to)) {
198 os_ << ":I" << index << ":n -> ID" << to->id() << ":s";
199 if (unconstrained) os_ << " [constraint=false,style=dotted]";
200 } else {
201 os_ << " -> ID" << to->id() << ":s [color=transparent"
202 << (unconstrained ? ", constraint=false" : "") << "]";
203 }
204 os_ << "\n";
205 }
206
207
208 void GraphVisualizer::Print() {
209 os_ << "digraph D {\n"
210 << " node [fontsize=8,height=0.25]\n"
211 << " rankdir=\"BT\"\n"
212 << " \n";
213
214 // Make sure all nodes have been output before writing out the edges.
215 use_to_def_ = true;
216 // TODO(svenpanne) Remove the need for the const_casts.
217 const_cast<Graph*>(graph_)->VisitNodeInputsFromEnd(this);
218 white_nodes_.insert(const_cast<Graph*>(graph_)->start());
219
220 // Visit all uses of white nodes.
221 use_to_def_ = false;
222 GenericGraphVisit::Visit<GraphVisualizer, NodeUseIterationTraits<Node> >(
223 const_cast<Graph*>(graph_), white_nodes_.begin(), white_nodes_.end(),
224 this);
225
226 os_ << " DEAD_INPUT [\n"
227 << " style=\"filled\" \n"
228 << " fillcolor=\"" DEAD_COLOR "\"\n"
229 << " ]\n"
230 << "\n";
231
232 // With all the nodes written, add the edges.
233 for (NodeSetIter i = all_nodes_.begin(); i != all_nodes_.end(); ++i) {
234 Node::Inputs inputs = (*i)->inputs();
235 for (Node::Inputs::iterator iter(inputs.begin()); iter != inputs.end();
236 ++iter) {
237 PrintEdge(iter.edge().from(), iter.edge().index(), iter.edge().to());
238 }
239 }
240 os_ << "}\n";
241 }
242
243
244 GraphVisualizer::GraphVisualizer(OStream& os, const Graph* graph) // NOLINT
245 : all_nodes_(NodeSet::key_compare(),
246 NodeSet::allocator_type(graph->zone())),
247 white_nodes_(NodeSet::key_compare(),
248 NodeSet::allocator_type(graph->zone())),
249 use_to_def_(true),
250 os_(os),
251 graph_(graph) {}
252
253
254 OStream& operator<<(OStream& os, const AsDOT& ad) {
255 GraphVisualizer(os, &ad.graph).Print();
256 return os;
257 }
258 }
259 }
260 } // namespace v8::internal::compiler
OLDNEW
« no previous file with comments | « src/compiler/graph-visualizer.h ('k') | src/compiler/ia32/code-generator-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698