• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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