Commit 328cf76e authored by danno's avatar danno Committed by Commit bot

[turbofan] Improve JSON output

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

Cr-Commit-Position: refs/heads/master@{#26323}
parent 7a8d0c02
......@@ -60,18 +60,20 @@ class Escaped {
class JSONGraphNodeWriter {
public:
JSONGraphNodeWriter(std::ostream& os, Zone* zone, const Graph* graph)
: os_(os), all_(zone, graph), first_node_(true) {}
JSONGraphNodeWriter(std::ostream& os, Zone* zone, const Graph* graph,
const SourcePositionTable* positions)
: os_(os), all_(zone, graph), positions_(positions), first_node_(true) {}
void Print() {
for (Node* const node : all_.live) PrintNode(node);
os_ << "\n";
}
void PrintNode(Node* node) {
if (first_node_) {
first_node_ = false;
} else {
os_ << ",";
os_ << ",\n";
}
std::ostringstream label;
label << *node->op();
......@@ -91,6 +93,11 @@ class JSONGraphNodeWriter {
if (opcode == IrOpcode::kBranch) {
os_ << ",\"rankInputs\":[0]";
}
SourcePosition position = positions_->GetSourcePosition(node);
if (!position.IsUnknown()) {
DCHECK(!position.IsInvalid());
os_ << ",\"pos\":" << position.raw();
}
os_ << ",\"opcode\":\"" << IrOpcode::Mnemonic(node->opcode()) << "\"";
os_ << ",\"control\":" << (NodeProperties::IsControl(node) ? "true"
: "false");
......@@ -100,6 +107,7 @@ class JSONGraphNodeWriter {
private:
std::ostream& os_;
AllNodes all_;
const SourcePositionTable* positions_;
bool first_node_;
DISALLOW_COPY_AND_ASSIGN(JSONGraphNodeWriter);
......@@ -113,6 +121,7 @@ class JSONGraphEdgeWriter {
void Print() {
for (Node* const node : all_.live) PrintEdges(node);
os_ << "\n";
}
void PrintEdges(Node* node) {
......@@ -127,7 +136,7 @@ class JSONGraphEdgeWriter {
if (first_edge_) {
first_edge_ = false;
} else {
os_ << ",";
os_ << ",\n";
}
const char* edge_type = NULL;
if (index < NodeProperties::FirstValueIndex(from)) {
......@@ -158,9 +167,9 @@ class JSONGraphEdgeWriter {
std::ostream& operator<<(std::ostream& os, const AsJSON& ad) {
Zone tmp_zone;
os << "{\"nodes\":[";
JSONGraphNodeWriter(os, &tmp_zone, &ad.graph).Print();
os << "],\"edges\":[";
os << "{\n\"nodes\":[";
JSONGraphNodeWriter(os, &tmp_zone, &ad.graph, ad.positions).Print();
os << "],\n\"edges\":[";
JSONGraphEdgeWriter(os, &tmp_zone, &ad.graph).Print();
os << "]}";
return os;
......
......@@ -30,8 +30,9 @@ std::ostream& operator<<(std::ostream& os, const AsDOT& ad);
struct AsJSON {
explicit AsJSON(const Graph& g) : graph(g) {}
AsJSON(const Graph& g, SourcePositionTable* p) : graph(g), positions(p) {}
const Graph& graph;
const SourcePositionTable* positions;
};
std::ostream& operator<<(std::ostream& os, const AsJSON& ad);
......
......@@ -691,33 +691,44 @@ struct GenerateCodePhase {
};
namespace {
FILE* OpenLogFile(CompilationInfo* info, const char* phase, const char* suffix,
const char* mode) {
EmbeddedVector<char, 256> filename;
SmartArrayPointer<char> function_name;
if (!info->shared_info().is_null()) {
function_name = info->shared_info()->DebugName()->ToCString();
if (strlen(function_name.get()) > 0) {
SNPrintF(filename, "turbo-%s", function_name.get());
} else {
SNPrintF(filename, "turbo-%p", static_cast<void*>(info));
}
} else {
SNPrintF(filename, "turbo-none-%s", phase);
}
std::replace(filename.start(), filename.start() + filename.length(), ' ',
'_');
EmbeddedVector<char, 256> full_filename;
if (phase == NULL) {
SNPrintF(full_filename, "%s.%s", filename.start(), suffix);
} else {
SNPrintF(full_filename, "%s-%s.%s", filename.start(), phase, suffix);
}
return base::OS::FOpen(full_filename.start(), mode);
}
}
struct PrintGraphPhase {
static const char* phase_name() { return nullptr; }
void Run(PipelineData* data, Zone* temp_zone, const char* phase) {
CompilationInfo* info = data->info();
Graph* graph = data->graph();
char buffer[256];
Vector<char> filename(buffer, sizeof(buffer));
SmartArrayPointer<char> functionname;
if (!info->shared_info().is_null()) {
functionname = info->shared_info()->DebugName()->ToCString();
if (strlen(functionname.get()) > 0) {
SNPrintF(filename, "turbo-%s-%s", functionname.get(), phase);
} else {
SNPrintF(filename, "turbo-%p-%s", static_cast<void*>(info), phase);
}
} else {
SNPrintF(filename, "turbo-none-%s", phase);
}
std::replace(filename.start(), filename.start() + filename.length(), ' ',
'_');
{ // Print dot.
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+");
FILE* dot_file = OpenLogFile(info, phase, "dot", "w+");
if (dot_file == nullptr) return;
OFStream dot_of(dot_file);
dot_of << AsDOT(*graph);
......@@ -725,13 +736,11 @@ struct PrintGraphPhase {
}
{ // Print JSON.
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+");
FILE* json_file = OpenLogFile(info, NULL, "json", "a+");
if (json_file == nullptr) return;
OFStream json_of(json_file);
json_of << AsJSON(*graph);
json_of << "{\"name\":\"" << phase << "\",\"type\":\"graph\",\"data\":"
<< AsJSON(*graph, data->source_positions()) << "},\n";
fclose(json_file);
}
......@@ -740,9 +749,6 @@ struct PrintGraphPhase {
os << "-- Graph after " << phase << " -- " << std::endl;
os << AsRPO(*graph);
}
os << "-- " << phase << " graph printed to file " << filename.start()
<< std::endl;
}
};
......@@ -801,6 +807,32 @@ Handle<Code> Pipeline::GenerateCode() {
pipeline_statistics->BeginPhaseKind("initializing");
}
if (FLAG_trace_turbo) {
FILE* json_file = OpenLogFile(info(), NULL, "json", "w+");
if (json_file != nullptr) {
OFStream json_of(json_file);
Handle<Script> script = info()->script();
FunctionLiteral* function = info()->function();
SmartArrayPointer<char> function_name =
info()->shared_info()->DebugName()->ToCString();
int pos = info()->shared_info()->start_position();
json_of << "{\"function\":\"" << function_name.get()
<< "\", \"sourcePosition\":" << pos << ", \"source\":\"";
if (!script->IsUndefined() && !script->source()->IsUndefined()) {
DisallowHeapAllocation no_allocation;
int start = function->start_position();
int len = function->end_position() - start + 1;
String::SubStringRange source(String::cast(script->source()), start,
len);
for (const auto& c : source) {
json_of << AsEscapedUC16ForJSON(c);
}
}
json_of << "\",\n\"phases\":[";
fclose(json_file);
}
}
PipelineData data(&zone_pool, info());
this->data_ = &data;
data.Initialize(pipeline_statistics.get());
......@@ -915,6 +947,22 @@ Handle<Code> Pipeline::GenerateCode() {
v8::internal::CodeGenerator::PrintCode(code, info());
if (FLAG_trace_turbo) {
FILE* json_file = OpenLogFile(info(), NULL, "json", "a+");
if (json_file != nullptr) {
OFStream json_of(json_file);
json_of
<< "{\"name\":\"disassembly\",\"type\":\"disassembly\",\"data\":\"";
#if ENABLE_DISASSEMBLER
std::stringstream disassembly_stream;
code->Disassemble(NULL, disassembly_stream);
std::string disassembly_string(disassembly_stream.str());
for (const auto& c : disassembly_string) {
json_of << AsEscapedUC16ForJSON(c);
}
#endif // ENABLE_DISASSEMBLER
json_of << "\"}\n]}";
fclose(json_file);
}
OFStream os(stdout);
os << "---------------------------------------------------\n"
<< "Finished compiling method " << GetDebugName(info()).get()
......
......@@ -3511,16 +3511,13 @@ int HGraph::TraceInlinedFunction(
os << "--- FUNCTION SOURCE (" << shared->DebugName()->ToCString().get()
<< ") id{" << info()->optimization_id() << "," << id << "} ---\n";
{
StringCharacterStream stream(String::cast(script->source()),
shared->start_position());
// fun->end_position() points to the last character in the stream. We
// need to compensate by adding one to calculate the length.
int source_len =
shared->end_position() - shared->start_position() + 1;
for (int i = 0; i < source_len; i++) {
if (stream.HasMore()) {
os << AsReversiblyEscapedUC16(stream.GetNext());
}
DisallowHeapAllocation no_allocation;
int start = shared->start_position();
int len = shared->end_position() - start + 1;
String::SubStringRange source(String::cast(script->source()), start,
len);
for (const auto& c : source) {
os << AsReversiblyEscapedUC16(c);
}
}
......
......@@ -7521,6 +7521,49 @@ Object* JSMapIterator::CurrentValue() {
}
class String::SubStringRange::iterator FINAL {
public:
typedef std::forward_iterator_tag iterator_category;
typedef int difference_type;
typedef uc16 value_type;
typedef uc16* pointer;
typedef uc16& reference;
iterator(const iterator& other)
: content_(other.content_), offset_(other.offset_) {}
uc16 operator*() { return content_.Get(offset_); }
bool operator==(const iterator& other) const {
return content_.UsesSameString(other.content_) && offset_ == other.offset_;
}
bool operator!=(const iterator& other) const {
return !content_.UsesSameString(other.content_) || offset_ != other.offset_;
}
iterator& operator++() {
++offset_;
return *this;
}
iterator operator++(int);
private:
friend class String;
iterator(String* from, int offset)
: content_(from->GetFlatContent()), offset_(offset) {}
String::FlatContent content_;
int offset_;
};
String::SubStringRange::iterator String::SubStringRange::begin() {
return String::SubStringRange::iterator(string_, first_);
}
String::SubStringRange::iterator String::SubStringRange::end() {
return String::SubStringRange::iterator(string_, first_ + length_);
}
#undef TYPE_CHECKER
#undef CAST_ACCESSOR
#undef INT_ACCESSORS
......
......@@ -8847,6 +8847,22 @@ class String: public Name {
<< ArrayIndexLengthBits::kShift) |
kIsNotArrayIndexMask;
class SubStringRange {
public:
explicit SubStringRange(String* string, int first = 0, int length = -1)
: string_(string),
first_(first),
length_(length == -1 ? string->length() : length) {}
class iterator;
inline iterator begin();
inline iterator end();
private:
String* string_;
int first_;
int length_;
};
// Representation of the flat content of a String.
// A non-flat string doesn't have flat content.
// A flat string has content that's encoded as a sequence of either
......@@ -8881,6 +8897,10 @@ class String: public Name {
return twobyte_start[i];
}
bool UsesSameString(const FlatContent& other) const {
return onebyte_start == other.onebyte_start;
}
private:
enum State { NON_FLAT, ONE_BYTE, TWO_BYTE };
......@@ -8899,6 +8919,7 @@ class String: public Name {
State state_;
friend class String;
friend class IterableSubString;
};
template <typename Char>
......
......@@ -66,6 +66,15 @@ std::ostream& operator<<(std::ostream& os, const AsReversiblyEscapedUC16& c) {
}
std::ostream& operator<<(std::ostream& os, const AsEscapedUC16ForJSON& c) {
if (c.value == '\n') return os << "\\n";
if (c.value == '\r') return os << "\\r";
if (c.value == '\"') return os << "\\\"";
if (c.value == '\'') return os << "\\\'";
return PrintUC16(os, c.value, IsOK);
}
std::ostream& operator<<(std::ostream& os, const AsUC16& c) {
return PrintUC16(os, c.value, IsPrint);
}
......
......@@ -55,12 +55,20 @@ struct AsReversiblyEscapedUC16 {
uint16_t value;
};
struct AsEscapedUC16ForJSON {
explicit AsEscapedUC16ForJSON(uint16_t v) : value(v) {}
uint16_t value;
};
// Writes the given character to the output escaping everything outside of
// printable/space ASCII range. Additionally escapes '\' making escaping
// reversible.
std::ostream& operator<<(std::ostream& os, const AsReversiblyEscapedUC16& c);
// Same as AsReversiblyEscapedUC16 with additional escaping of \n, \r, " and '.
std::ostream& operator<<(std::ostream& os, const AsEscapedUC16ForJSON& c);
// Writes the given character to the output escaping everything outside
// of printable ASCII range.
std::ostream& operator<<(std::ostream& os, const AsUC16& c);
......
......@@ -14,6 +14,7 @@
#include "src/compiler/operator.h"
#include "src/compiler/schedule.h"
#include "src/compiler/scheduler.h"
#include "src/compiler/source-position.h"
#include "src/compiler/verifier.h"
using namespace v8::internal;
......@@ -33,7 +34,8 @@ TEST(NodeWithNullInputReachableFromEnd) {
OFStream os(stdout);
os << AsDOT(graph);
os << AsJSON(graph);
SourcePositionTable table(&graph);
os << AsJSON(graph, &table);
}
......@@ -51,7 +53,8 @@ TEST(NodeWithNullControlReachableFromEnd) {
OFStream os(stdout);
os << AsDOT(graph);
os << AsJSON(graph);
SourcePositionTable table(&graph);
os << AsJSON(graph, &table);
}
......@@ -69,7 +72,8 @@ TEST(NodeWithNullInputReachableFromStart) {
OFStream os(stdout);
os << AsDOT(graph);
os << AsJSON(graph);
SourcePositionTable table(&graph);
os << AsJSON(graph, &table);
}
......@@ -86,5 +90,6 @@ TEST(NodeWithNullControlReachableFromStart) {
OFStream os(stdout);
os << AsDOT(graph);
os << AsJSON(graph);
SourcePositionTable table(&graph);
os << AsJSON(graph, &table);
}
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