1 // Copyright 2016 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_LOGGING_CODE_EVENTS_H_ 6 #define V8_LOGGING_CODE_EVENTS_H_ 7 8 #include <unordered_set> 9 10 #include "src/base/platform/mutex.h" 11 #include "src/base/vector.h" 12 #include "src/common/globals.h" 13 #include "src/objects/code.h" 14 #include "src/objects/name.h" 15 #include "src/objects/shared-function-info.h" 16 #include "src/objects/string.h" 17 18 namespace v8 { 19 namespace internal { 20 21 class AbstractCode; 22 class Name; 23 class SharedFunctionInfo; 24 class String; 25 26 namespace wasm { 27 class WasmCode; 28 using WasmName = base::Vector<const char>; 29 } // namespace wasm 30 31 // clang-format off 32 #define LOG_EVENTS_LIST(V) \ 33 V(CODE_CREATION_EVENT, code-creation) \ 34 V(CODE_DISABLE_OPT_EVENT, code-disable-optimization) \ 35 V(CODE_MOVE_EVENT, code-move) \ 36 V(CODE_DELETE_EVENT, code-delete) \ 37 V(CODE_MOVING_GC, code-moving-gc) \ 38 V(SHARED_FUNC_MOVE_EVENT, sfi-move) \ 39 V(SNAPSHOT_CODE_NAME_EVENT, snapshot-code-name) \ 40 V(TICK_EVENT, tick) 41 // clang-format on 42 43 #define TAGS_LIST(V) \ 44 V(BUILTIN_TAG, Builtin) \ 45 V(CALLBACK_TAG, Callback) \ 46 V(EVAL_TAG, Eval) \ 47 V(FUNCTION_TAG, Function) \ 48 V(HANDLER_TAG, Handler) \ 49 V(BYTECODE_HANDLER_TAG, BytecodeHandler) \ 50 V(LAZY_COMPILE_TAG, LazyCompile) \ 51 V(REG_EXP_TAG, RegExp) \ 52 V(SCRIPT_TAG, Script) \ 53 V(STUB_TAG, Stub) \ 54 V(NATIVE_FUNCTION_TAG, Function) \ 55 V(NATIVE_LAZY_COMPILE_TAG, LazyCompile) \ 56 V(NATIVE_SCRIPT_TAG, Script) 57 // Note that 'NATIVE_' cases for functions and scripts are mapped onto 58 // original tags when writing to the log. 59 60 #define LOG_EVENTS_AND_TAGS_LIST(V) \ 61 LOG_EVENTS_LIST(V) \ 62 TAGS_LIST(V) 63 64 #define PROFILE(the_isolate, Call) (the_isolate)->code_event_dispatcher()->Call; 65 66 class CodeEventListener { 67 public: 68 #define DECLARE_ENUM(enum_item, _) enum_item, 69 enum LogEventsAndTags { 70 LOG_EVENTS_AND_TAGS_LIST(DECLARE_ENUM) NUMBER_OF_LOG_EVENTS 71 }; 72 #undef DECLARE_ENUM 73 74 virtual ~CodeEventListener() = default; 75 76 virtual void CodeCreateEvent(LogEventsAndTags tag, Handle<AbstractCode> code, 77 const char* name) = 0; 78 virtual void CodeCreateEvent(LogEventsAndTags tag, Handle<AbstractCode> code, 79 Handle<Name> name) = 0; 80 virtual void CodeCreateEvent(LogEventsAndTags tag, Handle<AbstractCode> code, 81 Handle<SharedFunctionInfo> shared, 82 Handle<Name> script_name) = 0; 83 virtual void CodeCreateEvent(LogEventsAndTags tag, Handle<AbstractCode> code, 84 Handle<SharedFunctionInfo> shared, 85 Handle<Name> script_name, int line, 86 int column) = 0; 87 #if V8_ENABLE_WEBASSEMBLY 88 virtual void CodeCreateEvent(LogEventsAndTags tag, const wasm::WasmCode* code, 89 wasm::WasmName name, const char* source_url, 90 int code_offset, int script_id) = 0; 91 #endif // V8_ENABLE_WEBASSEMBLY 92 93 virtual void CallbackEvent(Handle<Name> name, Address entry_point) = 0; 94 virtual void GetterCallbackEvent(Handle<Name> name, Address entry_point) = 0; 95 virtual void SetterCallbackEvent(Handle<Name> name, Address entry_point) = 0; 96 virtual void RegExpCodeCreateEvent(Handle<AbstractCode> code, 97 Handle<String> source) = 0; 98 // Not handlified as this happens during GC. No allocation allowed. 99 virtual void CodeMoveEvent(AbstractCode from, AbstractCode to) = 0; 100 virtual void SharedFunctionInfoMoveEvent(Address from, Address to) = 0; 101 virtual void NativeContextMoveEvent(Address from, Address to) = 0; 102 virtual void CodeMovingGCEvent() = 0; 103 virtual void CodeDisableOptEvent(Handle<AbstractCode> code, 104 Handle<SharedFunctionInfo> shared) = 0; 105 virtual void CodeDeoptEvent(Handle<Code> code, DeoptimizeKind kind, 106 Address pc, int fp_to_sp_delta) = 0; 107 // These events can happen when 1. an assumption made by optimized code fails 108 // or 2. a weakly embedded object dies. 109 virtual void CodeDependencyChangeEvent(Handle<Code> code, 110 Handle<SharedFunctionInfo> shared, 111 const char* reason) = 0; 112 // Called during GC shortly after any weak references to code objects are 113 // cleared. 114 virtual void WeakCodeClearEvent() = 0; 115 is_listening_to_code_events()116 virtual bool is_listening_to_code_events() { return false; } 117 }; 118 119 // Dispatches code events to a set of registered listeners. 120 class CodeEventDispatcher : public CodeEventListener { 121 public: 122 using LogEventsAndTags = CodeEventListener::LogEventsAndTags; 123 124 CodeEventDispatcher() = default; 125 CodeEventDispatcher(const CodeEventDispatcher&) = delete; 126 CodeEventDispatcher& operator=(const CodeEventDispatcher&) = delete; 127 AddListener(CodeEventListener * listener)128 bool AddListener(CodeEventListener* listener) { 129 base::MutexGuard guard(&mutex_); 130 return listeners_.insert(listener).second; 131 } RemoveListener(CodeEventListener * listener)132 void RemoveListener(CodeEventListener* listener) { 133 base::MutexGuard guard(&mutex_); 134 listeners_.erase(listener); 135 } IsListeningToCodeEvents()136 bool IsListeningToCodeEvents() { 137 for (auto it : listeners_) { 138 if (it->is_listening_to_code_events()) { 139 return true; 140 } 141 } 142 return false; 143 } 144 DispatchEventToListeners(std::function<void (CodeEventListener *)> callback)145 void DispatchEventToListeners( 146 std::function<void(CodeEventListener*)> callback) { 147 base::MutexGuard guard(&mutex_); 148 for (CodeEventListener* listener : listeners_) { 149 callback(listener); 150 } 151 } 152 CodeCreateEvent(LogEventsAndTags tag,Handle<AbstractCode> code,const char * comment)153 void CodeCreateEvent(LogEventsAndTags tag, Handle<AbstractCode> code, 154 const char* comment) override { 155 DispatchEventToListeners([=](CodeEventListener* listener) { 156 listener->CodeCreateEvent(tag, code, comment); 157 }); 158 } CodeCreateEvent(LogEventsAndTags tag,Handle<AbstractCode> code,Handle<Name> name)159 void CodeCreateEvent(LogEventsAndTags tag, Handle<AbstractCode> code, 160 Handle<Name> name) override { 161 DispatchEventToListeners([=](CodeEventListener* listener) { 162 listener->CodeCreateEvent(tag, code, name); 163 }); 164 } CodeCreateEvent(LogEventsAndTags tag,Handle<AbstractCode> code,Handle<SharedFunctionInfo> shared,Handle<Name> name)165 void CodeCreateEvent(LogEventsAndTags tag, Handle<AbstractCode> code, 166 Handle<SharedFunctionInfo> shared, 167 Handle<Name> name) override { 168 DispatchEventToListeners([=](CodeEventListener* listener) { 169 listener->CodeCreateEvent(tag, code, shared, name); 170 }); 171 } CodeCreateEvent(LogEventsAndTags tag,Handle<AbstractCode> code,Handle<SharedFunctionInfo> shared,Handle<Name> source,int line,int column)172 void CodeCreateEvent(LogEventsAndTags tag, Handle<AbstractCode> code, 173 Handle<SharedFunctionInfo> shared, Handle<Name> source, 174 int line, int column) override { 175 DispatchEventToListeners([=](CodeEventListener* listener) { 176 listener->CodeCreateEvent(tag, code, shared, source, line, column); 177 }); 178 } 179 #if V8_ENABLE_WEBASSEMBLY CodeCreateEvent(LogEventsAndTags tag,const wasm::WasmCode * code,wasm::WasmName name,const char * source_url,int code_offset,int script_id)180 void CodeCreateEvent(LogEventsAndTags tag, const wasm::WasmCode* code, 181 wasm::WasmName name, const char* source_url, 182 int code_offset, int script_id) override { 183 DispatchEventToListeners([=](CodeEventListener* listener) { 184 listener->CodeCreateEvent(tag, code, name, source_url, code_offset, 185 script_id); 186 }); 187 } 188 #endif // V8_ENABLE_WEBASSEMBLY CallbackEvent(Handle<Name> name,Address entry_point)189 void CallbackEvent(Handle<Name> name, Address entry_point) override { 190 DispatchEventToListeners([=](CodeEventListener* listener) { 191 listener->CallbackEvent(name, entry_point); 192 }); 193 } GetterCallbackEvent(Handle<Name> name,Address entry_point)194 void GetterCallbackEvent(Handle<Name> name, Address entry_point) override { 195 DispatchEventToListeners([=](CodeEventListener* listener) { 196 listener->GetterCallbackEvent(name, entry_point); 197 }); 198 } SetterCallbackEvent(Handle<Name> name,Address entry_point)199 void SetterCallbackEvent(Handle<Name> name, Address entry_point) override { 200 DispatchEventToListeners([=](CodeEventListener* listener) { 201 listener->SetterCallbackEvent(name, entry_point); 202 }); 203 } RegExpCodeCreateEvent(Handle<AbstractCode> code,Handle<String> source)204 void RegExpCodeCreateEvent(Handle<AbstractCode> code, 205 Handle<String> source) override { 206 DispatchEventToListeners([=](CodeEventListener* listener) { 207 listener->RegExpCodeCreateEvent(code, source); 208 }); 209 } CodeMoveEvent(AbstractCode from,AbstractCode to)210 void CodeMoveEvent(AbstractCode from, AbstractCode to) override { 211 DispatchEventToListeners([=](CodeEventListener* listener) { 212 listener->CodeMoveEvent(from, to); 213 }); 214 } SharedFunctionInfoMoveEvent(Address from,Address to)215 void SharedFunctionInfoMoveEvent(Address from, Address to) override { 216 DispatchEventToListeners([=](CodeEventListener* listener) { 217 listener->SharedFunctionInfoMoveEvent(from, to); 218 }); 219 } NativeContextMoveEvent(Address from,Address to)220 void NativeContextMoveEvent(Address from, Address to) override { 221 DispatchEventToListeners([=](CodeEventListener* listener) { 222 listener->NativeContextMoveEvent(from, to); 223 }); 224 } CodeMovingGCEvent()225 void CodeMovingGCEvent() override { 226 DispatchEventToListeners( 227 [](CodeEventListener* listener) { listener->CodeMovingGCEvent(); }); 228 } CodeDisableOptEvent(Handle<AbstractCode> code,Handle<SharedFunctionInfo> shared)229 void CodeDisableOptEvent(Handle<AbstractCode> code, 230 Handle<SharedFunctionInfo> shared) override { 231 DispatchEventToListeners([=](CodeEventListener* listener) { 232 listener->CodeDisableOptEvent(code, shared); 233 }); 234 } CodeDeoptEvent(Handle<Code> code,DeoptimizeKind kind,Address pc,int fp_to_sp_delta)235 void CodeDeoptEvent(Handle<Code> code, DeoptimizeKind kind, Address pc, 236 int fp_to_sp_delta) override { 237 DispatchEventToListeners([=](CodeEventListener* listener) { 238 listener->CodeDeoptEvent(code, kind, pc, fp_to_sp_delta); 239 }); 240 } CodeDependencyChangeEvent(Handle<Code> code,Handle<SharedFunctionInfo> sfi,const char * reason)241 void CodeDependencyChangeEvent(Handle<Code> code, 242 Handle<SharedFunctionInfo> sfi, 243 const char* reason) override { 244 DispatchEventToListeners([=](CodeEventListener* listener) { 245 listener->CodeDependencyChangeEvent(code, sfi, reason); 246 }); 247 } WeakCodeClearEvent()248 void WeakCodeClearEvent() override { 249 DispatchEventToListeners( 250 [=](CodeEventListener* listener) { listener->WeakCodeClearEvent(); }); 251 } 252 253 private: 254 std::unordered_set<CodeEventListener*> listeners_; 255 base::Mutex mutex_; 256 }; 257 258 } // namespace internal 259 } // namespace v8 260 261 #endif // V8_LOGGING_CODE_EVENTS_H_ 262