Commit c43d79f8 authored by Sigurd Schneider's avatar Sigurd Schneider Committed by Commit Bot

[turbolizer] Add inlining information to --trace-turbo

Bug: v8:7327
Change-Id: Ic00291784e982632b15cd83059397b6e9e4c4f79
Reviewed-on: https://chromium-review.googlesource.com/1057487
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53211}
parent 5999f8f1
...@@ -51,7 +51,7 @@ void SourcePositionTable::SetSourcePosition(Node* node, ...@@ -51,7 +51,7 @@ void SourcePositionTable::SetSourcePosition(Node* node,
table_.Set(node, position); table_.Set(node, position);
} }
void SourcePositionTable::Print(std::ostream& os) const { void SourcePositionTable::PrintJson(std::ostream& os) const {
os << "{"; os << "{";
bool needs_comma = false; bool needs_comma = false;
for (auto i : table_) { for (auto i : table_) {
...@@ -60,8 +60,8 @@ void SourcePositionTable::Print(std::ostream& os) const { ...@@ -60,8 +60,8 @@ void SourcePositionTable::Print(std::ostream& os) const {
if (needs_comma) { if (needs_comma) {
os << ","; os << ",";
} }
os << "\"" << i.first << "\"" os << "\"" << i.first << "\" : ";
<< ":" << pos.ScriptOffset(); pos.PrintJson(os);
needs_comma = true; needs_comma = true;
} }
} }
......
...@@ -53,7 +53,7 @@ class V8_EXPORT_PRIVATE SourcePositionTable final ...@@ -53,7 +53,7 @@ class V8_EXPORT_PRIVATE SourcePositionTable final
current_position_ = pos; current_position_ = pos;
} }
void Print(std::ostream& os) const; void PrintJson(std::ostream& os) const;
private: private:
class Decorator; class Decorator;
......
...@@ -22,13 +22,133 @@ ...@@ -22,13 +22,133 @@
#include "src/compiler/scheduler.h" #include "src/compiler/scheduler.h"
#include "src/interpreter/bytecodes.h" #include "src/interpreter/bytecodes.h"
#include "src/objects/script-inl.h" #include "src/objects/script-inl.h"
#include "src/objects/shared-function-info.h"
#include "src/optimized-compilation-info.h" #include "src/optimized-compilation-info.h"
#include "src/ostreams.h" #include "src/ostreams.h"
#include "src/source-position.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
namespace compiler { namespace compiler {
TurboJsonFile::TurboJsonFile(OptimizedCompilationInfo* info,
std::ios_base::openmode mode)
: std::ofstream(
GetVisualizerLogFileName(info, FLAG_trace_turbo_path, nullptr, "json")
.get(),
mode) {}
std::ostream& operator<<(std::ostream& out,
const SourcePositionAsJSON& asJSON) {
asJSON.sp.PrintJson(out);
return out;
}
void JsonPrintFunctionSource(std::ostream& os, int source_id,
std::unique_ptr<char[]> function_name,
Handle<Script> script, Isolate* isolate,
Handle<SharedFunctionInfo> shared, bool with_key) {
if (with_key) os << "\"" << source_id << "\" : ";
os << "{ ";
os << "\"sourceId\": " << source_id;
os << ", \"functionName\": \"" << function_name.get() << "\" ";
int start = 0;
int end = 0;
if (!script.is_null() && !script->IsUndefined(isolate) && !shared.is_null()) {
Object* source_name = script->name();
os << ", \"sourceName\": \"";
if (source_name->IsString()) {
os << String::cast(source_name)->ToCString().get();
}
os << "\"";
{
DisallowHeapAllocation no_allocation;
start = shared->StartPosition();
end = shared->EndPosition();
os << ", \"sourceText\": \"";
int len = shared->EndPosition() - start;
String::SubStringRange source(String::cast(script->source()), start, len);
for (const auto& c : source) {
os << AsEscapedUC16ForJSON(c);
}
os << "\"";
}
} else {
os << ", \"sourceName\": \"\"";
os << ", \"sourceText\": \"\"";
}
os << ", \"startPosition\": " << start;
os << ", \"endPosition\": " << end;
os << "}";
}
int SourceIdAssigner::GetIdFor(Handle<SharedFunctionInfo> shared) {
for (unsigned i = 0; i < printed_.size(); i++) {
if (printed_.at(i).is_identical_to(shared)) {
return i;
}
}
const int source_id = static_cast<int>(printed_.size());
printed_.push_back(shared);
source_ids_.push_back(source_id);
return source_id;
}
namespace {
void JsonPrintInlinedFunctionInfo(
std::ostream& os, int source_id, int inlining_id,
const OptimizedCompilationInfo::InlinedFunctionHolder& h) {
os << "\"" << inlining_id << "\" : ";
os << "{ \"inliningId\" : " << inlining_id;
os << ", \"sourceId\" : " << source_id;
const SourcePosition position = h.position.position;
if (position.IsKnown()) {
os << ", \"inliningPosition\" : " << AsJSON(position);
}
os << "}";
}
} // namespace
void JsonPrintAllSourceWithPositions(std::ostream& os,
OptimizedCompilationInfo* info,
Isolate* isolate) {
AllowDeferredHandleDereference allow_deference_for_print_code;
os << "\"sources\" : {";
Handle<Script> script =
(info->shared_info().is_null() || !info->shared_info()->script())
? Handle<Script>()
: handle(Script::cast(info->shared_info()->script()));
JsonPrintFunctionSource(os, -1,
info->shared_info().is_null()
? std::unique_ptr<char[]>(new char[1]{0})
: info->shared_info()->DebugName()->ToCString(),
script, isolate, info->shared_info(), true);
const auto& inlined = info->inlined_functions();
SourceIdAssigner id_assigner(info->inlined_functions().size());
for (unsigned id = 0; id < inlined.size(); id++) {
os << ", ";
Handle<SharedFunctionInfo> shared = inlined[id].shared_info;
const int source_id = id_assigner.GetIdFor(shared);
JsonPrintFunctionSource(os, source_id, shared->DebugName()->ToCString(),
handle(Script::cast(shared->script())), isolate,
shared, true);
}
os << "}, ";
os << "\"inlinings\" : {";
bool need_comma = false;
for (unsigned id = 0; id < inlined.size(); id++) {
if (need_comma) os << ", ";
const int source_id = id_assigner.GetIdAt(id);
JsonPrintInlinedFunctionInfo(os, source_id, id, inlined[id]);
need_comma = true;
}
os << "}";
}
std::unique_ptr<char[]> GetVisualizerLogFileName(OptimizedCompilationInfo* info, std::unique_ptr<char[]> GetVisualizerLogFileName(OptimizedCompilationInfo* info,
const char* optional_base_dir, const char* optional_base_dir,
const char* phase, const char* phase,
...@@ -168,7 +288,7 @@ class JSONGraphNodeWriter { ...@@ -168,7 +288,7 @@ class JSONGraphNodeWriter {
} }
SourcePosition position = positions_->GetSourcePosition(node); SourcePosition position = positions_->GetSourcePosition(node);
if (position.IsKnown()) { if (position.IsKnown()) {
os_ << ",\"pos\":" << position.ScriptOffset(); os_ << ", \"sourcePosition\" : " << AsJSON(position);
} }
os_ << ",\"opcode\":\"" << IrOpcode::Mnemonic(node->opcode()) << "\""; os_ << ",\"opcode\":\"" << IrOpcode::Mnemonic(node->opcode()) << "\"";
os_ << ",\"control\":" << (NodeProperties::IsControl(node) ? "true" os_ << ",\"control\":" << (NodeProperties::IsControl(node) ? "true"
...@@ -249,8 +369,7 @@ class JSONGraphEdgeWriter { ...@@ -249,8 +369,7 @@ class JSONGraphEdgeWriter {
DISALLOW_COPY_AND_ASSIGN(JSONGraphEdgeWriter); DISALLOW_COPY_AND_ASSIGN(JSONGraphEdgeWriter);
}; };
std::ostream& operator<<(std::ostream& os, const GraphAsJSON& ad) {
std::ostream& operator<<(std::ostream& os, const AsJSON& ad) {
AccountingAllocator allocator; AccountingAllocator allocator;
Zone tmp_zone(&allocator, ZONE_NAME); Zone tmp_zone(&allocator, ZONE_NAME);
os << "{\n\"nodes\":["; os << "{\n\"nodes\":[";
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define V8_COMPILER_GRAPH_VISUALIZER_H_ #define V8_COMPILER_GRAPH_VISUALIZER_H_
#include <stdio.h> #include <stdio.h>
#include <fstream> // NOLINT(readability/streams)
#include <iosfwd> #include <iosfwd>
#include <memory> #include <memory>
...@@ -15,7 +16,8 @@ namespace v8 { ...@@ -15,7 +16,8 @@ namespace v8 {
namespace internal { namespace internal {
class OptimizedCompilationInfo; class OptimizedCompilationInfo;
class SharedFunctionInfo;
class SourcePosition;
namespace compiler { namespace compiler {
class Graph; class Graph;
...@@ -24,18 +26,65 @@ class RegisterAllocationData; ...@@ -24,18 +26,65 @@ class RegisterAllocationData;
class Schedule; class Schedule;
class SourcePositionTable; class SourcePositionTable;
struct TurboJsonFile : public std::ofstream {
TurboJsonFile(OptimizedCompilationInfo* info, std::ios_base::openmode mode);
};
struct SourcePositionAsJSON {
explicit SourcePositionAsJSON(const SourcePosition& sp) : sp(sp) {}
const SourcePosition& sp;
};
V8_INLINE V8_EXPORT_PRIVATE SourcePositionAsJSON
AsJSON(const SourcePosition& sp) {
return SourcePositionAsJSON(sp);
}
std::ostream& operator<<(std::ostream& out, const SourcePositionAsJSON& pos);
// Small helper that deduplicates SharedFunctionInfos.
class SourceIdAssigner {
public:
explicit SourceIdAssigner(size_t size) {
printed_.reserve(size);
source_ids_.reserve(size);
}
int GetIdFor(Handle<SharedFunctionInfo> shared);
int GetIdAt(size_t pos) const { return source_ids_[pos]; }
private:
std::vector<Handle<SharedFunctionInfo>> printed_;
std::vector<int> source_ids_;
};
void JsonPrintAllSourceWithPositions(std::ostream& os,
OptimizedCompilationInfo* info,
Isolate* isolate);
void JsonPrintFunctionSource(std::ostream& os, int source_id,
std::unique_ptr<char[]> function_name,
Handle<Script> script, Isolate* isolate,
Handle<SharedFunctionInfo> shared,
bool with_key = false);
std::unique_ptr<char[]> GetVisualizerLogFileName(OptimizedCompilationInfo* info, std::unique_ptr<char[]> GetVisualizerLogFileName(OptimizedCompilationInfo* info,
const char* optional_base_dir, const char* optional_base_dir,
const char* phase, const char* phase,
const char* suffix); const char* suffix);
struct AsJSON { struct GraphAsJSON {
AsJSON(const Graph& g, SourcePositionTable* p) : graph(g), positions(p) {} GraphAsJSON(const Graph& g, SourcePositionTable* p)
: graph(g), positions(p) {}
const Graph& graph; const Graph& graph;
const SourcePositionTable* positions; const SourcePositionTable* positions;
}; };
V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, const AsJSON& ad); V8_INLINE V8_EXPORT_PRIVATE GraphAsJSON AsJSON(const Graph& g,
SourcePositionTable* p) {
return GraphAsJSON(g, p);
}
V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
const GraphAsJSON& ad);
struct AsRPO { struct AsRPO {
explicit AsRPO(const Graph& g) : graph(g) {} explicit AsRPO(const Graph& g) : graph(g) {}
......
...@@ -69,6 +69,7 @@ ...@@ -69,6 +69,7 @@
#include "src/compiler/verifier.h" #include "src/compiler/verifier.h"
#include "src/compiler/zone-stats.h" #include "src/compiler/zone-stats.h"
#include "src/isolate-inl.h" #include "src/isolate-inl.h"
#include "src/objects/shared-function-info.h"
#include "src/optimized-compilation-info.h" #include "src/optimized-compilation-info.h"
#include "src/ostreams.h" #include "src/ostreams.h"
#include "src/parsing/parse-info.h" #include "src/parsing/parse-info.h"
...@@ -470,24 +471,8 @@ class PipelineImpl final { ...@@ -470,24 +471,8 @@ class PipelineImpl final {
namespace { namespace {
// Print function's source if it was not printed before. void PrintFunctionSource(OptimizedCompilationInfo* info, Isolate* isolate,
// Return a sequential id under which this function was printed. int source_id, Handle<SharedFunctionInfo> shared) {
int PrintFunctionSource(OptimizedCompilationInfo* info, Isolate* isolate,
std::vector<Handle<SharedFunctionInfo>>* printed,
int inlining_id, Handle<SharedFunctionInfo> shared) {
// Outermost function has source id -1 and inlined functions take
// source ids starting from 0.
int source_id = -1;
if (inlining_id != SourcePosition::kNotInlined) {
for (unsigned i = 0; i < printed->size(); i++) {
if (printed->at(i).is_identical_to(shared)) {
return i;
}
}
source_id = static_cast<int>(printed->size());
printed->push_back(shared);
}
if (!shared->script()->IsUndefined(isolate)) { if (!shared->script()->IsUndefined(isolate)) {
Handle<Script> script(Script::cast(shared->script()), isolate); Handle<Script> script(Script::cast(shared->script()), isolate);
...@@ -516,8 +501,6 @@ int PrintFunctionSource(OptimizedCompilationInfo* info, Isolate* isolate, ...@@ -516,8 +501,6 @@ int PrintFunctionSource(OptimizedCompilationInfo* info, Isolate* isolate,
os << "\n--- END ---\n"; os << "\n--- END ---\n";
} }
} }
return source_id;
} }
// Print information for the given inlining: which function was inlined and // Print information for the given inlining: which function was inlined and
...@@ -541,18 +524,16 @@ void PrintInlinedFunctionInfo( ...@@ -541,18 +524,16 @@ void PrintInlinedFunctionInfo(
// Print the source of all functions that participated in this optimizing // Print the source of all functions that participated in this optimizing
// compilation. For inlined functions print source position of their inlining. // compilation. For inlined functions print source position of their inlining.
void DumpParticipatingSource(OptimizedCompilationInfo* info, Isolate* isolate) { void PrintParticipatingSource(OptimizedCompilationInfo* info,
Isolate* isolate) {
AllowDeferredHandleDereference allow_deference_for_print_code; AllowDeferredHandleDereference allow_deference_for_print_code;
std::vector<Handle<SharedFunctionInfo>> printed; SourceIdAssigner id_assigner(info->inlined_functions().size());
printed.reserve(info->inlined_functions().size()); PrintFunctionSource(info, isolate, -1, info->shared_info());
PrintFunctionSource(info, isolate, &printed, SourcePosition::kNotInlined,
info->shared_info());
const auto& inlined = info->inlined_functions(); const auto& inlined = info->inlined_functions();
for (unsigned id = 0; id < inlined.size(); id++) { for (unsigned id = 0; id < inlined.size(); id++) {
const int source_id = PrintFunctionSource(info, isolate, &printed, id, const int source_id = id_assigner.GetIdFor(inlined[id].shared_info);
inlined[id].shared_info); PrintFunctionSource(info, isolate, source_id, inlined[id].shared_info);
PrintInlinedFunctionInfo(info, isolate, source_id, id, inlined[id]); PrintInlinedFunctionInfo(info, isolate, source_id, id, inlined[id]);
} }
} }
...@@ -561,7 +542,7 @@ void DumpParticipatingSource(OptimizedCompilationInfo* info, Isolate* isolate) { ...@@ -561,7 +542,7 @@ void DumpParticipatingSource(OptimizedCompilationInfo* info, Isolate* isolate) {
void PrintCode(Handle<Code> code, OptimizedCompilationInfo* info) { void PrintCode(Handle<Code> code, OptimizedCompilationInfo* info) {
Isolate* isolate = code->GetIsolate(); Isolate* isolate = code->GetIsolate();
if (FLAG_print_opt_source && info->IsOptimizing()) { if (FLAG_print_opt_source && info->IsOptimizing()) {
DumpParticipatingSource(info, isolate); PrintParticipatingSource(info, isolate);
} }
#ifdef ENABLE_DISASSEMBLER #ifdef ENABLE_DISASSEMBLER
...@@ -621,14 +602,6 @@ struct TurboCfgFile : public std::ofstream { ...@@ -621,14 +602,6 @@ struct TurboCfgFile : public std::ofstream {
std::ios_base::app) {} std::ios_base::app) {}
}; };
struct TurboJsonFile : public std::ofstream {
TurboJsonFile(OptimizedCompilationInfo* info, std::ios_base::openmode mode)
: std::ofstream(GetVisualizerLogFileName(info, FLAG_trace_turbo_path,
nullptr, "json")
.get(),
mode) {}
};
void TraceSchedule(OptimizedCompilationInfo* info, Isolate* isolate, void TraceSchedule(OptimizedCompilationInfo* info, Isolate* isolate,
Schedule* schedule) { Schedule* schedule) {
if (info->trace_turbo_json_enabled()) { if (info->trace_turbo_json_enabled()) {
...@@ -715,21 +688,10 @@ PipelineStatistics* CreatePipelineStatistics(Handle<Script> script, ...@@ -715,21 +688,10 @@ PipelineStatistics* CreatePipelineStatistics(Handle<Script> script,
if (info->trace_turbo_json_enabled()) { if (info->trace_turbo_json_enabled()) {
TurboJsonFile json_of(info, std::ios_base::trunc); TurboJsonFile json_of(info, std::ios_base::trunc);
std::unique_ptr<char[]> function_name = info->GetDebugName(); json_of << "{\"function\" : ";
int pos = JsonPrintFunctionSource(json_of, -1, info->GetDebugName(), script, isolate,
info->has_shared_info() ? info->shared_info()->StartPosition() : 0; info->shared_info());
json_of << "{\"function\":\"" << function_name.get() json_of << ",\n\"phases\":[";
<< "\", \"sourcePosition\":" << pos << ", \"source\":\"";
if (!script.is_null() && !script->source()->IsUndefined(isolate)) {
DisallowHeapAllocation no_allocation;
int start = info->shared_info()->StartPosition();
int len = info->shared_info()->EndPosition() - start;
String::SubStringRange source(String::cast(script->source()), start, len);
for (const auto& c : source) {
json_of << AsEscapedUC16ForJSON(c);
}
}
json_of << "\",\n\"phases\":[";
} }
return pipeline_statistics; return pipeline_statistics;
...@@ -1755,6 +1717,7 @@ struct PrintGraphPhase { ...@@ -1755,6 +1717,7 @@ struct PrintGraphPhase {
if (info->trace_turbo_json_enabled()) { // Print JSON. if (info->trace_turbo_json_enabled()) { // Print JSON.
AllowHandleDereference allow_deref; AllowHandleDereference allow_deref;
TurboJsonFile json_of(info, std::ios_base::app); TurboJsonFile json_of(info, std::ios_base::app);
json_of << "{\"name\":\"" << phase << "\",\"type\":\"graph\",\"data\":" json_of << "{\"name\":\"" << phase << "\",\"type\":\"graph\",\"data\":"
<< AsJSON(*graph, data->source_positions()) << "},\n"; << AsJSON(*graph, data->source_positions()) << "},\n";
...@@ -2007,8 +1970,11 @@ Handle<Code> Pipeline::GenerateCodeForCodeStub( ...@@ -2007,8 +1970,11 @@ Handle<Code> Pipeline::GenerateCodeForCodeStub(
<< "Begin compiling " << debug_name << " using Turbofan" << std::endl; << "Begin compiling " << debug_name << " using Turbofan" << std::endl;
if (info.trace_turbo_json_enabled()) { if (info.trace_turbo_json_enabled()) {
TurboJsonFile json_of(&info, std::ios_base::trunc); TurboJsonFile json_of(&info, std::ios_base::trunc);
json_of << "{\"function\":\"" << info.GetDebugName().get() json_of << "{\"function\" : ";
<< "\", \"source\":\"\",\n\"phases\":["; JsonPrintFunctionSource(json_of, -1, info.GetDebugName(),
Handle<Script>(), isolate,
Handle<SharedFunctionInfo>());
json_of << ",\n\"phases\":[";
} }
pipeline.Run<PrintGraphPhase>("Machine"); pipeline.Run<PrintGraphPhase>("Machine");
} }
...@@ -2194,7 +2160,7 @@ bool PipelineImpl::SelectInstructions(Linkage* linkage) { ...@@ -2194,7 +2160,7 @@ bool PipelineImpl::SelectInstructions(Linkage* linkage) {
if (info()->trace_turbo_json_enabled()) { if (info()->trace_turbo_json_enabled()) {
std::ostringstream source_position_output; std::ostringstream source_position_output;
// Output source position information before the graph is deleted. // Output source position information before the graph is deleted.
data_->source_positions()->Print(source_position_output); data_->source_positions()->PrintJson(source_position_output);
data_->set_source_position_output(source_position_output.str()); data_->set_source_position_output(source_position_output.str());
} }
...@@ -2280,8 +2246,9 @@ Handle<Code> PipelineImpl::FinalizeCode() { ...@@ -2280,8 +2246,9 @@ Handle<Code> PipelineImpl::FinalizeCode() {
#endif // ENABLE_DISASSEMBLER #endif // ENABLE_DISASSEMBLER
json_of << "\"}\n],\n"; json_of << "\"}\n],\n";
json_of << "\"nodePositions\":"; json_of << "\"nodePositions\":";
json_of << data->source_position_output(); json_of << data->source_position_output() << ",\n";
json_of << "}"; JsonPrintAllSourceWithPositions(json_of, data->info(), isolate());
json_of << "\n}";
} }
if (info()->trace_turbo_json_enabled() || if (info()->trace_turbo_json_enabled() ||
info()->trace_turbo_graph_enabled()) { info()->trace_turbo_graph_enabled()) {
......
...@@ -94,6 +94,11 @@ void SourcePosition::Print(std::ostream& out, ...@@ -94,6 +94,11 @@ void SourcePosition::Print(std::ostream& out,
out << ":" << pos.line + 1 << ":" << pos.column + 1 << ">"; out << ":" << pos.line + 1 << ":" << pos.column + 1 << ">";
} }
void SourcePosition::PrintJson(std::ostream& out) const {
out << "{ \"scriptOffset\" : " << ScriptOffset() << ", "
<< " \"inliningId\" : " << InliningId() << "}";
}
void SourcePosition::Print(std::ostream& out, Code* code) const { void SourcePosition::Print(std::ostream& out, Code* code) const {
DeoptimizationData* deopt_data = DeoptimizationData* deopt_data =
DeoptimizationData::cast(code->deoptimization_data()); DeoptimizationData::cast(code->deoptimization_data());
......
...@@ -48,6 +48,7 @@ class SourcePosition final { ...@@ -48,6 +48,7 @@ class SourcePosition final {
OptimizedCompilationInfo* cinfo) const; OptimizedCompilationInfo* cinfo) const;
void Print(std::ostream& out, Code* code) const; void Print(std::ostream& out, Code* code) const;
void PrintJson(std::ostream& out) const;
int ScriptOffset() const { return ScriptOffsetField::decode(value_) - 1; } int ScriptOffset() const { return ScriptOffsetField::decode(value_) - 1; }
int InliningId() const { return InliningIdField::decode(value_) - 1; } int InliningId() const { return InliningIdField::decode(value_) - 1; }
......
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