Bug 1658230 - Deduplicate ProfileJSONWriter classes - r=gregtatum
authorGerald Squelart <gsquelart@mozilla.com>
Tue, 11 Aug 2020 03:50:54 +0000
changeset 544205 7ae81a4ff37e3e5720d358d0615eb8079a3f46cc
parent 544204 801e1d8c1de087a6188533292d073aa6dc112217
child 544206 61871a38eb0ff8d9ebdc28db10f03e74e01912a3
push id37689
push userncsoregi@mozilla.com
push dateTue, 11 Aug 2020 09:17:31 +0000
treeherdermozilla-central@3fa98e681edd [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 - Deduplicate ProfileJSONWriter classes - r=gregtatum The main change is removing ProfileJSONWriter.cpp, making ProfileJSONWriter.h point at BaseProfileJSONWriter.h, and exposing `mozilla::baseprofiler::` classes in the top namespace as expected by users of ProfileJSONWriter.h (to minimize changes). These two headers are now always present in the "mozilla" include directory, independent of MOZ_GECKO_PROFILER settings. The rest is just needed tweaks to match the above changes. Differential Revision: https://phabricator.services.mozilla.com/D86504
gfx/layers/ipc/CompositorBridgeParent.cpp
gfx/layers/ipc/ContentCompositorBridgeParent.cpp
gfx/layers/wr/WebRenderBridgeParent.cpp
mozglue/baseprofiler/core/PageInformation.cpp
mozglue/baseprofiler/core/ProfileBufferEntry.h
mozglue/baseprofiler/core/ProfiledThreadData.cpp
mozglue/baseprofiler/core/ProfilerBacktrace.cpp
mozglue/baseprofiler/core/ProfilerMarkerPayload.cpp
mozglue/baseprofiler/moz.build
mozglue/tests/TestBaseProfiler.cpp
tools/profiler/core/PageInformation.cpp
tools/profiler/core/PageInformation.h
tools/profiler/core/ProfileBufferEntry.h
tools/profiler/core/ProfileJSONWriter.cpp
tools/profiler/core/ProfiledThreadData.cpp
tools/profiler/core/ProfilerBacktrace.cpp
tools/profiler/core/ProfilerBacktrace.h
tools/profiler/core/ProfilerMarkerPayload.cpp
tools/profiler/gecko/nsProfiler.h
tools/profiler/moz.build
tools/profiler/public/GeckoProfiler.h
tools/profiler/public/ProfileJSONWriter.h
tools/profiler/public/ProfilerMarkerPayload.h
tools/profiler/tests/gtest/GeckoProfiler.cpp
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -2776,17 +2776,17 @@ int32_t RecordContentFrameTime(
           const override {
         return CommonPropsTagAndSerializationBytes();
       }
       void SerializeTagAndPayload(
           mozilla::ProfileBufferEntryWriter& aEntryWriter) const override {
         static const DeserializerTag tag = TagForDeserializer(Deserialize);
         SerializeTagAndCommonProps(tag, aEntryWriter);
       }
-      void StreamPayload(SpliceableJSONWriter& aWriter,
+      void StreamPayload(mozilla::baseprofiler::SpliceableJSONWriter& aWriter,
                          const TimeStamp& aProcessStartTime,
                          UniqueStacks& aUniqueStacks) const override {
         StreamCommonProps("CONTENT_FRAME_TIME", aWriter, aProcessStartTime,
                           aUniqueStacks);
       }
 
      private:
       explicit ContentFramePayload(CommonProps&& aCommonProps)
--- a/gfx/layers/ipc/ContentCompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/ContentCompositorBridgeParent.cpp
@@ -380,17 +380,17 @@ void ContentCompositorBridgeParent::Shad
           const override {
         return CommonPropsTagAndSerializationBytes();
       }
       void SerializeTagAndPayload(
           mozilla::ProfileBufferEntryWriter& aEntryWriter) const override {
         static const DeserializerTag tag = TagForDeserializer(Deserialize);
         SerializeTagAndCommonProps(tag, aEntryWriter);
       }
-      void StreamPayload(SpliceableJSONWriter& aWriter,
+      void StreamPayload(mozilla::baseprofiler::SpliceableJSONWriter& aWriter,
                          const TimeStamp& aProcessStartTime,
                          UniqueStacks& aUniqueStacks) const override {
         StreamCommonProps("CONTENT_FULL_PAINT_TIME", aWriter, aProcessStartTime,
                           aUniqueStacks);
       }
 
      private:
       explicit ContentBuildPayload(CommonProps&& aCommonProps)
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -234,19 +234,20 @@ class SceneBuiltNotification : public wr
                 return CommonPropsTagAndSerializationBytes();
               }
               void SerializeTagAndPayload(mozilla::ProfileBufferEntryWriter&
                                               aEntryWriter) const override {
                 static const DeserializerTag tag =
                     TagForDeserializer(Deserialize);
                 SerializeTagAndCommonProps(tag, aEntryWriter);
               }
-              void StreamPayload(SpliceableJSONWriter& aWriter,
-                                 const TimeStamp& aProcessStartTime,
-                                 UniqueStacks& aUniqueStacks) const override {
+              void StreamPayload(
+                  mozilla::baseprofiler::SpliceableJSONWriter& aWriter,
+                  const TimeStamp& aProcessStartTime,
+                  UniqueStacks& aUniqueStacks) const override {
                 StreamCommonProps("CONTENT_FULL_PAINT_TIME", aWriter,
                                   aProcessStartTime, aUniqueStacks);
               }
 
              private:
               explicit ContentFullPaintPayload(CommonProps&& aCommonProps)
                   : ProfilerMarkerPayload(std::move(aCommonProps)) {}
               static mozilla::UniquePtr<ProfilerMarkerPayload> Deserialize(
--- a/mozglue/baseprofiler/core/PageInformation.cpp
+++ b/mozglue/baseprofiler/core/PageInformation.cpp
@@ -2,17 +2,18 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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 "PageInformation.h"
 
 #include "BaseProfiler.h"
-#include "BaseProfileJSONWriter.h"
+
+#include "mozilla/BaseProfileJSONWriter.h"
 
 namespace mozilla {
 namespace baseprofiler {
 
 PageInformation::PageInformation(uint64_t aBrowsingContextID,
                                  uint64_t aInnerWindowID,
                                  const std::string& aUrl,
                                  uint64_t aEmbedderInnerWindowID)
--- a/mozglue/baseprofiler/core/ProfileBufferEntry.h
+++ b/mozglue/baseprofiler/core/ProfileBufferEntry.h
@@ -2,20 +2,19 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
 
 #ifndef ProfileBufferEntry_h
 #define ProfileBufferEntry_h
 
-#include "BaseProfileJSONWriter.h"
-
+#include "BaseProfilingCategory.h"
 #include "gtest/MozGtestFriend.h"
-#include "BaseProfilingCategory.h"
+#include "mozilla/BaseProfileJSONWriter.h"
 #include "mozilla/HashFunctions.h"
 #include "mozilla/HashTable.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/Variant.h"
 #include "mozilla/Vector.h"
 
 #include <string>
--- a/mozglue/baseprofiler/core/ProfiledThreadData.cpp
+++ b/mozglue/baseprofiler/core/ProfiledThreadData.cpp
@@ -3,17 +3,18 @@
 /* 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 "ProfiledThreadData.h"
 
 #include "BaseProfiler.h"
 #include "ProfileBuffer.h"
-#include "BaseProfileJSONWriter.h"
+
+#include "mozilla/BaseProfileJSONWriter.h"
 
 #if defined(GP_OS_darwin)
 #  include <pthread.h>
 #endif
 
 namespace mozilla {
 namespace baseprofiler {
 
--- a/mozglue/baseprofiler/core/ProfilerBacktrace.cpp
+++ b/mozglue/baseprofiler/core/ProfilerBacktrace.cpp
@@ -2,21 +2,22 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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 "ProfilerBacktrace.h"
 
 #include "BaseProfiler.h"
-#include "BaseProfileJSONWriter.h"
 #include "ProfileBuffer.h"
 #include "ProfiledThreadData.h"
 #include "ThreadInfo.h"
 
+#include "mozilla/BaseProfileJSONWriter.h"
+
 namespace mozilla {
 namespace baseprofiler {
 
 ProfilerBacktrace::ProfilerBacktrace(
     const char* aName, int aThreadId,
     UniquePtr<ProfileChunkedBuffer> aProfileChunkedBuffer,
     UniquePtr<ProfileBuffer> aProfileBuffer)
     : mName(strdup(aName)),
--- a/mozglue/baseprofiler/core/ProfilerMarkerPayload.cpp
+++ b/mozglue/baseprofiler/core/ProfilerMarkerPayload.cpp
@@ -1,24 +1,24 @@
 /* -*- 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 "BaseProfilerMarkerPayload.h"
 
-#include <inttypes.h>
+#include "BaseProfiler.h"
+#include "ProfileBufferEntry.h"
+#include "ProfilerBacktrace.h"
 
+#include "mozilla/BaseProfileJSONWriter.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/Sprintf.h"
 
-#include "BaseProfiler.h"
-#include "BaseProfileJSONWriter.h"
-#include "ProfileBufferEntry.h"
-#include "ProfilerBacktrace.h"
+#include <inttypes.h>
 
 namespace mozilla {
 namespace baseprofiler {
 
 static UniquePtr<ProfilerMarkerPayload> DeserializeNothing(
     mozilla::ProfileBufferEntryReader&) {
   return nullptr;
 }
--- a/mozglue/baseprofiler/moz.build
+++ b/mozglue/baseprofiler/moz.build
@@ -7,17 +7,16 @@
 # This is pretty much a copy from tools/profiler, cut down to exclude anything
 # that cannot work in mozglue (because they are totally dependent on libxul-
 # specific code).
 # All exported headers now prefixed with "Base" to avoid #include name clashes.
 
 if CONFIG['MOZ_GECKO_PROFILER']:
     DEFINES['IMPL_MFBT'] = True
     EXPORTS += [
-        'public/BaseProfileJSONWriter.h',
         'public/BaseProfilerMarkerPayload.h',
         'public/BaseProfilerSharedLibraries.h',
         'public/BaseProfilingCategory.h',
         'public/BaseProfilingStack.h',
         'public/ProfilingCategoryList.h',
     ]
     UNIFIED_SOURCES += [
         'core/PageInformation.cpp',
@@ -75,16 +74,17 @@ if CONFIG['MOZ_GECKO_PROFILER']:
 # builds.
 # BaseProfiler.h and BaseProfilerCounts.h only contain no-op macros in that
 # case.
 EXPORTS += [
     'public/BaseProfiler.h',
 ]
 
 EXPORTS.mozilla += [
+    'public/BaseProfileJSONWriter.h',
     'public/BaseProfilerCounts.h',
     'public/BaseProfilerDetail.h',
     'public/BlocksRingBuffer.h',
     'public/leb128iterator.h',
     'public/ModuloBuffer.h',
     'public/PowerOfTwo.h',
     'public/ProfileBufferChunk.h',
     'public/ProfileBufferChunkManager.h',
--- a/mozglue/tests/TestBaseProfiler.cpp
+++ b/mozglue/tests/TestBaseProfiler.cpp
@@ -2,19 +2,19 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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 "BaseProfiler.h"
 
 #include "mozilla/Attributes.h"
+#include "mozilla/BaseProfileJSONWriter.h"
 
 #ifdef MOZ_GECKO_PROFILER
-#  include "BaseProfileJSONWriter.h"
 #  include "BaseProfilerMarkerPayload.h"
 #  include "mozilla/BlocksRingBuffer.h"
 #  include "mozilla/leb128iterator.h"
 #  include "mozilla/ModuloBuffer.h"
 #  include "mozilla/PowerOfTwo.h"
 #  include "mozilla/ProfileBufferChunk.h"
 #  include "mozilla/ProfileBufferChunkManagerSingle.h"
 #  include "mozilla/ProfileBufferChunkManagerWithLocalLimit.h"
--- a/tools/profiler/core/PageInformation.cpp
+++ b/tools/profiler/core/PageInformation.cpp
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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 "PageInformation.h"
 
-#include "ProfileJSONWriter.h"
+#include "mozilla/ProfileJSONWriter.h"
 
 PageInformation::PageInformation(uint64_t aBrowsingContextID,
                                  uint64_t aInnerWindowID, const nsCString& aUrl,
                                  uint64_t aEmbedderInnerWindowID)
     : mBrowsingContextID(aBrowsingContextID),
       mInnerWindowID(aInnerWindowID),
       mUrl(aUrl),
       mEmbedderInnerWindowID(aEmbedderInnerWindowID) {}
--- a/tools/profiler/core/PageInformation.h
+++ b/tools/profiler/core/PageInformation.h
@@ -7,34 +7,38 @@
 #ifndef PageInformation_h
 #define PageInformation_h
 
 #include "mozilla/Maybe.h"
 #include "mozilla/MemoryReporting.h"
 #include "nsISupportsImpl.h"
 #include "nsString.h"
 
+namespace mozilla {
+namespace baseprofiler {
 class SpliceableJSONWriter;
+}  // namespace baseprofiler
+}  // namespace mozilla
 
 // This class contains information that's relevant to a single page only
 // while the page information is important and registered with the profiler,
 // but regardless of whether the profiler is running. All accesses to it are
 // protected by the profiler state lock.
 // When the page gets unregistered, we keep the profiler buffer position
 // to determine if we are still using this page. If not, we unregister
 // it in the next page registration.
 class PageInformation final {
  public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PageInformation)
   PageInformation(uint64_t aBrowsingContextID, uint64_t aInnerWindowID,
                   const nsCString& aUrl, uint64_t aEmbedderInnerWindowID);
 
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
   bool Equals(PageInformation* aOtherPageInfo) const;
-  void StreamJSON(SpliceableJSONWriter& aWriter) const;
+  void StreamJSON(mozilla::baseprofiler::SpliceableJSONWriter& aWriter) const;
 
   uint64_t InnerWindowID() const { return mInnerWindowID; }
   uint64_t BrowsingContextID() const { return mBrowsingContextID; }
   const nsCString& Url() const { return mUrl; }
   uint64_t EmbedderInnerWindowID() const { return mEmbedderInnerWindowID; }
 
   mozilla::Maybe<uint64_t> BufferPositionWhenUnregistered() const {
     return mBufferPositionWhenUnregistered;
--- a/tools/profiler/core/ProfileBufferEntry.h
+++ b/tools/profiler/core/ProfileBufferEntry.h
@@ -2,24 +2,23 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
 
 #ifndef ProfileBufferEntry_h
 #define ProfileBufferEntry_h
 
-#include "ProfileJSONWriter.h"
-
 #include "gtest/MozGtestFriend.h"
 #include "js/ProfilingCategory.h"
 #include "js/ProfilingFrameIterator.h"
 #include "mozilla/HashFunctions.h"
 #include "mozilla/HashTable.h"
 #include "mozilla/Maybe.h"
+#include "mozilla/ProfileJSONWriter.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/Variant.h"
 #include "mozilla/Vector.h"
 #include "nsString.h"
 
 class ProfilerCodeAddressService;
 
 // NOTE!  If you add entries, you need to verify if they need to be added to the
deleted file mode 100644
--- a/tools/profiler/core/ProfileJSONWriter.cpp
+++ /dev/null
@@ -1,123 +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 "ProfileJSONWriter.h"
-
-#include "mozilla/HashFunctions.h"
-
-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';
-}
-
-mozilla::UniquePtr<char[]> ChunkedJSONWriteFunc::CopyData() const {
-  mozilla::UniquePtr<char[]> c;
-  CopyDataIntoLazilyAllocatedBuffer([&](size_t allocationSize) {
-    c = mozilla::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());
-  mozilla::UniquePtr<char[]> newChunk = mozilla::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;
-}
--- a/tools/profiler/core/ProfiledThreadData.cpp
+++ b/tools/profiler/core/ProfiledThreadData.cpp
@@ -2,20 +2,20 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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 "ProfiledThreadData.h"
 
 #include "ProfileBuffer.h"
-#include "ProfileJSONWriter.h"
 
 #include "js/TraceLoggerAPI.h"
 #include "mozilla/dom/ContentChild.h"
+#include "mozilla/ProfileJSONWriter.h"
 
 #if defined(GP_OS_darwin)
 #  include <pthread.h>
 #endif
 
 ProfiledThreadData::ProfiledThreadData(ThreadInfo* aThreadInfo,
                                        nsIEventTarget* aEventTarget)
     : mThreadInfo(aThreadInfo) {
--- a/tools/profiler/core/ProfilerBacktrace.cpp
+++ b/tools/profiler/core/ProfilerBacktrace.cpp
@@ -3,19 +3,20 @@
 /* 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 "ProfilerBacktrace.h"
 
 #include "ProfileBuffer.h"
 #include "ProfiledThreadData.h"
-#include "ProfileJSONWriter.h"
 #include "ThreadInfo.h"
 
+#include "mozilla/ProfileJSONWriter.h"
+
 ProfilerBacktrace::ProfilerBacktrace(
     const char* aName, int aThreadId,
     mozilla::UniquePtr<mozilla::ProfileChunkedBuffer> aProfileChunkedBuffer,
     mozilla::UniquePtr<ProfileBuffer> aProfileBuffer)
     : mName(strdup(aName)),
       mThreadId(aThreadId),
       mProfileChunkedBuffer(std::move(aProfileChunkedBuffer)),
       mProfileBuffer(std::move(aProfileBuffer)) {
--- a/tools/profiler/core/ProfilerBacktrace.h
+++ b/tools/profiler/core/ProfilerBacktrace.h
@@ -9,23 +9,25 @@
 
 #include "ProfileBuffer.h"
 
 #include "mozilla/ProfileBufferEntrySerialization.h"
 #include "mozilla/UniquePtrExtensions.h"
 
 class ProfileBuffer;
 class ProfilerCodeAddressService;
-class SpliceableJSONWriter;
 class ThreadInfo;
 class UniqueStacks;
 
 namespace mozilla {
 class ProfileChunkedBuffer;
 class TimeStamp;
+namespace baseprofiler {
+class SpliceableJSONWriter;
+}  // namespace baseprofiler
 }  // namespace mozilla
 
 // ProfilerBacktrace encapsulates a synchronous sample.
 class ProfilerBacktrace {
  public:
   ProfilerBacktrace(
       const char* aName, int aThreadId,
       mozilla::UniquePtr<mozilla::ProfileChunkedBuffer> aProfileChunkedBuffer,
@@ -33,17 +35,17 @@ class ProfilerBacktrace {
   ~ProfilerBacktrace();
 
   // ProfilerBacktraces' stacks are deduplicated in the context of the
   // profile that contains the backtrace as a marker payload.
   //
   // That is, markers that contain backtraces should not need their own stack,
   // frame, and string tables. They should instead reuse their parent
   // profile's tables.
-  void StreamJSON(SpliceableJSONWriter& aWriter,
+  void StreamJSON(mozilla::baseprofiler::SpliceableJSONWriter& aWriter,
                   const mozilla::TimeStamp& aProcessStartTime,
                   UniqueStacks& aUniqueStacks);
 
  private:
   // Used to serialize a ProfilerBacktrace.
   friend struct mozilla::ProfileBufferEntryWriter::Serializer<
       ProfilerBacktrace>;
   friend struct mozilla::ProfileBufferEntryReader::Deserializer<
--- a/tools/profiler/core/ProfilerMarkerPayload.cpp
+++ b/tools/profiler/core/ProfilerMarkerPayload.cpp
@@ -2,25 +2,25 @@
 /* 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 "ProfilerMarkerPayload.h"
 
 #include "GeckoProfiler.h"
 #include "ProfileBufferEntry.h"
-#include "ProfileJSONWriter.h"
 #include "ProfilerBacktrace.h"
 
 #include "gfxASurface.h"
 #include "Layers.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/net/HttpBaseChannel.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/ProfileBufferEntrySerializationGeckoExtensions.h"
+#include "mozilla/ProfileJSONWriter.h"
 #include "mozilla/Sprintf.h"
 
 #include <inttypes.h>
 
 using namespace mozilla;
 
 static UniquePtr<ProfilerMarkerPayload> DeserializeNothing(
     ProfileBufferEntryReader&) {
--- a/tools/profiler/gecko/nsProfiler.h
+++ b/tools/profiler/gecko/nsProfiler.h
@@ -5,23 +5,23 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsProfiler_h
 #define nsProfiler_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/MozPromise.h"
+#include "mozilla/ProfileJSONWriter.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/Vector.h"
 #include "nsIObserver.h"
 #include "nsIProfiler.h"
 #include "nsITimer.h"
 #include "nsServiceManagerUtils.h"
-#include "ProfileJSONWriter.h"
 #include "ProfilerCodeAddressService.h"
 
 class nsProfiler final : public nsIProfiler, public nsIObserver {
  public:
   nsProfiler();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
--- a/tools/profiler/moz.build
+++ b/tools/profiler/moz.build
@@ -8,30 +8,28 @@ if CONFIG['MOZ_GECKO_PROFILER']:
     DEFINES['MOZ_REPLACE_MALLOC_PREFIX'] = 'profiler'
     XPIDL_MODULE = 'profiler'
     XPIDL_SOURCES += [
         'gecko/nsIProfiler.idl',
     ]
     EXPORTS += [
         'public/ChildProfilerController.h',
         'public/GeckoProfilerReporter.h',
-        'public/ProfileJSONWriter.h',
         'public/ProfilerChild.h',
         'public/ProfilerCodeAddressService.h',
         'public/ProfilerMarkerPayload.h',
         'public/ProfilerParent.h',
         'public/shared-libraries.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/ProfilerCodeAddressService.cpp',
         'core/ProfilerMarkerPayload.cpp',
         'core/RegisteredThread.cpp',
         'gecko/ChildProfilerController.cpp',
         'gecko/nsProfilerStartParams.cpp',
         'gecko/ProfilerChild.cpp',
         'gecko/ProfilerIOInterposeObserver.cpp',
@@ -133,16 +131,17 @@ include('/ipc/chromium/chromium-config.m
 # non-MOZ_GECKO_PROFILER builds, and they only contains no-op macros in that
 # case.
 EXPORTS += [
     'public/GeckoProfiler.h',
 ]
 
 EXPORTS.mozilla += [
     'public/ProfileBufferEntrySerializationGeckoExtensions.h',
+    'public/ProfileJSONWriter.h',
     # vm/GeckoProfiler.h needs to include this and doesn't like #include "ProfilerCounts.h"
     'public/ProfilerCounts.h',
 ]
 
 if CONFIG['MOZ_VTUNE']:
     DEFINES['MOZ_VTUNE_INSTRUMENTATION'] = True
     UNIFIED_SOURCES += [
         'core/VTuneProfiler.cpp',
--- a/tools/profiler/public/GeckoProfiler.h
+++ b/tools/profiler/public/GeckoProfiler.h
@@ -106,19 +106,21 @@ static inline UniqueProfilerBacktrace pr
 #  include "nsString.h"
 
 #  include <functional>
 #  include <stdint.h>
 
 class ProfilerBacktrace;
 class ProfilerCodeAddressService;
 class ProfilerMarkerPayload;
-class SpliceableJSONWriter;
 namespace mozilla {
 class ProfileBufferControlledChunkManager;
+namespace baseprofiler {
+class SpliceableJSONWriter;
+}  // namespace baseprofiler
 namespace net {
 struct TimingStruct;
 enum CacheDisposition : uint8_t;
 }  // namespace net
 }  // namespace mozilla
 class nsIURI;
 class nsIDocShell;
 
@@ -1049,17 +1051,17 @@ void profiler_set_process_name(const nsA
 // If aIsShuttingDown is true, the current time is included as the process
 // shutdown time in the JSON's "meta" object.
 mozilla::UniquePtr<char[]> profiler_get_profile(double aSinceTime = 0,
                                                 bool aIsShuttingDown = false);
 
 // Write the profile for this process (excluding subprocesses) into aWriter.
 // Returns false if the profiler is inactive.
 bool profiler_stream_json_for_this_process(
-    SpliceableJSONWriter& aWriter, double aSinceTime = 0,
+    mozilla::baseprofiler::SpliceableJSONWriter& aWriter, double aSinceTime = 0,
     bool aIsShuttingDown = false,
     ProfilerCodeAddressService* aService = nullptr);
 
 // Get the profile and write it into a file. A no-op if the profile is
 // inactive.
 //
 // This function is 'extern "C"' so that it is easily callable from a debugger
 // in a build without debugging information (a workaround for
--- a/tools/profiler/public/ProfileJSONWriter.h
+++ b/tools/profiler/public/ProfileJSONWriter.h
@@ -1,143 +1,18 @@
 /* -*- 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/. */
 
 #ifndef PROFILEJSONWRITER_H
 #define PROFILEJSONWRITER_H
 
-#include "mozilla/JSONWriter.h"
-#include "mozilla/UniquePtr.h"
-
-#include <functional>
-#include <ostream>
-#include <string>
-
-class SpliceableChunkedJSONWriter;
-
-// On average, profile JSONs are large enough such that we want to avoid
-// reallocating its buffer when expanding. Additionally, the contents of the
-// profile are not accessed until the profile is entirely written. For these
-// reasons we use a chunked writer that keeps an array of chunks, which is
-// concatenated together after writing is finished.
-class ChunkedJSONWriteFunc : public mozilla::JSONWriteFunc {
- public:
-  friend class SpliceableJSONWriter;
-
-  ChunkedJSONWriteFunc() : mChunkPtr{nullptr}, mChunkEnd{nullptr} {
-    AllocChunk(kChunkSize);
-  }
-
-  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 CopyDataIntoLazilyAllocatedBuffer(
-      const std::function<char*(size_t)>& aAllocator) const;
-  mozilla::UniquePtr<char[]> CopyData() const;
-  void Take(ChunkedJSONWriteFunc&& aOther);
-  // Returns the byte length of the complete combined string, including the
-  // null terminator byte.
-  size_t GetTotalLength() const;
-
- private:
-  void AllocChunk(size_t aChunkSize);
-
-  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;
-
-  // Pointer to the end of the current chunk.
-  //
-  // The current chunk is always at the back of mChunkList, i.e.,
-  // mChunkEnd >= mChunkList.back() + mChunkLengths.back().
-  char* mChunkEnd;
-
-  // List of chunks and their lengths.
-  //
-  // For all i, the length of the string in mChunkList[i] is
-  // mChunkLengths[i].
-  mozilla::Vector<mozilla::UniquePtr<char[]>> mChunkList;
-  mozilla::Vector<size_t> mChunkLengths;
-};
-
-struct OStreamJSONWriteFunc : public mozilla::JSONWriteFunc {
-  explicit OStreamJSONWriteFunc(std::ostream& aStream) : mStream(aStream) {}
+#include "mozilla/BaseProfileJSONWriter.h"
 
-  void Write(const char* aStr) override { mStream << aStr; }
-  void Write(const char* aStr, size_t aLen) override { mStream << aStr; }
-
-  std::ostream& mStream;
-};
-
-class SpliceableJSONWriter : public mozilla::JSONWriter {
- public:
-  explicit SpliceableJSONWriter(
-      mozilla::UniquePtr<mozilla::JSONWriteFunc> aWriter)
-      : JSONWriter(std::move(aWriter)) {}
-
-  void StartBareList(CollectionStyle aStyle = MultiLineStyle) {
-    StartCollection(nullptr, "", aStyle);
-  }
-
-  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);
-
-  // 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);
-};
-
-class SpliceableChunkedJSONWriter : public SpliceableJSONWriter {
- public:
-  explicit SpliceableChunkedJSONWriter()
-      : SpliceableJSONWriter(mozilla::MakeUnique<ChunkedJSONWriteFunc>()) {}
-
-  ChunkedJSONWriteFunc* WriteFunc() const {
-    return static_cast<ChunkedJSONWriteFunc*>(JSONWriter::WriteFunc());
-  }
-
-  // Adopts the chunks from aFunc without copying.
-  virtual void TakeAndSplice(ChunkedJSONWriteFunc* aFunc) override;
-};
-
-class JSONSchemaWriter {
-  mozilla::JSONWriter& mWriter;
-  uint32_t mIndex;
-
- public:
-  explicit JSONSchemaWriter(mozilla::JSONWriter& aWriter)
-      : mWriter(aWriter), mIndex(0) {
-    aWriter.StartObjectProperty("schema",
-                                SpliceableJSONWriter::SingleLineStyle);
-  }
-
-  void WriteField(const char* aName) { mWriter.IntProperty(aName, mIndex++); }
-
-  ~JSONSchemaWriter() { mWriter.EndObject(); }
-};
+using ChunkedJSONWriteFunc = mozilla::baseprofiler::ChunkedJSONWriteFunc;
+using JSONSchemaWriter = mozilla::baseprofiler::JSONSchemaWriter;
+using OStreamJSONWriteFunc = mozilla::baseprofiler::OStreamJSONWriteFunc;
+using SpliceableChunkedJSONWriter =
+    mozilla::baseprofiler::SpliceableChunkedJSONWriter;
+using SpliceableJSONWriter = mozilla::baseprofiler::SpliceableJSONWriter;
 
 #endif  // PROFILEJSONWRITER_H
--- a/tools/profiler/public/ProfilerMarkerPayload.h
+++ b/tools/profiler/public/ProfilerMarkerPayload.h
@@ -25,22 +25,24 @@
 
 #include "js/Utility.h"
 #include "js/AllocationRecording.h"
 #include "js/ProfilingFrameIterator.h"
 #include "gfxASurface.h"
 #include "mozilla/ServoTraversalStatistics.h"
 
 namespace mozilla {
+namespace baseprofiler {
+class SpliceableJSONWriter;
+}  // namespace baseprofiler
 namespace layers {
 class Layer;
 }  // namespace layers
 }  // namespace mozilla
 
-class SpliceableJSONWriter;
 class UniqueStacks;
 
 // This is an abstract class that can be implemented to supply data to be
 // attached with a profiler marker.
 //
 // When subclassing this, note that the destructor can be called on any thread,
 // i.e. not necessarily on the thread that created the object.
 class ProfilerMarkerPayload {
@@ -85,19 +87,20 @@ class ProfilerMarkerPayload {
   // (nullptr) case.
   static mozilla::UniquePtr<ProfilerMarkerPayload> DeserializeTagAndPayload(
       mozilla::ProfileBufferEntryReader& aER) {
     const auto tag = aER.ReadObject<DeserializerTag>();
     Deserializer deserializer = DeserializerForTag(tag);
     return deserializer(aER);
   }
 
-  virtual void StreamPayload(SpliceableJSONWriter& aWriter,
-                             const mozilla::TimeStamp& aProcessStartTime,
-                             UniqueStacks& aUniqueStacks) const = 0;
+  virtual void StreamPayload(
+      mozilla::baseprofiler::SpliceableJSONWriter& aWriter,
+      const mozilla::TimeStamp& aProcessStartTime,
+      UniqueStacks& aUniqueStacks) const = 0;
 
   const mozilla::TimeStamp& GetStartTime() const {
     return mCommonProps.mStartTime;
   }
   const mozilla::TimeStamp& GetEndTime() const { return mCommonProps.mEndTime; }
 
  protected:
   // A `Deserializer` is a free function that can read a serialized payload from
@@ -150,22 +153,24 @@ class ProfilerMarkerPayload {
   mozilla::ProfileBufferEntryWriter::Length
   CommonPropsTagAndSerializationBytes() const;
   void SerializeTagAndCommonProps(
       DeserializerTag aDeserializerTag,
       mozilla::ProfileBufferEntryWriter& aEntryWriter) const;
   static CommonProps DeserializeCommonProps(
       mozilla::ProfileBufferEntryReader& aEntryReader);
 
-  void StreamType(const char* aMarkerType, SpliceableJSONWriter& aWriter) const;
+  void StreamType(const char* aMarkerType,
+                  mozilla::baseprofiler::SpliceableJSONWriter& aWriter) const;
 
-  void StreamCommonProps(const char* aMarkerType, SpliceableJSONWriter& aWriter,
+  void StreamCommonProps(const char* aMarkerType,
+                         mozilla::baseprofiler::SpliceableJSONWriter& aWriter,
                          const mozilla::TimeStamp& aProcessStartTime,
                          UniqueStacks& aUniqueStacks) const;
-  void StreamStartEndTime(SpliceableJSONWriter& aWriter,
+  void StreamStartEndTime(mozilla::baseprofiler::SpliceableJSONWriter& aWriter,
                           const mozilla::TimeStamp& aProcessStartTime) const;
 
  private:
   // Compute the number of bytes needed to serialize payload in
   // `SerializeTagAndPayload` below.
   virtual mozilla::ProfileBufferEntryWriter::Length TagAndSerializationBytes()
       const = 0;
 
@@ -173,17 +178,17 @@ class ProfilerMarkerPayload {
   // Must be of the exact size given by `TagAndSerializationBytes()`.
   virtual void SerializeTagAndPayload(
       mozilla::ProfileBufferEntryWriter& aEntryWriter) const = 0;
 
   CommonProps mCommonProps;
 };
 
 #define DECL_STREAM_PAYLOAD                                                    \
-  void StreamPayload(SpliceableJSONWriter& aWriter,                            \
+  void StreamPayload(mozilla::baseprofiler::SpliceableJSONWriter& aWriter,     \
                      const mozilla::TimeStamp& aProcessStartTime,              \
                      UniqueStacks& aUniqueStacks) const override;              \
   static mozilla::UniquePtr<ProfilerMarkerPayload> Deserialize(                \
       mozilla::ProfileBufferEntryReader& aEntryReader);                        \
   mozilla::ProfileBufferEntryWriter::Length TagAndSerializationBytes()         \
       const override;                                                          \
   void SerializeTagAndPayload(mozilla::ProfileBufferEntryWriter& aEntryWriter) \
       const override;
--- a/tools/profiler/tests/gtest/GeckoProfiler.cpp
+++ b/tools/profiler/tests/gtest/GeckoProfiler.cpp
@@ -7,26 +7,26 @@
 // This file tests a lot of the profiler_*() functions in GeckoProfiler.h.
 // Most of the tests just check that nothing untoward (e.g. crashes, deadlocks)
 // happens when calling these functions. They don't do much inspection of
 // profiler internals.
 
 #include "GeckoProfiler.h"
 #include "platform.h"
 #include "ProfileBuffer.h"
-#include "ProfileJSONWriter.h"
 #include "ProfilerMarkerPayload.h"
 
 #include "js/Initialization.h"
 #include "js/Printf.h"
 #include "jsapi.h"
 #include "json/json.h"
 #include "mozilla/Atomics.h"
 #include "mozilla/BlocksRingBuffer.h"
 #include "mozilla/ProfileBufferEntrySerializationGeckoExtensions.h"
+#include "mozilla/ProfileJSONWriter.h"
 #include "mozilla/UniquePtrExtensions.h"
 #include "mozilla/net/HttpBaseChannel.h"
 #include "nsIThread.h"
 #include "nsThreadUtils.h"
 
 #include "gtest/gtest.h"
 
 #include <cstring>
@@ -824,17 +824,17 @@ TEST(GeckoProfiler, Markers)
   PROFILER_ADD_MARKER_WITH_PAYLOAD(
       "IPCMarkerPayload marker", IPC, IPCMarkerPayload,
       (1111, 1, 3 /* PAPZ::Msg_LayerTransforms */, mozilla::ipc::ParentSide,
        mozilla::ipc::MessageDirection::eSending,
        mozilla::ipc::MessagePhase::Endpoint, false, ts1));
 
   SpliceableChunkedJSONWriter w;
   w.Start();
-  EXPECT_TRUE(profiler_stream_json_for_this_process(w));
+  EXPECT_TRUE(::profiler_stream_json_for_this_process(w));
   w.End();
 
   // The GTestMarkerPayloads should have been deserialized, streamed, and
   // destroyed.
   EXPECT_EQ(GTestMarkerPayload::sNumCreated, 10 + 0);
   EXPECT_EQ(GTestMarkerPayload::sNumSerialized, 10 + 0);
   EXPECT_EQ(GTestMarkerPayload::sNumDeserialized, 0 + 10);
   EXPECT_EQ(GTestMarkerPayload::sNumStreamed, 0 + 10);
@@ -1462,17 +1462,17 @@ TEST(GeckoProfiler, Markers)
   for (int i = 0; i < 10; i++) {
     PROFILER_ADD_MARKER_WITH_PAYLOAD("M5", OTHER, GTestMarkerPayload, (i));
   }
 
   // Warning: this could be racy
   profiler_start(PROFILER_DEFAULT_ENTRIES, PROFILER_DEFAULT_INTERVAL, features,
                  filters, MOZ_ARRAY_LENGTH(filters), 0);
 
-  EXPECT_TRUE(profiler_stream_json_for_this_process(w));
+  EXPECT_TRUE(::profiler_stream_json_for_this_process(w));
 
   profiler_stop();
 
   // The second set of GTestMarkerPayloads should not have been serialized or
   // streamed.
   EXPECT_EQ(GTestMarkerPayload::sNumCreated, 10 + 0 + 0 + 10);
   EXPECT_EQ(GTestMarkerPayload::sNumSerialized, 10 + 0 + 0 + 0);
   EXPECT_EQ(GTestMarkerPayload::sNumDeserialized, 0 + 10 + 0 + 0);
@@ -1536,30 +1536,30 @@ TEST(GeckoProfiler, Counters)
   PR_Sleep(PR_MillisecondsToInterval(200));
   AUTO_PROFILER_COUNT_TOTAL(TestCounter, 7);
   PR_Sleep(PR_MillisecondsToInterval(200));
   AUTO_PROFILER_COUNT_TOTAL(TestCounter, -17);
   PR_Sleep(PR_MillisecondsToInterval(200));
 
   // Verify we got counters in the output
   SpliceableChunkedJSONWriter w;
-  ASSERT_TRUE(profiler_stream_json_for_this_process(w));
+  ASSERT_TRUE(::profiler_stream_json_for_this_process(w));
 
   UniquePtr<char[]> profile = w.WriteFunc()->CopyData();
 
   // counter name and description should appear as is.
   ASSERT_TRUE(strstr(profile.get(), COUNTER_NAME));
   ASSERT_TRUE(strstr(profile.get(), COUNTER_DESCRIPTION));
   ASSERT_FALSE(strstr(profile.get(), COUNTER_NAME2));
   ASSERT_FALSE(strstr(profile.get(), COUNTER_DESCRIPTION2));
 
   AUTO_PROFILER_COUNT_TOTAL(TestCounter2, 10);
   PR_Sleep(PR_MillisecondsToInterval(200));
 
-  ASSERT_TRUE(profiler_stream_json_for_this_process(w));
+  ASSERT_TRUE(::profiler_stream_json_for_this_process(w));
 
   profile = w.WriteFunc()->CopyData();
   ASSERT_TRUE(strstr(profile.get(), COUNTER_NAME));
   ASSERT_TRUE(strstr(profile.get(), COUNTER_DESCRIPTION));
   ASSERT_TRUE(strstr(profile.get(), COUNTER_NAME2));
   ASSERT_TRUE(strstr(profile.get(), COUNTER_DESCRIPTION2));
 
   profiler_stop();
@@ -1629,80 +1629,80 @@ static void JSONOutputCheck(const char* 
 }
 
 TEST(GeckoProfiler, StreamJSONForThisProcess)
 {
   uint32_t features = ProfilerFeature::StackWalk;
   const char* filters[] = {"GeckoMain"};
 
   SpliceableChunkedJSONWriter w;
-  ASSERT_TRUE(!profiler_stream_json_for_this_process(w));
+  ASSERT_TRUE(!::profiler_stream_json_for_this_process(w));
 
   profiler_start(PROFILER_DEFAULT_ENTRIES, PROFILER_DEFAULT_INTERVAL, features,
                  filters, MOZ_ARRAY_LENGTH(filters), 0);
 
   w.Start();
-  ASSERT_TRUE(profiler_stream_json_for_this_process(w));
+  ASSERT_TRUE(::profiler_stream_json_for_this_process(w));
   w.End();
 
   UniquePtr<char[]> profile = w.WriteFunc()->CopyData();
 
   JSONOutputCheck(profile.get());
 
   profiler_stop();
 
-  ASSERT_TRUE(!profiler_stream_json_for_this_process(w));
+  ASSERT_TRUE(!::profiler_stream_json_for_this_process(w));
 }
 
 TEST(GeckoProfiler, StreamJSONForThisProcessThreaded)
 {
   // Same as the previous test, but calling some things on background threads.
   nsCOMPtr<nsIThread> thread;
   nsresult rv = NS_NewNamedThread("GeckoProfGTest", getter_AddRefs(thread));
   ASSERT_TRUE(NS_SUCCEEDED(rv));
 
   uint32_t features = ProfilerFeature::StackWalk;
   const char* filters[] = {"GeckoMain"};
 
   SpliceableChunkedJSONWriter w;
-  ASSERT_TRUE(!profiler_stream_json_for_this_process(w));
+  ASSERT_TRUE(!::profiler_stream_json_for_this_process(w));
 
   // Start the profiler on the main thread.
   profiler_start(PROFILER_DEFAULT_ENTRIES, PROFILER_DEFAULT_INTERVAL, features,
                  filters, MOZ_ARRAY_LENGTH(filters), 0);
 
   // Call profiler_stream_json_for_this_process on a background thread.
   thread->Dispatch(
       NS_NewRunnableFunction(
           "GeckoProfiler_StreamJSONForThisProcessThreaded_Test::TestBody",
           [&]() {
             w.Start();
-            ASSERT_TRUE(profiler_stream_json_for_this_process(w));
+            ASSERT_TRUE(::profiler_stream_json_for_this_process(w));
             w.End();
           }),
       NS_DISPATCH_SYNC);
 
   UniquePtr<char[]> profile = w.WriteFunc()->CopyData();
 
   JSONOutputCheck(profile.get());
 
   // Stop the profiler and call profiler_stream_json_for_this_process on a
   // background thread.
   thread->Dispatch(
       NS_NewRunnableFunction(
           "GeckoProfiler_StreamJSONForThisProcessThreaded_Test::TestBody",
           [&]() {
             profiler_stop();
-            ASSERT_TRUE(!profiler_stream_json_for_this_process(w));
+            ASSERT_TRUE(!::profiler_stream_json_for_this_process(w));
           }),
       NS_DISPATCH_SYNC);
   thread->Shutdown();
 
   // Call profiler_stream_json_for_this_process on the main thread.
-  ASSERT_TRUE(!profiler_stream_json_for_this_process(w));
+  ASSERT_TRUE(!::profiler_stream_json_for_this_process(w));
 }
 
 TEST(GeckoProfiler, ProfilingStack)
 {
   uint32_t features = ProfilerFeature::StackWalk;
   const char* filters[] = {"GeckoMain"};
 
   AUTO_PROFILER_LABEL("A::B", OTHER);