OLD | NEW |
1 /* | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 * Copyright (C) 2011 Google Inc. All rights reserved. | 2 // Use of this source code is governed by a BSD-style license that can be |
3 * | 3 // found in the LICENSE file. |
4 * Redistribution and use in source and binary forms, with or without | |
5 * modification, are permitted provided that the following conditions | |
6 * are met: | |
7 * | |
8 * 1. Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * 2. Redistributions in binary form must reproduce the above copyright | |
11 * notice, this list of conditions and the following disclaimer in the | |
12 * documentation and/or other materials provided with the distribution. | |
13 * | |
14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY | |
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY | |
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 */ | |
25 | |
26 // This header file defines implementation details of how the trace macros in | |
27 // TraceEventCommon.h collect and store trace events. Anything not | |
28 // implementation-specific should go in TraceEventCommon.h instead of here. | |
29 | 4 |
30 #ifndef TraceEvent_h | 5 #ifndef TraceEvent_h |
31 #define TraceEvent_h | 6 #define TraceEvent_h |
32 | 7 |
33 #include "platform/EventTracer.h" | 8 #include "base/time/time.h" |
34 #include "platform/TraceEventCommon.h" | 9 #include "base/trace_event/trace_event.h" |
| 10 #include "wtf/text/CString.h" |
35 | 11 |
36 #include "platform/TracedValue.h" | 12 namespace WTF { |
37 #include "wtf/Allocator.h" | |
38 #include "wtf/DynamicAnnotations.h" | |
39 #include "wtf/Noncopyable.h" | |
40 #include "wtf/text/CString.h" | |
41 #include <memory> | |
42 | 13 |
43 //////////////////////////////////////////////////////////////////////////////// | 14 // CString version of SetTraceValue so that trace arguments can be strings. |
44 // Implementation specific tracing API definitions. | 15 static inline void SetTraceValue(const CString& arg, unsigned char* type, unsign
ed long long* value) |
| 16 { |
| 17 trace_event_internal::TraceValueUnion typeValue; |
| 18 typeValue.as_string = arg.data(); |
| 19 *type = TRACE_VALUE_TYPE_COPY_STRING; |
| 20 *value = typeValue.as_uint; |
| 21 } |
45 | 22 |
46 // By default, const char* argument values are assumed to have long-lived scope | 23 } // namespace WTF |
47 // and will not be copied. Use this macro to force a const char* to be copied. | |
48 #define TRACE_STR_COPY(str) \ | |
49 blink::TraceEvent::TraceStringWithCopy(str) | |
50 | |
51 // By default, uint64 ID argument values are not mangled with the Process ID in | |
52 // TRACE_EVENT_ASYNC macros. Use this macro to force Process ID mangling. | |
53 #define TRACE_ID_MANGLE(id) \ | |
54 blink::TraceEvent::TraceID::ForceMangle(id) | |
55 | |
56 // By default, pointers are mangled with the Process ID in TRACE_EVENT_ASYNC | |
57 // macros. Use this macro to prevent Process ID mangling. | |
58 #define TRACE_ID_DONT_MANGLE(id) \ | |
59 blink::TraceEvent::TraceID::DontMangle(id) | |
60 | |
61 // By default, trace IDs are eventually converted to a single 64-bit number. Use | |
62 // this macro to add a scope string. | |
63 #define TRACE_ID_WITH_SCOPE(scope, id) \ | |
64 blink::TraceEvent::TraceID::WithScope(scope, id) | |
65 | |
66 // Creates a scope of a sampling state with the given category and name (both mu
st | |
67 // be constant strings). These states are intended for a sampling profiler. | |
68 // Implementation note: we store category and name together because we don't | |
69 // want the inconsistency/expense of storing two pointers. | |
70 // |thread_bucket| is [0..2] and is used to statically isolate samples in one | |
71 // thread from others. | |
72 // | |
73 // { // The sampling state is set within this scope. | |
74 // TRACE_EVENT_SAMPLING_STATE_SCOPE_FOR_BUCKET(0, "category", "name"); | |
75 // ...; | |
76 // } | |
77 #define TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET(bucket_number, category, na
me) \ | |
78 TraceEvent::SamplingStateScope<bucket_number> traceEventSamplingScope(catego
ry "\0" name); | |
79 | |
80 // Returns a current sampling state of the given bucket. | |
81 // The format of the returned string is "category\0name". | |
82 #define TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(bucket_number) \ | |
83 TraceEvent::SamplingStateScope<bucket_number>::current() | |
84 | |
85 // Sets a current sampling state of the given bucket. | |
86 // |category| and |name| have to be constant strings. | |
87 #define TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(bucket_number, category, name)
\ | |
88 TraceEvent::SamplingStateScope<bucket_number>::set(category "\0" name) | |
89 | |
90 // Sets a current sampling state of the given bucket. | |
91 // |categoryAndName| doesn't need to be a constant string. | |
92 // The format of the string is "category\0name". | |
93 #define TRACE_EVENT_SET_NONCONST_SAMPLING_STATE_FOR_BUCKET(bucket_number, catego
ryAndName) \ | |
94 TraceEvent::SamplingStateScope<bucket_number>::set(categoryAndName) | |
95 | |
96 // Get a pointer to the enabled state of the given trace category. Only | |
97 // long-lived literal strings should be given as the category name. The returned | |
98 // pointer can be held permanently in a local static for example. If the | |
99 // unsigned char is non-zero, tracing is enabled. If tracing is enabled, | |
100 // TRACE_EVENT_API_ADD_TRACE_EVENT can be called. It's OK if tracing is disabled | |
101 // between the load of the tracing state and the call to | |
102 // TRACE_EVENT_API_ADD_TRACE_EVENT, because this flag only provides an early out | |
103 // for best performance when tracing is disabled. | |
104 // const unsigned char* | |
105 // TRACE_EVENT_API_GET_CATEGORY_ENABLED(const char* category_name) | |
106 #define TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED \ | |
107 blink::EventTracer::getTraceCategoryEnabledFlag | |
108 | |
109 // Add a trace event to the platform tracing system. | |
110 // blink::TraceEvent::TraceEventHandle TRACE_EVENT_API_ADD_TRACE_EVENT( | |
111 // const char* name, | |
112 // const char* scope, | |
113 // unsigned long long id, | |
114 // double timestamp, | |
115 // int num_args, | |
116 // const char** arg_names, | |
117 // const unsigned char* arg_types, | |
118 // const unsigned long long* arg_values, | |
119 // std::unique_ptr<TracedValue> tracedValues[], | |
120 // unsigned char flags) | |
121 #define TRACE_EVENT_API_ADD_TRACE_EVENT \ | |
122 blink::EventTracer::addTraceEvent | |
123 | |
124 // Set the duration field of a COMPLETE trace event. | |
125 // void TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION( | |
126 // blink::TraceEvent::TraceEventHandle handle) | |
127 #define TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION \ | |
128 blink::EventTracer::updateTraceEventDuration | |
129 | |
130 //////////////////////////////////////////////////////////////////////////////// | |
131 | |
132 // Implementation detail: trace event macros create temporary variables | |
133 // to keep instrumentation overhead low. These macros give each temporary | |
134 // variable a unique name based on the line number to prevent name collissions. | |
135 #define INTERNAL_TRACE_EVENT_UID3(a, b) \ | |
136 trace_event_unique_##a##b | |
137 #define INTERNAL_TRACE_EVENT_UID2(a, b) \ | |
138 INTERNAL_TRACE_EVENT_UID3(a, b) | |
139 #define INTERNALTRACEEVENTUID(name_prefix) \ | |
140 INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__) | |
141 | |
142 // Implementation detail: internal macro to create static category. | |
143 // - WTF_ANNOTATE_BENIGN_RACE, see Thread Safety above. | |
144 | |
145 #define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category) \ | |
146 static const unsigned char* INTERNALTRACEEVENTUID(categoryGroupEnabled) = 0;
\ | |
147 WTF_ANNOTATE_BENIGN_RACE(&INTERNALTRACEEVENTUID(categoryGroupEnabled), \ | |
148 "trace_event category"); \ | |
149 if (!INTERNALTRACEEVENTUID(categoryGroupEnabled)) { \ | |
150 INTERNALTRACEEVENTUID(categoryGroupEnabled) = \ | |
151 TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category); \ | |
152 } | |
153 | |
154 // Implementation detail: internal macro to create static category and add | |
155 // event if the category is enabled. | |
156 #define INTERNAL_TRACE_EVENT_ADD(phase, category, name, flags, ...) \ | |
157 do { \ | |
158 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \ | |
159 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) {
\ | |
160 blink::TraceEvent::addTraceEvent( \ | |
161 phase, INTERNALTRACEEVENTUID(categoryGroupEnabled), name, \ | |
162 blink::TraceEvent::kGlobalScope, blink::TraceEvent::noEventId, \ | |
163 flags, ##__VA_ARGS__); \ | |
164 } \ | |
165 } while (0) | |
166 | |
167 // Implementation detail: internal macro to create static category and add begin | |
168 // event if the category is enabled. Also adds the end event when the scope | |
169 // ends. | |
170 #define INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, ...) \ | |
171 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \ | |
172 blink::TraceEvent::ScopedTracer INTERNALTRACEEVENTUID(scopedTracer); \ | |
173 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ | |
174 blink::TraceEvent::TraceEventHandle h = \ | |
175 blink::TraceEvent::addTraceEvent( \ | |
176 TRACE_EVENT_PHASE_COMPLETE, \ | |
177 INTERNALTRACEEVENTUID(categoryGroupEnabled), name, \ | |
178 blink::TraceEvent::kGlobalScope, blink::TraceEvent::noEventId, \ | |
179 TRACE_EVENT_FLAG_NONE, ##__VA_ARGS__); \ | |
180 INTERNALTRACEEVENTUID(scopedTracer).initialize( \ | |
181 INTERNALTRACEEVENTUID(categoryGroupEnabled), name, h); \ | |
182 } | |
183 | |
184 #define INTERNAL_TRACE_EVENT_ADD_SCOPED_WITH_FLOW(category, name, bindId, flowFl
ags, ...) \ | |
185 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \ | |
186 blink::TraceEvent::ScopedTracer INTERNALTRACEEVENTUID(scopedTracer); \ | |
187 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ | |
188 unsigned traceEventFlags = flowFlags; \ | |
189 blink::TraceEvent::TraceID traceEventBindId(bindId, &traceEventFlags); \ | |
190 blink::TraceEvent::TraceEventHandle h = \ | |
191 blink::TraceEvent::addTraceEvent( \ | |
192 TRACE_EVENT_PHASE_COMPLETE, \ | |
193 INTERNALTRACEEVENTUID(categoryGroupEnabled), name, \ | |
194 blink::TraceEvent::kGlobalScope, blink::TraceEvent::noEventId, \ | |
195 traceEventBindId.data(), \ | |
196 EventTracer::systemTraceTime(), traceEventFlags, ##__VA_ARGS__);
\ | |
197 INTERNALTRACEEVENTUID(scopedTracer).initialize( \ | |
198 INTERNALTRACEEVENTUID(categoryGroupEnabled), name, h); \ | |
199 } | |
200 | |
201 // Implementation detail: internal macro to create static category and add | |
202 // event if the category is enabled. | |
203 #define INTERNAL_TRACE_EVENT_ADD_WITH_ID(phase, category, name, id, flags, ...)
\ | |
204 do { \ | |
205 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \ | |
206 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) {
\ | |
207 unsigned traceEventFlags = flags | TRACE_EVENT_FLAG_HAS_ID; \ | |
208 blink::TraceEvent::TraceID traceEventTraceID( \ | |
209 id, &traceEventFlags); \ | |
210 blink::TraceEvent::addTraceEvent( \ | |
211 phase, INTERNALTRACEEVENTUID(categoryGroupEnabled), name, \ | |
212 traceEventTraceID.scope(), traceEventTraceID.data(), \ | |
213 traceEventFlags, ##__VA_ARGS__); \ | |
214 } \ | |
215 } while (0) | |
216 | |
217 | |
218 // Implementation detail: internal macro to create static category and add event | |
219 // if the category is enabled. | |
220 #define INTERNAL_TRACE_EVENT_ADD_WITH_ID_AND_TIMESTAMP(phase, category, name, id
, timestamp, flags, ...) \ | |
221 do { \ | |
222 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \ | |
223 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) {
\ | |
224 unsigned traceEventFlags = flags | TRACE_EVENT_FLAG_HAS_ID; \ | |
225 blink::TraceEvent::TraceID traceEventTraceID( \ | |
226 id, &traceEventFlags); \ | |
227 blink::TraceEvent::addTraceEvent( \ | |
228 phase, INTERNALTRACEEVENTUID(categoryGroupEnabled), name, \ | |
229 traceEventTraceID.scope(), traceEventTraceID.data(), \ | |
230 blink::TraceEvent::noBindId, \ | |
231 timestamp, traceEventFlags, ##__VA_ARGS__); \ | |
232 } \ | |
233 } while (0) | |
234 | |
235 // Implementation detail: internal macro to create static category and add | |
236 // event if the category is enabled. | |
237 #define INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP(phase, category, name, timestamp
, flags, ...) \ | |
238 do { \ | |
239 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \ | |
240 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) {
\ | |
241 blink::TraceEvent::addTraceEvent( \ | |
242 phase, INTERNALTRACEEVENTUID(categoryGroupEnabled), name, \ | |
243 blink::TraceEvent::kGlobalScope, blink::TraceEvent::noEventId, \ | |
244 blink::TraceEvent::noBindId, \ | |
245 timestamp, flags, ##__VA_ARGS__); \ | |
246 } \ | |
247 } while (0) | |
248 | |
249 // Implementation detail: internal macro to enter and leave a context based on | |
250 // the current scope. | |
251 #define INTERNAL_TRACE_EVENT_SCOPED_CONTEXT(categoryGroup, name, context) \ | |
252 struct INTERNAL_TRACE_EVENT_UID(ScopedContext) { \ | |
253 public: \ | |
254 INTERNAL_TRACE_EVENT_UID(ScopedContext)(uint64_t cid) : m_cid(cid) { \ | |
255 TRACE_EVENT_ENTER_CONTEXT(category_group, name, m_cid); \ | |
256 } \ | |
257 ~INTERNAL_TRACE_EVENT_UID(ScopedContext)() { \ | |
258 TRACE_EVENT_LEAVE_CONTEXT(category_group, name, m_cid); \ | |
259 } \ | |
260 private: \ | |
261 uint64_t m_cid; \ | |
262 INTERNAL_TRACE_EVENT_UID(ScopedContext) \ | |
263 (const INTERNAL_TRACE_EVENT_UID(ScopedContext)&) {}; \ | |
264 void operator=(const INTERNAL_TRACE_EVENT_UID(ScopedContext)&) {}; \ | |
265 }; \ | |
266 INTERNAL_TRACE_EVENT_UID(ScopedContext) \ | |
267 INTERNAL_TRACE_EVENT_UID(scoped_context)(context.data()); | |
268 | |
269 // These values must be in sync with base::debug::TraceLog::CategoryGroupEnabled
Flags. | |
270 #define INTERNAL_ENABLED_FOR_RECORDING (1 << 0) | |
271 #define INTERNAL_ENABLED_FOR_EVENT_CALLBACK (1 << 2) | |
272 | |
273 #define INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE() \ | |
274 (*INTERNALTRACEEVENTUID(categoryGroupEnabled) & (INTERNAL_ENABLED_FOR_RECORD
ING | INTERNAL_ENABLED_FOR_EVENT_CALLBACK)) | |
275 | |
276 #define INTERNAL_TRACE_MEMORY(category, name) | |
277 | 24 |
278 namespace blink { | 25 namespace blink { |
279 | |
280 namespace TraceEvent { | 26 namespace TraceEvent { |
281 | 27 |
282 // Specify these values when the corresponding argument of addTraceEvent is not | 28 using base::trace_event::TraceScopedTrackableObject; |
283 // used. | |
284 const int zeroNumArgs = 0; | |
285 const std::nullptr_t kGlobalScope = nullptr; | |
286 const unsigned long long noEventId = 0; | |
287 const unsigned long long noBindId = 0; | |
288 | 29 |
289 // TraceID encapsulates an ID that can either be an integer or pointer; | 30 inline int64_t toTraceTimestamp(double seconds) |
290 // optionally, it can be paired with a scope string, too. Pointers are mangled | |
291 // with the Process ID so that they are unlikely to collide when the same | |
292 // pointer is used on different processes. | |
293 class TraceID final { | |
294 STACK_ALLOCATED(); | |
295 WTF_MAKE_NONCOPYABLE(TraceID); | |
296 public: | |
297 class WithScope final { | |
298 STACK_ALLOCATED(); | |
299 public: | |
300 template<typename T> WithScope(const char* scope, T id) | |
301 : m_scope(scope), m_data(reinterpret_cast<unsigned long long>(id)) {
} | |
302 const char* scope() const { return m_scope; } | |
303 unsigned long long data() const { return m_data; } | |
304 private: | |
305 const char* m_scope = kGlobalScope; | |
306 unsigned long long m_data; | |
307 }; | |
308 | |
309 template<bool dummyMangle> class MangleBehavior final { | |
310 STACK_ALLOCATED(); | |
311 public: | |
312 template<typename T> explicit MangleBehavior(T id) : m_data(reinterpret_
cast<unsigned long long>(id)) { } | |
313 explicit MangleBehavior(WithScope scopedID) : m_scope(scopedID.scope()),
m_data(scopedID.data()) { } | |
314 const char* scope() const { return m_scope; } | |
315 unsigned long long data() const { return m_data; } | |
316 private: | |
317 const char* m_scope = kGlobalScope; | |
318 unsigned long long m_data; | |
319 }; | |
320 typedef MangleBehavior<false> DontMangle; | |
321 typedef MangleBehavior<true> ForceMangle; | |
322 | |
323 TraceID(const void* id, unsigned* flags) | |
324 : m_data(static_cast<unsigned long long>(reinterpret_cast<uintptr_t>(id)
)) | |
325 { | |
326 *flags |= TRACE_EVENT_FLAG_MANGLE_ID; | |
327 } | |
328 TraceID(ForceMangle id, unsigned* flags) | |
329 : m_scope(id.scope()), m_data(id.data()) | |
330 { | |
331 *flags |= TRACE_EVENT_FLAG_MANGLE_ID; | |
332 } | |
333 TraceID(DontMangle id, unsigned*) : m_scope(id.scope()), m_data(id.data()) {
} | |
334 TraceID(unsigned long long id, unsigned*) : m_data(id) { } | |
335 TraceID(unsigned long id, unsigned*) : m_data(id) { } | |
336 TraceID(unsigned id, unsigned*) : m_data(id) { } | |
337 TraceID(unsigned short id, unsigned*) : m_data(id) { } | |
338 TraceID(unsigned char id, unsigned*) : m_data(id) { } | |
339 TraceID(long long id, unsigned*) : | |
340 m_data(static_cast<unsigned long long>(id)) { } | |
341 TraceID(long id, unsigned*) : | |
342 m_data(static_cast<unsigned long long>(id)) { } | |
343 TraceID(int id, unsigned*) : | |
344 m_data(static_cast<unsigned long long>(id)) { } | |
345 TraceID(short id, unsigned*) : | |
346 m_data(static_cast<unsigned long long>(id)) { } | |
347 TraceID(signed char id, unsigned*) : | |
348 m_data(static_cast<unsigned long long>(id)) { } | |
349 TraceID(WithScope scopedID, unsigned*) : | |
350 m_scope(scopedID.scope()), m_data(scopedID.data()) { } | |
351 | |
352 const char* scope() const { return m_scope; } | |
353 unsigned long long data() const { return m_data; } | |
354 | |
355 private: | |
356 const char* m_scope = kGlobalScope; | |
357 unsigned long long m_data; | |
358 }; | |
359 | |
360 // Simple union to store various types as unsigned long long. | |
361 union TraceValueUnion { | |
362 bool m_bool; | |
363 unsigned long long m_uint; | |
364 long long m_int; | |
365 double m_double; | |
366 const void* m_pointer; | |
367 const char* m_string; | |
368 }; | |
369 | |
370 // Simple container for const char* that should be copied instead of retained. | |
371 class TraceStringWithCopy { | |
372 STACK_ALLOCATED(); | |
373 public: | |
374 explicit TraceStringWithCopy(const char* str) : m_str(str) { } | |
375 const char* str() const { return m_str; } | |
376 private: | |
377 const char* m_str; | |
378 }; | |
379 | |
380 // Define setTraceValue for each allowed type. It stores the type and | |
381 // value in the return arguments. This allows this API to avoid declaring any | |
382 // structures so that it is portable to third_party libraries. | |
383 #define INTERNAL_DECLARE_SET_TRACE_VALUE(actualType, argExpression, unionMember,
valueTypeId) \ | |
384 static inline void setTraceValue(actualType arg, unsigned char* type, unsign
ed long long* value) { \ | |
385 TraceValueUnion typeValue; \ | |
386 typeValue.unionMember = argExpression; \ | |
387 *type = valueTypeId; \ | |
388 *value = typeValue.m_uint; \ | |
389 } | |
390 // Simpler form for int types that can be safely casted. | |
391 #define INTERNAL_DECLARE_SET_TRACE_VALUE_INT(actualType, valueTypeId) \ | |
392 static inline void setTraceValue(actualType arg, \ | |
393 unsigned char* type, \ | |
394 unsigned long long* value) { \ | |
395 *type = valueTypeId; \ | |
396 *value = static_cast<unsigned long long>(arg); \ | |
397 } | |
398 | |
399 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long long, TRACE_VALUE_TYPE_UINT) | |
400 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned, TRACE_VALUE_TYPE_UINT) | |
401 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned short, TRACE_VALUE_TYPE_UINT) | |
402 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned char, TRACE_VALUE_TYPE_UINT) | |
403 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long long, TRACE_VALUE_TYPE_INT) | |
404 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int, TRACE_VALUE_TYPE_INT) | |
405 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(short, TRACE_VALUE_TYPE_INT) | |
406 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(signed char, TRACE_VALUE_TYPE_INT) | |
407 INTERNAL_DECLARE_SET_TRACE_VALUE(bool, arg, m_bool, TRACE_VALUE_TYPE_BOOL) | |
408 INTERNAL_DECLARE_SET_TRACE_VALUE(double, arg, m_double, TRACE_VALUE_TYPE_DOUBLE) | |
409 INTERNAL_DECLARE_SET_TRACE_VALUE(const void*, arg, m_pointer, TRACE_VALUE_TYPE_P
OINTER) | |
410 INTERNAL_DECLARE_SET_TRACE_VALUE(const char*, arg, m_string, TRACE_VALUE_TYPE_ST
RING) | |
411 INTERNAL_DECLARE_SET_TRACE_VALUE(const TraceStringWithCopy&, arg.str(), m_string
, TRACE_VALUE_TYPE_COPY_STRING) | |
412 | |
413 #undef INTERNAL_DECLARE_SET_TRACE_VALUE | |
414 #undef INTERNAL_DECLARE_SET_TRACE_VALUE_INT | |
415 | |
416 // WTF::String version of setTraceValue so that trace arguments can be strings. | |
417 static inline void setTraceValue(const WTF::CString& arg, unsigned char* type, u
nsigned long long* value) | |
418 { | 31 { |
419 TraceValueUnion typeValue; | 32 return (base::TimeTicks() + base::TimeDelta::FromSecondsD(seconds)).ToIntern
alValue(); |
420 typeValue.m_string = arg.data(); | |
421 *type = TRACE_VALUE_TYPE_COPY_STRING; | |
422 *value = typeValue.m_uint; | |
423 } | 33 } |
424 | 34 |
425 static inline void setTraceValue(TracedValue*, unsigned char* type, unsigned lon
g long*) | |
426 { | |
427 *type = TRACE_VALUE_TYPE_CONVERTABLE; | |
428 } | |
429 | |
430 template<typename T> static inline void setTraceValue(const std::unique_ptr<T>&
ptr, unsigned char* type, unsigned long long* value) | |
431 { | |
432 setTraceValue(ptr.get(), type, value); | |
433 } | |
434 | |
435 template<typename T> struct TracedValueTraits { | |
436 static const bool isTracedValue = false; | |
437 static std::unique_ptr<TracedValue> moveFromIfTracedValue(const T&) | |
438 { | |
439 return nullptr; | |
440 } | |
441 }; | |
442 | |
443 template<typename T> struct TracedValueTraits<std::unique_ptr<T>> { | |
444 static const bool isTracedValue = std::is_convertible<T*, TracedValue*>::val
ue; | |
445 static std::unique_ptr<TracedValue> moveFromIfTracedValue(std::unique_ptr<T>
&& tracedValue) | |
446 { | |
447 return std::move(tracedValue); | |
448 } | |
449 }; | |
450 | |
451 template<typename T> bool isTracedValue(const T&) | |
452 { | |
453 return TracedValueTraits<T>::isTracedValue; | |
454 } | |
455 | |
456 template<typename T> std::unique_ptr<TracedValue> moveFromIfTracedValue(T&& valu
e) | |
457 { | |
458 return TracedValueTraits<T>::moveFromIfTracedValue(std::forward<T>(value)); | |
459 } | |
460 | |
461 // These addTraceEvent template functions are defined here instead of in the | |
462 // macro, because the arg values could be temporary string objects. In order to | |
463 // store pointers to the internal c_str and pass through to the tracing API, the | |
464 // arg values must live throughout these procedures. | |
465 | |
466 static inline TraceEventHandle addTraceEvent( | |
467 char phase, | |
468 const unsigned char* categoryEnabled, | |
469 const char* name, | |
470 const char* scope, | |
471 unsigned long long id, | |
472 unsigned long long bindId, | |
473 double timestamp, | |
474 unsigned flags) | |
475 { | |
476 return TRACE_EVENT_API_ADD_TRACE_EVENT( | |
477 phase, categoryEnabled, name, scope, id, bindId, timestamp, | |
478 zeroNumArgs, 0, 0, 0, | |
479 flags); | |
480 } | |
481 | |
482 template <typename ARG1_TYPE> | |
483 static inline TraceEventHandle addTraceEvent( | |
484 char phase, | |
485 const unsigned char* categoryEnabled, | |
486 const char* name, | |
487 const char* scope, | |
488 unsigned long long id, | |
489 unsigned long long bindId, | |
490 double timestamp, | |
491 unsigned flags, | |
492 const char* arg1Name, | |
493 ARG1_TYPE&& arg1Val) | |
494 { | |
495 const int numArgs = 1; | |
496 unsigned char argTypes[1]; | |
497 unsigned long long argValues[1]; | |
498 setTraceValue(arg1Val, &argTypes[0], &argValues[0]); | |
499 if (isTracedValue(arg1Val)) { | |
500 return TRACE_EVENT_API_ADD_TRACE_EVENT( | |
501 phase, categoryEnabled, name, scope, id, bindId, timestamp, | |
502 numArgs, &arg1Name, argTypes, argValues, | |
503 moveFromIfTracedValue(std::forward<ARG1_TYPE>(arg1Val)), | |
504 nullptr, | |
505 flags); | |
506 } | |
507 return TRACE_EVENT_API_ADD_TRACE_EVENT( | |
508 phase, categoryEnabled, name, scope, id, bindId, timestamp, | |
509 numArgs, &arg1Name, argTypes, argValues, | |
510 flags); | |
511 } | |
512 | |
513 template<typename ARG1_TYPE, typename ARG2_TYPE> | |
514 static inline TraceEventHandle addTraceEvent( | |
515 char phase, | |
516 const unsigned char* categoryEnabled, | |
517 const char* name, | |
518 const char* scope, | |
519 unsigned long long id, | |
520 unsigned long long bindId, | |
521 double timestamp, | |
522 unsigned flags, | |
523 const char* arg1Name, | |
524 ARG1_TYPE&& arg1Val, | |
525 const char* arg2Name, | |
526 ARG2_TYPE&& arg2Val) | |
527 { | |
528 const int numArgs = 2; | |
529 const char* argNames[2] = { arg1Name, arg2Name }; | |
530 unsigned char argTypes[2]; | |
531 unsigned long long argValues[2]; | |
532 setTraceValue(arg1Val, &argTypes[0], &argValues[0]); | |
533 setTraceValue(arg2Val, &argTypes[1], &argValues[1]); | |
534 if (isTracedValue(arg1Val) || isTracedValue(arg2Val)) { | |
535 return TRACE_EVENT_API_ADD_TRACE_EVENT( | |
536 phase, categoryEnabled, name, scope, id, bindId, timestamp, | |
537 numArgs, argNames, argTypes, argValues, | |
538 moveFromIfTracedValue(std::forward<ARG1_TYPE>(arg1Val)), | |
539 moveFromIfTracedValue(std::forward<ARG2_TYPE>(arg2Val)), | |
540 flags); | |
541 } | |
542 return TRACE_EVENT_API_ADD_TRACE_EVENT( | |
543 phase, categoryEnabled, name, scope, id, bindId, timestamp, | |
544 numArgs, argNames, argTypes, argValues, | |
545 flags); | |
546 } | |
547 | |
548 static inline TraceEventHandle addTraceEvent( | |
549 char phase, | |
550 const unsigned char* categoryEnabled, | |
551 const char* name, | |
552 const char* scope, | |
553 unsigned long long id, | |
554 unsigned flags) | |
555 { | |
556 return addTraceEvent(phase, categoryEnabled, name, scope, id, | |
557 blink::TraceEvent::noBindId, EventTracer::systemTraceTime(), flags); | |
558 } | |
559 | |
560 template<typename ARG1_TYPE> | |
561 static inline TraceEventHandle addTraceEvent( | |
562 char phase, | |
563 const unsigned char* categoryEnabled, | |
564 const char* name, | |
565 const char* scope, | |
566 unsigned long long id, | |
567 unsigned flags, | |
568 const char* arg1Name, | |
569 ARG1_TYPE&& arg1Val) | |
570 { | |
571 return addTraceEvent(phase, categoryEnabled, name, scope, id, | |
572 blink::TraceEvent::noBindId, EventTracer::systemTraceTime(), flags, | |
573 arg1Name, std::forward<ARG1_TYPE>(arg1Val)); | |
574 } | |
575 | |
576 | |
577 template<typename ARG1_TYPE, typename ARG2_TYPE> | |
578 static inline TraceEventHandle addTraceEvent( | |
579 char phase, | |
580 const unsigned char* categoryEnabled, | |
581 const char* name, | |
582 const char* scope, | |
583 unsigned long long id, | |
584 unsigned flags, | |
585 const char* arg1Name, | |
586 ARG1_TYPE&& arg1Val, | |
587 const char* arg2Name, | |
588 ARG2_TYPE&& arg2Val) | |
589 { | |
590 return addTraceEvent(phase, categoryEnabled, name, scope, id, | |
591 blink::TraceEvent::noBindId, EventTracer::systemTraceTime(), flags, | |
592 arg1Name, std::forward<ARG1_TYPE>(arg1Val), | |
593 arg2Name, std::forward<ARG2_TYPE>(arg2Val)); | |
594 } | |
595 | |
596 // Used by TRACE_EVENTx macro. Do not use directly. | |
597 class ScopedTracer final { | |
598 STACK_ALLOCATED(); | |
599 WTF_MAKE_NONCOPYABLE(ScopedTracer); | |
600 public: | |
601 // Note: members of m_data intentionally left uninitialized. See initialize. | |
602 ScopedTracer() : m_pdata(0) { } | |
603 ~ScopedTracer() | |
604 { | |
605 if (m_pdata && *m_pdata->categoryGroupEnabled) | |
606 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(m_data.categoryGroupEnab
led, m_data.name, m_data.eventHandle); | |
607 } | |
608 | |
609 void initialize(const unsigned char* categoryGroupEnabled, const char* name,
TraceEventHandle eventHandle) | |
610 { | |
611 m_data.categoryGroupEnabled = categoryGroupEnabled; | |
612 m_data.name = name; | |
613 m_data.eventHandle = eventHandle; | |
614 m_pdata = &m_data; | |
615 } | |
616 | |
617 private: | |
618 // This Data struct workaround is to avoid initializing all the members | |
619 // in Data during construction of this object, since this object is always | |
620 // constructed, even when tracing is disabled. If the members of Data were | |
621 // members of this class instead, compiler warnings occur about potential | |
622 // uninitialized accesses. | |
623 struct Data { | |
624 DISALLOW_NEW(); | |
625 const unsigned char* categoryGroupEnabled; | |
626 const char* name; | |
627 TraceEventHandle eventHandle; | |
628 }; | |
629 Data* m_pdata; | |
630 Data m_data; | |
631 }; | |
632 | |
633 // TraceEventSamplingStateScope records the current sampling state | |
634 // and sets a new sampling state. When the scope exists, it restores | |
635 // the sampling state having recorded. | |
636 template<size_t BucketNumber> | |
637 class SamplingStateScope final { | |
638 STACK_ALLOCATED(); | |
639 WTF_MAKE_NONCOPYABLE(SamplingStateScope); | |
640 public: | |
641 SamplingStateScope(const char* categoryAndName) | |
642 { | |
643 m_previousState = SamplingStateScope<BucketNumber>::current(); | |
644 SamplingStateScope<BucketNumber>::set(categoryAndName); | |
645 } | |
646 | |
647 ~SamplingStateScope() | |
648 { | |
649 SamplingStateScope<BucketNumber>::set(m_previousState); | |
650 } | |
651 | |
652 // FIXME: Make load/store to traceSamplingState[] thread-safe and atomic. | |
653 static const char* current() | |
654 { | |
655 return reinterpret_cast<const char*>(*blink::traceSamplingState[BucketNu
mber]); | |
656 } | |
657 static void set(const char* categoryAndName) | |
658 { | |
659 *blink::traceSamplingState[BucketNumber] = reinterpret_cast<TraceEventAP
IAtomicWord>(categoryAndName); | |
660 } | |
661 | |
662 private: | |
663 const char* m_previousState; | |
664 }; | |
665 | |
666 template<typename IDType> class TraceScopedTrackableObject { | |
667 STACK_ALLOCATED(); | |
668 WTF_MAKE_NONCOPYABLE(TraceScopedTrackableObject); | |
669 public: | |
670 TraceScopedTrackableObject(const char* categoryGroup, const char* name, IDTy
pe id) | |
671 : m_categoryGroup(categoryGroup), m_name(name), m_id(id) | |
672 { | |
673 TRACE_EVENT_OBJECT_CREATED_WITH_ID(m_categoryGroup, m_name, m_id); | |
674 } | |
675 | |
676 ~TraceScopedTrackableObject() | |
677 { | |
678 TRACE_EVENT_OBJECT_DELETED_WITH_ID(m_categoryGroup, m_name, m_id); | |
679 } | |
680 | |
681 private: | |
682 const char* m_categoryGroup; | |
683 const char* m_name; | |
684 IDType m_id; | |
685 }; | |
686 | |
687 } // namespace TraceEvent | 35 } // namespace TraceEvent |
688 | |
689 } // namespace blink | 36 } // namespace blink |
690 | 37 |
691 #endif | 38 #endif |
OLD | NEW |