code-events.h 10.1 KB
Newer Older
1 2 3 4
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6
#ifndef V8_LOGGING_CODE_EVENTS_H_
#define V8_LOGGING_CODE_EVENTS_H_
7 8 9

#include <unordered_set>

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 19 20 21 22 23 24 25

namespace v8 {
namespace internal {

class AbstractCode;
class Name;
class SharedFunctionInfo;
class String;

26 27 28 29 30
namespace wasm {
class WasmCode;
using WasmName = Vector<const char>;
}  // namespace wasm

31
// clang-format off
32 33 34 35 36 37 38 39
#define LOG_EVENTS_LIST(V)                             \
  V(CODE_CREATION_EVENT, code-creation)                \
  V(CODE_DISABLE_OPT_EVENT, code-disable-optimization) \
  V(CODE_MOVE_EVENT, code-move)                        \
  V(CODE_DELETE_EVENT, code-delete)                    \
  V(CODE_MOVING_GC, code-moving-gc)                    \
  V(SHARED_FUNC_MOVE_EVENT, sfi-move)                  \
  V(SNAPSHOT_CODE_NAME_EVENT, snapshot-code-name)      \
40
  V(TICK_EVENT, tick)
41
// clang-format on
42

43 44 45 46 47 48 49 50 51 52 53 54 55
#define TAGS_LIST(V)                       \
  V(BUILTIN_TAG, Builtin)                  \
  V(CALLBACK_TAG, Callback)                \
  V(EVAL_TAG, Eval)                        \
  V(FUNCTION_TAG, Function)                \
  V(HANDLER_TAG, Handler)                  \
  V(BYTECODE_HANDLER_TAG, BytecodeHandler) \
  V(LAZY_COMPILE_TAG, LazyCompile)         \
  V(REG_EXP_TAG, RegExp)                   \
  V(SCRIPT_TAG, Script)                    \
  V(STUB_TAG, Stub)                        \
  V(NATIVE_FUNCTION_TAG, Function)         \
  V(NATIVE_LAZY_COMPILE_TAG, LazyCompile)  \
56
  V(NATIVE_SCRIPT_TAG, Script)
57 58 59
// Note that 'NATIVE_' cases for functions and scripts are mapped onto
// original tags when writing to the log.

60 61 62 63
#define LOG_EVENTS_AND_TAGS_LIST(V) \
  LOG_EVENTS_LIST(V)                \
  TAGS_LIST(V)

64 65 66 67 68 69 70 71 72 73
#define PROFILE(the_isolate, Call) (the_isolate)->code_event_dispatcher()->Call;

class CodeEventListener {
 public:
#define DECLARE_ENUM(enum_item, _) enum_item,
  enum LogEventsAndTags {
    LOG_EVENTS_AND_TAGS_LIST(DECLARE_ENUM) NUMBER_OF_LOG_EVENTS
  };
#undef DECLARE_ENUM

74
  virtual ~CodeEventListener() = default;
75

76 77 78 79 80 81 82 83 84 85
  virtual void CodeCreateEvent(LogEventsAndTags tag, Handle<AbstractCode> code,
                               const char* name) = 0;
  virtual void CodeCreateEvent(LogEventsAndTags tag, Handle<AbstractCode> code,
                               Handle<Name> name) = 0;
  virtual void CodeCreateEvent(LogEventsAndTags tag, Handle<AbstractCode> code,
                               Handle<SharedFunctionInfo> shared,
                               Handle<Name> script_name) = 0;
  virtual void CodeCreateEvent(LogEventsAndTags tag, Handle<AbstractCode> code,
                               Handle<SharedFunctionInfo> shared,
                               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 90
                               wasm::WasmName name, const char* source_url,
                               int code_offset, int script_id) = 0;
91
#endif  // V8_ENABLE_WEBASSEMBLY
92 93 94 95 96 97 98

  virtual void CallbackEvent(Handle<Name> name, Address entry_point) = 0;
  virtual void GetterCallbackEvent(Handle<Name> name, Address entry_point) = 0;
  virtual void SetterCallbackEvent(Handle<Name> name, Address entry_point) = 0;
  virtual void RegExpCodeCreateEvent(Handle<AbstractCode> code,
                                     Handle<String> source) = 0;
  // 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 104 105
  virtual void CodeDisableOptEvent(Handle<AbstractCode> code,
                                   Handle<SharedFunctionInfo> shared) = 0;
  virtual void CodeDeoptEvent(Handle<Code> code, DeoptimizeKind kind,
106 107
                              Address pc, int fp_to_sp_delta,
                              bool reuse_code) = 0;
108 109 110 111 112
  // These events can happen when 1. an assumption made by optimized code fails
  // or 2. a weakly embedded object dies.
  virtual void CodeDependencyChangeEvent(Handle<Code> code,
                                         Handle<SharedFunctionInfo> shared,
                                         const char* reason) = 0;
113 114 115
  // Called during GC shortly after any weak references to code objects are
  // cleared.
  virtual void WeakCodeClearEvent() = 0;
116 117

  virtual bool is_listening_to_code_events() { return false; }
118 119
};

120 121
// Dispatches code events to a set of registered listeners.
class CodeEventDispatcher : public CodeEventListener {
122 123 124
 public:
  using LogEventsAndTags = CodeEventListener::LogEventsAndTags;

125
  CodeEventDispatcher() = default;
126 127
  CodeEventDispatcher(const CodeEventDispatcher&) = delete;
  CodeEventDispatcher& operator=(const CodeEventDispatcher&) = delete;
128 129

  bool AddListener(CodeEventListener* listener) {
130
    base::MutexGuard guard(&mutex_);
131 132 133
    return listeners_.insert(listener).second;
  }
  void RemoveListener(CodeEventListener* listener) {
134
    base::MutexGuard guard(&mutex_);
135 136
    listeners_.erase(listener);
  }
137 138 139 140 141 142 143 144
  bool IsListeningToCodeEvents() {
    for (auto it : listeners_) {
      if (it->is_listening_to_code_events()) {
        return true;
      }
    }
    return false;
  }
145

146 147 148 149 150 151
  void DispatchEventToListeners(
      std::function<void(CodeEventListener*)> callback) {
    base::MutexGuard guard(&mutex_);
    for (CodeEventListener* listener : listeners_) {
      callback(listener);
    }
152
  }
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178

  void CodeCreateEvent(LogEventsAndTags tag, Handle<AbstractCode> code,
                       const char* comment) override {
    DispatchEventToListeners([=](CodeEventListener* listener) {
      listener->CodeCreateEvent(tag, code, comment);
    });
  }
  void CodeCreateEvent(LogEventsAndTags tag, Handle<AbstractCode> code,
                       Handle<Name> name) override {
    DispatchEventToListeners([=](CodeEventListener* listener) {
      listener->CodeCreateEvent(tag, code, name);
    });
  }
  void CodeCreateEvent(LogEventsAndTags tag, Handle<AbstractCode> code,
                       Handle<SharedFunctionInfo> shared,
                       Handle<Name> name) override {
    DispatchEventToListeners([=](CodeEventListener* listener) {
      listener->CodeCreateEvent(tag, code, shared, name);
    });
  }
  void CodeCreateEvent(LogEventsAndTags tag, Handle<AbstractCode> code,
                       Handle<SharedFunctionInfo> shared, Handle<Name> source,
                       int line, int column) override {
    DispatchEventToListeners([=](CodeEventListener* listener) {
      listener->CodeCreateEvent(tag, code, shared, source, line, column);
    });
179
  }
180
#if V8_ENABLE_WEBASSEMBLY
181
  void CodeCreateEvent(LogEventsAndTags tag, const wasm::WasmCode* code,
182 183
                       wasm::WasmName name, const char* source_url,
                       int code_offset, int script_id) override {
184
    DispatchEventToListeners([=](CodeEventListener* listener) {
185 186
      listener->CodeCreateEvent(tag, code, name, source_url, code_offset,
                                script_id);
187 188
    });
  }
189
#endif  // V8_ENABLE_WEBASSEMBLY
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
  void CallbackEvent(Handle<Name> name, Address entry_point) override {
    DispatchEventToListeners([=](CodeEventListener* listener) {
      listener->CallbackEvent(name, entry_point);
    });
  }
  void GetterCallbackEvent(Handle<Name> name, Address entry_point) override {
    DispatchEventToListeners([=](CodeEventListener* listener) {
      listener->GetterCallbackEvent(name, entry_point);
    });
  }
  void SetterCallbackEvent(Handle<Name> name, Address entry_point) override {
    DispatchEventToListeners([=](CodeEventListener* listener) {
      listener->SetterCallbackEvent(name, entry_point);
    });
  }
  void RegExpCodeCreateEvent(Handle<AbstractCode> code,
                             Handle<String> source) override {
    DispatchEventToListeners([=](CodeEventListener* listener) {
      listener->RegExpCodeCreateEvent(code, source);
    });
  }
  void CodeMoveEvent(AbstractCode from, AbstractCode to) override {
    DispatchEventToListeners([=](CodeEventListener* listener) {
      listener->CodeMoveEvent(from, to);
    });
  }
  void SharedFunctionInfoMoveEvent(Address from, Address to) override {
    DispatchEventToListeners([=](CodeEventListener* listener) {
      listener->SharedFunctionInfoMoveEvent(from, to);
    });
  }
221 222 223 224 225
  void NativeContextMoveEvent(Address from, Address to) override {
    DispatchEventToListeners([=](CodeEventListener* listener) {
      listener->NativeContextMoveEvent(from, to);
    });
  }
226 227 228 229 230 231 232 233 234 235 236
  void CodeMovingGCEvent() override {
    DispatchEventToListeners(
        [](CodeEventListener* listener) { listener->CodeMovingGCEvent(); });
  }
  void CodeDisableOptEvent(Handle<AbstractCode> code,
                           Handle<SharedFunctionInfo> shared) override {
    DispatchEventToListeners([=](CodeEventListener* listener) {
      listener->CodeDisableOptEvent(code, shared);
    });
  }
  void CodeDeoptEvent(Handle<Code> code, DeoptimizeKind kind, Address pc,
237
                      int fp_to_sp_delta, bool reuse_code) override {
238
    DispatchEventToListeners([=](CodeEventListener* listener) {
239
      listener->CodeDeoptEvent(code, kind, pc, fp_to_sp_delta, reuse_code);
240
    });
241
  }
242 243 244 245 246 247 248
  void CodeDependencyChangeEvent(Handle<Code> code,
                                 Handle<SharedFunctionInfo> sfi,
                                 const char* reason) override {
    DispatchEventToListeners([=](CodeEventListener* listener) {
      listener->CodeDependencyChangeEvent(code, sfi, reason);
    });
  }
249 250 251
  void WeakCodeClearEvent() override {
    DispatchEventToListeners(
        [=](CodeEventListener* listener) { listener->WeakCodeClearEvent(); });
252
  }
253 254 255

 private:
  std::unordered_set<CodeEventListener*> listeners_;
256
  base::Mutex mutex_;
257 258 259 260 261
};

}  // namespace internal
}  // namespace v8

262
#endif  // V8_LOGGING_CODE_EVENTS_H_