#ifndef TraceEvent_h
#define TraceEvent_h
#include "platform/EventTracer.h"
#include "wtf/DynamicAnnotations.h"
#include "wtf/text/CString.h"
#define TRACE_STR_COPY(str) \
WebCore::TraceEvent::TraceStringWithCopy(str)
#define TRACE_ID_MANGLE(id) \
TraceID::ForceMangle(id)
#define TRACE_ID_DONT_MANGLE(id) \
TraceID::DontMangle(id)
#define TRACE_EVENT0(category, name) \
INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name)
#define TRACE_EVENT1(category, name, arg1_name, arg1_val) \
INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, arg1_name, arg1_val)
#define TRACE_EVENT2(category, name, arg1_name, arg1_val, arg2_name, arg2_val) \
INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, arg1_name, arg1_val, \
arg2_name, arg2_val)
#define TRACE_EVENT_INSTANT0(category, name) \
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
category, name, TRACE_EVENT_FLAG_NONE)
#define TRACE_EVENT_INSTANT1(category, name, arg1_name, arg1_val) \
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
#define TRACE_EVENT_INSTANT2(category, name, arg1_name, arg1_val, \
arg2_name, arg2_val) \
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \
arg2_name, arg2_val)
#define TRACE_EVENT_COPY_INSTANT0(category, name) \
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
category, name, TRACE_EVENT_FLAG_COPY)
#define TRACE_EVENT_COPY_INSTANT1(category, name, arg1_name, arg1_val) \
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)
#define TRACE_EVENT_COPY_INSTANT2(category, name, arg1_name, arg1_val, \
arg2_name, arg2_val) \
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \
arg2_name, arg2_val)
#define TRACE_EVENT_BEGIN0(category, name) \
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
category, name, TRACE_EVENT_FLAG_NONE)
#define TRACE_EVENT_BEGIN1(category, name, arg1_name, arg1_val) \
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
#define TRACE_EVENT_BEGIN2(category, name, arg1_name, arg1_val, \
arg2_name, arg2_val) \
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \
arg2_name, arg2_val)
#define TRACE_EVENT_COPY_BEGIN0(category, name) \
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
category, name, TRACE_EVENT_FLAG_COPY)
#define TRACE_EVENT_COPY_BEGIN1(category, name, arg1_name, arg1_val) \
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)
#define TRACE_EVENT_COPY_BEGIN2(category, name, arg1_name, arg1_val, \
arg2_name, arg2_val) \
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \
arg2_name, arg2_val)
#define TRACE_EVENT_END0(category, name) \
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
category, name, TRACE_EVENT_FLAG_NONE)
#define TRACE_EVENT_END1(category, name, arg1_name, arg1_val) \
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
#define TRACE_EVENT_END2(category, name, arg1_name, arg1_val, \
arg2_name, arg2_val) \
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \
arg2_name, arg2_val)
#define TRACE_EVENT_COPY_END0(category, name) \
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
category, name, TRACE_EVENT_FLAG_COPY)
#define TRACE_EVENT_COPY_END1(category, name, arg1_name, arg1_val) \
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)
#define TRACE_EVENT_COPY_END2(category, name, arg1_name, arg1_val, \
arg2_name, arg2_val) \
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \
arg2_name, arg2_val)
#define TRACE_COUNTER1(category, name, value) \
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \
category, name, TRACE_EVENT_FLAG_NONE, \
"value", static_cast<int>(value))
#define TRACE_COPY_COUNTER1(category, name, value) \
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \
category, name, TRACE_EVENT_FLAG_COPY, \
"value", static_cast<int>(value))
#define TRACE_COUNTER2(category, name, value1_name, value1_val, \
value2_name, value2_val) \
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \
category, name, TRACE_EVENT_FLAG_NONE, \
value1_name, static_cast<int>(value1_val), \
value2_name, static_cast<int>(value2_val))
#define TRACE_COPY_COUNTER2(category, name, value1_name, value1_val, \
value2_name, value2_val) \
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \
category, name, TRACE_EVENT_FLAG_COPY, \
value1_name, static_cast<int>(value1_val), \
value2_name, static_cast<int>(value2_val))
#define TRACE_COUNTER_ID1(category, name, id, value) \
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \
category, name, id, TRACE_EVENT_FLAG_NONE, \
"value", static_cast<int>(value))
#define TRACE_COPY_COUNTER_ID1(category, name, id, value) \
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \
category, name, id, TRACE_EVENT_FLAG_COPY, \
"value", static_cast<int>(value))
#define TRACE_COUNTER_ID2(category, name, id, value1_name, value1_val, \
value2_name, value2_val) \
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \
category, name, id, TRACE_EVENT_FLAG_NONE, \
value1_name, static_cast<int>(value1_val), \
value2_name, static_cast<int>(value2_val))
#define TRACE_COPY_COUNTER_ID2(category, name, id, value1_name, value1_val, \
value2_name, value2_val) \
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \
category, name, id, TRACE_EVENT_FLAG_COPY, \
value1_name, static_cast<int>(value1_val), \
value2_name, static_cast<int>(value2_val))
#define TRACE_EVENT_ASYNC_BEGIN0(category, name, id) \
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
category, name, id, TRACE_EVENT_FLAG_NONE)
#define TRACE_EVENT_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
#define TRACE_EVENT_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, \
arg2_name, arg2_val) \
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
category, name, id, TRACE_EVENT_FLAG_NONE, \
arg1_name, arg1_val, arg2_name, arg2_val)
#define TRACE_EVENT_COPY_ASYNC_BEGIN0(category, name, id) \
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
category, name, id, TRACE_EVENT_FLAG_COPY)
#define TRACE_EVENT_COPY_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
category, name, id, TRACE_EVENT_FLAG_COPY, \
arg1_name, arg1_val)
#define TRACE_EVENT_COPY_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, \
arg2_name, arg2_val) \
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
category, name, id, TRACE_EVENT_FLAG_COPY, \
arg1_name, arg1_val, arg2_name, arg2_val)
#define TRACE_EVENT_ASYNC_STEP_INTO0(category, name, id, step) \
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP_INTO, \
category, name, id, TRACE_EVENT_FLAG_NONE, "step", step)
#define TRACE_EVENT_ASYNC_STEP_INTO1(category, name, id, step, \
arg1_name, arg1_val) \
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP_INTO, \
category, name, id, TRACE_EVENT_FLAG_NONE, "step", step, \
arg1_name, arg1_val)
#define TRACE_EVENT_ASYNC_STEP_PAST0(category_group, name, id, step) \
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP_PAST, \
category_group, name, id, TRACE_EVENT_FLAG_NONE, "step", step)
#define TRACE_EVENT_ASYNC_STEP_PAST1(category_group, name, id, step, arg1_name, arg1_val) \
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP_PAST, \
category_group, name, id, TRACE_EVENT_FLAG_NONE, "step", step, \
arg1_name, arg1_val)
#define TRACE_EVENT_ASYNC_END0(category, name, id) \
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
category, name, id, TRACE_EVENT_FLAG_NONE)
#define TRACE_EVENT_ASYNC_END1(category, name, id, arg1_name, arg1_val) \
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
#define TRACE_EVENT_ASYNC_END2(category, name, id, arg1_name, arg1_val, \
arg2_name, arg2_val) \
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
category, name, id, TRACE_EVENT_FLAG_NONE, \
arg1_name, arg1_val, arg2_name, arg2_val)
#define TRACE_EVENT_COPY_ASYNC_END0(category, name, id) \
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
category, name, id, TRACE_EVENT_FLAG_COPY)
#define TRACE_EVENT_COPY_ASYNC_END1(category, name, id, arg1_name, arg1_val) \
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
category, name, id, TRACE_EVENT_FLAG_COPY, \
arg1_name, arg1_val)
#define TRACE_EVENT_COPY_ASYNC_END2(category, name, id, arg1_name, arg1_val, \
arg2_name, arg2_val) \
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
category, name, id, TRACE_EVENT_FLAG_COPY, \
arg1_name, arg1_val, arg2_name, arg2_val)
#define TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET(bucket_number, category, name) \
TraceEvent::SamplingStateScope<bucket_number> traceEventSamplingScope(category "\0" name);
#define TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(bucket_number) \
TraceEvent::SamplingStateScope<bucket_number>::current()
#define TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(bucket_number, category, name) \
TraceEvent::SamplingStateScope<bucket_number>::set(category "\0" name)
#define TRACE_EVENT_SET_NONCONST_SAMPLING_STATE_FOR_BUCKET(bucket_number, categoryAndName) \
TraceEvent::SamplingStateScope<bucket_number>::set(categoryAndName)
#define TRACE_EVENT_SCOPED_SAMPLING_STATE(category, name) \
TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET(0, category, name)
#define TRACE_EVENT_GET_SAMPLING_STATE() \
TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(0)
#define TRACE_EVENT_SET_SAMPLING_STATE(category, name) \
TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(0, category, name)
#define TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(categoryAndName) \
TRACE_EVENT_SET_NONCONST_SAMPLING_STATE_FOR_BUCKET(0, categoryAndName)
#define TRACE_EVENT_OBJECT_CREATED_WITH_ID(categoryGroup, name, id) \
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_CREATE_OBJECT, \
categoryGroup, name, TRACE_ID_DONT_MANGLE(id), TRACE_EVENT_FLAG_NONE)
#define TRACE_EVENT_OBJECT_DELETED_WITH_ID(categoryGroup, name, id) \
INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_DELETE_OBJECT, \
categoryGroup, name, TRACE_ID_DONT_MANGLE(id), TRACE_EVENT_FLAG_NONE)
#define TRACE_EVENT_CATEGORY_GROUP_ENABLED(categoryGroup, ret) \
do { \
INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(categoryGroup); \
if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
*ret = true; \
} else { \
*ret = false; \
} \
} while (0)
#define TRACE_DISABLED_BY_DEFAULT(name) "disabled-by-default-" name
#define TRACE_EVENT_API_GET_CATEGORY_ENABLED \
WebCore::EventTracer::getTraceCategoryEnabledFlag
#define TRACE_EVENT_API_ADD_TRACE_EVENT \
WebCore::EventTracer::addTraceEvent
#define TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION \
WebCore::EventTracer::updateTraceEventDuration
#define INTERNAL_TRACE_EVENT_UID3(a, b) \
trace_event_unique_##a##b
#define INTERNAL_TRACE_EVENT_UID2(a, b) \
INTERNAL_TRACE_EVENT_UID3(a, b)
#define INTERNALTRACEEVENTUID(name_prefix) \
INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__)
#define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category) \
static const unsigned char* INTERNALTRACEEVENTUID(categoryGroupEnabled) = 0; \
WTF_ANNOTATE_BENIGN_RACE(&INTERNALTRACEEVENTUID(categoryGroupEnabled), \
"trace_event category"); \
if (!INTERNALTRACEEVENTUID(categoryGroupEnabled)) { \
INTERNALTRACEEVENTUID(categoryGroupEnabled) = \
TRACE_EVENT_API_GET_CATEGORY_ENABLED(category); \
}
#define INTERNAL_TRACE_EVENT_ADD(phase, category, name, flags, ...) \
do { \
INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \
if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
WebCore::TraceEvent::addTraceEvent( \
phase, INTERNALTRACEEVENTUID(categoryGroupEnabled), name, \
WebCore::TraceEvent::noEventId, flags, ##__VA_ARGS__); \
} \
} while (0)
#define INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, ...) \
INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \
WebCore::TraceEvent::ScopedTracer INTERNALTRACEEVENTUID(scopedTracer); \
if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
WebCore::TraceEvent::TraceEventHandle h = \
WebCore::TraceEvent::addTraceEvent( \
TRACE_EVENT_PHASE_COMPLETE, \
INTERNALTRACEEVENTUID(categoryGroupEnabled), \
name, WebCore::TraceEvent::noEventId, \
TRACE_EVENT_FLAG_NONE, ##__VA_ARGS__); \
INTERNALTRACEEVENTUID(scopedTracer).initialize( \
INTERNALTRACEEVENTUID(categoryGroupEnabled), name, h); \
}
#define INTERNAL_TRACE_EVENT_ADD_WITH_ID(phase, category, name, id, flags, \
...) \
do { \
INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \
if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \
unsigned char traceEventFlags = flags | TRACE_EVENT_FLAG_HAS_ID; \
WebCore::TraceEvent::TraceID traceEventTraceID( \
id, &traceEventFlags); \
WebCore::TraceEvent::addTraceEvent( \
phase, INTERNALTRACEEVENTUID(categoryGroupEnabled), \
name, traceEventTraceID.data(), traceEventFlags, \
##__VA_ARGS__); \
} \
} while (0)
#define TRACE_EVENT_PHASE_BEGIN ('B')
#define TRACE_EVENT_PHASE_END ('E')
#define TRACE_EVENT_PHASE_COMPLETE ('X')
#define TRACE_EVENT_PHASE_INSTANT ('I')
#define TRACE_EVENT_PHASE_INSTANT_WITH_SCOPE ('i')
#define TRACE_EVENT_PHASE_ASYNC_BEGIN ('S')
#define TRACE_EVENT_PHASE_ASYNC_STEP_INTO ('T')
#define TRACE_EVENT_PHASE_ASYNC_STEP_PAST ('p')
#define TRACE_EVENT_PHASE_ASYNC_END ('F')
#define TRACE_EVENT_PHASE_METADATA ('M')
#define TRACE_EVENT_PHASE_COUNTER ('C')
#define TRACE_EVENT_PHASE_SAMPLE ('P')
#define TRACE_EVENT_PHASE_CREATE_OBJECT ('N')
#define TRACE_EVENT_PHASE_DELETE_OBJECT ('D')
#define TRACE_EVENT_FLAG_NONE (static_cast<unsigned char>(0))
#define TRACE_EVENT_FLAG_COPY (static_cast<unsigned char>(1 << 0))
#define TRACE_EVENT_FLAG_HAS_ID (static_cast<unsigned char>(1 << 1))
#define TRACE_EVENT_FLAG_MANGLE_ID (static_cast<unsigned char>(1 << 2))
#define TRACE_VALUE_TYPE_BOOL (static_cast<unsigned char>(1))
#define TRACE_VALUE_TYPE_UINT (static_cast<unsigned char>(2))
#define TRACE_VALUE_TYPE_INT (static_cast<unsigned char>(3))
#define TRACE_VALUE_TYPE_DOUBLE (static_cast<unsigned char>(4))
#define TRACE_VALUE_TYPE_POINTER (static_cast<unsigned char>(5))
#define TRACE_VALUE_TYPE_STRING (static_cast<unsigned char>(6))
#define TRACE_VALUE_TYPE_COPY_STRING (static_cast<unsigned char>(7))
#define ENABLED_FOR_RECORDING (1 << 0)
#define ENABLED_FOR_EVENT_CALLBACK (1 << 2)
#define INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE() \
(*INTERNALTRACEEVENTUID(categoryGroupEnabled) & (ENABLED_FOR_RECORDING | ENABLED_FOR_EVENT_CALLBACK))
namespace WebCore {
namespace TraceEvent {
const int zeroNumArgs = 0;
const unsigned long long noEventId = 0;
class TraceID {
public:
template<bool dummyMangle> class MangleBehavior {
public:
template<typename T> explicit MangleBehavior(T id) : m_data(reinterpret_cast<unsigned long long>(id)) { }
unsigned long long data() const { return m_data; }
private:
unsigned long long m_data;
};
typedef MangleBehavior<false> DontMangle;
typedef MangleBehavior<true> ForceMangle;
TraceID(const void* id, unsigned char* flags) :
m_data(static_cast<unsigned long long>(reinterpret_cast<unsigned long>(id)))
{
*flags |= TRACE_EVENT_FLAG_MANGLE_ID;
}
TraceID(ForceMangle id, unsigned char* flags) : m_data(id.data())
{
*flags |= TRACE_EVENT_FLAG_MANGLE_ID;
}
TraceID(DontMangle id, unsigned char*) : m_data(id.data()) { }
TraceID(unsigned long long id, unsigned char*) : m_data(id) { }
TraceID(unsigned long id, unsigned char*) : m_data(id) { }
TraceID(unsigned id, unsigned char*) : m_data(id) { }
TraceID(unsigned short id, unsigned char*) : m_data(id) { }
TraceID(unsigned char id, unsigned char*) : m_data(id) { }
TraceID(long long id, unsigned char*) :
m_data(static_cast<unsigned long long>(id)) { }
TraceID(long id, unsigned char*) :
m_data(static_cast<unsigned long long>(id)) { }
TraceID(int id, unsigned char*) :
m_data(static_cast<unsigned long long>(id)) { }
TraceID(short id, unsigned char*) :
m_data(static_cast<unsigned long long>(id)) { }
TraceID(signed char id, unsigned char*) :
m_data(static_cast<unsigned long long>(id)) { }
unsigned long long data() const { return m_data; }
private:
unsigned long long m_data;
};
union TraceValueUnion {
bool m_bool;
unsigned long long m_uint;
long long m_int;
double m_double;
const void* m_pointer;
const char* m_string;
};
class TraceStringWithCopy {
public:
explicit TraceStringWithCopy(const char* str) : m_str(str) { }
operator const char* () const { return m_str; }
private:
const char* m_str;
};
#define INTERNAL_DECLARE_SET_TRACE_VALUE(actual_type, \
union_member, \
value_type_id) \
static inline void setTraceValue(actual_type arg, \
unsigned char* type, \
unsigned long long* value) { \
TraceValueUnion typeValue; \
typeValue.union_member = arg; \
*type = value_type_id; \
*value = typeValue.m_uint; \
}
#define INTERNAL_DECLARE_SET_TRACE_VALUE_INT(actual_type, \
value_type_id) \
static inline void setTraceValue(actual_type arg, \
unsigned char* type, \
unsigned long long* value) { \
*type = value_type_id; \
*value = static_cast<unsigned long long>(arg); \
}
INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long long, TRACE_VALUE_TYPE_UINT)
INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned, TRACE_VALUE_TYPE_UINT)
INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned short, TRACE_VALUE_TYPE_UINT)
INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned char, TRACE_VALUE_TYPE_UINT)
INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long long, TRACE_VALUE_TYPE_INT)
INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int, TRACE_VALUE_TYPE_INT)
INTERNAL_DECLARE_SET_TRACE_VALUE_INT(short, TRACE_VALUE_TYPE_INT)
INTERNAL_DECLARE_SET_TRACE_VALUE_INT(signed char, TRACE_VALUE_TYPE_INT)
INTERNAL_DECLARE_SET_TRACE_VALUE(bool, m_bool, TRACE_VALUE_TYPE_BOOL)
INTERNAL_DECLARE_SET_TRACE_VALUE(double, m_double, TRACE_VALUE_TYPE_DOUBLE)
INTERNAL_DECLARE_SET_TRACE_VALUE(const void*, m_pointer,
TRACE_VALUE_TYPE_POINTER)
INTERNAL_DECLARE_SET_TRACE_VALUE(const char*, m_string,
TRACE_VALUE_TYPE_STRING)
INTERNAL_DECLARE_SET_TRACE_VALUE(const TraceStringWithCopy&, m_string,
TRACE_VALUE_TYPE_COPY_STRING)
#undef INTERNAL_DECLARE_SET_TRACE_VALUE
#undef INTERNAL_DECLARE_SET_TRACE_VALUE_INT
static inline void setTraceValue(const WTF::CString& arg, unsigned char* type, unsigned long long* value)
{
TraceValueUnion typeValue;
typeValue.m_string = arg.data();
*type = TRACE_VALUE_TYPE_COPY_STRING;
*value = typeValue.m_uint;
}
static inline TraceEventHandle addTraceEvent(
char phase,
const unsigned char* categoryEnabled,
const char* name,
unsigned long long id,
unsigned char flags)
{
return TRACE_EVENT_API_ADD_TRACE_EVENT(
phase, categoryEnabled, name, id,
zeroNumArgs, 0, 0, 0,
flags);
}
template<class ARG1_TYPE>
static inline TraceEventHandle addTraceEvent(
char phase,
const unsigned char* categoryEnabled,
const char* name,
unsigned long long id,
unsigned char flags,
const char* arg1Name,
const ARG1_TYPE& arg1Val)
{
const int numArgs = 1;
unsigned char argTypes[1];
unsigned long long argValues[1];
setTraceValue(arg1Val, &argTypes[0], &argValues[0]);
return TRACE_EVENT_API_ADD_TRACE_EVENT(
phase, categoryEnabled, name, id,
numArgs, &arg1Name, argTypes, argValues,
flags);
}
template<class ARG1_TYPE, class ARG2_TYPE>
static inline TraceEventHandle addTraceEvent(
char phase,
const unsigned char* categoryEnabled,
const char* name,
unsigned long long id,
unsigned char flags,
const char* arg1Name,
const ARG1_TYPE& arg1Val,
const char* arg2Name,
const ARG2_TYPE& arg2Val)
{
const int numArgs = 2;
const char* argNames[2] = { arg1Name, arg2Name };
unsigned char argTypes[2];
unsigned long long argValues[2];
setTraceValue(arg1Val, &argTypes[0], &argValues[0]);
setTraceValue(arg2Val, &argTypes[1], &argValues[1]);
return TRACE_EVENT_API_ADD_TRACE_EVENT(
phase, categoryEnabled, name, id,
numArgs, argNames, argTypes, argValues,
flags);
}
class ScopedTracer {
public:
ScopedTracer() : m_pdata(0) { }
~ScopedTracer()
{
if (m_pdata && *m_pdata->categoryGroupEnabled)
TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(m_data.categoryGroupEnabled, m_data.name, m_data.eventHandle);
}
void initialize(const unsigned char* categoryGroupEnabled, const char* name, TraceEventHandle eventHandle)
{
m_data.categoryGroupEnabled = categoryGroupEnabled;
m_data.name = name;
m_data.eventHandle = eventHandle;
m_pdata = &m_data;
}
private:
struct Data {
const unsigned char* categoryGroupEnabled;
const char* name;
TraceEventHandle eventHandle;
};
Data* m_pdata;
Data m_data;
};
template<size_t BucketNumber>
class SamplingStateScope {
WTF_MAKE_FAST_ALLOCATED;
public:
SamplingStateScope(const char* categoryAndName)
{
m_previousState = SamplingStateScope<BucketNumber>::current();
SamplingStateScope<BucketNumber>::set(categoryAndName);
}
~SamplingStateScope()
{
SamplingStateScope<BucketNumber>::set(m_previousState);
}
static inline const char* current()
{
return reinterpret_cast<const char*>(*WebCore::traceSamplingState[BucketNumber]);
}
static inline void set(const char* categoryAndName)
{
*WebCore::traceSamplingState[BucketNumber] = reinterpret_cast<long>(const_cast<char*>(categoryAndName));
}
private:
const char* m_previousState;
};
template<typename IDType> class TraceScopedTrackableObject {
WTF_MAKE_NONCOPYABLE(TraceScopedTrackableObject);
public:
TraceScopedTrackableObject(const char* categoryGroup, const char* name, IDType id)
: m_categoryGroup(categoryGroup), m_name(name), m_id(id)
{
TRACE_EVENT_OBJECT_CREATED_WITH_ID(m_categoryGroup, m_name, m_id);
}
~TraceScopedTrackableObject()
{
TRACE_EVENT_OBJECT_DELETED_WITH_ID(m_categoryGroup, m_name, m_id);
}
private:
const char* m_categoryGroup;
const char* m_name;
IDType m_id;
};
}
}
#endif