OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/graph-visualizer.h" | 5 #include "src/compiler/graph-visualizer.h" |
6 | 6 |
7 #include <sstream> | 7 #include <sstream> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
200 Zone tmp_zone; | 200 Zone tmp_zone; |
201 os << "{\n\"nodes\":["; | 201 os << "{\n\"nodes\":["; |
202 JSONGraphNodeWriter(os, &tmp_zone, &ad.graph, ad.positions).Print(); | 202 JSONGraphNodeWriter(os, &tmp_zone, &ad.graph, ad.positions).Print(); |
203 os << "],\n\"edges\":["; | 203 os << "],\n\"edges\":["; |
204 JSONGraphEdgeWriter(os, &tmp_zone, &ad.graph).Print(); | 204 JSONGraphEdgeWriter(os, &tmp_zone, &ad.graph).Print(); |
205 os << "]}"; | 205 os << "]}"; |
206 return os; | 206 return os; |
207 } | 207 } |
208 | 208 |
209 | 209 |
210 class GraphVisualizer { | |
211 public: | |
212 GraphVisualizer(std::ostream& os, Zone* zone, const Graph* graph) | |
213 : all_(zone, graph), os_(os) {} | |
214 | |
215 void Print(); | |
216 | |
217 void PrintNode(Node* node, bool gray); | |
218 | |
219 private: | |
220 void PrintEdge(Edge edge); | |
221 | |
222 AllNodes all_; | |
223 std::ostream& os_; | |
224 | |
225 DISALLOW_COPY_AND_ASSIGN(GraphVisualizer); | |
226 }; | |
227 | |
228 | |
229 static Node* GetControlCluster(Node* node) { | |
230 if (OperatorProperties::IsBasicBlockBegin(node->op())) { | |
231 return node; | |
232 } else if (node->op()->ControlInputCount() == 1) { | |
233 Node* control = NodeProperties::GetControlInput(node, 0); | |
234 return control != NULL && | |
235 OperatorProperties::IsBasicBlockBegin(control->op()) | |
236 ? control | |
237 : NULL; | |
238 } else { | |
239 return NULL; | |
240 } | |
241 } | |
242 | |
243 | |
244 void GraphVisualizer::PrintNode(Node* node, bool gray) { | |
245 Node* control_cluster = GetControlCluster(node); | |
246 if (control_cluster != NULL) { | |
247 os_ << " subgraph cluster_BasicBlock" << control_cluster->id() << " {\n"; | |
248 } | |
249 os_ << " ID" << SafeId(node) << " [\n"; | |
250 | |
251 os_ << " shape=\"record\"\n"; | |
252 switch (node->opcode()) { | |
253 case IrOpcode::kEnd: | |
254 case IrOpcode::kDead: | |
255 case IrOpcode::kStart: | |
256 os_ << " style=\"diagonals\"\n"; | |
257 break; | |
258 case IrOpcode::kMerge: | |
259 case IrOpcode::kIfTrue: | |
260 case IrOpcode::kIfFalse: | |
261 case IrOpcode::kLoop: | |
262 os_ << " style=\"rounded\"\n"; | |
263 break; | |
264 default: | |
265 break; | |
266 } | |
267 | |
268 if (gray) { | |
269 os_ << " style=\"filled\"\n" | |
270 << " fillcolor=\"" DEAD_COLOR "\"\n"; | |
271 } | |
272 | |
273 std::ostringstream label; | |
274 label << *node->op(); | |
275 os_ << " label=\"{{#" << SafeId(node) << ":" << Escaped(label); | |
276 | |
277 auto i = node->input_edges().begin(); | |
278 for (int j = node->op()->ValueInputCount(); j > 0; ++i, j--) { | |
279 os_ << "|<I" << (*i).index() << ">#" << SafeId((*i).to()); | |
280 } | |
281 for (int j = OperatorProperties::GetContextInputCount(node->op()); j > 0; | |
282 ++i, j--) { | |
283 os_ << "|<I" << (*i).index() << ">X #" << SafeId((*i).to()); | |
284 } | |
285 for (int j = OperatorProperties::GetFrameStateInputCount(node->op()); j > 0; | |
286 ++i, j--) { | |
287 os_ << "|<I" << (*i).index() << ">F #" << SafeId((*i).to()); | |
288 } | |
289 for (int j = node->op()->EffectInputCount(); j > 0; ++i, j--) { | |
290 os_ << "|<I" << (*i).index() << ">E #" << SafeId((*i).to()); | |
291 } | |
292 | |
293 if (OperatorProperties::IsBasicBlockBegin(node->op()) || | |
294 GetControlCluster(node) == NULL) { | |
295 for (int j = node->op()->ControlInputCount(); j > 0; ++i, j--) { | |
296 os_ << "|<I" << (*i).index() << ">C #" << SafeId((*i).to()); | |
297 } | |
298 } | |
299 os_ << "}"; | |
300 | |
301 if (FLAG_trace_turbo_types && NodeProperties::IsTyped(node)) { | |
302 Type* type = NodeProperties::GetType(node); | |
303 std::ostringstream type_out; | |
304 type->PrintTo(type_out); | |
305 os_ << "|" << Escaped(type_out); | |
306 } | |
307 os_ << "}\"\n"; | |
308 | |
309 os_ << " ]\n"; | |
310 if (control_cluster != NULL) os_ << " }\n"; | |
311 } | |
312 | |
313 | |
314 static bool IsLikelyBackEdge(Node* from, int index, Node* to) { | |
315 if (NodeProperties::IsPhi(from)) { | |
316 Node* control = NodeProperties::GetControlInput(from, 0); | |
317 return control != NULL && control->opcode() != IrOpcode::kMerge && | |
318 control != to && index != 0; | |
319 } else if (from->opcode() == IrOpcode::kLoop) { | |
320 return index != 0; | |
321 } else { | |
322 return false; | |
323 } | |
324 } | |
325 | |
326 | |
327 void GraphVisualizer::PrintEdge(Edge edge) { | |
328 Node* from = edge.from(); | |
329 int index = edge.index(); | |
330 Node* to = edge.to(); | |
331 | |
332 if (!all_.IsLive(to)) return; // skip inputs that point to dead or NULL. | |
333 | |
334 bool unconstrained = IsLikelyBackEdge(from, index, to); | |
335 os_ << " ID" << SafeId(from); | |
336 | |
337 if (OperatorProperties::IsBasicBlockBegin(from->op()) || | |
338 GetControlCluster(from) == NULL || | |
339 (from->op()->ControlInputCount() > 0 && | |
340 NodeProperties::GetControlInput(from) != to)) { | |
341 os_ << ":I" << index << ":n -> ID" << SafeId(to) << ":s" | |
342 << "[" << (unconstrained ? "constraint=false, " : "") | |
343 << (NodeProperties::IsControlEdge(edge) ? "style=bold, " : "") | |
344 << (NodeProperties::IsEffectEdge(edge) ? "style=dotted, " : "") | |
345 << (NodeProperties::IsContextEdge(edge) ? "style=dashed, " : "") << "]"; | |
346 } else { | |
347 os_ << " -> ID" << SafeId(to) << ":s [color=transparent, " | |
348 << (unconstrained ? "constraint=false, " : "") | |
349 << (NodeProperties::IsControlEdge(edge) ? "style=dashed, " : "") << "]"; | |
350 } | |
351 os_ << "\n"; | |
352 } | |
353 | |
354 | |
355 void GraphVisualizer::Print() { | |
356 os_ << "digraph D {\n" | |
357 << " node [fontsize=8,height=0.25]\n" | |
358 << " rankdir=\"BT\"\n" | |
359 << " ranksep=\"1.2 equally\"\n" | |
360 << " overlap=\"false\"\n" | |
361 << " splines=\"true\"\n" | |
362 << " concentrate=\"true\"\n" | |
363 << " \n"; | |
364 | |
365 // Find all nodes that are not reachable from end that use live nodes. | |
366 std::set<Node*> gray; | |
367 for (Node* const node : all_.live) { | |
368 for (Node* const use : node->uses()) { | |
369 if (!all_.IsLive(use)) gray.insert(use); | |
370 } | |
371 } | |
372 | |
373 // Make sure all nodes have been output before writing out the edges. | |
374 for (Node* const node : all_.live) PrintNode(node, false); | |
375 for (Node* const node : gray) PrintNode(node, true); | |
376 | |
377 // With all the nodes written, add the edges. | |
378 for (Node* const node : all_.live) { | |
379 for (Edge edge : node->use_edges()) { | |
380 PrintEdge(edge); | |
381 } | |
382 } | |
383 os_ << "}\n"; | |
384 } | |
385 | |
386 | |
387 std::ostream& operator<<(std::ostream& os, const AsDOT& ad) { | |
388 Zone tmp_zone; | |
389 GraphVisualizer(os, &tmp_zone, &ad.graph).Print(); | |
390 return os; | |
391 } | |
392 | |
393 | |
394 class GraphC1Visualizer { | 210 class GraphC1Visualizer { |
395 public: | 211 public: |
396 GraphC1Visualizer(std::ostream& os, Zone* zone); // NOLINT | 212 GraphC1Visualizer(std::ostream& os, Zone* zone); // NOLINT |
397 | 213 |
398 void PrintCompilation(const CompilationInfo* info); | 214 void PrintCompilation(const CompilationInfo* info); |
399 void PrintSchedule(const char* phase, const Schedule* schedule, | 215 void PrintSchedule(const char* phase, const Schedule* schedule, |
400 const SourcePositionTable* positions, | 216 const SourcePositionTable* positions, |
401 const InstructionSequence* instructions); | 217 const InstructionSequence* instructions); |
402 void PrintLiveRanges(const char* phase, const RegisterAllocationData* data); | 218 void PrintLiveRanges(const char* phase, const RegisterAllocationData* data); |
403 Zone* zone() const { return zone_; } | 219 Zone* zone() const { return zone_; } |
(...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
821 os << "#" << SafeId(i) << ":" << SafeMnemonic(i); | 637 os << "#" << SafeId(i) << ":" << SafeMnemonic(i); |
822 } | 638 } |
823 os << ")" << std::endl; | 639 os << ")" << std::endl; |
824 } | 640 } |
825 } | 641 } |
826 return os; | 642 return os; |
827 } | 643 } |
828 } // namespace compiler | 644 } // namespace compiler |
829 } // namespace internal | 645 } // namespace internal |
830 } // namespace v8 | 646 } // namespace v8 |
OLD | NEW |