| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 2011 Google Inc. All rights reserved. | |
| 3 * | |
| 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 | |
| 30 #ifndef TraceEvent_h | |
| 31 #define TraceEvent_h | |
| 32 | |
| 33 #include "platform/EventTracer.h" | |
| 34 #include "platform/TraceEventCommon.h" | |
| 35 | |
| 36 #include "platform/TracedValue.h" | |
| 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 | |
| 43 //////////////////////////////////////////////////////////////////////////////// | |
| 44 // Implementation specific tracing API definitions. | |
| 45 | |
| 46 // By default, const char* argument values are assumed to have long-lived scope | |
| 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 | |
| 278 namespace blink { | |
| 279 | |
| 280 namespace TraceEvent { | |
| 281 | |
| 282 // Specify these values when the corresponding argument of addTraceEvent is not | |
| 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 | |
| 289 // TraceID encapsulates an ID that can either be an integer or pointer; | |
| 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 { | |
| 419 TraceValueUnion typeValue; | |
| 420 typeValue.m_string = arg.data(); | |
| 421 *type = TRACE_VALUE_TYPE_COPY_STRING; | |
| 422 *value = typeValue.m_uint; | |
| 423 } | |
| 424 | |
| 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 | |
| 688 | |
| 689 } // namespace blink | |
| 690 | |
| 691 #endif | |
| OLD | NEW |