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