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