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,
table_.Set(node, position);
}
void SourcePositionTable::Print(std::ostream& os) const {
void SourcePositionTable::PrintJson(std::ostream& os) const {
os << "{";
bool needs_comma = false;
for (auto i : table_) {
......@@ -60,8 +60,8 @@ void SourcePositionTable::Print(std::ostream& os) const {
if (needs_comma) {
os << ",";
}
os << "\"" << i.first << "\""
<< ":" << pos.ScriptOffset();
os << "\"" << i.first << "\" : ";
pos.PrintJson(os);
needs_comma = true;
}
}
......
......@@ -53,7 +53,7 @@ class V8_EXPORT_PRIVATE SourcePositionTable final
current_position_ = pos;
}
void Print(std::ostream& os) const;
void PrintJson(std::ostream& os) const;
private:
class Decorator;
......
......@@ -22,13 +22,133 @@
#include "src/compiler/scheduler.h"
#include "src/interpreter/bytecodes.h"
#include "src/objects/script-inl.h"
#include "src/objects/shared-function-info.h"
#include "src/optimized-compilation-info.h"
#include "src/ostreams.h"
#include "src/source-position.h"
namespace v8 {
namespace internal {
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,
const char* optional_base_dir,
const char* phase,
......@@ -168,7 +288,7 @@ class JSONGraphNodeWriter {
}
SourcePosition position = positions_->GetSourcePosition(node);
if (position.IsKnown()) {
os_ << ",\"pos\":" << position.ScriptOffset();
os_ << ", \"sourcePosition\" : " << AsJSON(position);
}
os_ << ",\"opcode\":\"" << IrOpcode::Mnemonic(node->opcode()) << "\"";
os_ << ",\"control\":" << (NodeProperties::IsControl(node) ? "true"
......@@ -249,8 +369,7 @@ class JSONGraphEdgeWriter {
DISALLOW_COPY_AND_ASSIGN(JSONGraphEdgeWriter);
};
std::ostream& operator<<(std::ostream& os, const AsJSON& ad) {
std::ostream& operator<<(std::ostream& os, const GraphAsJSON& ad) {
AccountingAllocator allocator;
Zone tmp_zone(&allocator, ZONE_NAME);
os << "{\n\"nodes\":[";
......
......@@ -6,6 +6,7 @@
#define V8_COMPILER_GRAPH_VISUALIZER_H_
#include <stdio.h>
#include <fstream> // NOLINT(readability/streams)
#include <iosfwd>
#include <memory>
......@@ -15,7 +16,8 @@ namespace v8 {
namespace internal {
class OptimizedCompilationInfo;
class SharedFunctionInfo;
class SourcePosition;
namespace compiler {
class Graph;
......@@ -24,18 +26,65 @@ class RegisterAllocationData;
class Schedule;
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,
const char* optional_base_dir,
const char* phase,
const char* suffix);
struct AsJSON {
AsJSON(const Graph& g, SourcePositionTable* p) : graph(g), positions(p) {}
struct GraphAsJSON {
GraphAsJSON(const Graph& g, SourcePositionTable* p)
: graph(g), positions(p) {}
const Graph& graph;
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 {
explicit AsRPO(const Graph& g) : graph(g) {}
......
......@@ -69,6 +69,7 @@
#include "src/compiler/verifier.h"
#include "src/compiler/zone-stats.h"
#include "src/isolate-inl.h"
#include "src/objects/shared-function-info.h"
#include "src/optimized-compilation-info.h"
#include "src/ostreams.h"
#include "src/parsing/parse-info.h"
......@@ -470,24 +471,8 @@ class PipelineImpl final {
namespace {
// Print function's source if it was not printed before.
// Return a sequential id under which this function was printed.
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);
}
void PrintFunctionSource(OptimizedCompilationInfo* info, Isolate* isolate,
int source_id, Handle<SharedFunctionInfo> shared) {
if (!shared->script()->IsUndefined(isolate)) {
Handle<Script> script(Script::cast(shared->script()), isolate);
......@@ -516,8 +501,6 @@ int PrintFunctionSource(OptimizedCompilationInfo* info, Isolate* isolate,
os << "\n--- END ---\n";
}
}
return source_id;
}
// Print information for the given inlining: which function was inlined and
......@@ -541,18 +524,16 @@ void PrintInlinedFunctionInfo(
// Print the source of all functions that participated in this optimizing
// 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;
std::vector<Handle<SharedFunctionInfo>> printed;
printed.reserve(info->inlined_functions().size());
PrintFunctionSource(info, isolate, &printed, SourcePosition::kNotInlined,
info->shared_info());
SourceIdAssigner id_assigner(info->inlined_functions().size());
PrintFunctionSource(info, isolate, -1, info->shared_info());
const auto& inlined = info->inlined_functions();
for (unsigned id = 0; id < inlined.size(); id++) {
const int source_id = PrintFunctionSource(info, isolate, &printed, id,
inlined[id].shared_info);
const int source_id = id_assigner.GetIdFor(inlined[id].shared_info);
PrintFunctionSource(info, isolate, source_id, inlined[id].shared_info);
PrintInlinedFunctionInfo(info, isolate, source_id, id, inlined[id]);
}
}
......@@ -561,7 +542,7 @@ void DumpParticipatingSource(OptimizedCompilationInfo* info, Isolate* isolate) {
void PrintCode(Handle<Code> code, OptimizedCompilationInfo* info) {
Isolate* isolate = code->GetIsolate();
if (FLAG_print_opt_source && info->IsOptimizing()) {
DumpParticipatingSource(info, isolate);
PrintParticipatingSource(info, isolate);
}
#ifdef ENABLE_DISASSEMBLER
......@@ -621,14 +602,6 @@ struct TurboCfgFile : public std::ofstream {
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,
Schedule* schedule) {
if (info->trace_turbo_json_enabled()) {
......@@ -715,21 +688,10 @@ PipelineStatistics* CreatePipelineStatistics(Handle<Script> script,
if (info->trace_turbo_json_enabled()) {
TurboJsonFile json_of(info, std::ios_base::trunc);
std::unique_ptr<char[]> function_name = info->GetDebugName();
int pos =
info->has_shared_info() ? info->shared_info()->StartPosition() : 0;
json_of << "{\"function\":\"" << function_name.get()
<< "\", \"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\":[";
json_of << "{\"function\" : ";
JsonPrintFunctionSource(json_of, -1, info->GetDebugName(), script, isolate,
info->shared_info());
json_of << ",\n\"phases\":[";
}
return pipeline_statistics;
......@@ -1755,6 +1717,7 @@ struct PrintGraphPhase {
if (info->trace_turbo_json_enabled()) { // Print JSON.
AllowHandleDereference allow_deref;
TurboJsonFile json_of(info, std::ios_base::app);
json_of << "{\"name\":\"" << phase << "\",\"type\":\"graph\",\"data\":"
<< AsJSON(*graph, data->source_positions()) << "},\n";
......@@ -2007,8 +1970,11 @@ Handle<Code> Pipeline::GenerateCodeForCodeStub(
<< "Begin compiling " << debug_name << " using Turbofan" << std::endl;
if (info.trace_turbo_json_enabled()) {
TurboJsonFile json_of(&info, std::ios_base::trunc);
json_of << "{\"function\":\"" << info.GetDebugName().get()
<< "\", \"source\":\"\",\n\"phases\":[";
json_of << "{\"function\" : ";
JsonPrintFunctionSource(json_of, -1, info.GetDebugName(),
Handle<Script>(), isolate,
Handle<SharedFunctionInfo>());
json_of << ",\n\"phases\":[";
}
pipeline.Run<PrintGraphPhase>("Machine");
}
......@@ -2194,7 +2160,7 @@ bool PipelineImpl::SelectInstructions(Linkage* linkage) {
if (info()->trace_turbo_json_enabled()) {
std::ostringstream source_position_output;
// 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());
}
......@@ -2280,8 +2246,9 @@ Handle<Code> PipelineImpl::FinalizeCode() {
#endif // ENABLE_DISASSEMBLER
json_of << "\"}\n],\n";
json_of << "\"nodePositions\":";
json_of << data->source_position_output();
json_of << "}";
json_of << data->source_position_output() << ",\n";
JsonPrintAllSourceWithPositions(json_of, data->info(), isolate());
json_of << "\n}";
}
if (info()->trace_turbo_json_enabled() ||
info()->trace_turbo_graph_enabled()) {
......
......@@ -94,6 +94,11 @@ void SourcePosition::Print(std::ostream& out,
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 {
DeoptimizationData* deopt_data =
DeoptimizationData::cast(code->deoptimization_data());
......
......@@ -48,6 +48,7 @@ class SourcePosition final {
OptimizedCompilationInfo* cinfo) const;
void Print(std::ostream& out, Code* code) const;
void PrintJson(std::ostream& out) const;
int ScriptOffset() const { return ScriptOffsetField::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