Add TraceForCategory* methods for legacy macros
Introduces additional TrackEvent template methods and redefines legacy
macros using them. The goal is to avoid instantiating templates taking
a lambda as a parameter, because this leads to binary size bloat.
This change saves ~220KB of binary size in Chrome Android build with
Perfetto client library.
Bug: 268328757
Change-Id: I1437e1348b7ab0667e029145063760b427c4011c
diff --git a/BUILD b/BUILD
index cc7ec83..716126d 100644
--- a/BUILD
+++ b/BUILD
@@ -676,6 +676,7 @@
"include/perfetto/tracing/internal/track_event_data_source.h",
"include/perfetto/tracing/internal/track_event_internal.h",
"include/perfetto/tracing/internal/track_event_interned_fields.h",
+ "include/perfetto/tracing/internal/track_event_legacy.h",
"include/perfetto/tracing/internal/track_event_macros.h",
"include/perfetto/tracing/internal/write_track_event_args.h",
"include/perfetto/tracing/locked_handle.h",
diff --git a/include/perfetto/tracing/BUILD.gn b/include/perfetto/tracing/BUILD.gn
index 21abc8e..d417668 100644
--- a/include/perfetto/tracing/BUILD.gn
+++ b/include/perfetto/tracing/BUILD.gn
@@ -48,6 +48,7 @@
"internal/track_event_data_source.h",
"internal/track_event_internal.h",
"internal/track_event_interned_fields.h",
+ "internal/track_event_legacy.h",
"internal/track_event_macros.h",
"internal/write_track_event_args.h",
"locked_handle.h",
diff --git a/include/perfetto/tracing/internal/track_event_data_source.h b/include/perfetto/tracing/internal/track_event_data_source.h
index 4f96fe9..0a636ef 100644
--- a/include/perfetto/tracing/internal/track_event_data_source.h
+++ b/include/perfetto/tracing/internal/track_event_data_source.h
@@ -24,6 +24,7 @@
#include "perfetto/tracing/data_source.h"
#include "perfetto/tracing/event_context.h"
#include "perfetto/tracing/internal/track_event_internal.h"
+#include "perfetto/tracing/internal/track_event_legacy.h"
#include "perfetto/tracing/internal/write_track_event_args.h"
#include "perfetto/tracing/track.h"
#include "perfetto/tracing/track_event_category_registry.h"
@@ -144,6 +145,22 @@
} // namespace
+inline ::perfetto::DynamicString DecayEventNameType(
+ ::perfetto::DynamicString name) {
+ return name;
+}
+
+inline ::perfetto::StaticString DecayEventNameType(
+ ::perfetto::StaticString name) {
+ return name;
+}
+
+// Convert all static strings of different length to StaticString to avoid
+// unnecessary template instantiations.
+inline ::perfetto::StaticString DecayEventNameType(const char* name) {
+ return ::perfetto::StaticString{name};
+}
+
// Traits for dynamic categories.
template <typename CategoryType>
struct CategoryTraits {
@@ -432,6 +449,135 @@
});
}
+// Additional trace points used in legacy macros.
+// It's possible to implement legacy macros using a common TraceForCategory,
+// by supplying a lambda that sets all necessary legacy fields. But this
+// results in a binary size bloat because every trace point generates its own
+// template instantiation with its own lambda. ICF can't eliminate those as
+// each lambda captures different variables and so the code is not completely
+// identical.
+// What we do instead is define additional TraceForCategoryLegacy templates
+// that take legacy arguments directly. Their instantiations can have the same
+// binary code for at least some macro invocations and so can be successfully
+// folded by the linker.
+#if PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
+ template <typename TrackType,
+ typename CategoryType,
+ typename EventNameType,
+ typename... Arguments,
+ typename TrackTypeCheck = typename std::enable_if<
+ std::is_convertible<TrackType, Track>::value>::type>
+ static void TraceForCategoryLegacy(
+ uint32_t instances,
+ const CategoryType& category,
+ const EventNameType& event_name,
+ perfetto::protos::pbzero::TrackEvent::Type type,
+ TrackType&& track,
+ char phase,
+ uint32_t flags,
+ Arguments&&... args) PERFETTO_NO_INLINE {
+ TraceForCategoryImpl(instances, category, event_name, type, track,
+ TrackEventInternal::GetTraceTime(),
+ [&](perfetto::EventContext ctx)
+ PERFETTO_NO_THREAD_SAFETY_ANALYSIS {
+ using ::perfetto::internal::TrackEventLegacy;
+ TrackEventLegacy::WriteLegacyEvent(
+ std::move(ctx), phase, flags, args...);
+ });
+ }
+
+ template <typename TrackType,
+ typename CategoryType,
+ typename EventNameType,
+ typename TimestampType = uint64_t,
+ typename... Arguments,
+ typename TrackTypeCheck = typename std::enable_if<
+ std::is_convertible<TrackType, Track>::value>::type,
+ typename TimestampTypeCheck = typename std::enable_if<
+ IsValidTimestamp<TimestampType>()>::type>
+ static void TraceForCategoryLegacy(
+ uint32_t instances,
+ const CategoryType& category,
+ const EventNameType& event_name,
+ perfetto::protos::pbzero::TrackEvent::Type type,
+ TrackType&& track,
+ char phase,
+ uint32_t flags,
+ TimestampType&& timestamp,
+ Arguments&&... args) PERFETTO_NO_INLINE {
+ TraceForCategoryImpl(
+ instances, category, event_name, type, track, timestamp,
+ [&](perfetto::EventContext ctx) PERFETTO_NO_THREAD_SAFETY_ANALYSIS {
+ using ::perfetto::internal::TrackEventLegacy;
+ TrackEventLegacy::WriteLegacyEvent(std::move(ctx), phase, flags,
+ args...);
+ });
+ }
+
+ template <typename TrackType,
+ typename CategoryType,
+ typename EventNameType,
+ typename ThreadIdType,
+ typename LegacyIdType,
+ typename... Arguments,
+ typename TrackTypeCheck = typename std::enable_if<
+ std::is_convertible<TrackType, Track>::value>::type>
+ static void TraceForCategoryLegacyWithId(
+ uint32_t instances,
+ const CategoryType& category,
+ const EventNameType& event_name,
+ perfetto::protos::pbzero::TrackEvent::Type type,
+ TrackType&& track,
+ char phase,
+ uint32_t flags,
+ ThreadIdType thread_id,
+ LegacyIdType legacy_id,
+ Arguments&&... args) PERFETTO_NO_INLINE {
+ TraceForCategoryImpl(
+ instances, category, event_name, type, track,
+ TrackEventInternal::GetTraceTime(),
+ [&](perfetto::EventContext ctx) PERFETTO_NO_THREAD_SAFETY_ANALYSIS {
+ using ::perfetto::internal::TrackEventLegacy;
+ ::perfetto::internal::LegacyTraceId trace_id{legacy_id};
+ TrackEventLegacy::WriteLegacyEventWithIdAndTid(
+ std::move(ctx), phase, flags, trace_id, thread_id, args...);
+ });
+ }
+
+ template <typename TrackType,
+ typename CategoryType,
+ typename EventNameType,
+ typename ThreadIdType,
+ typename LegacyIdType,
+ typename TimestampType = uint64_t,
+ typename... Arguments,
+ typename TrackTypeCheck = typename std::enable_if<
+ std::is_convertible<TrackType, Track>::value>::type,
+ typename TimestampTypeCheck = typename std::enable_if<
+ IsValidTimestamp<TimestampType>()>::type>
+ static void TraceForCategoryLegacyWithId(
+ uint32_t instances,
+ const CategoryType& category,
+ const EventNameType& event_name,
+ perfetto::protos::pbzero::TrackEvent::Type type,
+ TrackType&& track,
+ char phase,
+ uint32_t flags,
+ ThreadIdType thread_id,
+ LegacyIdType legacy_id,
+ TimestampType&& timestamp,
+ Arguments&&... args) PERFETTO_NO_INLINE {
+ TraceForCategoryImpl(
+ instances, category, event_name, type, track, timestamp,
+ [&](perfetto::EventContext ctx) PERFETTO_NO_THREAD_SAFETY_ANALYSIS {
+ using ::perfetto::internal::TrackEventLegacy;
+ ::perfetto::internal::LegacyTraceId trace_id{legacy_id};
+ TrackEventLegacy::WriteLegacyEventWithIdAndTid(
+ std::move(ctx), phase, flags, trace_id, thread_id, args...);
+ });
+ }
+#endif // PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
+
// Initialize the track event library. Should be called before tracing is
// enabled.
static bool Register() {
diff --git a/include/perfetto/tracing/internal/track_event_legacy.h b/include/perfetto/tracing/internal/track_event_legacy.h
new file mode 100644
index 0000000..95b40ca
--- /dev/null
+++ b/include/perfetto/tracing/internal/track_event_legacy.h
@@ -0,0 +1,436 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_LEGACY_H_
+#define INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_LEGACY_H_
+
+#ifndef PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
+#define PERFETTO_ENABLE_LEGACY_TRACE_EVENTS 0
+#endif
+
+// ----------------------------------------------------------------------------
+// Constants.
+// ----------------------------------------------------------------------------
+
+namespace perfetto {
+namespace legacy {
+
+enum TraceEventFlag {
+ kTraceEventFlagNone = 0,
+ kTraceEventFlagCopy = 1u << 0,
+ kTraceEventFlagHasId = 1u << 1,
+ kTraceEventFlagScopeOffset = 1u << 2,
+ kTraceEventFlagScopeExtra = 1u << 3,
+ kTraceEventFlagExplicitTimestamp = 1u << 4,
+ kTraceEventFlagAsyncTTS = 1u << 5,
+ kTraceEventFlagBindToEnclosing = 1u << 6,
+ kTraceEventFlagFlowIn = 1u << 7,
+ kTraceEventFlagFlowOut = 1u << 8,
+ kTraceEventFlagHasContextId = 1u << 9,
+ kTraceEventFlagHasProcessId = 1u << 10,
+ kTraceEventFlagHasLocalId = 1u << 11,
+ kTraceEventFlagHasGlobalId = 1u << 12,
+ // TODO(eseckler): Remove once we have native support for typed proto events
+ // in TRACE_EVENT macros.
+ kTraceEventFlagTypedProtoArgs = 1u << 15,
+ kTraceEventFlagJavaStringLiterals = 1u << 16,
+};
+
+enum PerfettoLegacyCurrentThreadId { kCurrentThreadId };
+
+// The following user-provided adaptors are used to serialize user-defined
+// thread id and time types into track events. For full compatibility, the user
+// should also define the following macros appropriately:
+//
+// #define TRACE_TIME_TICKS_NOW() ...
+// #define TRACE_TIME_NOW() ...
+
+// User-provided function to convert an abstract thread id into a thread track.
+template <typename T>
+ThreadTrack ConvertThreadId(const T&);
+
+// Built-in implementation for events referring to the current thread.
+template <>
+ThreadTrack PERFETTO_EXPORT_COMPONENT
+ConvertThreadId(const PerfettoLegacyCurrentThreadId&);
+
+} // namespace legacy
+} // namespace perfetto
+
+#if PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
+// The following constants are defined in the global namespace, since they were
+// originally implemented as macros.
+
+// Event phases.
+static constexpr char TRACE_EVENT_PHASE_BEGIN = 'B';
+static constexpr char TRACE_EVENT_PHASE_END = 'E';
+static constexpr char TRACE_EVENT_PHASE_COMPLETE = 'X';
+static constexpr char TRACE_EVENT_PHASE_INSTANT = 'I';
+static constexpr char TRACE_EVENT_PHASE_ASYNC_BEGIN = 'S';
+static constexpr char TRACE_EVENT_PHASE_ASYNC_STEP_INTO = 'T';
+static constexpr char TRACE_EVENT_PHASE_ASYNC_STEP_PAST = 'p';
+static constexpr char TRACE_EVENT_PHASE_ASYNC_END = 'F';
+static constexpr char TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN = 'b';
+static constexpr char TRACE_EVENT_PHASE_NESTABLE_ASYNC_END = 'e';
+static constexpr char TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT = 'n';
+static constexpr char TRACE_EVENT_PHASE_FLOW_BEGIN = 's';
+static constexpr char TRACE_EVENT_PHASE_FLOW_STEP = 't';
+static constexpr char TRACE_EVENT_PHASE_FLOW_END = 'f';
+static constexpr char TRACE_EVENT_PHASE_METADATA = 'M';
+static constexpr char TRACE_EVENT_PHASE_COUNTER = 'C';
+static constexpr char TRACE_EVENT_PHASE_SAMPLE = 'P';
+static constexpr char TRACE_EVENT_PHASE_CREATE_OBJECT = 'N';
+static constexpr char TRACE_EVENT_PHASE_SNAPSHOT_OBJECT = 'O';
+static constexpr char TRACE_EVENT_PHASE_DELETE_OBJECT = 'D';
+static constexpr char TRACE_EVENT_PHASE_MEMORY_DUMP = 'v';
+static constexpr char TRACE_EVENT_PHASE_MARK = 'R';
+static constexpr char TRACE_EVENT_PHASE_CLOCK_SYNC = 'c';
+
+// Flags for changing the behavior of TRACE_EVENT_API_ADD_TRACE_EVENT.
+static constexpr uint32_t TRACE_EVENT_FLAG_NONE =
+ perfetto::legacy::kTraceEventFlagNone;
+static constexpr uint32_t TRACE_EVENT_FLAG_COPY =
+ perfetto::legacy::kTraceEventFlagCopy;
+static constexpr uint32_t TRACE_EVENT_FLAG_HAS_ID =
+ perfetto::legacy::kTraceEventFlagHasId;
+static constexpr uint32_t TRACE_EVENT_FLAG_SCOPE_OFFSET =
+ perfetto::legacy::kTraceEventFlagScopeOffset;
+static constexpr uint32_t TRACE_EVENT_FLAG_SCOPE_EXTRA =
+ perfetto::legacy::kTraceEventFlagScopeExtra;
+static constexpr uint32_t TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP =
+ perfetto::legacy::kTraceEventFlagExplicitTimestamp;
+static constexpr uint32_t TRACE_EVENT_FLAG_ASYNC_TTS =
+ perfetto::legacy::kTraceEventFlagAsyncTTS;
+static constexpr uint32_t TRACE_EVENT_FLAG_BIND_TO_ENCLOSING =
+ perfetto::legacy::kTraceEventFlagBindToEnclosing;
+static constexpr uint32_t TRACE_EVENT_FLAG_FLOW_IN =
+ perfetto::legacy::kTraceEventFlagFlowIn;
+static constexpr uint32_t TRACE_EVENT_FLAG_FLOW_OUT =
+ perfetto::legacy::kTraceEventFlagFlowOut;
+static constexpr uint32_t TRACE_EVENT_FLAG_HAS_CONTEXT_ID =
+ perfetto::legacy::kTraceEventFlagHasContextId;
+static constexpr uint32_t TRACE_EVENT_FLAG_HAS_PROCESS_ID =
+ perfetto::legacy::kTraceEventFlagHasProcessId;
+static constexpr uint32_t TRACE_EVENT_FLAG_HAS_LOCAL_ID =
+ perfetto::legacy::kTraceEventFlagHasLocalId;
+static constexpr uint32_t TRACE_EVENT_FLAG_HAS_GLOBAL_ID =
+ perfetto::legacy::kTraceEventFlagHasGlobalId;
+static constexpr uint32_t TRACE_EVENT_FLAG_TYPED_PROTO_ARGS =
+ perfetto::legacy::kTraceEventFlagTypedProtoArgs;
+static constexpr uint32_t TRACE_EVENT_FLAG_JAVA_STRING_LITERALS =
+ perfetto::legacy::kTraceEventFlagJavaStringLiterals;
+
+static constexpr uint32_t TRACE_EVENT_FLAG_SCOPE_MASK =
+ TRACE_EVENT_FLAG_SCOPE_OFFSET | TRACE_EVENT_FLAG_SCOPE_EXTRA;
+
+// Type values for identifying types in the TraceValue union.
+static constexpr uint8_t TRACE_VALUE_TYPE_BOOL = 1;
+static constexpr uint8_t TRACE_VALUE_TYPE_UINT = 2;
+static constexpr uint8_t TRACE_VALUE_TYPE_INT = 3;
+static constexpr uint8_t TRACE_VALUE_TYPE_DOUBLE = 4;
+static constexpr uint8_t TRACE_VALUE_TYPE_POINTER = 5;
+static constexpr uint8_t TRACE_VALUE_TYPE_STRING = 6;
+static constexpr uint8_t TRACE_VALUE_TYPE_COPY_STRING = 7;
+static constexpr uint8_t TRACE_VALUE_TYPE_CONVERTABLE = 8;
+static constexpr uint8_t TRACE_VALUE_TYPE_PROTO = 9;
+
+// Enum reflecting the scope of an INSTANT event. Must fit within
+// TRACE_EVENT_FLAG_SCOPE_MASK.
+static constexpr uint8_t TRACE_EVENT_SCOPE_GLOBAL = 0u << 2;
+static constexpr uint8_t TRACE_EVENT_SCOPE_PROCESS = 1u << 2;
+static constexpr uint8_t TRACE_EVENT_SCOPE_THREAD = 2u << 2;
+
+static constexpr char TRACE_EVENT_SCOPE_NAME_GLOBAL = 'g';
+static constexpr char TRACE_EVENT_SCOPE_NAME_PROCESS = 'p';
+static constexpr char TRACE_EVENT_SCOPE_NAME_THREAD = 't';
+
+#define TRACE_EVENT_API_CURRENT_THREAD_ID ::perfetto::legacy::kCurrentThreadId
+
+#endif // PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
+
+namespace perfetto {
+namespace internal {
+
+// LegacyTraceId encapsulates an ID that can either be an integer or pointer.
+class PERFETTO_EXPORT_COMPONENT LegacyTraceId {
+ public:
+ // Can be combined with WithScope.
+ class LocalId {
+ public:
+ explicit LocalId(const void* raw_id)
+ : raw_id_(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(raw_id))) {}
+ explicit LocalId(uint64_t raw_id) : raw_id_(raw_id) {}
+ uint64_t raw_id() const { return raw_id_; }
+
+ private:
+ uint64_t raw_id_;
+ };
+
+ // Can be combined with WithScope.
+ class GlobalId {
+ public:
+ explicit GlobalId(uint64_t raw_id) : raw_id_(raw_id) {}
+ uint64_t raw_id() const { return raw_id_; }
+
+ private:
+ uint64_t raw_id_;
+ };
+
+ class WithScope {
+ public:
+ WithScope(const char* scope, uint64_t raw_id)
+ : scope_(scope), raw_id_(raw_id) {}
+ WithScope(const char* scope, LocalId local_id)
+ : scope_(scope), raw_id_(local_id.raw_id()) {
+ id_flags_ = legacy::kTraceEventFlagHasLocalId;
+ }
+ WithScope(const char* scope, GlobalId global_id)
+ : scope_(scope), raw_id_(global_id.raw_id()) {
+ id_flags_ = legacy::kTraceEventFlagHasGlobalId;
+ }
+ WithScope(const char* scope, uint64_t prefix, uint64_t raw_id)
+ : scope_(scope), has_prefix_(true), prefix_(prefix), raw_id_(raw_id) {}
+ WithScope(const char* scope, uint64_t prefix, GlobalId global_id)
+ : scope_(scope),
+ has_prefix_(true),
+ prefix_(prefix),
+ raw_id_(global_id.raw_id()) {
+ id_flags_ = legacy::kTraceEventFlagHasGlobalId;
+ }
+ uint64_t raw_id() const { return raw_id_; }
+ const char* scope() const { return scope_; }
+ bool has_prefix() const { return has_prefix_; }
+ uint64_t prefix() const { return prefix_; }
+ uint32_t id_flags() const { return id_flags_; }
+
+ private:
+ const char* scope_ = nullptr;
+ bool has_prefix_ = false;
+ uint64_t prefix_;
+ uint64_t raw_id_;
+ uint32_t id_flags_ = legacy::kTraceEventFlagHasId;
+ };
+
+ explicit LegacyTraceId(const void* raw_id)
+ : raw_id_(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(raw_id))) {
+ id_flags_ = legacy::kTraceEventFlagHasLocalId;
+ }
+ explicit LegacyTraceId(uint64_t raw_id) : raw_id_(raw_id) {}
+ explicit LegacyTraceId(uint32_t raw_id) : raw_id_(raw_id) {}
+ explicit LegacyTraceId(uint16_t raw_id) : raw_id_(raw_id) {}
+ explicit LegacyTraceId(uint8_t raw_id) : raw_id_(raw_id) {}
+ explicit LegacyTraceId(int64_t raw_id)
+ : raw_id_(static_cast<uint64_t>(raw_id)) {}
+ explicit LegacyTraceId(int32_t raw_id)
+ : raw_id_(static_cast<uint64_t>(raw_id)) {}
+ explicit LegacyTraceId(int16_t raw_id)
+ : raw_id_(static_cast<uint64_t>(raw_id)) {}
+ explicit LegacyTraceId(int8_t raw_id)
+ : raw_id_(static_cast<uint64_t>(raw_id)) {}
+// Different platforms disagree on which integer types are same and which
+// are different. E.g. on Mac size_t is considered a different type from
+// uint64_t even though it has the same size and signedness.
+// Below we add overloads for those types that are known to cause ambiguity.
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
+ explicit LegacyTraceId(size_t raw_id) : raw_id_(raw_id) {}
+ explicit LegacyTraceId(intptr_t raw_id)
+ : raw_id_(static_cast<uint64_t>(raw_id)) {}
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ explicit LegacyTraceId(unsigned long raw_id) : raw_id_(raw_id) {}
+#endif
+ explicit LegacyTraceId(LocalId raw_id) : raw_id_(raw_id.raw_id()) {
+ id_flags_ = legacy::kTraceEventFlagHasLocalId;
+ }
+ explicit LegacyTraceId(GlobalId raw_id) : raw_id_(raw_id.raw_id()) {
+ id_flags_ = legacy::kTraceEventFlagHasGlobalId;
+ }
+ explicit LegacyTraceId(WithScope scoped_id)
+ : scope_(scoped_id.scope()),
+ has_prefix_(scoped_id.has_prefix()),
+ prefix_(scoped_id.prefix()),
+ raw_id_(scoped_id.raw_id()),
+ id_flags_(scoped_id.id_flags()) {}
+
+ uint64_t raw_id() const { return raw_id_; }
+ const char* scope() const { return scope_; }
+ bool has_prefix() const { return has_prefix_; }
+ uint64_t prefix() const { return prefix_; }
+ uint32_t id_flags() const { return id_flags_; }
+
+ void Write(protos::pbzero::TrackEvent::LegacyEvent*,
+ uint32_t event_flags) const;
+
+ private:
+ const char* scope_ = nullptr;
+ bool has_prefix_ = false;
+ uint64_t prefix_;
+ uint64_t raw_id_;
+ uint32_t id_flags_ = legacy::kTraceEventFlagHasId;
+};
+
+#if PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
+template <typename T>
+bool IsEqual(T x, T y) {
+ return x == y;
+}
+
+template <typename T, typename U>
+bool IsEqual(T, U) {
+ return false;
+}
+
+class PERFETTO_EXPORT_COMPONENT TrackEventLegacy {
+ public:
+ static constexpr protos::pbzero::TrackEvent::Type PhaseToType(char phase) {
+ // clang-format off
+ return (phase == TRACE_EVENT_PHASE_BEGIN) ?
+ protos::pbzero::TrackEvent::TYPE_SLICE_BEGIN :
+ (phase == TRACE_EVENT_PHASE_END) ?
+ protos::pbzero::TrackEvent::TYPE_SLICE_END :
+ (phase == TRACE_EVENT_PHASE_INSTANT) ?
+ protos::pbzero::TrackEvent::TYPE_INSTANT :
+ protos::pbzero::TrackEvent::TYPE_UNSPECIFIED;
+ // clang-format on
+ }
+
+ // Reduce binary size overhead by outlining most of the code for writing a
+ // legacy trace event.
+ template <typename... Args>
+ static void WriteLegacyEvent(EventContext ctx,
+ char phase,
+ uint32_t flags,
+ Args&&... args) PERFETTO_NO_INLINE {
+ PERFETTO_DCHECK(!(flags & TRACE_EVENT_FLAG_HAS_PROCESS_ID));
+ AddDebugAnnotations(&ctx, std::forward<Args>(args)...);
+ if (NeedLegacyFlags(phase, flags)) {
+ auto legacy_event = ctx.event()->set_legacy_event();
+ SetLegacyFlags(legacy_event, phase, flags);
+ }
+ }
+
+ template <typename ThreadIdType, typename... Args>
+ static void WriteLegacyEventWithIdAndTid(EventContext ctx,
+ char phase,
+ uint32_t flags,
+ const LegacyTraceId& id,
+ const ThreadIdType& thread_id,
+ Args&&... args) PERFETTO_NO_INLINE {
+ //
+ // Overrides to consider:
+ //
+ // 1. If we have an id, we need to write {unscoped,local,global}_id and/or
+ // bind_id.
+ // 2. If we have a thread id, we need to write track_uuid() or
+ // {pid,tid}_override if the id represents another process. The
+ // conversion from |thread_id| happens in embedder code since the type is
+ // embedder-specified.
+ // 3. If we have a timestamp, we need to write a different timestamp in the
+ // trace packet itself and make sure TrackEvent won't write one
+ // internally. This is already done at the call site.
+ //
+ PERFETTO_DCHECK(PhaseToType(phase) ==
+ protos::pbzero::TrackEvent::TYPE_UNSPECIFIED ||
+ !(flags & TRACE_EVENT_FLAG_HAS_PROCESS_ID));
+ flags |= id.id_flags();
+ AddDebugAnnotations(&ctx, std::forward<Args>(args)...);
+ if (NeedLegacyFlags(phase, flags)) {
+ auto legacy_event = ctx.event()->set_legacy_event();
+ SetLegacyFlags(legacy_event, phase, flags);
+ if (id.id_flags())
+ id.Write(legacy_event, flags);
+ if (flags & TRACE_EVENT_FLAG_HAS_PROCESS_ID) {
+ // The thread identifier actually represents a process id. Let's set an
+ // override for it.
+ int32_t pid_override =
+ static_cast<int32_t>(legacy::ConvertThreadId(thread_id).tid);
+ legacy_event->set_pid_override(pid_override);
+ legacy_event->set_tid_override(-1);
+ } else {
+ // Only synchronous phases are supported for other threads. These phases
+ // are supported in TrackEvent types and receive a track_uuid
+ // association via TrackEventDataSource::TraceForCategoryImpl().
+ PERFETTO_DCHECK(PhaseToType(phase) !=
+ protos::pbzero::TrackEvent::TYPE_UNSPECIFIED ||
+ IsEqual(thread_id, TRACE_EVENT_API_CURRENT_THREAD_ID) ||
+ legacy::ConvertThreadId(thread_id).tid ==
+ ThreadTrack::Current().tid);
+ }
+ }
+ }
+
+ // No arguments.
+ static void AddDebugAnnotations(EventContext*) {}
+
+ // N number of debug arguments.
+ template <typename ArgNameType, typename ArgType, typename... OtherArgs>
+ static void AddDebugAnnotations(EventContext* ctx,
+ ArgNameType&& arg_name,
+ ArgType&& arg_value,
+ OtherArgs&&... more_args) {
+ TrackEventInternal::AddDebugAnnotation(ctx,
+ std::forward<ArgNameType>(arg_name),
+ std::forward<ArgType>(arg_value));
+ AddDebugAnnotations(ctx, std::forward<OtherArgs>(more_args)...);
+ }
+
+ private:
+ static bool NeedLegacyFlags(char phase, uint32_t flags) {
+ if (PhaseToType(phase) == protos::pbzero::TrackEvent::TYPE_UNSPECIFIED)
+ return true;
+ // TODO(skyostil): Implement/deprecate:
+ // - TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP
+ // - TRACE_EVENT_FLAG_HAS_CONTEXT_ID
+ // - TRACE_EVENT_FLAG_TYPED_PROTO_ARGS
+ // - TRACE_EVENT_FLAG_JAVA_STRING_LITERALS
+ return flags &
+ (TRACE_EVENT_FLAG_HAS_ID | TRACE_EVENT_FLAG_HAS_LOCAL_ID |
+ TRACE_EVENT_FLAG_HAS_GLOBAL_ID | TRACE_EVENT_FLAG_ASYNC_TTS |
+ TRACE_EVENT_FLAG_BIND_TO_ENCLOSING | TRACE_EVENT_FLAG_FLOW_IN |
+ TRACE_EVENT_FLAG_FLOW_OUT | TRACE_EVENT_FLAG_HAS_PROCESS_ID);
+ }
+
+ static void SetLegacyFlags(
+ protos::pbzero::TrackEvent::LegacyEvent* legacy_event,
+ char phase,
+ uint32_t flags) {
+ if (PhaseToType(phase) == protos::pbzero::TrackEvent::TYPE_UNSPECIFIED)
+ legacy_event->set_phase(phase);
+ if (flags & TRACE_EVENT_FLAG_ASYNC_TTS)
+ legacy_event->set_use_async_tts(true);
+ if (flags & TRACE_EVENT_FLAG_BIND_TO_ENCLOSING)
+ legacy_event->set_bind_to_enclosing(true);
+
+ const auto kFlowIn = TRACE_EVENT_FLAG_FLOW_IN;
+ const auto kFlowOut = TRACE_EVENT_FLAG_FLOW_OUT;
+ const auto kFlowInOut = kFlowIn | kFlowOut;
+ if ((flags & kFlowInOut) == kFlowInOut) {
+ legacy_event->set_flow_direction(
+ protos::pbzero::TrackEvent::LegacyEvent::FLOW_INOUT);
+ } else if (flags & kFlowIn) {
+ legacy_event->set_flow_direction(
+ protos::pbzero::TrackEvent::LegacyEvent::FLOW_IN);
+ } else if (flags & kFlowOut) {
+ legacy_event->set_flow_direction(
+ protos::pbzero::TrackEvent::LegacyEvent::FLOW_OUT);
+ }
+ }
+};
+#endif // PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
+
+} // namespace internal
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_LEGACY_H_
diff --git a/include/perfetto/tracing/internal/track_event_macros.h b/include/perfetto/tracing/internal/track_event_macros.h
index 3078f88..6d2777e 100644
--- a/include/perfetto/tracing/internal/track_event_macros.h
+++ b/include/perfetto/tracing/internal/track_event_macros.h
@@ -112,7 +112,7 @@
// Efficiently determines whether tracing is enabled for the given category, and
// if so, emits one trace event with the given arguments.
-#define PERFETTO_INTERNAL_TRACK_EVENT(category, name, ...) \
+#define PERFETTO_INTERNAL_TRACK_EVENT_WITH_METHOD(method, category, name, ...) \
do { \
::perfetto::internal::ValidateEventNameType<decltype(name)>(); \
namespace tns = PERFETTO_TRACK_EVENT_NAMESPACE; \
@@ -125,14 +125,13 @@
category)) { \
tns::TrackEvent::CallIfEnabled( \
[&](uint32_t instances) PERFETTO_NO_THREAD_SAFETY_ANALYSIS { \
- tns::TrackEvent::TraceForCategory(instances, category, name, \
- ##__VA_ARGS__); \
+ tns::TrackEvent::method(instances, category, name, ##__VA_ARGS__); \
}); \
} else { \
tns::TrackEvent::CallIfCategoryEnabled( \
PERFETTO_UID(kCatIndex_ADD_TO_PERFETTO_DEFINE_CATEGORIES_IF_FAILS_), \
[&](uint32_t instances) PERFETTO_NO_THREAD_SAFETY_ANALYSIS { \
- tns::TrackEvent::TraceForCategory( \
+ tns::TrackEvent::method( \
instances, \
PERFETTO_UID( \
kCatIndex_ADD_TO_PERFETTO_DEFINE_CATEGORIES_IF_FAILS_), \
@@ -141,6 +140,19 @@
} \
} while (false)
+#define PERFETTO_INTERNAL_TRACK_EVENT(...) \
+ PERFETTO_INTERNAL_TRACK_EVENT_WITH_METHOD(TraceForCategory, ##__VA_ARGS__)
+
+#if PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
+#define PERFETTO_INTERNAL_LEGACY_TRACK_EVENT(...) \
+ PERFETTO_INTERNAL_TRACK_EVENT_WITH_METHOD(TraceForCategoryLegacy, \
+ ##__VA_ARGS__)
+
+#define PERFETTO_INTERNAL_LEGACY_TRACK_EVENT_WITH_ID(...) \
+ PERFETTO_INTERNAL_TRACK_EVENT_WITH_METHOD(TraceForCategoryLegacyWithId, \
+ ##__VA_ARGS__)
+#endif // PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
+
// C++17 doesn't like a move constructor being defined for the EventFinalizer
// class but C++11 and MSVC doesn't compile without it being defined so support
// both.
@@ -150,7 +162,7 @@
#define PERFETTO_INTERNAL_EVENT_FINALIZER_KEYWORD default
#endif
-#define PERFETTO_INTERNAL_SCOPED_TRACK_EVENT(category, name, ...) \
+#define PERFETTO_INTERNAL_SCOPED_EVENT_FINALIZER(category) \
struct PERFETTO_UID(ScopedEvent) { \
struct EventFinalizer { \
/* The parameter is an implementation detail. It allows the */ \
@@ -170,13 +182,34 @@
PERFETTO_INTERNAL_EVENT_FINALIZER_KEYWORD; \
EventFinalizer& operator=(EventFinalizer&&) = delete; \
} finalizer; \
- } PERFETTO_UID(scoped_event) { \
- [&]() { \
- TRACE_EVENT_BEGIN(category, name, ##__VA_ARGS__); \
- return 0; \
- }() \
}
+#define PERFETTO_INTERNAL_SCOPED_TRACK_EVENT(category, name, ...) \
+ PERFETTO_INTERNAL_SCOPED_EVENT_FINALIZER(category) \
+ PERFETTO_UID(scoped_event) { \
+ [&]() { \
+ TRACE_EVENT_BEGIN(category, name, ##__VA_ARGS__); \
+ return 0; \
+ }() \
+ }
+
+#if PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
+// Required for TRACE_EVENT_WITH_FLOW legacy macros, which pass the bind_id as
+// id.
+#define PERFETTO_INTERNAL_SCOPED_LEGACY_TRACK_EVENT_WITH_ID( \
+ category, name, track, flags, thread_id, id, ...) \
+ PERFETTO_INTERNAL_SCOPED_EVENT_FINALIZER(category) \
+ PERFETTO_UID(scoped_event) { \
+ [&]() { \
+ PERFETTO_INTERNAL_LEGACY_TRACK_EVENT_WITH_ID( \
+ category, name, \
+ ::perfetto::protos::pbzero::TrackEvent::TYPE_SLICE_BEGIN, track, \
+ 'B', flags, thread_id, id, ##__VA_ARGS__); \
+ return 0; \
+ }() \
+ }
+#endif // PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
+
#if PERFETTO_BUILDFLAG(PERFETTO_COMPILER_GCC)
// On GCC versions <9 there's a bug that prevents using captured constant
// variables in constexpr evaluation inside a lambda:
diff --git a/include/perfetto/tracing/track_event.h b/include/perfetto/tracing/track_event.h
index 7366b85..f95d42c 100644
--- a/include/perfetto/tracing/track_event.h
+++ b/include/perfetto/tracing/track_event.h
@@ -126,6 +126,7 @@
// If the program uses multiple track event namespaces, category & track event
// registration (see quickstart above) needs to happen for both namespaces
// separately.
+
#ifndef PERFETTO_TRACK_EVENT_NAMESPACE
#define PERFETTO_TRACK_EVENT_NAMESPACE perfetto_track_event
#endif
@@ -350,9 +351,9 @@
// TRACE_EVENT("category", "Name", perfetto::Track(1234),
// "arg", value, "arg2", value2);
//
-#define TRACE_EVENT_BEGIN(category, name, ...) \
- PERFETTO_INTERNAL_TRACK_EVENT( \
- category, name, \
+#define TRACE_EVENT_BEGIN(category, name, ...) \
+ PERFETTO_INTERNAL_TRACK_EVENT( \
+ category, ::perfetto::internal::DecayEventNameType(name), \
::perfetto::protos::pbzero::TrackEvent::TYPE_SLICE_BEGIN, ##__VA_ARGS__)
// End a slice under |category|.
@@ -363,13 +364,14 @@
// Begin a slice which gets automatically closed when going out of scope.
#define TRACE_EVENT(category, name, ...) \
- PERFETTO_INTERNAL_SCOPED_TRACK_EVENT(category, name, ##__VA_ARGS__)
+ PERFETTO_INTERNAL_SCOPED_TRACK_EVENT( \
+ category, ::perfetto::internal::DecayEventNameType(name), ##__VA_ARGS__)
// Emit a slice which has zero duration.
-#define TRACE_EVENT_INSTANT(category, name, ...) \
- PERFETTO_INTERNAL_TRACK_EVENT( \
- category, name, ::perfetto::protos::pbzero::TrackEvent::TYPE_INSTANT, \
- ##__VA_ARGS__)
+#define TRACE_EVENT_INSTANT(category, name, ...) \
+ PERFETTO_INTERNAL_TRACK_EVENT( \
+ category, ::perfetto::internal::DecayEventNameType(name), \
+ ::perfetto::protos::pbzero::TrackEvent::TYPE_INSTANT, ##__VA_ARGS__)
// Efficiently determine if the given static or dynamic trace category or
// category group is enabled for tracing.
diff --git a/include/perfetto/tracing/track_event_legacy.h b/include/perfetto/tracing/track_event_legacy.h
index 373e2a5..7111733 100644
--- a/include/perfetto/tracing/track_event_legacy.h
+++ b/include/perfetto/tracing/track_event_legacy.h
@@ -37,130 +37,6 @@
#endif
// ----------------------------------------------------------------------------
-// Constants.
-// ----------------------------------------------------------------------------
-
-namespace perfetto {
-namespace legacy {
-
-enum TraceEventFlag {
- kTraceEventFlagNone = 0,
- kTraceEventFlagCopy = 1u << 0,
- kTraceEventFlagHasId = 1u << 1,
- kTraceEventFlagScopeOffset = 1u << 2,
- kTraceEventFlagScopeExtra = 1u << 3,
- kTraceEventFlagExplicitTimestamp = 1u << 4,
- kTraceEventFlagAsyncTTS = 1u << 5,
- kTraceEventFlagBindToEnclosing = 1u << 6,
- kTraceEventFlagFlowIn = 1u << 7,
- kTraceEventFlagFlowOut = 1u << 8,
- kTraceEventFlagHasContextId = 1u << 9,
- kTraceEventFlagHasProcessId = 1u << 10,
- kTraceEventFlagHasLocalId = 1u << 11,
- kTraceEventFlagHasGlobalId = 1u << 12,
- // TODO(eseckler): Remove once we have native support for typed proto events
- // in TRACE_EVENT macros.
- kTraceEventFlagTypedProtoArgs = 1u << 15,
- kTraceEventFlagJavaStringLiterals = 1u << 16,
-};
-
-enum PerfettoLegacyCurrentThreadId { kCurrentThreadId };
-
-} // namespace legacy
-} // namespace perfetto
-
-#if PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
-// The following constants are defined in the global namespace, since they were
-// originally implemented as macros.
-
-// Event phases.
-static constexpr char TRACE_EVENT_PHASE_BEGIN = 'B';
-static constexpr char TRACE_EVENT_PHASE_END = 'E';
-static constexpr char TRACE_EVENT_PHASE_COMPLETE = 'X';
-static constexpr char TRACE_EVENT_PHASE_INSTANT = 'I';
-static constexpr char TRACE_EVENT_PHASE_ASYNC_BEGIN = 'S';
-static constexpr char TRACE_EVENT_PHASE_ASYNC_STEP_INTO = 'T';
-static constexpr char TRACE_EVENT_PHASE_ASYNC_STEP_PAST = 'p';
-static constexpr char TRACE_EVENT_PHASE_ASYNC_END = 'F';
-static constexpr char TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN = 'b';
-static constexpr char TRACE_EVENT_PHASE_NESTABLE_ASYNC_END = 'e';
-static constexpr char TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT = 'n';
-static constexpr char TRACE_EVENT_PHASE_FLOW_BEGIN = 's';
-static constexpr char TRACE_EVENT_PHASE_FLOW_STEP = 't';
-static constexpr char TRACE_EVENT_PHASE_FLOW_END = 'f';
-static constexpr char TRACE_EVENT_PHASE_METADATA = 'M';
-static constexpr char TRACE_EVENT_PHASE_COUNTER = 'C';
-static constexpr char TRACE_EVENT_PHASE_SAMPLE = 'P';
-static constexpr char TRACE_EVENT_PHASE_CREATE_OBJECT = 'N';
-static constexpr char TRACE_EVENT_PHASE_SNAPSHOT_OBJECT = 'O';
-static constexpr char TRACE_EVENT_PHASE_DELETE_OBJECT = 'D';
-static constexpr char TRACE_EVENT_PHASE_MEMORY_DUMP = 'v';
-static constexpr char TRACE_EVENT_PHASE_MARK = 'R';
-static constexpr char TRACE_EVENT_PHASE_CLOCK_SYNC = 'c';
-
-// Flags for changing the behavior of TRACE_EVENT_API_ADD_TRACE_EVENT.
-static constexpr uint32_t TRACE_EVENT_FLAG_NONE =
- perfetto::legacy::kTraceEventFlagNone;
-static constexpr uint32_t TRACE_EVENT_FLAG_COPY =
- perfetto::legacy::kTraceEventFlagCopy;
-static constexpr uint32_t TRACE_EVENT_FLAG_HAS_ID =
- perfetto::legacy::kTraceEventFlagHasId;
-static constexpr uint32_t TRACE_EVENT_FLAG_SCOPE_OFFSET =
- perfetto::legacy::kTraceEventFlagScopeOffset;
-static constexpr uint32_t TRACE_EVENT_FLAG_SCOPE_EXTRA =
- perfetto::legacy::kTraceEventFlagScopeExtra;
-static constexpr uint32_t TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP =
- perfetto::legacy::kTraceEventFlagExplicitTimestamp;
-static constexpr uint32_t TRACE_EVENT_FLAG_ASYNC_TTS =
- perfetto::legacy::kTraceEventFlagAsyncTTS;
-static constexpr uint32_t TRACE_EVENT_FLAG_BIND_TO_ENCLOSING =
- perfetto::legacy::kTraceEventFlagBindToEnclosing;
-static constexpr uint32_t TRACE_EVENT_FLAG_FLOW_IN =
- perfetto::legacy::kTraceEventFlagFlowIn;
-static constexpr uint32_t TRACE_EVENT_FLAG_FLOW_OUT =
- perfetto::legacy::kTraceEventFlagFlowOut;
-static constexpr uint32_t TRACE_EVENT_FLAG_HAS_CONTEXT_ID =
- perfetto::legacy::kTraceEventFlagHasContextId;
-static constexpr uint32_t TRACE_EVENT_FLAG_HAS_PROCESS_ID =
- perfetto::legacy::kTraceEventFlagHasProcessId;
-static constexpr uint32_t TRACE_EVENT_FLAG_HAS_LOCAL_ID =
- perfetto::legacy::kTraceEventFlagHasLocalId;
-static constexpr uint32_t TRACE_EVENT_FLAG_HAS_GLOBAL_ID =
- perfetto::legacy::kTraceEventFlagHasGlobalId;
-static constexpr uint32_t TRACE_EVENT_FLAG_TYPED_PROTO_ARGS =
- perfetto::legacy::kTraceEventFlagTypedProtoArgs;
-static constexpr uint32_t TRACE_EVENT_FLAG_JAVA_STRING_LITERALS =
- perfetto::legacy::kTraceEventFlagJavaStringLiterals;
-
-static constexpr uint32_t TRACE_EVENT_FLAG_SCOPE_MASK =
- TRACE_EVENT_FLAG_SCOPE_OFFSET | TRACE_EVENT_FLAG_SCOPE_EXTRA;
-
-// Type values for identifying types in the TraceValue union.
-static constexpr uint8_t TRACE_VALUE_TYPE_BOOL = 1;
-static constexpr uint8_t TRACE_VALUE_TYPE_UINT = 2;
-static constexpr uint8_t TRACE_VALUE_TYPE_INT = 3;
-static constexpr uint8_t TRACE_VALUE_TYPE_DOUBLE = 4;
-static constexpr uint8_t TRACE_VALUE_TYPE_POINTER = 5;
-static constexpr uint8_t TRACE_VALUE_TYPE_STRING = 6;
-static constexpr uint8_t TRACE_VALUE_TYPE_COPY_STRING = 7;
-static constexpr uint8_t TRACE_VALUE_TYPE_CONVERTABLE = 8;
-static constexpr uint8_t TRACE_VALUE_TYPE_PROTO = 9;
-
-// Enum reflecting the scope of an INSTANT event. Must fit within
-// TRACE_EVENT_FLAG_SCOPE_MASK.
-static constexpr uint8_t TRACE_EVENT_SCOPE_GLOBAL = 0u << 2;
-static constexpr uint8_t TRACE_EVENT_SCOPE_PROCESS = 1u << 2;
-static constexpr uint8_t TRACE_EVENT_SCOPE_THREAD = 2u << 2;
-
-static constexpr char TRACE_EVENT_SCOPE_NAME_GLOBAL = 'g';
-static constexpr char TRACE_EVENT_SCOPE_NAME_PROCESS = 'p';
-static constexpr char TRACE_EVENT_SCOPE_NAME_THREAD = 't';
-
-#define TRACE_EVENT_API_CURRENT_THREAD_ID ::perfetto::legacy::kCurrentThreadId
-
-#endif // PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
-
-// ----------------------------------------------------------------------------
// Internal legacy trace point implementation.
// ----------------------------------------------------------------------------
@@ -184,310 +60,33 @@
ConvertThreadId(const PerfettoLegacyCurrentThreadId&);
} // namespace legacy
-
-namespace internal {
-
-// LegacyTraceId encapsulates an ID that can either be an integer or pointer.
-class PERFETTO_EXPORT_COMPONENT LegacyTraceId {
- public:
- // Can be combined with WithScope.
- class LocalId {
- public:
- explicit LocalId(const void* raw_id)
- : raw_id_(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(raw_id))) {}
- explicit LocalId(uint64_t raw_id) : raw_id_(raw_id) {}
- uint64_t raw_id() const { return raw_id_; }
-
- private:
- uint64_t raw_id_;
- };
-
- // Can be combined with WithScope.
- class GlobalId {
- public:
- explicit GlobalId(uint64_t raw_id) : raw_id_(raw_id) {}
- uint64_t raw_id() const { return raw_id_; }
-
- private:
- uint64_t raw_id_;
- };
-
- class WithScope {
- public:
- WithScope(const char* scope, uint64_t raw_id)
- : scope_(scope), raw_id_(raw_id) {}
- WithScope(const char* scope, LocalId local_id)
- : scope_(scope), raw_id_(local_id.raw_id()) {
- id_flags_ = legacy::kTraceEventFlagHasLocalId;
- }
- WithScope(const char* scope, GlobalId global_id)
- : scope_(scope), raw_id_(global_id.raw_id()) {
- id_flags_ = legacy::kTraceEventFlagHasGlobalId;
- }
- WithScope(const char* scope, uint64_t prefix, uint64_t raw_id)
- : scope_(scope), has_prefix_(true), prefix_(prefix), raw_id_(raw_id) {}
- WithScope(const char* scope, uint64_t prefix, GlobalId global_id)
- : scope_(scope),
- has_prefix_(true),
- prefix_(prefix),
- raw_id_(global_id.raw_id()) {
- id_flags_ = legacy::kTraceEventFlagHasGlobalId;
- }
- uint64_t raw_id() const { return raw_id_; }
- const char* scope() const { return scope_; }
- bool has_prefix() const { return has_prefix_; }
- uint64_t prefix() const { return prefix_; }
- uint32_t id_flags() const { return id_flags_; }
-
- private:
- const char* scope_ = nullptr;
- bool has_prefix_ = false;
- uint64_t prefix_;
- uint64_t raw_id_;
- uint32_t id_flags_ = legacy::kTraceEventFlagHasId;
- };
-
- explicit LegacyTraceId(const void* raw_id)
- : raw_id_(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(raw_id))) {
- id_flags_ = legacy::kTraceEventFlagHasLocalId;
- }
- explicit LegacyTraceId(uint64_t raw_id) : raw_id_(raw_id) {}
- explicit LegacyTraceId(uint32_t raw_id) : raw_id_(raw_id) {}
- explicit LegacyTraceId(uint16_t raw_id) : raw_id_(raw_id) {}
- explicit LegacyTraceId(uint8_t raw_id) : raw_id_(raw_id) {}
- explicit LegacyTraceId(int64_t raw_id)
- : raw_id_(static_cast<uint64_t>(raw_id)) {}
- explicit LegacyTraceId(int32_t raw_id)
- : raw_id_(static_cast<uint64_t>(raw_id)) {}
- explicit LegacyTraceId(int16_t raw_id)
- : raw_id_(static_cast<uint64_t>(raw_id)) {}
- explicit LegacyTraceId(int8_t raw_id)
- : raw_id_(static_cast<uint64_t>(raw_id)) {}
-// Different platforms disagree on which integer types are same and which
-// are different. E.g. on Mac size_t is considered a different type from
-// uint64_t even though it has the same size and signedness.
-// Below we add overloads for those types that are known to cause ambiguity.
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
- explicit LegacyTraceId(size_t raw_id) : raw_id_(raw_id) {}
- explicit LegacyTraceId(intptr_t raw_id)
- : raw_id_(static_cast<uint64_t>(raw_id)) {}
-#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
- explicit LegacyTraceId(unsigned long raw_id) : raw_id_(raw_id) {}
-#endif
- explicit LegacyTraceId(LocalId raw_id) : raw_id_(raw_id.raw_id()) {
- id_flags_ = legacy::kTraceEventFlagHasLocalId;
- }
- explicit LegacyTraceId(GlobalId raw_id) : raw_id_(raw_id.raw_id()) {
- id_flags_ = legacy::kTraceEventFlagHasGlobalId;
- }
- explicit LegacyTraceId(WithScope scoped_id)
- : scope_(scoped_id.scope()),
- has_prefix_(scoped_id.has_prefix()),
- prefix_(scoped_id.prefix()),
- raw_id_(scoped_id.raw_id()),
- id_flags_(scoped_id.id_flags()) {}
-
- uint64_t raw_id() const { return raw_id_; }
- const char* scope() const { return scope_; }
- bool has_prefix() const { return has_prefix_; }
- uint64_t prefix() const { return prefix_; }
- uint32_t id_flags() const { return id_flags_; }
-
- void Write(protos::pbzero::TrackEvent::LegacyEvent*,
- uint32_t event_flags) const;
-
- private:
- const char* scope_ = nullptr;
- bool has_prefix_ = false;
- uint64_t prefix_;
- uint64_t raw_id_;
- uint32_t id_flags_ = legacy::kTraceEventFlagHasId;
-};
-
-} // namespace internal
} // namespace perfetto
#if PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
-namespace perfetto {
-namespace internal {
-
-template <typename T>
-bool IsEqual(T x, T y) {
- return x == y;
-}
-
-template <typename T, typename U>
-bool IsEqual(T x, U y) {
- return false;
-}
-
-class PERFETTO_EXPORT_COMPONENT TrackEventLegacy {
- public:
- static constexpr protos::pbzero::TrackEvent::Type PhaseToType(char phase) {
- // clang-format off
- return (phase == TRACE_EVENT_PHASE_BEGIN) ?
- protos::pbzero::TrackEvent::TYPE_SLICE_BEGIN :
- (phase == TRACE_EVENT_PHASE_END) ?
- protos::pbzero::TrackEvent::TYPE_SLICE_END :
- (phase == TRACE_EVENT_PHASE_INSTANT) ?
- protos::pbzero::TrackEvent::TYPE_INSTANT :
- protos::pbzero::TrackEvent::TYPE_UNSPECIFIED;
- // clang-format on
- }
-
- // Reduce binary size overhead by outlining most of the code for writing a
- // legacy trace event.
- template <typename... Args>
- static void WriteLegacyEvent(EventContext ctx,
- char phase,
- uint32_t flags,
- Args&&... args) PERFETTO_NO_INLINE {
- PERFETTO_DCHECK(!(flags & TRACE_EVENT_FLAG_HAS_PROCESS_ID));
- AddDebugAnnotations(&ctx, std::forward<Args>(args)...);
- if (NeedLegacyFlags(phase, flags)) {
- auto legacy_event = ctx.event()->set_legacy_event();
- SetLegacyFlags(legacy_event, phase, flags);
- }
- }
-
- template <typename ThreadIdType, typename... Args>
- static void WriteLegacyEventWithIdAndTid(EventContext ctx,
- char phase,
- uint32_t flags,
- const LegacyTraceId& id,
- const ThreadIdType& thread_id,
- Args&&... args) PERFETTO_NO_INLINE {
- //
- // Overrides to consider:
- //
- // 1. If we have an id, we need to write {unscoped,local,global}_id and/or
- // bind_id.
- // 2. If we have a thread id, we need to write track_uuid() or
- // {pid,tid}_override if the id represents another process. The
- // conversion from |thread_id| happens in embedder code since the type is
- // embedder-specified.
- // 3. If we have a timestamp, we need to write a different timestamp in the
- // trace packet itself and make sure TrackEvent won't write one
- // internally. This is already done at the call site.
- //
- PERFETTO_DCHECK(PhaseToType(phase) ==
- protos::pbzero::TrackEvent::TYPE_UNSPECIFIED ||
- !(flags & TRACE_EVENT_FLAG_HAS_PROCESS_ID));
- flags |= id.id_flags();
- AddDebugAnnotations(&ctx, std::forward<Args>(args)...);
- if (NeedLegacyFlags(phase, flags)) {
- auto legacy_event = ctx.event()->set_legacy_event();
- SetLegacyFlags(legacy_event, phase, flags);
- if (id.id_flags())
- id.Write(legacy_event, flags);
- if (flags & TRACE_EVENT_FLAG_HAS_PROCESS_ID) {
- // The thread identifier actually represents a process id. Let's set an
- // override for it.
- int32_t pid_override =
- static_cast<int32_t>(legacy::ConvertThreadId(thread_id).tid);
- legacy_event->set_pid_override(pid_override);
- legacy_event->set_tid_override(-1);
- } else {
- // Only synchronous phases are supported for other threads. These phases
- // are supported in TrackEvent types and receive a track_uuid
- // association via TrackEventDataSource::TraceForCategoryImpl().
- PERFETTO_DCHECK(PhaseToType(phase) !=
- protos::pbzero::TrackEvent::TYPE_UNSPECIFIED ||
- IsEqual(thread_id, TRACE_EVENT_API_CURRENT_THREAD_ID) ||
- legacy::ConvertThreadId(thread_id).tid ==
- ThreadTrack::Current().tid);
- }
- }
- }
-
- // No arguments.
- static void AddDebugAnnotations(EventContext*) {}
-
- // N number of debug arguments.
- template <typename ArgNameType, typename ArgType, typename... OtherArgs>
- static void AddDebugAnnotations(EventContext* ctx,
- ArgNameType&& arg_name,
- ArgType&& arg_value,
- OtherArgs&&... more_args) {
- TrackEventInternal::AddDebugAnnotation(ctx,
- std::forward<ArgNameType>(arg_name),
- std::forward<ArgType>(arg_value));
- AddDebugAnnotations(ctx, std::forward<OtherArgs>(more_args)...);
- }
-
- private:
- static bool NeedLegacyFlags(char phase, uint32_t flags) {
- if (PhaseToType(phase) == protos::pbzero::TrackEvent::TYPE_UNSPECIFIED)
- return true;
- // TODO(skyostil): Implement/deprecate:
- // - TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP
- // - TRACE_EVENT_FLAG_HAS_CONTEXT_ID
- // - TRACE_EVENT_FLAG_TYPED_PROTO_ARGS
- // - TRACE_EVENT_FLAG_JAVA_STRING_LITERALS
- return flags &
- (TRACE_EVENT_FLAG_HAS_ID | TRACE_EVENT_FLAG_HAS_LOCAL_ID |
- TRACE_EVENT_FLAG_HAS_GLOBAL_ID | TRACE_EVENT_FLAG_ASYNC_TTS |
- TRACE_EVENT_FLAG_BIND_TO_ENCLOSING | TRACE_EVENT_FLAG_FLOW_IN |
- TRACE_EVENT_FLAG_FLOW_OUT | TRACE_EVENT_FLAG_HAS_PROCESS_ID);
- }
-
- static void SetLegacyFlags(
- protos::pbzero::TrackEvent::LegacyEvent* legacy_event,
- char phase,
- uint32_t flags) {
- if (PhaseToType(phase) == protos::pbzero::TrackEvent::TYPE_UNSPECIFIED)
- legacy_event->set_phase(phase);
- if (flags & TRACE_EVENT_FLAG_ASYNC_TTS)
- legacy_event->set_use_async_tts(true);
- if (flags & TRACE_EVENT_FLAG_BIND_TO_ENCLOSING)
- legacy_event->set_bind_to_enclosing(true);
-
- const auto kFlowIn = TRACE_EVENT_FLAG_FLOW_IN;
- const auto kFlowOut = TRACE_EVENT_FLAG_FLOW_OUT;
- const auto kFlowInOut = kFlowIn | kFlowOut;
- if ((flags & kFlowInOut) == kFlowInOut) {
- legacy_event->set_flow_direction(
- protos::pbzero::TrackEvent::LegacyEvent::FLOW_INOUT);
- } else if (flags & kFlowIn) {
- legacy_event->set_flow_direction(
- protos::pbzero::TrackEvent::LegacyEvent::FLOW_IN);
- } else if (flags & kFlowOut) {
- legacy_event->set_flow_direction(
- protos::pbzero::TrackEvent::LegacyEvent::FLOW_OUT);
- }
- }
-};
-
-inline ::perfetto::DynamicString GetEventNameTypeForLegacyEvents(
- ::perfetto::DynamicString name) {
- return name;
-}
-
-inline ::perfetto::StaticString GetEventNameTypeForLegacyEvents(
- ::perfetto::StaticString name) {
- return name;
-}
-
-// In legacy macro, `const char*` is considered static by default, unless it's
-// wrapped in `TRACE_STR_COPY`.
-inline ::perfetto::StaticString GetEventNameTypeForLegacyEvents(
- const char* name) {
- return ::perfetto::StaticString{name};
-}
-
-} // namespace internal
-} // namespace perfetto
-
// Implementations for the INTERNAL_* adapter macros used by the trace points
// below.
#define PERFETTO_INTERNAL_LEGACY_EVENT_ON_TRACK(phase, category, name, track, \
...) \
PERFETTO_INTERNAL_TRACK_EVENT( \
- category, ::perfetto::internal::GetEventNameTypeForLegacyEvents(name), \
+ category, ::perfetto::internal::DecayEventNameType(name), \
::perfetto::internal::TrackEventLegacy::PhaseToType(phase), track, \
##__VA_ARGS__);
+#define PERFETTO_INTERNAL_LEGACY_EVENT_WITH_FLAGS_ON_TRACK( \
+ phase, category, name, track, flags, ...) \
+ PERFETTO_INTERNAL_LEGACY_TRACK_EVENT( \
+ category, ::perfetto::internal::DecayEventNameType(name), \
+ ::perfetto::internal::TrackEventLegacy::PhaseToType(phase), track, \
+ phase, flags, ##__VA_ARGS__);
+
+#define PERFETTO_INTERNAL_LEGACY_EVENT_WITH_ID_ON_TRACK( \
+ phase, category, name, track, flags, thread_id, id, ...) \
+ PERFETTO_INTERNAL_LEGACY_TRACK_EVENT_WITH_ID( \
+ category, ::perfetto::internal::DecayEventNameType(name), \
+ ::perfetto::internal::TrackEventLegacy::PhaseToType(phase), track, \
+ phase, flags, thread_id, id, ##__VA_ARGS__);
+
// The main entrypoint for writing unscoped legacy events. This macro
// determines the right track to write the event on based on |flags| and
// |thread_id|.
@@ -502,14 +101,14 @@
auto scope = (flags)&TRACE_EVENT_FLAG_SCOPE_MASK; \
switch (scope) { \
case TRACE_EVENT_SCOPE_GLOBAL: \
- PERFETTO_INTERNAL_LEGACY_EVENT_ON_TRACK( \
- phase, category, name, ::perfetto::Track::Global(0), \
+ PERFETTO_INTERNAL_LEGACY_EVENT_WITH_FLAGS_ON_TRACK( \
+ phase, category, name, ::perfetto::Track::Global(0), flags, \
##__VA_ARGS__); \
return; \
case TRACE_EVENT_SCOPE_PROCESS: \
- PERFETTO_INTERNAL_LEGACY_EVENT_ON_TRACK( \
+ PERFETTO_INTERNAL_LEGACY_EVENT_WITH_FLAGS_ON_TRACK( \
phase, category, name, ::perfetto::ProcessTrack::Current(), \
- ##__VA_ARGS__); \
+ flags, ##__VA_ARGS__); \
return; \
default: \
case TRACE_EVENT_SCOPE_THREAD: \
@@ -524,84 +123,94 @@
decltype(thread_id), \
::perfetto::legacy::PerfettoLegacyCurrentThreadId>::value || \
((flags)&TRACE_EVENT_FLAG_HAS_PROCESS_ID)) { \
- PERFETTO_INTERNAL_LEGACY_EVENT_ON_TRACK( \
- phase, category, name, TrackEventInternal::kDefaultTrack, \
+ PERFETTO_INTERNAL_LEGACY_EVENT_WITH_FLAGS_ON_TRACK( \
+ phase, category, name, TrackEventInternal::kDefaultTrack, flags, \
##__VA_ARGS__); \
} else { \
- PERFETTO_INTERNAL_LEGACY_EVENT_ON_TRACK( \
+ PERFETTO_INTERNAL_LEGACY_EVENT_WITH_FLAGS_ON_TRACK( \
phase, category, name, \
- ::perfetto::legacy::ConvertThreadId(thread_id), ##__VA_ARGS__); \
+ ::perfetto::legacy::ConvertThreadId(thread_id), flags, \
+ ##__VA_ARGS__); \
} \
}()
-#define INTERNAL_TRACE_EVENT_ADD(phase, category, name, flags, ...) \
- PERFETTO_INTERNAL_LEGACY_EVENT( \
- phase, category, name, flags, ::perfetto::legacy::kCurrentThreadId, \
- [&](perfetto::EventContext ctx) PERFETTO_NO_THREAD_SAFETY_ANALYSIS { \
- using ::perfetto::internal::TrackEventLegacy; \
- TrackEventLegacy::WriteLegacyEvent(std::move(ctx), phase, flags, \
- ##__VA_ARGS__); \
- })
+#define PERFETTO_INTERNAL_LEGACY_EVENT_WITH_ID(phase, category, name, flags, \
+ thread_id, id, ...) \
+ [&]() { \
+ using ::perfetto::internal::TrackEventInternal; \
+ PERFETTO_DCHECK(!(flags & TRACE_EVENT_FLAG_COPY)); \
+ /* First check the scope for instant events. */ \
+ if ((phase) == TRACE_EVENT_PHASE_INSTANT) { \
+ /* Note: Avoids the need to set LegacyEvent::instant_event_scope. */ \
+ auto scope = (flags)&TRACE_EVENT_FLAG_SCOPE_MASK; \
+ switch (scope) { \
+ case TRACE_EVENT_SCOPE_GLOBAL: \
+ PERFETTO_INTERNAL_LEGACY_EVENT_WITH_ID_ON_TRACK( \
+ phase, category, name, ::perfetto::Track::Global(0), flags, \
+ thread_id, id, ##__VA_ARGS__); \
+ return; \
+ case TRACE_EVENT_SCOPE_PROCESS: \
+ PERFETTO_INTERNAL_LEGACY_EVENT_WITH_ID_ON_TRACK( \
+ phase, category, name, ::perfetto::ProcessTrack::Current(), \
+ flags, thread_id, id, ##__VA_ARGS__); \
+ return; \
+ default: \
+ case TRACE_EVENT_SCOPE_THREAD: \
+ /* Fallthrough. */ \
+ break; \
+ } \
+ } \
+ /* If an event targets the current thread or another process, write \
+ * it on the current thread's track. The process override case is \
+ * handled through |pid_override| in WriteLegacyEvent. */ \
+ if (std::is_same< \
+ decltype(thread_id), \
+ ::perfetto::legacy::PerfettoLegacyCurrentThreadId>::value || \
+ ((flags)&TRACE_EVENT_FLAG_HAS_PROCESS_ID)) { \
+ PERFETTO_INTERNAL_LEGACY_EVENT_WITH_ID_ON_TRACK( \
+ phase, category, name, TrackEventInternal::kDefaultTrack, flags, \
+ thread_id, id, ##__VA_ARGS__); \
+ } else { \
+ PERFETTO_INTERNAL_LEGACY_EVENT_WITH_ID_ON_TRACK( \
+ phase, category, name, \
+ ::perfetto::legacy::ConvertThreadId(thread_id), flags, thread_id, \
+ id, ##__VA_ARGS__); \
+ } \
+ }()
-// PERFETTO_INTERNAL_SCOPED_TRACK_EVENT does not require GetStaticString, as it
-// uses TRACE_EVENT_BEGIN/END internally, which already have this call.
-#define INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, ...) \
- PERFETTO_INTERNAL_SCOPED_TRACK_EVENT( \
- category, ::perfetto::internal::GetEventNameTypeForLegacyEvents(name), \
- [&](perfetto::EventContext ctx) PERFETTO_NO_THREAD_SAFETY_ANALYSIS { \
- using ::perfetto::internal::TrackEventLegacy; \
- TrackEventLegacy::AddDebugAnnotations(&ctx, ##__VA_ARGS__); \
- })
+#define INTERNAL_TRACE_EVENT_ADD(phase, category, name, flags, ...) \
+ PERFETTO_INTERNAL_LEGACY_EVENT( \
+ phase, category, ::perfetto::internal::DecayEventNameType(name), flags, \
+ ::perfetto::legacy::kCurrentThreadId, ##__VA_ARGS__)
-// PERFETTO_INTERNAL_SCOPED_TRACK_EVENT does not require GetStaticString, as it
-// uses TRACE_EVENT_BEGIN/END internally, which already have this call.
-#define INTERNAL_TRACE_EVENT_ADD_SCOPED_WITH_FLOW(category, name, bind_id, \
- flags, ...) \
- PERFETTO_INTERNAL_SCOPED_TRACK_EVENT( \
- category, ::perfetto::internal::GetEventNameTypeForLegacyEvents(name), \
- [&](perfetto::EventContext ctx) PERFETTO_NO_THREAD_SAFETY_ANALYSIS { \
- using ::perfetto::internal::TrackEventLegacy; \
- ::perfetto::internal::LegacyTraceId PERFETTO_UID(trace_id){bind_id}; \
- TrackEventLegacy::WriteLegacyEventWithIdAndTid( \
- std::move(ctx), TRACE_EVENT_PHASE_BEGIN, flags, \
- PERFETTO_UID(trace_id), TRACE_EVENT_API_CURRENT_THREAD_ID, \
- ##__VA_ARGS__); \
- })
+#define INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, ...) \
+ PERFETTO_INTERNAL_SCOPED_TRACK_EVENT( \
+ category, ::perfetto::internal::DecayEventNameType(name), ##__VA_ARGS__)
-#define INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP(phase, category, name, \
- timestamp, flags, ...) \
- PERFETTO_INTERNAL_LEGACY_EVENT( \
- phase, category, name, flags, ::perfetto::legacy::kCurrentThreadId, \
- timestamp, \
- [&](perfetto::EventContext ctx) PERFETTO_NO_THREAD_SAFETY_ANALYSIS { \
- using ::perfetto::internal::TrackEventLegacy; \
- TrackEventLegacy::WriteLegacyEvent(std::move(ctx), phase, flags, \
- ##__VA_ARGS__); \
- })
+#define INTERNAL_TRACE_EVENT_ADD_SCOPED_WITH_FLOW(category, name, bind_id, \
+ flags, ...) \
+ PERFETTO_INTERNAL_SCOPED_LEGACY_TRACK_EVENT_WITH_ID( \
+ category, ::perfetto::internal::DecayEventNameType(name), \
+ ::perfetto::internal::TrackEventInternal::kDefaultTrack, flags, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, bind_id, ##__VA_ARGS__)
-#define INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
- phase, category, name, id, thread_id, timestamp, flags, ...) \
- PERFETTO_INTERNAL_LEGACY_EVENT( \
- phase, category, name, flags, thread_id, timestamp, \
- [&](perfetto::EventContext ctx) PERFETTO_NO_THREAD_SAFETY_ANALYSIS { \
- using ::perfetto::internal::TrackEventLegacy; \
- ::perfetto::internal::LegacyTraceId PERFETTO_UID(trace_id){id}; \
- TrackEventLegacy::WriteLegacyEventWithIdAndTid( \
- std::move(ctx), phase, flags, PERFETTO_UID(trace_id), thread_id, \
- ##__VA_ARGS__); \
- })
+#define INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP(phase, category, name, \
+ timestamp, flags, ...) \
+ PERFETTO_INTERNAL_LEGACY_EVENT( \
+ phase, category, ::perfetto::internal::DecayEventNameType(name), flags, \
+ ::perfetto::legacy::kCurrentThreadId, timestamp, ##__VA_ARGS__)
-#define INTERNAL_TRACE_EVENT_ADD_WITH_ID(phase, category, name, id, flags, \
- ...) \
- PERFETTO_INTERNAL_LEGACY_EVENT( \
- phase, category, name, flags, ::perfetto::legacy::kCurrentThreadId, \
- [&](perfetto::EventContext ctx) PERFETTO_NO_THREAD_SAFETY_ANALYSIS { \
- using ::perfetto::internal::TrackEventLegacy; \
- ::perfetto::internal::LegacyTraceId PERFETTO_UID(trace_id){id}; \
- TrackEventLegacy::WriteLegacyEventWithIdAndTid( \
- std::move(ctx), phase, flags, PERFETTO_UID(trace_id), \
- TRACE_EVENT_API_CURRENT_THREAD_ID, ##__VA_ARGS__); \
- })
+#define INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ phase, category, name, id, thread_id, timestamp, flags, ...) \
+ PERFETTO_INTERNAL_LEGACY_EVENT_WITH_ID( \
+ phase, category, ::perfetto::internal::DecayEventNameType(name), flags, \
+ thread_id, id, timestamp, ##__VA_ARGS__)
+
+#define INTERNAL_TRACE_EVENT_ADD_WITH_ID(phase, category, name, id, flags, \
+ ...) \
+ PERFETTO_INTERNAL_LEGACY_EVENT_WITH_ID( \
+ phase, category, ::perfetto::internal::DecayEventNameType(name), flags, \
+ ::perfetto::legacy::kCurrentThreadId, id, ##__VA_ARGS__)
#define INTERNAL_TRACE_EVENT_METADATA_ADD(category, name, ...) \
INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_METADATA, category, name, \