Line data Source code
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 : v8::internal::tracing::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 :
62 : ////////////////////////////////////////////////////////////////////////////////
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 :
134 : ////////////////////////////////////////////////////////////////////////////////
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 : #define TRACE_EVENT_CALL_STATS_SCOPED(isolate, category_group, name) \
274 : INTERNAL_TRACE_EVENT_CALL_STATS_SCOPED(isolate, category_group, name)
275 :
276 : #define INTERNAL_TRACE_EVENT_CALL_STATS_SCOPED(isolate, category_group, name) \
277 : INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
278 : v8::internal::tracing::CallStatsScopedTracer INTERNAL_TRACE_EVENT_UID( \
279 : tracer); \
280 : if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
281 : INTERNAL_TRACE_EVENT_UID(tracer) \
282 : .Initialize(isolate, INTERNAL_TRACE_EVENT_UID(category_group_enabled), \
283 : name); \
284 : }
285 :
286 : namespace v8 {
287 : namespace internal {
288 :
289 : class Isolate;
290 :
291 : namespace tracing {
292 :
293 : // Specify these values when the corresponding argument of AddTraceEvent is not
294 : // used.
295 : const int kZeroNumArgs = 0;
296 : const decltype(nullptr) kGlobalScope = nullptr;
297 : const uint64_t kNoId = 0;
298 :
299 : class TraceEventHelper {
300 : public:
301 : V8_EXPORT_PRIVATE static v8::TracingController* GetTracingController();
302 : };
303 :
304 : // TraceID encapsulates an ID that can either be an integer or pointer. Pointers
305 : // are by default mangled with the Process ID so that they are unlikely to
306 : // collide when the same pointer is used on different processes.
307 : class TraceID {
308 : public:
309 : class WithScope {
310 : public:
311 : WithScope(const char* scope, uint64_t raw_id)
312 : : scope_(scope), raw_id_(raw_id) {}
313 : uint64_t raw_id() const { return raw_id_; }
314 : const char* scope() const { return scope_; }
315 :
316 : private:
317 : const char* scope_ = nullptr;
318 : uint64_t raw_id_;
319 : };
320 :
321 : class DontMangle {
322 : public:
323 : explicit DontMangle(const void* raw_id)
324 : : raw_id_(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(raw_id))) {}
325 : explicit DontMangle(uint64_t raw_id) : raw_id_(raw_id) {}
326 : explicit DontMangle(unsigned int raw_id) : raw_id_(raw_id) {}
327 : explicit DontMangle(uint16_t raw_id) : raw_id_(raw_id) {}
328 : explicit DontMangle(unsigned char raw_id) : raw_id_(raw_id) {}
329 : explicit DontMangle(int64_t raw_id)
330 : : raw_id_(static_cast<uint64_t>(raw_id)) {}
331 : explicit DontMangle(int raw_id) : raw_id_(static_cast<uint64_t>(raw_id)) {}
332 : explicit DontMangle(int16_t raw_id)
333 : : raw_id_(static_cast<uint64_t>(raw_id)) {}
334 : explicit DontMangle(signed char raw_id)
335 : : raw_id_(static_cast<uint64_t>(raw_id)) {}
336 : explicit DontMangle(WithScope scoped_id)
337 : : scope_(scoped_id.scope()), raw_id_(scoped_id.raw_id()) {}
338 : const char* scope() const { return scope_; }
339 : uint64_t raw_id() const { return raw_id_; }
340 :
341 : private:
342 : const char* scope_ = nullptr;
343 : uint64_t raw_id_;
344 : };
345 :
346 : class ForceMangle {
347 : public:
348 : explicit ForceMangle(uint64_t raw_id) : raw_id_(raw_id) {}
349 : explicit ForceMangle(unsigned int raw_id) : raw_id_(raw_id) {}
350 : explicit ForceMangle(uint16_t raw_id) : raw_id_(raw_id) {}
351 : explicit ForceMangle(unsigned char raw_id) : raw_id_(raw_id) {}
352 : explicit ForceMangle(int64_t raw_id)
353 : : raw_id_(static_cast<uint64_t>(raw_id)) {}
354 : explicit ForceMangle(int raw_id) : raw_id_(static_cast<uint64_t>(raw_id)) {}
355 : explicit ForceMangle(int16_t raw_id)
356 : : raw_id_(static_cast<uint64_t>(raw_id)) {}
357 : explicit ForceMangle(signed char raw_id)
358 : : raw_id_(static_cast<uint64_t>(raw_id)) {}
359 : uint64_t raw_id() const { return raw_id_; }
360 :
361 : private:
362 : uint64_t raw_id_;
363 : };
364 :
365 : TraceID(const void* raw_id, unsigned int* flags)
366 0 : : raw_id_(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(raw_id))) {
367 : *flags |= TRACE_EVENT_FLAG_MANGLE_ID;
368 : }
369 : TraceID(ForceMangle raw_id, unsigned int* flags) : raw_id_(raw_id.raw_id()) {
370 : *flags |= TRACE_EVENT_FLAG_MANGLE_ID;
371 : }
372 : TraceID(DontMangle maybe_scoped_id, unsigned int* flags)
373 : : scope_(maybe_scoped_id.scope()), raw_id_(maybe_scoped_id.raw_id()) {}
374 : TraceID(uint64_t raw_id, unsigned int* flags) : raw_id_(raw_id) {
375 : (void)flags;
376 : }
377 13 : TraceID(unsigned int raw_id, unsigned int* flags) : raw_id_(raw_id) {
378 : (void)flags;
379 : }
380 : TraceID(uint16_t raw_id, unsigned int* flags) : raw_id_(raw_id) {
381 : (void)flags;
382 : }
383 : TraceID(unsigned char raw_id, unsigned int* flags) : raw_id_(raw_id) {
384 : (void)flags;
385 : }
386 : TraceID(int64_t raw_id, unsigned int* flags)
387 : : raw_id_(static_cast<uint64_t>(raw_id)) {
388 : (void)flags;
389 : }
390 : TraceID(int raw_id, unsigned int* flags)
391 : : raw_id_(static_cast<uint64_t>(raw_id)) {
392 : (void)flags;
393 : }
394 : TraceID(int16_t raw_id, unsigned int* flags)
395 : : raw_id_(static_cast<uint64_t>(raw_id)) {
396 : (void)flags;
397 : }
398 : TraceID(signed char raw_id, unsigned int* flags)
399 : : raw_id_(static_cast<uint64_t>(raw_id)) {
400 : (void)flags;
401 : }
402 : TraceID(WithScope scoped_id, unsigned int* flags)
403 : : scope_(scoped_id.scope()), raw_id_(scoped_id.raw_id()) {}
404 :
405 : uint64_t raw_id() const { return raw_id_; }
406 : const char* scope() const { return scope_; }
407 :
408 : private:
409 : const char* scope_ = nullptr;
410 : uint64_t raw_id_;
411 : };
412 :
413 : // Simple union to store various types as uint64_t.
414 : union TraceValueUnion {
415 : bool as_bool;
416 : uint64_t as_uint;
417 : int64_t as_int;
418 : double as_double;
419 : const void* as_pointer;
420 : const char* as_string;
421 : };
422 :
423 : // Simple container for const char* that should be copied instead of retained.
424 : class TraceStringWithCopy {
425 : public:
426 : explicit TraceStringWithCopy(const char* str) : str_(str) {}
427 : operator const char*() const { return str_; }
428 :
429 : private:
430 : const char* str_;
431 : };
432 :
433 : static V8_INLINE uint64_t AddTraceEventImpl(
434 : char phase, const uint8_t* category_group_enabled, const char* name,
435 : const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args,
436 : const char** arg_names, const uint8_t* arg_types,
437 : const uint64_t* arg_values, unsigned int flags) {
438 2732 : std::unique_ptr<ConvertableToTraceFormat> arg_convertables[2];
439 15 : if (num_args > 0 && arg_types[0] == TRACE_VALUE_TYPE_CONVERTABLE) {
440 15 : arg_convertables[0].reset(reinterpret_cast<ConvertableToTraceFormat*>(
441 15 : static_cast<intptr_t>(arg_values[0])));
442 : }
443 10 : if (num_args > 1 && arg_types[1] == TRACE_VALUE_TYPE_CONVERTABLE) {
444 0 : arg_convertables[1].reset(reinterpret_cast<ConvertableToTraceFormat*>(
445 0 : static_cast<intptr_t>(arg_values[1])));
446 : }
447 : DCHECK_LE(num_args, 2);
448 : v8::TracingController* controller =
449 673 : v8::internal::tracing::TraceEventHelper::GetTracingController();
450 10 : return controller->AddTraceEvent(phase, category_group_enabled, name, scope,
451 : id, bind_id, num_args, arg_names, arg_types,
452 693 : arg_values, arg_convertables, flags);
453 : }
454 :
455 : static V8_INLINE uint64_t AddTraceEventWithTimestampImpl(
456 : char phase, const uint8_t* category_group_enabled, const char* name,
457 : const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args,
458 : const char** arg_names, const uint8_t* arg_types,
459 : const uint64_t* arg_values, unsigned int flags, int64_t timestamp) {
460 100 : std::unique_ptr<ConvertableToTraceFormat> arg_convertables[2];
461 : if (num_args > 0 && arg_types[0] == TRACE_VALUE_TYPE_CONVERTABLE) {
462 : arg_convertables[0].reset(reinterpret_cast<ConvertableToTraceFormat*>(
463 : static_cast<intptr_t>(arg_values[0])));
464 : }
465 : if (num_args > 1 && arg_types[1] == TRACE_VALUE_TYPE_CONVERTABLE) {
466 : arg_convertables[1].reset(reinterpret_cast<ConvertableToTraceFormat*>(
467 : static_cast<intptr_t>(arg_values[1])));
468 : }
469 : DCHECK_LE(num_args, 2);
470 : v8::TracingController* controller =
471 25 : v8::internal::tracing::TraceEventHelper::GetTracingController();
472 : return controller->AddTraceEventWithTimestamp(
473 : phase, category_group_enabled, name, scope, id, bind_id, num_args,
474 25 : arg_names, arg_types, arg_values, arg_convertables, flags, timestamp);
475 : }
476 :
477 : // Define SetTraceValue for each allowed type. It stores the type and
478 : // value in the return arguments. This allows this API to avoid declaring any
479 : // structures so that it is portable to third_party libraries.
480 : #define INTERNAL_DECLARE_SET_TRACE_VALUE(actual_type, union_member, \
481 : value_type_id) \
482 : static V8_INLINE void SetTraceValue(actual_type arg, unsigned char* type, \
483 : uint64_t* value) { \
484 : TraceValueUnion type_value; \
485 : type_value.union_member = arg; \
486 : *type = value_type_id; \
487 : *value = type_value.as_uint; \
488 : }
489 : // Simpler form for int types that can be safely casted.
490 : #define INTERNAL_DECLARE_SET_TRACE_VALUE_INT(actual_type, value_type_id) \
491 : static V8_INLINE void SetTraceValue(actual_type arg, unsigned char* type, \
492 : uint64_t* value) { \
493 : *type = value_type_id; \
494 : *value = static_cast<uint64_t>(arg); \
495 : }
496 :
497 10 : INTERNAL_DECLARE_SET_TRACE_VALUE_INT(uint64_t, TRACE_VALUE_TYPE_UINT)
498 5 : INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned int, TRACE_VALUE_TYPE_UINT)
499 5 : INTERNAL_DECLARE_SET_TRACE_VALUE_INT(uint16_t, TRACE_VALUE_TYPE_UINT)
500 5 : INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned char, TRACE_VALUE_TYPE_UINT)
501 5 : INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int64_t, TRACE_VALUE_TYPE_INT)
502 50 : INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int, TRACE_VALUE_TYPE_INT)
503 5 : INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int16_t, TRACE_VALUE_TYPE_INT)
504 5 : INTERNAL_DECLARE_SET_TRACE_VALUE_INT(signed char, TRACE_VALUE_TYPE_INT)
505 10 : INTERNAL_DECLARE_SET_TRACE_VALUE(bool, as_bool, TRACE_VALUE_TYPE_BOOL)
506 25 : INTERNAL_DECLARE_SET_TRACE_VALUE(double, as_double, TRACE_VALUE_TYPE_DOUBLE)
507 5 : INTERNAL_DECLARE_SET_TRACE_VALUE(const void*, as_pointer,
508 : TRACE_VALUE_TYPE_POINTER)
509 55 : INTERNAL_DECLARE_SET_TRACE_VALUE(const char*, as_string,
510 : TRACE_VALUE_TYPE_STRING)
511 10 : INTERNAL_DECLARE_SET_TRACE_VALUE(const TraceStringWithCopy&, as_string,
512 : TRACE_VALUE_TYPE_COPY_STRING)
513 :
514 : #undef INTERNAL_DECLARE_SET_TRACE_VALUE
515 : #undef INTERNAL_DECLARE_SET_TRACE_VALUE_INT
516 :
517 : static V8_INLINE void SetTraceValue(ConvertableToTraceFormat* convertable_value,
518 : unsigned char* type, uint64_t* value) {
519 43 : *type = TRACE_VALUE_TYPE_CONVERTABLE;
520 43 : *value = static_cast<uint64_t>(reinterpret_cast<intptr_t>(convertable_value));
521 : }
522 :
523 : template <typename T>
524 : static V8_INLINE typename std::enable_if<
525 : std::is_convertible<T*, ConvertableToTraceFormat*>::value>::type
526 : SetTraceValue(std::unique_ptr<T> ptr, unsigned char* type, uint64_t* value) {
527 5 : SetTraceValue(ptr.release(), type, value);
528 : }
529 :
530 : // These AddTraceEvent template
531 : // function is defined here instead of in the macro, because the arg_values
532 : // could be temporary objects, such as std::string. In order to store
533 : // pointers to the internal c_str and pass through to the tracing API,
534 : // the arg_values must live throughout these procedures.
535 :
536 : static V8_INLINE uint64_t AddTraceEvent(char phase,
537 : const uint8_t* category_group_enabled,
538 : const char* name, const char* scope,
539 : uint64_t id, uint64_t bind_id,
540 : unsigned int flags) {
541 : return TRACE_EVENT_API_ADD_TRACE_EVENT(phase, category_group_enabled, name,
542 : scope, id, bind_id, kZeroNumArgs,
543 : nullptr, nullptr, nullptr, flags);
544 : }
545 :
546 : template <class ARG1_TYPE>
547 : static V8_INLINE uint64_t AddTraceEvent(
548 : char phase, const uint8_t* category_group_enabled, const char* name,
549 : const char* scope, uint64_t id, uint64_t bind_id, unsigned int flags,
550 : const char* arg1_name, ARG1_TYPE&& arg1_val) {
551 : const int num_args = 1;
552 : uint8_t arg_type;
553 : uint64_t arg_value;
554 15 : SetTraceValue(std::forward<ARG1_TYPE>(arg1_val), &arg_type, &arg_value);
555 : return TRACE_EVENT_API_ADD_TRACE_EVENT(
556 : phase, category_group_enabled, name, scope, id, bind_id, num_args,
557 : &arg1_name, &arg_type, &arg_value, flags);
558 : }
559 :
560 : template <class ARG1_TYPE, class ARG2_TYPE>
561 : static V8_INLINE uint64_t AddTraceEvent(
562 : char phase, const uint8_t* category_group_enabled, const char* name,
563 : const char* scope, uint64_t id, uint64_t bind_id, unsigned int flags,
564 : const char* arg1_name, ARG1_TYPE&& arg1_val, const char* arg2_name,
565 : ARG2_TYPE&& arg2_val) {
566 : const int num_args = 2;
567 45 : const char* arg_names[2] = {arg1_name, arg2_name};
568 : unsigned char arg_types[2];
569 : uint64_t arg_values[2];
570 5 : SetTraceValue(std::forward<ARG1_TYPE>(arg1_val), &arg_types[0],
571 : &arg_values[0]);
572 0 : SetTraceValue(std::forward<ARG2_TYPE>(arg2_val), &arg_types[1],
573 : &arg_values[1]);
574 : return TRACE_EVENT_API_ADD_TRACE_EVENT(
575 : phase, category_group_enabled, name, scope, id, bind_id, num_args,
576 : arg_names, arg_types, arg_values, flags);
577 : }
578 :
579 : static V8_INLINE uint64_t AddTraceEventWithTimestamp(
580 : char phase, const uint8_t* category_group_enabled, const char* name,
581 : const char* scope, uint64_t id, uint64_t bind_id, unsigned int flags,
582 : int64_t timestamp) {
583 : return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP(
584 : phase, category_group_enabled, name, scope, id, bind_id, kZeroNumArgs,
585 : nullptr, nullptr, nullptr, flags, timestamp);
586 : }
587 :
588 : template <class ARG1_TYPE>
589 : static V8_INLINE uint64_t AddTraceEventWithTimestamp(
590 : char phase, const uint8_t* category_group_enabled, const char* name,
591 : const char* scope, uint64_t id, uint64_t bind_id, unsigned int flags,
592 : int64_t timestamp, const char* arg1_name, ARG1_TYPE&& arg1_val) {
593 : const int num_args = 1;
594 : uint8_t arg_type;
595 : uint64_t arg_value;
596 : SetTraceValue(std::forward<ARG1_TYPE>(arg1_val), &arg_type, &arg_value);
597 : return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP(
598 : phase, category_group_enabled, name, scope, id, bind_id, num_args,
599 : &arg1_name, &arg_type, &arg_value, flags, timestamp);
600 : }
601 :
602 : template <class ARG1_TYPE, class ARG2_TYPE>
603 : static V8_INLINE uint64_t AddTraceEventWithTimestamp(
604 : char phase, const uint8_t* category_group_enabled, const char* name,
605 : const char* scope, uint64_t id, uint64_t bind_id, unsigned int flags,
606 : int64_t timestamp, const char* arg1_name, ARG1_TYPE&& arg1_val,
607 : const char* arg2_name, ARG2_TYPE&& arg2_val) {
608 : const int num_args = 2;
609 5 : const char* arg_names[2] = {arg1_name, arg2_name};
610 : unsigned char arg_types[2];
611 : uint64_t arg_values[2];
612 : SetTraceValue(std::forward<ARG1_TYPE>(arg1_val), &arg_types[0],
613 : &arg_values[0]);
614 : SetTraceValue(std::forward<ARG2_TYPE>(arg2_val), &arg_types[1],
615 : &arg_values[1]);
616 : return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP(
617 : phase, category_group_enabled, name, scope, id, bind_id, num_args,
618 : arg_names, arg_types, arg_values, flags, timestamp);
619 : }
620 :
621 : // Used by TRACE_EVENTx macros. Do not use directly.
622 : class ScopedTracer {
623 : public:
624 : // Note: members of data_ intentionally left uninitialized. See Initialize.
625 35419883 : ScopedTracer() : p_data_(nullptr) {}
626 :
627 70821370 : ~ScopedTracer() {
628 35411255 : if (p_data_ && base::Relaxed_Load(reinterpret_cast<const base::Atomic8*>(
629 570 : data_.category_group_enabled))) {
630 910 : TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(
631 910 : data_.category_group_enabled, data_.name, data_.event_handle);
632 : }
633 35410685 : }
634 :
635 : void Initialize(const uint8_t* category_group_enabled, const char* name,
636 : uint64_t event_handle) {
637 570 : data_.category_group_enabled = category_group_enabled;
638 570 : data_.name = name;
639 570 : data_.event_handle = event_handle;
640 570 : p_data_ = &data_;
641 : }
642 :
643 : private:
644 : // This Data struct workaround is to avoid initializing all the members
645 : // in Data during construction of this object, since this object is always
646 : // constructed, even when tracing is disabled. If the members of Data were
647 : // members of this class instead, compiler warnings occur about potential
648 : // uninitialized accesses.
649 : struct Data {
650 : const uint8_t* category_group_enabled;
651 : const char* name;
652 : uint64_t event_handle;
653 : };
654 : Data* p_data_;
655 : Data data_;
656 : };
657 :
658 : // Do not use directly.
659 : class CallStatsScopedTracer {
660 : public:
661 1075356 : CallStatsScopedTracer() : p_data_(nullptr) {}
662 1075357 : ~CallStatsScopedTracer() {
663 1075357 : if (V8_UNLIKELY(p_data_ && *data_.category_group_enabled)) {
664 5 : AddEndTraceEvent();
665 : }
666 : }
667 :
668 : void Initialize(v8::internal::Isolate* isolate,
669 : const uint8_t* category_group_enabled, const char* name);
670 :
671 : private:
672 : void AddEndTraceEvent();
673 : struct Data {
674 : const uint8_t* category_group_enabled;
675 : const char* name;
676 : v8::internal::Isolate* isolate;
677 : };
678 : bool has_parent_scope_;
679 : Data* p_data_;
680 : Data data_;
681 : };
682 :
683 : } // namespace tracing
684 : } // namespace internal
685 : } // namespace v8
686 :
687 : #endif // V8_TRACING_TRACE_EVENT_H_
|