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 2020 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_HEAP_CPPGC_TRACE_EVENT_H_
6#define V8_HEAP_CPPGC_TRACE_EVENT_H_
7
8#if !CPPGC_IS_STANDALONE
11#else
12// This is a subset of stc/tracing/trace-event.h required to support
13// tracing in the cppgc standalone library using TracingController.
14
16#include "src/base/atomicops.h"
17#include "src/base/macros.h"
19
20// This header file defines implementation details of how the trace macros in
21// trace-event-no-erfetto.h collect and store trace events. Anything not
22// implementation-specific should go in trace_macros_common.h instead of here.
23
24// The pointer returned from GetCategoryGroupEnabled() points to a
25// value with zero or more of the following bits. Used in this class only.
26// The TRACE_EVENT macros should only use the value as a bool.
27// These values must be in sync with macro values in trace_log.h in
28// chromium.
30 // Category group enabled for the recording mode.
32 // Category group enabled by SetEventCallbackEnabled().
34};
35
36#define INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE() \
37 TRACE_EVENT_API_LOAD_CATEGORY_GROUP_ENABLED() & \
38 (kEnabledForRecording_CategoryGroupEnabledFlags | \
39 kEnabledForEventCallback_CategoryGroupEnabledFlags)
40
42// Implementation specific tracing API definitions.
43
44// Get a pointer to the enabled state of the given trace category. Only
45// long-lived literal strings should be given as the category group. The
46// returned pointer can be held permanently in a local static for example. If
47// the unsigned char is non-zero, tracing is enabled. If tracing is enabled,
48// TRACE_EVENT_API_ADD_TRACE_EVENT can be called. It's OK if tracing is disabled
49// between the load of the tracing state and the call to
50// TRACE_EVENT_API_ADD_TRACE_EVENT, because this flag only provides an early out
51// for best performance when tracing is disabled.
52// const uint8_t*
53// TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(const char* category_group)
54#define TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED \
55 platform->GetTracingController()->GetCategoryGroupEnabled
56
57// Add a trace event to the platform tracing system.
58// uint64_t TRACE_EVENT_API_ADD_TRACE_EVENT(
59// char phase,
60// const uint8_t* category_group_enabled,
61// const char* name,
62// const char* scope,
63// uint64_t id,
64// uint64_t bind_id,
65// int num_args,
66// const char** arg_names,
67// const uint8_t* arg_types,
68// const uint64_t* arg_values,
69// unsigned int flags)
70#define TRACE_EVENT_API_ADD_TRACE_EVENT cppgc::internal::AddTraceEventImpl
71
72// Defines atomic operations used internally by the tracing system.
73// Acquire/release barriers are important here: crbug.com/1330114#c8.
74#define TRACE_EVENT_API_ATOMIC_WORD v8::base::AtomicWord
75#define TRACE_EVENT_API_ATOMIC_LOAD(var) v8::base::Acquire_Load(&(var))
76#define TRACE_EVENT_API_ATOMIC_STORE(var, value) \
77 v8::base::Release_Store(&(var), (value))
78// This load can be Relaxed because it's reading the state of
79// `category_group_enabled` and not inferring other variable's state from the
80// result.
81#define TRACE_EVENT_API_LOAD_CATEGORY_GROUP_ENABLED() \
82 v8::base::Relaxed_Load(reinterpret_cast<const v8::base::Atomic8*>( \
83 INTERNAL_TRACE_EVENT_UID(category_group_enabled)))
84
86
87// Implementation detail: trace event macros create temporary variables
88// to keep instrumentation overhead low. These macros give each temporary
89// variable a unique name based on the line number to prevent name collisions.
90#define INTERNAL_TRACE_EVENT_UID3(a, b) cppgc_trace_event_unique_##a##b
91#define INTERNAL_TRACE_EVENT_UID2(a, b) INTERNAL_TRACE_EVENT_UID3(a, b)
92#define INTERNAL_TRACE_EVENT_UID(name_prefix) \
93 INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__)
94
95// Implementation detail: internal macro to create static category.
96// No barriers are needed, because this code is designed to operate safely
97// even when the unsigned char* points to garbage data (which may be the case
98// on processors without cache coherency).
99#define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES( \
100 category_group, atomic, category_group_enabled) \
101 category_group_enabled = \
102 reinterpret_cast<const uint8_t*>(TRACE_EVENT_API_ATOMIC_LOAD(atomic)); \
103 if (!category_group_enabled) { \
104 category_group_enabled = \
105 TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_group); \
106 TRACE_EVENT_API_ATOMIC_STORE( \
107 atomic, reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD>( \
108 category_group_enabled)); \
109 }
110
111#define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group) \
112 static TRACE_EVENT_API_ATOMIC_WORD INTERNAL_TRACE_EVENT_UID(atomic) = 0; \
113 const uint8_t* INTERNAL_TRACE_EVENT_UID(category_group_enabled); \
114 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES( \
115 category_group, INTERNAL_TRACE_EVENT_UID(atomic), \
116 INTERNAL_TRACE_EVENT_UID(category_group_enabled));
117
118// Implementation detail: internal macro to create static category and add
119// event if the category is enabled.
120#define INTERNAL_TRACE_EVENT_ADD(phase, category_group, name, flags, ...) \
121 DCHECK_NOT_NULL(name); \
122 do { \
123 cppgc::Platform* platform = stats_collector_->platform_; \
124 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
125 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
126 cppgc::internal::AddTraceEvent( \
127 phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
128 nullptr /* scope */, 0 /* id */, 0 /* bind_id */, flags, platform, \
129 ##__VA_ARGS__); \
130 } \
131 } while (false)
132
133namespace cppgc {
134namespace internal {
135
137
138class TraceEventHelper {
139 public:
140 V8_EXPORT_PRIVATE static TracingController* GetTracingController();
141};
142
143static V8_INLINE uint64_t AddTraceEventImpl(
144 char phase, const uint8_t* category_group_enabled, const char* name,
145 const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args,
146 const char** arg_names, const uint8_t* arg_types,
147 const uint64_t* arg_values, unsigned int flags, Platform* platform) {
148 std::unique_ptr<ConvertableToTraceFormat> arg_convertables[2];
149 if (num_args > 0 && arg_types[0] == TRACE_VALUE_TYPE_CONVERTABLE) {
150 arg_convertables[0].reset(reinterpret_cast<ConvertableToTraceFormat*>(
151 static_cast<intptr_t>(arg_values[0])));
152 }
153 if (num_args > 1 && arg_types[1] == TRACE_VALUE_TYPE_CONVERTABLE) {
154 arg_convertables[1].reset(reinterpret_cast<ConvertableToTraceFormat*>(
155 static_cast<intptr_t>(arg_values[1])));
156 }
157 DCHECK_LE(num_args, 2);
158 TracingController* controller = platform->GetTracingController();
159 return controller->AddTraceEvent(phase, category_group_enabled, name, scope,
160 id, bind_id, num_args, arg_names, arg_types,
161 arg_values, arg_convertables, flags);
162}
163
164// Define SetTraceValue for each allowed type. It stores the type and value
165// in the return arguments. This allows this API to avoid declaring any
166// structures so that it is portable to third_party libraries.
167// This is the base implementation for integer types (including bool) and enums.
168template <typename T>
169static V8_INLINE typename std::enable_if<
170 std::is_integral<T>::value || std::is_enum<T>::value, void>::type
171SetTraceValue(T arg, unsigned char* type, uint64_t* value) {
172 *type = std::is_same<T, bool>::value
174 : std::is_signed<T>::value ? TRACE_VALUE_TYPE_INT
176 *value = static_cast<uint64_t>(arg);
177}
178
179#define INTERNAL_DECLARE_SET_TRACE_VALUE(actual_type, value_type_id) \
180 static V8_INLINE void SetTraceValue(actual_type arg, unsigned char* type, \
181 uint64_t* value) { \
182 *type = value_type_id; \
183 *value = 0; \
184 static_assert(sizeof(arg) <= sizeof(*value)); \
185 memcpy(value, &arg, sizeof(arg)); \
186 }
189#undef INTERNAL_DECLARE_SET_TRACE_VALUE
190
191// These AddTraceEvent template functions are defined here instead of in
192// the macro, because the arg_values could be temporary objects, such as
193// std::string. In order to store pointers to the internal c_str and pass
194// through to the tracing API, the arg_values must live throughout these
195// procedures.
196
197static V8_INLINE uint64_t AddTraceEvent(char phase,
198 const uint8_t* category_group_enabled,
199 const char* name, const char* scope,
200 uint64_t id, uint64_t bind_id,
201 unsigned int flags,
202 Platform* platform) {
204 phase, category_group_enabled, name, scope, id, bind_id, 0 /* num_args */,
205 nullptr, nullptr, nullptr, flags, platform);
206}
207
208template <class ARG1_TYPE>
209static V8_INLINE uint64_t AddTraceEvent(
210 char phase, const uint8_t* category_group_enabled, const char* name,
211 const char* scope, uint64_t id, uint64_t bind_id, unsigned int flags,
212 Platform* platform, const char* arg1_name, ARG1_TYPE&& arg1_val) {
213 const int num_args = 1;
214 uint8_t arg_type;
215 uint64_t arg_value;
216 SetTraceValue(std::forward<ARG1_TYPE>(arg1_val), &arg_type, &arg_value);
218 phase, category_group_enabled, name, scope, id, bind_id, num_args,
219 &arg1_name, &arg_type, &arg_value, flags, platform);
220}
221
222template <class ARG1_TYPE, class ARG2_TYPE>
223static V8_INLINE uint64_t AddTraceEvent(
224 char phase, const uint8_t* category_group_enabled, const char* name,
225 const char* scope, uint64_t id, uint64_t bind_id, unsigned int flags,
226 Platform* platform, const char* arg1_name, ARG1_TYPE&& arg1_val,
227 const char* arg2_name, ARG2_TYPE&& arg2_val) {
228 const int num_args = 2;
229 const char* arg_names[2] = {arg1_name, arg2_name};
230 unsigned char arg_types[2];
231 uint64_t arg_values[2];
232 SetTraceValue(std::forward<ARG1_TYPE>(arg1_val), &arg_types[0],
233 &arg_values[0]);
234 SetTraceValue(std::forward<ARG2_TYPE>(arg2_val), &arg_types[1],
235 &arg_values[1]);
237 phase, category_group_enabled, name, scope, id, bind_id, num_args,
238 arg_names, arg_types, arg_values, flags, platform);
239}
240
241} // namespace internal
242} // namespace cppgc
243
244#endif // !CPPGC_IS_STANDALONE
245
246#endif // V8_HEAP_CPPGC_TRACE_EVENT_H_
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)
v8::TracingController TracingController
Definition platform.h:26
#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_INT
#define TRACE_VALUE_TYPE_UINT
#define TRACE_VALUE_TYPE_DOUBLE
#define TRACE_VALUE_TYPE_CONVERTABLE
CategoryGroupEnabledFlags
Definition trace-event.h:35
@ kEnabledForEventCallback_CategoryGroupEnabledFlags
Definition trace-event.h:39
@ kEnabledForRecording_CategoryGroupEnabledFlags
Definition trace-event.h:37
#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