Commit ca080a4f authored by danno@chromium.org's avatar danno@chromium.org

[TurboFan]: Add JSON output for the visualizer

R=mstarzinger@chromium.org

Review URL: https://codereview.chromium.org/599453002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24220 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent b91704fd
......@@ -22,6 +22,141 @@ namespace compiler {
#define DEAD_COLOR "#999999"
class Escaped {
public:
explicit Escaped(const OStringStream& os, const char* escaped_chars = "<>|{}")
: str_(os.c_str()), escaped_chars_(escaped_chars) {}
friend OStream& operator<<(OStream& os, const Escaped& e) {
for (const char* s = e.str_; *s != '\0'; ++s) {
if (e.needs_escape(*s)) os << "\\";
os << *s;
}
return os;
}
private:
bool needs_escape(char ch) const {
for (size_t i = 0; i < strlen(escaped_chars_); ++i) {
if (ch == escaped_chars_[i]) return true;
}
return false;
}
const char* const str_;
const char* const escaped_chars_;
};
class JSONGraphNodeWriter : public NullNodeVisitor {
public:
JSONGraphNodeWriter(OStream& os, Zone* zone, const Graph* graph) // NOLINT
: os_(os),
graph_(graph),
first_node_(true) {}
void Print() { const_cast<Graph*>(graph_)->VisitNodeInputsFromEnd(this); }
GenericGraphVisit::Control Pre(Node* node);
private:
OStream& os_;
const Graph* const graph_;
bool first_node_;
DISALLOW_COPY_AND_ASSIGN(JSONGraphNodeWriter);
};
GenericGraphVisit::Control JSONGraphNodeWriter::Pre(Node* node) {
if (first_node_) {
first_node_ = false;
} else {
os_ << ",";
}
OStringStream label;
label << *node->op();
os_ << "{\"id\":" << node->id() << ",\"label\":\"" << Escaped(label, "\"")
<< "\"";
IrOpcode::Value opcode = node->opcode();
if (opcode == IrOpcode::kPhi || opcode == IrOpcode::kEffectPhi) {
os_ << ",\"rankInputs\":[0," << NodeProperties::FirstControlIndex(node)
<< "]";
os_ << ",\"rankWithInput\":[" << NodeProperties::FirstControlIndex(node)
<< "]";
} else if (opcode == IrOpcode::kIfTrue || opcode == IrOpcode::kIfFalse ||
opcode == IrOpcode::kLoop) {
os_ << ",\"rankInputs\":[" << NodeProperties::FirstControlIndex(node)
<< "]";
}
if (opcode == IrOpcode::kBranch) {
os_ << ",\"rankInputs\":[0]";
}
os_ << ",\"opcode\":\"" << IrOpcode::Mnemonic(node->opcode()) << "\"";
os_ << ",\"control\":" << (NodeProperties::IsControl(node) ? "true"
: "false");
os_ << "}";
return GenericGraphVisit::CONTINUE;
}
class JSONGraphEdgeWriter : public NullNodeVisitor {
public:
JSONGraphEdgeWriter(OStream& os, Zone* zone, const Graph* graph) // NOLINT
: os_(os),
graph_(graph),
first_edge_(true) {}
void Print() { const_cast<Graph*>(graph_)->VisitNodeInputsFromEnd(this); }
GenericGraphVisit::Control PreEdge(Node* from, int index, Node* to);
private:
OStream& os_;
const Graph* const graph_;
bool first_edge_;
DISALLOW_COPY_AND_ASSIGN(JSONGraphEdgeWriter);
};
GenericGraphVisit::Control JSONGraphEdgeWriter::PreEdge(Node* from, int index,
Node* to) {
if (first_edge_) {
first_edge_ = false;
} else {
os_ << ",";
}
const char* edge_type = NULL;
if (index < NodeProperties::FirstValueIndex(from)) {
edge_type = "unknown";
} else if (index < NodeProperties::FirstContextIndex(from)) {
edge_type = "value";
} else if (index < NodeProperties::FirstFrameStateIndex(from)) {
edge_type = "context";
} else if (index < NodeProperties::FirstEffectIndex(from)) {
edge_type = "frame-state";
} else if (index < NodeProperties::FirstControlIndex(from)) {
edge_type = "effect";
} else {
edge_type = "control";
}
os_ << "{\"source\":" << to->id() << ",\"target\":" << from->id()
<< ",\"index\":" << index << ",\"type\":\"" << edge_type << "\"}";
return GenericGraphVisit::CONTINUE;
}
OStream& operator<<(OStream& os, const AsJSON& ad) {
Zone tmp_zone(ad.graph.zone()->isolate());
os << "{\"nodes\":[";
JSONGraphNodeWriter(os, &tmp_zone, &ad.graph).Print();
os << "],\"edges\":[";
JSONGraphEdgeWriter(os, &tmp_zone, &ad.graph).Print();
os << "]}";
return os;
}
class GraphVisualizer : public NullNodeVisitor {
public:
GraphVisualizer(OStream& os, Zone* zone, const Graph* graph); // NOLINT
......@@ -87,36 +222,6 @@ GenericGraphVisit::Control GraphVisualizer::PreEdge(Node* from, int index,
}
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) {
......
......@@ -22,6 +22,13 @@ struct AsDOT {
};
OStream& operator<<(OStream& os, const AsDOT& ad);
struct AsJSON {
explicit AsJSON(const Graph& g) : graph(g) {}
const Graph& graph;
};
OStream& operator<<(OStream& os, const AsJSON& ad);
}
}
} // namespace v8::internal::compiler
......
......@@ -95,19 +95,31 @@ void Pipeline::VerifyAndPrintGraph(Graph* graph, const char* phase) {
SmartArrayPointer<char> functionname =
info_->shared_info()->DebugName()->ToCString();
if (strlen(functionname.get()) > 0) {
SNPrintF(filename, "turbo-%s-%s.dot", functionname.get(), phase);
SNPrintF(filename, "turbo-%s-%s", functionname.get(), phase);
} else {
SNPrintF(filename, "turbo-%p-%s.dot", static_cast<void*>(info_), phase);
SNPrintF(filename, "turbo-%p-%s", static_cast<void*>(info_), phase);
}
} else {
SNPrintF(filename, "turbo-none-%s.dot", phase);
SNPrintF(filename, "turbo-none-%s", phase);
}
std::replace(filename.start(), filename.start() + filename.length(), ' ',
'_');
FILE* file = base::OS::FOpen(filename.start(), "w+");
OFStream of(file);
of << AsDOT(*graph);
fclose(file);
char dot_buffer[256];
Vector<char> dot_filename(dot_buffer, sizeof(dot_buffer));
SNPrintF(dot_filename, "%s.dot", filename.start());
FILE* dot_file = base::OS::FOpen(dot_filename.start(), "w+");
OFStream dot_of(dot_file);
dot_of << AsDOT(*graph);
fclose(dot_file);
char json_buffer[256];
Vector<char> json_filename(json_buffer, sizeof(json_buffer));
SNPrintF(json_filename, "%s.json", filename.start());
FILE* json_file = base::OS::FOpen(json_filename.start(), "w+");
OFStream json_of(json_file);
json_of << AsJSON(*graph);
fclose(json_file);
OFStream os(stdout);
os << "-- " << phase << " graph printed to file " << filename.start()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment