v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
trace-event.h
Go to the documentation of this file.
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 first to ensure that V8_USE_PERFETTO can be defined before use.
12#include "v8config.h" // NOLINT(build/include_directory)
13
14#if defined(V8_USE_PERFETTO)
15#include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
17#else
19#endif // !defined(V8_USE_PERFETTO)
20
21#include "include/v8-platform.h"
22#include "src/base/atomicops.h"
23#include "src/base/macros.h"
24
25// This header file defines implementation details of how the trace macros in
26// trace-event-no-perfetto.h collect and store trace events. Anything not
27// implementation-specific should go in trace_macros_common.h instead of here.
28
29
30// The pointer returned from GetCategoryGroupEnabled() points to a
31// value with zero or more of the following bits. Used in this class only.
32// The TRACE_EVENT macros should only use the value as a bool.
33// These values must be in sync with macro values in trace_log.h in
34// chromium.
36 // Category group enabled for the recording mode.
38 // Category group enabled by SetEventCallbackEnabled().
40 // Category group enabled to export events to ETW.
42};
43
44#if !defined(V8_USE_PERFETTO)
45
46// TODO(petermarshall): Remove with the old tracing implementation - Perfetto
47// copies const char* arguments by default.
48// By default, const char* argument values are assumed to have long-lived scope
49// and will not be copied. Use this macro to force a const char* to be copied.
50#define TRACE_STR_COPY(str) v8::internal::tracing::TraceStringWithCopy(str)
51
52// By default, trace IDs are eventually converted to a single 64-bit number. Use
53// this macro to add a scope string.
54#define TRACE_ID_WITH_SCOPE(scope, id) \
55 v8::internal::tracing::TraceID::WithScope(scope, id)
56
57#define INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE() \
58 TRACE_EVENT_API_LOAD_CATEGORY_GROUP_ENABLED() & \
59 (kEnabledForRecording_CategoryGroupEnabledFlags | \
60 kEnabledForEventCallback_CategoryGroupEnabledFlags)
61
62// The following macro has no implementation, but it needs to exist since
63// it gets called from scoped trace events. It cannot call UNIMPLEMENTED()
64// since an empty implementation is a valid one.
65#define INTERNAL_TRACE_MEMORY(category, name)
66
68// Implementation specific tracing API definitions.
69
70// Get a pointer to the enabled state of the given trace category. Only
71// long-lived literal strings should be given as the category group. The
72// returned pointer can be held permanently in a local static for example. If
73// the unsigned char is non-zero, tracing is enabled. If tracing is enabled,
74// TRACE_EVENT_API_ADD_TRACE_EVENT can be called. It's OK if tracing is disabled
75// between the load of the tracing state and the call to
76// TRACE_EVENT_API_ADD_TRACE_EVENT, because this flag only provides an early out
77// for best performance when tracing is disabled.
78// const uint8_t*
79// TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(const char* category_group)
80#define TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED \
81 v8::internal::tracing::TraceEventHelper::GetTracingController() \
82 ->GetCategoryGroupEnabled
83
84// Get the number of times traces have been recorded. This is used to implement
85// the TRACE_EVENT_IS_NEW_TRACE facility.
86// unsigned int TRACE_EVENT_API_GET_NUM_TRACES_RECORDED()
87#define TRACE_EVENT_API_GET_NUM_TRACES_RECORDED UNIMPLEMENTED()
88
89// Add a trace event to the platform tracing system.
90// uint64_t TRACE_EVENT_API_ADD_TRACE_EVENT(
91// char phase,
92// const uint8_t* category_group_enabled,
93// const char* name,
94// const char* scope,
95// uint64_t id,
96// uint64_t bind_id,
97// int num_args,
98// const char** arg_names,
99// const uint8_t* arg_types,
100// const uint64_t* arg_values,
101// unsigned int flags)
102#define TRACE_EVENT_API_ADD_TRACE_EVENT v8::internal::tracing::AddTraceEventImpl
103
104// Add a trace event to the platform tracing system.
105// uint64_t TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP(
106// char phase,
107// const uint8_t* category_group_enabled,
108// const char* name,
109// const char* scope,
110// uint64_t id,
111// uint64_t bind_id,
112// int num_args,
113// const char** arg_names,
114// const uint8_t* arg_types,
115// const uint64_t* arg_values,
116// unsigned int flags,
117// int64_t timestamp)
118#define TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP \
119 v8::internal::tracing::AddTraceEventWithTimestampImpl
120
121// Set the duration field of a COMPLETE trace event.
122// void TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(
123// const uint8_t* category_group_enabled,
124// const char* name,
125// uint64_t id)
126#define TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION \
127 v8::internal::tracing::TraceEventHelper::GetTracingController() \
128 ->UpdateTraceEventDuration
129
130// Defines atomic operations used internally by the tracing system.
131// Acquire/release barriers are important here: crbug.com/1330114#c8.
132#define TRACE_EVENT_API_ATOMIC_WORD v8::base::AtomicWord
133#define TRACE_EVENT_API_ATOMIC_LOAD(var) v8::base::Acquire_Load(&(var))
134#define TRACE_EVENT_API_ATOMIC_STORE(var, value) \
135 v8::base::Release_Store(&(var), (value))
136// This load can be Relaxed because it's reading the state of
137// `category_group_enabled` and not inferring other variable's state from the
138// result.
139#define TRACE_EVENT_API_LOAD_CATEGORY_GROUP_ENABLED() \
140 v8::base::Relaxed_Load(reinterpret_cast<const v8::base::Atomic8*>( \
141 INTERNAL_TRACE_EVENT_UID(category_group_enabled)))
142
144
145// Implementation detail: trace event macros create temporary variables
146// to keep instrumentation overhead low. These macros give each temporary
147// variable a unique name based on the line number to prevent name collisions.
148#define INTERNAL_TRACE_EVENT_UID3(a, b) trace_event_unique_##a##b
149#define INTERNAL_TRACE_EVENT_UID2(a, b) INTERNAL_TRACE_EVENT_UID3(a, b)
150#define INTERNAL_TRACE_EVENT_UID(name_prefix) \
151 INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__)
152
153// Implementation detail: internal macro to create static category.
154// No barriers are needed, because this code is designed to operate safely
155// even when the unsigned char* points to garbage data (which may be the case
156// on processors without cache coherency).
157// TODO(fmeawad): This implementation contradicts that we can have a different
158// configuration for each isolate,
159// https://code.google.com/p/v8/issues/detail?id=4563
160#define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES( \
161 category_group, atomic, category_group_enabled) \
162 category_group_enabled = \
163 reinterpret_cast<const uint8_t*>(TRACE_EVENT_API_ATOMIC_LOAD(atomic)); \
164 if (!category_group_enabled) { \
165 category_group_enabled = \
166 TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_group); \
167 TRACE_EVENT_API_ATOMIC_STORE( \
168 atomic, reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD>( \
169 category_group_enabled)); \
170 }
171
172#define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group) \
173 static TRACE_EVENT_API_ATOMIC_WORD INTERNAL_TRACE_EVENT_UID(atomic) = 0; \
174 const uint8_t* INTERNAL_TRACE_EVENT_UID(category_group_enabled); \
175 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES( \
176 category_group, INTERNAL_TRACE_EVENT_UID(atomic), \
177 INTERNAL_TRACE_EVENT_UID(category_group_enabled));
178
179// Implementation detail: internal macro to create static category and add
180// event if the category is enabled.
181#define INTERNAL_TRACE_EVENT_ADD(phase, category_group, name, flags, ...) \
182 do { \
183 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
184 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
185 v8::internal::tracing::AddTraceEvent( \
186 phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
187 v8::internal::tracing::kGlobalScope, v8::internal::tracing::kNoId, \
188 v8::internal::tracing::kNoId, flags, ##__VA_ARGS__); \
189 } \
190 } while (false)
191
192// Implementation detail: internal macro to create static category and add begin
193// event if the category is enabled. Also adds the end event when the scope
194// ends.
195#define INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, ...) \
196 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
197 v8::internal::tracing::ScopedTracer INTERNAL_TRACE_EVENT_UID(tracer); \
198 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
199 uint64_t h = v8::internal::tracing::AddTraceEvent( \
200 TRACE_EVENT_PHASE_COMPLETE, \
201 INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
202 v8::internal::tracing::kGlobalScope, v8::internal::tracing::kNoId, \
203 v8::internal::tracing::kNoId, TRACE_EVENT_FLAG_NONE, ##__VA_ARGS__); \
204 INTERNAL_TRACE_EVENT_UID(tracer) \
205 .Initialize(INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
206 h); \
207 }
208
209#define INTERNAL_TRACE_EVENT_ADD_SCOPED_WITH_FLOW(category_group, name, \
210 bind_id, flow_flags, ...) \
211 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
212 v8::internal::tracing::ScopedTracer INTERNAL_TRACE_EVENT_UID(tracer); \
213 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
214 unsigned int trace_event_flags = flow_flags; \
215 v8::internal::tracing::TraceID trace_event_bind_id(bind_id, \
216 &trace_event_flags); \
217 uint64_t h = v8::internal::tracing::AddTraceEvent( \
218 TRACE_EVENT_PHASE_COMPLETE, \
219 INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
220 v8::internal::tracing::kGlobalScope, v8::internal::tracing::kNoId, \
221 trace_event_bind_id.raw_id(), trace_event_flags, ##__VA_ARGS__); \
222 INTERNAL_TRACE_EVENT_UID(tracer) \
223 .Initialize(INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
224 h); \
225 }
226
227// Implementation detail: internal macro to create static category and add
228// event if the category is enabled.
229#define INTERNAL_TRACE_EVENT_ADD_WITH_ID(phase, category_group, name, id, \
230 flags, ...) \
231 do { \
232 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
233 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
234 unsigned int trace_event_flags = flags | TRACE_EVENT_FLAG_HAS_ID; \
235 v8::internal::tracing::TraceID trace_event_trace_id(id, \
236 &trace_event_flags); \
237 v8::internal::tracing::AddTraceEvent( \
238 phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
239 trace_event_trace_id.scope(), trace_event_trace_id.raw_id(), \
240 v8::internal::tracing::kNoId, trace_event_flags, ##__VA_ARGS__); \
241 } \
242 } while (false)
243
244// Adds a trace event with a given timestamp.
245#define INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP(phase, category_group, name, \
246 timestamp, flags, ...) \
247 do { \
248 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
249 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
250 v8::internal::tracing::AddTraceEventWithTimestamp( \
251 phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
252 v8::internal::tracing::kGlobalScope, v8::internal::tracing::kNoId, \
253 v8::internal::tracing::kNoId, flags, timestamp, ##__VA_ARGS__); \
254 } \
255 } while (false)
256
257// Adds a trace event with a given id and timestamp.
258#define INTERNAL_TRACE_EVENT_ADD_WITH_ID_AND_TIMESTAMP( \
259 phase, category_group, name, id, timestamp, flags, ...) \
260 do { \
261 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
262 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
263 unsigned int trace_event_flags = flags | TRACE_EVENT_FLAG_HAS_ID; \
264 v8::internal::tracing::TraceID trace_event_trace_id(id, \
265 &trace_event_flags); \
266 v8::internal::tracing::AddTraceEventWithTimestamp( \
267 phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
268 trace_event_trace_id.scope(), trace_event_trace_id.raw_id(), \
269 v8::internal::tracing::kNoId, trace_event_flags, timestamp, \
270 ##__VA_ARGS__); \
271 } \
272 } while (false)
273
274// Adds a trace event with a given id, thread_id, and timestamp. This redirects
275// to INTERNAL_TRACE_EVENT_ADD_WITH_ID_AND_TIMESTAMP as we presently do not care
276// about the thread id.
277#define INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
278 phase, category_group, name, id, thread_id, timestamp, flags, ...) \
279 INTERNAL_TRACE_EVENT_ADD_WITH_ID_AND_TIMESTAMP( \
280 phase, category_group, name, id, timestamp, flags, ##__VA_ARGS__)
281
282#define TRACE_EVENT_CALL_STATS_SCOPED(isolate, category_group, name) \
283 INTERNAL_TRACE_EVENT_CALL_STATS_SCOPED(isolate, category_group, name)
284
285#ifdef V8_RUNTIME_CALL_STATS
286#define INTERNAL_TRACE_EVENT_CALL_STATS_SCOPED(isolate, category_group, name) \
287 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
288 v8::internal::tracing::CallStatsScopedTracer INTERNAL_TRACE_EVENT_UID( \
289 tracer); \
290 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
291 INTERNAL_TRACE_EVENT_UID(tracer) \
292 .Initialize(isolate, INTERNAL_TRACE_EVENT_UID(category_group_enabled), \
293 name); \
294 }
295#else // V8_RUNTIME_CALL_STATS
296#define INTERNAL_TRACE_EVENT_CALL_STATS_SCOPED(isolate, category_group, name)
297#endif // V8_RUNTIME_CALL_STATS
298
299namespace v8 {
300namespace internal {
301
302class Isolate;
303
304namespace tracing {
305
306// Specify these values when the corresponding argument of AddTraceEvent
307// is not used.
308const int kZeroNumArgs = 0;
309const decltype(nullptr) kGlobalScope = nullptr;
310const uint64_t kNoId = 0;
311
316
317// TraceID encapsulates an ID that can either be an integer or pointer.
318class TraceID {
319 public:
320 class WithScope {
321 public:
322 WithScope(const char* scope, uint64_t raw_id)
323 : scope_(scope), raw_id_(raw_id) {}
324 uint64_t raw_id() const { return raw_id_; }
325 const char* scope() const { return scope_; }
326
327 private:
328 const char* scope_ = nullptr;
329 uint64_t raw_id_;
330 };
331
332 TraceID(const void* raw_id, unsigned int* flags)
333 : raw_id_(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(raw_id))) {}
334 TraceID(uint64_t raw_id, unsigned int* flags) : raw_id_(raw_id) {
335 (void)flags;
336 }
337 TraceID(unsigned int raw_id, unsigned int* flags) : raw_id_(raw_id) {
338 (void)flags;
339 }
340 TraceID(uint16_t raw_id, unsigned int* flags) : raw_id_(raw_id) {
341 (void)flags;
342 }
343 TraceID(unsigned char raw_id, unsigned int* flags) : raw_id_(raw_id) {
344 (void)flags;
345 }
346 TraceID(int64_t raw_id, unsigned int* flags)
347 : raw_id_(static_cast<uint64_t>(raw_id)) {
348 (void)flags;
349 }
350 TraceID(int raw_id, unsigned int* flags)
351 : raw_id_(static_cast<uint64_t>(raw_id)) {
352 (void)flags;
353 }
354 TraceID(int16_t raw_id, unsigned int* flags)
355 : raw_id_(static_cast<uint64_t>(raw_id)) {
356 (void)flags;
357 }
358 TraceID(signed char raw_id, unsigned int* flags)
359 : raw_id_(static_cast<uint64_t>(raw_id)) {
360 (void)flags;
361 }
362 TraceID(WithScope scoped_id, unsigned int* flags)
363 : scope_(scoped_id.scope()), raw_id_(scoped_id.raw_id()) {}
364
365 uint64_t raw_id() const { return raw_id_; }
366 const char* scope() const { return scope_; }
367
368 private:
369 const char* scope_ = nullptr;
370 uint64_t raw_id_;
371};
372
373// Simple container for const char* that should be copied instead of retained.
375 public:
376 explicit TraceStringWithCopy(const char* str) : str_(str) {}
377 operator const char*() const { return str_; }
378
379 private:
380 const char* str_;
381};
382
384 char phase, const uint8_t* category_group_enabled, const char* name,
385 const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args,
386 const char** arg_names, const uint8_t* arg_types,
387 const uint64_t* arg_values, unsigned int flags) {
388 std::unique_ptr<ConvertableToTraceFormat> arg_convertables[2];
389 if (num_args > 0 && arg_types[0] == TRACE_VALUE_TYPE_CONVERTABLE) {
390 arg_convertables[0].reset(reinterpret_cast<ConvertableToTraceFormat*>(
391 static_cast<intptr_t>(arg_values[0])));
392 }
393 if (num_args > 1 && arg_types[1] == TRACE_VALUE_TYPE_CONVERTABLE) {
394 arg_convertables[1].reset(reinterpret_cast<ConvertableToTraceFormat*>(
395 static_cast<intptr_t>(arg_values[1])));
396 }
397 DCHECK_LE(num_args, 2);
398 v8::TracingController* controller =
400 return controller->AddTraceEvent(phase, category_group_enabled, name, scope,
401 id, bind_id, num_args, arg_names, arg_types,
402 arg_values, arg_convertables, flags);
403}
404
406 char phase, const uint8_t* category_group_enabled, const char* name,
407 const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args,
408 const char** arg_names, const uint8_t* arg_types,
409 const uint64_t* arg_values, unsigned int flags, int64_t timestamp) {
410 std::unique_ptr<ConvertableToTraceFormat> arg_convertables[2];
411 if (num_args > 0 && arg_types[0] == TRACE_VALUE_TYPE_CONVERTABLE) {
412 arg_convertables[0].reset(reinterpret_cast<ConvertableToTraceFormat*>(
413 static_cast<intptr_t>(arg_values[0])));
414 }
415 if (num_args > 1 && arg_types[1] == TRACE_VALUE_TYPE_CONVERTABLE) {
416 arg_convertables[1].reset(reinterpret_cast<ConvertableToTraceFormat*>(
417 static_cast<intptr_t>(arg_values[1])));
418 }
419 DCHECK_LE(num_args, 2);
420 v8::TracingController* controller =
422 return controller->AddTraceEventWithTimestamp(
423 phase, category_group_enabled, name, scope, id, bind_id, num_args,
424 arg_names, arg_types, arg_values, arg_convertables, flags, timestamp);
425}
426
427// Define SetTraceValue for each allowed type. It stores the type and
428// value in the return arguments. This allows this API to avoid declaring any
429// structures so that it is portable to third_party libraries.
430// This is the base implementation for integer types (including bool) and enums.
431template <typename T>
432static V8_INLINE void SetTraceValue(T arg, unsigned char* type, uint64_t* value)
433 requires(std::is_integral<T>::value || std::is_enum<T>::value)
434{
435 *type = std::is_same<T, bool>::value
437 : std::is_signed<T>::value ? TRACE_VALUE_TYPE_INT
439 *value = static_cast<uint64_t>(arg);
440}
441
442#define INTERNAL_DECLARE_SET_TRACE_VALUE(actual_type, value_type_id) \
443 static V8_INLINE void SetTraceValue(actual_type arg, unsigned char* type, \
444 uint64_t* value) { \
445 *type = value_type_id; \
446 *value = 0; \
447 static_assert(sizeof(arg) <= sizeof(*value)); \
448 memcpy(value, &arg, sizeof(arg)); \
449 }
455#undef INTERNAL_DECLARE_SET_TRACE_VALUE
456
457static V8_INLINE void SetTraceValue(ConvertableToTraceFormat* convertable_value,
458 unsigned char* type, uint64_t* value) {
460 *value = static_cast<uint64_t>(reinterpret_cast<intptr_t>(convertable_value));
461}
462
463template <typename T>
464static V8_INLINE void SetTraceValue(std::unique_ptr<T> ptr, unsigned char* type,
465 uint64_t* value)
466 requires std::is_convertible<T*, ConvertableToTraceFormat*>::value
467{
468 SetTraceValue(ptr.release(), type, value);
469}
470
471// These AddTraceEvent template
472// function is defined here instead of in the macro, because the arg_values
473// could be temporary objects, such as std::string. In order to store
474// pointers to the internal c_str and pass through to the tracing API,
475// the arg_values must live throughout these procedures.
476
477static V8_INLINE uint64_t AddTraceEvent(char phase,
478 const uint8_t* category_group_enabled,
479 const char* name, const char* scope,
480 uint64_t id, uint64_t bind_id,
481 unsigned int flags) {
482 return TRACE_EVENT_API_ADD_TRACE_EVENT(phase, category_group_enabled, name,
483 scope, id, bind_id, kZeroNumArgs,
484 nullptr, nullptr, nullptr, flags);
485}
486
487template <class ARG1_TYPE>
488static V8_INLINE uint64_t AddTraceEvent(
489 char phase, const uint8_t* category_group_enabled, const char* name,
490 const char* scope, uint64_t id, uint64_t bind_id, unsigned int flags,
491 const char* arg1_name, ARG1_TYPE&& arg1_val) {
492 const int num_args = 1;
493 uint8_t arg_type;
494 uint64_t arg_value;
495 SetTraceValue(std::forward<ARG1_TYPE>(arg1_val), &arg_type, &arg_value);
497 phase, category_group_enabled, name, scope, id, bind_id, num_args,
498 &arg1_name, &arg_type, &arg_value, flags);
499}
500
501template <class ARG1_TYPE, class ARG2_TYPE>
502static V8_INLINE uint64_t AddTraceEvent(
503 char phase, const uint8_t* category_group_enabled, const char* name,
504 const char* scope, uint64_t id, uint64_t bind_id, unsigned int flags,
505 const char* arg1_name, ARG1_TYPE&& arg1_val, const char* arg2_name,
506 ARG2_TYPE&& arg2_val) {
507 const int num_args = 2;
508 const char* arg_names[2] = {arg1_name, arg2_name};
509 unsigned char arg_types[2];
510 uint64_t arg_values[2];
511 SetTraceValue(std::forward<ARG1_TYPE>(arg1_val), &arg_types[0],
512 &arg_values[0]);
513 SetTraceValue(std::forward<ARG2_TYPE>(arg2_val), &arg_types[1],
514 &arg_values[1]);
516 phase, category_group_enabled, name, scope, id, bind_id, num_args,
517 arg_names, arg_types, arg_values, flags);
518}
519
521 char phase, const uint8_t* category_group_enabled, const char* name,
522 const char* scope, uint64_t id, uint64_t bind_id, unsigned int flags,
523 int64_t timestamp) {
525 phase, category_group_enabled, name, scope, id, bind_id, kZeroNumArgs,
526 nullptr, nullptr, nullptr, flags, timestamp);
527}
528
529template <class ARG1_TYPE>
531 char phase, const uint8_t* category_group_enabled, const char* name,
532 const char* scope, uint64_t id, uint64_t bind_id, unsigned int flags,
533 int64_t timestamp, const char* arg1_name, ARG1_TYPE&& arg1_val) {
534 const int num_args = 1;
535 uint8_t arg_type;
536 uint64_t arg_value;
537 SetTraceValue(std::forward<ARG1_TYPE>(arg1_val), &arg_type, &arg_value);
539 phase, category_group_enabled, name, scope, id, bind_id, num_args,
540 &arg1_name, &arg_type, &arg_value, flags, timestamp);
541}
542
543template <class ARG1_TYPE, class ARG2_TYPE>
545 char phase, const uint8_t* category_group_enabled, const char* name,
546 const char* scope, uint64_t id, uint64_t bind_id, unsigned int flags,
547 int64_t timestamp, const char* arg1_name, ARG1_TYPE&& arg1_val,
548 const char* arg2_name, ARG2_TYPE&& arg2_val) {
549 const int num_args = 2;
550 const char* arg_names[2] = {arg1_name, arg2_name};
551 unsigned char arg_types[2];
552 uint64_t arg_values[2];
553 SetTraceValue(std::forward<ARG1_TYPE>(arg1_val), &arg_types[0],
554 &arg_values[0]);
555 SetTraceValue(std::forward<ARG2_TYPE>(arg2_val), &arg_types[1],
556 &arg_values[1]);
558 phase, category_group_enabled, name, scope, id, bind_id, num_args,
559 arg_names, arg_types, arg_values, flags, timestamp);
560}
561
562// Used by TRACE_EVENTx macros. Do not use directly.
564 public:
565 // Note: members of data_ intentionally left uninitialized. See Initialize.
566 ScopedTracer() : p_data_(nullptr) {}
567
575
576 void Initialize(const uint8_t* category_group_enabled, const char* name,
577 uint64_t event_handle) {
578 data_.category_group_enabled = category_group_enabled;
579 data_.name = name;
580 data_.event_handle = event_handle;
581 p_data_ = &data_;
582 }
583
584 private:
585 // This Data struct workaround is to avoid initializing all the members
586 // in Data during construction of this object, since this object is always
587 // constructed, even when tracing is disabled. If the members of Data were
588 // members of this class instead, compiler warnings occur about potential
589 // uninitialized accesses.
590 struct Data {
592 const char* name;
593 uint64_t event_handle;
594 };
597};
598
599#ifdef V8_RUNTIME_CALL_STATS
600// Do not use directly.
601class CallStatsScopedTracer {
602 public:
603 CallStatsScopedTracer() : p_data_(nullptr) {}
604 ~CallStatsScopedTracer() {
605 if (V8_UNLIKELY(p_data_ && *data_.category_group_enabled)) {
606 AddEndTraceEvent();
607 }
608 }
609
610 void Initialize(v8::internal::Isolate* isolate,
611 const uint8_t* category_group_enabled, const char* name);
612
613 private:
614 void AddEndTraceEvent();
615 struct Data {
616 const uint8_t* category_group_enabled;
617 const char* name;
619 };
620 bool has_parent_scope_;
621 Data* p_data_;
622 Data data_;
623};
624#endif // V8_RUNTIME_CALL_STATS
625
626} // namespace tracing
627} // namespace internal
628} // namespace v8
629
630#else // defined(V8_USE_PERFETTO)
631
632#ifdef V8_RUNTIME_CALL_STATS
633
634#define TRACE_EVENT_CALL_STATS_SCOPED(isolate, category, name) \
635 struct PERFETTO_UID(ScopedEvent) { \
636 struct ScopedStats { \
637 ScopedStats(v8::internal::Isolate* isolate_arg, int) { \
638 TRACE_EVENT_BEGIN(category, name, [&](perfetto::EventContext) { \
639 isolate_ = isolate_arg; \
640 internal::RuntimeCallStats* table = \
641 isolate_->counters()->runtime_call_stats(); \
642 has_parent_scope_ = table->InUse(); \
643 if (!has_parent_scope_) table->Reset(); \
644 }); \
645 } \
646 ~ScopedStats() { \
647 TRACE_EVENT_END(category, [&](perfetto::EventContext ctx) { \
648 if (!has_parent_scope_ && isolate_) { \
649 /* TODO(skyostil): Write as typed event instead of JSON */ \
650 auto value = v8::tracing::TracedValue::Create(); \
651 isolate_->counters()->runtime_call_stats()->Dump(value.get()); \
652 auto annotation = ctx.event()->add_debug_annotations(); \
653 annotation->set_name("runtime-call-stats"); \
654 value->Add(annotation); \
655 } \
656 }); \
657 } \
658 v8::internal::Isolate* isolate_ = nullptr; \
659 bool has_parent_scope_ = false; \
660 } stats; \
661 } PERFETTO_UID(scoped_event) { \
662 { isolate, 0 } \
663 }
664#else // V8_RUNTIME_CALL_STATS
665#define TRACE_EVENT_CALL_STATS_SCOPED(isolate, category, name)
666#endif // V8_RUNTIME_CALL_STATS
667#endif // defined(V8_USE_PERFETTO)
668
669#endif // V8_TRACING_TRACE_EVENT_H_
uint8_t data_[MAX_STACK_LENGTH]
const char * name
Definition builtins.cc:39
virtual uint64_t AddTraceEventWithTimestamp(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, int64_t timestamp)
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)
void Initialize(const uint8_t *category_group_enabled, const char *name, uint64_t event_handle)
static V8_EXPORT_PRIVATE v8::TracingController * GetTracingController()
WithScope(const char *scope, uint64_t raw_id)
TraceID(int raw_id, unsigned int *flags)
TraceID(int64_t raw_id, unsigned int *flags)
TraceID(unsigned int raw_id, unsigned int *flags)
TraceID(signed char raw_id, unsigned int *flags)
TraceID(const void *raw_id, unsigned int *flags)
const char * scope() const
TraceID(unsigned char raw_id, unsigned int *flags)
TraceID(uint64_t raw_id, unsigned int *flags)
TraceID(WithScope scoped_id, unsigned int *flags)
TraceID(uint16_t raw_id, unsigned int *flags)
TraceID(int16_t raw_id, unsigned int *flags)
Isolate * isolate
Atomic8 Relaxed_Load(volatile const Atomic8 *ptr)
Definition atomicops.h:234
char Atomic8
Definition atomicops.h:57
static V8_INLINE uint64_t AddTraceEventImpl(char phase, const uint8_t *category_group_enabled, 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, unsigned int flags)
static V8_INLINE uint64_t AddTraceEvent(char phase, const uint8_t *category_group_enabled, const char *name, const char *scope, uint64_t id, uint64_t bind_id, unsigned int flags)
const decltype(nullptr) kGlobalScope
static V8_INLINE void SetTraceValue(T arg, unsigned char *type, uint64_t *value)
const uint64_t kNoId
static V8_INLINE uint64_t AddTraceEventWithTimestamp(char phase, const uint8_t *category_group_enabled, const char *name, const char *scope, uint64_t id, uint64_t bind_id, unsigned int flags, int64_t timestamp)
static V8_INLINE uint64_t AddTraceEventWithTimestampImpl(char phase, const uint8_t *category_group_enabled, 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, unsigned int flags, int64_t timestamp)
too high values may cause the compiler to set high thresholds for inlining to as much as possible avoid inlined allocation of objects that cannot escape trace load stores from virtual maglev objects use TurboFan fast string builder analyze liveness of environment slots and zap dead values trace TurboFan load elimination emit data about basic block usage in builtins to this enable builtin reordering when run mksnapshot flag for emit warnings when applying builtin profile data verify register allocation in TurboFan randomly schedule instructions to stress dependency tracking enable store store elimination in TurboFan rewrite far to near simulate GC compiler thread race related to allow float parameters to be passed in simulator mode JS Wasm Run additional turbo_optimize_inlined_js_wasm_wrappers enable experimental feedback collection in generic lowering enable Turboshaft s WasmLoadElimination enable Turboshaft s low level load elimination for JS enable Turboshaft s escape analysis for string concatenation use enable Turbolev features that we want to ship in the not too far future trace individual Turboshaft reduction steps trace intermediate Turboshaft reduction steps invocation count threshold for early optimization Enables optimizations which favor memory size over execution speed Enables sampling allocation profiler with X as a sample interval min size of a semi the new space consists of two semi spaces max size of the Collect garbage after Collect garbage after keeps maps alive for< n > old space garbage collections print one detailed trace line in name
Definition flags.cc:2086
Flag flags[]
Definition flags.cc:3797
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define V8_EXPORT_PRIVATE
Definition macros.h:460
#define TRACE_VALUE_TYPE_STRING
#define TRACE_VALUE_TYPE_BOOL
#define TRACE_VALUE_TYPE_POINTER
#define TRACE_VALUE_TYPE_COPY_STRING
#define TRACE_VALUE_TYPE_INT
#define TRACE_VALUE_TYPE_UINT
#define TRACE_VALUE_TYPE_DOUBLE
#define TRACE_VALUE_TYPE_CONVERTABLE
#define TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION
#define TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP
CategoryGroupEnabledFlags
Definition trace-event.h:35
@ kEnabledForEventCallback_CategoryGroupEnabledFlags
Definition trace-event.h:39
@ kEnabledForRecording_CategoryGroupEnabledFlags
Definition trace-event.h:37
@ kEnabledForETWExport_CategoryGroupEnabledFlags
Definition trace-event.h:41
#define INTERNAL_DECLARE_SET_TRACE_VALUE(actual_type, value_type_id)
#define TRACE_EVENT_API_ADD_TRACE_EVENT
#define V8_INLINE
Definition v8config.h:500
#define V8_UNLIKELY(condition)
Definition v8config.h:660