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/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/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, AbstractCode code, |
76 | const char* ) = 0; |
77 | virtual void CodeCreateEvent(LogEventsAndTags tag, AbstractCode code, |
78 | Name name) = 0; |
79 | virtual void CodeCreateEvent(LogEventsAndTags tag, AbstractCode code, |
80 | SharedFunctionInfo shared, Name source) = 0; |
81 | virtual void CodeCreateEvent(LogEventsAndTags tag, AbstractCode code, |
82 | SharedFunctionInfo shared, Name source, int line, |
83 | int column) = 0; |
84 | virtual void CodeCreateEvent(LogEventsAndTags tag, const wasm::WasmCode* code, |
85 | wasm::WasmName name) = 0; |
86 | virtual void CallbackEvent(Name name, Address entry_point) = 0; |
87 | virtual void GetterCallbackEvent(Name name, Address entry_point) = 0; |
88 | virtual void SetterCallbackEvent(Name name, Address entry_point) = 0; |
89 | virtual void RegExpCodeCreateEvent(AbstractCode code, String source) = 0; |
90 | virtual void CodeMoveEvent(AbstractCode from, AbstractCode to) = 0; |
91 | virtual void SharedFunctionInfoMoveEvent(Address from, Address to) = 0; |
92 | virtual void CodeMovingGCEvent() = 0; |
93 | virtual void CodeDisableOptEvent(AbstractCode code, |
94 | SharedFunctionInfo shared) = 0; |
95 | virtual void CodeDeoptEvent(Code code, DeoptimizeKind kind, Address pc, |
96 | int fp_to_sp_delta) = 0; |
97 | |
98 | virtual bool is_listening_to_code_events() { return false; } |
99 | }; |
100 | |
101 | class CodeEventDispatcher { |
102 | public: |
103 | using LogEventsAndTags = CodeEventListener::LogEventsAndTags; |
104 | |
105 | CodeEventDispatcher() = default; |
106 | |
107 | bool AddListener(CodeEventListener* listener) { |
108 | base::MutexGuard guard(&mutex_); |
109 | return listeners_.insert(listener).second; |
110 | } |
111 | void RemoveListener(CodeEventListener* listener) { |
112 | base::MutexGuard guard(&mutex_); |
113 | listeners_.erase(listener); |
114 | } |
115 | bool IsListeningToCodeEvents() { |
116 | for (auto it : listeners_) { |
117 | if (it->is_listening_to_code_events()) { |
118 | return true; |
119 | } |
120 | } |
121 | return false; |
122 | } |
123 | |
124 | #define CODE_EVENT_DISPATCH(code) \ |
125 | base::MutexGuard guard(&mutex_); \ |
126 | for (auto it = listeners_.begin(); it != listeners_.end(); ++it) (*it)->code |
127 | |
128 | void CodeCreateEvent(LogEventsAndTags tag, AbstractCode code, |
129 | const char* ) { |
130 | CODE_EVENT_DISPATCH(CodeCreateEvent(tag, code, comment)); |
131 | } |
132 | void CodeCreateEvent(LogEventsAndTags tag, AbstractCode code, Name name) { |
133 | CODE_EVENT_DISPATCH(CodeCreateEvent(tag, code, name)); |
134 | } |
135 | void CodeCreateEvent(LogEventsAndTags tag, AbstractCode code, |
136 | SharedFunctionInfo shared, Name name) { |
137 | CODE_EVENT_DISPATCH(CodeCreateEvent(tag, code, shared, name)); |
138 | } |
139 | void CodeCreateEvent(LogEventsAndTags tag, AbstractCode code, |
140 | SharedFunctionInfo shared, Name source, int line, |
141 | int column) { |
142 | CODE_EVENT_DISPATCH( |
143 | CodeCreateEvent(tag, code, shared, source, line, column)); |
144 | } |
145 | void CodeCreateEvent(LogEventsAndTags tag, const wasm::WasmCode* code, |
146 | wasm::WasmName name) { |
147 | CODE_EVENT_DISPATCH(CodeCreateEvent(tag, code, name)); |
148 | } |
149 | void CallbackEvent(Name name, Address entry_point) { |
150 | CODE_EVENT_DISPATCH(CallbackEvent(name, entry_point)); |
151 | } |
152 | void GetterCallbackEvent(Name name, Address entry_point) { |
153 | CODE_EVENT_DISPATCH(GetterCallbackEvent(name, entry_point)); |
154 | } |
155 | void SetterCallbackEvent(Name name, Address entry_point) { |
156 | CODE_EVENT_DISPATCH(SetterCallbackEvent(name, entry_point)); |
157 | } |
158 | void RegExpCodeCreateEvent(AbstractCode code, String source) { |
159 | CODE_EVENT_DISPATCH(RegExpCodeCreateEvent(code, source)); |
160 | } |
161 | void CodeMoveEvent(AbstractCode from, AbstractCode to) { |
162 | CODE_EVENT_DISPATCH(CodeMoveEvent(from, to)); |
163 | } |
164 | void SharedFunctionInfoMoveEvent(Address from, Address to) { |
165 | CODE_EVENT_DISPATCH(SharedFunctionInfoMoveEvent(from, to)); |
166 | } |
167 | void CodeMovingGCEvent() { CODE_EVENT_DISPATCH(CodeMovingGCEvent()); } |
168 | void CodeDisableOptEvent(AbstractCode code, SharedFunctionInfo shared) { |
169 | CODE_EVENT_DISPATCH(CodeDisableOptEvent(code, shared)); |
170 | } |
171 | void CodeDeoptEvent(Code code, DeoptimizeKind kind, Address pc, |
172 | int fp_to_sp_delta) { |
173 | CODE_EVENT_DISPATCH(CodeDeoptEvent(code, kind, pc, fp_to_sp_delta)); |
174 | } |
175 | #undef CODE_EVENT_DISPATCH |
176 | |
177 | private: |
178 | std::unordered_set<CodeEventListener*> listeners_; |
179 | base::Mutex mutex_; |
180 | |
181 | DISALLOW_COPY_AND_ASSIGN(CodeEventDispatcher); |
182 | }; |
183 | |
184 | } // namespace internal |
185 | } // namespace v8 |
186 | |
187 | #endif // V8_CODE_EVENTS_H_ |
188 | |