• 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/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