Home | History | Annotate | Download | only in trace_event
      1 // Copyright (c) 2012 The Chromium 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 BASE_TRACE_EVENT_TRACE_EVENT_H_
      6 #define BASE_TRACE_EVENT_TRACE_EVENT_H_
      7 
      8 // This header file defines implementation details of how the trace macros in
      9 // trace_event_common.h collect and store trace events. Anything not
     10 // implementation-specific should go in trace_event_common.h instead of here.
     11 
     12 #include <stddef.h>
     13 #include <stdint.h>
     14 
     15 #include <string>
     16 
     17 #include "base/atomicops.h"
     18 #include "base/macros.h"
     19 #include "base/time/time.h"
     20 #include "base/trace_event/common/trace_event_common.h"
     21 #include "base/trace_event/heap_profiler.h"
     22 #include "base/trace_event/trace_category.h"
     23 #include "base/trace_event/trace_event_system_stats_monitor.h"
     24 #include "base/trace_event/trace_log.h"
     25 #include "build/build_config.h"
     26 
     27 // By default, const char* argument values are assumed to have long-lived scope
     28 // and will not be copied. Use this macro to force a const char* to be copied.
     29 #define TRACE_STR_COPY(str) \
     30     trace_event_internal::TraceStringWithCopy(str)
     31 
     32 // DEPRECATED: do not use: Consider using TRACE_ID_{GLOBAL, LOCAL} macros,
     33 // instead. By default, uint64_t ID argument values are not mangled with the
     34 // Process ID in TRACE_EVENT_ASYNC macros. Use this macro to force Process ID
     35 // mangling.
     36 #define TRACE_ID_MANGLE(id) \
     37     trace_event_internal::TraceID::ForceMangle(id)
     38 
     39 // DEPRECATED: do not use: Consider using TRACE_ID_{GLOBAL, LOCAL} macros,
     40 // instead. By default, pointers are mangled with the Process ID in
     41 // TRACE_EVENT_ASYNC macros. Use this macro to prevent Process ID mangling.
     42 #define TRACE_ID_DONT_MANGLE(id) \
     43     trace_event_internal::TraceID::DontMangle(id)
     44 
     45 // By default, trace IDs are eventually converted to a single 64-bit number. Use
     46 // this macro to add a scope string. For example,
     47 //
     48 // TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(
     49 //     "network", "ResourceLoad",
     50 //     TRACE_ID_WITH_SCOPE("BlinkResourceID", resourceID));
     51 //
     52 // Also, it is possible to prepend the ID with another number, like the process
     53 // ID. This is useful in creatin IDs that are unique among all processes. To do
     54 // that, pass two numbers after the scope string instead of one. For example,
     55 //
     56 // TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(
     57 //     "network", "ResourceLoad",
     58 //     TRACE_ID_WITH_SCOPE("BlinkResourceID", pid, resourceID));
     59 #define TRACE_ID_WITH_SCOPE(scope, ...) \
     60   trace_event_internal::TraceID::WithScope(scope, ##__VA_ARGS__)
     61 
     62 #define TRACE_ID_GLOBAL(id) trace_event_internal::TraceID::GlobalId(id)
     63 #define TRACE_ID_LOCAL(id) trace_event_internal::TraceID::LocalId(id)
     64 
     65 #define TRACE_EVENT_API_CURRENT_THREAD_ID \
     66   static_cast<int>(base::PlatformThread::CurrentId())
     67 
     68 #define INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE() \
     69   UNLIKELY(*INTERNAL_TRACE_EVENT_UID(category_group_enabled) &           \
     70            (base::trace_event::TraceCategory::ENABLED_FOR_RECORDING |    \
     71             base::trace_event::TraceCategory::ENABLED_FOR_ETW_EXPORT))
     72 
     73 #define INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()                  \
     74   UNLIKELY(*INTERNAL_TRACE_EVENT_UID(category_group_enabled) &         \
     75            (base::trace_event::TraceCategory::ENABLED_FOR_RECORDING |  \
     76             base::trace_event::TraceCategory::ENABLED_FOR_ETW_EXPORT | \
     77             base::trace_event::TraceCategory::ENABLED_FOR_FILTERING))
     78 
     79 ////////////////////////////////////////////////////////////////////////////////
     80 // Implementation specific tracing API definitions.
     81 
     82 // Get a pointer to the enabled state of the given trace category. Only
     83 // long-lived literal strings should be given as the category group. The
     84 // returned pointer can be held permanently in a local static for example. If
     85 // the unsigned char is non-zero, tracing is enabled. If tracing is enabled,
     86 // TRACE_EVENT_API_ADD_TRACE_EVENT can be called. It's OK if tracing is disabled
     87 // between the load of the tracing state and the call to
     88 // TRACE_EVENT_API_ADD_TRACE_EVENT, because this flag only provides an early out
     89 // for best performance when tracing is disabled.
     90 // const unsigned char*
     91 //     TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(const char* category_group)
     92 #define TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED \
     93     base::trace_event::TraceLog::GetCategoryGroupEnabled
     94 
     95 // Get the number of times traces have been recorded. This is used to implement
     96 // the TRACE_EVENT_IS_NEW_TRACE facility.
     97 // unsigned int TRACE_EVENT_API_GET_NUM_TRACES_RECORDED()
     98 #define TRACE_EVENT_API_GET_NUM_TRACES_RECORDED \
     99     base::trace_event::TraceLog::GetInstance()->GetNumTracesRecorded
    100 
    101 // Add a trace event to the platform tracing system.
    102 // base::trace_event::TraceEventHandle TRACE_EVENT_API_ADD_TRACE_EVENT(
    103 //                    char phase,
    104 //                    const unsigned char* category_group_enabled,
    105 //                    const char* name,
    106 //                    const char* scope,
    107 //                    unsigned long long id,
    108 //                    int num_args,
    109 //                    const char** arg_names,
    110 //                    const unsigned char* arg_types,
    111 //                    const unsigned long long* arg_values,
    112 //                    std::unique_ptr<ConvertableToTraceFormat>*
    113 //                    convertable_values,
    114 //                    unsigned int flags)
    115 #define TRACE_EVENT_API_ADD_TRACE_EVENT \
    116     base::trace_event::TraceLog::GetInstance()->AddTraceEvent
    117 
    118 // Add a trace event to the platform tracing system.
    119 // base::trace_event::TraceEventHandle
    120 // TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_BIND_ID(
    121 //                    char phase,
    122 //                    const unsigned char* category_group_enabled,
    123 //                    const char* name,
    124 //                    const char* scope,
    125 //                    unsigned long long id,
    126 //                    unsigned long long bind_id,
    127 //                    int num_args,
    128 //                    const char** arg_names,
    129 //                    const unsigned char* arg_types,
    130 //                    const unsigned long long* arg_values,
    131 //                    std::unique_ptr<ConvertableToTraceFormat>*
    132 //                    convertable_values,
    133 //                    unsigned int flags)
    134 #define TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_BIND_ID \
    135   base::trace_event::TraceLog::GetInstance()->AddTraceEventWithBindId
    136 
    137 // Add a trace event to the platform tracing system overriding the pid.
    138 // The resulting event will have tid = pid == (process_id passed here).
    139 // base::trace_event::TraceEventHandle
    140 // TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_PROCESS_ID(
    141 //                    char phase,
    142 //                    const unsigned char* category_group_enabled,
    143 //                    const char* name,
    144 //                    const char* scope,
    145 //                    unsigned long long id,
    146 //                    int process_id,
    147 //                    int num_args,
    148 //                    const char** arg_names,
    149 //                    const unsigned char* arg_types,
    150 //                    const unsigned long long* arg_values,
    151 //                    std::unique_ptr<ConvertableToTraceFormat>*
    152 //                    convertable_values,
    153 //                    unsigned int flags)
    154 #define TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_PROCESS_ID \
    155   base::trace_event::TraceLog::GetInstance()->AddTraceEventWithProcessId
    156 
    157 // Add a trace event to the platform tracing system.
    158 // base::trace_event::TraceEventHandle
    159 // TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP(
    160 //                    char phase,
    161 //                    const unsigned char* category_group_enabled,
    162 //                    const char* name,
    163 //                    const char* scope,
    164 //                    unsigned long long id,
    165 //                    int thread_id,
    166 //                    const TimeTicks& timestamp,
    167 //                    int num_args,
    168 //                    const char** arg_names,
    169 //                    const unsigned char* arg_types,
    170 //                    const unsigned long long* arg_values,
    171 //                    std::unique_ptr<ConvertableToTraceFormat>*
    172 //                    convertable_values,
    173 //                    unsigned int flags)
    174 #define TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP \
    175     base::trace_event::TraceLog::GetInstance() \
    176       ->AddTraceEventWithThreadIdAndTimestamp
    177 
    178 // Set the duration field of a COMPLETE trace event.
    179 // void TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(
    180 //     const unsigned char* category_group_enabled,
    181 //     const char* name,
    182 //     base::trace_event::TraceEventHandle id)
    183 #define TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION \
    184     base::trace_event::TraceLog::GetInstance()->UpdateTraceEventDuration
    185 
    186 // Adds a metadata event to the trace log. The |AppendValueAsTraceFormat| method
    187 // on the convertable value will be called at flush time.
    188 // TRACE_EVENT_API_ADD_METADATA_EVENT(
    189 //     const unsigned char* category_group_enabled,
    190 //     const char* event_name,
    191 //     const char* arg_name,
    192 //     std::unique_ptr<ConvertableToTraceFormat> arg_value)
    193 #define TRACE_EVENT_API_ADD_METADATA_EVENT \
    194     trace_event_internal::AddMetadataEvent
    195 
    196 // Defines atomic operations used internally by the tracing system.
    197 #define TRACE_EVENT_API_ATOMIC_WORD base::subtle::AtomicWord
    198 #define TRACE_EVENT_API_ATOMIC_LOAD(var) base::subtle::NoBarrier_Load(&(var))
    199 #define TRACE_EVENT_API_ATOMIC_STORE(var, value) \
    200     base::subtle::NoBarrier_Store(&(var), (value))
    201 
    202 // Defines visibility for classes in trace_event.h
    203 #define TRACE_EVENT_API_CLASS_EXPORT BASE_EXPORT
    204 
    205 ////////////////////////////////////////////////////////////////////////////////
    206 
    207 // Implementation detail: trace event macros create temporary variables
    208 // to keep instrumentation overhead low. These macros give each temporary
    209 // variable a unique name based on the line number to prevent name collisions.
    210 #define INTERNAL_TRACE_EVENT_UID3(a,b) \
    211     trace_event_unique_##a##b
    212 #define INTERNAL_TRACE_EVENT_UID2(a,b) \
    213     INTERNAL_TRACE_EVENT_UID3(a,b)
    214 #define INTERNAL_TRACE_EVENT_UID(name_prefix) \
    215     INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__)
    216 
    217 // Implementation detail: internal macro to create static category.
    218 // No barriers are needed, because this code is designed to operate safely
    219 // even when the unsigned char* points to garbage data (which may be the case
    220 // on processors without cache coherency).
    221 #define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES( \
    222     category_group, atomic, category_group_enabled) \
    223     category_group_enabled = \
    224         reinterpret_cast<const unsigned char*>(TRACE_EVENT_API_ATOMIC_LOAD( \
    225             atomic)); \
    226     if (UNLIKELY(!category_group_enabled)) { \
    227       category_group_enabled = \
    228           TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_group); \
    229       TRACE_EVENT_API_ATOMIC_STORE(atomic, \
    230           reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD>( \
    231               category_group_enabled)); \
    232     }
    233 
    234 #define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group) \
    235     static TRACE_EVENT_API_ATOMIC_WORD INTERNAL_TRACE_EVENT_UID(atomic) = 0; \
    236     const unsigned char* INTERNAL_TRACE_EVENT_UID(category_group_enabled); \
    237     INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES(category_group, \
    238         INTERNAL_TRACE_EVENT_UID(atomic), \
    239         INTERNAL_TRACE_EVENT_UID(category_group_enabled));
    240 
    241 // Implementation detail: internal macro to create static category and add
    242 // event if the category is enabled.
    243 #define INTERNAL_TRACE_EVENT_ADD(phase, category_group, name, flags, ...)  \
    244   do {                                                                     \
    245     INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group);                \
    246     if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()) {                   \
    247       trace_event_internal::AddTraceEvent(                                 \
    248           phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name,   \
    249           trace_event_internal::kGlobalScope, trace_event_internal::kNoId, \
    250           flags, trace_event_internal::kNoId, ##__VA_ARGS__);              \
    251     }                                                                      \
    252   } while (0)
    253 
    254 // Implementation detail: internal macro to create static category and add begin
    255 // event if the category is enabled. Also adds the end event when the scope
    256 // ends.
    257 #define INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, ...)           \
    258   INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group);                    \
    259   trace_event_internal::ScopedTracer INTERNAL_TRACE_EVENT_UID(tracer);       \
    260   if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()) {                       \
    261     base::trace_event::TraceEventHandle h =                                  \
    262         trace_event_internal::AddTraceEvent(                                 \
    263             TRACE_EVENT_PHASE_COMPLETE,                                      \
    264             INTERNAL_TRACE_EVENT_UID(category_group_enabled), name,          \
    265             trace_event_internal::kGlobalScope, trace_event_internal::kNoId, \
    266             TRACE_EVENT_FLAG_NONE, trace_event_internal::kNoId,              \
    267             ##__VA_ARGS__);                                                  \
    268     INTERNAL_TRACE_EVENT_UID(tracer).Initialize(                             \
    269         INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, h);          \
    270   }
    271 
    272 #define INTERNAL_TRACE_EVENT_ADD_SCOPED_WITH_FLOW(category_group, name,      \
    273                                                   bind_id, flow_flags, ...)  \
    274   INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group);                    \
    275   trace_event_internal::ScopedTracer INTERNAL_TRACE_EVENT_UID(tracer);       \
    276   if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()) {                       \
    277     trace_event_internal::TraceID trace_event_bind_id((bind_id));            \
    278     unsigned int trace_event_flags =                                         \
    279         flow_flags | trace_event_bind_id.id_flags();                         \
    280     base::trace_event::TraceEventHandle h =                                  \
    281         trace_event_internal::AddTraceEvent(                                 \
    282             TRACE_EVENT_PHASE_COMPLETE,                                      \
    283             INTERNAL_TRACE_EVENT_UID(category_group_enabled), name,          \
    284             trace_event_internal::kGlobalScope, trace_event_internal::kNoId, \
    285             trace_event_flags, trace_event_bind_id.raw_id(), ##__VA_ARGS__); \
    286     INTERNAL_TRACE_EVENT_UID(tracer).Initialize(                             \
    287         INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, h);          \
    288   }
    289 
    290 // Implementation detail: internal macro to create static category and add
    291 // event if the category is enabled.
    292 #define INTERNAL_TRACE_EVENT_ADD_WITH_ID(phase, category_group, name, id, \
    293                                          flags, ...)                      \
    294   do {                                                                    \
    295     INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group);               \
    296     if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()) {                  \
    297       trace_event_internal::TraceID trace_event_trace_id((id));           \
    298       unsigned int trace_event_flags =                                    \
    299           flags | trace_event_trace_id.id_flags();                        \
    300       trace_event_internal::AddTraceEvent(                                \
    301           phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name,  \
    302           trace_event_trace_id.scope(), trace_event_trace_id.raw_id(),    \
    303           trace_event_flags, trace_event_internal::kNoId, ##__VA_ARGS__); \
    304     }                                                                     \
    305   } while (0)
    306 
    307 // Implementation detail: internal macro to create static category and add
    308 // event if the category is enabled.
    309 #define INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP(phase, category_group, name, \
    310                                                 timestamp, flags, ...)       \
    311   do {                                                                       \
    312     INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group);                  \
    313     if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()) {                     \
    314       trace_event_internal::AddTraceEventWithThreadIdAndTimestamp(           \
    315           phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name,     \
    316           trace_event_internal::kGlobalScope, trace_event_internal::kNoId,   \
    317           TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp,                      \
    318           flags | TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP,                       \
    319           trace_event_internal::kNoId, ##__VA_ARGS__);                       \
    320     }                                                                        \
    321   } while (0)
    322 
    323 // Implementation detail: internal macro to create static category and add
    324 // event if the category is enabled.
    325 #define INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP(              \
    326     phase, category_group, name, id, thread_id, timestamp, flags, ...)   \
    327   do {                                                                   \
    328     INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group);              \
    329     if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()) {                 \
    330       trace_event_internal::TraceID trace_event_trace_id((id));          \
    331       unsigned int trace_event_flags =                                   \
    332           flags | trace_event_trace_id.id_flags();                       \
    333       trace_event_internal::AddTraceEventWithThreadIdAndTimestamp(       \
    334           phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
    335           trace_event_trace_id.scope(), trace_event_trace_id.raw_id(),   \
    336           thread_id, timestamp,                                          \
    337           trace_event_flags | TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP,       \
    338           trace_event_internal::kNoId, ##__VA_ARGS__);                   \
    339     }                                                                    \
    340   } while (0)
    341 
    342 // The linked ID will not be mangled.
    343 #define INTERNAL_TRACE_EVENT_ADD_LINK_IDS(category_group, name, id1, id2) \
    344   do {                                                                    \
    345     INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group);               \
    346     if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()) {                  \
    347       trace_event_internal::TraceID source_id((id1));                     \
    348       unsigned int source_flags = source_id.id_flags();                   \
    349       trace_event_internal::TraceID target_id((id2));                     \
    350       trace_event_internal::AddTraceEvent(                                \
    351           TRACE_EVENT_PHASE_LINK_IDS,                                     \
    352           INTERNAL_TRACE_EVENT_UID(category_group_enabled), name,         \
    353           source_id.scope(), source_id.raw_id(), source_flags,            \
    354           trace_event_internal::kNoId, "linked_id",                       \
    355           target_id.AsConvertableToTraceFormat());                        \
    356     }                                                                     \
    357   } while (0)
    358 
    359 // Implementation detail: internal macro to create static category and add
    360 // metadata event if the category is enabled.
    361 #define INTERNAL_TRACE_EVENT_METADATA_ADD(category_group, name, ...) \
    362   do {                                                               \
    363     INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group);          \
    364     if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()) {             \
    365       TRACE_EVENT_API_ADD_METADATA_EVENT(                            \
    366           INTERNAL_TRACE_EVENT_UID(category_group_enabled), name,    \
    367           ##__VA_ARGS__);                                            \
    368     }                                                                \
    369   } while (0)
    370 
    371 // Implementation detail: internal macro to enter and leave a
    372 // context based on the current scope.
    373 #define INTERNAL_TRACE_EVENT_SCOPED_CONTEXT(category_group, name, context) \
    374   struct INTERNAL_TRACE_EVENT_UID(ScopedContext) {                         \
    375    public:                                                                 \
    376     INTERNAL_TRACE_EVENT_UID(ScopedContext)(uint64_t cid) : cid_(cid) {    \
    377       TRACE_EVENT_ENTER_CONTEXT(category_group, name, cid_);               \
    378     }                                                                      \
    379     ~INTERNAL_TRACE_EVENT_UID(ScopedContext)() {                           \
    380       TRACE_EVENT_LEAVE_CONTEXT(category_group, name, cid_);               \
    381     }                                                                      \
    382                                                                            \
    383    private:                                                                \
    384     uint64_t cid_;                                                         \
    385     /* Local class friendly DISALLOW_COPY_AND_ASSIGN */                    \
    386     INTERNAL_TRACE_EVENT_UID(ScopedContext)                                \
    387     (const INTERNAL_TRACE_EVENT_UID(ScopedContext)&) {};                   \
    388     void operator=(const INTERNAL_TRACE_EVENT_UID(ScopedContext)&) {};     \
    389   };                                                                       \
    390   INTERNAL_TRACE_EVENT_UID(ScopedContext)                                  \
    391   INTERNAL_TRACE_EVENT_UID(scoped_context)(context);
    392 
    393 // Implementation detail: internal macro to trace a task execution with the
    394 // location where it was posted from.
    395 #define INTERNAL_TRACE_TASK_EXECUTION(run_function, task)                 \
    396   TRACE_EVENT2("toplevel", run_function, "src_file",                      \
    397                (task).posted_from.file_name(), "src_func",                \
    398                (task).posted_from.function_name());                       \
    399   TRACE_HEAP_PROFILER_API_SCOPED_TASK_EXECUTION INTERNAL_TRACE_EVENT_UID( \
    400       task_event)((task).posted_from.file_name());
    401 
    402 namespace trace_event_internal {
    403 
    404 // Specify these values when the corresponding argument of AddTraceEvent is not
    405 // used.
    406 const int kZeroNumArgs = 0;
    407 const std::nullptr_t kGlobalScope = nullptr;
    408 const unsigned long long kNoId = 0;
    409 
    410 // TraceID encapsulates an ID that can either be an integer or pointer. Pointers
    411 // are by default mangled with the Process ID so that they are unlikely to
    412 // collide when the same pointer is used on different processes.
    413 class BASE_EXPORT TraceID {
    414  public:
    415   // Can be combined with WithScope.
    416   class LocalId {
    417    public:
    418     explicit LocalId(unsigned long long raw_id) : raw_id_(raw_id) {}
    419     unsigned long long raw_id() const { return raw_id_; }
    420    private:
    421     unsigned long long raw_id_;
    422   };
    423 
    424   // Can be combined with WithScope.
    425   class GlobalId {
    426    public:
    427     explicit GlobalId(unsigned long long raw_id) : raw_id_(raw_id) {}
    428     unsigned long long raw_id() const { return raw_id_; }
    429    private:
    430     unsigned long long raw_id_;
    431   };
    432 
    433   class WithScope {
    434    public:
    435     WithScope(const char* scope, unsigned long long raw_id)
    436         : scope_(scope), raw_id_(raw_id) {}
    437     WithScope(const char* scope, LocalId local_id)
    438         : scope_(scope), raw_id_(local_id.raw_id()) {
    439       id_flags_ = TRACE_EVENT_FLAG_HAS_LOCAL_ID;
    440     }
    441     WithScope(const char* scope, GlobalId global_id)
    442         : scope_(scope), raw_id_(global_id.raw_id()) {
    443       id_flags_ = TRACE_EVENT_FLAG_HAS_GLOBAL_ID;
    444     }
    445     WithScope(const char* scope,
    446               unsigned long long prefix,
    447               unsigned long long raw_id)
    448         : scope_(scope), has_prefix_(true), prefix_(prefix), raw_id_(raw_id) {}
    449     WithScope(const char* scope, unsigned long long prefix, GlobalId global_id)
    450         : scope_(scope),
    451           has_prefix_(true),
    452           prefix_(prefix),
    453           raw_id_(global_id.raw_id()) {
    454       id_flags_ = TRACE_EVENT_FLAG_HAS_GLOBAL_ID;
    455     }
    456     unsigned long long raw_id() const { return raw_id_; }
    457     const char* scope() const { return scope_; }
    458     bool has_prefix() const { return has_prefix_; }
    459     unsigned long long prefix() const { return prefix_; }
    460     unsigned int id_flags() const { return id_flags_; }
    461 
    462    private:
    463     const char* scope_ = nullptr;
    464     bool has_prefix_ = false;
    465     unsigned long long prefix_;
    466     unsigned long long raw_id_;
    467     unsigned int id_flags_ = TRACE_EVENT_FLAG_HAS_ID;
    468   };
    469 
    470   // DEPRECATED: consider using LocalId or GlobalId, instead.
    471   class DontMangle {
    472    public:
    473     explicit DontMangle(const void* raw_id)
    474         : raw_id_(static_cast<unsigned long long>(
    475               reinterpret_cast<uintptr_t>(raw_id))) {}
    476     explicit DontMangle(unsigned long long raw_id) : raw_id_(raw_id) {}
    477     explicit DontMangle(unsigned long raw_id) : raw_id_(raw_id) {}
    478     explicit DontMangle(unsigned int raw_id) : raw_id_(raw_id) {}
    479     explicit DontMangle(unsigned short raw_id) : raw_id_(raw_id) {}
    480     explicit DontMangle(unsigned char raw_id) : raw_id_(raw_id) {}
    481     explicit DontMangle(long long raw_id)
    482         : raw_id_(static_cast<unsigned long long>(raw_id)) {}
    483     explicit DontMangle(long raw_id)
    484         : raw_id_(static_cast<unsigned long long>(raw_id)) {}
    485     explicit DontMangle(int raw_id)
    486         : raw_id_(static_cast<unsigned long long>(raw_id)) {}
    487     explicit DontMangle(short raw_id)
    488         : raw_id_(static_cast<unsigned long long>(raw_id)) {}
    489     explicit DontMangle(signed char raw_id)
    490         : raw_id_(static_cast<unsigned long long>(raw_id)) {}
    491     unsigned long long raw_id() const { return raw_id_; }
    492    private:
    493     unsigned long long raw_id_;
    494   };
    495 
    496   // DEPRECATED: consider using LocalId or GlobalId, instead.
    497   class ForceMangle {
    498    public:
    499     explicit ForceMangle(unsigned long long raw_id) : raw_id_(raw_id) {}
    500     explicit ForceMangle(unsigned long raw_id) : raw_id_(raw_id) {}
    501     explicit ForceMangle(unsigned int raw_id) : raw_id_(raw_id) {}
    502     explicit ForceMangle(unsigned short raw_id) : raw_id_(raw_id) {}
    503     explicit ForceMangle(unsigned char raw_id) : raw_id_(raw_id) {}
    504     explicit ForceMangle(long long raw_id)
    505         : raw_id_(static_cast<unsigned long long>(raw_id)) {}
    506     explicit ForceMangle(long raw_id)
    507         : raw_id_(static_cast<unsigned long long>(raw_id)) {}
    508     explicit ForceMangle(int raw_id)
    509         : raw_id_(static_cast<unsigned long long>(raw_id)) {}
    510     explicit ForceMangle(short raw_id)
    511         : raw_id_(static_cast<unsigned long long>(raw_id)) {}
    512     explicit ForceMangle(signed char raw_id)
    513         : raw_id_(static_cast<unsigned long long>(raw_id)) {}
    514     unsigned long long raw_id() const { return raw_id_; }
    515    private:
    516     unsigned long long raw_id_;
    517   };
    518 
    519   TraceID(const void* raw_id) : raw_id_(static_cast<unsigned long long>(
    520                                         reinterpret_cast<uintptr_t>(raw_id))) {
    521     id_flags_ = TRACE_EVENT_FLAG_HAS_ID | TRACE_EVENT_FLAG_MANGLE_ID;
    522   }
    523   TraceID(ForceMangle raw_id) : raw_id_(raw_id.raw_id()) {
    524     id_flags_ = TRACE_EVENT_FLAG_HAS_ID | TRACE_EVENT_FLAG_MANGLE_ID;
    525   }
    526   TraceID(DontMangle raw_id) : raw_id_(raw_id.raw_id()) {}
    527   TraceID(unsigned long long raw_id) : raw_id_(raw_id) {}
    528   TraceID(unsigned long raw_id) : raw_id_(raw_id) {}
    529   TraceID(unsigned int raw_id) : raw_id_(raw_id) {}
    530   TraceID(unsigned short raw_id) : raw_id_(raw_id) {}
    531   TraceID(unsigned char raw_id) : raw_id_(raw_id) {}
    532   TraceID(long long raw_id)
    533       : raw_id_(static_cast<unsigned long long>(raw_id)) {}
    534   TraceID(long raw_id)
    535       : raw_id_(static_cast<unsigned long long>(raw_id)) {}
    536   TraceID(int raw_id)
    537       : raw_id_(static_cast<unsigned long long>(raw_id)) {}
    538   TraceID(short raw_id)
    539       : raw_id_(static_cast<unsigned long long>(raw_id)) {}
    540   TraceID(signed char raw_id)
    541       : raw_id_(static_cast<unsigned long long>(raw_id)) {}
    542   TraceID(LocalId raw_id) : raw_id_(raw_id.raw_id()) {
    543     id_flags_ = TRACE_EVENT_FLAG_HAS_LOCAL_ID;
    544   }
    545   TraceID(GlobalId raw_id) : raw_id_(raw_id.raw_id()) {
    546     id_flags_ = TRACE_EVENT_FLAG_HAS_GLOBAL_ID;
    547   }
    548   TraceID(WithScope scoped_id)
    549       : scope_(scoped_id.scope()),
    550         has_prefix_(scoped_id.has_prefix()),
    551         prefix_(scoped_id.prefix()),
    552         raw_id_(scoped_id.raw_id()),
    553         id_flags_(scoped_id.id_flags()) {}
    554 
    555   unsigned long long raw_id() const { return raw_id_; }
    556   const char* scope() const { return scope_; }
    557   bool has_prefix() const { return has_prefix_; }
    558   unsigned long long prefix() const { return prefix_; }
    559   unsigned int id_flags() const { return id_flags_; }
    560 
    561   std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
    562   AsConvertableToTraceFormat() const;
    563 
    564  private:
    565   const char* scope_ = nullptr;
    566   bool has_prefix_ = false;
    567   unsigned long long prefix_;
    568   unsigned long long raw_id_;
    569   unsigned int id_flags_ = TRACE_EVENT_FLAG_HAS_ID;
    570 };
    571 
    572 // Simple union to store various types as unsigned long long.
    573 union TraceValueUnion {
    574   bool as_bool;
    575   unsigned long long as_uint;
    576   long long as_int;
    577   double as_double;
    578   const void* as_pointer;
    579   const char* as_string;
    580 };
    581 
    582 // Simple container for const char* that should be copied instead of retained.
    583 class TraceStringWithCopy {
    584  public:
    585   explicit TraceStringWithCopy(const char* str) : str_(str) {}
    586   const char* str() const { return str_; }
    587  private:
    588   const char* str_;
    589 };
    590 
    591 // Define SetTraceValue for each allowed type. It stores the type and
    592 // value in the return arguments. This allows this API to avoid declaring any
    593 // structures so that it is portable to third_party libraries.
    594 #define INTERNAL_DECLARE_SET_TRACE_VALUE(actual_type, \
    595                                          arg_expression, \
    596                                          union_member, \
    597                                          value_type_id) \
    598     static inline void SetTraceValue( \
    599         actual_type arg, \
    600         unsigned char* type, \
    601         unsigned long long* value) { \
    602       TraceValueUnion type_value; \
    603       type_value.union_member = arg_expression; \
    604       *type = value_type_id; \
    605       *value = type_value.as_uint; \
    606     }
    607 // Simpler form for int types that can be safely casted.
    608 #define INTERNAL_DECLARE_SET_TRACE_VALUE_INT(actual_type, \
    609                                              value_type_id) \
    610     static inline void SetTraceValue( \
    611         actual_type arg, \
    612         unsigned char* type, \
    613         unsigned long long* value) { \
    614       *type = value_type_id; \
    615       *value = static_cast<unsigned long long>(arg); \
    616     }
    617 
    618 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long long, TRACE_VALUE_TYPE_UINT)
    619 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long, TRACE_VALUE_TYPE_UINT)
    620 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned int, TRACE_VALUE_TYPE_UINT)
    621 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned short, TRACE_VALUE_TYPE_UINT)
    622 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned char, TRACE_VALUE_TYPE_UINT)
    623 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long long, TRACE_VALUE_TYPE_INT)
    624 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long, TRACE_VALUE_TYPE_INT)
    625 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int, TRACE_VALUE_TYPE_INT)
    626 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(short, TRACE_VALUE_TYPE_INT)
    627 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(signed char, TRACE_VALUE_TYPE_INT)
    628 INTERNAL_DECLARE_SET_TRACE_VALUE(bool, arg, as_bool, TRACE_VALUE_TYPE_BOOL)
    629 INTERNAL_DECLARE_SET_TRACE_VALUE(double, arg, as_double,
    630                                  TRACE_VALUE_TYPE_DOUBLE)
    631 INTERNAL_DECLARE_SET_TRACE_VALUE(const void*, arg, as_pointer,
    632                                  TRACE_VALUE_TYPE_POINTER)
    633 INTERNAL_DECLARE_SET_TRACE_VALUE(const char*, arg, as_string,
    634                                  TRACE_VALUE_TYPE_STRING)
    635 INTERNAL_DECLARE_SET_TRACE_VALUE(const TraceStringWithCopy&, arg.str(),
    636                                  as_string, TRACE_VALUE_TYPE_COPY_STRING)
    637 
    638 #undef INTERNAL_DECLARE_SET_TRACE_VALUE
    639 #undef INTERNAL_DECLARE_SET_TRACE_VALUE_INT
    640 
    641 // std::string version of SetTraceValue so that trace arguments can be strings.
    642 static inline void SetTraceValue(const std::string& arg,
    643                                  unsigned char* type,
    644                                  unsigned long long* value) {
    645   TraceValueUnion type_value;
    646   type_value.as_string = arg.c_str();
    647   *type = TRACE_VALUE_TYPE_COPY_STRING;
    648   *value = type_value.as_uint;
    649 }
    650 
    651 // base::Time, base::TimeTicks, etc. versions of SetTraceValue to make it easier
    652 // to trace these types.
    653 static inline void SetTraceValue(const base::Time arg,
    654                                  unsigned char* type,
    655                                  unsigned long long* value) {
    656   *type = TRACE_VALUE_TYPE_INT;
    657   *value = arg.ToInternalValue();
    658 }
    659 
    660 static inline void SetTraceValue(const base::TimeTicks arg,
    661                                  unsigned char* type,
    662                                  unsigned long long* value) {
    663   *type = TRACE_VALUE_TYPE_INT;
    664   *value = arg.ToInternalValue();
    665 }
    666 
    667 static inline void SetTraceValue(const base::ThreadTicks arg,
    668                                  unsigned char* type,
    669                                  unsigned long long* value) {
    670   *type = TRACE_VALUE_TYPE_INT;
    671   *value = arg.ToInternalValue();
    672 }
    673 
    674 // These AddTraceEvent and AddTraceEventWithThreadIdAndTimestamp template
    675 // functions are defined here instead of in the macro, because the arg_values
    676 // could be temporary objects, such as std::string. In order to store
    677 // pointers to the internal c_str and pass through to the tracing API,
    678 // the arg_values must live throughout these procedures.
    679 
    680 template <class ARG1_CONVERTABLE_TYPE>
    681 static inline base::trace_event::TraceEventHandle
    682 AddTraceEventWithThreadIdAndTimestamp(
    683     char phase,
    684     const unsigned char* category_group_enabled,
    685     const char* name,
    686     const char* scope,
    687     unsigned long long id,
    688     int thread_id,
    689     const base::TimeTicks& timestamp,
    690     unsigned int flags,
    691     unsigned long long bind_id,
    692     const char* arg1_name,
    693     std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg1_val) {
    694   const int num_args = 1;
    695   unsigned char arg_types[1] = { TRACE_VALUE_TYPE_CONVERTABLE };
    696   std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
    697       convertable_values[1] = {std::move(arg1_val)};
    698   return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
    699       phase, category_group_enabled, name, scope, id, bind_id, thread_id,
    700       timestamp, num_args, &arg1_name, arg_types, NULL, convertable_values,
    701       flags);
    702 }
    703 
    704 template <class ARG1_TYPE, class ARG2_CONVERTABLE_TYPE>
    705 static inline base::trace_event::TraceEventHandle
    706 AddTraceEventWithThreadIdAndTimestamp(
    707     char phase,
    708     const unsigned char* category_group_enabled,
    709     const char* name,
    710     const char* scope,
    711     unsigned long long id,
    712     int thread_id,
    713     const base::TimeTicks& timestamp,
    714     unsigned int flags,
    715     unsigned long long bind_id,
    716     const char* arg1_name,
    717     const ARG1_TYPE& arg1_val,
    718     const char* arg2_name,
    719     std::unique_ptr<ARG2_CONVERTABLE_TYPE> arg2_val) {
    720   const int num_args = 2;
    721   const char* arg_names[2] = { arg1_name, arg2_name };
    722 
    723   unsigned char arg_types[2];
    724   unsigned long long arg_values[2];
    725   SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]);
    726   arg_types[1] = TRACE_VALUE_TYPE_CONVERTABLE;
    727   std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
    728       convertable_values[2] = {nullptr, std::move(arg2_val)};
    729   return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
    730       phase, category_group_enabled, name, scope, id, bind_id, thread_id,
    731       timestamp, num_args, arg_names, arg_types, arg_values, convertable_values,
    732       flags);
    733 }
    734 
    735 template <class ARG1_CONVERTABLE_TYPE, class ARG2_TYPE>
    736 static inline base::trace_event::TraceEventHandle
    737 AddTraceEventWithThreadIdAndTimestamp(
    738     char phase,
    739     const unsigned char* category_group_enabled,
    740     const char* name,
    741     const char* scope,
    742     unsigned long long id,
    743     int thread_id,
    744     const base::TimeTicks& timestamp,
    745     unsigned int flags,
    746     unsigned long long bind_id,
    747     const char* arg1_name,
    748     std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg1_val,
    749     const char* arg2_name,
    750     const ARG2_TYPE& arg2_val) {
    751   const int num_args = 2;
    752   const char* arg_names[2] = { arg1_name, arg2_name };
    753 
    754   unsigned char arg_types[2];
    755   unsigned long long arg_values[2];
    756   arg_types[0] = TRACE_VALUE_TYPE_CONVERTABLE;
    757   arg_values[0] = 0;
    758   SetTraceValue(arg2_val, &arg_types[1], &arg_values[1]);
    759   std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
    760       convertable_values[2] = {std::move(arg1_val), nullptr};
    761   return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
    762       phase, category_group_enabled, name, scope, id, bind_id, thread_id,
    763       timestamp, num_args, arg_names, arg_types, arg_values, convertable_values,
    764       flags);
    765 }
    766 
    767 template <class ARG1_CONVERTABLE_TYPE, class ARG2_CONVERTABLE_TYPE>
    768 static inline base::trace_event::TraceEventHandle
    769 AddTraceEventWithThreadIdAndTimestamp(
    770     char phase,
    771     const unsigned char* category_group_enabled,
    772     const char* name,
    773     const char* scope,
    774     unsigned long long id,
    775     int thread_id,
    776     const base::TimeTicks& timestamp,
    777     unsigned int flags,
    778     unsigned long long bind_id,
    779     const char* arg1_name,
    780     std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg1_val,
    781     const char* arg2_name,
    782     std::unique_ptr<ARG2_CONVERTABLE_TYPE> arg2_val) {
    783   const int num_args = 2;
    784   const char* arg_names[2] = { arg1_name, arg2_name };
    785   unsigned char arg_types[2] =
    786       { TRACE_VALUE_TYPE_CONVERTABLE, TRACE_VALUE_TYPE_CONVERTABLE };
    787   std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
    788       convertable_values[2] = {std::move(arg1_val), std::move(arg2_val)};
    789   return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
    790       phase, category_group_enabled, name, scope, id, bind_id, thread_id,
    791       timestamp, num_args, arg_names, arg_types, NULL, convertable_values,
    792       flags);
    793 }
    794 
    795 static inline base::trace_event::TraceEventHandle
    796 AddTraceEventWithThreadIdAndTimestamp(
    797     char phase,
    798     const unsigned char* category_group_enabled,
    799     const char* name,
    800     const char* scope,
    801     unsigned long long id,
    802     int thread_id,
    803     const base::TimeTicks& timestamp,
    804     unsigned int flags,
    805     unsigned long long bind_id) {
    806   return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
    807       phase, category_group_enabled, name, scope, id, bind_id, thread_id,
    808       timestamp, kZeroNumArgs, NULL, NULL, NULL, NULL, flags);
    809 }
    810 
    811 static inline base::trace_event::TraceEventHandle AddTraceEvent(
    812     char phase,
    813     const unsigned char* category_group_enabled,
    814     const char* name,
    815     const char* scope,
    816     unsigned long long id,
    817     unsigned int flags,
    818     unsigned long long bind_id) {
    819   const int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
    820   const base::TimeTicks now = base::TimeTicks::Now();
    821   return AddTraceEventWithThreadIdAndTimestamp(
    822       phase, category_group_enabled, name, scope, id, thread_id, now, flags,
    823       bind_id);
    824 }
    825 
    826 template<class ARG1_TYPE>
    827 static inline base::trace_event::TraceEventHandle
    828 AddTraceEventWithThreadIdAndTimestamp(
    829     char phase,
    830     const unsigned char* category_group_enabled,
    831     const char* name,
    832     const char* scope,
    833     unsigned long long id,
    834     int thread_id,
    835     const base::TimeTicks& timestamp,
    836     unsigned int flags,
    837     unsigned long long bind_id,
    838     const char* arg1_name,
    839     const ARG1_TYPE& arg1_val) {
    840   const int num_args = 1;
    841   unsigned char arg_types[1];
    842   unsigned long long arg_values[1];
    843   SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]);
    844   return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
    845       phase, category_group_enabled, name, scope, id, bind_id, thread_id,
    846       timestamp, num_args, &arg1_name, arg_types, arg_values, NULL, flags);
    847 }
    848 
    849 template<class ARG1_TYPE>
    850 static inline base::trace_event::TraceEventHandle AddTraceEvent(
    851     char phase,
    852     const unsigned char* category_group_enabled,
    853     const char* name,
    854     const char* scope,
    855     unsigned long long id,
    856     unsigned int flags,
    857     unsigned long long bind_id,
    858     const char* arg1_name,
    859     const ARG1_TYPE& arg1_val) {
    860   int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
    861   base::TimeTicks now = base::TimeTicks::Now();
    862   return AddTraceEventWithThreadIdAndTimestamp(
    863       phase, category_group_enabled, name, scope, id, thread_id, now, flags,
    864       bind_id, arg1_name, arg1_val);
    865 }
    866 
    867 template <class ARG1_CONVERTABLE_TYPE>
    868 static inline base::trace_event::TraceEventHandle AddTraceEvent(
    869     char phase,
    870     const unsigned char* category_group_enabled,
    871     const char* name,
    872     const char* scope,
    873     unsigned long long id,
    874     unsigned int flags,
    875     unsigned long long bind_id,
    876     const char* arg1_name,
    877     std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg1_val) {
    878   int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
    879   base::TimeTicks now = base::TimeTicks::Now();
    880   return AddTraceEventWithThreadIdAndTimestamp(
    881       phase, category_group_enabled, name, scope, id, thread_id, now, flags,
    882       bind_id, arg1_name, std::move(arg1_val));
    883 }
    884 
    885 template<class ARG1_TYPE, class ARG2_TYPE>
    886 static inline base::trace_event::TraceEventHandle
    887 AddTraceEventWithThreadIdAndTimestamp(
    888     char phase,
    889     const unsigned char* category_group_enabled,
    890     const char* name,
    891     const char* scope,
    892     unsigned long long id,
    893     int thread_id,
    894     const base::TimeTicks& timestamp,
    895     unsigned int flags,
    896     unsigned long long bind_id,
    897     const char* arg1_name,
    898     const ARG1_TYPE& arg1_val,
    899     const char* arg2_name,
    900     const ARG2_TYPE& arg2_val) {
    901   const int num_args = 2;
    902   const char* arg_names[2] = { arg1_name, arg2_name };
    903   unsigned char arg_types[2];
    904   unsigned long long arg_values[2];
    905   SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]);
    906   SetTraceValue(arg2_val, &arg_types[1], &arg_values[1]);
    907   return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
    908       phase, category_group_enabled, name, scope, id, bind_id, thread_id,
    909       timestamp, num_args, arg_names, arg_types, arg_values, NULL, flags);
    910 }
    911 
    912 template <class ARG1_CONVERTABLE_TYPE, class ARG2_TYPE>
    913 static inline base::trace_event::TraceEventHandle AddTraceEvent(
    914     char phase,
    915     const unsigned char* category_group_enabled,
    916     const char* name,
    917     const char* scope,
    918     unsigned long long id,
    919     unsigned int flags,
    920     unsigned long long bind_id,
    921     const char* arg1_name,
    922     std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg1_val,
    923     const char* arg2_name,
    924     const ARG2_TYPE& arg2_val) {
    925   int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
    926   base::TimeTicks now = base::TimeTicks::Now();
    927   return AddTraceEventWithThreadIdAndTimestamp(
    928       phase, category_group_enabled, name, scope, id, thread_id, now, flags,
    929       bind_id, arg1_name, std::move(arg1_val), arg2_name, arg2_val);
    930 }
    931 
    932 template <class ARG1_TYPE, class ARG2_CONVERTABLE_TYPE>
    933 static inline base::trace_event::TraceEventHandle AddTraceEvent(
    934     char phase,
    935     const unsigned char* category_group_enabled,
    936     const char* name,
    937     const char* scope,
    938     unsigned long long id,
    939     unsigned int flags,
    940     unsigned long long bind_id,
    941     const char* arg1_name,
    942     const ARG1_TYPE& arg1_val,
    943     const char* arg2_name,
    944     std::unique_ptr<ARG2_CONVERTABLE_TYPE> arg2_val) {
    945   int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
    946   base::TimeTicks now = base::TimeTicks::Now();
    947   return AddTraceEventWithThreadIdAndTimestamp(
    948       phase, category_group_enabled, name, scope, id, thread_id, now, flags,
    949       bind_id, arg1_name, arg1_val, arg2_name, std::move(arg2_val));
    950 }
    951 
    952 template <class ARG1_CONVERTABLE_TYPE, class ARG2_CONVERTABLE_TYPE>
    953 static inline base::trace_event::TraceEventHandle AddTraceEvent(
    954     char phase,
    955     const unsigned char* category_group_enabled,
    956     const char* name,
    957     const char* scope,
    958     unsigned long long id,
    959     unsigned int flags,
    960     unsigned long long bind_id,
    961     const char* arg1_name,
    962     std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg1_val,
    963     const char* arg2_name,
    964     std::unique_ptr<ARG2_CONVERTABLE_TYPE> arg2_val) {
    965   int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
    966   base::TimeTicks now = base::TimeTicks::Now();
    967   return AddTraceEventWithThreadIdAndTimestamp(
    968       phase, category_group_enabled, name, scope, id, thread_id, now, flags,
    969       bind_id, arg1_name, std::move(arg1_val), arg2_name, std::move(arg2_val));
    970 }
    971 
    972 template<class ARG1_TYPE, class ARG2_TYPE>
    973 static inline base::trace_event::TraceEventHandle AddTraceEvent(
    974     char phase,
    975     const unsigned char* category_group_enabled,
    976     const char* name,
    977     const char* scope,
    978     unsigned long long id,
    979     unsigned int flags,
    980     unsigned long long bind_id,
    981     const char* arg1_name,
    982     const ARG1_TYPE& arg1_val,
    983     const char* arg2_name,
    984     const ARG2_TYPE& arg2_val) {
    985   int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
    986   base::TimeTicks now = base::TimeTicks::Now();
    987   return AddTraceEventWithThreadIdAndTimestamp(
    988       phase, category_group_enabled, name, scope, id, thread_id, now, flags,
    989       bind_id, arg1_name, arg1_val, arg2_name, arg2_val);
    990 }
    991 
    992 template <class ARG1_CONVERTABLE_TYPE>
    993 static inline void AddMetadataEvent(
    994     const unsigned char* category_group_enabled,
    995     const char* event_name,
    996     const char* arg_name,
    997     std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg_value) {
    998   const char* arg_names[1] = {arg_name};
    999   unsigned char arg_types[1] = {TRACE_VALUE_TYPE_CONVERTABLE};
   1000   std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
   1001       convertable_values[1] = {std::move(arg_value)};
   1002   base::trace_event::TraceLog::GetInstance()->AddMetadataEvent(
   1003       category_group_enabled, event_name,
   1004       1,  // num_args
   1005       arg_names, arg_types,
   1006       nullptr,  // arg_values
   1007       convertable_values, TRACE_EVENT_FLAG_NONE);
   1008 }
   1009 
   1010 template <class ARG1_TYPE>
   1011 static void AddMetadataEvent(const unsigned char* category_group_enabled,
   1012                              const char* event_name,
   1013                              const char* arg_name,
   1014                              const ARG1_TYPE& arg_val) {
   1015   const int num_args = 1;
   1016   const char* arg_names[1] = {arg_name};
   1017   unsigned char arg_types[1];
   1018   unsigned long long arg_values[1];
   1019   SetTraceValue(arg_val, &arg_types[0], &arg_values[0]);
   1020 
   1021   base::trace_event::TraceLog::GetInstance()->AddMetadataEvent(
   1022       category_group_enabled, event_name, num_args, arg_names, arg_types,
   1023       arg_values, nullptr, TRACE_EVENT_FLAG_NONE);
   1024 }
   1025 
   1026 // Used by TRACE_EVENTx macros. Do not use directly.
   1027 class TRACE_EVENT_API_CLASS_EXPORT ScopedTracer {
   1028  public:
   1029   // Note: members of data_ intentionally left uninitialized. See Initialize.
   1030   ScopedTracer() : p_data_(NULL) {}
   1031 
   1032   ~ScopedTracer() {
   1033     if (p_data_ && *data_.category_group_enabled) {
   1034       TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(
   1035           data_.category_group_enabled, data_.name, data_.event_handle);
   1036     }
   1037   }
   1038 
   1039   void Initialize(const unsigned char* category_group_enabled,
   1040                   const char* name,
   1041                   base::trace_event::TraceEventHandle event_handle) {
   1042     data_.category_group_enabled = category_group_enabled;
   1043     data_.name = name;
   1044     data_.event_handle = event_handle;
   1045     p_data_ = &data_;
   1046   }
   1047 
   1048  private:
   1049   // This Data struct workaround is to avoid initializing all the members
   1050   // in Data during construction of this object, since this object is always
   1051   // constructed, even when tracing is disabled. If the members of Data were
   1052   // members of this class instead, compiler warnings occur about potential
   1053   // uninitialized accesses.
   1054   struct Data {
   1055     const unsigned char* category_group_enabled;
   1056     const char* name;
   1057     base::trace_event::TraceEventHandle event_handle;
   1058   };
   1059   Data* p_data_;
   1060   Data data_;
   1061 };
   1062 
   1063 // Used by TRACE_EVENT_BINARY_EFFICIENTx macro. Do not use directly.
   1064 class TRACE_EVENT_API_CLASS_EXPORT ScopedTraceBinaryEfficient {
   1065  public:
   1066   ScopedTraceBinaryEfficient(const char* category_group, const char* name);
   1067   ~ScopedTraceBinaryEfficient();
   1068 
   1069  private:
   1070   const unsigned char* category_group_enabled_;
   1071   const char* name_;
   1072   base::trace_event::TraceEventHandle event_handle_;
   1073 };
   1074 
   1075 // This macro generates less code then TRACE_EVENT0 but is also
   1076 // slower to execute when tracing is off. It should generally only be
   1077 // used with code that is seldom executed or conditionally executed
   1078 // when debugging.
   1079 // For now the category_group must be "gpu".
   1080 #define TRACE_EVENT_BINARY_EFFICIENT0(category_group, name) \
   1081     trace_event_internal::ScopedTraceBinaryEfficient \
   1082         INTERNAL_TRACE_EVENT_UID(scoped_trace)(category_group, name);
   1083 
   1084 }  // namespace trace_event_internal
   1085 
   1086 namespace base {
   1087 namespace trace_event {
   1088 
   1089 template<typename IDType> class TraceScopedTrackableObject {
   1090  public:
   1091   TraceScopedTrackableObject(const char* category_group, const char* name,
   1092       IDType id)
   1093     : category_group_(category_group),
   1094       name_(name),
   1095       id_(id) {
   1096     TRACE_EVENT_OBJECT_CREATED_WITH_ID(category_group_, name_, id_);
   1097   }
   1098 
   1099   template <typename ArgType> void snapshot(ArgType snapshot) {
   1100     TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(category_group_, name_, id_, snapshot);
   1101   }
   1102 
   1103   ~TraceScopedTrackableObject() {
   1104     TRACE_EVENT_OBJECT_DELETED_WITH_ID(category_group_, name_, id_);
   1105   }
   1106 
   1107  private:
   1108   const char* category_group_;
   1109   const char* name_;
   1110   IDType id_;
   1111 
   1112   DISALLOW_COPY_AND_ASSIGN(TraceScopedTrackableObject);
   1113 };
   1114 
   1115 }  // namespace trace_event
   1116 }  // namespace base
   1117 
   1118 #endif  // BASE_TRACE_EVENT_TRACE_EVENT_H_
   1119