Backed out changeset b71c8c052463 (bug 1943846) for causing mass failures. CLOSED...
[gecko.git] / tools / profiler / core / ProfilerBacktrace.h
blob55811f442249f15f2044cf318834f4706a53890c
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef __PROFILER_BACKTRACE_H
8 #define __PROFILER_BACKTRACE_H
10 #include "ProfileBuffer.h"
12 #include "mozilla/ProfileBufferEntrySerialization.h"
13 #include "mozilla/UniquePtrExtensions.h"
15 #include <string>
17 class ProfileBuffer;
18 class ProfilerCodeAddressService;
19 class ThreadInfo;
20 class UniqueStacks;
22 namespace mozilla {
23 class ProfileChunkedBuffer;
24 class TimeStamp;
25 namespace baseprofiler {
26 class SpliceableJSONWriter;
27 } // namespace baseprofiler
28 } // namespace mozilla
30 // ProfilerBacktrace encapsulates a synchronous sample.
31 // It can work with a ProfileBuffer and/or a ProfileChunkedBuffer (if both, they
32 // must already be linked together). The ProfileChunkedBuffer contains all the
33 // data; the ProfileBuffer is not strictly needed, only provide it if it is
34 // already available at the call site.
35 // And these buffers can either be:
36 // - owned here, so that the ProfilerBacktrace object can be kept for later
37 // use), OR
38 // - referenced through pointers (in cases where the backtrace is immediately
39 // streamed out, so we only need temporary references to external buffers);
40 // these pointers may be null for empty backtraces.
41 class ProfilerBacktrace {
42 public:
43 // Take ownership of external buffers and use them to keep, and to stream a
44 // backtrace. If a ProfileBuffer is given, its underlying chunked buffer must
45 // be provided as well.
46 explicit ProfilerBacktrace(
47 const char* aName,
48 mozilla::UniquePtr<mozilla::ProfileChunkedBuffer>
49 aProfileChunkedBufferStorage,
50 mozilla::UniquePtr<ProfileBuffer> aProfileBufferStorageOrNull = nullptr);
52 // Take pointers to external buffers and use them to stream a backtrace.
53 // If null, the backtrace is effectively empty.
54 // If both are provided, they must already be connected.
55 explicit ProfilerBacktrace(
56 const char* aName,
57 mozilla::ProfileChunkedBuffer* aExternalProfileChunkedBufferOrNull =
58 nullptr,
59 ProfileBuffer* aExternalProfileBufferOrNull = nullptr);
61 ~ProfilerBacktrace();
63 [[nodiscard]] bool IsEmpty() const {
64 return !mProfileChunkedBuffer ||
65 mozilla::ProfileBufferEntryWriter::Serializer<
66 mozilla::ProfileChunkedBuffer>::Bytes(*mProfileChunkedBuffer) <=
67 mozilla::ULEB128Size(0u);
70 // ProfilerBacktraces' stacks are deduplicated in the context of the
71 // profile that contains the backtrace as a marker payload.
73 // That is, markers that contain backtraces should not need their own stack,
74 // frame, and string tables. They should instead reuse their parent
75 // profile's tables.
76 ProfilerThreadId StreamJSON(
77 mozilla::baseprofiler::SpliceableJSONWriter& aWriter,
78 const mozilla::TimeStamp& aProcessStartTime, UniqueStacks& aUniqueStacks);
80 private:
81 // Used to serialize a ProfilerBacktrace.
82 friend struct mozilla::ProfileBufferEntryWriter::Serializer<
83 ProfilerBacktrace>;
84 friend struct mozilla::ProfileBufferEntryReader::Deserializer<
85 ProfilerBacktrace>;
87 std::string mName;
89 // `ProfileChunkedBuffer` in which `mProfileBuffer` stores its data; must be
90 // located before `mProfileBuffer` so that it's destroyed after.
91 mozilla::UniquePtr<mozilla::ProfileChunkedBuffer>
92 mOptionalProfileChunkedBufferStorage;
93 // If null, there is no need to check mProfileBuffer's (if present) underlying
94 // buffer because this is done when constructed.
95 mozilla::ProfileChunkedBuffer* mProfileChunkedBuffer;
97 mozilla::UniquePtr<ProfileBuffer> mOptionalProfileBufferStorage;
98 ProfileBuffer* mProfileBuffer;
101 namespace mozilla {
103 // Format: [ UniquePtr<BlockRingsBuffer> | name ]
104 // Initial len==0 marks a nullptr or empty backtrace.
105 template <>
106 struct mozilla::ProfileBufferEntryWriter::Serializer<ProfilerBacktrace> {
107 static Length Bytes(const ProfilerBacktrace& aBacktrace) {
108 if (!aBacktrace.mProfileChunkedBuffer) {
109 // No buffer.
110 return ULEB128Size(0u);
112 auto bufferBytes = SumBytes(*aBacktrace.mProfileChunkedBuffer);
113 if (bufferBytes <= ULEB128Size(0u)) {
114 // Empty buffer.
115 return ULEB128Size(0u);
117 return bufferBytes + SumBytes(aBacktrace.mName);
120 static void Write(mozilla::ProfileBufferEntryWriter& aEW,
121 const ProfilerBacktrace& aBacktrace) {
122 if (!aBacktrace.mProfileChunkedBuffer ||
123 SumBytes(*aBacktrace.mProfileChunkedBuffer) <= ULEB128Size(0u)) {
124 // No buffer, or empty buffer.
125 aEW.WriteULEB128(0u);
126 return;
128 aEW.WriteObject(*aBacktrace.mProfileChunkedBuffer);
129 aEW.WriteObject(aBacktrace.mName);
133 template <typename Destructor>
134 struct mozilla::ProfileBufferEntryWriter::Serializer<
135 mozilla::UniquePtr<ProfilerBacktrace, Destructor>> {
136 static Length Bytes(
137 const mozilla::UniquePtr<ProfilerBacktrace, Destructor>& aBacktrace) {
138 if (!aBacktrace) {
139 // Null backtrace pointer (treated like an empty backtrace).
140 return ULEB128Size(0u);
142 return SumBytes(*aBacktrace);
145 static void Write(
146 mozilla::ProfileBufferEntryWriter& aEW,
147 const mozilla::UniquePtr<ProfilerBacktrace, Destructor>& aBacktrace) {
148 if (!aBacktrace) {
149 // Null backtrace pointer (treated like an empty backtrace).
150 aEW.WriteULEB128(0u);
151 return;
153 aEW.WriteObject(*aBacktrace);
157 template <typename Destructor>
158 struct mozilla::ProfileBufferEntryReader::Deserializer<
159 mozilla::UniquePtr<ProfilerBacktrace, Destructor>> {
160 static void ReadInto(
161 mozilla::ProfileBufferEntryReader& aER,
162 mozilla::UniquePtr<ProfilerBacktrace, Destructor>& aBacktrace) {
163 aBacktrace = Read(aER);
166 static mozilla::UniquePtr<ProfilerBacktrace, Destructor> Read(
167 mozilla::ProfileBufferEntryReader& aER) {
168 auto profileChunkedBuffer =
169 aER.ReadObject<UniquePtr<ProfileChunkedBuffer>>();
170 if (!profileChunkedBuffer) {
171 return nullptr;
173 MOZ_ASSERT(
174 !profileChunkedBuffer->IsThreadSafe(),
175 "ProfilerBacktrace only stores non-thread-safe ProfileChunkedBuffers");
176 std::string name = aER.ReadObject<std::string>();
177 return UniquePtr<ProfilerBacktrace, Destructor>{
178 new ProfilerBacktrace(name.c_str(), std::move(profileChunkedBuffer))};
182 } // namespace mozilla
184 #endif // __PROFILER_BACKTRACE_H