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

Unified 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, 5 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/compiler/graph-visualizer.h ('k') | src/compiler/ia32/code-generator-ia32.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/graph-visualizer.cc
diff --git a/src/compiler/graph-visualizer.cc b/src/compiler/graph-visualizer.cc
new file mode 100644
index 0000000000000000000000000000000000000000..032d3d95c6bb1a72e971f64f9f534b32180e2a72
--- /dev/null
+++ b/src/compiler/graph-visualizer.cc
@@ -0,0 +1,260 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/compiler/graph-visualizer.h"
+
+#include "src/compiler/generic-algorithm.h"
+#include "src/compiler/generic-node.h"
+#include "src/compiler/generic-node-inl.h"
+#include "src/compiler/graph.h"
+#include "src/compiler/graph-inl.h"
+#include "src/compiler/node.h"
+#include "src/compiler/node-properties.h"
+#include "src/compiler/node-properties-inl.h"
+#include "src/compiler/opcodes.h"
+#include "src/compiler/operator.h"
+#include "src/ostreams.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+#define DEAD_COLOR "#999999"
+
+class GraphVisualizer : public NullNodeVisitor {
+ public:
+ GraphVisualizer(OStream& os, const Graph* graph); // NOLINT
+
+ void Print();
+
+ GenericGraphVisit::Control Pre(Node* node);
+ GenericGraphVisit::Control PreEdge(Node* from, int index, Node* to);
+
+ private:
+ void AnnotateNode(Node* node);
+ void PrintEdge(Node* from, int index, Node* to);
+
+ NodeSet all_nodes_;
+ NodeSet white_nodes_;
+ bool use_to_def_;
+ OStream& os_;
+ const Graph* const graph_;
+
+ DISALLOW_COPY_AND_ASSIGN(GraphVisualizer);
+};
+
+
+static Node* GetControlCluster(Node* node) {
+ if (NodeProperties::IsBasicBlockBegin(node)) {
+ return node;
+ } else if (NodeProperties::GetControlInputCount(node) == 1) {
+ Node* control = NodeProperties::GetControlInput(node, 0);
+ return NodeProperties::IsBasicBlockBegin(control) ? control : NULL;
+ } else {
+ return NULL;
+ }
+}
+
+
+GenericGraphVisit::Control GraphVisualizer::Pre(Node* node) {
+ if (all_nodes_.count(node) == 0) {
+ Node* control_cluster = GetControlCluster(node);
+ if (control_cluster != NULL) {
+ os_ << " subgraph cluster_BasicBlock" << control_cluster->id() << " {\n";
+ }
+ os_ << " ID" << node->id() << " [\n";
+ AnnotateNode(node);
+ os_ << " ]\n";
+ if (control_cluster != NULL) os_ << " }\n";
+ all_nodes_.insert(node);
+ if (use_to_def_) white_nodes_.insert(node);
+ }
+ return GenericGraphVisit::CONTINUE;
+}
+
+
+GenericGraphVisit::Control GraphVisualizer::PreEdge(Node* from, int index,
+ Node* to) {
+ if (use_to_def_) return GenericGraphVisit::CONTINUE;
+ // When going from def to use, only consider white -> other edges, which are
+ // the dead nodes that use live nodes. We're probably not interested in
+ // dead nodes that only use other dead nodes.
+ if (white_nodes_.count(from) > 0) return GenericGraphVisit::CONTINUE;
+ return GenericGraphVisit::SKIP;
+}
+
+
+class Escaped {
+ public:
+ explicit Escaped(const OStringStream& os) : str_(os.c_str()) {}
+
+ friend OStream& operator<<(OStream& os, const Escaped& e) {
+ for (const char* s = e.str_; *s != '\0'; ++s) {
+ if (needs_escape(*s)) os << "\\";
+ os << *s;
+ }
+ return os;
+ }
+
+ private:
+ static bool needs_escape(char ch) {
+ switch (ch) {
+ case '>':
+ case '<':
+ case '|':
+ case '}':
+ case '{':
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ const char* const str_;
+};
+
+
+static bool IsLikelyBackEdge(Node* from, int index, Node* to) {
+ if (from->opcode() == IrOpcode::kPhi ||
+ from->opcode() == IrOpcode::kEffectPhi) {
+ Node* control = NodeProperties::GetControlInput(from, 0);
+ return control->opcode() != IrOpcode::kMerge && control != to && index != 0;
+ } else if (from->opcode() == IrOpcode::kLoop) {
+ return index != 0;
+ } else {
+ return false;
+ }
+}
+
+
+void GraphVisualizer::AnnotateNode(Node* node) {
+ if (!use_to_def_) {
+ os_ << " style=\"filled\"\n"
+ << " fillcolor=\"" DEAD_COLOR "\"\n";
+ }
+
+ os_ << " shape=\"record\"\n";
+ switch (node->opcode()) {
+ case IrOpcode::kEnd:
+ case IrOpcode::kDead:
+ case IrOpcode::kStart:
+ os_ << " style=\"diagonals\"\n";
+ break;
+ case IrOpcode::kMerge:
+ case IrOpcode::kIfTrue:
+ case IrOpcode::kIfFalse:
+ case IrOpcode::kLoop:
+ os_ << " style=\"rounded\"\n";
+ break;
+ default:
+ break;
+ }
+
+ OStringStream label;
+ label << *node->op();
+ os_ << " label=\"{{#" << node->id() << ":" << Escaped(label);
+
+ InputIter i = node->inputs().begin();
+ for (int j = NodeProperties::GetValueInputCount(node); j > 0; ++i, j--) {
+ os_ << "|<I" << i.index() << ">#" << (*i)->id();
+ }
+ for (int j = NodeProperties::GetContextInputCount(node); j > 0; ++i, j--) {
+ os_ << "|<I" << i.index() << ">X #" << (*i)->id();
+ }
+ for (int j = NodeProperties::GetEffectInputCount(node); j > 0; ++i, j--) {
+ os_ << "|<I" << i.index() << ">E #" << (*i)->id();
+ }
+
+ if (!use_to_def_ || NodeProperties::IsBasicBlockBegin(node) ||
+ GetControlCluster(node) == NULL) {
+ for (int j = NodeProperties::GetControlInputCount(node); j > 0; ++i, j--) {
+ os_ << "|<I" << i.index() << ">C #" << (*i)->id();
+ }
+ }
+ os_ << "}";
+
+ if (FLAG_trace_turbo_types && !NodeProperties::IsControl(node)) {
+ Bounds bounds = NodeProperties::GetBounds(node);
+ OStringStream upper;
+ bounds.upper->PrintTo(upper);
+ OStringStream lower;
+ bounds.lower->PrintTo(lower);
+ os_ << "|" << Escaped(upper) << "|" << Escaped(lower);
+ }
+ os_ << "}\"\n";
+}
+
+
+void GraphVisualizer::PrintEdge(Node* from, int index, Node* to) {
+ bool unconstrained = IsLikelyBackEdge(from, index, to);
+ os_ << " ID" << from->id();
+ if (all_nodes_.count(to) == 0) {
+ os_ << ":I" << index << ":n -> DEAD_INPUT";
+ } else if (NodeProperties::IsBasicBlockBegin(from) ||
+ GetControlCluster(from) == NULL ||
+ (NodeProperties::GetControlInputCount(from) > 0 &&
+ NodeProperties::GetControlInput(from) != to)) {
+ os_ << ":I" << index << ":n -> ID" << to->id() << ":s";
+ if (unconstrained) os_ << " [constraint=false,style=dotted]";
+ } else {
+ os_ << " -> ID" << to->id() << ":s [color=transparent"
+ << (unconstrained ? ", constraint=false" : "") << "]";
+ }
+ os_ << "\n";
+}
+
+
+void GraphVisualizer::Print() {
+ os_ << "digraph D {\n"
+ << " node [fontsize=8,height=0.25]\n"
+ << " rankdir=\"BT\"\n"
+ << " \n";
+
+ // Make sure all nodes have been output before writing out the edges.
+ use_to_def_ = true;
+ // TODO(svenpanne) Remove the need for the const_casts.
+ const_cast<Graph*>(graph_)->VisitNodeInputsFromEnd(this);
+ white_nodes_.insert(const_cast<Graph*>(graph_)->start());
+
+ // Visit all uses of white nodes.
+ use_to_def_ = false;
+ GenericGraphVisit::Visit<GraphVisualizer, NodeUseIterationTraits<Node> >(
+ const_cast<Graph*>(graph_), white_nodes_.begin(), white_nodes_.end(),
+ this);
+
+ os_ << " DEAD_INPUT [\n"
+ << " style=\"filled\" \n"
+ << " fillcolor=\"" DEAD_COLOR "\"\n"
+ << " ]\n"
+ << "\n";
+
+ // With all the nodes written, add the edges.
+ for (NodeSetIter i = all_nodes_.begin(); i != all_nodes_.end(); ++i) {
+ Node::Inputs inputs = (*i)->inputs();
+ for (Node::Inputs::iterator iter(inputs.begin()); iter != inputs.end();
+ ++iter) {
+ PrintEdge(iter.edge().from(), iter.edge().index(), iter.edge().to());
+ }
+ }
+ os_ << "}\n";
+}
+
+
+GraphVisualizer::GraphVisualizer(OStream& os, const Graph* graph) // NOLINT
+ : all_nodes_(NodeSet::key_compare(),
+ NodeSet::allocator_type(graph->zone())),
+ white_nodes_(NodeSet::key_compare(),
+ NodeSet::allocator_type(graph->zone())),
+ use_to_def_(true),
+ os_(os),
+ graph_(graph) {}
+
+
+OStream& operator<<(OStream& os, const AsDOT& ad) {
+ GraphVisualizer(os, &ad.graph).Print();
+ return os;
+}
+}
+}
+} // namespace v8::internal::compiler
« 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