V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
trace-event.h
1 // Copyright 2015 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_TRACING_TRACE_EVENT_H_
6 #define V8_TRACING_TRACE_EVENT_H_
7 
8 #include <stddef.h>
9 #include <memory>
10 
11 #include "base/trace_event/common/trace_event_common.h"
12 #include "include/v8-platform.h"
13 #include "src/base/atomicops.h"
14 #include "src/base/macros.h"
15 
16 // This header file defines implementation details of how the trace macros in
17 // trace_event_common.h collect and store trace events. Anything not
18 // implementation-specific should go in trace_macros_common.h instead of here.
19 
20 
21 // The pointer returned from GetCategoryGroupEnabled() points to a
22 // value with zero or more of the following bits. Used in this class only.
23 // The TRACE_EVENT macros should only use the value as a bool.
24 // These values must be in sync with macro values in trace_log.h in
25 // chromium.
26 enum CategoryGroupEnabledFlags {
27  // Category group enabled for the recording mode.
28  kEnabledForRecording_CategoryGroupEnabledFlags = 1 << 0,
29  // Category group enabled by SetEventCallbackEnabled().
30  kEnabledForEventCallback_CategoryGroupEnabledFlags = 1 << 2,
31  // Category group enabled to export events to ETW.
32  kEnabledForETWExport_CategoryGroupEnabledFlags = 1 << 3,
33 };
34 
35 // By default, const char* asrgument values are assumed to have long-lived scope
36 // and will not be copied. Use this macro to force a const char* to be copied.
37 #define TRACE_STR_COPY(str) v8::internal::tracing::TraceStringWithCopy(str)
38 
39 // By default, uint64 ID argument values are not mangled with the Process ID in
40 // TRACE_EVENT_ASYNC macros. Use this macro to force Process ID mangling.
41 #define TRACE_ID_MANGLE(id) v8::internal::tracing::TraceID::ForceMangle(id)
42 
43 // By default, pointers are mangled with the Process ID in TRACE_EVENT_ASYNC
44 // macros. Use this macro to prevent Process ID mangling.
45 #define TRACE_ID_DONT_MANGLE(id) v8::internal::tracing::TraceID::DontMangle(id)
46 
47 // By default, trace IDs are eventually converted to a single 64-bit number. Use
48 // this macro to add a scope string.
49 #define TRACE_ID_WITH_SCOPE(scope, id) \
50  trace_event_internal::TraceID::WithScope(scope, id)
51 
52 #define INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE() \
53  TRACE_EVENT_API_LOAD_CATEGORY_GROUP_ENABLED() & \
54  (kEnabledForRecording_CategoryGroupEnabledFlags | \
55  kEnabledForEventCallback_CategoryGroupEnabledFlags)
56 
57 // The following macro has no implementation, but it needs to exist since
58 // it gets called from scoped trace events. It cannot call UNIMPLEMENTED()
59 // since an empty implementation is a valid one.
60 #define INTERNAL_TRACE_MEMORY(category, name)
61 
63 // Implementation specific tracing API definitions.
64 
65 // Get a pointer to the enabled state of the given trace category. Only
66 // long-lived literal strings should be given as the category group. The
67 // returned pointer can be held permanently in a local static for example. If
68 // the unsigned char is non-zero, tracing is enabled. If tracing is enabled,
69 // TRACE_EVENT_API_ADD_TRACE_EVENT can be called. It's OK if tracing is disabled
70 // between the load of the tracing state and the call to
71 // TRACE_EVENT_API_ADD_TRACE_EVENT, because this flag only provides an early out
72 // for best performance when tracing is disabled.
73 // const uint8_t*
74 // TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(const char* category_group)
75 #define TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED \
76  v8::internal::tracing::TraceEventHelper::GetTracingController() \
77  ->GetCategoryGroupEnabled
78 
79 // Get the number of times traces have been recorded. This is used to implement
80 // the TRACE_EVENT_IS_NEW_TRACE facility.
81 // unsigned int TRACE_EVENT_API_GET_NUM_TRACES_RECORDED()
82 #define TRACE_EVENT_API_GET_NUM_TRACES_RECORDED UNIMPLEMENTED()
83 
84 // Add a trace event to the platform tracing system.
85 // uint64_t TRACE_EVENT_API_ADD_TRACE_EVENT(
86 // char phase,
87 // const uint8_t* category_group_enabled,
88 // const char* name,
89 // const char* scope,
90 // uint64_t id,
91 // uint64_t bind_id,
92 // int num_args,
93 // const char** arg_names,
94 // const uint8_t* arg_types,
95 // const uint64_t* arg_values,
96 // unsigned int flags)
97 #define TRACE_EVENT_API_ADD_TRACE_EVENT v8::internal::tracing::AddTraceEventImpl
98 
99 // Add a trace event to the platform tracing system.
100 // uint64_t TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP(
101 // char phase,
102 // const uint8_t* category_group_enabled,
103 // const char* name,
104 // const char* scope,
105 // uint64_t id,
106 // uint64_t bind_id,
107 // int num_args,
108 // const char** arg_names,
109 // const uint8_t* arg_types,
110 // const uint64_t* arg_values,
111 // unsigned int flags,
112 // int64_t timestamp)
113 #define TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP \
114  v8::internal::tracing::AddTraceEventWithTimestampImpl
115 
116 // Set the duration field of a COMPLETE trace event.
117 // void TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(
118 // const uint8_t* category_group_enabled,
119 // const char* name,
120 // uint64_t id)
121 #define TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION \
122  v8::internal::tracing::TraceEventHelper::GetTracingController() \
123  ->UpdateTraceEventDuration
124 
125 // Defines atomic operations used internally by the tracing system.
126 #define TRACE_EVENT_API_ATOMIC_WORD v8::base::AtomicWord
127 #define TRACE_EVENT_API_ATOMIC_LOAD(var) v8::base::Relaxed_Load(&(var))
128 #define TRACE_EVENT_API_ATOMIC_STORE(var, value) \
129  v8::base::Relaxed_Store(&(var), (value))
130 #define TRACE_EVENT_API_LOAD_CATEGORY_GROUP_ENABLED() \
131  v8::base::Relaxed_Load(reinterpret_cast<const v8::base::Atomic8*>( \
132  INTERNAL_TRACE_EVENT_UID(category_group_enabled)))
133 
135 
136 // Implementation detail: trace event macros create temporary variables
137 // to keep instrumentation overhead low. These macros give each temporary
138 // variable a unique name based on the line number to prevent name collisions.
139 #define INTERNAL_TRACE_EVENT_UID3(a, b) trace_event_unique_##a##b
140 #define INTERNAL_TRACE_EVENT_UID2(a, b) INTERNAL_TRACE_EVENT_UID3(a, b)
141 #define INTERNAL_TRACE_EVENT_UID(name_prefix) \
142  INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__)
143 
144 // Implementation detail: internal macro to create static category.
145 // No barriers are needed, because this code is designed to operate safely
146 // even when the unsigned char* points to garbage data (which may be the case
147 // on processors without cache coherency).
148 // TODO(fmeawad): This implementation contradicts that we can have a different
149 // configuration for each isolate,
150 // https://code.google.com/p/v8/issues/detail?id=4563
151 #define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES( \
152  category_group, atomic, category_group_enabled) \
153  category_group_enabled = \
154  reinterpret_cast<const uint8_t*>(TRACE_EVENT_API_ATOMIC_LOAD(atomic)); \
155  if (!category_group_enabled) { \
156  category_group_enabled = \
157  TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_group); \
158  TRACE_EVENT_API_ATOMIC_STORE( \
159  atomic, reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD>( \
160  category_group_enabled)); \
161  }
162 
163 #define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group) \
164  static TRACE_EVENT_API_ATOMIC_WORD INTERNAL_TRACE_EVENT_UID(atomic) = 0; \
165  const uint8_t* INTERNAL_TRACE_EVENT_UID(category_group_enabled); \
166  INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES( \
167  category_group, INTERNAL_TRACE_EVENT_UID(atomic), \
168  INTERNAL_TRACE_EVENT_UID(category_group_enabled));
169 
170 // Implementation detail: internal macro to create static category and add
171 // event if the category is enabled.
172 #define INTERNAL_TRACE_EVENT_ADD(phase, category_group, name, flags, ...) \
173  do { \
174  INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
175  if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
176  v8::internal::tracing::AddTraceEvent( \
177  phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
178  v8::internal::tracing::kGlobalScope, v8::internal::tracing::kNoId, \
179  v8::internal::tracing::kNoId, flags, ##__VA_ARGS__); \
180  } \
181  } while (false)
182 
183 // Implementation detail: internal macro to create static category and add begin
184 // event if the category is enabled. Also adds the end event when the scope
185 // ends.
186 #define INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, ...) \
187  INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
188  v8::internal::tracing::ScopedTracer INTERNAL_TRACE_EVENT_UID(tracer); \
189  if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
190  uint64_t h = v8::internal::tracing::AddTraceEvent( \
191  TRACE_EVENT_PHASE_COMPLETE, \
192  INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
193  v8::internal::tracing::kGlobalScope, v8::internal::tracing::kNoId, \
194  v8::internal::tracing::kNoId, TRACE_EVENT_FLAG_NONE, ##__VA_ARGS__); \
195  INTERNAL_TRACE_EVENT_UID(tracer) \
196  .Initialize(INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
197  h); \
198  }
199 
200 #define INTERNAL_TRACE_EVENT_ADD_SCOPED_WITH_FLOW(category_group, name, \
201  bind_id, flow_flags, ...) \
202  INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
203  v8::internal::tracing::ScopedTracer INTERNAL_TRACE_EVENT_UID(tracer); \
204  if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
205  unsigned int trace_event_flags = flow_flags; \
206  v8::internal::tracing::TraceID trace_event_bind_id(bind_id, \
207  &trace_event_flags); \
208  uint64_t h = v8::internal::tracing::AddTraceEvent( \
209  TRACE_EVENT_PHASE_COMPLETE, \
210  INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
211  v8::internal::tracing::kGlobalScope, v8::internal::tracing::kNoId, \
212  trace_event_bind_id.raw_id(), trace_event_flags, ##__VA_ARGS__); \
213  INTERNAL_TRACE_EVENT_UID(tracer) \
214  .Initialize(INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
215  h); \
216  }
217 
218 // Implementation detail: internal macro to create static category and add
219 // event if the category is enabled.
220 #define INTERNAL_TRACE_EVENT_ADD_WITH_ID(phase, category_group, name, id, \
221  flags, ...) \
222  do { \
223  INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
224  if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
225  unsigned int trace_event_flags = flags | TRACE_EVENT_FLAG_HAS_ID; \
226  v8::internal::tracing::TraceID trace_event_trace_id(id, \
227  &trace_event_flags); \
228  v8::internal::tracing::AddTraceEvent( \
229  phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
230  trace_event_trace_id.scope(), trace_event_trace_id.raw_id(), \
231  v8::internal::tracing::kNoId, trace_event_flags, ##__VA_ARGS__); \
232  } \
233  } while (false)
234 
235 // Adds a trace event with a given timestamp.
236 #define INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP(phase, category_group, name, \
237  timestamp, flags, ...) \
238  do { \
239  INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
240  if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
241  v8::internal::tracing::AddTraceEventWithTimestamp( \
242  phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
243  v8::internal::tracing::kGlobalScope, v8::internal::tracing::kNoId, \
244  v8::internal::tracing::kNoId, flags, timestamp, ##__VA_ARGS__); \
245  } \
246  } while (false)
247 
248 // Adds a trace event with a given id and timestamp.
249 #define INTERNAL_TRACE_EVENT_ADD_WITH_ID_AND_TIMESTAMP( \
250  phase, category_group, name, id, timestamp, flags, ...) \
251  do { \
252  INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
253  if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
254  unsigned int trace_event_flags = flags | TRACE_EVENT_FLAG_HAS_ID; \
255  v8::internal::tracing::TraceID trace_event_trace_id(id, \
256  &trace_event_flags); \
257  v8::internal::tracing::AddTraceEventWithTimestamp( \
258  phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
259  trace_event_trace_id.scope(), trace_event_trace_id.raw_id(), \
260  v8::internal::tracing::kNoId, trace_event_flags, timestamp, \
261  ##__VA_ARGS__); \
262  } \
263  } while (false)
264 
265 // Adds a trace event with a given id, thread_id, and timestamp. This redirects
266 // to INTERNAL_TRACE_EVENT_ADD_WITH_ID_AND_TIMESTAMP as we presently do not care
267 // about the thread id.
268 #define INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
269  phase, category_group, name, id, thread_id, timestamp, flags, ...) \
270  INTERNAL_TRACE_EVENT_ADD_WITH_ID_AND_TIMESTAMP( \
271  phase, category_group, name, id, timestamp, flags, ##__VA_ARGS__)
272 
273 // Enter and leave a context based on the current scope.
274 #define INTERNAL_TRACE_EVENT_SCOPED_CONTEXT(category_group, name, context) \
275  struct INTERNAL_TRACE_EVENT_UID(ScopedContext) { \
276  public: \
277  INTERNAL_TRACE_EVENT_UID(ScopedContext)(uint64_t cid) : cid_(cid) { \
278  TRACE_EVENT_ENTER_CONTEXT(category_group, name, cid_); \
279  } \
280  ~INTERNAL_TRACE_EVENT_UID(ScopedContext)() { \
281  TRACE_EVENT_LEAVE_CONTEXT(category_group, name, cid_); \
282  } \
283  \
284  private: \
285  /* Local class friendly DISALLOW_COPY_AND_ASSIGN */ \
286  INTERNAL_TRACE_EVENT_UID(ScopedContext) \
287  (const INTERNAL_TRACE_EVENT_UID(ScopedContext)&) {} \
288  void operator=(const INTERNAL_TRACE_EVENT_UID(ScopedContext)&) {} \
289  uint64_t cid_; \
290  }; \
291  INTERNAL_TRACE_EVENT_UID(ScopedContext) \
292  INTERNAL_TRACE_EVENT_UID(scoped_context)(context);
293 
294 #define TRACE_EVENT_CALL_STATS_SCOPED(isolate, category_group, name) \
295  INTERNAL_TRACE_EVENT_CALL_STATS_SCOPED(isolate, category_group, name)
296 
297 #define INTERNAL_TRACE_EVENT_CALL_STATS_SCOPED(isolate, category_group, name) \
298  INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
299  v8::internal::tracing::CallStatsScopedTracer INTERNAL_TRACE_EVENT_UID( \
300  tracer); \
301  if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
302  INTERNAL_TRACE_EVENT_UID(tracer) \
303  .Initialize(isolate, INTERNAL_TRACE_EVENT_UID(category_group_enabled), \
304  name); \
305  }
306 
307 namespace v8 {
308 namespace internal {
309 
310 class Isolate;
311 
312 namespace tracing {
313 
314 // Specify these values when the corresponding argument of AddTraceEvent is not
315 // used.
316 const int kZeroNumArgs = 0;
317 const decltype(nullptr) kGlobalScope = nullptr;
318 const uint64_t kNoId = 0;
319 
321  public:
322  static v8::TracingController* GetTracingController();
323 };
324 
325 // TraceID encapsulates an ID that can either be an integer or pointer. Pointers
326 // are by default mangled with the Process ID so that they are unlikely to
327 // collide when the same pointer is used on different processes.
328 class TraceID {
329  public:
330  class WithScope {
331  public:
332  WithScope(const char* scope, uint64_t raw_id)
333  : scope_(scope), raw_id_(raw_id) {}
334  uint64_t raw_id() const { return raw_id_; }
335  const char* scope() const { return scope_; }
336 
337  private:
338  const char* scope_ = nullptr;
339  uint64_t raw_id_;
340  };
341 
342  class DontMangle {
343  public:
344  explicit DontMangle(const void* raw_id)
345  : raw_id_(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(raw_id))) {}
346  explicit DontMangle(uint64_t raw_id) : raw_id_(raw_id) {}
347  explicit DontMangle(unsigned int raw_id) : raw_id_(raw_id) {}
348  explicit DontMangle(uint16_t raw_id) : raw_id_(raw_id) {}
349  explicit DontMangle(unsigned char raw_id) : raw_id_(raw_id) {}
350  explicit DontMangle(int64_t raw_id)
351  : raw_id_(static_cast<uint64_t>(raw_id)) {}
352  explicit DontMangle(int raw_id) : raw_id_(static_cast<uint64_t>(raw_id)) {}
353  explicit DontMangle(int16_t raw_id)
354  : raw_id_(static_cast<uint64_t>(raw_id)) {}
355  explicit DontMangle(signed char raw_id)
356  : raw_id_(static_cast<uint64_t>(raw_id)) {}
357  explicit DontMangle(WithScope scoped_id)
358  : scope_(scoped_id.scope()), raw_id_(scoped_id.raw_id()) {}
359  const char* scope() const { return scope_; }
360  uint64_t raw_id() const { return raw_id_; }
361 
362  private:
363  const char* scope_ = nullptr;
364  uint64_t raw_id_;
365  };
366 
367  class ForceMangle {
368  public:
369  explicit ForceMangle(uint64_t raw_id) : raw_id_(raw_id) {}
370  explicit ForceMangle(unsigned int raw_id) : raw_id_(raw_id) {}
371  explicit ForceMangle(uint16_t raw_id) : raw_id_(raw_id) {}
372  explicit ForceMangle(unsigned char raw_id) : raw_id_(raw_id) {}
373  explicit ForceMangle(int64_t raw_id)
374  : raw_id_(static_cast<uint64_t>(raw_id)) {}
375  explicit ForceMangle(int raw_id) : raw_id_(static_cast<uint64_t>(raw_id)) {}
376  explicit ForceMangle(int16_t raw_id)
377  : raw_id_(static_cast<uint64_t>(raw_id)) {}
378  explicit ForceMangle(signed char raw_id)
379  : raw_id_(static_cast<uint64_t>(raw_id)) {}
380  uint64_t raw_id() const { return raw_id_; }
381 
382  private:
383  uint64_t raw_id_;
384  };
385 
386  TraceID(const void* raw_id, unsigned int* flags)
387  : raw_id_(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(raw_id))) {
388  *flags |= TRACE_EVENT_FLAG_MANGLE_ID;
389  }
390  TraceID(ForceMangle raw_id, unsigned int* flags) : raw_id_(raw_id.raw_id()) {
391  *flags |= TRACE_EVENT_FLAG_MANGLE_ID;
392  }
393  TraceID(DontMangle maybe_scoped_id, unsigned int* flags)
394  : scope_(maybe_scoped_id.scope()), raw_id_(maybe_scoped_id.raw_id()) {}
395  TraceID(uint64_t raw_id, unsigned int* flags) : raw_id_(raw_id) {
396  (void)flags;
397  }
398  TraceID(unsigned int raw_id, unsigned int* flags) : raw_id_(raw_id) {
399  (void)flags;
400  }
401  TraceID(uint16_t raw_id, unsigned int* flags) : raw_id_(raw_id) {
402  (void)flags;
403  }
404  TraceID(unsigned char raw_id, unsigned int* flags) : raw_id_(raw_id) {
405  (void)flags;
406  }
407  TraceID(int64_t raw_id, unsigned int* flags)
408  : raw_id_(static_cast<uint64_t>(raw_id)) {
409  (void)flags;
410  }
411  TraceID(int raw_id, unsigned int* flags)
412  : raw_id_(static_cast<uint64_t>(raw_id)) {
413  (void)flags;
414  }
415  TraceID(int16_t raw_id, unsigned int* flags)
416  : raw_id_(static_cast<uint64_t>(raw_id)) {
417  (void)flags;
418  }
419  TraceID(signed char raw_id, unsigned int* flags)
420  : raw_id_(static_cast<uint64_t>(raw_id)) {
421  (void)flags;
422  }
423  TraceID(WithScope scoped_id, unsigned int* flags)
424  : scope_(scoped_id.scope()), raw_id_(scoped_id.raw_id()) {}
425 
426  uint64_t raw_id() const { return raw_id_; }
427  const char* scope() const { return scope_; }
428 
429  private:
430  const char* scope_ = nullptr;
431  uint64_t raw_id_;
432 };
433 
434 // Simple union to store various types as uint64_t.
436  bool as_bool;
437  uint64_t as_uint;
438  int64_t as_int;
439  double as_double;
440  const void* as_pointer;
441  const char* as_string;
442 };
443 
444 // Simple container for const char* that should be copied instead of retained.
446  public:
447  explicit TraceStringWithCopy(const char* str) : str_(str) {}
448  operator const char*() const { return str_; }
449 
450  private:
451  const char* str_;
452 };
453 
454 static V8_INLINE uint64_t AddTraceEventImpl(
455  char phase, const uint8_t* category_group_enabled, const char* name,
456  const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args,
457  const char** arg_names, const uint8_t* arg_types,
458  const uint64_t* arg_values, unsigned int flags) {
459  std::unique_ptr<ConvertableToTraceFormat> arg_convertables[2];
460  if (num_args > 0 && arg_types[0] == TRACE_VALUE_TYPE_CONVERTABLE) {
461  arg_convertables[0].reset(reinterpret_cast<ConvertableToTraceFormat*>(
462  static_cast<intptr_t>(arg_values[0])));
463  }
464  if (num_args > 1 && arg_types[1] == TRACE_VALUE_TYPE_CONVERTABLE) {
465  arg_convertables[1].reset(reinterpret_cast<ConvertableToTraceFormat*>(
466  static_cast<intptr_t>(arg_values[1])));
467  }
468  DCHECK_LE(num_args, 2);
469  v8::TracingController* controller =
470  v8::internal::tracing::TraceEventHelper::GetTracingController();
471  return controller->AddTraceEvent(phase, category_group_enabled, name, scope,
472  id, bind_id, num_args, arg_names, arg_types,
473  arg_values, arg_convertables, flags);
474 }
475 
476 static V8_INLINE uint64_t AddTraceEventWithTimestampImpl(
477  char phase, const uint8_t* category_group_enabled, const char* name,
478  const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args,
479  const char** arg_names, const uint8_t* arg_types,
480  const uint64_t* arg_values, unsigned int flags, int64_t timestamp) {
481  std::unique_ptr<ConvertableToTraceFormat> arg_convertables[2];
482  if (num_args > 0 && arg_types[0] == TRACE_VALUE_TYPE_CONVERTABLE) {
483  arg_convertables[0].reset(reinterpret_cast<ConvertableToTraceFormat*>(
484  static_cast<intptr_t>(arg_values[0])));
485  }
486  if (num_args > 1 && arg_types[1] == TRACE_VALUE_TYPE_CONVERTABLE) {
487  arg_convertables[1].reset(reinterpret_cast<ConvertableToTraceFormat*>(
488  static_cast<intptr_t>(arg_values[1])));
489  }
490  DCHECK_LE(num_args, 2);
491  v8::TracingController* controller =
492  v8::internal::tracing::TraceEventHelper::GetTracingController();
493  return controller->AddTraceEventWithTimestamp(
494  phase, category_group_enabled, name, scope, id, bind_id, num_args,
495  arg_names, arg_types, arg_values, arg_convertables, flags, timestamp);
496 }
497 
498 // Define SetTraceValue for each allowed type. It stores the type and
499 // value in the return arguments. This allows this API to avoid declaring any
500 // structures so that it is portable to third_party libraries.
501 #define INTERNAL_DECLARE_SET_TRACE_VALUE(actual_type, union_member, \
502  value_type_id) \
503  static V8_INLINE void SetTraceValue(actual_type arg, unsigned char* type, \
504  uint64_t* value) { \
505  TraceValueUnion type_value; \
506  type_value.union_member = arg; \
507  *type = value_type_id; \
508  *value = type_value.as_uint; \
509  }
510 // Simpler form for int types that can be safely casted.
511 #define INTERNAL_DECLARE_SET_TRACE_VALUE_INT(actual_type, value_type_id) \
512  static V8_INLINE void SetTraceValue(actual_type arg, unsigned char* type, \
513  uint64_t* value) { \
514  *type = value_type_id; \
515  *value = static_cast<uint64_t>(arg); \
516  }
517 
518 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(uint64_t, TRACE_VALUE_TYPE_UINT)
519 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned int, TRACE_VALUE_TYPE_UINT)
520 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(uint16_t, TRACE_VALUE_TYPE_UINT)
521 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned char, TRACE_VALUE_TYPE_UINT)
522 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int64_t, TRACE_VALUE_TYPE_INT)
523 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int, TRACE_VALUE_TYPE_INT)
524 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int16_t, TRACE_VALUE_TYPE_INT)
525 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(signed char, TRACE_VALUE_TYPE_INT)
526 INTERNAL_DECLARE_SET_TRACE_VALUE(bool, as_bool, TRACE_VALUE_TYPE_BOOL)
527 INTERNAL_DECLARE_SET_TRACE_VALUE(double, as_double, TRACE_VALUE_TYPE_DOUBLE)
528 INTERNAL_DECLARE_SET_TRACE_VALUE(const void*, as_pointer,
529  TRACE_VALUE_TYPE_POINTER)
530 INTERNAL_DECLARE_SET_TRACE_VALUE(const char*, as_string,
531  TRACE_VALUE_TYPE_STRING)
532 INTERNAL_DECLARE_SET_TRACE_VALUE(const TraceStringWithCopy&, as_string,
533  TRACE_VALUE_TYPE_COPY_STRING)
534 
535 #undef INTERNAL_DECLARE_SET_TRACE_VALUE
536 #undef INTERNAL_DECLARE_SET_TRACE_VALUE_INT
537 
538 static V8_INLINE void SetTraceValue(ConvertableToTraceFormat* convertable_value,
539  unsigned char* type, uint64_t* value) {
540  *type = TRACE_VALUE_TYPE_CONVERTABLE;
541  *value = static_cast<uint64_t>(reinterpret_cast<intptr_t>(convertable_value));
542 }
543 
544 template <typename T>
545 static V8_INLINE typename std::enable_if<
546  std::is_convertible<T*, ConvertableToTraceFormat*>::value>::type
547 SetTraceValue(std::unique_ptr<T> ptr, unsigned char* type, uint64_t* value) {
548  SetTraceValue(ptr.release(), type, value);
549 }
550 
551 // These AddTraceEvent template
552 // function is defined here instead of in the macro, because the arg_values
553 // could be temporary objects, such as std::string. In order to store
554 // pointers to the internal c_str and pass through to the tracing API,
555 // the arg_values must live throughout these procedures.
556 
557 static V8_INLINE uint64_t AddTraceEvent(char phase,
558  const uint8_t* category_group_enabled,
559  const char* name, const char* scope,
560  uint64_t id, uint64_t bind_id,
561  unsigned int flags) {
562  return TRACE_EVENT_API_ADD_TRACE_EVENT(phase, category_group_enabled, name,
563  scope, id, bind_id, kZeroNumArgs,
564  nullptr, nullptr, nullptr, flags);
565 }
566 
567 template <class ARG1_TYPE>
568 static V8_INLINE uint64_t AddTraceEvent(
569  char phase, const uint8_t* category_group_enabled, const char* name,
570  const char* scope, uint64_t id, uint64_t bind_id, unsigned int flags,
571  const char* arg1_name, ARG1_TYPE&& arg1_val) {
572  const int num_args = 1;
573  uint8_t arg_type;
574  uint64_t arg_value;
575  SetTraceValue(std::forward<ARG1_TYPE>(arg1_val), &arg_type, &arg_value);
576  return TRACE_EVENT_API_ADD_TRACE_EVENT(
577  phase, category_group_enabled, name, scope, id, bind_id, num_args,
578  &arg1_name, &arg_type, &arg_value, flags);
579 }
580 
581 template <class ARG1_TYPE, class ARG2_TYPE>
582 static V8_INLINE uint64_t AddTraceEvent(
583  char phase, const uint8_t* category_group_enabled, const char* name,
584  const char* scope, uint64_t id, uint64_t bind_id, unsigned int flags,
585  const char* arg1_name, ARG1_TYPE&& arg1_val, const char* arg2_name,
586  ARG2_TYPE&& arg2_val) {
587  const int num_args = 2;
588  const char* arg_names[2] = {arg1_name, arg2_name};
589  unsigned char arg_types[2];
590  uint64_t arg_values[2];
591  SetTraceValue(std::forward<ARG1_TYPE>(arg1_val), &arg_types[0],
592  &arg_values[0]);
593  SetTraceValue(std::forward<ARG2_TYPE>(arg2_val), &arg_types[1],
594  &arg_values[1]);
595  return TRACE_EVENT_API_ADD_TRACE_EVENT(
596  phase, category_group_enabled, name, scope, id, bind_id, num_args,
597  arg_names, arg_types, arg_values, flags);
598 }
599 
600 static V8_INLINE uint64_t AddTraceEventWithTimestamp(
601  char phase, const uint8_t* category_group_enabled, const char* name,
602  const char* scope, uint64_t id, uint64_t bind_id, unsigned int flags,
603  int64_t timestamp) {
604  return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP(
605  phase, category_group_enabled, name, scope, id, bind_id, kZeroNumArgs,
606  nullptr, nullptr, nullptr, flags, timestamp);
607 }
608 
609 template <class ARG1_TYPE>
610 static V8_INLINE uint64_t AddTraceEventWithTimestamp(
611  char phase, const uint8_t* category_group_enabled, const char* name,
612  const char* scope, uint64_t id, uint64_t bind_id, unsigned int flags,
613  int64_t timestamp, const char* arg1_name, ARG1_TYPE&& arg1_val) {
614  const int num_args = 1;
615  uint8_t arg_type;
616  uint64_t arg_value;
617  SetTraceValue(std::forward<ARG1_TYPE>(arg1_val), &arg_type, &arg_value);
618  return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP(
619  phase, category_group_enabled, name, scope, id, bind_id, num_args,
620  &arg1_name, &arg_type, &arg_value, flags, timestamp);
621 }
622 
623 template <class ARG1_TYPE, class ARG2_TYPE>
624 static V8_INLINE uint64_t AddTraceEventWithTimestamp(
625  char phase, const uint8_t* category_group_enabled, const char* name,
626  const char* scope, uint64_t id, uint64_t bind_id, unsigned int flags,
627  int64_t timestamp, const char* arg1_name, ARG1_TYPE&& arg1_val,
628  const char* arg2_name, ARG2_TYPE&& arg2_val) {
629  const int num_args = 2;
630  const char* arg_names[2] = {arg1_name, arg2_name};
631  unsigned char arg_types[2];
632  uint64_t arg_values[2];
633  SetTraceValue(std::forward<ARG1_TYPE>(arg1_val), &arg_types[0],
634  &arg_values[0]);
635  SetTraceValue(std::forward<ARG2_TYPE>(arg2_val), &arg_types[1],
636  &arg_values[1]);
637  return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP(
638  phase, category_group_enabled, name, scope, id, bind_id, num_args,
639  arg_names, arg_types, arg_values, flags, timestamp);
640 }
641 
642 // Used by TRACE_EVENTx macros. Do not use directly.
644  public:
645  // Note: members of data_ intentionally left uninitialized. See Initialize.
646  ScopedTracer() : p_data_(nullptr) {}
647 
648  ~ScopedTracer() {
649  if (p_data_ && *data_.category_group_enabled)
650  TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(
651  data_.category_group_enabled, data_.name, data_.event_handle);
652  }
653 
654  void Initialize(const uint8_t* category_group_enabled, const char* name,
655  uint64_t event_handle) {
656  data_.category_group_enabled = category_group_enabled;
657  data_.name = name;
658  data_.event_handle = event_handle;
659  p_data_ = &data_;
660  }
661 
662  private:
663  // This Data struct workaround is to avoid initializing all the members
664  // in Data during construction of this object, since this object is always
665  // constructed, even when tracing is disabled. If the members of Data were
666  // members of this class instead, compiler warnings occur about potential
667  // uninitialized accesses.
668  struct Data {
669  const uint8_t* category_group_enabled;
670  const char* name;
671  uint64_t event_handle;
672  };
673  Data* p_data_;
674  Data data_;
675 };
676 
677 // Do not use directly.
679  public:
680  CallStatsScopedTracer() : p_data_(nullptr) {}
682  if (V8_UNLIKELY(p_data_ && *data_.category_group_enabled)) {
683  AddEndTraceEvent();
684  }
685  }
686 
687  void Initialize(v8::internal::Isolate* isolate,
688  const uint8_t* category_group_enabled, const char* name);
689 
690  private:
691  void AddEndTraceEvent();
692  struct Data {
693  const uint8_t* category_group_enabled;
694  const char* name;
695  v8::internal::Isolate* isolate;
696  };
697  bool has_parent_scope_;
698  Data* p_data_;
699  Data data_;
700 };
701 
702 } // namespace tracing
703 } // namespace internal
704 } // namespace v8
705 
706 #endif // V8_TRACING_TRACE_EVENT_H_
Definition: libplatform.h:13
virtual uint64_t AddTraceEvent(char phase, const uint8_t *category_enabled_flag, const char *name, const char *scope, uint64_t id, uint64_t bind_id, int32_t num_args, const char **arg_names, const uint8_t *arg_types, const uint64_t *arg_values, std::unique_ptr< ConvertableToTraceFormat > *arg_convertables, unsigned int flags)
Definition: v8-platform.h:146