Commit a25a55e8 authored by Stephan Herhut's avatar Stephan Herhut Committed by Commit Bot

[wasm] Emit bytecode positions for --trace-turbo

This adds a decorator to add the wasm bytecode offset as origin
for graph nodes and emits a little table that maps lines in the
generated wasm assembly listing to the corresponding bytecode
offset.

Change-Id: Ibc0431a122e543f95173ffc3b1b4ca461e372f28
Reviewed-on: https://chromium-review.googlesource.com/1071290Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarSigurd Schneider <sigurds@chromium.org>
Commit-Queue: Stephan Herhut <herhut@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53484}
parent 02ba28b6
......@@ -12,7 +12,15 @@ namespace compiler {
void NodeOrigin::PrintJson(std::ostream& out) const {
out << "{ ";
out << "\"nodeId\" : " << created_from();
switch (origin_kind_) {
case kGraphNode:
out << "\"nodeId\" : ";
break;
case kWasmBytecode:
out << "\"bytecodePosition\" : ";
break;
}
out << created_from();
out << ", \"reducer\" : \"" << reducer_name() << "\"";
out << ", \"phase\" : \"" << phase_name() << "\"";
out << "}";
......
......@@ -18,11 +18,21 @@ namespace compiler {
class NodeOrigin {
public:
typedef enum { kWasmBytecode, kGraphNode } OriginKind;
NodeOrigin(const char* phase_name, const char* reducer_name,
NodeId created_from)
: phase_name_(phase_name),
reducer_name_(reducer_name),
origin_kind_(kGraphNode),
created_from_(created_from) {}
NodeOrigin(const char* phase_name, const char* reducer_name,
OriginKind origin_kind, uint64_t created_from)
: phase_name_(phase_name),
reducer_name_(reducer_name),
origin_kind_(origin_kind),
created_from_(created_from) {}
NodeOrigin(const NodeOrigin& other) = default;
static NodeOrigin Unknown() { return NodeOrigin(); }
......@@ -31,6 +41,8 @@ class NodeOrigin {
const char* reducer_name() const { return reducer_name_; }
const char* phase_name() const { return phase_name_; }
OriginKind origin_kind() const { return origin_kind_; }
bool operator==(const NodeOrigin& o) const {
return reducer_name_ == o.reducer_name_ && created_from_ == o.created_from_;
}
......@@ -44,6 +56,7 @@ class NodeOrigin {
created_from_(std::numeric_limits<int64_t>::min()) {}
const char* phase_name_;
const char* reducer_name_;
OriginKind origin_kind_;
int64_t created_from_;
};
......
......@@ -759,12 +759,22 @@ PipelineStatistics* CreatePipelineStatistics(wasm::FunctionBody function_body,
json_of << "{\"function\":\"" << function_name.get() << "\", \"source\":\"";
AccountingAllocator allocator;
std::ostringstream disassembly;
std::vector<int> source_positions;
wasm::PrintRawWasmCode(&allocator, function_body, wasm_module,
wasm::kPrintLocals, disassembly);
wasm::kPrintLocals, disassembly, &source_positions);
for (const auto& c : disassembly.str()) {
json_of << AsEscapedUC16ForJSON(c);
}
json_of << "\",\n\"phases\":[";
json_of << "\",\n\"sourceLineToBytecodePosition\" : [";
bool insert_comma = false;
for (auto val : source_positions) {
if (insert_comma) {
json_of << ", ";
}
json_of << val;
insert_comma = true;
}
json_of << "],\n\"phases\":[";
}
return pipeline_statistics;
......@@ -988,6 +998,10 @@ PipelineWasmCompilationJob::ExecuteJobImpl() {
pipeline_.RunPrintAndVerify("wasm optimization", true);
}
if (data_.node_origins()) {
data_.node_origins()->RemoveDecorator();
}
pipeline_.ComputeScheduledGraph();
if (!pipeline_.SelectInstructions(&linkage_)) return FAILED;
pipeline_.AssembleCode(&linkage_);
......
......@@ -3946,6 +3946,35 @@ Node* WasmGraphBuilder::AtomicOp(wasm::WasmOpcode opcode, Node* const* inputs,
#undef ATOMIC_LOAD_LIST
#undef ATOMIC_STORE_LIST
class WasmDecorator final : public GraphDecorator {
public:
explicit WasmDecorator(NodeOriginTable* origins, wasm::Decoder* decoder)
: origins_(origins), decoder_(decoder) {}
void Decorate(Node* node) final {
origins_->SetNodeOrigin(
node, NodeOrigin("wasm graph creation", "n/a",
NodeOrigin::kWasmBytecode, decoder_->position()));
}
private:
compiler::NodeOriginTable* origins_;
wasm::Decoder* decoder_;
};
void WasmGraphBuilder::AddBytecodePositionDecorator(
NodeOriginTable* node_origins, wasm::Decoder* decoder) {
DCHECK_NULL(decorator_);
decorator_ = new (graph()->zone()) WasmDecorator(node_origins, decoder);
graph()->AddDecorator(decorator_);
}
void WasmGraphBuilder::RemoveBytecodePositionDecorator() {
DCHECK_NOT_NULL(decorator_);
graph()->RemoveDecorator(decorator_);
decorator_ = nullptr;
}
namespace {
bool must_record_function_compilation(Isolate* isolate) {
return isolate->logger()->is_listening_to_code_events() ||
......@@ -4992,7 +5021,7 @@ TurbofanWasmCompilationUnit::TurbofanWasmCompilationUnit(
TurbofanWasmCompilationUnit::~TurbofanWasmCompilationUnit() = default;
SourcePositionTable* TurbofanWasmCompilationUnit::BuildGraphForWasmFunction(
double* decode_ms) {
double* decode_ms, NodeOriginTable* node_origins) {
base::ElapsedTimer decode_timer;
if (FLAG_trace_wasm_decode_time) {
decode_timer.Start();
......@@ -5004,8 +5033,9 @@ SourcePositionTable* TurbofanWasmCompilationUnit::BuildGraphForWasmFunction(
WasmGraphBuilder builder(wasm_unit_->isolate_, wasm_unit_->env_,
mcgraph_->zone(), mcgraph_, wasm_unit_->centry_stub_,
wasm_unit_->func_body_.sig, source_position_table);
graph_construction_result_ = wasm::BuildTFGraph(
wasm_unit_->isolate_->allocator(), &builder, wasm_unit_->func_body_);
graph_construction_result_ =
wasm::BuildTFGraph(wasm_unit_->isolate_->allocator(), &builder,
wasm_unit_->func_body_, node_origins);
if (graph_construction_result_.failed()) {
if (FLAG_trace_wasm_compiler) {
OFStream os(stdout);
......@@ -5072,23 +5102,37 @@ void TurbofanWasmCompilationUnit::ExecuteCompilation() {
&graph_zone, MachineType::PointerRepresentation(),
InstructionSelector::SupportedMachineOperatorFlags(),
InstructionSelector::AlignmentRequirements()));
compilation_zone_.reset(
new Zone(wasm_unit_->isolate_->allocator(), ZONE_NAME));
info_.reset(new OptimizedCompilationInfo(
GetDebugName(compilation_zone_.get(), wasm_unit_->func_name_,
wasm_unit_->func_index_),
compilation_zone_.get(), Code::WASM_FUNCTION));
NodeOriginTable* node_origins = info_->trace_turbo_json_enabled()
? new (&graph_zone)
NodeOriginTable(mcgraph_->graph())
: nullptr;
SourcePositionTable* source_positions =
BuildGraphForWasmFunction(&decode_ms);
BuildGraphForWasmFunction(&decode_ms, node_origins);
if (graph_construction_result_.failed()) {
ok_ = false;
return;
}
if (node_origins) {
node_origins->AddDecorator();
}
base::ElapsedTimer pipeline_timer;
if (FLAG_trace_wasm_decode_time) {
node_count = mcgraph_->graph()->NodeCount();
pipeline_timer.Start();
}
compilation_zone_.reset(
new Zone(wasm_unit_->isolate_->allocator(), ZONE_NAME));
// Run the compiler pipeline to generate machine code.
auto call_descriptor = GetWasmCallDescriptor(compilation_zone_.get(),
wasm_unit_->func_body_.sig);
......@@ -5096,15 +5140,6 @@ void TurbofanWasmCompilationUnit::ExecuteCompilation() {
call_descriptor =
GetI32WasmCallDescriptor(compilation_zone_.get(), call_descriptor);
}
info_.reset(new OptimizedCompilationInfo(
GetDebugName(compilation_zone_.get(), wasm_unit_->func_name_,
wasm_unit_->func_index_),
compilation_zone_.get(), Code::WASM_FUNCTION));
NodeOriginTable* node_origins = info_->trace_turbo_json_enabled()
? new (&graph_zone)
NodeOriginTable(mcgraph_->graph())
: nullptr;
job_.reset(Pipeline::NewWasmCompilationJob(
info_.get(), wasm_unit_->isolate_, mcgraph_, call_descriptor,
......
......@@ -29,8 +29,10 @@ class CallDescriptor;
class Graph;
class MachineGraph;
class Node;
class NodeOriginTable;
class Operator;
class SourcePositionTable;
class WasmDecorator;
} // namespace compiler
namespace wasm {
......@@ -78,7 +80,8 @@ class TurbofanWasmCompilationUnit {
explicit TurbofanWasmCompilationUnit(wasm::WasmCompilationUnit* wasm_unit);
~TurbofanWasmCompilationUnit();
SourcePositionTable* BuildGraphForWasmFunction(double* decode_ms);
SourcePositionTable* BuildGraphForWasmFunction(double* decode_ms,
NodeOriginTable* node_origins);
void ExecuteCompilation();
......@@ -331,6 +334,11 @@ class WasmGraphBuilder {
MachineGraph* mcgraph() { return mcgraph_; }
Graph* graph();
void AddBytecodePositionDecorator(NodeOriginTable* node_origins,
wasm::Decoder* decoder);
void RemoveBytecodePositionDecorator();
protected:
static const int kDefaultBufferSize = 16;
......@@ -361,6 +369,8 @@ class WasmGraphBuilder {
wasm::FunctionSig* const sig_;
compiler::WasmDecorator* decorator_ = nullptr;
compiler::SourcePositionTable* const source_position_table_ = nullptr;
Node* CEntryStub();
......
......@@ -857,11 +857,18 @@ DecodeResult VerifyWasmCodeWithStats(AccountingAllocator* allocator,
}
DecodeResult BuildTFGraph(AccountingAllocator* allocator, TFBuilder* builder,
FunctionBody& body) {
FunctionBody& body,
compiler::NodeOriginTable* node_origins) {
Zone zone(allocator, ZONE_NAME);
WasmFullDecoder<Decoder::kValidate, WasmGraphBuildingInterface> decoder(
&zone, builder->module(), body, builder);
if (node_origins) {
builder->AddBytecodePositionDecorator(node_origins, &decoder);
}
decoder.Decode();
if (node_origins) {
builder->RemoveBytecodePositionDecorator();
}
return decoder.toResult(nullptr);
}
......@@ -907,15 +914,17 @@ bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
const wasm::WasmModule* module, PrintLocals print_locals,
std::ostream& os) {
std::ostream& os, std::vector<int>* line_numbers) {
Zone zone(allocator, ZONE_NAME);
WasmDecoder<Decoder::kNoValidate> decoder(module, body.sig, body.start,
body.end);
int line_nr = 0;
constexpr int kNoByteCode = -1;
// Print the function signature.
if (body.sig) {
os << "// signature: " << *body.sig << std::endl;
if (line_numbers) line_numbers->push_back(kNoByteCode);
++line_nr;
}
......@@ -938,16 +947,19 @@ bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
}
}
os << std::endl;
if (line_numbers) line_numbers->push_back(kNoByteCode);
++line_nr;
for (const byte* locals = body.start; locals < i.pc(); locals++) {
os << (locals == body.start ? "0x" : " 0x") << AsHex(*locals, 2) << ",";
}
os << std::endl;
if (line_numbers) line_numbers->push_back(kNoByteCode);
++line_nr;
}
os << "// body: " << std::endl;
if (line_numbers) line_numbers->push_back(kNoByteCode);
++line_nr;
unsigned control_depth = 0;
for (; i.has_next(); i.next()) {
......@@ -955,6 +967,7 @@ bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
WasmDecoder<Decoder::kNoValidate>::OpcodeLength(&decoder, i.pc());
WasmOpcode opcode = i.current();
if (line_numbers) line_numbers->push_back(i.position());
if (opcode == kExprElse) control_depth--;
int num_whitespaces = control_depth < 32 ? 2 * control_depth : 64;
......@@ -1051,6 +1064,7 @@ bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
os << std::endl;
++line_nr;
}
DCHECK(!line_numbers || line_numbers->size() == static_cast<size_t>(line_nr));
return decoder.ok();
}
......
......@@ -20,6 +20,7 @@ class BitVector; // forward declaration
class Counters;
namespace compiler { // external declarations from compiler.
class NodeOriginTable;
class WasmGraphBuilder;
}
......@@ -53,7 +54,8 @@ DecodeResult VerifyWasmCodeWithStats(AccountingAllocator* allocator,
Counters* counters);
DecodeResult BuildTFGraph(AccountingAllocator* allocator, TFBuilder* builder,
FunctionBody& body);
FunctionBody& body,
compiler::NodeOriginTable* node_origins);
enum PrintLocals { kPrintLocals, kOmitLocals };
V8_EXPORT_PRIVATE
bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
......@@ -62,7 +64,8 @@ bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
V8_EXPORT_PRIVATE
bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
const wasm::WasmModule* module, PrintLocals print_locals,
std::ostream& out);
std::ostream& out,
std::vector<int>* line_numbers = nullptr);
// A simplified form of AST printing, e.g. from a debugger.
void PrintRawWasmCode(const byte* start, const byte* end);
......@@ -78,7 +81,7 @@ inline DecodeResult BuildTFGraph(AccountingAllocator* allocator,
TFBuilder* builder, FunctionSig* sig,
const byte* start, const byte* end) {
FunctionBody body(sig, 0, start, end);
return BuildTFGraph(allocator, builder, body);
return BuildTFGraph(allocator, builder, body, nullptr);
}
struct BodyLocalDecls {
......
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