tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ProfilerBacktrace.h (5896B)


      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/. */
      6 
      7 #ifndef __PROFILER_BACKTRACE_H
      8 #define __PROFILER_BACKTRACE_H
      9 
     10 #include "mozilla/ProfileChunkedBuffer.h"
     11 #include "mozilla/UniquePtr.h"
     12 
     13 #include <string>
     14 
     15 namespace mozilla {
     16 
     17 class TimeStamp;
     18 
     19 namespace baseprofiler {
     20 
     21 class ProfileBuffer;
     22 class SpliceableJSONWriter;
     23 class ThreadInfo;
     24 class UniqueStacks;
     25 
     26 // ProfilerBacktrace encapsulates a synchronous sample.
     27 // It can work with a ProfileBuffer and/or a ProfileChunkedBuffer (if both, they
     28 // must already be linked together). The ProfileChunkedBuffer contains all the
     29 // data; the ProfileBuffer is not strictly needed, only provide it if it is
     30 // already available at the call site.
     31 // And these buffers can either be:
     32 // - owned here, so that the ProfilerBacktrace object can be kept for later
     33 //   use), OR
     34 // - referenced through pointers (in cases where the backtrace is immediately
     35 //   streamed out, so we only need temporary references to external buffers);
     36 //   these pointers may be null for empty backtraces.
     37 class ProfilerBacktrace {
     38 public:
     39  // Take ownership of external buffers and use them to keep, and to stream a
     40  // backtrace. If a ProfileBuffer is given, its underlying chunked buffer must
     41  // be provided as well.
     42  explicit ProfilerBacktrace(
     43      const char* aName,
     44      UniquePtr<ProfileChunkedBuffer> aProfileChunkedBufferStorage,
     45      UniquePtr<ProfileBuffer> aProfileBufferStorageOrNull = nullptr);
     46 
     47  // Take pointers to external buffers and use them to stream a backtrace.
     48  // If null, the backtrace is effectively empty.
     49  // If both are provided, they must already be connected.
     50  explicit ProfilerBacktrace(
     51      const char* aName,
     52      ProfileChunkedBuffer* aExternalProfileChunkedBufferOrNull = nullptr,
     53      ProfileBuffer* aExternalProfileBufferOrNull = nullptr);
     54 
     55  ~ProfilerBacktrace();
     56 
     57  [[nodiscard]] bool IsEmpty() const {
     58    return !mProfileChunkedBuffer ||
     59           ProfileBufferEntryWriter::Serializer<ProfileChunkedBuffer>::Bytes(
     60               *mProfileChunkedBuffer) <= ULEB128Size(0u);
     61  }
     62 
     63  // ProfilerBacktraces' stacks are deduplicated in the context of the
     64  // profile that contains the backtrace as a marker payload.
     65  //
     66  // That is, markers that contain backtraces should not need their own stack,
     67  // frame, and string tables. They should instead reuse their parent
     68  // profile's tables.
     69  BaseProfilerThreadId StreamJSON(SpliceableJSONWriter& aWriter,
     70                                  const TimeStamp& aProcessStartTime,
     71                                  UniqueStacks& aUniqueStacks);
     72 
     73 private:
     74  // Used to de/serialize a ProfilerBacktrace.
     75  friend ProfileBufferEntryWriter::Serializer<ProfilerBacktrace>;
     76  friend ProfileBufferEntryReader::Deserializer<ProfilerBacktrace>;
     77 
     78  std::string mName;
     79 
     80  // `ProfileChunkedBuffer` in which `mProfileBuffer` stores its data; must be
     81  // located before `mProfileBuffer` so that it's destroyed after.
     82  UniquePtr<ProfileChunkedBuffer> mOptionalProfileChunkedBufferStorage;
     83  // If null, there is no need to check mProfileBuffer's (if present) underlying
     84  // buffer because this is done when constructed.
     85  ProfileChunkedBuffer* mProfileChunkedBuffer;
     86 
     87  UniquePtr<ProfileBuffer> mOptionalProfileBufferStorage;
     88  ProfileBuffer* mProfileBuffer;
     89 };
     90 
     91 }  // namespace baseprofiler
     92 
     93 // Format: [ UniquePtr<BlockRingsBuffer> | name ]
     94 // Initial len==0 marks a nullptr or empty backtrace.
     95 template <>
     96 struct ProfileBufferEntryWriter::Serializer<baseprofiler::ProfilerBacktrace> {
     97  static Length Bytes(const baseprofiler::ProfilerBacktrace& aBacktrace) {
     98    if (!aBacktrace.mProfileChunkedBuffer) {
     99      // No buffer.
    100      return ULEB128Size(0u);
    101    }
    102    auto bufferBytes = SumBytes(*aBacktrace.mProfileChunkedBuffer);
    103    if (bufferBytes <= ULEB128Size(0u)) {
    104      // Empty buffer.
    105      return ULEB128Size(0u);
    106    }
    107    return bufferBytes + SumBytes(aBacktrace.mName);
    108  }
    109 
    110  static void Write(ProfileBufferEntryWriter& aEW,
    111                    const baseprofiler::ProfilerBacktrace& aBacktrace) {
    112    if (!aBacktrace.mProfileChunkedBuffer ||
    113        SumBytes(*aBacktrace.mProfileChunkedBuffer) <= ULEB128Size(0u)) {
    114      // No buffer, or empty buffer.
    115      aEW.WriteULEB128(0u);
    116      return;
    117    }
    118    aEW.WriteObject(*aBacktrace.mProfileChunkedBuffer);
    119    aEW.WriteObject(aBacktrace.mName);
    120  }
    121 };
    122 
    123 template <typename Destructor>
    124 struct ProfileBufferEntryWriter::Serializer<
    125    UniquePtr<baseprofiler::ProfilerBacktrace, Destructor>> {
    126  static Length Bytes(const UniquePtr<baseprofiler::ProfilerBacktrace,
    127                                      Destructor>& aBacktrace) {
    128    if (!aBacktrace) {
    129      // Null backtrace pointer (treated like an empty backtrace).
    130      return ULEB128Size(0u);
    131    }
    132    return SumBytes(*aBacktrace);
    133  }
    134 
    135  static void Write(ProfileBufferEntryWriter& aEW,
    136                    const UniquePtr<baseprofiler::ProfilerBacktrace,
    137                                    Destructor>& aBacktrace) {
    138    if (!aBacktrace) {
    139      // Null backtrace pointer (treated like an empty backtrace).
    140      aEW.WriteULEB128(0u);
    141      return;
    142    }
    143    aEW.WriteObject(*aBacktrace);
    144  }
    145 };
    146 
    147 template <typename Destructor>
    148 struct ProfileBufferEntryReader::Deserializer<
    149    UniquePtr<baseprofiler::ProfilerBacktrace, Destructor>> {
    150  static void ReadInto(
    151      ProfileBufferEntryReader& aER,
    152      UniquePtr<baseprofiler::ProfilerBacktrace, Destructor>& aBacktrace) {
    153    aBacktrace = Read(aER);
    154  }
    155 
    156  static UniquePtr<baseprofiler::ProfilerBacktrace, Destructor> Read(
    157      ProfileBufferEntryReader& aER);
    158 };
    159 
    160 }  // namespace mozilla
    161 
    162 #endif  // __PROFILER_BACKTRACE_H