Bug 1658230 - Make BaseProfileJSONWriter.h header-only - r=gregtatum
authorGerald Squelart <gsquelart@mozilla.com>
Tue, 11 Aug 2020 03:49:00 +0000
changeset 544221 801e1d8c1de087a6188533292d073aa6dc112217
parent 544220 f2f72d4877cc4346e4c4749baceba46c7e87278c
child 544222 7ae81a4ff37e3e5720d358d0615eb8079a3f46cc
push id123900
push usergsquelart@mozilla.com
push dateTue, 11 Aug 2020 03:59:25 +0000
treeherderautoland@61871a38eb0f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgregtatum
bugs1658230
milestone81.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1658230 - Make BaseProfileJSONWriter.h header-only - r=gregtatum Because this header will be used across libraries (mozglue and xul), it is simpler and more efficient to make it fully self-contained instead of using MFBT_API. It may lead to slightly longer build times, but since it's only used inside the profilers, it won't impact other components. The compiler can better optimize it in context, and decide what to inline. Differential Revision: https://phabricator.services.mozilla.com/D86503
mozglue/baseprofiler/core/ProfileJSONWriter.cpp
mozglue/baseprofiler/moz.build
mozglue/baseprofiler/public/BaseProfileJSONWriter.h
deleted file mode 100644
--- a/mozglue/baseprofiler/core/ProfileJSONWriter.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "BaseProfileJSONWriter.h"
-
-#include "mozilla/HashFunctions.h"
-
-#include "BaseProfiler.h"
-
-namespace mozilla {
-namespace baseprofiler {
-
-void ChunkedJSONWriteFunc::Write(const char* aStr) {
-  size_t len = strlen(aStr);
-  Write(aStr, len);
-}
-
-void ChunkedJSONWriteFunc::Write(const char* aStr, size_t aLen) {
-  MOZ_ASSERT(mChunkPtr >= mChunkList.back().get() && mChunkPtr <= mChunkEnd);
-  MOZ_ASSERT(mChunkEnd >= mChunkList.back().get() + mChunkLengths.back());
-  MOZ_ASSERT(*mChunkPtr == '\0');
-
-  // Most strings to be written are small, but subprocess profiles (e.g.,
-  // from the content process in e10s) may be huge. If the string is larger
-  // than a chunk, allocate its own chunk.
-  char* newPtr;
-  if (aLen >= kChunkSize) {
-    AllocChunk(aLen + 1);
-    newPtr = mChunkPtr + aLen;
-  } else {
-    newPtr = mChunkPtr + aLen;
-    if (newPtr >= mChunkEnd) {
-      AllocChunk(kChunkSize);
-      newPtr = mChunkPtr + aLen;
-    }
-  }
-
-  memcpy(mChunkPtr, aStr, aLen);
-  *newPtr = '\0';
-  mChunkPtr = newPtr;
-  mChunkLengths.back() += aLen;
-}
-
-size_t ChunkedJSONWriteFunc::GetTotalLength() const {
-  MOZ_ASSERT(mChunkLengths.length() == mChunkList.length());
-  size_t totalLen = 1;
-  for (size_t i = 0; i < mChunkLengths.length(); i++) {
-    MOZ_ASSERT(strlen(mChunkList[i].get()) == mChunkLengths[i]);
-    totalLen += mChunkLengths[i];
-  }
-  return totalLen;
-}
-
-void ChunkedJSONWriteFunc::CopyDataIntoLazilyAllocatedBuffer(
-    const std::function<char*(size_t)>& aAllocator) const {
-  size_t totalLen = GetTotalLength();
-  char* ptr = aAllocator(totalLen);
-
-  if (!ptr) {
-    // Failed to allocate memory.
-    return;
-  }
-
-  for (size_t i = 0; i < mChunkList.length(); i++) {
-    size_t len = mChunkLengths[i];
-    memcpy(ptr, mChunkList[i].get(), len);
-    ptr += len;
-  }
-  *ptr = '\0';
-}
-
-UniquePtr<char[]> ChunkedJSONWriteFunc::CopyData() const {
-  UniquePtr<char[]> c;
-  CopyDataIntoLazilyAllocatedBuffer([&](size_t allocationSize) {
-    c = MakeUnique<char[]>(allocationSize);
-    return c.get();
-  });
-  return c;
-}
-
-void ChunkedJSONWriteFunc::Take(ChunkedJSONWriteFunc&& aOther) {
-  for (size_t i = 0; i < aOther.mChunkList.length(); i++) {
-    MOZ_ALWAYS_TRUE(mChunkLengths.append(aOther.mChunkLengths[i]));
-    MOZ_ALWAYS_TRUE(mChunkList.append(std::move(aOther.mChunkList[i])));
-  }
-  mChunkPtr = mChunkList.back().get() + mChunkLengths.back();
-  mChunkEnd = mChunkPtr;
-  aOther.mChunkPtr = nullptr;
-  aOther.mChunkEnd = nullptr;
-  aOther.mChunkList.clear();
-  aOther.mChunkLengths.clear();
-}
-
-void ChunkedJSONWriteFunc::AllocChunk(size_t aChunkSize) {
-  MOZ_ASSERT(mChunkLengths.length() == mChunkList.length());
-  UniquePtr<char[]> newChunk = MakeUnique<char[]>(aChunkSize);
-  mChunkPtr = newChunk.get();
-  mChunkEnd = mChunkPtr + aChunkSize;
-  *mChunkPtr = '\0';
-  MOZ_ALWAYS_TRUE(mChunkLengths.append(0));
-  MOZ_ALWAYS_TRUE(mChunkList.append(std::move(newChunk)));
-}
-
-void SpliceableJSONWriter::TakeAndSplice(ChunkedJSONWriteFunc* aFunc) {
-  Separator();
-  for (size_t i = 0; i < aFunc->mChunkList.length(); i++) {
-    WriteFunc()->Write(aFunc->mChunkList[i].get());
-  }
-  aFunc->mChunkPtr = nullptr;
-  aFunc->mChunkEnd = nullptr;
-  aFunc->mChunkList.clear();
-  aFunc->mChunkLengths.clear();
-  mNeedComma[mDepth] = true;
-}
-
-void SpliceableJSONWriter::Splice(const char* aStr) {
-  Separator();
-  WriteFunc()->Write(aStr);
-  mNeedComma[mDepth] = true;
-}
-
-void SpliceableChunkedJSONWriter::TakeAndSplice(ChunkedJSONWriteFunc* aFunc) {
-  Separator();
-  WriteFunc()->Take(std::move(*aFunc));
-  mNeedComma[mDepth] = true;
-}
-
-}  // namespace baseprofiler
-}  // namespace mozilla
--- a/mozglue/baseprofiler/moz.build
+++ b/mozglue/baseprofiler/moz.build
@@ -20,17 +20,16 @@ if CONFIG['MOZ_GECKO_PROFILER']:
         'public/ProfilingCategoryList.h',
     ]
     UNIFIED_SOURCES += [
         'core/PageInformation.cpp',
         'core/platform.cpp',
         'core/ProfileBuffer.cpp',
         'core/ProfileBufferEntry.cpp',
         'core/ProfiledThreadData.cpp',
-        'core/ProfileJSONWriter.cpp',
         'core/ProfilerBacktrace.cpp',
         'core/ProfilerMarkerPayload.cpp',
         'core/ProfilingCategory.cpp',
         'core/ProfilingStack.cpp',
         'core/RegisteredThread.cpp',
     ]
 
     if CONFIG['OS_TARGET'] in ('Android', 'Linux', 'FreeBSD'):
--- a/mozglue/baseprofiler/public/BaseProfileJSONWriter.h
+++ b/mozglue/baseprofiler/public/BaseProfileJSONWriter.h
@@ -38,28 +38,104 @@ class ChunkedJSONWriteFunc : public JSON
   }
 
   bool IsEmpty() const {
     MOZ_ASSERT_IF(!mChunkPtr, !mChunkEnd && mChunkList.length() == 0 &&
                                   mChunkLengths.length() == 0);
     return !mChunkPtr;
   }
 
-  void Write(const char* aStr) override;
-  void Write(const char* aStr, size_t aLen) override;
+  void Write(const char* aStr) override {
+    size_t len = strlen(aStr);
+    Write(aStr, len);
+  }
+  void Write(const char* aStr, size_t aLen) override {
+    MOZ_ASSERT(mChunkPtr >= mChunkList.back().get() && mChunkPtr <= mChunkEnd);
+    MOZ_ASSERT(mChunkEnd >= mChunkList.back().get() + mChunkLengths.back());
+    MOZ_ASSERT(*mChunkPtr == '\0');
+
+    // Most strings to be written are small, but subprocess profiles (e.g.,
+    // from the content process in e10s) may be huge. If the string is larger
+    // than a chunk, allocate its own chunk.
+    char* newPtr;
+    if (aLen >= kChunkSize) {
+      AllocChunk(aLen + 1);
+      newPtr = mChunkPtr + aLen;
+    } else {
+      newPtr = mChunkPtr + aLen;
+      if (newPtr >= mChunkEnd) {
+        AllocChunk(kChunkSize);
+        newPtr = mChunkPtr + aLen;
+      }
+    }
+
+    memcpy(mChunkPtr, aStr, aLen);
+    *newPtr = '\0';
+    mChunkPtr = newPtr;
+    mChunkLengths.back() += aLen;
+  }
   void CopyDataIntoLazilyAllocatedBuffer(
-      const std::function<char*(size_t)>& aAllocator) const;
-  UniquePtr<char[]> CopyData() const;
-  void Take(ChunkedJSONWriteFunc&& aOther);
+      const std::function<char*(size_t)>& aAllocator) const {
+    size_t totalLen = GetTotalLength();
+    char* ptr = aAllocator(totalLen);
+
+    if (!ptr) {
+      // Failed to allocate memory.
+      return;
+    }
+
+    for (size_t i = 0; i < mChunkList.length(); i++) {
+      size_t len = mChunkLengths[i];
+      memcpy(ptr, mChunkList[i].get(), len);
+      ptr += len;
+    }
+    *ptr = '\0';
+  }
+  UniquePtr<char[]> CopyData() const {
+    UniquePtr<char[]> c;
+    CopyDataIntoLazilyAllocatedBuffer([&](size_t allocationSize) {
+      c = MakeUnique<char[]>(allocationSize);
+      return c.get();
+    });
+    return c;
+  }
+  void Take(ChunkedJSONWriteFunc&& aOther) {
+    for (size_t i = 0; i < aOther.mChunkList.length(); i++) {
+      MOZ_ALWAYS_TRUE(mChunkLengths.append(aOther.mChunkLengths[i]));
+      MOZ_ALWAYS_TRUE(mChunkList.append(std::move(aOther.mChunkList[i])));
+    }
+    mChunkPtr = mChunkList.back().get() + mChunkLengths.back();
+    mChunkEnd = mChunkPtr;
+    aOther.mChunkPtr = nullptr;
+    aOther.mChunkEnd = nullptr;
+    aOther.mChunkList.clear();
+    aOther.mChunkLengths.clear();
+  }
   // Returns the byte length of the complete combined string, including the
   // null terminator byte.
-  size_t GetTotalLength() const;
+  size_t GetTotalLength() const {
+    MOZ_ASSERT(mChunkLengths.length() == mChunkList.length());
+    size_t totalLen = 1;
+    for (size_t i = 0; i < mChunkLengths.length(); i++) {
+      MOZ_ASSERT(strlen(mChunkList[i].get()) == mChunkLengths[i]);
+      totalLen += mChunkLengths[i];
+    }
+    return totalLen;
+  }
 
  private:
-  void AllocChunk(size_t aChunkSize);
+  void AllocChunk(size_t aChunkSize) {
+    MOZ_ASSERT(mChunkLengths.length() == mChunkList.length());
+    UniquePtr<char[]> newChunk = MakeUnique<char[]>(aChunkSize);
+    mChunkPtr = newChunk.get();
+    mChunkEnd = mChunkPtr + aChunkSize;
+    *mChunkPtr = '\0';
+    MOZ_ALWAYS_TRUE(mChunkLengths.append(0));
+    MOZ_ALWAYS_TRUE(mChunkList.append(std::move(newChunk)));
+  }
 
   static const size_t kChunkSize = 4096 * 512;
 
   // Pointer for writing inside the current chunk.
   //
   // The current chunk is always at the back of mChunkList, i.e.,
   // mChunkList.back() <= mChunkPtr <= mChunkEnd.
   char* mChunkPtr;
@@ -99,42 +175,59 @@ class SpliceableJSONWriter : public JSON
   void EndBareList() { EndCollection(""); }
 
   void NullElements(uint32_t aCount) {
     for (uint32_t i = 0; i < aCount; i++) {
       NullElement();
     }
   }
 
-  void Splice(const ChunkedJSONWriteFunc* aFunc);
-  void Splice(const char* aStr);
+  void Splice(const char* aStr) {
+    Separator();
+    WriteFunc()->Write(aStr);
+    mNeedComma[mDepth] = true;
+  }
 
   // Splice the given JSON directly in, without quoting.
   void SplicedJSONProperty(const char* aMaybePropertyName,
                            const char* aJsonValue) {
     Scalar(aMaybePropertyName, aJsonValue);
   }
 
   // Takes the chunks from aFunc and write them. If move is not possible
   // (e.g., using OStreamJSONWriteFunc), aFunc's chunks are copied and its
   // storage cleared.
-  virtual void TakeAndSplice(ChunkedJSONWriteFunc* aFunc);
+  virtual void TakeAndSplice(ChunkedJSONWriteFunc* aFunc) {
+    Separator();
+    for (size_t i = 0; i < aFunc->mChunkList.length(); i++) {
+      WriteFunc()->Write(aFunc->mChunkList[i].get());
+    }
+    aFunc->mChunkPtr = nullptr;
+    aFunc->mChunkEnd = nullptr;
+    aFunc->mChunkList.clear();
+    aFunc->mChunkLengths.clear();
+    mNeedComma[mDepth] = true;
+  }
 };
 
 class SpliceableChunkedJSONWriter : public SpliceableJSONWriter {
  public:
   explicit SpliceableChunkedJSONWriter()
       : SpliceableJSONWriter(MakeUnique<ChunkedJSONWriteFunc>()) {}
 
   ChunkedJSONWriteFunc* WriteFunc() const {
     return static_cast<ChunkedJSONWriteFunc*>(JSONWriter::WriteFunc());
   }
 
   // Adopts the chunks from aFunc without copying.
-  virtual void TakeAndSplice(ChunkedJSONWriteFunc* aFunc) override;
+  virtual void TakeAndSplice(ChunkedJSONWriteFunc* aFunc) override {
+    Separator();
+    WriteFunc()->Take(std::move(*aFunc));
+    mNeedComma[mDepth] = true;
+  }
 };
 
 class JSONSchemaWriter {
   JSONWriter& mWriter;
   uint32_t mIndex;
 
  public:
   explicit JSONSchemaWriter(JSONWriter& aWriter) : mWriter(aWriter), mIndex(0) {