Commit 94fb8904 authored by danno's avatar danno Committed by Commit bot

[turbofan] Fix source position integration with Linux perf

Review-Url: https://codereview.chromium.org/2558283002
Cr-Commit-Position: refs/heads/master@{#41637}
parent 291ab70f
...@@ -1086,10 +1086,9 @@ DEFINE_IMPLICATION(perf_basic_prof_only_functions, perf_basic_prof) ...@@ -1086,10 +1086,9 @@ DEFINE_IMPLICATION(perf_basic_prof_only_functions, perf_basic_prof)
DEFINE_BOOL(perf_prof, false, DEFINE_BOOL(perf_prof, false,
"Enable perf linux profiler (experimental annotate support).") "Enable perf linux profiler (experimental annotate support).")
DEFINE_NEG_IMPLICATION(perf_prof, compact_code_space) DEFINE_NEG_IMPLICATION(perf_prof, compact_code_space)
DEFINE_BOOL(perf_prof_debug_info, false,
"Enable debug info for perf linux profiler (experimental).")
DEFINE_BOOL(perf_prof_unwinding_info, false, DEFINE_BOOL(perf_prof_unwinding_info, false,
"Enable unwinding info for perf linux profiler (experimental).") "Enable unwinding info for perf linux profiler (experimental).")
DEFINE_IMPLICATION(perf_prof, perf_prof_unwinding_info)
DEFINE_STRING(gc_fake_mmap, "/tmp/__v8_gc__", DEFINE_STRING(gc_fake_mmap, "/tmp/__v8_gc__",
"Specify the name of the file for fake gc mmap used in ll_prof") "Specify the name of the file for fake gc mmap used in ll_prof")
DEFINE_BOOL(log_internal_timer_events, false, "Time internal events.") DEFINE_BOOL(log_internal_timer_events, false, "Time internal events.")
......
...@@ -2818,8 +2818,8 @@ bool Isolate::use_crankshaft() const { ...@@ -2818,8 +2818,8 @@ bool Isolate::use_crankshaft() const {
bool Isolate::NeedsSourcePositionsForProfiling() const { bool Isolate::NeedsSourcePositionsForProfiling() const {
return FLAG_trace_deopt || FLAG_trace_turbo || FLAG_trace_turbo_graph || return FLAG_trace_deopt || FLAG_trace_turbo || FLAG_trace_turbo_graph ||
FLAG_turbo_profiling || is_profiling() || debug_->is_active() || FLAG_turbo_profiling || FLAG_perf_prof || is_profiling() ||
logger_->is_logging(); debug_->is_active() || logger_->is_logging();
} }
bool Isolate::IsArrayOrObjectPrototype(Object* object) { bool Isolate::IsArrayOrObjectPrototype(Object* object) {
......
...@@ -212,7 +212,7 @@ void PerfJitLogger::LogRecordedBuffer(AbstractCode* abstract_code, ...@@ -212,7 +212,7 @@ void PerfJitLogger::LogRecordedBuffer(AbstractCode* abstract_code,
DCHECK(code->instruction_start() == code->address() + Code::kHeaderSize); DCHECK(code->instruction_start() == code->address() + Code::kHeaderSize);
// Debug info has to be emitted first. // Debug info has to be emitted first.
if (FLAG_perf_prof_debug_info && shared != nullptr) { if (FLAG_perf_prof && shared != nullptr) {
LogWriteDebugInfo(code, shared); LogWriteDebugInfo(code, shared);
} }
...@@ -246,34 +246,47 @@ void PerfJitLogger::LogRecordedBuffer(AbstractCode* abstract_code, ...@@ -246,34 +246,47 @@ void PerfJitLogger::LogRecordedBuffer(AbstractCode* abstract_code,
LogWriteBytes(reinterpret_cast<const char*>(code_pointer), code_size); LogWriteBytes(reinterpret_cast<const char*>(code_pointer), code_size);
} }
void PerfJitLogger::LogWriteDebugInfo(Code* code, SharedFunctionInfo* shared) { namespace {
DisallowHeapAllocation no_gc;
// Compute the entry count and get the name of the script.
uint32_t entry_count = 0;
for (SourcePositionTableIterator iterator(code->source_position_table());
!iterator.done(); iterator.Advance()) {
entry_count++;
}
if (entry_count == 0) return;
Script* script = Script::cast(shared->script());
Object* name_or_url = script->GetNameOrSourceURL();
std::unique_ptr<char[]> GetScriptName(Handle<Script> script) {
Object* name_or_url = script->GetNameOrSourceURL();
int name_length = 0; int name_length = 0;
std::unique_ptr<char[]> name_string; std::unique_ptr<char[]> name_string;
if (name_or_url->IsString()) { if (name_or_url->IsString()) {
name_string = return String::cast(name_or_url)
String::cast(name_or_url) ->ToCString(DISALLOW_NULLS, FAST_STRING_TRAVERSAL, &name_length);
->ToCString(DISALLOW_NULLS, FAST_STRING_TRAVERSAL, &name_length);
DCHECK_EQ(0, name_string.get()[name_length]);
} else { } else {
const char unknown[] = "<unknown>"; const char unknown[] = "<unknown>";
name_length = static_cast<int>(strlen(unknown)); name_length = static_cast<int>(strlen(unknown));
char* buffer = NewArray<char>(name_length); char* buffer = NewArray<char>(name_length);
base::OS::StrNCpy(buffer, name_length + 1, unknown, base::OS::StrNCpy(buffer, name_length + 1, unknown,
static_cast<size_t>(name_length)); static_cast<size_t>(name_length));
name_string = std::unique_ptr<char[]>(buffer); return std::unique_ptr<char[]>(buffer);
}
}
SourcePositionInfo GetSourcePositionInfo(Handle<Code> code,
Handle<SharedFunctionInfo> function,
SourcePosition pos) {
if (code->is_turbofanned() || code->is_crankshafted()) {
DisallowHeapAllocation disallow;
return pos.InliningStack(code)[0];
} else {
return SourcePositionInfo(pos, function);
}
}
} // namespace
void PerfJitLogger::LogWriteDebugInfo(Code* code, SharedFunctionInfo* shared) {
// Compute the entry count and get the name of the script.
uint32_t entry_count = 0;
for (SourcePositionTableIterator iterator(code->source_position_table());
!iterator.done(); iterator.Advance()) {
entry_count++;
} }
DCHECK_EQ(name_length, static_cast<int>(strlen(name_string.get()))); if (entry_count == 0) return;
Handle<Script> script(Script::cast(shared->script()));
PerfJitCodeDebugInfo debug_info; PerfJitCodeDebugInfo debug_info;
...@@ -285,42 +298,44 @@ void PerfJitLogger::LogWriteDebugInfo(Code* code, SharedFunctionInfo* shared) { ...@@ -285,42 +298,44 @@ void PerfJitLogger::LogWriteDebugInfo(Code* code, SharedFunctionInfo* shared) {
uint32_t size = sizeof(debug_info); uint32_t size = sizeof(debug_info);
// Add the sizes of fixed parts of entries. // Add the sizes of fixed parts of entries.
size += entry_count * sizeof(PerfJitDebugEntry); size += entry_count * sizeof(PerfJitDebugEntry);
// Add the size of the name after the first entry. // Add the size of the name after each entry.
size += (static_cast<uint32_t>(name_length) + 1) * entry_count;
int padding = ((size + 7) & (~7)) - size; Handle<Code> code_handle(code);
Handle<SharedFunctionInfo> function_handle(shared);
for (SourcePositionTableIterator iterator(code->source_position_table());
!iterator.done(); iterator.Advance()) {
SourcePositionInfo info(GetSourcePositionInfo(code_handle, function_handle,
iterator.source_position()));
Handle<Script> script(Script::cast(info.function->script()));
std::unique_ptr<char[]> name_string = GetScriptName(script);
size += (static_cast<uint32_t>(strlen(name_string.get())) + 1);
}
int padding = ((size + 7) & (~7)) - size;
debug_info.size_ = size + padding; debug_info.size_ = size + padding;
LogWriteBytes(reinterpret_cast<const char*>(&debug_info), sizeof(debug_info)); LogWriteBytes(reinterpret_cast<const char*>(&debug_info), sizeof(debug_info));
int script_line_offset = script->line_offset();
FixedArray* line_ends = FixedArray::cast(script->line_ends());
Address code_start = code->instruction_start(); Address code_start = code->instruction_start();
for (SourcePositionTableIterator iterator(code->source_position_table()); for (SourcePositionTableIterator iterator(code->source_position_table());
!iterator.done(); iterator.Advance()) { !iterator.done(); iterator.Advance()) {
int position = iterator.source_position().ScriptOffset(); SourcePositionInfo info(GetSourcePositionInfo(code_handle, function_handle,
int line_number = script->GetLineNumber(position); iterator.source_position()));
// Compute column.
int relative_line_number = line_number - script_line_offset;
int start =
(relative_line_number == 0)
? 0
: Smi::cast(line_ends->get(relative_line_number - 1))->value() + 1;
int column_offset = position - start;
if (relative_line_number == 0) {
// For the case where the code is on the same line as the script tag.
column_offset += script->column_offset();
}
PerfJitDebugEntry entry; PerfJitDebugEntry entry;
// TODO(danno): There seems to be a bug in the dwarf handling of JIT code in
// the perf tool. It seems to erroneously believe that the first instruction
// of functions is at offset 0x40 when displayed in "perf report". To
// compensate for this, add a magic constant to the position addresses when
// writing them out.
entry.address_ = entry.address_ =
reinterpret_cast<uint64_t>(code_start + iterator.code_offset()); reinterpret_cast<intptr_t>(code_start + iterator.code_offset() + 0x40);
entry.line_number_ = line_number; entry.line_number_ = info.line + 1;
entry.column_ = column_offset; entry.column_ = info.column + 1;
LogWriteBytes(reinterpret_cast<const char*>(&entry), sizeof(entry)); LogWriteBytes(reinterpret_cast<const char*>(&entry), sizeof(entry));
LogWriteBytes(name_string.get(), name_length + 1); Handle<Script> script(Script::cast(info.function->script()));
std::unique_ptr<char[]> name_string = GetScriptName(script);
LogWriteBytes(name_string.get(),
static_cast<uint32_t>(strlen(name_string.get())) + 1);
} }
char padding_bytes[] = "\0\0\0\0\0\0\0\0"; char padding_bytes[] = "\0\0\0\0\0\0\0\0";
LogWriteBytes(padding_bytes, padding); LogWriteBytes(padding_bytes, padding);
......
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