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 SRC_TRACING_TRACE_EVENT_H_
6 : #define SRC_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 : *INTERNAL_TRACE_EVENT_UID(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::GetCurrentPlatform() \
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 : // Set the duration field of a COMPLETE trace event.
100 : // void TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(
101 : // const uint8_t* category_group_enabled,
102 : // const char* name,
103 : // uint64_t id)
104 : #define TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION \
105 : v8::internal::tracing::TraceEventHelper::GetCurrentPlatform() \
106 : ->UpdateTraceEventDuration
107 :
108 : // Defines atomic operations used internally by the tracing system.
109 : #define TRACE_EVENT_API_ATOMIC_WORD v8::base::AtomicWord
110 : #define TRACE_EVENT_API_ATOMIC_LOAD(var) v8::base::NoBarrier_Load(&(var))
111 : #define TRACE_EVENT_API_ATOMIC_STORE(var, value) \
112 : v8::base::NoBarrier_Store(&(var), (value))
113 :
114 : ////////////////////////////////////////////////////////////////////////////////
115 :
116 : // Implementation detail: trace event macros create temporary variables
117 : // to keep instrumentation overhead low. These macros give each temporary
118 : // variable a unique name based on the line number to prevent name collisions.
119 : #define INTERNAL_TRACE_EVENT_UID3(a, b) trace_event_unique_##a##b
120 : #define INTERNAL_TRACE_EVENT_UID2(a, b) INTERNAL_TRACE_EVENT_UID3(a, b)
121 : #define INTERNAL_TRACE_EVENT_UID(name_prefix) \
122 : INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__)
123 :
124 : // Implementation detail: internal macro to create static category.
125 : // No barriers are needed, because this code is designed to operate safely
126 : // even when the unsigned char* points to garbage data (which may be the case
127 : // on processors without cache coherency).
128 : // TODO(fmeawad): This implementation contradicts that we can have a different
129 : // configuration for each isolate,
130 : // https://code.google.com/p/v8/issues/detail?id=4563
131 : #define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES( \
132 : category_group, atomic, category_group_enabled) \
133 : category_group_enabled = \
134 : reinterpret_cast<const uint8_t*>(TRACE_EVENT_API_ATOMIC_LOAD(atomic)); \
135 : if (!category_group_enabled) { \
136 : category_group_enabled = \
137 : TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_group); \
138 : TRACE_EVENT_API_ATOMIC_STORE( \
139 : atomic, reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD>( \
140 : category_group_enabled)); \
141 : }
142 :
143 : #define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group) \
144 : static TRACE_EVENT_API_ATOMIC_WORD INTERNAL_TRACE_EVENT_UID(atomic) = 0; \
145 : const uint8_t* INTERNAL_TRACE_EVENT_UID(category_group_enabled); \
146 : INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES( \
147 : category_group, INTERNAL_TRACE_EVENT_UID(atomic), \
148 : INTERNAL_TRACE_EVENT_UID(category_group_enabled));
149 :
150 : // Implementation detail: internal macro to create static category and add
151 : // event if the category is enabled.
152 : #define INTERNAL_TRACE_EVENT_ADD(phase, category_group, name, flags, ...) \
153 : do { \
154 : INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
155 : if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
156 : v8::internal::tracing::AddTraceEvent( \
157 : phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
158 : v8::internal::tracing::kGlobalScope, v8::internal::tracing::kNoId, \
159 : v8::internal::tracing::kNoId, flags, ##__VA_ARGS__); \
160 : } \
161 : } while (0)
162 :
163 : // Implementation detail: internal macro to create static category and add begin
164 : // event if the category is enabled. Also adds the end event when the scope
165 : // ends.
166 : #define INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, ...) \
167 : INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
168 : v8::internal::tracing::ScopedTracer INTERNAL_TRACE_EVENT_UID(tracer); \
169 : if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
170 : uint64_t h = v8::internal::tracing::AddTraceEvent( \
171 : TRACE_EVENT_PHASE_COMPLETE, \
172 : INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
173 : v8::internal::tracing::kGlobalScope, v8::internal::tracing::kNoId, \
174 : v8::internal::tracing::kNoId, TRACE_EVENT_FLAG_NONE, ##__VA_ARGS__); \
175 : INTERNAL_TRACE_EVENT_UID(tracer) \
176 : .Initialize(INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
177 : h); \
178 : }
179 :
180 : #define INTERNAL_TRACE_EVENT_ADD_SCOPED_WITH_FLOW(category_group, name, \
181 : bind_id, flow_flags, ...) \
182 : INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
183 : v8::internal::tracing::ScopedTracer INTERNAL_TRACE_EVENT_UID(tracer); \
184 : if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
185 : unsigned int trace_event_flags = flow_flags; \
186 : v8::internal::tracing::TraceID trace_event_bind_id(bind_id, \
187 : &trace_event_flags); \
188 : uint64_t h = v8::internal::tracing::AddTraceEvent( \
189 : TRACE_EVENT_PHASE_COMPLETE, \
190 : INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
191 : v8::internal::tracing::kGlobalScope, v8::internal::tracing::kNoId, \
192 : trace_event_bind_id.raw_id(), trace_event_flags, ##__VA_ARGS__); \
193 : INTERNAL_TRACE_EVENT_UID(tracer) \
194 : .Initialize(INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
195 : h); \
196 : }
197 :
198 : // Implementation detail: internal macro to create static category and add
199 : // event if the category is enabled.
200 : #define INTERNAL_TRACE_EVENT_ADD_WITH_ID(phase, category_group, name, id, \
201 : flags, ...) \
202 : do { \
203 : INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
204 : if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
205 : unsigned int trace_event_flags = flags | TRACE_EVENT_FLAG_HAS_ID; \
206 : v8::internal::tracing::TraceID trace_event_trace_id(id, \
207 : &trace_event_flags); \
208 : v8::internal::tracing::AddTraceEvent( \
209 : phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
210 : trace_event_trace_id.scope(), trace_event_trace_id.raw_id(), \
211 : v8::internal::tracing::kNoId, trace_event_flags, ##__VA_ARGS__); \
212 : } \
213 : } while (0)
214 :
215 : // Adds a trace event with a given timestamp. Not Implemented.
216 : #define INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP(phase, category_group, name, \
217 : timestamp, flags, ...) \
218 : UNIMPLEMENTED()
219 :
220 : // Adds a trace event with a given id and timestamp. Not Implemented.
221 : #define INTERNAL_TRACE_EVENT_ADD_WITH_ID_AND_TIMESTAMP( \
222 : phase, category_group, name, id, timestamp, flags, ...) \
223 : UNIMPLEMENTED()
224 :
225 : // Adds a trace event with a given id, thread_id, and timestamp. Not
226 : // Implemented.
227 : #define INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
228 : phase, category_group, name, id, thread_id, timestamp, flags, ...) \
229 : UNIMPLEMENTED()
230 :
231 : // Enter and leave a context based on the current scope.
232 : #define INTERNAL_TRACE_EVENT_SCOPED_CONTEXT(category_group, name, context) \
233 : struct INTERNAL_TRACE_EVENT_UID(ScopedContext) { \
234 : public: \
235 : INTERNAL_TRACE_EVENT_UID(ScopedContext)(uint64_t cid) : cid_(cid) { \
236 : TRACE_EVENT_ENTER_CONTEXT(category_group, name, cid_); \
237 : } \
238 : ~INTERNAL_TRACE_EVENT_UID(ScopedContext)() { \
239 : TRACE_EVENT_LEAVE_CONTEXT(category_group, name, cid_); \
240 : } \
241 : \
242 : private: \
243 : /* Local class friendly DISALLOW_COPY_AND_ASSIGN */ \
244 : INTERNAL_TRACE_EVENT_UID(ScopedContext) \
245 : (const INTERNAL_TRACE_EVENT_UID(ScopedContext)&) {} \
246 : void operator=(const INTERNAL_TRACE_EVENT_UID(ScopedContext)&) {} \
247 : uint64_t cid_; \
248 : }; \
249 : INTERNAL_TRACE_EVENT_UID(ScopedContext) \
250 : INTERNAL_TRACE_EVENT_UID(scoped_context)(context);
251 :
252 : #define TRACE_EVENT_CALL_STATS_SCOPED(isolate, category_group, name) \
253 : INTERNAL_TRACE_EVENT_CALL_STATS_SCOPED(isolate, category_group, name)
254 :
255 : #define INTERNAL_TRACE_EVENT_CALL_STATS_SCOPED(isolate, category_group, name) \
256 : INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \
257 : v8::internal::tracing::CallStatsScopedTracer INTERNAL_TRACE_EVENT_UID( \
258 : tracer); \
259 : if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
260 : INTERNAL_TRACE_EVENT_UID(tracer) \
261 : .Initialize(isolate, INTERNAL_TRACE_EVENT_UID(category_group_enabled), \
262 : name); \
263 : }
264 :
265 : namespace v8 {
266 : namespace internal {
267 :
268 : class Isolate;
269 :
270 : namespace tracing {
271 :
272 : // Specify these values when the corresponding argument of AddTraceEvent is not
273 : // used.
274 : const int kZeroNumArgs = 0;
275 : const decltype(nullptr) kGlobalScope = nullptr;
276 : const uint64_t kNoId = 0;
277 :
278 : class TraceEventHelper {
279 : public:
280 : static v8::Platform* GetCurrentPlatform();
281 : };
282 :
283 : // TraceID encapsulates an ID that can either be an integer or pointer. Pointers
284 : // are by default mangled with the Process ID so that they are unlikely to
285 : // collide when the same pointer is used on different processes.
286 : class TraceID {
287 : public:
288 : class WithScope {
289 : public:
290 : WithScope(const char* scope, uint64_t raw_id)
291 : : scope_(scope), raw_id_(raw_id) {}
292 : uint64_t raw_id() const { return raw_id_; }
293 : const char* scope() const { return scope_; }
294 :
295 : private:
296 : const char* scope_ = nullptr;
297 : uint64_t raw_id_;
298 : };
299 :
300 : class DontMangle {
301 : public:
302 : explicit DontMangle(const void* raw_id)
303 : : raw_id_(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(raw_id))) {}
304 : explicit DontMangle(uint64_t raw_id) : raw_id_(raw_id) {}
305 : explicit DontMangle(unsigned int raw_id) : raw_id_(raw_id) {}
306 : explicit DontMangle(uint16_t raw_id) : raw_id_(raw_id) {}
307 : explicit DontMangle(unsigned char raw_id) : raw_id_(raw_id) {}
308 : explicit DontMangle(int64_t raw_id)
309 : : raw_id_(static_cast<uint64_t>(raw_id)) {}
310 : explicit DontMangle(int raw_id) : raw_id_(static_cast<uint64_t>(raw_id)) {}
311 : explicit DontMangle(int16_t raw_id)
312 : : raw_id_(static_cast<uint64_t>(raw_id)) {}
313 : explicit DontMangle(signed char raw_id)
314 : : raw_id_(static_cast<uint64_t>(raw_id)) {}
315 : explicit DontMangle(WithScope scoped_id)
316 : : scope_(scoped_id.scope()), raw_id_(scoped_id.raw_id()) {}
317 : const char* scope() const { return scope_; }
318 : uint64_t raw_id() const { return raw_id_; }
319 :
320 : private:
321 : const char* scope_ = nullptr;
322 : uint64_t raw_id_;
323 : };
324 :
325 : class ForceMangle {
326 : public:
327 : explicit ForceMangle(uint64_t raw_id) : raw_id_(raw_id) {}
328 : explicit ForceMangle(unsigned int raw_id) : raw_id_(raw_id) {}
329 : explicit ForceMangle(uint16_t raw_id) : raw_id_(raw_id) {}
330 : explicit ForceMangle(unsigned char raw_id) : raw_id_(raw_id) {}
331 : explicit ForceMangle(int64_t raw_id)
332 : : raw_id_(static_cast<uint64_t>(raw_id)) {}
333 : explicit ForceMangle(int raw_id) : raw_id_(static_cast<uint64_t>(raw_id)) {}
334 : explicit ForceMangle(int16_t raw_id)
335 : : raw_id_(static_cast<uint64_t>(raw_id)) {}
336 : explicit ForceMangle(signed char raw_id)
337 : : raw_id_(static_cast<uint64_t>(raw_id)) {}
338 : uint64_t raw_id() const { return raw_id_; }
339 :
340 : private:
341 : uint64_t raw_id_;
342 : };
343 :
344 : TraceID(const void* raw_id, unsigned int* flags)
345 6 : : raw_id_(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(raw_id))) {
346 : *flags |= TRACE_EVENT_FLAG_MANGLE_ID;
347 : }
348 : TraceID(ForceMangle raw_id, unsigned int* flags) : raw_id_(raw_id.raw_id()) {
349 : *flags |= TRACE_EVENT_FLAG_MANGLE_ID;
350 : }
351 : TraceID(DontMangle maybe_scoped_id, unsigned int* flags)
352 : : scope_(maybe_scoped_id.scope()), raw_id_(maybe_scoped_id.raw_id()) {}
353 : TraceID(uint64_t raw_id, unsigned int* flags) : raw_id_(raw_id) {
354 : (void)flags;
355 : }
356 : TraceID(unsigned int raw_id, unsigned int* flags) : raw_id_(raw_id) {
357 : (void)flags;
358 : }
359 : TraceID(uint16_t raw_id, unsigned int* flags) : raw_id_(raw_id) {
360 : (void)flags;
361 : }
362 : TraceID(unsigned char raw_id, unsigned int* flags) : raw_id_(raw_id) {
363 : (void)flags;
364 : }
365 : TraceID(int64_t raw_id, unsigned int* flags)
366 : : raw_id_(static_cast<uint64_t>(raw_id)) {
367 : (void)flags;
368 : }
369 : TraceID(int raw_id, unsigned int* flags)
370 : : raw_id_(static_cast<uint64_t>(raw_id)) {
371 : (void)flags;
372 : }
373 : TraceID(int16_t raw_id, unsigned int* flags)
374 : : raw_id_(static_cast<uint64_t>(raw_id)) {
375 : (void)flags;
376 : }
377 : TraceID(signed char raw_id, unsigned int* flags)
378 : : raw_id_(static_cast<uint64_t>(raw_id)) {
379 : (void)flags;
380 : }
381 : TraceID(WithScope scoped_id, unsigned int* flags)
382 : : scope_(scoped_id.scope()), raw_id_(scoped_id.raw_id()) {}
383 :
384 : uint64_t raw_id() const { return raw_id_; }
385 : const char* scope() const { return scope_; }
386 :
387 : private:
388 : const char* scope_ = nullptr;
389 : uint64_t raw_id_;
390 : };
391 :
392 : // Simple union to store various types as uint64_t.
393 : union TraceValueUnion {
394 : bool as_bool;
395 : uint64_t as_uint;
396 : int64_t as_int;
397 : double as_double;
398 : const void* as_pointer;
399 : const char* as_string;
400 : };
401 :
402 : // Simple container for const char* that should be copied instead of retained.
403 : class TraceStringWithCopy {
404 : public:
405 0 : explicit TraceStringWithCopy(const char* str) : str_(str) {}
406 0 : operator const char*() const { return str_; }
407 :
408 : private:
409 : const char* str_;
410 : };
411 :
412 : static V8_INLINE uint64_t AddTraceEventImpl(
413 : char phase, const uint8_t* category_group_enabled, const char* name,
414 : const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args,
415 : const char** arg_names, const uint8_t* arg_types,
416 : const uint64_t* arg_values, unsigned int flags) {
417 24 : std::unique_ptr<ConvertableToTraceFormat> arg_convertables[2];
418 6 : if (num_args > 0 && arg_types[0] == TRACE_VALUE_TYPE_CONVERTABLE) {
419 : arg_convertables[0].reset(reinterpret_cast<ConvertableToTraceFormat*>(
420 6 : static_cast<intptr_t>(arg_values[0])));
421 : }
422 0 : if (num_args > 1 && arg_types[1] == TRACE_VALUE_TYPE_CONVERTABLE) {
423 : arg_convertables[1].reset(reinterpret_cast<ConvertableToTraceFormat*>(
424 0 : static_cast<intptr_t>(arg_values[1])));
425 : }
426 : DCHECK(num_args <= 2);
427 : v8::Platform* platform =
428 6 : v8::internal::tracing::TraceEventHelper::GetCurrentPlatform();
429 : return platform->AddTraceEvent(phase, category_group_enabled, name, scope, id,
430 : bind_id, num_args, arg_names, arg_types,
431 6 : arg_values, arg_convertables, flags);
432 : }
433 :
434 : // Define SetTraceValue for each allowed type. It stores the type and
435 : // value in the return arguments. This allows this API to avoid declaring any
436 : // structures so that it is portable to third_party libraries.
437 : #define INTERNAL_DECLARE_SET_TRACE_VALUE(actual_type, union_member, \
438 : value_type_id) \
439 : static V8_INLINE void SetTraceValue(actual_type arg, unsigned char* type, \
440 : uint64_t* value) { \
441 : TraceValueUnion type_value; \
442 : type_value.union_member = arg; \
443 : *type = value_type_id; \
444 : *value = type_value.as_uint; \
445 : }
446 : // Simpler form for int types that can be safely casted.
447 : #define INTERNAL_DECLARE_SET_TRACE_VALUE_INT(actual_type, value_type_id) \
448 : static V8_INLINE void SetTraceValue(actual_type arg, unsigned char* type, \
449 : uint64_t* value) { \
450 : *type = value_type_id; \
451 : *value = static_cast<uint64_t>(arg); \
452 : }
453 :
454 : INTERNAL_DECLARE_SET_TRACE_VALUE_INT(uint64_t, TRACE_VALUE_TYPE_UINT)
455 : INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned int, TRACE_VALUE_TYPE_UINT)
456 : INTERNAL_DECLARE_SET_TRACE_VALUE_INT(uint16_t, TRACE_VALUE_TYPE_UINT)
457 : INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned char, TRACE_VALUE_TYPE_UINT)
458 : INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int64_t, TRACE_VALUE_TYPE_INT)
459 : INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int, TRACE_VALUE_TYPE_INT)
460 : INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int16_t, TRACE_VALUE_TYPE_INT)
461 : INTERNAL_DECLARE_SET_TRACE_VALUE_INT(signed char, TRACE_VALUE_TYPE_INT)
462 : INTERNAL_DECLARE_SET_TRACE_VALUE(bool, as_bool, TRACE_VALUE_TYPE_BOOL)
463 : INTERNAL_DECLARE_SET_TRACE_VALUE(double, as_double, TRACE_VALUE_TYPE_DOUBLE)
464 : INTERNAL_DECLARE_SET_TRACE_VALUE(const void*, as_pointer,
465 : TRACE_VALUE_TYPE_POINTER)
466 : INTERNAL_DECLARE_SET_TRACE_VALUE(const char*, as_string,
467 : TRACE_VALUE_TYPE_STRING)
468 0 : INTERNAL_DECLARE_SET_TRACE_VALUE(const TraceStringWithCopy&, as_string,
469 : TRACE_VALUE_TYPE_COPY_STRING)
470 :
471 : #undef INTERNAL_DECLARE_SET_TRACE_VALUE
472 : #undef INTERNAL_DECLARE_SET_TRACE_VALUE_INT
473 :
474 : static V8_INLINE void SetTraceValue(ConvertableToTraceFormat* convertable_value,
475 : unsigned char* type, uint64_t* value) {
476 6 : *type = TRACE_VALUE_TYPE_CONVERTABLE;
477 6 : *value = static_cast<uint64_t>(reinterpret_cast<intptr_t>(convertable_value));
478 : }
479 :
480 : template <typename T>
481 : static V8_INLINE typename std::enable_if<
482 : std::is_convertible<T*, ConvertableToTraceFormat*>::value>::type
483 : SetTraceValue(std::unique_ptr<T> ptr, unsigned char* type, uint64_t* value) {
484 6 : SetTraceValue(ptr.release(), type, value);
485 : }
486 :
487 : // These AddTraceEvent template
488 : // function is defined here instead of in the macro, because the arg_values
489 : // could be temporary objects, such as std::string. In order to store
490 : // pointers to the internal c_str and pass through to the tracing API,
491 : // the arg_values must live throughout these procedures.
492 :
493 : static V8_INLINE uint64_t AddTraceEvent(char phase,
494 : const uint8_t* category_group_enabled,
495 : const char* name, const char* scope,
496 : uint64_t id, uint64_t bind_id,
497 : unsigned int flags) {
498 : return TRACE_EVENT_API_ADD_TRACE_EVENT(phase, category_group_enabled, name,
499 : scope, id, bind_id, kZeroNumArgs,
500 : nullptr, nullptr, nullptr, flags);
501 : }
502 :
503 : template <class ARG1_TYPE>
504 : static V8_INLINE uint64_t AddTraceEvent(
505 : char phase, const uint8_t* category_group_enabled, const char* name,
506 : const char* scope, uint64_t id, uint64_t bind_id, unsigned int flags,
507 : const char* arg1_name, ARG1_TYPE&& arg1_val) {
508 : const int num_args = 1;
509 : uint8_t arg_type;
510 : uint64_t arg_value;
511 12 : SetTraceValue(std::forward<ARG1_TYPE>(arg1_val), &arg_type, &arg_value);
512 : return TRACE_EVENT_API_ADD_TRACE_EVENT(
513 : phase, category_group_enabled, name, scope, id, bind_id, num_args,
514 : &arg1_name, &arg_type, &arg_value, flags);
515 : }
516 :
517 : template <class ARG1_TYPE, class ARG2_TYPE>
518 : static V8_INLINE uint64_t AddTraceEvent(
519 : char phase, const uint8_t* category_group_enabled, const char* name,
520 : const char* scope, uint64_t id, uint64_t bind_id, unsigned int flags,
521 : const char* arg1_name, ARG1_TYPE&& arg1_val, const char* arg2_name,
522 : ARG2_TYPE&& arg2_val) {
523 : const int num_args = 2;
524 0 : const char* arg_names[2] = {arg1_name, arg2_name};
525 : unsigned char arg_types[2];
526 : uint64_t arg_values[2];
527 0 : SetTraceValue(std::forward<ARG1_TYPE>(arg1_val), &arg_types[0],
528 : &arg_values[0]);
529 0 : SetTraceValue(std::forward<ARG2_TYPE>(arg2_val), &arg_types[1],
530 : &arg_values[1]);
531 : return TRACE_EVENT_API_ADD_TRACE_EVENT(
532 : phase, category_group_enabled, name, scope, id, bind_id, num_args,
533 : arg_names, arg_types, arg_values, flags);
534 : }
535 :
536 : // Used by TRACE_EVENTx macros. Do not use directly.
537 : class ScopedTracer {
538 : public:
539 : // Note: members of data_ intentionally left uninitialized. See Initialize.
540 19518853 : ScopedTracer() : p_data_(NULL) {}
541 :
542 19518843 : ~ScopedTracer() {
543 19518843 : if (p_data_ && *data_.category_group_enabled)
544 0 : TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(
545 0 : data_.category_group_enabled, data_.name, data_.event_handle);
546 19518843 : }
547 :
548 0 : void Initialize(const uint8_t* category_group_enabled, const char* name,
549 : uint64_t event_handle) {
550 0 : data_.category_group_enabled = category_group_enabled;
551 0 : data_.name = name;
552 0 : data_.event_handle = event_handle;
553 0 : p_data_ = &data_;
554 0 : }
555 :
556 : private:
557 : // This Data struct workaround is to avoid initializing all the members
558 : // in Data during construction of this object, since this object is always
559 : // constructed, even when tracing is disabled. If the members of Data were
560 : // members of this class instead, compiler warnings occur about potential
561 : // uninitialized accesses.
562 : struct Data {
563 : const uint8_t* category_group_enabled;
564 : const char* name;
565 : uint64_t event_handle;
566 : };
567 : Data* p_data_;
568 : Data data_;
569 : };
570 :
571 : // Do not use directly.
572 : class CallStatsScopedTracer {
573 : public:
574 30484940 : CallStatsScopedTracer() : p_data_(nullptr) {}
575 30484934 : ~CallStatsScopedTracer() {
576 30484934 : if (V8_UNLIKELY(p_data_ && *data_.category_group_enabled)) {
577 0 : AddEndTraceEvent();
578 : }
579 30484934 : }
580 :
581 : void Initialize(v8::internal::Isolate* isolate,
582 : const uint8_t* category_group_enabled, const char* name);
583 :
584 : private:
585 : void AddEndTraceEvent();
586 : struct Data {
587 : const uint8_t* category_group_enabled;
588 : const char* name;
589 : v8::internal::Isolate* isolate;
590 : };
591 : bool has_parent_scope_;
592 : Data* p_data_;
593 : Data data_;
594 : };
595 :
596 : } // namespace tracing
597 : } // namespace internal
598 : } // namespace v8
599 :
600 : #endif // SRC_TRACING_TRACE_EVENT_H_
|