Coverage Report

Created: 2025-07-04 09:33

/src/node/deps/v8/include/libplatform/v8-tracing.h
Line
Count
Source (jump to first uncovered line)
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_LIBPLATFORM_V8_TRACING_H_
6
#define V8_LIBPLATFORM_V8_TRACING_H_
7
8
#include <atomic>
9
#include <fstream>
10
#include <memory>
11
#include <unordered_set>
12
#include <vector>
13
14
#include "libplatform/libplatform-export.h"
15
#include "v8-platform.h"  // NOLINT(build/include_directory)
16
17
namespace perfetto {
18
namespace trace_processor {
19
class TraceProcessorStorage;
20
}
21
class TracingSession;
22
}
23
24
namespace v8 {
25
26
namespace base {
27
class Mutex;
28
}  // namespace base
29
30
namespace platform {
31
namespace tracing {
32
33
class TraceEventListener;
34
35
const int kTraceMaxNumArgs = 2;
36
37
class V8_PLATFORM_EXPORT TraceObject {
38
 public:
39
  union ArgValue {
40
    uint64_t as_uint;
41
    int64_t as_int;
42
    double as_double;
43
    const void* as_pointer;
44
    const char* as_string;
45
  };
46
47
0
  TraceObject() = default;
48
  ~TraceObject();
49
  void Initialize(
50
      char phase, const uint8_t* category_enabled_flag, const char* name,
51
      const char* scope, uint64_t id, uint64_t bind_id, int num_args,
52
      const char** arg_names, const uint8_t* arg_types,
53
      const uint64_t* arg_values,
54
      std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables,
55
      unsigned int flags, int64_t timestamp, int64_t cpu_timestamp);
56
  void UpdateDuration(int64_t timestamp, int64_t cpu_timestamp);
57
  void InitializeForTesting(
58
      char phase, const uint8_t* category_enabled_flag, const char* name,
59
      const char* scope, uint64_t id, uint64_t bind_id, int num_args,
60
      const char** arg_names, const uint8_t* arg_types,
61
      const uint64_t* arg_values,
62
      std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables,
63
      unsigned int flags, int pid, int tid, int64_t ts, int64_t tts,
64
      uint64_t duration, uint64_t cpu_duration);
65
66
0
  int pid() const { return pid_; }
67
0
  int tid() const { return tid_; }
68
0
  char phase() const { return phase_; }
69
0
  const uint8_t* category_enabled_flag() const {
70
0
    return category_enabled_flag_;
71
0
  }
72
0
  const char* name() const { return name_; }
73
0
  const char* scope() const { return scope_; }
74
0
  uint64_t id() const { return id_; }
75
0
  uint64_t bind_id() const { return bind_id_; }
76
0
  int num_args() const { return num_args_; }
77
0
  const char** arg_names() { return arg_names_; }
78
0
  uint8_t* arg_types() { return arg_types_; }
79
0
  ArgValue* arg_values() { return arg_values_; }
80
0
  std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables() {
81
0
    return arg_convertables_;
82
0
  }
83
0
  unsigned int flags() const { return flags_; }
84
0
  int64_t ts() { return ts_; }
85
0
  int64_t tts() { return tts_; }
86
0
  uint64_t duration() { return duration_; }
87
0
  uint64_t cpu_duration() { return cpu_duration_; }
88
89
 private:
90
  int pid_;
91
  int tid_;
92
  char phase_;
93
  const char* name_;
94
  const char* scope_;
95
  const uint8_t* category_enabled_flag_;
96
  uint64_t id_;
97
  uint64_t bind_id_;
98
  int num_args_ = 0;
99
  const char* arg_names_[kTraceMaxNumArgs];
100
  uint8_t arg_types_[kTraceMaxNumArgs];
101
  ArgValue arg_values_[kTraceMaxNumArgs];
102
  std::unique_ptr<v8::ConvertableToTraceFormat>
103
      arg_convertables_[kTraceMaxNumArgs];
104
  char* parameter_copy_storage_ = nullptr;
105
  unsigned int flags_;
106
  int64_t ts_;
107
  int64_t tts_;
108
  uint64_t duration_;
109
  uint64_t cpu_duration_;
110
111
  // Disallow copy and assign
112
  TraceObject(const TraceObject&) = delete;
113
  void operator=(const TraceObject&) = delete;
114
};
115
116
class V8_PLATFORM_EXPORT TraceWriter {
117
 public:
118
  TraceWriter() = default;
119
  virtual ~TraceWriter() = default;
120
  virtual void AppendTraceEvent(TraceObject* trace_event) = 0;
121
  virtual void Flush() = 0;
122
123
  static TraceWriter* CreateJSONTraceWriter(std::ostream& stream);
124
  static TraceWriter* CreateJSONTraceWriter(std::ostream& stream,
125
                                            const std::string& tag);
126
127
  static TraceWriter* CreateSystemInstrumentationTraceWriter();
128
129
 private:
130
  // Disallow copy and assign
131
  TraceWriter(const TraceWriter&) = delete;
132
  void operator=(const TraceWriter&) = delete;
133
};
134
135
class V8_PLATFORM_EXPORT TraceBufferChunk {
136
 public:
137
  explicit TraceBufferChunk(uint32_t seq);
138
139
  void Reset(uint32_t new_seq);
140
0
  bool IsFull() const { return next_free_ == kChunkSize; }
141
  TraceObject* AddTraceEvent(size_t* event_index);
142
0
  TraceObject* GetEventAt(size_t index) { return &chunk_[index]; }
143
144
0
  uint32_t seq() const { return seq_; }
145
0
  size_t size() const { return next_free_; }
146
147
  static const size_t kChunkSize = 64;
148
149
 private:
150
  size_t next_free_ = 0;
151
  TraceObject chunk_[kChunkSize];
152
  uint32_t seq_;
153
154
  // Disallow copy and assign
155
  TraceBufferChunk(const TraceBufferChunk&) = delete;
156
  void operator=(const TraceBufferChunk&) = delete;
157
};
158
159
class V8_PLATFORM_EXPORT TraceBuffer {
160
 public:
161
0
  TraceBuffer() = default;
162
0
  virtual ~TraceBuffer() = default;
163
164
  virtual TraceObject* AddTraceEvent(uint64_t* handle) = 0;
165
  virtual TraceObject* GetEventByHandle(uint64_t handle) = 0;
166
  virtual bool Flush() = 0;
167
168
  static const size_t kRingBufferChunks = 1024;
169
170
  static TraceBuffer* CreateTraceBufferRingBuffer(size_t max_chunks,
171
                                                  TraceWriter* trace_writer);
172
173
 private:
174
  // Disallow copy and assign
175
  TraceBuffer(const TraceBuffer&) = delete;
176
  void operator=(const TraceBuffer&) = delete;
177
};
178
179
// Options determines how the trace buffer stores data.
180
enum TraceRecordMode {
181
  // Record until the trace buffer is full.
182
  RECORD_UNTIL_FULL,
183
184
  // Record until the user ends the trace. The trace buffer is a fixed size
185
  // and we use it as a ring buffer during recording.
186
  RECORD_CONTINUOUSLY,
187
188
  // Record until the trace buffer is full, but with a huge buffer size.
189
  RECORD_AS_MUCH_AS_POSSIBLE,
190
191
  // Echo to console. Events are discarded.
192
  ECHO_TO_CONSOLE,
193
};
194
195
class V8_PLATFORM_EXPORT TraceConfig {
196
 public:
197
  typedef std::vector<std::string> StringList;
198
199
  static TraceConfig* CreateDefaultTraceConfig();
200
201
0
  TraceConfig() : enable_systrace_(false), enable_argument_filter_(false) {}
202
0
  TraceRecordMode GetTraceRecordMode() const { return record_mode_; }
203
0
  const StringList& GetEnabledCategories() const {
204
0
    return included_categories_;
205
0
  }
206
0
  bool IsSystraceEnabled() const { return enable_systrace_; }
207
0
  bool IsArgumentFilterEnabled() const { return enable_argument_filter_; }
208
209
0
  void SetTraceRecordMode(TraceRecordMode mode) { record_mode_ = mode; }
210
0
  void EnableSystrace() { enable_systrace_ = true; }
211
0
  void EnableArgumentFilter() { enable_argument_filter_ = true; }
212
213
  void AddIncludedCategory(const char* included_category);
214
215
  bool IsCategoryGroupEnabled(const char* category_group) const;
216
217
 private:
218
  TraceRecordMode record_mode_;
219
  bool enable_systrace_ : 1;
220
  bool enable_argument_filter_ : 1;
221
  StringList included_categories_;
222
223
  // Disallow copy and assign
224
  TraceConfig(const TraceConfig&) = delete;
225
  void operator=(const TraceConfig&) = delete;
226
};
227
228
#if defined(_MSC_VER)
229
#define V8_PLATFORM_NON_EXPORTED_BASE(code) \
230
  __pragma(warning(suppress : 4275)) code
231
#else
232
#define V8_PLATFORM_NON_EXPORTED_BASE(code) code
233
#endif  // defined(_MSC_VER)
234
235
class V8_PLATFORM_EXPORT TracingController
236
    : public V8_PLATFORM_NON_EXPORTED_BASE(v8::TracingController) {
237
 public:
238
  TracingController();
239
  ~TracingController() override;
240
241
#if defined(V8_USE_PERFETTO)
242
  // Must be called before StartTracing() if V8_USE_PERFETTO is true. Provides
243
  // the output stream for the JSON trace data.
244
  void InitializeForPerfetto(std::ostream* output_stream);
245
  // Provide an optional listener for testing that will receive trace events.
246
  // Must be called before StartTracing().
247
  void SetTraceEventListenerForTesting(TraceEventListener* listener);
248
#else   // defined(V8_USE_PERFETTO)
249
  // The pointer returned from GetCategoryGroupEnabled() points to a value with
250
  // zero or more of the following bits. Used in this class only. The
251
  // TRACE_EVENT macros should only use the value as a bool. These values must
252
  // be in sync with macro values in TraceEvent.h in Blink.
253
  enum CategoryGroupEnabledFlags {
254
    // Category group enabled for the recording mode.
255
    ENABLED_FOR_RECORDING = 1 << 0,
256
    // Category group enabled by SetEventCallbackEnabled().
257
    ENABLED_FOR_EVENT_CALLBACK = 1 << 2,
258
    // Category group enabled to export events to ETW.
259
    ENABLED_FOR_ETW_EXPORT = 1 << 3
260
  };
261
262
  // Takes ownership of |trace_buffer|.
263
  void Initialize(TraceBuffer* trace_buffer);
264
265
  // v8::TracingController implementation.
266
  const uint8_t* GetCategoryGroupEnabled(const char* category_group) override;
267
  uint64_t AddTraceEvent(
268
      char phase, const uint8_t* category_enabled_flag, const char* name,
269
      const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args,
270
      const char** arg_names, const uint8_t* arg_types,
271
      const uint64_t* arg_values,
272
      std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables,
273
      unsigned int flags) override;
274
  uint64_t AddTraceEventWithTimestamp(
275
      char phase, const uint8_t* category_enabled_flag, const char* name,
276
      const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args,
277
      const char** arg_names, const uint8_t* arg_types,
278
      const uint64_t* arg_values,
279
      std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables,
280
      unsigned int flags, int64_t timestamp) override;
281
  void UpdateTraceEventDuration(const uint8_t* category_enabled_flag,
282
                                const char* name, uint64_t handle) override;
283
284
  static const char* GetCategoryGroupName(const uint8_t* category_enabled_flag);
285
286
  void AddTraceStateObserver(
287
      v8::TracingController::TraceStateObserver* observer) override;
288
  void RemoveTraceStateObserver(
289
      v8::TracingController::TraceStateObserver* observer) override;
290
#endif  // !defined(V8_USE_PERFETTO)
291
292
  void StartTracing(TraceConfig* trace_config);
293
  void StopTracing();
294
295
 protected:
296
#if !defined(V8_USE_PERFETTO)
297
  virtual int64_t CurrentTimestampMicroseconds();
298
  virtual int64_t CurrentCpuTimestampMicroseconds();
299
#endif  // !defined(V8_USE_PERFETTO)
300
301
 private:
302
#if !defined(V8_USE_PERFETTO)
303
  void UpdateCategoryGroupEnabledFlag(size_t category_index);
304
  void UpdateCategoryGroupEnabledFlags();
305
#endif  // !defined(V8_USE_PERFETTO)
306
307
  std::unique_ptr<base::Mutex> mutex_;
308
  std::unique_ptr<TraceConfig> trace_config_;
309
  std::atomic_bool recording_{false};
310
311
#if defined(V8_USE_PERFETTO)
312
  std::ostream* output_stream_ = nullptr;
313
  std::unique_ptr<perfetto::trace_processor::TraceProcessorStorage>
314
      trace_processor_;
315
  TraceEventListener* listener_for_testing_ = nullptr;
316
  std::unique_ptr<perfetto::TracingSession> tracing_session_;
317
#else   // !defined(V8_USE_PERFETTO)
318
  std::unordered_set<v8::TracingController::TraceStateObserver*> observers_;
319
  std::unique_ptr<TraceBuffer> trace_buffer_;
320
#endif  // !defined(V8_USE_PERFETTO)
321
322
  // Disallow copy and assign
323
  TracingController(const TracingController&) = delete;
324
  void operator=(const TracingController&) = delete;
325
};
326
327
#undef V8_PLATFORM_NON_EXPORTED_BASE
328
329
}  // namespace tracing
330
}  // namespace platform
331
}  // namespace v8
332
333
#endif  // V8_LIBPLATFORM_V8_TRACING_H_