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_CODE_EVENTS_H_ 6 #define V8_CODE_EVENTS_H_ 7 8 #include <unordered_set> 9 10 #include "src/base/platform/mutex.h" 11 #include "src/globals.h" 12 #include "src/vector.h" 13 14 namespace v8 { 15 namespace internal { 16 17 class AbstractCode; 18 class Name; 19 class SharedFunctionInfo; 20 class String; 21 22 namespace wasm { 23 class WasmCode; 24 using WasmName = Vector<const char>; 25 } // namespace wasm 26 27 #define LOG_EVENTS_LIST(V) \ 28 V(CODE_CREATION_EVENT, code-creation) \ 29 V(CODE_DISABLE_OPT_EVENT, code-disable-optimization) \ 30 V(CODE_MOVE_EVENT, code-move) \ 31 V(CODE_DELETE_EVENT, code-delete) \ 32 V(CODE_MOVING_GC, code-moving-gc) \ 33 V(SHARED_FUNC_MOVE_EVENT, sfi-move) \ 34 V(SNAPSHOT_CODE_NAME_EVENT, snapshot-code-name) \ 35 V(TICK_EVENT, tick) 36 37 #define TAGS_LIST(V) \ 38 V(BUILTIN_TAG, Builtin) \ 39 V(CALLBACK_TAG, Callback) \ 40 V(EVAL_TAG, Eval) \ 41 V(FUNCTION_TAG, Function) \ 42 V(INTERPRETED_FUNCTION_TAG, InterpretedFunction) \ 43 V(HANDLER_TAG, Handler) \ 44 V(BYTECODE_HANDLER_TAG, BytecodeHandler) \ 45 V(LAZY_COMPILE_TAG, LazyCompile) \ 46 V(REG_EXP_TAG, RegExp) \ 47 V(SCRIPT_TAG, Script) \ 48 V(STUB_TAG, Stub) \ 49 V(NATIVE_FUNCTION_TAG, Function) \ 50 V(NATIVE_LAZY_COMPILE_TAG, LazyCompile) \ 51 V(NATIVE_SCRIPT_TAG, Script) 52 // Note that 'NATIVE_' cases for functions and scripts are mapped onto 53 // original tags when writing to the log. 54 55 #define LOG_EVENTS_AND_TAGS_LIST(V) \ 56 LOG_EVENTS_LIST(V) \ 57 TAGS_LIST(V) 58 59 #define PROFILE(the_isolate, Call) (the_isolate)->code_event_dispatcher()->Call; 60 61 class CodeEventListener { 62 public: 63 #define DECLARE_ENUM(enum_item, _) enum_item, 64 enum LogEventsAndTags { 65 LOG_EVENTS_AND_TAGS_LIST(DECLARE_ENUM) NUMBER_OF_LOG_EVENTS 66 }; 67 #undef DECLARE_ENUM 68 ~CodeEventListener()69 virtual ~CodeEventListener() {} 70 71 virtual void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code, 72 const char* comment) = 0; 73 virtual void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code, 74 Name* name) = 0; 75 virtual void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code, 76 SharedFunctionInfo* shared, Name* source) = 0; 77 virtual void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code, 78 SharedFunctionInfo* shared, Name* source, 79 int line, int column) = 0; 80 virtual void CodeCreateEvent(LogEventsAndTags tag, const wasm::WasmCode* code, 81 wasm::WasmName name) = 0; 82 virtual void CallbackEvent(Name* name, Address entry_point) = 0; 83 virtual void GetterCallbackEvent(Name* name, Address entry_point) = 0; 84 virtual void SetterCallbackEvent(Name* name, Address entry_point) = 0; 85 virtual void RegExpCodeCreateEvent(AbstractCode* code, String* source) = 0; 86 virtual void CodeMoveEvent(AbstractCode* from, AbstractCode* to) = 0; 87 virtual void SharedFunctionInfoMoveEvent(Address from, Address to) = 0; 88 virtual void CodeMovingGCEvent() = 0; 89 virtual void CodeDisableOptEvent(AbstractCode* code, 90 SharedFunctionInfo* shared) = 0; 91 virtual void CodeDeoptEvent(Code* code, DeoptimizeKind kind, Address pc, 92 int fp_to_sp_delta) = 0; 93 is_listening_to_code_events()94 virtual bool is_listening_to_code_events() { return false; } 95 }; 96 97 class CodeEventDispatcher { 98 public: 99 using LogEventsAndTags = CodeEventListener::LogEventsAndTags; 100 CodeEventDispatcher()101 CodeEventDispatcher() {} 102 AddListener(CodeEventListener * listener)103 bool AddListener(CodeEventListener* listener) { 104 base::LockGuard<base::Mutex> guard(&mutex_); 105 return listeners_.insert(listener).second; 106 } RemoveListener(CodeEventListener * listener)107 void RemoveListener(CodeEventListener* listener) { 108 base::LockGuard<base::Mutex> guard(&mutex_); 109 listeners_.erase(listener); 110 } IsListeningToCodeEvents()111 bool IsListeningToCodeEvents() { 112 for (auto it : listeners_) { 113 if (it->is_listening_to_code_events()) { 114 return true; 115 } 116 } 117 return false; 118 } 119 120 #define CODE_EVENT_DISPATCH(code) \ 121 base::LockGuard<base::Mutex> guard(&mutex_); \ 122 for (auto it = listeners_.begin(); it != listeners_.end(); ++it) (*it)->code 123 CodeCreateEvent(LogEventsAndTags tag,AbstractCode * code,const char * comment)124 void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code, 125 const char* comment) { 126 CODE_EVENT_DISPATCH(CodeCreateEvent(tag, code, comment)); 127 } CodeCreateEvent(LogEventsAndTags tag,AbstractCode * code,Name * name)128 void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code, Name* name) { 129 CODE_EVENT_DISPATCH(CodeCreateEvent(tag, code, name)); 130 } CodeCreateEvent(LogEventsAndTags tag,AbstractCode * code,SharedFunctionInfo * shared,Name * name)131 void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code, 132 SharedFunctionInfo* shared, Name* name) { 133 CODE_EVENT_DISPATCH(CodeCreateEvent(tag, code, shared, name)); 134 } CodeCreateEvent(LogEventsAndTags tag,AbstractCode * code,SharedFunctionInfo * shared,Name * source,int line,int column)135 void CodeCreateEvent(LogEventsAndTags tag, AbstractCode* code, 136 SharedFunctionInfo* shared, Name* source, int line, 137 int column) { 138 CODE_EVENT_DISPATCH( 139 CodeCreateEvent(tag, code, shared, source, line, column)); 140 } CodeCreateEvent(LogEventsAndTags tag,const wasm::WasmCode * code,wasm::WasmName name)141 void CodeCreateEvent(LogEventsAndTags tag, const wasm::WasmCode* code, 142 wasm::WasmName name) { 143 CODE_EVENT_DISPATCH(CodeCreateEvent(tag, code, name)); 144 } CallbackEvent(Name * name,Address entry_point)145 void CallbackEvent(Name* name, Address entry_point) { 146 CODE_EVENT_DISPATCH(CallbackEvent(name, entry_point)); 147 } GetterCallbackEvent(Name * name,Address entry_point)148 void GetterCallbackEvent(Name* name, Address entry_point) { 149 CODE_EVENT_DISPATCH(GetterCallbackEvent(name, entry_point)); 150 } SetterCallbackEvent(Name * name,Address entry_point)151 void SetterCallbackEvent(Name* name, Address entry_point) { 152 CODE_EVENT_DISPATCH(SetterCallbackEvent(name, entry_point)); 153 } RegExpCodeCreateEvent(AbstractCode * code,String * source)154 void RegExpCodeCreateEvent(AbstractCode* code, String* source) { 155 CODE_EVENT_DISPATCH(RegExpCodeCreateEvent(code, source)); 156 } CodeMoveEvent(AbstractCode * from,AbstractCode * to)157 void CodeMoveEvent(AbstractCode* from, AbstractCode* to) { 158 CODE_EVENT_DISPATCH(CodeMoveEvent(from, to)); 159 } SharedFunctionInfoMoveEvent(Address from,Address to)160 void SharedFunctionInfoMoveEvent(Address from, Address to) { 161 CODE_EVENT_DISPATCH(SharedFunctionInfoMoveEvent(from, to)); 162 } CodeMovingGCEvent()163 void CodeMovingGCEvent() { CODE_EVENT_DISPATCH(CodeMovingGCEvent()); } CodeDisableOptEvent(AbstractCode * code,SharedFunctionInfo * shared)164 void CodeDisableOptEvent(AbstractCode* code, SharedFunctionInfo* shared) { 165 CODE_EVENT_DISPATCH(CodeDisableOptEvent(code, shared)); 166 } CodeDeoptEvent(Code * code,DeoptimizeKind kind,Address pc,int fp_to_sp_delta)167 void CodeDeoptEvent(Code* code, DeoptimizeKind kind, Address pc, 168 int fp_to_sp_delta) { 169 CODE_EVENT_DISPATCH(CodeDeoptEvent(code, kind, pc, fp_to_sp_delta)); 170 } 171 #undef CODE_EVENT_DISPATCH 172 173 private: 174 std::unordered_set<CodeEventListener*> listeners_; 175 base::Mutex mutex_; 176 177 DISALLOW_COPY_AND_ASSIGN(CodeEventDispatcher); 178 }; 179 180 } // namespace internal 181 } // namespace v8 182 183 #endif // V8_CODE_EVENTS_H_ 184