diff options
author | Michaël Zasso <targos@protonmail.com> | 2018-07-05 09:38:02 +0300 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2018-07-26 09:33:56 +0300 |
commit | 71fae5e81dc96e5501ddb3e89e4a49c427d89398 (patch) | |
tree | f88ad0e153839c5f902959ea5163a75a1cf42484 /deps | |
parent | 9b5cba9104dd4203ed0eac1153a708803cbb677b (diff) |
deps: cherry-pick aa6ce3e from upstream V8
Original commit message:
[log][api] introduce public CodeEventListener API
Introduce a new public API called CodeEventListener to allow embedders
to better support external profilers and other diagnostic tools without
relying on unsupported methods like --perf-basic-prof.
Bug: v8:7694
Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng
Change-Id: I063cc965394d59401358757634c9ea84c11517e9
Co-authored-by: Daniel Beckert <daniel@sthima.com.br>
Reviewed-on: https://chromium-review.googlesource.com/1028770
Commit-Queue: Yang Guo <yangguo@chromium.org>
Reviewed-by: Hannes Payer <hpayer@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53382}
Refs: https://github.com/v8/v8/commit/aa6ce3ee617b2f324bea3a5d8e3263aee4cde6d7
PR-URL: https://github.com/nodejs/node/pull/21079
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Yang Guo <yangguo@chromium.org>
Diffstat (limited to 'deps')
-rw-r--r-- | deps/v8/include/v8-profiler.h | 70 | ||||
-rw-r--r-- | deps/v8/src/api.cc | 64 | ||||
-rw-r--r-- | deps/v8/src/code-events.h | 62 | ||||
-rw-r--r-- | deps/v8/src/compiler.cc | 5 | ||||
-rw-r--r-- | deps/v8/src/compiler/wasm-compiler.cc | 3 | ||||
-rw-r--r-- | deps/v8/src/heap/mark-compact.cc | 2 | ||||
-rw-r--r-- | deps/v8/src/isolate.cc | 2 | ||||
-rw-r--r-- | deps/v8/src/isolate.h | 1 | ||||
-rw-r--r-- | deps/v8/src/log.cc | 510 | ||||
-rw-r--r-- | deps/v8/src/log.h | 86 | ||||
-rw-r--r-- | deps/v8/src/runtime/runtime-function.cc | 3 | ||||
-rw-r--r-- | deps/v8/src/snapshot/code-serializer.cc | 3 | ||||
-rw-r--r-- | deps/v8/src/snapshot/snapshot-common.cc | 6 | ||||
-rw-r--r-- | deps/v8/src/wasm/wasm-code-manager.cc | 2 | ||||
-rw-r--r-- | deps/v8/test/cctest/test-log.cc | 75 |
15 files changed, 694 insertions, 200 deletions
diff --git a/deps/v8/include/v8-profiler.h b/deps/v8/include/v8-profiler.h index 34ad2b9cea5..76490afe3cf 100644 --- a/deps/v8/include/v8-profiler.h +++ b/deps/v8/include/v8-profiler.h @@ -992,6 +992,76 @@ struct HeapStatsUpdate { uint32_t size; // New value of size field for the interval with this index. }; +#define CODE_EVENTS_LIST(V) \ + V(Builtin) \ + V(Callback) \ + V(Eval) \ + V(Function) \ + V(InterpretedFunction) \ + V(Handler) \ + V(BytecodeHandler) \ + V(LazyCompile) \ + V(RegExp) \ + V(Script) \ + V(Stub) + +/** + * Note that this enum may be extended in the future. Please include a default + * case if this enum is used in a switch statement. + */ +enum CodeEventType { + kUnknownType = 0 +#define V(Name) , k##Name##Type + CODE_EVENTS_LIST(V) +#undef V +}; + +/** + * Representation of a code creation event + */ +class V8_EXPORT CodeEvent { + public: + uintptr_t GetCodeStartAddress(); + size_t GetCodeSize(); + Local<String> GetFunctionName(); + Local<String> GetScriptName(); + int GetScriptLine(); + int GetScriptColumn(); + /** + * NOTE (mmarchini): We can't allocate objects in the heap when we collect + * existing code, and both the code type and the comment are not stored in the + * heap, so we return those as const char*. + */ + CodeEventType GetCodeType(); + const char* GetComment(); + + static const char* GetCodeEventTypeName(CodeEventType code_event_type); +}; + +/** + * Interface to listen to code creation events. + */ +class V8_EXPORT CodeEventHandler { + public: + /** + * Creates a new listener for the |isolate|. The isolate must be initialized. + * The listener object must be disposed after use by calling |Dispose| method. + * Multiple listeners can be created for the same isolate. + */ + explicit CodeEventHandler(Isolate* isolate); + virtual ~CodeEventHandler(); + + virtual void Handle(CodeEvent* code_event) = 0; + + void Enable(); + void Disable(); + + private: + CodeEventHandler(); + CodeEventHandler(const CodeEventHandler&); + CodeEventHandler& operator=(const CodeEventHandler&); + void* internal_listener_; +}; } // namespace v8 diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc index 89bcb2e4fa5..f51576ed2a6 100644 --- a/deps/v8/src/api.cc +++ b/deps/v8/src/api.cc @@ -10104,6 +10104,70 @@ void CpuProfiler::SetIdle(bool is_idle) { isolate->SetIdle(is_idle); } +uintptr_t CodeEvent::GetCodeStartAddress() { + return reinterpret_cast<i::CodeEvent*>(this)->code_start_address; +} + +size_t CodeEvent::GetCodeSize() { + return reinterpret_cast<i::CodeEvent*>(this)->code_size; +} + +Local<String> CodeEvent::GetFunctionName() { + return ToApiHandle<String>( + reinterpret_cast<i::CodeEvent*>(this)->function_name); +} + +Local<String> CodeEvent::GetScriptName() { + return ToApiHandle<String>( + reinterpret_cast<i::CodeEvent*>(this)->script_name); +} + +int CodeEvent::GetScriptLine() { + return reinterpret_cast<i::CodeEvent*>(this)->script_line; +} + +int CodeEvent::GetScriptColumn() { + return reinterpret_cast<i::CodeEvent*>(this)->script_column; +} + +CodeEventType CodeEvent::GetCodeType() { + return reinterpret_cast<i::CodeEvent*>(this)->code_type; +} + +const char* CodeEvent::GetComment() { + return reinterpret_cast<i::CodeEvent*>(this)->comment; +} + +const char* CodeEvent::GetCodeEventTypeName(CodeEventType code_event_type) { + switch (code_event_type) { + case kUnknownType: + return "Unknown"; +#define V(Name) \ + case k##Name##Type: \ + return #Name; + CODE_EVENTS_LIST(V) +#undef V + } +} + +CodeEventHandler::CodeEventHandler(Isolate* isolate) { + internal_listener_ = + new i::ExternalCodeEventListener(reinterpret_cast<i::Isolate*>(isolate)); +} + +CodeEventHandler::~CodeEventHandler() { + delete reinterpret_cast<i::ExternalCodeEventListener*>(internal_listener_); +} + +void CodeEventHandler::Enable() { + reinterpret_cast<i::ExternalCodeEventListener*>(internal_listener_) + ->StartListening(this); +} + +void CodeEventHandler::Disable() { + reinterpret_cast<i::ExternalCodeEventListener*>(internal_listener_) + ->StopListening(); +} static i::HeapGraphEdge* ToInternal(const HeapGraphEdge* edge) { return const_cast<i::HeapGraphEdge*>( diff --git a/deps/v8/src/code-events.h b/deps/v8/src/code-events.h index 439cb54dca6..caed5160f47 100644 --- a/deps/v8/src/code-events.h +++ b/deps/v8/src/code-events.h @@ -24,32 +24,38 @@ class WasmCode; using WasmName = Vector<const char>; } // namespace wasm -#define LOG_EVENTS_AND_TAGS_LIST(V) \ - V(CODE_CREATION_EVENT, "code-creation") \ - V(CODE_DISABLE_OPT_EVENT, "code-disable-optimization") \ - V(CODE_MOVE_EVENT, "code-move") \ - V(CODE_DELETE_EVENT, "code-delete") \ - V(CODE_MOVING_GC, "code-moving-gc") \ - V(SHARED_FUNC_MOVE_EVENT, "sfi-move") \ - V(SNAPSHOT_CODE_NAME_EVENT, "snapshot-code-name") \ - V(TICK_EVENT, "tick") \ - V(BUILTIN_TAG, "Builtin") \ - V(CALLBACK_TAG, "Callback") \ - V(EVAL_TAG, "Eval") \ - V(FUNCTION_TAG, "Function") \ - V(INTERPRETED_FUNCTION_TAG, "InterpretedFunction") \ - V(HANDLER_TAG, "Handler") \ - V(BYTECODE_HANDLER_TAG, "BytecodeHandler") \ - V(LAZY_COMPILE_TAG, "LazyCompile") \ - V(REG_EXP_TAG, "RegExp") \ - V(SCRIPT_TAG, "Script") \ - V(STUB_TAG, "Stub") \ - V(NATIVE_FUNCTION_TAG, "Function") \ - V(NATIVE_LAZY_COMPILE_TAG, "LazyCompile") \ - V(NATIVE_SCRIPT_TAG, "Script") +#define LOG_EVENTS_LIST(V) \ + V(CODE_CREATION_EVENT, code-creation) \ + V(CODE_DISABLE_OPT_EVENT, code-disable-optimization) \ + V(CODE_MOVE_EVENT, code-move) \ + V(CODE_DELETE_EVENT, code-delete) \ + V(CODE_MOVING_GC, code-moving-gc) \ + V(SHARED_FUNC_MOVE_EVENT, sfi-move) \ + V(SNAPSHOT_CODE_NAME_EVENT, snapshot-code-name) \ + V(TICK_EVENT, tick) + +#define TAGS_LIST(V) \ + V(BUILTIN_TAG, Builtin) \ + V(CALLBACK_TAG, Callback) \ + V(EVAL_TAG, Eval) \ + V(FUNCTION_TAG, Function) \ + V(INTERPRETED_FUNCTION_TAG, InterpretedFunction) \ + V(HANDLER_TAG, Handler) \ + V(BYTECODE_HANDLER_TAG, BytecodeHandler) \ + V(LAZY_COMPILE_TAG, LazyCompile) \ + V(REG_EXP_TAG, RegExp) \ + V(SCRIPT_TAG, Script) \ + V(STUB_TAG, Stub) \ + V(NATIVE_FUNCTION_TAG, Function) \ + V(NATIVE_LAZY_COMPILE_TAG, LazyCompile) \ + V(NATIVE_SCRIPT_TAG, Script) // Note that 'NATIVE_' cases for functions and scripts are mapped onto // original tags when writing to the log. +#define LOG_EVENTS_AND_TAGS_LIST(V) \ + LOG_EVENTS_LIST(V) \ + TAGS_LIST(V) + #define PROFILE(the_isolate, Call) (the_isolate)->code_event_dispatcher()->Call; class CodeEventListener { @@ -85,6 +91,8 @@ class CodeEventListener { enum DeoptKind { kSoft, kLazy, kEager }; virtual void CodeDeoptEvent(Code* code, DeoptKind kind, Address pc, int fp_to_sp_delta) = 0; + + virtual bool is_listening_to_code_events() { return false; } }; class CodeEventDispatcher { @@ -101,6 +109,14 @@ class CodeEventDispatcher { base::LockGuard<base::Mutex> guard(&mutex_); listeners_.erase(listener); } + bool IsListeningToCodeEvents() { + for (auto it : listeners_) { + if (it->is_listening_to_code_events()) { + return true; + } + } + return false; + } #define CODE_EVENT_DISPATCH(code) \ base::LockGuard<base::Mutex> guard(&mutex_); \ diff --git a/deps/v8/src/compiler.cc b/deps/v8/src/compiler.cc index ae6bc9c4fa6..a01750b23ac 100644 --- a/deps/v8/src/compiler.cc +++ b/deps/v8/src/compiler.cc @@ -84,8 +84,9 @@ void LogFunctionCompilation(CodeEventListener::LogEventsAndTags tag, // Log the code generation. If source information is available include // script name and line number. Check explicitly whether logging is // enabled as finding the line number is not free. - if (!isolate->logger()->is_logging_code_events() && - !isolate->is_profiling() && !FLAG_log_function_events) { + if (!isolate->logger()->is_listening_to_code_events() && + !isolate->is_profiling() && !FLAG_log_function_events && + !isolate->code_event_dispatcher()->IsListeningToCodeEvents()) { return; } diff --git a/deps/v8/src/compiler/wasm-compiler.cc b/deps/v8/src/compiler/wasm-compiler.cc index daceffd3313..61c3a350f79 100644 --- a/deps/v8/src/compiler/wasm-compiler.cc +++ b/deps/v8/src/compiler/wasm-compiler.cc @@ -3952,7 +3952,8 @@ Node* WasmGraphBuilder::AtomicOp(wasm::WasmOpcode opcode, Node* const* inputs, namespace { bool must_record_function_compilation(Isolate* isolate) { - return isolate->logger()->is_logging_code_events() || isolate->is_profiling(); + return isolate->logger()->is_listening_to_code_events() || + isolate->is_profiling(); } PRINTF_FORMAT(4, 5) diff --git a/deps/v8/src/heap/mark-compact.cc b/deps/v8/src/heap/mark-compact.cc index 50be29c29a5..66575f82500 100644 --- a/deps/v8/src/heap/mark-compact.cc +++ b/deps/v8/src/heap/mark-compact.cc @@ -2414,7 +2414,7 @@ void MarkCompactCollectorBase::CreateAndExecuteEvacuationTasks( const bool profiling = heap()->isolate()->is_profiling() || - heap()->isolate()->logger()->is_logging_code_events() || + heap()->isolate()->logger()->is_listening_to_code_events() || heap()->isolate()->heap_profiler()->is_tracking_object_moves() || heap()->has_heap_object_allocation_tracker(); ProfilingMigrationObserver profiling_observer(heap()); diff --git a/deps/v8/src/isolate.cc b/deps/v8/src/isolate.cc index abd74ee40dd..dd66479f737 100644 --- a/deps/v8/src/isolate.cc +++ b/deps/v8/src/isolate.cc @@ -2892,7 +2892,7 @@ void CreateOffHeapTrampolines(Isolate* isolate) { // thus collected by the GC. builtins->set_builtin(i, *trampoline); - if (isolate->logger()->is_logging_code_events() || + if (isolate->logger()->is_listening_to_code_events() || isolate->is_profiling()) { isolate->logger()->LogCodeObject(*trampoline); } diff --git a/deps/v8/src/isolate.h b/deps/v8/src/isolate.h index 929403e1340..69ec1f18531 100644 --- a/deps/v8/src/isolate.h +++ b/deps/v8/src/isolate.h @@ -57,6 +57,7 @@ class BuiltinsConstantsTableBuilder; class CallInterfaceDescriptorData; class CancelableTaskManager; class CodeEventDispatcher; +class ExternalCodeEventListener; class CodeGenerator; class CodeRange; class CodeStubDescriptor; diff --git a/deps/v8/src/log.cc b/deps/v8/src/log.cc index f5e1fe6baf3..20e5f2c9643 100644 --- a/deps/v8/src/log.cc +++ b/deps/v8/src/log.cc @@ -40,11 +40,33 @@ namespace v8 { namespace internal { -#define DECLARE_EVENT(ignore1, name) name, +#define DECLARE_EVENT(ignore1, name) #name, static const char* kLogEventsNames[CodeEventListener::NUMBER_OF_LOG_EVENTS] = { LOG_EVENTS_AND_TAGS_LIST(DECLARE_EVENT)}; #undef DECLARE_EVENT +static v8::CodeEventType GetCodeEventTypeForTag( + CodeEventListener::LogEventsAndTags tag) { + switch (tag) { + case CodeEventListener::NUMBER_OF_LOG_EVENTS: +#define V(Event, _) case CodeEventListener::Event: + LOG_EVENTS_LIST(V) +#undef V + return v8::CodeEventType::kUnknownType; +#define V(From, To) \ + case CodeEventListener::From: \ + return v8::CodeEventType::k##To##Type; + TAGS_LIST(V) +#undef V + } +} +#define CALL_CODE_EVENT_HANDLER(Call) \ + if (listener_) { \ + listener_->Call; \ + } else { \ + PROFILE(isolate_, Call); \ + } + static const char* ComputeMarker(SharedFunctionInfo* shared, AbstractCode* code) { switch (code->kind()) { @@ -320,9 +342,147 @@ void PerfBasicLogger::LogRecordedBuffer(const wasm::WasmCode* code, code->instructions().length(), name, length); } -// Low-level logging support. -#define LL_LOG(Call) if (ll_logger_) ll_logger_->Call; +// External CodeEventListener +ExternalCodeEventListener::ExternalCodeEventListener(Isolate* isolate) + : is_listening_(false), isolate_(isolate), code_event_handler_(nullptr) {} + +ExternalCodeEventListener::~ExternalCodeEventListener() { + if (is_listening_) { + StopListening(); + } +} + +void ExternalCodeEventListener::LogExistingCode() { + HandleScope scope(isolate_); + ExistingCodeLogger logger(isolate_, this); + logger.LogCodeObjects(); + logger.LogBytecodeHandlers(); + logger.LogCompiledFunctions(); +} + +void ExternalCodeEventListener::StartListening( + CodeEventHandler* code_event_handler) { + if (is_listening_ || code_event_handler == nullptr) { + return; + } + code_event_handler_ = code_event_handler; + is_listening_ = isolate_->code_event_dispatcher()->AddListener(this); + if (is_listening_) { + LogExistingCode(); + } +} +void ExternalCodeEventListener::StopListening() { + if (!is_listening_) { + return; + } + + isolate_->code_event_dispatcher()->RemoveListener(this); + is_listening_ = false; +} + +void ExternalCodeEventListener::CodeCreateEvent( + CodeEventListener::LogEventsAndTags tag, AbstractCode* code, + const char* comment) { + CodeEvent code_event; + code_event.code_start_address = + static_cast<uintptr_t>(code->InstructionStart()); + code_event.code_size = static_cast<size_t>(code->InstructionSize()); + code_event.function_name = isolate_->factory()->empty_string(); + code_event.script_name = isolate_->factory()->empty_string(); + code_event.script_line = 0; + code_event.script_column = 0; + code_event.code_type = GetCodeEventTypeForTag(tag); + code_event.comment = comment; + + code_event_handler_->Handle(reinterpret_cast<v8::CodeEvent*>(&code_event)); +} + +void ExternalCodeEventListener::CodeCreateEvent( + CodeEventListener::LogEventsAndTags tag, AbstractCode* code, Name* name) { + Handle<String> name_string = + Name::ToFunctionName(Handle<Name>(name, isolate_)).ToHandleChecked(); + + CodeEvent code_event; + code_event.code_start_address = + static_cast<uintptr_t>(code->InstructionStart()); + code_event.code_size = static_cast<size_t>(code->InstructionSize()); + code_event.function_name = name_string; + code_event.script_name = isolate_->factory()->empty_string(); + code_event.script_line = 0; + code_event.script_column = 0; + code_event.code_type = GetCodeEventTypeForTag(tag); + code_event.comment = ""; + + code_event_handler_->Handle(reinterpret_cast<v8::CodeEvent*>(&code_event)); +} + +void ExternalCodeEventListener::CodeCreateEvent( + CodeEventListener::LogEventsAndTags tag, AbstractCode* code, + SharedFunctionInfo* shared, Name* name) { + Handle<String> name_string = + Name::ToFunctionName(Handle<Name>(name, isolate_)).ToHandleChecked(); + + CodeEvent code_event; + code_event.code_start_address = + static_cast<uintptr_t>(code->InstructionStart()); + code_event.code_size = static_cast<size_t>(code->InstructionSize()); + code_event.function_name = name_string; + code_event.script_name = isolate_->factory()->empty_string(); + code_event.script_line = 0; + code_event.script_column = 0; + code_event.code_type = GetCodeEventTypeForTag(tag); + code_event.comment = ""; + + code_event_handler_->Handle(reinterpret_cast<v8::CodeEvent*>(&code_event)); +} + +void ExternalCodeEventListener::CodeCreateEvent( + CodeEventListener::LogEventsAndTags tag, AbstractCode* code, + SharedFunctionInfo* shared, Name* source, int line, int column) { + Handle<String> name_string = + Name::ToFunctionName(Handle<Name>(shared->Name(), isolate_)) + .ToHandleChecked(); + Handle<String> source_string = + Name::ToFunctionName(Handle<Name>(source, isolate_)).ToHandleChecked(); + + CodeEvent code_event; + code_event.code_start_address = + static_cast<uintptr_t>(code->InstructionStart()); + code_event.code_size = static_cast<size_t>(code->InstructionSize()); + code_event.function_name = name_string; + code_event.script_name = source_string; + code_event.script_line = line; + code_event.script_column = column; + code_event.code_type = GetCodeEventTypeForTag(tag); + code_event.comment = ""; + + code_event_handler_->Handle(reinterpret_cast<v8::CodeEvent*>(&code_event)); +} + +void ExternalCodeEventListener::CodeCreateEvent(LogEventsAndTags tag, + const wasm::WasmCode* code, + wasm::WasmName name) { + // TODO(mmarchini): handle later +} + +void ExternalCodeEventListener::RegExpCodeCreateEvent(AbstractCode* code, + String* source) { + CodeEvent code_event; + code_event.code_start_address = + static_cast<uintptr_t>(code->InstructionStart()); + code_event.code_size = static_cast<size_t>(code->InstructionSize()); + code_event.function_name = Handle<String>(source, isolate_); + code_event.script_name = isolate_->factory()->empty_string(); + code_event.script_line = 0; + code_event.script_column = 0; + code_event.code_type = GetCodeEventTypeForTag(CodeEventListener::REG_EXP_TAG); + code_event.comment = ""; + + code_event_handler_->Handle(reinterpret_cast<v8::CodeEvent*>(&code_event)); +} + +// Low-level logging support. class LowLevelLogger : public CodeEventLogger { public: explicit LowLevelLogger(const char* file_name); @@ -809,7 +969,8 @@ Logger::Logger(Isolate* isolate) perf_jit_logger_(nullptr), ll_logger_(nullptr), jit_logger_(nullptr), - is_initialized_(false) {} + is_initialized_(false), + existing_code_logger_(isolate) {} Logger::~Logger() { delete log_; @@ -1078,7 +1239,7 @@ void AppendCodeCreateHeader(Log::MessageBuilder& msg, void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag, AbstractCode* code, const char* comment) { - if (!is_logging_code_events()) return; + if (!is_listening_to_code_events()) return; if (!FLAG_log_code || !log_->IsEnabled()) return; Log::MessageBuilder msg(log_); AppendCodeCreateHeader(msg, tag, code, &timer_); @@ -1088,7 +1249,7 @@ void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag, void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag, AbstractCode* code, Name* name) { - if (!is_logging_code_events()) return; + if (!is_listening_to_code_events()) return; if (!FLAG_log_code || !log_->IsEnabled()) return; Log::MessageBuilder msg(log_); AppendCodeCreateHeader(msg, tag, code, &timer_); @@ -1099,7 +1260,7 @@ void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag, void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag, AbstractCode* code, SharedFunctionInfo* shared, Name* name) { - if (!is_logging_code_events()) return; + if (!is_listening_to_code_events()) return; if (!FLAG_log_code || !log_->IsEnabled()) return; if (code == AbstractCode::cast( isolate_->builtins()->builtin(Builtins::kCompileLazy))) { @@ -1115,7 +1276,7 @@ void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag, void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag, const wasm::WasmCode* code, wasm::WasmName name) { - if (!is_logging_code_events()) return; + if (!is_listening_to_code_events()) return; if (!FLAG_log_code || !log_->IsEnabled()) return; Log::MessageBuilder msg(log_); AppendCodeCreateHeader(msg, tag, AbstractCode::Kind::WASM_FUNCTION, @@ -1143,7 +1304,7 @@ void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag, void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag, AbstractCode* code, SharedFunctionInfo* shared, Name* source, int line, int column) { - if (!is_logging_code_events()) return; + if (!is_listening_to_code_events()) return; if (!FLAG_log_code || !log_->IsEnabled()) return; Log::MessageBuilder msg(log_); @@ -1260,7 +1421,7 @@ void Logger::CodeCreateEvent(CodeEventListener::LogEventsAndTags tag, void Logger::CodeDisableOptEvent(AbstractCode* code, SharedFunctionInfo* shared) { - if (!is_logging_code_events()) return; + if (!is_listening_to_code_events()) return; if (!FLAG_log_code || !log_->IsEnabled()) return; Log::MessageBuilder msg(log_); msg << kLogEventsNames[CodeEventListener::CODE_DISABLE_OPT_EVENT] << kNext @@ -1271,13 +1432,13 @@ void Logger::CodeDisableOptEvent(AbstractCode* code, void Logger::CodeMovingGCEvent() { - if (!is_logging_code_events()) return; + if (!is_listening_to_code_events()) return; if (!log_->IsEnabled() || !FLAG_ll_prof) return; base::OS::SignalCodeMovingGC(); } void Logger::RegExpCodeCreateEvent(AbstractCode* code, String* source) { - if (!is_logging_code_events()) return; + if (!is_listening_to_code_events()) return; if (!FLAG_log_code || !log_->IsEnabled()) return; Log::MessageBuilder msg(log_); AppendCodeCreateHeader(msg, CodeEventListener::REG_EXP_TAG, code, &timer_); @@ -1286,7 +1447,7 @@ void Logger::RegExpCodeCreateEvent(AbstractCode* code, String* source) { } void Logger::CodeMoveEvent(AbstractCode* from, Address to) { - if (!is_logging_code_events()) return; + if (!is_listening_to_code_events()) return; MoveEventInternal(CodeEventListener::CODE_MOVE_EVENT, from->address(), to); } @@ -1335,7 +1496,7 @@ void Logger::CodeNameEvent(Address addr, int pos, const char* code_name) { void Logger::SharedFunctionInfoMoveEvent(Address from, Address to) { - if (!is_logging_code_events()) return; + if (!is_listening_to_code_events()) return; MoveEventInternal(CodeEventListener::SHARED_FUNC_MOVE_EVENT, from, to); } @@ -1625,170 +1786,28 @@ static int EnumerateWasmModules(Heap* heap, } void Logger::LogCodeObject(Object* object) { - AbstractCode* code_object = AbstractCode::cast(object); - CodeEventListener::LogEventsAndTags tag = CodeEventListener::STUB_TAG; - const char* description = "Unknown code from the snapshot"; - switch (code_object->kind()) { - case AbstractCode::INTERPRETED_FUNCTION: - case AbstractCode::OPTIMIZED_FUNCTION: - return; // We log this later using LogCompiledFunctions. - case AbstractCode::BYTECODE_HANDLER: - return; // We log it later by walking the dispatch table. - case AbstractCode::STUB: - description = - CodeStub::MajorName(CodeStub::GetMajorKey(code_object->GetCode())); - if (description == nullptr) description = "A stub from the snapshot"; - tag = CodeEventListener::STUB_TAG; - break; - case AbstractCode::REGEXP: - description = "Regular expression code"; - tag = CodeEventListener::REG_EXP_TAG; - break; - case AbstractCode::BUILTIN: - description = - isolate_->builtins()->name(code_object->GetCode()->builtin_index()); - tag = CodeEventListener::BUILTIN_TAG; - break; - case AbstractCode::WASM_FUNCTION: - description = "A Wasm function"; - tag = CodeEventListener::FUNCTION_TAG; - break; - case AbstractCode::JS_TO_WASM_FUNCTION: - description = "A JavaScript to Wasm adapter"; - tag = CodeEventListener::STUB_TAG; - break; - case AbstractCode::WASM_TO_JS_FUNCTION: - description = "A Wasm to JavaScript adapter"; - tag = CodeEventListener::STUB_TAG; - break; - case AbstractCode::WASM_INTERPRETER_ENTRY: - description = "A Wasm to Interpreter adapter"; - tag = CodeEventListener::STUB_TAG; - break; - case AbstractCode::C_WASM_ENTRY: - description = "A C to Wasm entry stub"; - tag = CodeEventListener::STUB_TAG; - break; - case AbstractCode::NUMBER_OF_KINDS: - UNIMPLEMENTED(); - } - PROFILE(isolate_, CodeCreateEvent(tag, code_object, description)); + existing_code_logger_.LogCodeObject(object); } -void Logger::LogCodeObjects() { - Heap* heap = isolate_->heap(); - HeapIterator iterator(heap); - DisallowHeapAllocation no_gc; - for (HeapObject* obj = iterator.next(); obj != nullptr; - obj = iterator.next()) { - if (obj->IsCode()) LogCodeObject(obj); - if (obj->IsBytecodeArray()) LogCodeObject(obj); - } -} +void Logger::LogCodeObjects() { existing_code_logger_.LogCodeObjects(); } void Logger::LogBytecodeHandler(interpreter::Bytecode bytecode, interpreter::OperandScale operand_scale, Code* code) { - std::string bytecode_name = - interpreter::Bytecodes::ToString(bytecode, operand_scale); - PROFILE(isolate_, - CodeCreateEvent(CodeEventListener::BYTECODE_HANDLER_TAG, - AbstractCode::cast(code), bytecode_name.c_str())); + existing_code_logger_.LogBytecodeHandler(bytecode, operand_scale, code); } void Logger::LogBytecodeHandlers() { - const interpreter::OperandScale kOperandScales[] = { -#define VALUE(Name, _) interpreter::OperandScale::k##Name, - OPERAND_SCALE_LIST(VALUE) -#undef VALUE - }; - - const int last_index = static_cast<int>(interpreter::Bytecode::kLast); - interpreter::Interpreter* interpreter = isolate_->interpreter(); - for (auto operand_scale : kOperandScales) { - for (int index = 0; index <= last_index; ++index) { - interpreter::Bytecode bytecode = interpreter::Bytecodes::FromByte(index); - if (interpreter::Bytecodes::BytecodeHasHandler(bytecode, operand_scale)) { - Code* code = interpreter->GetBytecodeHandler(bytecode, operand_scale); - if (isolate_->heap()->IsDeserializeLazyHandler(code)) continue; - LogBytecodeHandler(bytecode, operand_scale, code); - } - } - } + existing_code_logger_.LogBytecodeHandlers(); } void Logger::LogExistingFunction(Handle<SharedFunctionInfo> shared, Handle<AbstractCode> code) { - if (shared->script()->IsScript()) { - Handle<Script> script(Script::cast(shared->script())); - int line_num = Script::GetLineNumber(script, shared->StartPosition()) + 1; - int column_num = - Script::GetColumnNumber(script, shared->StartPosition()) + 1; - if (script->name()->IsString()) { - Handle<String> script_name(String::cast(script->name())); - if (line_num > 0) { - PROFILE(isolate_, - CodeCreateEvent( - Logger::ToNativeByScript( - CodeEventListener::LAZY_COMPILE_TAG, *script), - *code, *shared, *script_name, line_num, column_num)); - } else { - // Can't distinguish eval and script here, so always use Script. - PROFILE(isolate_, - CodeCreateEvent(Logger::ToNativeByScript( - CodeEventListener::SCRIPT_TAG, *script), - *code, *shared, *script_name)); - } - } else { - PROFILE(isolate_, - CodeCreateEvent(Logger::ToNativeByScript( - CodeEventListener::LAZY_COMPILE_TAG, *script), - *code, *shared, isolate_->heap()->empty_string(), - line_num, column_num)); - } - } else if (shared->IsApiFunction()) { - // API function. - FunctionTemplateInfo* fun_data = shared->get_api_func_data(); - Object* raw_call_data = fun_data->call_code(); - if (!raw_call_data->IsUndefined(isolate_)) { - CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data); - Object* callback_obj = call_data->callback(); - Address entry_point = v8::ToCData<Address>(callback_obj); -#if USES_FUNCTION_DESCRIPTORS - entry_point = *FUNCTION_ENTRYPOINT_ADDRESS(entry_point); -#endif - PROFILE(isolate_, CallbackEvent(shared->DebugName(), entry_point)); - } - } else { - PROFILE(isolate_, - CodeCreateEvent(CodeEventListener::LAZY_COMPILE_TAG, *code, *shared, - isolate_->heap()->empty_string())); - } + existing_code_logger_.LogExistingFunction(shared, code); } void Logger::LogCompiledFunctions() { - Heap* heap = isolate_->heap(); - HandleScope scope(isolate_); - const int compiled_funcs_count = - EnumerateCompiledFunctions(heap, nullptr, nullptr); - ScopedVector<Handle<SharedFunctionInfo>> sfis(compiled_funcs_count); - ScopedVector<Handle<AbstractCode> > code_objects(compiled_funcs_count); - EnumerateCompiledFunctions(heap, sfis.start(), code_objects.start()); - - // During iteration, there can be heap allocation due to - // GetScriptLineNumber call. - for (int i = 0; i < compiled_funcs_count; ++i) { - if (code_objects[i].is_identical_to(BUILTIN_CODE(isolate_, CompileLazy))) - continue; - 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_); - } + existing_code_logger_.LogCompiledFunctions(); } void Logger::LogAccessorCallbacks() { @@ -1992,5 +2011,172 @@ FILE* Logger::TearDown() { return log_->Close(); } +void ExistingCodeLogger::LogCodeObject(Object* object) { + AbstractCode* code_object = AbstractCode::cast(object); + CodeEventListener::LogEventsAndTags tag = CodeEventListener::STUB_TAG; + const char* description = "Unknown code from before profiling"; + switch (code_object->kind()) { + case AbstractCode::INTERPRETED_FUNCTION: + case AbstractCode::OPTIMIZED_FUNCTION: + return; // We log this later using LogCompiledFunctions. + case AbstractCode::BYTECODE_HANDLER: + return; // We log it later by walking the dispatch table. + case AbstractCode::STUB: + description = + CodeStub::MajorName(CodeStub::GetMajorKey(code_object->GetCode())); + if (description == nullptr) description = "A stub from before profiling"; + tag = CodeEventListener::STUB_TAG; + break; + case AbstractCode::REGEXP: + description = "Regular expression code"; + tag = CodeEventListener::REG_EXP_TAG; + break; + case AbstractCode::BUILTIN: + description = + isolate_->builtins()->name(code_object->GetCode()->builtin_index()); + tag = CodeEventListener::BUILTIN_TAG; + break; + case AbstractCode::WASM_FUNCTION: + description = "A Wasm function"; + tag = CodeEventListener::FUNCTION_TAG; + break; + case AbstractCode::JS_TO_WASM_FUNCTION: + description = "A JavaScript to Wasm adapter"; + tag = CodeEventListener::STUB_TAG; + break; + case AbstractCode::WASM_TO_JS_FUNCTION: + description = "A Wasm to JavaScript adapter"; + tag = CodeEventListener::STUB_TAG; + break; + case AbstractCode::WASM_INTERPRETER_ENTRY: + description = "A Wasm to Interpreter adapter"; + tag = CodeEventListener::STUB_TAG; + break; + case AbstractCode::C_WASM_ENTRY: + description = "A C to Wasm entry stub"; + tag = CodeEventListener::STUB_TAG; + break; + case AbstractCode::NUMBER_OF_KINDS: + UNIMPLEMENTED(); + } + CALL_CODE_EVENT_HANDLER(CodeCreateEvent(tag, code_object, description)) +} + +void ExistingCodeLogger::LogCodeObjects() { + Heap* heap = isolate_->heap(); + HeapIterator iterator(heap); + DisallowHeapAllocation no_gc; + for (HeapObject* obj = iterator.next(); obj != nullptr; + obj = iterator.next()) { + if (obj->IsCode()) LogCodeObject(obj); + if (obj->IsBytecodeArray()) LogCodeObject(obj); + } +} + +void ExistingCodeLogger::LogCompiledFunctions() { + Heap* heap = isolate_->heap(); + HandleScope scope(isolate_); + const int compiled_funcs_count = + EnumerateCompiledFunctions(heap, nullptr, nullptr); + ScopedVector<Handle<SharedFunctionInfo>> sfis(compiled_funcs_count); + ScopedVector<Handle<AbstractCode>> code_objects(compiled_funcs_count); + EnumerateCompiledFunctions(heap, sfis.start(), code_objects.start()); + + // During iteration, there can be heap allocation due to + // GetScriptLineNumber call. + for (int i = 0; i < compiled_funcs_count; ++i) { + if (code_objects[i].is_identical_to(BUILTIN_CODE(isolate_, CompileLazy))) + continue; + 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 ExistingCodeLogger::LogBytecodeHandler( + interpreter::Bytecode bytecode, interpreter::OperandScale operand_scale, + Code* code) { + std::string bytecode_name = + interpreter::Bytecodes::ToString(bytecode, operand_scale); + CALL_CODE_EVENT_HANDLER( + CodeCreateEvent(CodeEventListener::BYTECODE_HANDLER_TAG, + AbstractCode::cast(code), bytecode_name.c_str())) +} + +void ExistingCodeLogger::LogBytecodeHandlers() { + const interpreter::OperandScale kOperandScales[] = { +#define VALUE(Name, _) interpreter::OperandScale::k##Name, + OPERAND_SCALE_LIST(VALUE) +#undef VALUE + }; + + const int last_index = static_cast<int>(interpreter::Bytecode::kLast); + interpreter::Interpreter* interpreter = isolate_->interpreter(); + for (auto operand_scale : kOperandScales) { + for (int index = 0; index <= last_index; ++index) { + interpreter::Bytecode bytecode = interpreter::Bytecodes::FromByte(index); + if (interpreter::Bytecodes::BytecodeHasHandler(bytecode, operand_scale)) { + Code* code = interpreter->GetBytecodeHandler(bytecode, operand_scale); + if (isolate_->heap()->IsDeserializeLazyHandler(code)) continue; + LogBytecodeHandler(bytecode, operand_scale, code); + } + } + } +} + +void ExistingCodeLogger::LogExistingFunction(Handle<SharedFunctionInfo> shared, + Handle<AbstractCode> code) { + if (shared->script()->IsScript()) { + Handle<Script> script(Script::cast(shared->script())); + int line_num = Script::GetLineNumber(script, shared->StartPosition()) + 1; + int column_num = + Script::GetColumnNumber(script, shared->StartPosition()) + 1; + if (script->name()->IsString()) { + Handle<String> script_name(String::cast(script->name())); + if (line_num > 0) { + CALL_CODE_EVENT_HANDLER( + CodeCreateEvent(Logger::ToNativeByScript( + CodeEventListener::LAZY_COMPILE_TAG, *script), + *code, *shared, *script_name, line_num, column_num)) + } else { + // Can't distinguish eval and script here, so always use Script. + CALL_CODE_EVENT_HANDLER(CodeCreateEvent( + Logger::ToNativeByScript(CodeEventListener::SCRIPT_TAG, *script), + *code, *shared, *script_name)) + } + } else { + CALL_CODE_EVENT_HANDLER( + CodeCreateEvent(Logger::ToNativeByScript( + CodeEventListener::LAZY_COMPILE_TAG, *script), + *code, *shared, isolate_->heap()->empty_string(), + line_num, column_num)) + } + } else if (shared->IsApiFunction()) { + // API function. + FunctionTemplateInfo* fun_data = shared->get_api_func_data(); + Object* raw_call_data = fun_data->call_code(); + if (!raw_call_data->IsUndefined(isolate_)) { + CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data); + Object* callback_obj = call_data->callback(); + Address entry_point = v8::ToCData<Address>(callback_obj); +#if USES_FUNCTION_DESCRIPTORS + entry_point = *FUNCTION_ENTRYPOINT_ADDRESS(entry_point); +#endif + CALL_CODE_EVENT_HANDLER(CallbackEvent(shared->DebugName(), entry_point)) + } + } else { + CALL_CODE_EVENT_HANDLER(CodeCreateEvent(CodeEventListener::LAZY_COMPILE_TAG, + *code, *shared, + isolate_->heap()->empty_string())) + } +} + +#undef CALL_CODE_EVENT_HANDLER + } // namespace internal } // namespace v8 diff --git a/deps/v8/src/log.h b/deps/v8/src/log.h index 9943d8ca9be..738aef4d733 100644 --- a/deps/v8/src/log.h +++ b/deps/v8/src/log.h @@ -8,6 +8,7 @@ #include <set> #include <string> +#include "include/v8-profiler.h" #include "src/allocation.h" #include "src/base/compiler-specific.h" #include "src/base/platform/elapsed-timer.h" @@ -91,12 +92,33 @@ class WasmCode; if (logger->is_logging()) logger->Call; \ } while (false) -#define LOG_CODE_EVENT(isolate, Call) \ - do { \ - v8::internal::Logger* logger = (isolate)->logger(); \ - if (logger->is_logging_code_events()) logger->Call; \ +#define LOG_CODE_EVENT(isolate, Call) \ + do { \ + v8::internal::Logger* logger = (isolate)->logger(); \ + if (logger->is_listening_to_code_events()) logger->Call; \ } while (false) +class ExistingCodeLogger { + public: + explicit ExistingCodeLogger(Isolate* isolate, + CodeEventListener* listener = nullptr) + : isolate_(isolate), listener_(listener) {} + + void LogCodeObjects(); + void LogBytecodeHandlers(); + + void LogCompiledFunctions(); + void LogExistingFunction(Handle<SharedFunctionInfo> shared, + Handle<AbstractCode> code); + void LogCodeObject(Object* object); + void LogBytecodeHandler(interpreter::Bytecode bytecode, + interpreter::OperandScale operand_scale, Code* code); + + private: + Isolate* isolate_; + CodeEventListener* listener_; +}; + class Logger : public CodeEventListener { public: enum StartEnd { START = 0, END = 1, STAMP = 2 }; @@ -229,7 +251,7 @@ class Logger : public CodeEventListener { return is_logging_; } - bool is_logging_code_events() { + bool is_listening_to_code_events() { return is_logging() || jit_logger_ != nullptr; } @@ -327,6 +349,8 @@ class Logger : public CodeEventListener { // 'true' between SetUp() and TearDown(). bool is_initialized_; + ExistingCodeLogger existing_code_logger_; + base::ElapsedTimer timer_; friend class CpuProfiler; @@ -407,6 +431,58 @@ class CodeEventLogger : public CodeEventListener { NameBuffer* name_buffer_; }; +struct CodeEvent { + uintptr_t code_start_address; + size_t code_size; + Handle<String> function_name; + Handle<String> script_name; + int script_line; + int script_column; + CodeEventType code_type; + const char* comment; +}; + +class ExternalCodeEventListener : public CodeEventListener { + public: + explicit ExternalCodeEventListener(Isolate* isolate); + ~ExternalCodeEventListener() override; + + void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code, + const char* comment) override; + void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code, + Name* name) override; + void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code, + SharedFunctionInfo* shared, Name* name) override; + void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code, + SharedFunctionInfo* shared, Name* source, int line, + int column) override; + void CodeCreateEvent(LogEventsAndTags tag, const wasm::WasmCode* code, + wasm::WasmName name) override; + + void RegExpCodeCreateEvent(AbstractCode* code, String* source) override; + void CallbackEvent(Name* name, Address entry_point) override {} + void GetterCallbackEvent(Name* name, Address entry_point) override {} + void SetterCallbackEvent(Name* name, Address entry_point) override {} + void SharedFunctionInfoMoveEvent(Address from, Address to) override {} + void CodeMoveEvent(AbstractCode* from, Address to) override {} + void CodeDisableOptEvent(AbstractCode* code, + SharedFunctionInfo* shared) override {} + void CodeMovingGCEvent() override {} + void CodeDeoptEvent(Code* code, DeoptKind kind, Address pc, + int fp_to_sp_delta) override {} + + void StartListening(CodeEventHandler* code_event_handler); + void StopListening(); + + bool is_listening_to_code_events() override { return true; } + + private: + void LogExistingCode(); + + bool is_listening_; + Isolate* isolate_; + v8::CodeEventHandler* code_event_handler_; +}; } // namespace internal } // namespace v8 diff --git a/deps/v8/src/runtime/runtime-function.cc b/deps/v8/src/runtime/runtime-function.cc index 5dcb4115e51..9f1cbc00e99 100644 --- a/deps/v8/src/runtime/runtime-function.cc +++ b/deps/v8/src/runtime/runtime-function.cc @@ -147,7 +147,8 @@ RUNTIME_FUNCTION(Runtime_SetCode) { // the target_shared optimized code map. JSFunction::EnsureFeedbackVector(target); - if (isolate->logger()->is_logging_code_events() || isolate->is_profiling()) { + if (isolate->logger()->is_listening_to_code_events() || + isolate->is_profiling()) { isolate->logger()->LogExistingFunction( source_shared, Handle<AbstractCode>(source_shared->abstract_code())); } diff --git a/deps/v8/src/snapshot/code-serializer.cc b/deps/v8/src/snapshot/code-serializer.cc index 8dc98d836ba..0ff35abc5d3 100644 --- a/deps/v8/src/snapshot/code-serializer.cc +++ b/deps/v8/src/snapshot/code-serializer.cc @@ -287,7 +287,8 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize( PrintF("[Deserializing from %d bytes took %0.3f ms]\n", length, ms); } - if (isolate->logger()->is_logging_code_events() || isolate->is_profiling()) { + if (isolate->logger()->is_listening_to_code_events() || + isolate->is_profiling()) { String* name = isolate->heap()->empty_string(); if (result->script()->IsScript()) { Script* script = Script::cast(result->script()); diff --git a/deps/v8/src/snapshot/snapshot-common.cc b/deps/v8/src/snapshot/snapshot-common.cc index 902bda4a0f2..d2fcc3087b6 100644 --- a/deps/v8/src/snapshot/snapshot-common.cc +++ b/deps/v8/src/snapshot/snapshot-common.cc @@ -114,7 +114,8 @@ Code* Snapshot::DeserializeBuiltin(Isolate* isolate, int builtin_id) { Builtins::name(builtin_id), bytes, ms); } - if (isolate->logger()->is_logging_code_events() || isolate->is_profiling()) { + if (isolate->logger()->is_listening_to_code_events() || + isolate->is_profiling()) { isolate->logger()->LogCodeObject(code); } @@ -195,7 +196,8 @@ Code* Snapshot::DeserializeHandler(Isolate* isolate, bytes, ms); } - if (isolate->logger()->is_logging_code_events() || isolate->is_profiling()) { + if (isolate->logger()->is_listening_to_code_events() || + isolate->is_profiling()) { isolate->logger()->LogBytecodeHandler(bytecode, operand_scale, code); } diff --git a/deps/v8/src/wasm/wasm-code-manager.cc b/deps/v8/src/wasm/wasm-code-manager.cc index 6d32a354670..f997ef2a8cd 100644 --- a/deps/v8/src/wasm/wasm-code-manager.cc +++ b/deps/v8/src/wasm/wasm-code-manager.cc @@ -218,7 +218,7 @@ bool WasmCode::HasTrapHandlerIndex() const { return trap_handler_index_ >= 0; } void WasmCode::ResetTrapHandlerIndex() { trap_handler_index_ = -1; } bool WasmCode::ShouldBeLogged(Isolate* isolate) { - return isolate->logger()->is_logging_code_events() || + return isolate->logger()->is_listening_to_code_events() || isolate->is_profiling() || FLAG_print_wasm_code || FLAG_print_code; } diff --git a/deps/v8/test/cctest/test-log.cc b/deps/v8/test/cctest/test-log.cc index 27d363d5a41..97071a63f58 100644 --- a/deps/v8/test/cctest/test-log.cc +++ b/deps/v8/test/cctest/test-log.cc @@ -35,6 +35,7 @@ #endif // __linux__ #include <unordered_set> +#include <vector> #include "src/api.h" #include "src/log-utils.h" #include "src/log.h" @@ -251,6 +252,38 @@ class ScopedLoggerInitializer { DISALLOW_COPY_AND_ASSIGN(ScopedLoggerInitializer); }; +class TestCodeEventHandler : public v8::CodeEventHandler { + public: + explicit TestCodeEventHandler(v8::Isolate* isolate) + : v8::CodeEventHandler(isolate) {} + + const char* FindLine(const char* prefix, const char* suffix = nullptr, + const char* start = nullptr) { + if (!log_.length()) return NULL; + const char* c_log = log_.c_str(); + if (start == nullptr) start = c_log; + const char* end = c_log + log_.length(); + return FindLogLine(start, end, prefix, suffix); + } + + void Handle(v8::CodeEvent* code_event) override { + const char* code_type = + v8::CodeEvent::GetCodeEventTypeName(code_event->GetCodeType()); + char function_name[1000]; + strncpy(function_name, code_type, 1000); + function_name[strlen(code_type)] = ' '; + code_event->GetFunctionName()->WriteUtf8( + function_name + strlen(code_type) + 1, 1000); + function_name[strlen(function_name) + 1] = '\0'; + function_name[strlen(function_name)] = '\n'; + + log_ += std::string(function_name); + } + + private: + std::string log_; +}; + } // namespace TEST(FindLogLine) { @@ -800,6 +833,48 @@ TEST(LogInterpretedFramesNativeStack) { isolate->Dispose(); } +TEST(ExternalCodeEventListener) { + i::FLAG_log = false; + i::FLAG_prof = false; + + v8::Isolate::CreateParams create_params; + create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); + v8::Isolate* isolate = v8::Isolate::New(create_params); + + { + v8::HandleScope scope(isolate); + v8::Isolate::Scope isolate_scope(isolate); + v8::Local<v8::Context> context = v8::Context::New(isolate); + context->Enter(); + + TestCodeEventHandler code_event_handler(isolate); + + const char* source_text_before_start = + "function testCodeEventListenerBeforeStart(a,b) { return a + b };" + "testCodeEventListenerBeforeStart('1', 1);"; + CompileRun(source_text_before_start); + + CHECK_NULL(code_event_handler.FindLine("LazyCompile", + "testCodeEventListenerBeforeStart")); + + code_event_handler.Enable(); + + CHECK_NOT_NULL(code_event_handler.FindLine( + "LazyCompile", "testCodeEventListenerBeforeStart")); + + const char* source_text_after_start = + "function testCodeEventListenerAfterStart(a,b) { return a + b };" + "testCodeEventListenerAfterStart('1', 1);"; + CompileRun(source_text_after_start); + + CHECK_NOT_NULL(code_event_handler.FindLine( + "LazyCompile", "testCodeEventListenerAfterStart")); + + context->Exit(); + } + isolate->Dispose(); +} + TEST(TraceMaps) { SETUP_FLAGS(); i::FLAG_trace_maps = true; |