Commit 7ecb6a38 authored by Stephan Herhut's avatar Stephan Herhut Committed by Commit Bot

Implement code creation events for wasm code on native heap

Adds support for generating logging/profiling event when wasm code gets compiled
on the native heap. As code objects on the native heap are not ordinary heap
objects, the existing abstractions for reporting cannot be used. Instead, add
specialized versions for WasmCode objects.

Change-Id: I808618d70142073b3c1b06edef6931f59bed8cf5
Reviewed-on: https://chromium-review.googlesource.com/913308
Commit-Queue: Stephan Herhut <herhut@chromium.org>
Reviewed-by: 's avatarClemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51388}
parent be6d1292
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "src/base/platform/mutex.h" #include "src/base/platform/mutex.h"
#include "src/globals.h" #include "src/globals.h"
#include "src/vector.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -19,6 +20,11 @@ class Name; ...@@ -19,6 +20,11 @@ class Name;
class SharedFunctionInfo; class SharedFunctionInfo;
class String; class String;
namespace wasm {
class WasmCode;
using WasmName = Vector<const char>;
} // namespace wasm
#define LOG_EVENTS_AND_TAGS_LIST(V) \ #define LOG_EVENTS_AND_TAGS_LIST(V) \
V(CODE_CREATION_EVENT, "code-creation") \ V(CODE_CREATION_EVENT, "code-creation") \
V(CODE_DISABLE_OPT_EVENT, "code-disable-optimization") \ V(CODE_DISABLE_OPT_EVENT, "code-disable-optimization") \
...@@ -65,6 +71,8 @@ class CodeEventListener { ...@@ -65,6 +71,8 @@ class CodeEventListener {
virtual void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code, virtual void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
SharedFunctionInfo* shared, Name* source, SharedFunctionInfo* shared, Name* source,
int line, int column) = 0; int line, int column) = 0;
virtual void CodeCreateEvent(LogEventsAndTags tag, wasm::WasmCode* code,
wasm::WasmName name) = 0;
virtual void CallbackEvent(Name* name, Address entry_point) = 0; virtual void CallbackEvent(Name* name, Address entry_point) = 0;
virtual void GetterCallbackEvent(Name* name, Address entry_point) = 0; virtual void GetterCallbackEvent(Name* name, Address entry_point) = 0;
virtual void SetterCallbackEvent(Name* name, Address entry_point) = 0; virtual void SetterCallbackEvent(Name* name, Address entry_point) = 0;
...@@ -118,6 +126,10 @@ class CodeEventDispatcher { ...@@ -118,6 +126,10 @@ class CodeEventDispatcher {
CODE_EVENT_DISPATCH( CODE_EVENT_DISPATCH(
CodeCreateEvent(tag, code, shared, source, line, column)); CodeCreateEvent(tag, code, shared, source, line, column));
} }
void CodeCreateEvent(LogEventsAndTags tag, wasm::WasmCode* code,
wasm::WasmName name) {
CODE_EVENT_DISPATCH(CodeCreateEvent(tag, code, name));
}
void CallbackEvent(Name* name, Address entry_point) { void CallbackEvent(Name* name, Address entry_point) {
CODE_EVENT_DISPATCH(CallbackEvent(name, entry_point)); CODE_EVENT_DISPATCH(CallbackEvent(name, entry_point));
} }
......
...@@ -4688,7 +4688,7 @@ Handle<Code> CompileJSToWasmWrapper(Isolate* isolate, wasm::WasmModule* module, ...@@ -4688,7 +4688,7 @@ Handle<Code> CompileJSToWasmWrapper(Isolate* isolate, wasm::WasmModule* module,
#endif #endif
if (must_record_function_compilation(isolate)) { if (must_record_function_compilation(isolate)) {
RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, isolate, code, RecordFunctionCompilation(CodeEventListener::STUB_TAG, isolate, code,
"%.*s", func_name.length(), func_name.start()); "%.*s", func_name.length(), func_name.start());
} }
...@@ -4821,7 +4821,7 @@ Handle<Code> CompileWasmToJSWrapper( ...@@ -4821,7 +4821,7 @@ Handle<Code> CompileWasmToJSWrapper(
#endif #endif
if (must_record_function_compilation(isolate)) { if (must_record_function_compilation(isolate)) {
RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, isolate, code, RecordFunctionCompilation(CodeEventListener::STUB_TAG, isolate, code,
"%.*s", func_name.length(), func_name.start()); "%.*s", func_name.length(), func_name.start());
} }
...@@ -4894,7 +4894,7 @@ Handle<Code> CompileWasmToWasmWrapper(Isolate* isolate, WasmCodeWrapper target, ...@@ -4894,7 +4894,7 @@ Handle<Code> CompileWasmToWasmWrapper(Isolate* isolate, WasmCodeWrapper target,
buffer.Dispose(); buffer.Dispose();
} }
if (isolate->logger()->is_logging_code_events() || isolate->is_profiling()) { if (isolate->logger()->is_logging_code_events() || isolate->is_profiling()) {
RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, isolate, code, RecordFunctionCompilation(CodeEventListener::STUB_TAG, isolate, code,
"wasm-to-wasm"); "wasm-to-wasm");
} }
...@@ -4957,7 +4957,7 @@ Handle<Code> CompileWasmInterpreterEntry(Isolate* isolate, uint32_t func_index, ...@@ -4957,7 +4957,7 @@ Handle<Code> CompileWasmInterpreterEntry(Isolate* isolate, uint32_t func_index,
#endif #endif
if (must_record_function_compilation(isolate)) { if (must_record_function_compilation(isolate)) {
RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, isolate, code, RecordFunctionCompilation(CodeEventListener::STUB_TAG, isolate, code,
"%.*s", func_name.length(), func_name.start()); "%.*s", func_name.length(), func_name.start());
} }
} }
...@@ -5320,7 +5320,6 @@ WasmCodeWrapper WasmCompilationUnit::FinishTurbofanCompilation( ...@@ -5320,7 +5320,6 @@ WasmCodeWrapper WasmCompilationUnit::FinishTurbofanCompilation(
if (!code) { if (!code) {
return WasmCodeWrapper(code); return WasmCodeWrapper(code);
} }
// TODO(mtrofin): add CodeEventListener call - see the non-native case.
if (FLAG_trace_wasm_decode_time) { if (FLAG_trace_wasm_decode_time) {
double codegen_ms = codegen_timer.Elapsed().InMillisecondsF(); double codegen_ms = codegen_timer.Elapsed().InMillisecondsF();
PrintF("wasm-code-generation ok: %u bytes, %0.3f ms code generation\n", PrintF("wasm-code-generation ok: %u bytes, %0.3f ms code generation\n",
...@@ -5328,6 +5327,9 @@ WasmCodeWrapper WasmCompilationUnit::FinishTurbofanCompilation( ...@@ -5328,6 +5327,9 @@ WasmCodeWrapper WasmCompilationUnit::FinishTurbofanCompilation(
codegen_ms); codegen_ms);
} }
PROFILE(isolate_,
CodeCreateEvent(CodeEventListener::FUNCTION_TAG, code, func_name_));
Handle<ByteArray> source_positions = Handle<ByteArray> source_positions =
tf_.job_->compilation_info()->wasm_code_desc()->source_positions_table; tf_.job_->compilation_info()->wasm_code_desc()->source_positions_table;
MaybeHandle<HandlerTable> handler_table = MaybeHandle<HandlerTable> handler_table =
...@@ -5408,14 +5410,16 @@ WasmCodeWrapper WasmCompilationUnit::FinishLiftoffCompilation( ...@@ -5408,14 +5410,16 @@ WasmCodeWrapper WasmCompilationUnit::FinishLiftoffCompilation(
PackProtectedInstructions(code); PackProtectedInstructions(code);
ret = WasmCodeWrapper(code); ret = WasmCodeWrapper(code);
} else { } else {
// TODO(mtrofin): figure a way to raise events. // TODO(herhut) Consider lifting it to FinishCompilation.
// Consider lifting it to FinishCompilation.
native_module_->compiled_module()->source_positions()->set( native_module_->compiled_module()->source_positions()->set(
func_index_, *source_positions); func_index_, *source_positions);
ret = WasmCodeWrapper( wasm::WasmCode* code =
native_module_->AddCode(desc, liftoff_.asm_.GetTotalFrameSlotCount(), native_module_->AddCode(desc, liftoff_.asm_.GetTotalFrameSlotCount(),
func_index_, liftoff_.safepoint_table_offset_, func_index_, liftoff_.safepoint_table_offset_,
std::move(protected_instructions_), true)); std::move(protected_instructions_), true);
PROFILE(isolate_,
CodeCreateEvent(CodeEventListener::FUNCTION_TAG, code, func_name_));
ret = WasmCodeWrapper(code);
} }
#ifdef ENABLE_DISASSEMBLER #ifdef ENABLE_DISASSEMBLER
if (FLAG_print_code || FLAG_print_wasm_code) { if (FLAG_print_code || FLAG_print_wasm_code) {
......
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
#include "src/tracing/tracing-category-observer.h" #include "src/tracing/tracing-category-observer.h"
#include "src/unicode-inl.h" #include "src/unicode-inl.h"
#include "src/vm-state-inl.h" #include "src/vm-state-inl.h"
#include "src/wasm/wasm-code-manager.h"
#include "src/wasm/wasm-objects.h"
#include "src/utils.h" #include "src/utils.h"
#include "src/version.h" #include "src/version.h"
...@@ -201,6 +203,24 @@ void CodeEventLogger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag, ...@@ -201,6 +203,24 @@ void CodeEventLogger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
LogRecordedBuffer(code, shared, name_buffer_->get(), name_buffer_->size()); LogRecordedBuffer(code, shared, name_buffer_->get(), name_buffer_->size());
} }
void CodeEventLogger::CodeCreateEvent(LogEventsAndTags tag,
wasm::WasmCode* code,
wasm::WasmName name) {
name_buffer_->Init(tag);
if (name.is_empty()) {
name_buffer_->AppendBytes("<wasm-unknown>");
} else {
name_buffer_->AppendBytes(name.start(), name.length());
}
name_buffer_->AppendByte('-');
if (code->IsAnonymous()) {
name_buffer_->AppendBytes("<anonymous>");
} else {
name_buffer_->AppendInt(code->index());
}
LogRecordedBuffer(code, name_buffer_->get(), name_buffer_->size());
}
void CodeEventLogger::RegExpCodeCreateEvent(AbstractCode* code, void CodeEventLogger::RegExpCodeCreateEvent(AbstractCode* code,
String* source) { String* source) {
name_buffer_->Init(CodeEventListener::REG_EXP_TAG); name_buffer_->Init(CodeEventListener::REG_EXP_TAG);
...@@ -231,6 +251,10 @@ class PerfBasicLogger : public CodeEventLogger { ...@@ -231,6 +251,10 @@ class PerfBasicLogger : public CodeEventLogger {
const char* name, int length) override; const char* name, int length) override;
void LogRecordedBuffer(const InstructionStream* stream, const char* name, void LogRecordedBuffer(const InstructionStream* stream, const char* name,
int length) override; int length) override;
void LogRecordedBuffer(wasm::WasmCode* code, const char* name,
int length) override;
void WriteLogRecordedBuffer(uintptr_t address, int size, const char* name,
int name_length);
// Extension added to V8 log file name to get the low-level log name. // Extension added to V8 log file name to get the low-level log name.
static const char kFilenameFormatString[]; static const char kFilenameFormatString[];
...@@ -264,6 +288,19 @@ PerfBasicLogger::~PerfBasicLogger() { ...@@ -264,6 +288,19 @@ PerfBasicLogger::~PerfBasicLogger() {
perf_output_handle_ = nullptr; perf_output_handle_ = nullptr;
} }
void PerfBasicLogger::WriteLogRecordedBuffer(uintptr_t address, int size,
const char* name,
int name_length) {
// Linux perf expects hex literals without a leading 0x, while some
// implementations of printf might prepend one when using the %p format
// for pointers, leading to wrongly formatted JIT symbols maps.
//
// Instead, we use V8PRIxPTR format string and cast pointer to uintpr_t,
// so that we have control over the exact output format.
base::OS::FPrint(perf_output_handle_, "%" V8PRIxPTR " %x %.*s\n", address,
size, name_length, name);
}
void PerfBasicLogger::LogRecordedBuffer(AbstractCode* code, SharedFunctionInfo*, void PerfBasicLogger::LogRecordedBuffer(AbstractCode* code, SharedFunctionInfo*,
const char* name, int length) { const char* name, int length) {
if (FLAG_perf_basic_prof_only_functions && if (FLAG_perf_basic_prof_only_functions &&
...@@ -272,15 +309,15 @@ void PerfBasicLogger::LogRecordedBuffer(AbstractCode* code, SharedFunctionInfo*, ...@@ -272,15 +309,15 @@ void PerfBasicLogger::LogRecordedBuffer(AbstractCode* code, SharedFunctionInfo*,
return; return;
} }
// Linux perf expects hex literals without a leading 0x, while some WriteLogRecordedBuffer(reinterpret_cast<uintptr_t>(code->instruction_start()),
// implementations of printf might prepend one when using the %p format code->instruction_size(), name, length);
// for pointers, leading to wrongly formatted JIT symbols maps. }
//
// Instead, we use V8PRIxPTR format string and cast pointer to uintpr_t, void PerfBasicLogger::LogRecordedBuffer(wasm::WasmCode* code, const char* name,
// so that we have control over the exact output format. int length) {
base::OS::FPrint(perf_output_handle_, "%" V8PRIxPTR " %x %.*s\n", WriteLogRecordedBuffer(
reinterpret_cast<uintptr_t>(code->instruction_start()), reinterpret_cast<uintptr_t>(code->instructions().start()),
code->instruction_size(), length, name); code->instructions().length(), name, length);
} }
void PerfBasicLogger::LogRecordedBuffer(const InstructionStream* stream, void PerfBasicLogger::LogRecordedBuffer(const InstructionStream* stream,
...@@ -315,6 +352,8 @@ class LowLevelLogger : public CodeEventLogger { ...@@ -315,6 +352,8 @@ class LowLevelLogger : public CodeEventLogger {
const char* name, int length) override; const char* name, int length) override;
void LogRecordedBuffer(const InstructionStream* stream, const char* name, void LogRecordedBuffer(const InstructionStream* stream, const char* name,
int length) override; int length) override;
void LogRecordedBuffer(wasm::WasmCode* code, const char* name,
int length) override;
// Low-level profiling event structures. // Low-level profiling event structures.
struct CodeCreateStruct { struct CodeCreateStruct {
...@@ -423,6 +462,18 @@ void LowLevelLogger::LogRecordedBuffer(const InstructionStream* stream, ...@@ -423,6 +462,18 @@ void LowLevelLogger::LogRecordedBuffer(const InstructionStream* stream,
static_cast<int>(stream->byte_length())); static_cast<int>(stream->byte_length()));
} }
void LowLevelLogger::LogRecordedBuffer(wasm::WasmCode* code, const char* name,
int length) {
CodeCreateStruct event;
event.name_size = length;
event.code_address = code->instructions().start();
event.code_size = code->instructions().length();
LogWriteStruct(event);
LogWriteBytes(name, length);
LogWriteBytes(reinterpret_cast<const char*>(code->instructions().start()),
code->instructions().length());
}
void LowLevelLogger::CodeMoveEvent(AbstractCode* from, Address to) { void LowLevelLogger::CodeMoveEvent(AbstractCode* from, Address to) {
CodeMoveStruct event; CodeMoveStruct event;
event.from_address = from->instruction_start(); event.from_address = from->instruction_start();
...@@ -464,6 +515,8 @@ class JitLogger : public CodeEventLogger { ...@@ -464,6 +515,8 @@ class JitLogger : public CodeEventLogger {
const char* name, int length) override; const char* name, int length) override;
void LogRecordedBuffer(const InstructionStream* stream, const char* name, void LogRecordedBuffer(const InstructionStream* stream, const char* name,
int length) override; int length) override;
void LogRecordedBuffer(wasm::WasmCode* code, const char* name,
int length) override;
JitCodeEventHandler code_event_handler_; JitCodeEventHandler code_event_handler_;
base::Mutex logger_mutex_; base::Mutex logger_mutex_;
...@@ -506,6 +559,18 @@ void JitLogger::LogRecordedBuffer(const InstructionStream* stream, ...@@ -506,6 +559,18 @@ void JitLogger::LogRecordedBuffer(const InstructionStream* stream,
code_event_handler_(&event); code_event_handler_(&event);
} }
void JitLogger::LogRecordedBuffer(wasm::WasmCode* code, const char* name,
int length) {
JitCodeEvent event;
memset(&event, 0, sizeof(event));
event.type = JitCodeEvent::CODE_ADDED;
event.code_start = code->instructions().start();
event.code_len = code->instructions().length();
event.name.str = name;
event.name.len = length;
code_event_handler_(&event);
}
void JitLogger::CodeMoveEvent(AbstractCode* from, Address to) { void JitLogger::CodeMoveEvent(AbstractCode* from, Address to) {
base::LockGuard<base::Mutex> guard(&logger_mutex_); base::LockGuard<base::Mutex> guard(&logger_mutex_);
...@@ -1032,12 +1097,20 @@ namespace { ...@@ -1032,12 +1097,20 @@ namespace {
void AppendCodeCreateHeader(Log::MessageBuilder& msg, void AppendCodeCreateHeader(Log::MessageBuilder& msg,
CodeEventListener::LogEventsAndTags tag, CodeEventListener::LogEventsAndTags tag,
AbstractCode* code, base::ElapsedTimer* timer) { AbstractCode::Kind kind, uint8_t* address, int size,
base::ElapsedTimer* timer) {
msg << kLogEventsNames[CodeEventListener::CODE_CREATION_EVENT] msg << kLogEventsNames[CodeEventListener::CODE_CREATION_EVENT]
<< Logger::kNext << kLogEventsNames[tag] << Logger::kNext << code->kind() << Logger::kNext << kLogEventsNames[tag] << Logger::kNext << kind
<< Logger::kNext << timer->Elapsed().InMicroseconds() << Logger::kNext << Logger::kNext << timer->Elapsed().InMicroseconds() << Logger::kNext
<< reinterpret_cast<void*>(code->instruction_start()) << Logger::kNext << reinterpret_cast<void*>(address) << Logger::kNext << size
<< code->instruction_size() << Logger::kNext; << Logger::kNext;
}
void AppendCodeCreateHeader(Log::MessageBuilder& msg,
CodeEventListener::LogEventsAndTags tag,
AbstractCode* code, base::ElapsedTimer* timer) {
AppendCodeCreateHeader(msg, tag, code->kind(), code->instruction_start(),
code->instruction_size(), timer);
} }
void AppendCodeCreateHeader(Log::MessageBuilder& msg, void AppendCodeCreateHeader(Log::MessageBuilder& msg,
...@@ -1091,6 +1164,21 @@ void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag, ...@@ -1091,6 +1164,21 @@ void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
msg.WriteToLogFile(); msg.WriteToLogFile();
} }
void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
wasm::WasmCode* code, wasm::WasmName name) {
if (!is_logging_code_events()) return;
if (!FLAG_log_code || !log_->IsEnabled()) return;
Log::MessageBuilder msg(log_);
AppendCodeCreateHeader(msg, tag, AbstractCode::Kind::WASM_FUNCTION,
code->instructions().start(),
code->instructions().length(), &timer_);
if (name.is_empty()) {
msg << "<unknown wasm>";
} else {
msg << name.start();
}
msg.WriteToLogFile();
}
// Although, it is possible to extract source and line from // Although, it is possible to extract source and line from
// the SharedFunctionInfo object, we left it to caller // the SharedFunctionInfo object, we left it to caller
...@@ -1565,6 +1653,24 @@ static int EnumerateCompiledFunctions(Heap* heap, ...@@ -1565,6 +1653,24 @@ static int EnumerateCompiledFunctions(Heap* heap,
return compiled_funcs_count; return compiled_funcs_count;
} }
static int EnumerateWasmModules(Heap* heap,
Handle<WasmCompiledModule>* modules) {
HeapIterator iterator(heap);
DisallowHeapAllocation no_gc;
int wasm_modules_count = 0;
for (HeapObject* obj = iterator.next(); obj != nullptr;
obj = iterator.next()) {
if (WasmCompiledModule::IsWasmCompiledModule(obj)) {
WasmCompiledModule* module = WasmCompiledModule::cast(obj);
if (modules != nullptr) {
modules[wasm_modules_count] = Handle<WasmCompiledModule>(module);
}
wasm_modules_count++;
}
}
return wasm_modules_count;
}
void Logger::LogCodeObject(Object* object) { void Logger::LogCodeObject(Object* object) {
AbstractCode* code_object = AbstractCode::cast(object); AbstractCode* code_object = AbstractCode::cast(object);
...@@ -1593,7 +1699,7 @@ void Logger::LogCodeObject(Object* object) { ...@@ -1593,7 +1699,7 @@ void Logger::LogCodeObject(Object* object) {
break; break;
case AbstractCode::WASM_FUNCTION: case AbstractCode::WASM_FUNCTION:
description = "A Wasm function"; description = "A Wasm function";
tag = CodeEventListener::STUB_TAG; tag = CodeEventListener::FUNCTION_TAG;
break; break;
case AbstractCode::JS_TO_WASM_FUNCTION: case AbstractCode::JS_TO_WASM_FUNCTION:
description = "A JavaScript to Wasm adapter"; description = "A JavaScript to Wasm adapter";
...@@ -1719,13 +1825,12 @@ void Logger::LogExistingFunction(Handle<SharedFunctionInfo> shared, ...@@ -1719,13 +1825,12 @@ void Logger::LogExistingFunction(Handle<SharedFunctionInfo> shared,
} }
} }
void Logger::LogCompiledFunctions() { void Logger::LogCompiledFunctions() {
Heap* heap = isolate_->heap(); Heap* heap = isolate_->heap();
HandleScope scope(isolate_); HandleScope scope(isolate_);
const int compiled_funcs_count = const int compiled_funcs_count =
EnumerateCompiledFunctions(heap, nullptr, nullptr); EnumerateCompiledFunctions(heap, nullptr, nullptr);
ScopedVector< Handle<SharedFunctionInfo> > sfis(compiled_funcs_count); ScopedVector<Handle<SharedFunctionInfo>> sfis(compiled_funcs_count);
ScopedVector<Handle<AbstractCode> > code_objects(compiled_funcs_count); ScopedVector<Handle<AbstractCode> > code_objects(compiled_funcs_count);
EnumerateCompiledFunctions(heap, sfis.start(), code_objects.start()); EnumerateCompiledFunctions(heap, sfis.start(), code_objects.start());
...@@ -1736,8 +1841,14 @@ void Logger::LogCompiledFunctions() { ...@@ -1736,8 +1841,14 @@ void Logger::LogCompiledFunctions() {
continue; continue;
LogExistingFunction(sfis[i], code_objects[i]); LogExistingFunction(sfis[i], code_objects[i]);
} }
}
const int compiled_wasm_modules_count = EnumerateWasmModules(heap, nullptr);
ScopedVector<Handle<WasmCompiledModule>> modules(compiled_wasm_modules_count);
EnumerateWasmModules(heap, modules.start());
for (int i = 0; i < compiled_wasm_modules_count; ++i) {
modules[i]->LogWasmCodes(isolate_);
}
}
void Logger::LogAccessorCallbacks() { void Logger::LogAccessorCallbacks() {
Heap* heap = isolate_->heap(); Heap* heap = isolate_->heap();
......
...@@ -74,6 +74,11 @@ class Profiler; ...@@ -74,6 +74,11 @@ class Profiler;
class ProfilerListener; class ProfilerListener;
class RuntimeCallTimer; class RuntimeCallTimer;
class Ticker; class Ticker;
class WasmCompiledModule;
namespace wasm {
class WasmCode;
}
#undef LOG #undef LOG
#define LOG(isolate, Call) \ #define LOG(isolate, Call) \
...@@ -176,6 +181,8 @@ class Logger : public CodeEventListener { ...@@ -176,6 +181,8 @@ class Logger : public CodeEventListener {
void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag, void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
AbstractCode* code, SharedFunctionInfo* shared, AbstractCode* code, SharedFunctionInfo* shared,
Name* source, int line, int column); Name* source, int line, int column);
void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
wasm::WasmCode* code, wasm::WasmName name);
// Emits a code deoptimization event. // Emits a code deoptimization event.
void CodeDisableOptEvent(AbstractCode* code, SharedFunctionInfo* shared); void CodeDisableOptEvent(AbstractCode* code, SharedFunctionInfo* shared);
void CodeMovingGCEvent(); void CodeMovingGCEvent();
...@@ -237,6 +244,7 @@ class Logger : public CodeEventListener { ...@@ -237,6 +244,7 @@ class Logger : public CodeEventListener {
void LogExistingFunction(Handle<SharedFunctionInfo> shared, void LogExistingFunction(Handle<SharedFunctionInfo> shared,
Handle<AbstractCode> code); Handle<AbstractCode> code);
void LogCompiledModule(Handle<WasmCompiledModule> module);
// Logs all compiled functions found in the heap. // Logs all compiled functions found in the heap.
void LogCompiledFunctions(); void LogCompiledFunctions();
// Logs all accessor callbacks found in the heap. // Logs all accessor callbacks found in the heap.
...@@ -385,6 +393,9 @@ class CodeEventLogger : public CodeEventListener { ...@@ -385,6 +393,9 @@ class CodeEventLogger : public CodeEventListener {
void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code, void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code,
SharedFunctionInfo* shared, Name* source, int line, SharedFunctionInfo* shared, Name* source, int line,
int column) override; int column) override;
void CodeCreateEvent(LogEventsAndTags tag, wasm::WasmCode* code,
wasm::WasmName name) override;
void RegExpCodeCreateEvent(AbstractCode* code, String* source) override; void RegExpCodeCreateEvent(AbstractCode* code, String* source) override;
void InstructionStreamCreateEvent(LogEventsAndTags tag, void InstructionStreamCreateEvent(LogEventsAndTags tag,
const InstructionStream* stream, const InstructionStream* stream,
...@@ -404,6 +415,8 @@ class CodeEventLogger : public CodeEventListener { ...@@ -404,6 +415,8 @@ class CodeEventLogger : public CodeEventListener {
const char* name, int length) = 0; const char* name, int length) = 0;
virtual void LogRecordedBuffer(const InstructionStream* stream, virtual void LogRecordedBuffer(const InstructionStream* stream,
const char* name, int length) = 0; const char* name, int length) = 0;
virtual void LogRecordedBuffer(wasm::WasmCode* code, const char* name,
int length) = 0;
NameBuffer* name_buffer_; NameBuffer* name_buffer_;
}; };
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "src/instruction-stream.h" #include "src/instruction-stream.h"
#include "src/objects-inl.h" #include "src/objects-inl.h"
#include "src/source-position-table.h" #include "src/source-position-table.h"
#include "src/wasm/wasm-code-manager.h"
#if V8_OS_LINUX #if V8_OS_LINUX
#include <fcntl.h> #include <fcntl.h>
...@@ -214,7 +215,11 @@ void PerfJitLogger::LogRecordedBuffer(AbstractCode* abstract_code, ...@@ -214,7 +215,11 @@ void PerfJitLogger::LogRecordedBuffer(AbstractCode* abstract_code,
// Debug info has to be emitted first. // Debug info has to be emitted first.
if (FLAG_perf_prof && shared != nullptr) { if (FLAG_perf_prof && shared != nullptr) {
LogWriteDebugInfo(code, shared); // TODO(herhut): This currently breaks for js2wasm/wasm2js functions.
if (code->kind() != Code::JS_TO_WASM_FUNCTION &&
code->kind() != Code::WASM_TO_JS_FUNCTION) {
LogWriteDebugInfo(code, shared);
}
} }
const char* code_name = name; const char* code_name = name;
...@@ -227,11 +232,27 @@ void PerfJitLogger::LogRecordedBuffer(AbstractCode* abstract_code, ...@@ -227,11 +232,27 @@ void PerfJitLogger::LogRecordedBuffer(AbstractCode* abstract_code,
// Unwinding info comes right after debug info. // Unwinding info comes right after debug info.
if (FLAG_perf_prof_unwinding_info) LogWriteUnwindingInfo(code); if (FLAG_perf_prof_unwinding_info) LogWriteUnwindingInfo(code);
WriteJitCodeLoadEntry(code_pointer, code_size, code_name, length);
}
void PerfJitLogger::LogRecordedBuffer(wasm::WasmCode* code, const char* name,
int length) {
base::LockGuard<base::RecursiveMutex> guard_file(file_mutex_.Pointer());
if (perf_output_handle_ == nullptr) return;
WriteJitCodeLoadEntry(code->instructions().start(),
code->instructions().length(), name, length);
}
void PerfJitLogger::WriteJitCodeLoadEntry(const uint8_t* code_pointer,
uint32_t code_size, const char* name,
int name_length) {
static const char string_terminator[] = "\0"; static const char string_terminator[] = "\0";
PerfJitCodeLoad code_load; PerfJitCodeLoad code_load;
code_load.event_ = PerfJitCodeLoad::kLoad; code_load.event_ = PerfJitCodeLoad::kLoad;
code_load.size_ = sizeof(code_load) + length + 1 + code_size; code_load.size_ = sizeof(code_load) + name_length + 1 + code_size;
code_load.time_stamp_ = GetTimestamp(); code_load.time_stamp_ = GetTimestamp();
code_load.process_id_ = code_load.process_id_ =
static_cast<uint32_t>(base::OS::GetCurrentProcessId()); static_cast<uint32_t>(base::OS::GetCurrentProcessId());
...@@ -244,7 +265,7 @@ void PerfJitLogger::LogRecordedBuffer(AbstractCode* abstract_code, ...@@ -244,7 +265,7 @@ void PerfJitLogger::LogRecordedBuffer(AbstractCode* abstract_code,
code_index_++; code_index_++;
LogWriteBytes(reinterpret_cast<const char*>(&code_load), sizeof(code_load)); LogWriteBytes(reinterpret_cast<const char*>(&code_load), sizeof(code_load));
LogWriteBytes(code_name, length); LogWriteBytes(name, name_length);
LogWriteBytes(string_terminator, 1); LogWriteBytes(string_terminator, 1);
LogWriteBytes(reinterpret_cast<const char*>(code_pointer), code_size); LogWriteBytes(reinterpret_cast<const char*>(code_pointer), code_size);
} }
......
...@@ -56,6 +56,8 @@ class PerfJitLogger : public CodeEventLogger { ...@@ -56,6 +56,8 @@ class PerfJitLogger : public CodeEventLogger {
const char* name, int length) override; const char* name, int length) override;
void LogRecordedBuffer(const InstructionStream* stream, const char* name, void LogRecordedBuffer(const InstructionStream* stream, const char* name,
int length) override; int length) override;
void LogRecordedBuffer(wasm::WasmCode* code, const char* name,
int length) override;
// Extension added to V8 log file name to get the low-level log name. // Extension added to V8 log file name to get the low-level log name.
static const char kFilenameFormatString[]; static const char kFilenameFormatString[];
...@@ -65,6 +67,9 @@ class PerfJitLogger : public CodeEventLogger { ...@@ -65,6 +67,9 @@ class PerfJitLogger : public CodeEventLogger {
// minimize the associated overhead. // minimize the associated overhead.
static const int kLogBufferSize = 2 * MB; static const int kLogBufferSize = 2 * MB;
void WriteJitCodeLoadEntry(const uint8_t* code_pointer, uint32_t code_size,
const char* name, int name_length);
void LogWriteBytes(const char* bytes, int size); void LogWriteBytes(const char* bytes, int size);
void LogWriteHeader(); void LogWriteHeader();
void LogWriteDebugInfo(Code* code, SharedFunctionInfo* shared); void LogWriteDebugInfo(Code* code, SharedFunctionInfo* shared);
...@@ -133,6 +138,11 @@ class PerfJitLogger : public CodeEventLogger { ...@@ -133,6 +138,11 @@ class PerfJitLogger : public CodeEventLogger {
int length) override { int length) override {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
void LogRecordedBuffer(wasm::WasmCode* code, const char* name,
int length) override {
UNIMPLEMENTED();
}
}; };
#endif // V8_OS_LINUX #endif // V8_OS_LINUX
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "src/profiler/cpu-profiler.h" #include "src/profiler/cpu-profiler.h"
#include "src/profiler/profile-generator-inl.h" #include "src/profiler/profile-generator-inl.h"
#include "src/source-position-table.h" #include "src/source-position-table.h"
#include "src/wasm/wasm-code-manager.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -111,6 +112,21 @@ void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag, ...@@ -111,6 +112,21 @@ void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
DispatchCodeEvent(evt_rec); DispatchCodeEvent(evt_rec);
} }
void ProfilerListener::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
wasm::WasmCode* code,
wasm::WasmName name) {
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
rec->start = code->instructions().start();
rec->entry = NewCodeEntry(
tag, GetFunctionName(name.start()), CodeEntry::kEmptyNamePrefix,
CodeEntry::kEmptyResourceName, CpuProfileNode::kNoLineNumberInfo,
CpuProfileNode::kNoColumnNumberInfo, nullptr,
code->instructions().start());
rec->size = code->instructions().length();
DispatchCodeEvent(evt_rec);
}
void ProfilerListener::CodeMoveEvent(AbstractCode* from, Address to) { void ProfilerListener::CodeMoveEvent(AbstractCode* from, Address to) {
CodeEventsContainer evt_rec(CodeEventRecord::CODE_MOVE); CodeEventsContainer evt_rec(CodeEventRecord::CODE_MOVE);
CodeMoveEventRecord* rec = &evt_rec.CodeMoveEventRecord_; CodeMoveEventRecord* rec = &evt_rec.CodeMoveEventRecord_;
......
...@@ -37,6 +37,9 @@ class ProfilerListener : public CodeEventListener { ...@@ -37,6 +37,9 @@ class ProfilerListener : public CodeEventListener {
void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag, void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
AbstractCode* code, SharedFunctionInfo* shared, AbstractCode* code, SharedFunctionInfo* shared,
Name* script_name, int line, int column) override; Name* script_name, int line, int column) override;
void CodeCreateEvent(CodeEventListener::LogEventsAndTags tag,
wasm::WasmCode* code, wasm::WasmName name) override;
void CodeMovingGCEvent() override {} void CodeMovingGCEvent() override {}
void CodeMoveEvent(AbstractCode* from, Address to) override; void CodeMoveEvent(AbstractCode* from, Address to) override;
void CodeDisableOptEvent(AbstractCode* code, void CodeDisableOptEvent(AbstractCode* code,
......
...@@ -122,6 +122,11 @@ class CodeAddressMap : public CodeEventLogger { ...@@ -122,6 +122,11 @@ class CodeAddressMap : public CodeEventLogger {
address_to_name_map_.Insert(stream->bytes(), name, length); address_to_name_map_.Insert(stream->bytes(), name, length);
} }
void LogRecordedBuffer(wasm::WasmCode* code, const char* name,
int length) override {
UNREACHABLE();
}
NameMap address_to_name_map_; NameMap address_to_name_map_;
Isolate* isolate_; Isolate* isolate_;
}; };
......
...@@ -1819,6 +1819,28 @@ bool WasmCompiledModule::SetBreakPoint( ...@@ -1819,6 +1819,28 @@ bool WasmCompiledModule::SetBreakPoint(
return true; return true;
} }
void WasmCompiledModule::LogWasmCodes(Isolate* isolate) {
wasm::NativeModule* native_module = GetNativeModule();
if (native_module == nullptr) return;
const uint32_t number_of_codes = native_module->FunctionCount();
if (has_shared()) {
Handle<WasmSharedModuleData> shared_handle(shared(), isolate);
for (uint32_t i = 0; i < number_of_codes; i++) {
wasm::WasmCode* code = native_module->GetCode(i);
if (code == nullptr) continue;
int name_length;
Handle<String> name(
WasmSharedModuleData::GetFunctionName(isolate, shared_handle, i));
auto cname = name->ToCString(AllowNullsFlag::DISALLOW_NULLS,
RobustnessFlag::ROBUST_STRING_TRAVERSAL,
&name_length);
wasm::WasmName wasm_name(cname.get(), name_length);
PROFILE(isolate, CodeCreateEvent(CodeEventListener::FUNCTION_TAG, code,
wasm_name));
}
}
}
void AttachWasmFunctionInfo(Isolate* isolate, Handle<Code> code, void AttachWasmFunctionInfo(Isolate* isolate, Handle<Code> code,
MaybeHandle<WeakCell> weak_instance, MaybeHandle<WeakCell> weak_instance,
int func_index) { int func_index) {
......
...@@ -556,6 +556,8 @@ class WasmCompiledModule : public FixedArray { ...@@ -556,6 +556,8 @@ class WasmCompiledModule : public FixedArray {
static Address GetTableValue(FixedArray* table, int index); static Address GetTableValue(FixedArray* table, int index);
inline void ReplaceCodeTableForTesting(Handle<FixedArray> testing_table); inline void ReplaceCodeTableForTesting(Handle<FixedArray> testing_table);
void LogWasmCodes(Isolate* isolate);
private: private:
void InitId(); void InitId();
......
...@@ -705,6 +705,8 @@ TEST(Issue539892) { ...@@ -705,6 +705,8 @@ TEST(Issue539892) {
const char* name, int length) override {} const char* name, int length) override {}
void LogRecordedBuffer(const i::InstructionStream* stream, const char* name, void LogRecordedBuffer(const i::InstructionStream* stream, const char* name,
int length) override {} int length) override {}
void LogRecordedBuffer(i::wasm::WasmCode* code, const char* name,
int length) override {}
} code_event_logger; } code_event_logger;
SETUP_FLAGS(); SETUP_FLAGS();
v8::Isolate::CreateParams create_params; v8::Isolate::CreateParams create_params;
......
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