Bug 1492121 - All necessary changes to make baseprofiler build - r=njn
☠☠ backed out by 4494c0e5d35d ☠ ☠
authorGerald Squelart <gsquelart@mozilla.com>
Tue, 04 Jun 2019 06:53:01 +0000
changeset 476739 de1c3ae8df14cdb2c94a817b02dcffcb2cee12e2
parent 476738 0689c1b8f4f7775386fcd474adf60789ca297e84
child 476740 5f30af0d0f63036d387e5e4abc4fa36d1a3deab6
push id36106
push userbtara@mozilla.com
push dateTue, 04 Jun 2019 16:04:27 +0000
treeherdermozilla-central@d17dc040eec7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnjn
bugs1492121, 1536656
milestone69.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 1492121 - All necessary changes to make baseprofiler build - r=njn Almost-mechanical changes include: - Removed unneeded/incompatible #includes and functions (any JS- or XPCOM- dependent). - Use std::string for strings and nsIDs. - Use thin wrappers around mozilla::detail::MutexImpl for mutexes. - Use hand-rolled AddRef&Release's for ref-counted classes -- could not use mfbt/RefCounted.h because of bug 1536656. - Added some platform-specific polyfills, e.g.: MicrosecondsSince1970(). - Only record the main thread by default. - Logging controlled by env-vars MOZ_BASE_PROFILER_{,DEBUG_,VERBOSE_}LOGGING. This now builds (with --enable-base-profiler), but is not usable yet. Differential Revision: https://phabricator.services.mozilla.com/D31924
mozglue/baseprofiler/core/PageInformation.cpp
mozglue/baseprofiler/core/PageInformation.h
mozglue/baseprofiler/core/ProfileBuffer.cpp
mozglue/baseprofiler/core/ProfileBuffer.h
mozglue/baseprofiler/core/ProfileBufferEntry.cpp
mozglue/baseprofiler/core/ProfileBufferEntry.h
mozglue/baseprofiler/core/ProfiledThreadData.cpp
mozglue/baseprofiler/core/ProfiledThreadData.h
mozglue/baseprofiler/core/ProfilerBacktrace.cpp
mozglue/baseprofiler/core/ProfilerMarker.h
mozglue/baseprofiler/core/ProfilerMarkerPayload.cpp
mozglue/baseprofiler/core/ProfilingCategory.cpp
mozglue/baseprofiler/core/ProfilingStack.cpp
mozglue/baseprofiler/core/RegisteredThread.cpp
mozglue/baseprofiler/core/RegisteredThread.h
mozglue/baseprofiler/core/ThreadInfo.h
mozglue/baseprofiler/core/VTuneProfiler.cpp
mozglue/baseprofiler/core/platform-linux-android.cpp
mozglue/baseprofiler/core/platform-macos.cpp
mozglue/baseprofiler/core/platform-win32.cpp
mozglue/baseprofiler/core/platform.cpp
mozglue/baseprofiler/core/platform.h
mozglue/baseprofiler/core/shared-libraries-linux.cc
mozglue/baseprofiler/core/shared-libraries-macos.cc
mozglue/baseprofiler/core/shared-libraries-win32.cc
mozglue/baseprofiler/lul/AutoObjectMapper.cpp
mozglue/baseprofiler/lul/LulElf.cpp
mozglue/baseprofiler/lul/platform-linux-lul.cpp
mozglue/baseprofiler/lul/platform-linux-lul.h
mozglue/baseprofiler/public/BaseProfileJSONWriter.h
mozglue/baseprofiler/public/BaseProfiler.h
mozglue/baseprofiler/public/BaseProfilerCounts.h
mozglue/baseprofiler/public/BaseProfilerMarkerPayload.h
mozglue/baseprofiler/public/BaseProfilerSharedLibraries.h
mozglue/baseprofiler/public/BaseProfilingCategory.h
mozglue/baseprofiler/public/BaseProfilingStack.h
--- a/mozglue/baseprofiler/core/PageInformation.cpp
+++ b/mozglue/baseprofiler/core/PageInformation.cpp
@@ -7,35 +7,36 @@
 #include "BaseProfiler.h"
 
 #ifdef MOZ_BASE_PROFILER
 
 #  include "PageInformation.h"
 
 #  include "BaseProfileJSONWriter.h"
 
-PageInformation::PageInformation(const nsID& aDocShellId,
+PageInformation::PageInformation(const std::string& aDocShellId,
                                  uint32_t aDocShellHistoryId,
-                                 const nsCString& aUrl, bool aIsSubFrame)
+                                 const std::string& aUrl, bool aIsSubFrame)
     : mDocShellId(aDocShellId),
       mDocShellHistoryId(aDocShellHistoryId),
       mUrl(aUrl),
-      mIsSubFrame(aIsSubFrame) {}
+      mIsSubFrame(aIsSubFrame),
+      mRefCnt(0) {}
 
 bool PageInformation::Equals(PageInformation* aOtherPageInfo) {
   return DocShellHistoryId() == aOtherPageInfo->DocShellHistoryId() &&
-         DocShellId().Equals(aOtherPageInfo->DocShellId()) &&
+         DocShellId() == aOtherPageInfo->DocShellId() &&
          IsSubFrame() == aOtherPageInfo->IsSubFrame();
 }
 
 void PageInformation::StreamJSON(SpliceableJSONWriter& aWriter) {
   aWriter.StartObjectElement();
-  aWriter.StringProperty("docshellId", nsIDToCString(DocShellId()).get());
+  aWriter.StringProperty("docshellId", DocShellId().c_str());
   aWriter.DoubleProperty("historyId", DocShellHistoryId());
-  aWriter.StringProperty("url", Url().get());
+  aWriter.StringProperty("url", Url().c_str());
   aWriter.BoolProperty("isSubFrame", IsSubFrame());
   aWriter.EndObject();
 }
 
 size_t PageInformation::SizeOfIncludingThis(
     mozilla::MallocSizeOf aMallocSizeOf) const {
   return aMallocSizeOf(this);
 }
--- a/mozglue/baseprofiler/core/PageInformation.h
+++ b/mozglue/baseprofiler/core/PageInformation.h
@@ -2,61 +2,72 @@
 /* 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 PageInformation_h
 #define PageInformation_h
 
+#include "mozilla/Atomics.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/MemoryReporting.h"
-#include "nsID.h"
-#include "nsISupportsImpl.h"
-#include "nsString.h"
+
+#include <string>
 
 class SpliceableJSONWriter;
 
 // 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(const nsID& aDocShellId, uint32_t aDocShellHistoryId,
-                  const nsCString& aUrl, bool aIsSubFrame);
+  PageInformation(const std::string& aDocShellId, uint32_t aDocShellHistoryId,
+                  const std::string& aUrl, bool aIsSubFrame);
+
+  // Using hand-rolled ref-counting, because RefCounted.h macros don't produce
+  // the same code between mozglue and libxul, see bug 1536656.
+  MFBT_API void AddRef() const { ++mRefCnt; }
+  MFBT_API void Release() const {
+    MOZ_ASSERT(int32_t(mRefCnt) > 0);
+    if (--mRefCnt) {
+      delete this;
+    }
+  }
 
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
   bool Equals(PageInformation* aOtherDocShellInfo);
   void StreamJSON(SpliceableJSONWriter& aWriter);
 
   uint32_t DocShellHistoryId() { return mDocShellHistoryId; }
-  const nsID& DocShellId() { return mDocShellId; }
-  const nsCString& Url() { return mUrl; }
+  const std::string& DocShellId() { return mDocShellId; }
+  const std::string& Url() { return mUrl; }
   bool IsSubFrame() { return mIsSubFrame; }
 
   mozilla::Maybe<uint64_t> BufferPositionWhenUnregistered() {
     return mBufferPositionWhenUnregistered;
   }
 
   void NotifyUnregistered(uint64_t aBufferPosition) {
     mBufferPositionWhenUnregistered = mozilla::Some(aBufferPosition);
   }
 
  private:
-  const nsID mDocShellId;
+  const std::string mDocShellId;
   const uint32_t mDocShellHistoryId;
-  const nsCString mUrl;
+  const std::string mUrl;
   const bool mIsSubFrame;
 
   // Holds the buffer position when DocShell is unregistered.
   // It's used to determine if we still use this DocShell in the profiler or
   // not.
   mozilla::Maybe<uint64_t> mBufferPositionWhenUnregistered;
 
-  virtual ~PageInformation() = default;
+  mutable mozilla::Atomic<int32_t, mozilla::MemoryOrdering::ReleaseAcquire,
+                          mozilla::recordreplay::Behavior::DontPreserve>
+      mRefCnt;
 };
 
 #endif  // PageInformation_h
--- a/mozglue/baseprofiler/core/ProfileBuffer.cpp
+++ b/mozglue/baseprofiler/core/ProfileBuffer.cpp
@@ -7,20 +7,17 @@
 #include "BaseProfiler.h"
 
 #ifdef MOZ_BASE_PROFILER
 
 #  include "ProfileBuffer.h"
 
 #  include "ProfilerMarker.h"
 
-#  include "jsfriendapi.h"
 #  include "mozilla/MathAlgorithms.h"
-#  include "nsJSPrincipals.h"
-#  include "nsScriptSecurityManager.h"
 
 using namespace mozilla;
 
 ProfileBuffer::ProfileBuffer(uint32_t aCapacity)
     : mEntryIndexMask(0), mRangeStart(0), mRangeEnd(0), mCapacity(0) {
   // Round aCapacity up to the nearest power of two, so that we can index
   // mEntries with a simple mask and don't need to do a slow modulo operation.
   const uint32_t UINT32_MAX_POWER_OF_TWO = 1 << 31;
@@ -115,75 +112,34 @@ size_t ProfileBuffer::SizeOfIncludingThi
   // - memory pointed to by the elements within mEntries
   // - mStoredMarkers
 
   return n;
 }
 
 /* ProfileBufferCollector */
 
-static bool IsChromeJSScript(JSScript* aScript) {
-  // WARNING: this function runs within the profiler's "critical section".
-  auto realm = js::GetScriptRealm(aScript);
-  return js::IsSystemRealm(realm);
-}
-
 void ProfileBufferCollector::CollectNativeLeafAddr(void* aAddr) {
   mBuf.AddEntry(ProfileBufferEntry::NativeLeafAddr(aAddr));
 }
 
-void ProfileBufferCollector::CollectJitReturnAddr(void* aAddr) {
-  mBuf.AddEntry(ProfileBufferEntry::JitReturnAddr(aAddr));
-}
-
-void ProfileBufferCollector::CollectWasmFrame(const char* aLabel) {
-  mBuf.CollectCodeLocation("", aLabel, 0, Nothing(), Nothing(), Nothing());
-}
-
 void ProfileBufferCollector::CollectProfilingStackFrame(
     const js::ProfilingStackFrame& aFrame) {
   // WARNING: this function runs within the profiler's "critical section".
 
   MOZ_ASSERT(aFrame.isLabelFrame() ||
              (aFrame.isJsFrame() && !aFrame.isOSRFrame()));
 
   const char* label = aFrame.label();
   const char* dynamicString = aFrame.dynamicString();
   bool isChromeJSEntry = false;
   Maybe<uint32_t> line;
   Maybe<uint32_t> column;
 
-  if (aFrame.isJsFrame()) {
-    // There are two kinds of JS frames that get pushed onto the ProfilingStack.
-    //
-    // - label = "", dynamic string = <something>
-    // - label = "js::RunScript", dynamic string = nullptr
-    //
-    // The line number is only interesting in the first case.
-
-    if (label[0] == '\0') {
-      MOZ_ASSERT(dynamicString);
-
-      // We call aFrame.script() repeatedly -- rather than storing the result in
-      // a local variable in order -- to avoid rooting hazards.
-      if (aFrame.script()) {
-        isChromeJSEntry = IsChromeJSScript(aFrame.script());
-        if (aFrame.pc()) {
-          unsigned col = 0;
-          line = Some(JS_PCToLineNumber(aFrame.script(), aFrame.pc(), &col));
-          column = Some(col);
-        }
-      }
-
-    } else {
-      MOZ_ASSERT(strcmp(label, "js::RunScript") == 0 && !dynamicString);
-    }
-  } else {
-    MOZ_ASSERT(aFrame.isLabelFrame());
-  }
+  MOZ_ASSERT(aFrame.isLabelFrame());
 
   if (dynamicString) {
     // Adjust the dynamic string as necessary.
     if (ProfilerFeature::HasPrivacy(mFeatures) && !isChromeJSEntry) {
       dynamicString = "(private)";
     } else if (strlen(dynamicString) >= ProfileBuffer::kMaxFrameKeyLength) {
       dynamicString = "(too long)";
     }
--- a/mozglue/baseprofiler/core/ProfileBuffer.h
+++ b/mozglue/baseprofiler/core/ProfileBuffer.h
@@ -44,31 +44,20 @@ class ProfileBuffer final {
       const char* aLabel, const char* aStr, uint32_t aFrameFlags,
       const mozilla::Maybe<uint32_t>& aLineNumber,
       const mozilla::Maybe<uint32_t>& aColumnNumber,
       const mozilla::Maybe<JS::ProfilingCategoryPair>& aCategoryPair);
 
   // Maximum size of a frameKey string that we'll handle.
   static const size_t kMaxFrameKeyLength = 512;
 
-  // Add JIT frame information to aJITFrameInfo for any JitReturnAddr entries
-  // that are currently in the buffer at or after aRangeStart, in samples
-  // for the given thread.
-  void AddJITInfoForRange(uint64_t aRangeStart, int aThreadId,
-                          JSContext* aContext,
-                          JITFrameInfo& aJITFrameInfo) const;
-
   // Stream JSON for samples in the buffer to aWriter, using the supplied
   // UniqueStacks object.
   // Only streams samples for the given thread ID and which were taken at or
   // after aSinceTime.
-  // aUniqueStacks needs to contain information about any JIT frames that we
-  // might encounter in the buffer, before this method is called. In other
-  // words, you need to have called AddJITInfoForRange for every range that
-  // might contain JIT frame information before calling this method.
   void StreamSamplesToJSON(SpliceableJSONWriter& aWriter, int aThreadId,
                            double aSinceTime,
                            UniqueStacks& aUniqueStacks) const;
 
   void StreamMarkersToJSON(SpliceableJSONWriter& aWriter, int aThreadId,
                            const mozilla::TimeStamp& aProcessStartTime,
                            double aSinceTime,
                            UniqueStacks& aUniqueStacks) const;
@@ -158,18 +147,16 @@ class ProfileBufferCollector final : pub
     return mozilla::Some(mSamplePositionInBuffer);
   }
 
   mozilla::Maybe<uint64_t> BufferRangeStart() override {
     return mozilla::Some(mBuf.mRangeStart);
   }
 
   virtual void CollectNativeLeafAddr(void* aAddr) override;
-  virtual void CollectJitReturnAddr(void* aAddr) override;
-  virtual void CollectWasmFrame(const char* aLabel) override;
   virtual void CollectProfilingStackFrame(
       const js::ProfilingStackFrame& aFrame) override;
 
  private:
   ProfileBuffer& mBuf;
   uint64_t mSamplePositionInBuffer;
   uint32_t mFeatures;
 };
--- a/mozglue/baseprofiler/core/ProfileBufferEntry.cpp
+++ b/mozglue/baseprofiler/core/ProfileBufferEntry.cpp
@@ -8,24 +8,19 @@
 
 #ifdef MOZ_BASE_PROFILER
 
 #  include "ProfileBufferEntry.h"
 
 #  include "platform.h"
 #  include "ProfileBuffer.h"
 
-#  include "js/TrackedOptimizationInfo.h"
-#  include "jsapi.h"
-#  include "jsfriendapi.h"
 #  include "mozilla/Logging.h"
 #  include "mozilla/Sprintf.h"
 #  include "mozilla/StackWalk.h"
-#  include "nsThreadUtils.h"
-#  include "nsXULAppAPI.h"
 
 #  include <ostream>
 
 using namespace mozilla;
 
 ////////////////////////////////////////////////////////////////////////
 // BEGIN ProfileBufferEntry
 
@@ -115,61 +110,16 @@ uint64_t ProfileBufferEntry::GetUint64()
 
 void ProfileBufferEntry::CopyCharsInto(char (&aOutArray)[kNumChars]) const {
   memcpy(aOutArray, mStorage, kNumChars);
 }
 
 // END ProfileBufferEntry
 ////////////////////////////////////////////////////////////////////////
 
-struct TypeInfo {
-  Maybe<nsCString> mKeyedBy;
-  Maybe<nsCString> mName;
-  Maybe<nsCString> mLocation;
-  Maybe<unsigned> mLineNumber;
-};
-
-template <typename LambdaT>
-class ForEachTrackedOptimizationTypeInfoLambdaOp
-    : public JS::ForEachTrackedOptimizationTypeInfoOp {
- public:
-  // aLambda needs to be a function with the following signature:
-  // void lambda(JS::TrackedTypeSite site, const char* mirType,
-  //             const nsTArray<TypeInfo>& typeset)
-  // aLambda will be called once per entry.
-  explicit ForEachTrackedOptimizationTypeInfoLambdaOp(LambdaT&& aLambda)
-      : mLambda(aLambda) {}
-
-  // This is called 0 or more times per entry, *before* operator() is called
-  // for that entry.
-  void readType(const char* keyedBy, const char* name, const char* location,
-                const Maybe<unsigned>& lineno) override {
-    TypeInfo info = {keyedBy ? Some(nsCString(keyedBy)) : Nothing(),
-                     name ? Some(nsCString(name)) : Nothing(),
-                     location ? Some(nsCString(location)) : Nothing(), lineno};
-    mTypesetForUpcomingEntry.AppendElement(std::move(info));
-  }
-
-  void operator()(JS::TrackedTypeSite site, const char* mirType) override {
-    nsTArray<TypeInfo> typeset(std::move(mTypesetForUpcomingEntry));
-    mLambda(site, mirType, typeset);
-  }
-
- private:
-  nsTArray<TypeInfo> mTypesetForUpcomingEntry;
-  LambdaT mLambda;
-};
-
-template <typename LambdaT>
-ForEachTrackedOptimizationTypeInfoLambdaOp<LambdaT>
-MakeForEachTrackedOptimizationTypeInfoLambdaOp(LambdaT&& aLambda) {
-  return ForEachTrackedOptimizationTypeInfoLambdaOp<LambdaT>(
-      std::forward<LambdaT>(aLambda));
-}
-
 // As mentioned in ProfileBufferEntry.h, the JSON format contains many
 // arrays whose elements are laid out according to various schemas to help
 // de-duplication. This RAII class helps write these arrays by keeping track of
 // the last non-null element written and adding the appropriate number of null
 // elements when writing new non-null elements. It also automatically opens and
 // closes an array element on the given JSON writer.
 //
 // You grant the AutoArraySchemaWriter exclusive access to the JSONWriter and
@@ -249,38 +199,16 @@ class MOZ_RAII AutoArraySchemaWriter {
     mNextFreeIndex = aIndex + 1;
   }
 
   SpliceableJSONWriter& mJSONWriter;
   UniqueJSONStrings* mStrings;
   uint32_t mNextFreeIndex;
 };
 
-template <typename LambdaT>
-class ForEachTrackedOptimizationAttemptsLambdaOp
-    : public JS::ForEachTrackedOptimizationAttemptOp {
- public:
-  explicit ForEachTrackedOptimizationAttemptsLambdaOp(LambdaT&& aLambda)
-      : mLambda(std::move(aLambda)) {}
-  void operator()(JS::TrackedStrategy aStrategy,
-                  JS::TrackedOutcome aOutcome) override {
-    mLambda(aStrategy, aOutcome);
-  }
-
- private:
-  LambdaT mLambda;
-};
-
-template <typename LambdaT>
-ForEachTrackedOptimizationAttemptsLambdaOp<LambdaT>
-MakeForEachTrackedOptimizationAttemptsLambdaOp(LambdaT&& aLambda) {
-  return ForEachTrackedOptimizationAttemptsLambdaOp<LambdaT>(
-      std::move(aLambda));
-}
-
 UniqueJSONStrings::UniqueJSONStrings() { mStringTableWriter.StartBareList(); }
 
 UniqueJSONStrings::UniqueJSONStrings(const UniqueJSONStrings& aOther) {
   mStringTableWriter.StartBareList();
   uint32_t count = mStringHashToIndexMap.count();
   if (count != 0) {
     MOZ_RELEASE_ASSERT(mStringHashToIndexMap.reserve(count));
     for (auto iter = aOther.mStringHashToIndexMap.iter(); !iter.done();
@@ -313,69 +241,24 @@ UniqueStacks::StackKey UniqueStacks::Beg
 }
 
 UniqueStacks::StackKey UniqueStacks::AppendFrame(const StackKey& aStack,
                                                  const FrameKey& aFrame) {
   return StackKey(aStack, GetOrAddStackIndex(aStack),
                   GetOrAddFrameIndex(aFrame));
 }
 
-JITFrameInfoForBufferRange JITFrameInfoForBufferRange::Clone() const {
-  JITFrameInfoForBufferRange::JITAddressToJITFramesMap jitAddressToJITFramesMap;
-  MOZ_RELEASE_ASSERT(
-      jitAddressToJITFramesMap.reserve(mJITAddressToJITFramesMap.count()));
-  for (auto iter = mJITAddressToJITFramesMap.iter(); !iter.done();
-       iter.next()) {
-    const mozilla::Vector<JITFrameKey>& srcKeys = iter.get().value();
-    mozilla::Vector<JITFrameKey> destKeys;
-    MOZ_RELEASE_ASSERT(destKeys.appendAll(srcKeys));
-    jitAddressToJITFramesMap.putNewInfallible(iter.get().key(),
-                                              std::move(destKeys));
-  }
-
-  JITFrameInfoForBufferRange::JITFrameToFrameJSONMap jitFrameToFrameJSONMap;
-  MOZ_RELEASE_ASSERT(
-      jitFrameToFrameJSONMap.reserve(mJITFrameToFrameJSONMap.count()));
-  for (auto iter = mJITFrameToFrameJSONMap.iter(); !iter.done(); iter.next()) {
-    jitFrameToFrameJSONMap.putNewInfallible(iter.get().key(),
-                                            iter.get().value());
-  }
-
-  return JITFrameInfoForBufferRange{mRangeStart, mRangeEnd,
-                                    std::move(jitAddressToJITFramesMap),
-                                    std::move(jitFrameToFrameJSONMap)};
-}
-
-JITFrameInfo::JITFrameInfo(const JITFrameInfo& aOther)
-    : mUniqueStrings(MakeUnique<UniqueJSONStrings>(*aOther.mUniqueStrings)) {
-  for (const JITFrameInfoForBufferRange& range : aOther.mRanges) {
-    MOZ_RELEASE_ASSERT(mRanges.append(range.Clone()));
-  }
-}
-
 bool UniqueStacks::FrameKey::NormalFrameData::operator==(
     const NormalFrameData& aOther) const {
   return mLocation == aOther.mLocation &&
          mRelevantForJS == aOther.mRelevantForJS && mLine == aOther.mLine &&
          mColumn == aOther.mColumn && mCategoryPair == aOther.mCategoryPair;
 }
 
-bool UniqueStacks::FrameKey::JITFrameData::operator==(
-    const JITFrameData& aOther) const {
-  return mCanonicalAddress == aOther.mCanonicalAddress &&
-         mDepth == aOther.mDepth && mRangeIndex == aOther.mRangeIndex;
-}
-
-// Consume aJITFrameInfo by stealing its string table and its JIT frame info
-// ranges. The JIT frame info contains JSON which refers to strings from the
-// JIT frame info's string table, so our string table needs to have the same
-// strings at the same indices.
-UniqueStacks::UniqueStacks(JITFrameInfo&& aJITFrameInfo)
-    : mUniqueStrings(std::move(aJITFrameInfo.mUniqueStrings)),
-      mJITInfoRanges(std::move(aJITFrameInfo.mRanges)) {
+UniqueStacks::UniqueStacks() : mUniqueStrings(MakeUnique<UniqueJSONStrings>()) {
   mFrameTableWriter.StartBareList();
   mStackTableWriter.StartBareList();
 }
 
 uint32_t UniqueStacks::GetOrAddStackIndex(const StackKey& aStack) {
   uint32_t count = mStackToIndexMap.count();
   auto entry = mStackToIndexMap.lookupForAdd(aStack);
   if (entry) {
@@ -394,62 +277,16 @@ struct PositionInRangeComparator final {
     return aRange.mRangeStart <= aPos && aPos < aRange.mRangeEnd;
   }
 
   bool LessThan(const RangeT& aRange, PosT aPos) const {
     return aRange.mRangeEnd <= aPos;
   }
 };
 
-Maybe<Vector<UniqueStacks::FrameKey>>
-UniqueStacks::LookupFramesForJITAddressFromBufferPos(void* aJITAddress,
-                                                     uint64_t aBufferPos) {
-  JITFrameInfoForBufferRange* rangeIter =
-      std::lower_bound(mJITInfoRanges.begin(), mJITInfoRanges.end(), aBufferPos,
-                       [](const JITFrameInfoForBufferRange& aRange,
-                          uint64_t aPos) { return aRange.mRangeEnd < aPos; });
-  MOZ_RELEASE_ASSERT(
-      rangeIter != mJITInfoRanges.end() &&
-          rangeIter->mRangeStart <= aBufferPos &&
-          aBufferPos < rangeIter->mRangeEnd,
-      "Buffer position of jit address needs to be in one of the ranges");
-
-  using JITFrameKey = JITFrameInfoForBufferRange::JITFrameKey;
-
-  const JITFrameInfoForBufferRange& jitFrameInfoRange = *rangeIter;
-  auto jitFrameKeys =
-      jitFrameInfoRange.mJITAddressToJITFramesMap.lookup(aJITAddress);
-  if (!jitFrameKeys) {
-    return Nothing();
-  }
-
-  // Map the array of JITFrameKeys to an array of FrameKeys, and ensure that
-  // each of the FrameKeys exists in mFrameToIndexMap.
-  Vector<FrameKey> frameKeys;
-  MOZ_RELEASE_ASSERT(frameKeys.initCapacity(jitFrameKeys->value().length()));
-  for (const JITFrameKey& jitFrameKey : jitFrameKeys->value()) {
-    FrameKey frameKey(jitFrameKey.mCanonicalAddress, jitFrameKey.mDepth,
-                      rangeIter - mJITInfoRanges.begin());
-    uint32_t index = mFrameToIndexMap.count();
-    auto entry = mFrameToIndexMap.lookupForAdd(frameKey);
-    if (!entry) {
-      // We need to add this frame to our frame table. The JSON for this frame
-      // already exists in jitFrameInfoRange, we just need to splice it into
-      // the frame table and give it an index.
-      auto frameJSON =
-          jitFrameInfoRange.mJITFrameToFrameJSONMap.lookup(jitFrameKey);
-      MOZ_RELEASE_ASSERT(frameJSON, "Should have cached JSON for this frame");
-      mFrameTableWriter.Splice(frameJSON->value().get());
-      MOZ_RELEASE_ASSERT(mFrameToIndexMap.add(entry, frameKey, index));
-    }
-    MOZ_RELEASE_ASSERT(frameKeys.append(std::move(frameKey)));
-  }
-  return Some(std::move(frameKeys));
-}
-
 uint32_t UniqueStacks::GetOrAddFrameIndex(const FrameKey& aFrame) {
   uint32_t count = mFrameToIndexMap.count();
   auto entry = mFrameToIndexMap.lookupForAdd(aFrame);
   if (entry) {
     MOZ_ASSERT(entry->value() < count);
     return entry->value();
   }
 
@@ -489,218 +326,38 @@ void UniqueStacks::StreamNonJITFrame(con
     LINE = 4,
     COLUMN = 5,
     CATEGORY = 6
   };
 
   AutoArraySchemaWriter writer(mFrameTableWriter, *mUniqueStrings);
 
   const NormalFrameData& data = aFrame.mData.as<NormalFrameData>();
-  writer.StringElement(LOCATION, data.mLocation.get());
+  writer.StringElement(LOCATION, data.mLocation.c_str());
   writer.BoolElement(RELEVANT_FOR_JS, data.mRelevantForJS);
   if (data.mLine.isSome()) {
     writer.IntElement(LINE, *data.mLine);
   }
   if (data.mColumn.isSome()) {
     writer.IntElement(COLUMN, *data.mColumn);
   }
   if (data.mCategoryPair.isSome()) {
     const JS::ProfilingCategoryPairInfo& info =
-        JS::GetProfilingCategoryPairInfo(*data.mCategoryPair);
+        JS::GetBaseProfilingCategoryPairInfo(*data.mCategoryPair);
     writer.IntElement(CATEGORY, uint32_t(info.mCategory));
   }
 }
 
-static void StreamJITFrameOptimizations(
-    SpliceableJSONWriter& aWriter, UniqueJSONStrings& aUniqueStrings,
-    JSContext* aContext, const JS::ProfiledFrameHandle& aJITFrame) {
-  aWriter.StartObjectElement();
-  {
-    aWriter.StartArrayProperty("types");
-    {
-      auto op = MakeForEachTrackedOptimizationTypeInfoLambdaOp(
-          [&](JS::TrackedTypeSite site, const char* mirType,
-              const nsTArray<TypeInfo>& typeset) {
-            aWriter.StartObjectElement();
-            {
-              aUniqueStrings.WriteProperty(aWriter, "site",
-                                           JS::TrackedTypeSiteString(site));
-              aUniqueStrings.WriteProperty(aWriter, "mirType", mirType);
-
-              if (!typeset.IsEmpty()) {
-                aWriter.StartArrayProperty("typeset");
-                for (const TypeInfo& typeInfo : typeset) {
-                  aWriter.StartObjectElement();
-                  {
-                    aUniqueStrings.WriteProperty(aWriter, "keyedBy",
-                                                 typeInfo.mKeyedBy->get());
-                    if (typeInfo.mName) {
-                      aUniqueStrings.WriteProperty(aWriter, "name",
-                                                   typeInfo.mName->get());
-                    }
-                    if (typeInfo.mLocation) {
-                      aUniqueStrings.WriteProperty(aWriter, "location",
-                                                   typeInfo.mLocation->get());
-                    }
-                    if (typeInfo.mLineNumber.isSome()) {
-                      aWriter.IntProperty("line", *typeInfo.mLineNumber);
-                    }
-                  }
-                  aWriter.EndObject();
-                }
-                aWriter.EndArray();
-              }
-            }
-            aWriter.EndObject();
-          });
-      aJITFrame.forEachOptimizationTypeInfo(op);
-    }
-    aWriter.EndArray();
-
-    JS::Rooted<JSScript*> script(aContext);
-    jsbytecode* pc;
-    aWriter.StartObjectProperty("attempts");
-    {
-      {
-        JSONSchemaWriter schema(aWriter);
-        schema.WriteField("strategy");
-        schema.WriteField("outcome");
-      }
-
-      aWriter.StartArrayProperty("data");
-      {
-        auto op = MakeForEachTrackedOptimizationAttemptsLambdaOp(
-            [&](JS::TrackedStrategy strategy, JS::TrackedOutcome outcome) {
-              enum Schema : uint32_t { STRATEGY = 0, OUTCOME = 1 };
-
-              AutoArraySchemaWriter writer(aWriter, aUniqueStrings);
-              writer.StringElement(STRATEGY,
-                                   JS::TrackedStrategyString(strategy));
-              writer.StringElement(OUTCOME, JS::TrackedOutcomeString(outcome));
-            });
-        aJITFrame.forEachOptimizationAttempt(op, script.address(), &pc);
-      }
-      aWriter.EndArray();
-    }
-    aWriter.EndObject();
-
-    if (JSAtom* name = js::GetPropertyNameFromPC(script, pc)) {
-      char buf[512];
-      JS_PutEscapedFlatString(buf, ArrayLength(buf), js::AtomToFlatString(name),
-                              0);
-      aUniqueStrings.WriteProperty(aWriter, "propertyName", buf);
-    }
-
-    unsigned line, column;
-    line = JS_PCToLineNumber(script, pc, &column);
-    aWriter.IntProperty("line", line);
-    aWriter.IntProperty("column", column);
-  }
-  aWriter.EndObject();
-}
+struct CStringWriteFunc : public JSONWriteFunc {
+  std::string& mBuffer;  // The struct must not outlive this buffer
+  explicit CStringWriteFunc(std::string& aBuffer) : mBuffer(aBuffer) {}
 
-static void StreamJITFrame(JSContext* aContext, SpliceableJSONWriter& aWriter,
-                           UniqueJSONStrings& aUniqueStrings,
-                           const JS::ProfiledFrameHandle& aJITFrame) {
-  enum Schema : uint32_t {
-    LOCATION = 0,
-    RELEVANT_FOR_JS = 1,
-    IMPLEMENTATION = 2,
-    OPTIMIZATIONS = 3,
-    LINE = 4,
-    COLUMN = 5,
-    CATEGORY = 6
-  };
-
-  AutoArraySchemaWriter writer(aWriter, aUniqueStrings);
-
-  writer.StringElement(LOCATION, aJITFrame.label());
-  writer.BoolElement(RELEVANT_FOR_JS, false);
-
-  JS::ProfilingFrameIterator::FrameKind frameKind = aJITFrame.frameKind();
-  MOZ_ASSERT(frameKind == JS::ProfilingFrameIterator::Frame_Ion ||
-             frameKind == JS::ProfilingFrameIterator::Frame_Baseline);
-  writer.StringElement(
-      IMPLEMENTATION,
-      frameKind == JS::ProfilingFrameIterator::Frame_Ion ? "ion" : "baseline");
-
-  if (aJITFrame.hasTrackedOptimizations()) {
-    writer.FreeFormElement(
-        OPTIMIZATIONS,
-        [&](SpliceableJSONWriter& aWriter, UniqueJSONStrings& aUniqueStrings) {
-          StreamJITFrameOptimizations(aWriter, aUniqueStrings, aContext,
-                                      aJITFrame);
-        });
-  }
-}
-
-struct CStringWriteFunc : public JSONWriteFunc {
-  nsACString& mBuffer;  // The struct must not outlive this buffer
-  explicit CStringWriteFunc(nsACString& aBuffer) : mBuffer(aBuffer) {}
-
-  void Write(const char* aStr) override { mBuffer.Append(aStr); }
+  void Write(const char* aStr) override { mBuffer += aStr; }
 };
 
-static nsCString JSONForJITFrame(JSContext* aContext,
-                                 const JS::ProfiledFrameHandle& aJITFrame,
-                                 UniqueJSONStrings& aUniqueStrings) {
-  nsCString json;
-  SpliceableJSONWriter writer(MakeUnique<CStringWriteFunc>(json));
-  StreamJITFrame(aContext, writer, aUniqueStrings, aJITFrame);
-  return json;
-}
-
-void JITFrameInfo::AddInfoForRange(
-    uint64_t aRangeStart, uint64_t aRangeEnd, JSContext* aCx,
-    const std::function<void(const std::function<void(void*)>&)>&
-        aJITAddressProvider) {
-  if (aRangeStart == aRangeEnd) {
-    return;
-  }
-
-  MOZ_RELEASE_ASSERT(aRangeStart < aRangeEnd);
-
-  if (!mRanges.empty()) {
-    const JITFrameInfoForBufferRange& prevRange = mRanges.back();
-    MOZ_RELEASE_ASSERT(prevRange.mRangeEnd <= aRangeStart,
-                       "Ranges must be non-overlapping and added in-order.");
-  }
-
-  using JITFrameKey = JITFrameInfoForBufferRange::JITFrameKey;
-
-  JITFrameInfoForBufferRange::JITAddressToJITFramesMap jitAddressToJITFrameMap;
-  JITFrameInfoForBufferRange::JITFrameToFrameJSONMap jitFrameToFrameJSONMap;
-
-  aJITAddressProvider([&](void* aJITAddress) {
-    // Make sure that we have cached data for aJITAddress.
-    auto addressEntry = jitAddressToJITFrameMap.lookupForAdd(aJITAddress);
-    if (!addressEntry) {
-      Vector<JITFrameKey> jitFrameKeys;
-      for (JS::ProfiledFrameHandle handle :
-           JS::GetProfiledFrames(aCx, aJITAddress)) {
-        uint32_t depth = jitFrameKeys.length();
-        JITFrameKey jitFrameKey{handle.canonicalAddress(), depth};
-        auto frameEntry = jitFrameToFrameJSONMap.lookupForAdd(jitFrameKey);
-        if (!frameEntry) {
-          MOZ_RELEASE_ASSERT(jitFrameToFrameJSONMap.add(
-              frameEntry, jitFrameKey,
-              JSONForJITFrame(aCx, handle, *mUniqueStrings)));
-        }
-        MOZ_RELEASE_ASSERT(jitFrameKeys.append(jitFrameKey));
-      }
-      MOZ_RELEASE_ASSERT(jitAddressToJITFrameMap.add(addressEntry, aJITAddress,
-                                                     std::move(jitFrameKeys)));
-    }
-  });
-
-  MOZ_RELEASE_ASSERT(mRanges.append(JITFrameInfoForBufferRange{
-      aRangeStart, aRangeEnd, std::move(jitAddressToJITFrameMap),
-      std::move(jitFrameToFrameJSONMap)}));
-}
-
 struct ProfileSample {
   uint32_t mStack;
   double mTime;
   Maybe<double> mResponsiveness;
   Maybe<double> mRSS;
   Maybe<double> mUSS;
 };
 
@@ -1032,33 +689,43 @@ void ProfileBuffer::StreamSamplesToJSON(
             e.Next();
           } else {
             break;
           }
         }
         dynStrBuf[kMaxFrameKeyLength - 1] = '\0';
         bool hasDynamicString = (i != 0);
 
-        nsCString frameLabel;
+        std::string frameLabel;
         if (label[0] != '\0' && hasDynamicString) {
           if (frameFlags & uint32_t(FrameFlags::STRING_TEMPLATE_METHOD)) {
-            frameLabel.AppendPrintf("%s.%s", label, dynStrBuf.get());
+            frameLabel += label;
+            frameLabel += '.';
+            frameLabel += dynStrBuf.get();
           } else if (frameFlags &
                      uint32_t(FrameFlags::STRING_TEMPLATE_GETTER)) {
-            frameLabel.AppendPrintf("get %s.%s", label, dynStrBuf.get());
+            frameLabel += "get ";
+            frameLabel += label;
+            frameLabel += '.';
+            frameLabel += dynStrBuf.get();
           } else if (frameFlags &
                      uint32_t(FrameFlags::STRING_TEMPLATE_SETTER)) {
-            frameLabel.AppendPrintf("set %s.%s", label, dynStrBuf.get());
+            frameLabel += "set ";
+            frameLabel += label;
+            frameLabel += '.';
+            frameLabel += dynStrBuf.get();
           } else {
-            frameLabel.AppendPrintf("%s %s", label, dynStrBuf.get());
+            frameLabel += label;
+            frameLabel += ' ';
+            frameLabel += dynStrBuf.get();
           }
         } else if (hasDynamicString) {
-          frameLabel.Append(dynStrBuf.get());
+          frameLabel += dynStrBuf.get();
         } else {
-          frameLabel.Append(label);
+          frameLabel += label;
         }
 
         Maybe<unsigned> line;
         if (e.Has() && e.Get().IsLineNumber()) {
           line = Some(unsigned(e.Get().GetInt()));
           e.Next();
         }
 
@@ -1074,33 +741,16 @@ void ProfileBuffer::StreamSamplesToJSON(
               Some(JS::ProfilingCategoryPair(uint32_t(e.Get().GetInt())));
           e.Next();
         }
 
         stack = aUniqueStacks.AppendFrame(
             stack, UniqueStacks::FrameKey(std::move(frameLabel), relevantForJS,
                                           line, column, categoryPair));
 
-      } else if (e.Get().IsJitReturnAddr()) {
-        numFrames++;
-
-        // A JIT frame may expand to multiple frames due to inlining.
-        void* pc = e.Get().GetPtr();
-        const Maybe<Vector<UniqueStacks::FrameKey>>& frameKeys =
-            aUniqueStacks.LookupFramesForJITAddressFromBufferPos(pc,
-                                                                 e.CurPos());
-        MOZ_RELEASE_ASSERT(frameKeys,
-                           "Attempting to stream samples for a buffer range "
-                           "for which we don't have JITFrameInfo?");
-        for (const UniqueStacks::FrameKey& frameKey : *frameKeys) {
-          stack = aUniqueStacks.AppendFrame(stack, frameKey);
-        }
-
-        e.Next();
-
       } else {
         break;
       }
     }
 
     if (numFrames == 0) {
       // It is possible to have empty stacks if native stackwalking is
       // disabled. Skip samples with empty stacks. (See Bug 1497985).
@@ -1133,58 +783,16 @@ void ProfileBuffer::StreamSamplesToJSON(
       sample.mUSS = Some(e.Get().GetDouble());
       e.Next();
     }
 
     WriteSample(aWriter, *aUniqueStacks.mUniqueStrings, sample);
   }
 }
 
-void ProfileBuffer::AddJITInfoForRange(uint64_t aRangeStart, int aThreadId,
-                                       JSContext* aContext,
-                                       JITFrameInfo& aJITFrameInfo) const {
-  // We can only process JitReturnAddr entries if we have a JSContext.
-  MOZ_RELEASE_ASSERT(aContext);
-
-  aRangeStart = std::max(aRangeStart, mRangeStart);
-  aJITFrameInfo.AddInfoForRange(
-      aRangeStart, mRangeEnd, aContext,
-      [&](const std::function<void(void*)>& aJITAddressConsumer) {
-        // Find all JitReturnAddr entries in the given range for the given
-        // thread, and call aJITAddressConsumer with those addresses.
-
-        EntryGetter e(*this, aRangeStart);
-        while (true) {
-          // Advance to the next ThreadId entry.
-          while (e.Has() && !e.Get().IsThreadId()) {
-            e.Next();
-          }
-          if (!e.Has()) {
-            break;
-          }
-
-          MOZ_ASSERT(e.Get().IsThreadId());
-          int threadId = e.Get().GetInt();
-          e.Next();
-
-          // Ignore samples that are for a different thread.
-          if (threadId != aThreadId) {
-            continue;
-          }
-
-          while (e.Has() && !e.Get().IsThreadId()) {
-            if (e.Get().IsJitReturnAddr()) {
-              aJITAddressConsumer(e.Get().GetPtr());
-            }
-            e.Next();
-          }
-        }
-      });
-}
-
 void ProfileBuffer::StreamMarkersToJSON(SpliceableJSONWriter& aWriter,
                                         int aThreadId,
                                         const TimeStamp& aProcessStartTime,
                                         double aSinceTime,
                                         UniqueStacks& aUniqueStacks) const {
   EntryGetter e(*this);
 
   // Stream all markers whose threadId matches aThreadId. We skip other entries,
@@ -1340,18 +948,16 @@ void ProfileBuffer::StreamProfilerOverhe
 struct CounterKeyedSample {
   double mTime;
   uint64_t mNumber;
   int64_t mCount;
 };
 
 using CounterKeyedSamples = Vector<CounterKeyedSample>;
 
-static LazyLogModule sFuzzyfoxLog("Fuzzyfox");
-
 using CounterMap = HashMap<uint64_t, CounterKeyedSamples>;
 
 // HashMap lookup, if not found, a default value is inserted.
 // Returns reference to (existing or new) value inside the HashMap.
 template <typename HashM, typename Key>
 static auto& LookupOrAdd(HashM& aMap, Key&& aKey) {
   auto addPtr = aMap.lookupForAdd(aKey);
   if (!addPtr) {
@@ -1483,21 +1089,16 @@ void ProfileBuffer::StreamCountersToJSON
 
       aWriter.StartArrayProperty("data");
       uint64_t previousNumber = 0;
       int64_t previousCount = 0;
       for (size_t i = 0; i < size; i++) {
         // Encode as deltas, and only encode if different than the last sample
         if (i == 0 || samples[i].mNumber != previousNumber ||
             samples[i].mCount != previousCount) {
-          if (i != 0 && samples[i].mTime >= samples[i - 1].mTime) {
-            MOZ_LOG(sFuzzyfoxLog, mozilla::LogLevel::Error,
-                    ("Fuzzyfox Profiler Assertion: %f >= %f", samples[i].mTime,
-                     samples[i - 1].mTime));
-          }
           MOZ_ASSERT(i == 0 || samples[i].mTime >= samples[i - 1].mTime);
           MOZ_ASSERT(samples[i].mNumber >= previousNumber);
           MOZ_ASSERT(samples[i].mNumber - previousNumber <=
                      uint64_t(std::numeric_limits<int64_t>::max()));
 
           AutoArraySchemaWriter writer(aWriter);
           writer.DoubleElement(TIME, samples[i].mTime);
           writer.IntElement(NUMBER, static_cast<int64_t>(samples[i].mNumber -
--- a/mozglue/baseprofiler/core/ProfileBufferEntry.h
+++ b/mozglue/baseprofiler/core/ProfileBufferEntry.h
@@ -5,26 +5,25 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef ProfileBufferEntry_h
 #define ProfileBufferEntry_h
 
 #include "BaseProfileJSONWriter.h"
 
 #include "gtest/MozGtestFriend.h"
-#include "js/ProfilingCategory.h"
-#include "js/ProfilingFrameIterator.h"
-#include "js/TrackedOptimizationInfo.h"
+#include "BaseProfilingCategory.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 "nsString.h"
+
+#include <string>
 
 class ProfilerMarker;
 
 // NOTE!  If you add entries, you need to verify if they need to be added to the
 // switch statement in DuplicateLastSample!
 #define FOR_EACH_PROFILE_BUFFER_ENTRY_KIND(MACRO)                   \
   MACRO(CategoryPair, int)                                          \
   MACRO(CollectionStart, double)                                    \
@@ -137,182 +136,72 @@ class UniqueJSONStrings {
 
   uint32_t GetOrAddIndex(const char* aStr);
 
  private:
   SpliceableChunkedJSONWriter mStringTableWriter;
   mozilla::HashMap<mozilla::HashNumber, uint32_t> mStringHashToIndexMap;
 };
 
-// Contains all the information about JIT frames that is needed to stream stack
-// frames for JitReturnAddr entries in the profiler buffer.
-// Every return address (void*) is mapped to one or more JITFrameKeys, and
-// every JITFrameKey is mapped to a JSON string for that frame.
-// mRangeStart and mRangeEnd describe the range in the buffer for which this
-// mapping is valid. Only JitReturnAddr entries within that buffer range can be
-// processed using this JITFrameInfoForBufferRange object.
-struct JITFrameInfoForBufferRange final {
-  JITFrameInfoForBufferRange Clone() const;
-
-  uint64_t mRangeStart;
-  uint64_t mRangeEnd;  // mRangeEnd marks the first invalid index.
-
-  struct JITFrameKey {
-    bool operator==(const JITFrameKey& aOther) const {
-      return mCanonicalAddress == aOther.mCanonicalAddress &&
-             mDepth == aOther.mDepth;
-    }
-    bool operator!=(const JITFrameKey& aOther) const {
-      return !(*this == aOther);
-    }
-
-    void* mCanonicalAddress;
-    uint32_t mDepth;
-  };
-  struct JITFrameKeyHasher {
-    using Lookup = JITFrameKey;
-
-    static mozilla::HashNumber hash(const JITFrameKey& aLookup) {
-      mozilla::HashNumber hash = 0;
-      hash = mozilla::AddToHash(hash, aLookup.mCanonicalAddress);
-      hash = mozilla::AddToHash(hash, aLookup.mDepth);
-      return hash;
-    }
-
-    static bool match(const JITFrameKey& aKey, const JITFrameKey& aLookup) {
-      return aKey == aLookup;
-    }
-
-    static void rekey(JITFrameKey& aKey, const JITFrameKey& aNewKey) {
-      aKey = aNewKey;
-    }
-  };
-
-  using JITAddressToJITFramesMap =
-      mozilla::HashMap<void*, mozilla::Vector<JITFrameKey>>;
-  JITAddressToJITFramesMap mJITAddressToJITFramesMap;
-  using JITFrameToFrameJSONMap =
-      mozilla::HashMap<JITFrameKey, nsCString, JITFrameKeyHasher>;
-  JITFrameToFrameJSONMap mJITFrameToFrameJSONMap;
-};
-
-// Contains JITFrameInfoForBufferRange objects for multiple profiler buffer
-// ranges.
-struct JITFrameInfo final {
-  JITFrameInfo() : mUniqueStrings(mozilla::MakeUnique<UniqueJSONStrings>()) {}
-
-  MOZ_IMPLICIT JITFrameInfo(const JITFrameInfo& aOther);
-
-  // Creates a new JITFrameInfoForBufferRange object in mRanges by looking up
-  // information about the provided JIT return addresses using aCx.
-  // Addresses are provided like this:
-  // The caller of AddInfoForRange supplies a function in aJITAddressProvider.
-  // This function will be called once, synchronously, with an
-  // aJITAddressConsumer argument, which is a function that needs to be called
-  // for every address. That function can be called multiple times for the same
-  // address.
-  void AddInfoForRange(
-      uint64_t aRangeStart, uint64_t aRangeEnd, JSContext* aCx,
-      const std::function<void(const std::function<void(void*)>&)>&
-          aJITAddressProvider);
-
-  // Returns whether the information stored in this object is still relevant
-  // for any entries in the buffer.
-  bool HasExpired(uint64_t aCurrentBufferRangeStart) const {
-    if (mRanges.empty()) {
-      // No information means no relevant information. Allow this object to be
-      // discarded.
-      return true;
-    }
-    return mRanges.back().mRangeEnd <= aCurrentBufferRangeStart;
-  }
-
-  // The array of ranges of JIT frame information, sorted by buffer position.
-  // Ranges are non-overlapping.
-  // The JSON of the cached frames can contain string indexes, which refer
-  // to strings in mUniqueStrings.
-  mozilla::Vector<JITFrameInfoForBufferRange> mRanges;
-
-  // The string table which contains strings used in the frame JSON that's
-  // cached in mRanges.
-  mozilla::UniquePtr<UniqueJSONStrings> mUniqueStrings;
-};
-
 class UniqueStacks {
  public:
   struct FrameKey {
     explicit FrameKey(const char* aLocation)
-        : mData(NormalFrameData{nsCString(aLocation), false, mozilla::Nothing(),
-                                mozilla::Nothing()}) {}
+        : mData(NormalFrameData{std::string(aLocation), false,
+                                mozilla::Nothing(), mozilla::Nothing()}) {}
 
-    FrameKey(nsCString&& aLocation, bool aRelevantForJS,
+    FrameKey(std::string&& aLocation, bool aRelevantForJS,
              const mozilla::Maybe<unsigned>& aLine,
              const mozilla::Maybe<unsigned>& aColumn,
              const mozilla::Maybe<JS::ProfilingCategoryPair>& aCategoryPair)
         : mData(NormalFrameData{aLocation, aRelevantForJS, aLine, aColumn,
                                 aCategoryPair}) {}
 
-    FrameKey(void* aJITAddress, uint32_t aJITDepth, uint32_t aRangeIndex)
-        : mData(JITFrameData{aJITAddress, aJITDepth, aRangeIndex}) {}
-
     FrameKey(const FrameKey& aToCopy) = default;
 
     uint32_t Hash() const;
     bool operator==(const FrameKey& aOther) const {
       return mData == aOther.mData;
     }
 
     struct NormalFrameData {
       bool operator==(const NormalFrameData& aOther) const;
 
-      nsCString mLocation;
+      std::string mLocation;
       bool mRelevantForJS;
       mozilla::Maybe<unsigned> mLine;
       mozilla::Maybe<unsigned> mColumn;
       mozilla::Maybe<JS::ProfilingCategoryPair> mCategoryPair;
     };
-    struct JITFrameData {
-      bool operator==(const JITFrameData& aOther) const;
-
-      void* mCanonicalAddress;
-      uint32_t mDepth;
-      uint32_t mRangeIndex;
-    };
-    mozilla::Variant<NormalFrameData, JITFrameData> mData;
+    mozilla::Variant<NormalFrameData> mData;
   };
 
   struct FrameKeyHasher {
     using Lookup = FrameKey;
 
     static mozilla::HashNumber hash(const FrameKey& aLookup) {
       mozilla::HashNumber hash = 0;
       if (aLookup.mData.is<FrameKey::NormalFrameData>()) {
         const FrameKey::NormalFrameData& data =
             aLookup.mData.as<FrameKey::NormalFrameData>();
-        if (!data.mLocation.IsEmpty()) {
-          hash = mozilla::AddToHash(hash,
-                                    mozilla::HashString(data.mLocation.get()));
+        if (!data.mLocation.empty()) {
+          hash = mozilla::AddToHash(
+              hash, mozilla::HashString(data.mLocation.c_str()));
         }
         hash = mozilla::AddToHash(hash, data.mRelevantForJS);
         if (data.mLine.isSome()) {
           hash = mozilla::AddToHash(hash, *data.mLine);
         }
         if (data.mColumn.isSome()) {
           hash = mozilla::AddToHash(hash, *data.mColumn);
         }
         if (data.mCategoryPair.isSome()) {
           hash = mozilla::AddToHash(hash,
                                     static_cast<uint32_t>(*data.mCategoryPair));
         }
-      } else {
-        const FrameKey::JITFrameData& data =
-            aLookup.mData.as<FrameKey::JITFrameData>();
-        hash = mozilla::AddToHash(hash, data.mCanonicalAddress);
-        hash = mozilla::AddToHash(hash, data.mDepth);
-        hash = mozilla::AddToHash(hash, data.mRangeIndex);
       }
       return hash;
     }
 
     static bool match(const FrameKey& aKey, const FrameKey& aLookup) {
       return aKey == aLookup;
     }
 
@@ -356,34 +245,25 @@ class UniqueStacks {
       return aKey == aLookup;
     }
 
     static void rekey(StackKey& aKey, const StackKey& aNewKey) {
       aKey = aNewKey;
     }
   };
 
-  explicit UniqueStacks(JITFrameInfo&& aJITFrameInfo);
+  UniqueStacks();
 
   // Return a StackKey for aFrame as the stack's root frame (no prefix).
   MOZ_MUST_USE StackKey BeginStack(const FrameKey& aFrame);
 
   // Return a new StackKey that is obtained by appending aFrame to aStack.
   MOZ_MUST_USE StackKey AppendFrame(const StackKey& aStack,
                                     const FrameKey& aFrame);
 
-  // Look up frame keys for the given JIT address, and ensure that our frame
-  // table has entries for the returned frame keys. The JSON for these frames
-  // is taken from mJITInfoRanges.
-  // aBufferPosition is needed in order to look up the correct JIT frame info
-  // object in mJITInfoRanges.
-  MOZ_MUST_USE mozilla::Maybe<mozilla::Vector<UniqueStacks::FrameKey>>
-  LookupFramesForJITAddressFromBufferPos(void* aJITAddress,
-                                         uint64_t aBufferPosition);
-
   MOZ_MUST_USE uint32_t GetOrAddFrameIndex(const FrameKey& aFrame);
   MOZ_MUST_USE uint32_t GetOrAddStackIndex(const StackKey& aStack);
 
   void SpliceFrameTableElements(SpliceableJSONWriter& aWriter);
   void SpliceStackTableElements(SpliceableJSONWriter& aWriter);
 
  private:
   void StreamNonJITFrame(const FrameKey& aFrame);
@@ -393,18 +273,16 @@ class UniqueStacks {
   mozilla::UniquePtr<UniqueJSONStrings> mUniqueStrings;
 
  private:
   SpliceableChunkedJSONWriter mFrameTableWriter;
   mozilla::HashMap<FrameKey, uint32_t, FrameKeyHasher> mFrameToIndexMap;
 
   SpliceableChunkedJSONWriter mStackTableWriter;
   mozilla::HashMap<StackKey, uint32_t, StackKeyHasher> mStackToIndexMap;
-
-  mozilla::Vector<JITFrameInfoForBufferRange> mJITInfoRanges;
 };
 
 //
 // Thread profile JSON Format
 // --------------------------
 //
 // The profile contains much duplicate information. The output JSON of the
 // profile attempts to deduplicate strings, frames, and stack prefixes, to cut
--- a/mozglue/baseprofiler/core/ProfiledThreadData.cpp
+++ b/mozglue/baseprofiler/core/ProfiledThreadData.cpp
@@ -8,61 +8,31 @@
 
 #ifdef MOZ_BASE_PROFILER
 
 #  include "ProfiledThreadData.h"
 
 #  include "ProfileBuffer.h"
 #  include "BaseProfileJSONWriter.h"
 
-#  include "js/TraceLoggerAPI.h"
-#  include "mozilla/dom/ContentChild.h"
-
 #  if defined(GP_OS_darwin)
 #    include <pthread.h>
 #  endif
 
-ProfiledThreadData::ProfiledThreadData(ThreadInfo* aThreadInfo,
-                                       nsIEventTarget* aEventTarget,
-                                       bool aIncludeResponsiveness)
-    : mThreadInfo(aThreadInfo) {
-  MOZ_COUNT_CTOR(ProfiledThreadData);
-  if (aIncludeResponsiveness) {
-    mResponsiveness.emplace(aEventTarget, aThreadInfo->IsMainThread());
-  }
-}
+ProfiledThreadData::ProfiledThreadData(ThreadInfo* aThreadInfo)
+    : mThreadInfo(aThreadInfo) {}
 
-ProfiledThreadData::~ProfiledThreadData() {
-  MOZ_COUNT_DTOR(ProfiledThreadData);
-}
+ProfiledThreadData::~ProfiledThreadData() {}
 
 void ProfiledThreadData::StreamJSON(const ProfileBuffer& aBuffer,
-                                    JSContext* aCx,
                                     SpliceableJSONWriter& aWriter,
-                                    const nsACString& aProcessName,
+                                    const std::string& aProcessName,
                                     const mozilla::TimeStamp& aProcessStartTime,
-                                    double aSinceTime, bool JSTracerEnabled) {
-  if (mJITFrameInfoForPreviousJSContexts &&
-      mJITFrameInfoForPreviousJSContexts->HasExpired(aBuffer.mRangeStart)) {
-    mJITFrameInfoForPreviousJSContexts = nullptr;
-  }
-
-  // If we have an existing JITFrameInfo in mJITFrameInfoForPreviousJSContexts,
-  // copy the data from it.
-  JITFrameInfo jitFrameInfo =
-      mJITFrameInfoForPreviousJSContexts
-          ? JITFrameInfo(*mJITFrameInfoForPreviousJSContexts)
-          : JITFrameInfo();
-
-  if (aCx && mBufferPositionWhenReceivedJSContext) {
-    aBuffer.AddJITInfoForRange(*mBufferPositionWhenReceivedJSContext,
-                               mThreadInfo->ThreadId(), aCx, jitFrameInfo);
-  }
-
-  UniqueStacks uniqueStacks(std::move(jitFrameInfo));
+                                    double aSinceTime) {
+  UniqueStacks uniqueStacks;
 
   aWriter.Start();
   {
     StreamSamplesAndMarkers(mThreadInfo->Name(), mThreadInfo->ThreadId(),
                             aBuffer, aWriter, aProcessName, aProcessStartTime,
                             mThreadInfo->RegisterTime(), mUnregisterTime,
                             aSinceTime, uniqueStacks);
 
@@ -99,131 +69,36 @@ void ProfiledThreadData::StreamJSON(cons
     }
     aWriter.EndObject();
 
     aWriter.StartArrayProperty("stringTable");
     { uniqueStacks.mUniqueStrings->SpliceStringTableElements(aWriter); }
     aWriter.EndArray();
   }
 
-  if (aCx && JSTracerEnabled) {
-    StreamTraceLoggerJSON(aCx, aWriter, aProcessStartTime);
-  }
-
   aWriter.End();
 }
 
-void ProfiledThreadData::StreamTraceLoggerJSON(
-    JSContext* aCx, SpliceableJSONWriter& aWriter,
-    const mozilla::TimeStamp& aProcessStartTime) {
-  aWriter.StartObjectProperty("jsTracerEvents");
-  {
-    JS::AutoTraceLoggerLockGuard lockGuard;
-    JS::SpewTraceLoggerThread(aCx);
-
-    uint32_t length = 0;
-
-    // Collect Event Ids
-    aWriter.StartArrayProperty("events", mozilla::JSONWriter::SingleLineStyle);
-    {
-      JS::TraceLoggerIdBuffer collectionBuffer(lockGuard, aCx);
-      while (collectionBuffer.NextChunk()) {
-        for (uint32_t val : collectionBuffer) {
-          aWriter.IntElement(val);
-          length++;
-        }
-      }
-    }
-    aWriter.EndArray();
-
-    // Collect Event Timestamps
-    aWriter.StartArrayProperty("timestamps",
-                               mozilla::JSONWriter::SingleLineStyle);
-    {
-      JS::TraceLoggerTimeStampBuffer collectionBuffer(lockGuard, aCx);
-      while (collectionBuffer.NextChunk()) {
-        for (mozilla::TimeStamp val : collectionBuffer) {
-          aWriter.DoubleElement((val - aProcessStartTime).ToMicroseconds());
-        }
-      }
-    }
-    aWriter.EndArray();
-
-    // Collect Event Durations
-    aWriter.StartArrayProperty("durations",
-                               mozilla::JSONWriter::SingleLineStyle);
-    {
-      JS::TraceLoggerDurationBuffer collectionBuffer(lockGuard, aCx);
-      while (collectionBuffer.NextChunk()) {
-        for (double val : collectionBuffer) {
-          if (val == -1) {
-            aWriter.NullElement();
-          } else {
-            aWriter.DoubleElement(val);
-          }
-        }
-      }
-    }
-    aWriter.EndArray();
-
-    // Collect Event LineNo
-    aWriter.StartArrayProperty("line", mozilla::JSONWriter::SingleLineStyle);
-    {
-      JS::TraceLoggerLineNoBuffer collectionBuffer(lockGuard, aCx);
-      while (collectionBuffer.NextChunk()) {
-        for (int32_t val : collectionBuffer) {
-          if (val == -1) {
-            aWriter.NullElement();
-          } else {
-            aWriter.IntElement(val);
-          }
-        }
-      }
-    }
-    aWriter.EndArray();
-
-    // Collect Event ColNo
-    aWriter.StartArrayProperty("column", mozilla::JSONWriter::SingleLineStyle);
-    {
-      JS::TraceLoggerColNoBuffer collectionBuffer(lockGuard, aCx);
-      while (collectionBuffer.NextChunk()) {
-        for (int32_t val : collectionBuffer) {
-          if (val == -1) {
-            aWriter.NullElement();
-          } else {
-            aWriter.IntElement(val);
-          }
-        }
-      }
-    }
-    aWriter.EndArray();
-
-    aWriter.IntProperty("length", length);
-  }
-  aWriter.EndObject();
-}
-
 void StreamSamplesAndMarkers(const char* aName, int aThreadId,
                              const ProfileBuffer& aBuffer,
                              SpliceableJSONWriter& aWriter,
-                             const nsACString& aProcessName,
+                             const std::string& aProcessName,
                              const mozilla::TimeStamp& aProcessStartTime,
                              const mozilla::TimeStamp& aRegisterTime,
                              const mozilla::TimeStamp& aUnregisterTime,
                              double aSinceTime, UniqueStacks& aUniqueStacks) {
-  aWriter.StringProperty("processType",
-                         XRE_ChildProcessTypeToString(XRE_GetProcessType()));
+  aWriter.StringProperty(
+      "processType",
+      "(unknown)" /* XRE_ChildProcessTypeToString(XRE_GetProcessType()) */);
 
   aWriter.StringProperty("name", aName);
 
-  // Use given process name (if any), unless we're the parent process.
-  if (XRE_IsParentProcess()) {
-    aWriter.StringProperty("processName", "Parent Process");
-  } else if (!aProcessName.IsEmpty()) {
-    aWriter.StringProperty("processName", aProcessName.Data());
+  // Use given process name (if any).
+  if (!aProcessName.empty()) {
+    aWriter.StringProperty("processName", aProcessName.c_str());
   }
 
   aWriter.IntProperty("tid", static_cast<int64_t>(aThreadId));
   aWriter.IntProperty("pid",
                       static_cast<int64_t>(profiler_current_process_id()));
 
   if (aRegisterTime) {
     aWriter.DoubleProperty(
@@ -275,35 +150,9 @@ void StreamSamplesAndMarkers(const char*
       aBuffer.StreamMarkersToJSON(aWriter, aThreadId, aProcessStartTime,
                                   aSinceTime, aUniqueStacks);
     }
     aWriter.EndArray();
   }
   aWriter.EndObject();
 }
 
-void ProfiledThreadData::NotifyAboutToLoseJSContext(
-    JSContext* aContext, const mozilla::TimeStamp& aProcessStartTime,
-    ProfileBuffer& aBuffer) {
-  if (!mBufferPositionWhenReceivedJSContext) {
-    return;
-  }
-
-  MOZ_RELEASE_ASSERT(aContext);
-
-  if (mJITFrameInfoForPreviousJSContexts &&
-      mJITFrameInfoForPreviousJSContexts->HasExpired(aBuffer.mRangeStart)) {
-    mJITFrameInfoForPreviousJSContexts = nullptr;
-  }
-
-  mozilla::UniquePtr<JITFrameInfo> jitFrameInfo =
-      mJITFrameInfoForPreviousJSContexts
-          ? std::move(mJITFrameInfoForPreviousJSContexts)
-          : mozilla::MakeUnique<JITFrameInfo>();
-
-  aBuffer.AddJITInfoForRange(*mBufferPositionWhenReceivedJSContext,
-                             mThreadInfo->ThreadId(), aContext, *jitFrameInfo);
-
-  mJITFrameInfoForPreviousJSContexts = std::move(jitFrameInfo);
-  mBufferPositionWhenReceivedJSContext = mozilla::Nothing();
-}
-
 #endif  // MOZ_BASE_PROFILER
--- a/mozglue/baseprofiler/core/ProfiledThreadData.h
+++ b/mozglue/baseprofiler/core/ProfiledThreadData.h
@@ -2,25 +2,27 @@
 /* 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 ProfiledThreadData_h
 #define ProfiledThreadData_h
 
+#include "BaseProfilingStack.h"
 #include "platform.h"
 #include "ProfileBufferEntry.h"
 #include "ThreadInfo.h"
-#include "ThreadResponsiveness.h"
 
-#include "js/ProfilingStack.h"
+#include "mozilla/RefPtr.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/UniquePtr.h"
 
+#include <string>
+
 class ProfileBuffer;
 
 // This class contains information about a thread that is only relevant while
 // the profiler is running, for any threads (both alive and dead) whose thread
 // name matches the "thread filter" in the current profiler run.
 // ProfiledThreadData objects may be kept alive even after the thread is
 // unregistered, as long as there is still data for that thread in the profiler
 // buffer.
@@ -38,85 +40,57 @@ class ProfileBuffer;
 // The thread may be unregistered during the lifetime of ProfiledThreadData.
 // If that happens, NotifyUnregistered() is called.
 //
 // This class is the right place to store buffer positions. Profiler buffer
 // positions become invalid if the profiler buffer is destroyed, which happens
 // when the profiler is stopped.
 class ProfiledThreadData final {
  public:
-  ProfiledThreadData(ThreadInfo* aThreadInfo, nsIEventTarget* aEventTarget,
-                     bool aIncludeResponsiveness);
+  explicit ProfiledThreadData(ThreadInfo* aThreadInfo);
   ~ProfiledThreadData();
 
   void NotifyUnregistered(uint64_t aBufferPosition) {
-    mResponsiveness.reset();
     mLastSample = mozilla::Nothing();
     MOZ_ASSERT(!mBufferPositionWhenReceivedJSContext,
                "JSContext should have been cleared before the thread was "
                "unregistered");
     mUnregisterTime = mozilla::TimeStamp::Now();
     mBufferPositionWhenUnregistered = mozilla::Some(aBufferPosition);
   }
   mozilla::Maybe<uint64_t> BufferPositionWhenUnregistered() {
     return mBufferPositionWhenUnregistered;
   }
 
   mozilla::Maybe<uint64_t>& LastSample() { return mLastSample; }
 
-  void StreamJSON(const ProfileBuffer& aBuffer, JSContext* aCx,
-                  SpliceableJSONWriter& aWriter, const nsACString& aProcessName,
+  void StreamJSON(const ProfileBuffer& aBuffer, SpliceableJSONWriter& aWriter,
+                  const std::string& aProcessName,
                   const mozilla::TimeStamp& aProcessStartTime,
-                  double aSinceTime, bool aJSTracerEnabled);
-
-  void StreamTraceLoggerJSON(JSContext* aCx, SpliceableJSONWriter& aWriter,
-                             const mozilla::TimeStamp& aProcessStartTime);
-
-  // Returns nullptr if this is not the main thread, the responsiveness
-  // feature is not turned on, or if this thread is not being profiled.
-  ThreadResponsiveness* GetThreadResponsiveness() {
-    ThreadResponsiveness* responsiveness = mResponsiveness.ptrOr(nullptr);
-    return responsiveness;
-  }
+                  double aSinceTime);
 
   const RefPtr<ThreadInfo> Info() const { return mThreadInfo; }
 
   void NotifyReceivedJSContext(uint64_t aCurrentBufferPosition) {
     mBufferPositionWhenReceivedJSContext =
         mozilla::Some(aCurrentBufferPosition);
   }
 
-  // Call this method when the JS entries inside the buffer are about to
-  // become invalid, i.e., just before JS shutdown.
-  void NotifyAboutToLoseJSContext(JSContext* aCx,
-                                  const mozilla::TimeStamp& aProcessStartTime,
-                                  ProfileBuffer& aBuffer);
-
  private:
   // Group A:
   // The following fields are interesting for the entire lifetime of a
   // ProfiledThreadData object.
 
   // This thread's thread info.
   const RefPtr<ThreadInfo> mThreadInfo;
 
-  // Contains JSON for JIT frames from any JSContexts that were used for this
-  // thread in the past.
-  // Null if this thread has never lost a JSContext or if all samples from
-  // previous JSContexts have been evicted from the profiler buffer.
-  mozilla::UniquePtr<JITFrameInfo> mJITFrameInfoForPreviousJSContexts;
-
   // Group B:
   // The following fields are only used while this thread is alive and
   // registered. They become Nothing() once the thread is unregistered.
 
-  // A helper object that instruments nsIThreads to obtain responsiveness
-  // information about their event loop.
-  mozilla::Maybe<ThreadResponsiveness> mResponsiveness;
-
   // When sampling, this holds the position in ActivePS::mBuffer of the most
   // recent sample for this thread, or Nothing() if there is no sample for this
   // thread in the buffer.
   mozilla::Maybe<uint64_t> mLastSample;
 
   // Only non-Nothing() if the thread currently has a JSContext.
   mozilla::Maybe<uint64_t> mBufferPositionWhenReceivedJSContext;
 
@@ -125,15 +99,15 @@ class ProfiledThreadData final {
 
   mozilla::Maybe<uint64_t> mBufferPositionWhenUnregistered;
   mozilla::TimeStamp mUnregisterTime;
 };
 
 void StreamSamplesAndMarkers(const char* aName, int aThreadId,
                              const ProfileBuffer& aBuffer,
                              SpliceableJSONWriter& aWriter,
-                             const nsACString& aProcessName,
+                             const std::string& aProcessName,
                              const mozilla::TimeStamp& aProcessStartTime,
                              const mozilla::TimeStamp& aRegisterTime,
                              const mozilla::TimeStamp& aUnregisterTime,
                              double aSinceTime, UniqueStacks& aUniqueStacks);
 
 #endif  // ProfiledThreadData_h
--- a/mozglue/baseprofiler/core/ProfilerBacktrace.cpp
+++ b/mozglue/baseprofiler/core/ProfilerBacktrace.cpp
@@ -12,29 +12,27 @@
 
 #  include "ProfileBuffer.h"
 #  include "ProfiledThreadData.h"
 #  include "BaseProfileJSONWriter.h"
 #  include "ThreadInfo.h"
 
 ProfilerBacktrace::ProfilerBacktrace(const char* aName, int aThreadId,
                                      mozilla::UniquePtr<ProfileBuffer> aBuffer)
-    : mName(strdup(aName)), mThreadId(aThreadId), mBuffer(std::move(aBuffer)) {
-  MOZ_COUNT_CTOR(ProfilerBacktrace);
-}
+    : mName(strdup(aName)), mThreadId(aThreadId), mBuffer(std::move(aBuffer)) {}
 
-ProfilerBacktrace::~ProfilerBacktrace() { MOZ_COUNT_DTOR(ProfilerBacktrace); }
+ProfilerBacktrace::~ProfilerBacktrace() {}
 
 void ProfilerBacktrace::StreamJSON(SpliceableJSONWriter& aWriter,
                                    const mozilla::TimeStamp& aProcessStartTime,
                                    UniqueStacks& aUniqueStacks) {
   // Unlike ProfiledThreadData::StreamJSON, we don't need to call
   // ProfileBuffer::AddJITInfoForRange because mBuffer does not contain any
   // JitReturnAddr entries. For synchronous samples, JIT frames get expanded
   // at sample time.
-  StreamSamplesAndMarkers(mName.get(), mThreadId, *mBuffer.get(), aWriter,
-                          NS_LITERAL_CSTRING(""), aProcessStartTime,
+  StreamSamplesAndMarkers(mName.get(), mThreadId, *mBuffer.get(), aWriter, "",
+                          aProcessStartTime,
                           /* aRegisterTime */ mozilla::TimeStamp(),
                           /* aUnregisterTime */ mozilla::TimeStamp(),
                           /* aSinceTime */ 0, aUniqueStacks);
 }
 
 #endif  // MOZ_BASE_PROFILER
--- a/mozglue/baseprofiler/core/ProfilerMarker.h
+++ b/mozglue/baseprofiler/core/ProfilerMarker.h
@@ -51,17 +51,17 @@ class ProfilerMarker {
     // Schema:
     //   [name, time, category, data]
 
     aWriter.StartArrayElement();
     {
       aUniqueStacks.mUniqueStrings->WriteElement(aWriter, mMarkerName.get());
       aWriter.DoubleElement(mTime);
       const JS::ProfilingCategoryPairInfo& info =
-          JS::GetProfilingCategoryPairInfo(mCategoryPair);
+          JS::GetBaseProfilingCategoryPairInfo(mCategoryPair);
       aWriter.IntElement(unsigned(info.mCategory));
       // TODO: Store the callsite for this marker if available:
       // if have location data
       //   b.NameValue(marker, "location", ...);
       if (mPayload) {
         aWriter.StartObjectElement(SpliceableJSONWriter::SingleLineStyle);
         { mPayload->StreamPayload(aWriter, aProcessStartTime, aUniqueStacks); }
         aWriter.EndObject();
--- a/mozglue/baseprofiler/core/ProfilerMarkerPayload.cpp
+++ b/mozglue/baseprofiler/core/ProfilerMarkerPayload.cpp
@@ -8,20 +8,17 @@
 #ifdef MOZ_BASE_PROFILER
 
 #  include "BaseProfilerMarkerPayload.h"
 
 #  include "ProfileBufferEntry.h"
 #  include "BaseProfileJSONWriter.h"
 #  include "ProfilerBacktrace.h"
 
-#  include "gfxASurface.h"
-#  include "Layers.h"
 #  include "mozilla/Maybe.h"
-#  include "mozilla/net/HttpBaseChannel.h"
 #  include "mozilla/Sprintf.h"
 
 #  include <inttypes.h>
 
 using namespace mozilla;
 
 static void MOZ_ALWAYS_INLINE WriteTime(SpliceableJSONWriter& aWriter,
                                         const TimeStamp& aProcessStartTime,
@@ -40,17 +37,17 @@ void ProfilerMarkerPayload::StreamType(c
 
 void ProfilerMarkerPayload::StreamCommonProps(
     const char* aMarkerType, SpliceableJSONWriter& aWriter,
     const TimeStamp& aProcessStartTime, UniqueStacks& aUniqueStacks) {
   StreamType(aMarkerType, aWriter);
   WriteTime(aWriter, aProcessStartTime, mStartTime, "startTime");
   WriteTime(aWriter, aProcessStartTime, mEndTime, "endTime");
   if (mDocShellId) {
-    aWriter.StringProperty("docShellId", nsIDToCString(*mDocShellId).get());
+    aWriter.StringProperty("docShellId", mDocShellId->c_str());
   }
   if (mDocShellHistoryId) {
     aWriter.DoubleProperty("docshellHistoryId", mDocShellHistoryId.ref());
   }
   if (mStack) {
     aWriter.StartObjectProperty("stack");
     { mStack->StreamJSON(aWriter, aProcessStartTime, aUniqueStacks); }
     aWriter.EndObject();
@@ -83,220 +80,53 @@ void FileIOMarkerPayload::StreamPayload(
     aWriter.StringProperty("filename", mFilename.get());
   }
 }
 
 void UserTimingMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
                                             const TimeStamp& aProcessStartTime,
                                             UniqueStacks& aUniqueStacks) {
   StreamCommonProps("UserTiming", aWriter, aProcessStartTime, aUniqueStacks);
-  aWriter.StringProperty("name", NS_ConvertUTF16toUTF8(mName).get());
+  aWriter.StringProperty("name", mName.c_str());
   aWriter.StringProperty("entryType", mEntryType);
 
   if (mStartMark.isSome()) {
-    aWriter.StringProperty("startMark",
-                           NS_ConvertUTF16toUTF8(mStartMark.value()).get());
+    aWriter.StringProperty("startMark", mStartMark.value().c_str());
   } else {
     aWriter.NullProperty("startMark");
   }
   if (mEndMark.isSome()) {
-    aWriter.StringProperty("endMark",
-                           NS_ConvertUTF16toUTF8(mEndMark.value()).get());
+    aWriter.StringProperty("endMark", mEndMark.value().c_str());
   } else {
     aWriter.NullProperty("endMark");
   }
 }
 
 void TextMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
                                       const TimeStamp& aProcessStartTime,
                                       UniqueStacks& aUniqueStacks) {
   StreamCommonProps("Text", aWriter, aProcessStartTime, aUniqueStacks);
-  aWriter.StringProperty("name", mText.get());
+  aWriter.StringProperty("name", mText.c_str());
 }
 
 void LogMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
                                      const TimeStamp& aProcessStartTime,
                                      UniqueStacks& aUniqueStacks) {
   StreamCommonProps("Log", aWriter, aProcessStartTime, aUniqueStacks);
-  aWriter.StringProperty("name", mText.get());
-  aWriter.StringProperty("module", mModule.get());
-}
-
-void DOMEventMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
-                                          const TimeStamp& aProcessStartTime,
-                                          UniqueStacks& aUniqueStacks) {
-  TracingMarkerPayload::StreamPayload(aWriter, aProcessStartTime,
-                                      aUniqueStacks);
-
-  WriteTime(aWriter, aProcessStartTime, mTimeStamp, "timeStamp");
-  aWriter.StringProperty("eventType", NS_ConvertUTF16toUTF8(mEventType).get());
-}
-
-void LayerTranslationMarkerPayload::StreamPayload(
-    SpliceableJSONWriter& aWriter, const TimeStamp& aProcessStartTime,
-    UniqueStacks& aUniqueStacks) {
-  StreamType("LayerTranslation", aWriter);
-  const size_t bufferSize = 32;
-  char buffer[bufferSize];
-  SprintfLiteral(buffer, "%p", mLayer);
-
-  aWriter.StringProperty("layer", buffer);
-  aWriter.IntProperty("x", mPoint.x);
-  aWriter.IntProperty("y", mPoint.y);
-}
-
-void VsyncMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
-                                       const TimeStamp& aProcessStartTime,
-                                       UniqueStacks& aUniqueStacks) {
-  StreamType("VsyncTimestamp", aWriter);
-}
-
-static const char* GetNetworkState(NetworkLoadType aType) {
-  switch (aType) {
-    case NetworkLoadType::LOAD_START:
-      return "STATUS_START";
-    case NetworkLoadType::LOAD_STOP:
-      return "STATUS_STOP";
-    case NetworkLoadType::LOAD_REDIRECT:
-      return "STATUS_REDIRECT";
-  }
-  return "";
-}
-
-static const char* GetCacheState(
-    mozilla::net::CacheDisposition aCacheDisposition) {
-  switch (aCacheDisposition) {
-    case mozilla::net::kCacheUnresolved:
-      return "Unresolved";
-    case mozilla::net::kCacheHit:
-      return "Hit";
-    case mozilla::net::kCacheHitViaReval:
-      return "HitViaReval";
-    case mozilla::net::kCacheMissedViaReval:
-      return "MissedViaReval";
-    case mozilla::net::kCacheMissed:
-      return "Missed";
-    case mozilla::net::kCacheUnknown:
-    default:
-      return nullptr;
-  }
-}
-
-void NetworkMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
-                                         const TimeStamp& aProcessStartTime,
-                                         UniqueStacks& aUniqueStacks) {
-  StreamCommonProps("Network", aWriter, aProcessStartTime, aUniqueStacks);
-  aWriter.IntProperty("id", mID);
-  const char* typeString = GetNetworkState(mType);
-  const char* cacheString = GetCacheState(mCacheDisposition);
-  // want to use aUniqueStacks.mUniqueStrings->WriteElement(aWriter,
-  // typeString);
-  aWriter.StringProperty("status", typeString);
-  if (cacheString) {
-    aWriter.StringProperty("cache", cacheString);
-  }
-  aWriter.IntProperty("pri", mPri);
-  if (mCount > 0) {
-    aWriter.IntProperty("count", mCount);
-  }
-  if (mURI) {
-    aWriter.StringProperty("URI", mURI.get());
-  }
-  if (mRedirectURI) {
-    aWriter.StringProperty("RedirectURI", mRedirectURI.get());
-  }
-  if (mType != NetworkLoadType::LOAD_START) {
-    WriteTime(aWriter, aProcessStartTime, mTimings.domainLookupStart,
-              "domainLookupStart");
-    WriteTime(aWriter, aProcessStartTime, mTimings.domainLookupEnd,
-              "domainLookupEnd");
-    WriteTime(aWriter, aProcessStartTime, mTimings.connectStart,
-              "connectStart");
-    WriteTime(aWriter, aProcessStartTime, mTimings.tcpConnectEnd,
-              "tcpConnectEnd");
-    WriteTime(aWriter, aProcessStartTime, mTimings.secureConnectionStart,
-              "secureConnectionStart");
-    WriteTime(aWriter, aProcessStartTime, mTimings.connectEnd, "connectEnd");
-    WriteTime(aWriter, aProcessStartTime, mTimings.requestStart,
-              "requestStart");
-    WriteTime(aWriter, aProcessStartTime, mTimings.responseStart,
-              "responseStart");
-    WriteTime(aWriter, aProcessStartTime, mTimings.responseEnd, "responseEnd");
-  }
-}
-
-void ScreenshotPayload::StreamPayload(SpliceableJSONWriter& aWriter,
-                                      const TimeStamp& aProcessStartTime,
-                                      UniqueStacks& aUniqueStacks) {
-  StreamType("CompositorScreenshot", aWriter);
-  aUniqueStacks.mUniqueStrings->WriteProperty(aWriter, "url",
-                                              mScreenshotDataURL.get());
-
-  char hexWindowID[32];
-  SprintfLiteral(hexWindowID, "0x%" PRIXPTR, mWindowIdentifier);
-  aWriter.StringProperty("windowID", hexWindowID);
-  aWriter.DoubleProperty("windowWidth", mWindowSize.width);
-  aWriter.DoubleProperty("windowHeight", mWindowSize.height);
-}
-
-void GCSliceMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
-                                         const TimeStamp& aProcessStartTime,
-                                         UniqueStacks& aUniqueStacks) {
-  MOZ_ASSERT(mTimingJSON);
-  StreamCommonProps("GCSlice", aWriter, aProcessStartTime, aUniqueStacks);
-  if (mTimingJSON) {
-    aWriter.SplicedJSONProperty("timings", mTimingJSON.get());
-  } else {
-    aWriter.NullProperty("timings");
-  }
-}
-
-void GCMajorMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
-                                         const TimeStamp& aProcessStartTime,
-                                         UniqueStacks& aUniqueStacks) {
-  MOZ_ASSERT(mTimingJSON);
-  StreamCommonProps("GCMajor", aWriter, aProcessStartTime, aUniqueStacks);
-  if (mTimingJSON) {
-    aWriter.SplicedJSONProperty("timings", mTimingJSON.get());
-  } else {
-    aWriter.NullProperty("timings");
-  }
-}
-
-void GCMinorMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
-                                         const TimeStamp& aProcessStartTime,
-                                         UniqueStacks& aUniqueStacks) {
-  MOZ_ASSERT(mTimingData);
-  StreamCommonProps("GCMinor", aWriter, aProcessStartTime, aUniqueStacks);
-  if (mTimingData) {
-    aWriter.SplicedJSONProperty("nursery", mTimingData.get());
-  } else {
-    aWriter.NullProperty("nursery");
-  }
+  aWriter.StringProperty("name", mText.c_str());
+  aWriter.StringProperty("module", mModule.c_str());
 }
 
 void HangMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
                                       const TimeStamp& aProcessStartTime,
                                       UniqueStacks& aUniqueStacks) {
   StreamCommonProps("BHR-detected hang", aWriter, aProcessStartTime,
                     aUniqueStacks);
 }
 
-void StyleMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
-                                       const TimeStamp& aProcessStartTime,
-                                       UniqueStacks& aUniqueStacks) {
-  StreamCommonProps("Styles", aWriter, aProcessStartTime, aUniqueStacks);
-  aWriter.StringProperty("category", "Paint");
-  aWriter.IntProperty("elementsTraversed", mStats.mElementsTraversed);
-  aWriter.IntProperty("elementsStyled", mStats.mElementsStyled);
-  aWriter.IntProperty("elementsMatched", mStats.mElementsMatched);
-  aWriter.IntProperty("stylesShared", mStats.mStylesShared);
-  aWriter.IntProperty("stylesReused", mStats.mStylesReused);
-}
-
 void LongTaskMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
                                           const TimeStamp& aProcessStartTime,
                                           UniqueStacks& aUniqueStacks) {
   StreamCommonProps("MainThreadLongTask", aWriter, aProcessStartTime,
                     aUniqueStacks);
   aWriter.StringProperty("category", "LongTask");
 }
 
--- a/mozglue/baseprofiler/core/ProfilingCategory.cpp
+++ b/mozglue/baseprofiler/core/ProfilingCategory.cpp
@@ -3,526 +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 "BaseProfiler.h"
 
 #ifdef MOZ_BASE_PROFILER
 
-#  include "vm/GeckoProfiler-inl.h"
+#  include "BaseProfilingCategory.h"
 
 #  include "mozilla/ArrayUtils.h"
-#  include "mozilla/DebugOnly.h"
-#  include "mozilla/Sprintf.h"
-
-#  include "jsnum.h"
-
-#  include "gc/GC.h"
-#  include "gc/PublicIterators.h"
-#  include "jit/BaselineFrame.h"
-#  include "jit/BaselineJIT.h"
-#  include "jit/JitcodeMap.h"
-#  include "jit/JitFrames.h"
-#  include "jit/JitRealm.h"
-#  include "jit/JSJitFrameIter.h"
-#  include "js/TraceLoggerAPI.h"
-#  include "util/StringBuffer.h"
-#  include "vm/JSScript.h"
-
-#  include "gc/Marking-inl.h"
-#  include "vm/JSScript-inl.h"
-
-using namespace js;
-
-using mozilla::DebugOnly;
-
-GeckoProfilerThread::GeckoProfilerThread()
-    : profilingStack_(nullptr), profilingStackIfEnabled_(nullptr) {}
-
-GeckoProfilerRuntime::GeckoProfilerRuntime(JSRuntime* rt)
-    : rt(rt),
-      strings_(),
-      slowAssertions(false),
-      enabled_(false),
-      eventMarker_(nullptr) {
-  MOZ_ASSERT(rt != nullptr);
-}
-
-void GeckoProfilerThread::setProfilingStack(ProfilingStack* profilingStack,
-                                            bool enabled) {
-  profilingStack_ = profilingStack;
-  profilingStackIfEnabled_ = enabled ? profilingStack : nullptr;
-}
-
-void GeckoProfilerRuntime::setEventMarker(void (*fn)(const char*)) {
-  eventMarker_ = fn;
-}
-
-// Get a pointer to the top-most profiling frame, given the exit frame pointer.
-static void* GetTopProfilingJitFrame(Activation* act) {
-  if (!act || !act->isJit()) {
-    return nullptr;
-  }
-
-  jit::JitActivation* jitActivation = act->asJit();
-
-  // If there is no exit frame set, just return.
-  if (!jitActivation->hasExitFP()) {
-    return nullptr;
-  }
-
-  // Skip wasm frames that might be in the way.
-  OnlyJSJitFrameIter iter(jitActivation);
-  if (iter.done()) {
-    return nullptr;
-  }
-
-  jit::JSJitProfilingFrameIterator jitIter(
-      (jit::CommonFrameLayout*)iter.frame().fp());
-  MOZ_ASSERT(!jitIter.done());
-  return jitIter.fp();
-}
-
-void GeckoProfilerRuntime::enable(bool enabled) {
-  JSContext* cx = rt->mainContextFromAnyThread();
-  MOZ_ASSERT(cx->geckoProfiler().infraInstalled());
-
-  if (enabled_ == enabled) {
-    return;
-  }
-
-  /*
-   * Ensure all future generated code will be instrumented, or that all
-   * currently instrumented code is discarded
-   */
-  ReleaseAllJITCode(rt->defaultFreeOp());
-
-  // This function is called when the Gecko profiler makes a new Sampler
-  // (and thus, a new circular buffer). Set all current entries in the
-  // JitcodeGlobalTable as expired and reset the buffer range start.
-  if (rt->hasJitRuntime() && rt->jitRuntime()->hasJitcodeGlobalTable()) {
-    rt->jitRuntime()->getJitcodeGlobalTable()->setAllEntriesAsExpired();
-  }
-  rt->setProfilerSampleBufferRangeStart(0);
-
-  // Ensure that lastProfilingFrame is null for the main thread.
-  if (cx->jitActivation) {
-    cx->jitActivation->setLastProfilingFrame(nullptr);
-    cx->jitActivation->setLastProfilingCallSite(nullptr);
-  }
-
-  // Reset the tracelogger, if toggled on
-  JS::ResetTraceLogger();
-
-  enabled_ = enabled;
-
-  /* Toggle Gecko Profiler-related jumps on baseline jitcode.
-   * The call to |ReleaseAllJITCode| above will release most baseline jitcode,
-   * but not jitcode for scripts with active frames on the stack.  These scripts
-   * need to have their profiler state toggled so they behave properly.
-   */
-  jit::ToggleBaselineProfiling(rt, enabled);
-
-  // Update lastProfilingFrame to point to the top-most JS jit-frame currently
-  // on stack.
-  if (cx->jitActivation) {
-    // Walk through all activations, and set their lastProfilingFrame
-    // appropriately.
-    if (enabled) {
-      Activation* act = cx->activation();
-      void* lastProfilingFrame = GetTopProfilingJitFrame(act);
-
-      jit::JitActivation* jitActivation = cx->jitActivation;
-      while (jitActivation) {
-        jitActivation->setLastProfilingFrame(lastProfilingFrame);
-        jitActivation->setLastProfilingCallSite(nullptr);
-
-        jitActivation = jitActivation->prevJitActivation();
-        lastProfilingFrame = GetTopProfilingJitFrame(jitActivation);
-      }
-    } else {
-      jit::JitActivation* jitActivation = cx->jitActivation;
-      while (jitActivation) {
-        jitActivation->setLastProfilingFrame(nullptr);
-        jitActivation->setLastProfilingCallSite(nullptr);
-        jitActivation = jitActivation->prevJitActivation();
-      }
-    }
-  }
-
-  // WebAssembly code does not need to be released, but profiling string
-  // labels have to be generated so that they are available during async
-  // profiling stack iteration.
-  for (RealmsIter r(rt); !r.done(); r.next()) {
-    r->wasm.ensureProfilingLabels(enabled);
-  }
-
-#  ifdef JS_STRUCTURED_SPEW
-  // Enable the structured spewer if the environment variable is set.
-  if (enabled) {
-    cx->spewer().enableSpewing();
-  } else {
-    cx->spewer().disableSpewing();
-  }
-#  endif
-}
-
-/* Lookup the string for the function/script, creating one if necessary */
-const char* GeckoProfilerRuntime::profileString(JSContext* cx,
-                                                JSScript* script) {
-  ProfileStringMap::AddPtr s = strings().lookupForAdd(script);
-
-  if (!s) {
-    UniqueChars str = allocProfileString(cx, script);
-    if (!str) {
-      return nullptr;
-    }
-    if (!strings().add(s, script, std::move(str))) {
-      ReportOutOfMemory(cx);
-      return nullptr;
-    }
-  }
-
-  return s->value().get();
-}
-
-void GeckoProfilerRuntime::onScriptFinalized(JSScript* script) {
-  /*
-   * This function is called whenever a script is destroyed, regardless of
-   * whether profiling has been turned on, so don't invoke a function on an
-   * invalid hash set. Also, even if profiling was enabled but then turned
-   * off, we still want to remove the string, so no check of enabled() is
-   * done.
-   */
-  if (ProfileStringMap::Ptr entry = strings().lookup(script)) {
-    strings().remove(entry);
-  }
-}
-
-void GeckoProfilerRuntime::markEvent(const char* event) {
-  MOZ_ASSERT(enabled());
-  if (eventMarker_) {
-    JS::AutoSuppressGCAnalysis nogc;
-    eventMarker_(event);
-  }
-}
-
-bool GeckoProfilerThread::enter(JSContext* cx, JSScript* script) {
-  const char* dynamicString =
-      cx->runtime()->geckoProfiler().profileString(cx, script);
-  if (dynamicString == nullptr) {
-    return false;
-  }
-
-#  ifdef DEBUG
-  // In debug builds, assert the JS profiling stack frames already on the
-  // stack have a non-null pc. Only look at the top frames to avoid quadratic
-  // behavior.
-  uint32_t sp = profilingStack_->stackPointer;
-  if (sp > 0 && sp - 1 < profilingStack_->stackCapacity()) {
-    size_t start = (sp > 4) ? sp - 4 : 0;
-    for (size_t i = start; i < sp - 1; i++) {
-      MOZ_ASSERT_IF(profilingStack_->frames[i].isJsFrame(),
-                    profilingStack_->frames[i].pc());
-    }
-  }
-#  endif
-
-  profilingStack_->pushJsFrame("", dynamicString, script, script->code());
-  return true;
-}
-
-void GeckoProfilerThread::exit(JSContext* cx, JSScript* script) {
-  profilingStack_->pop();
-
-#  ifdef DEBUG
-  /* Sanity check to make sure push/pop balanced */
-  uint32_t sp = profilingStack_->stackPointer;
-  if (sp < profilingStack_->stackCapacity()) {
-    JSRuntime* rt = script->runtimeFromMainThread();
-    const char* dynamicString = rt->geckoProfiler().profileString(cx, script);
-    /* Can't fail lookup because we should already be in the set */
-    MOZ_ASSERT(dynamicString);
-
-    // Bug 822041
-    if (!profilingStack_->frames[sp].isJsFrame()) {
-      fprintf(stderr, "--- ABOUT TO FAIL ASSERTION ---\n");
-      fprintf(stderr, " frames=%p size=%u/%u\n", (void*)profilingStack_->frames,
-              uint32_t(profilingStack_->stackPointer),
-              profilingStack_->stackCapacity());
-      for (int32_t i = sp; i >= 0; i--) {
-        ProfilingStackFrame& frame = profilingStack_->frames[i];
-        if (frame.isJsFrame()) {
-          fprintf(stderr, "  [%d] JS %s\n", i, frame.dynamicString());
-        } else {
-          fprintf(stderr, "  [%d] Label %s\n", i, frame.dynamicString());
-        }
-      }
-    }
-
-    ProfilingStackFrame& frame = profilingStack_->frames[sp];
-    MOZ_ASSERT(frame.isJsFrame());
-    MOZ_ASSERT(frame.script() == script);
-    MOZ_ASSERT(strcmp((const char*)frame.dynamicString(), dynamicString) == 0);
-  }
-#  endif
-}
-
-/*
- * Serializes the script/function pair into a "descriptive string" which is
- * allowed to fail. This function cannot trigger a GC because it could finalize
- * some scripts, resize the hash table of profile strings, and invalidate the
- * AddPtr held while invoking allocProfileString.
- */
-/* static */
-UniqueChars GeckoProfilerRuntime::allocProfileString(JSContext* cx,
-                                                     JSScript* script) {
-  // Note: this profiler string is regexp-matched by
-  // devtools/client/profiler/cleopatra/js/parserWorker.js.
-
-  // If the script has a function, try calculating its name.
-  bool hasName = false;
-  size_t nameLength = 0;
-  UniqueChars nameStr;
-  JSFunction* func = script->functionDelazifying();
-  if (func && func->displayAtom()) {
-    nameStr = StringToNewUTF8CharsZ(cx, *func->displayAtom());
-    if (!nameStr) {
-      return nullptr;
-    }
-
-    nameLength = strlen(nameStr.get());
-    hasName = true;
-  }
-
-  // Calculate filename length.
-  const char* filenameStr = script->filename() ? script->filename() : "(null)";
-  size_t filenameLength = strlen(filenameStr);
-
-  // Calculate line + column length.
-  bool hasLineAndColumn = false;
-  size_t lineAndColumnLength = 0;
-  char lineAndColumnStr[30];
-  if (hasName || script->functionNonDelazifying() || script->isForEval()) {
-    lineAndColumnLength = SprintfLiteral(lineAndColumnStr, "%u:%u",
-                                         script->lineno(), script->column());
-    hasLineAndColumn = true;
-  }
-
-  // Full profile string for scripts with functions is:
-  //      FuncName (FileName:Lineno:Column)
-  // Full profile string for scripts without functions is:
-  //      FileName:Lineno:Column
-  // Full profile string for scripts without functions and without lines is:
-  //      FileName
-
-  // Calculate full string length.
-  size_t fullLength = 0;
-  if (hasName) {
-    MOZ_ASSERT(hasLineAndColumn);
-    fullLength = nameLength + 2 + filenameLength + 1 + lineAndColumnLength + 1;
-  } else if (hasLineAndColumn) {
-    fullLength = filenameLength + 1 + lineAndColumnLength;
-  } else {
-    fullLength = filenameLength;
-  }
-
-  // Allocate string.
-  UniqueChars str(cx->pod_malloc<char>(fullLength + 1));
-  if (!str) {
-    return nullptr;
-  }
-
-  size_t cur = 0;
-
-  // Fill string with function name if needed.
-  if (hasName) {
-    memcpy(str.get() + cur, nameStr.get(), nameLength);
-    cur += nameLength;
-    str[cur++] = ' ';
-    str[cur++] = '(';
-  }
-
-  // Fill string with filename chars.
-  memcpy(str.get() + cur, filenameStr, filenameLength);
-  cur += filenameLength;
-
-  // Fill line + column chars.
-  if (hasLineAndColumn) {
-    str[cur++] = ':';
-    memcpy(str.get() + cur, lineAndColumnStr, lineAndColumnLength);
-    cur += lineAndColumnLength;
-  }
-
-  // Terminal ')' if necessary.
-  if (hasName) {
-    str[cur++] = ')';
-  }
-
-  MOZ_ASSERT(cur == fullLength);
-  str[cur] = 0;
-
-  return str;
-}
-
-void GeckoProfilerThread::trace(JSTracer* trc) {
-  if (profilingStack_) {
-    size_t size = profilingStack_->stackSize();
-    for (size_t i = 0; i < size; i++) {
-      profilingStack_->frames[i].trace(trc);
-    }
-  }
-}
-
-void GeckoProfilerRuntime::fixupStringsMapAfterMovingGC() {
-  for (ProfileStringMap::Enum e(strings()); !e.empty(); e.popFront()) {
-    JSScript* script = e.front().key();
-    if (IsForwarded(script)) {
-      script = Forwarded(script);
-      e.rekeyFront(script);
-    }
-  }
-}
-
-#  ifdef JSGC_HASH_TABLE_CHECKS
-void GeckoProfilerRuntime::checkStringsMapAfterMovingGC() {
-  for (auto r = strings().all(); !r.empty(); r.popFront()) {
-    JSScript* script = r.front().key();
-    CheckGCThingAfterMovingGC(script);
-    auto ptr = strings().lookup(script);
-    MOZ_RELEASE_ASSERT(ptr.found() && &*ptr == &r.front());
-  }
-}
-#  endif
-
-void ProfilingStackFrame::trace(JSTracer* trc) {
-  if (isJsFrame()) {
-    JSScript* s = rawScript();
-    TraceNullableRoot(trc, &s, "ProfilingStackFrame script");
-    spOrScript = s;
-  }
-}
-
-GeckoProfilerBaselineOSRMarker::GeckoProfilerBaselineOSRMarker(
-    JSContext* cx,
-    bool hasProfilerFrame MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
-    : profiler(&cx->geckoProfiler()) {
-  MOZ_GUARD_OBJECT_NOTIFIER_INIT;
-  if (!hasProfilerFrame || !cx->runtime()->geckoProfiler().enabled()) {
-    profiler = nullptr;
-    return;
-  }
-
-  uint32_t sp = profiler->profilingStack_->stackPointer;
-  if (sp >= profiler->profilingStack_->stackCapacity()) {
-    profiler = nullptr;
-    return;
-  }
-
-  spBefore_ = sp;
-  if (sp == 0) {
-    return;
-  }
-
-  ProfilingStackFrame& frame = profiler->profilingStack_->frames[sp - 1];
-  MOZ_ASSERT(!frame.isOSRFrame());
-  frame.setIsOSRFrame(true);
-}
-
-GeckoProfilerBaselineOSRMarker::~GeckoProfilerBaselineOSRMarker() {
-  if (profiler == nullptr) {
-    return;
-  }
-
-  uint32_t sp = profiler->stackPointer();
-  MOZ_ASSERT(spBefore_ == sp);
-  if (sp == 0) {
-    return;
-  }
-
-  ProfilingStackFrame& frame = profiler->stack()[sp - 1];
-  MOZ_ASSERT(frame.isOSRFrame());
-  frame.setIsOSRFrame(false);
-}
-
-JS_PUBLIC_API JSScript* ProfilingStackFrame::script() const {
-  MOZ_ASSERT(isJsFrame());
-  auto script = reinterpret_cast<JSScript*>(spOrScript.operator void*());
-  if (!script) {
-    return nullptr;
-  }
-
-  // If profiling is supressed then we can't trust the script pointers to be
-  // valid as they could be in the process of being moved by a compacting GC
-  // (although it's still OK to get the runtime from them).
-  JSContext* cx = script->runtimeFromAnyThread()->mainContextFromAnyThread();
-  if (!cx->isProfilerSamplingEnabled()) {
-    return nullptr;
-  }
-
-  MOZ_ASSERT(!IsForwarded(script));
-  return script;
-}
-
-JS_FRIEND_API jsbytecode* ProfilingStackFrame::pc() const {
-  MOZ_ASSERT(isJsFrame());
-  if (pcOffsetIfJS_ == NullPCOffset) {
-    return nullptr;
-  }
-
-  JSScript* script = this->script();
-  return script ? script->offsetToPC(pcOffsetIfJS_) : nullptr;
-}
-
-/* static */
-int32_t ProfilingStackFrame::pcToOffset(JSScript* aScript, jsbytecode* aPc) {
-  return aPc ? aScript->pcToOffset(aPc) : NullPCOffset;
-}
-
-void ProfilingStackFrame::setPC(jsbytecode* pc) {
-  MOZ_ASSERT(isJsFrame());
-  JSScript* script = this->script();
-  MOZ_ASSERT(
-      script);  // This should not be called while profiling is suppressed.
-  pcOffsetIfJS_ = pcToOffset(script, pc);
-}
-
-JS_FRIEND_API void js::SetContextProfilingStack(
-    JSContext* cx, ProfilingStack* profilingStack) {
-  cx->geckoProfiler().setProfilingStack(
-      profilingStack, cx->runtime()->geckoProfiler().enabled());
-}
-
-JS_FRIEND_API void js::EnableContextProfilingStack(JSContext* cx,
-                                                   bool enabled) {
-  cx->geckoProfiler().enable(enabled);
-  cx->runtime()->geckoProfiler().enable(enabled);
-}
-
-JS_FRIEND_API void js::RegisterContextProfilingEventMarker(
-    JSContext* cx, void (*fn)(const char*)) {
-  MOZ_ASSERT(cx->runtime()->geckoProfiler().enabled());
-  cx->runtime()->geckoProfiler().setEventMarker(fn);
-}
-
-AutoSuppressProfilerSampling::AutoSuppressProfilerSampling(
-    JSContext* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
-    : cx_(cx), previouslyEnabled_(cx->isProfilerSamplingEnabled()) {
-  MOZ_GUARD_OBJECT_NOTIFIER_INIT;
-  if (previouslyEnabled_) {
-    cx_->disableProfilerSampling();
-  }
-}
-
-AutoSuppressProfilerSampling::~AutoSuppressProfilerSampling() {
-  if (previouslyEnabled_) {
-    cx_->enableProfilerSampling();
-  }
-}
+#  include "mozilla/Assertions.h"
 
 namespace JS {
 
 // clang-format off
 
 // ProfilingSubcategory_X:
 // One enum for each category X, listing that category's subcategories. This
 // allows the sProfilingCategoryInfo macro construction below to look up a
@@ -555,17 +49,17 @@ const ProfilingCategoryPairInfo sProfili
                           CATEGORY_INFO_END_CATEGORY)
 };
 #undef CATEGORY_INFO_BEGIN_CATEGORY
 #undef CATEGORY_INFO_SUBCATEGORY
 #undef CATEGORY_INFO_END_CATEGORY
 
 // clang-format on
 
-JS_FRIEND_API const ProfilingCategoryPairInfo& GetProfilingCategoryPairInfo(
+const ProfilingCategoryPairInfo& GetBaseProfilingCategoryPairInfo(
     ProfilingCategoryPair aCategoryPair) {
   static_assert(
       MOZ_ARRAY_LENGTH(sProfilingCategoryPairInfo) ==
           uint32_t(ProfilingCategoryPair::COUNT),
       "sProfilingCategoryPairInfo and ProfilingCategory need to have the "
       "same order and the same length");
 
   uint32_t categoryPairIndex = uint32_t(aCategoryPair);
--- a/mozglue/baseprofiler/core/ProfilingStack.cpp
+++ b/mozglue/baseprofiler/core/ProfilingStack.cpp
@@ -3,17 +3,17 @@
  * 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"
 
 #ifdef MOZ_BASE_PROFILER
 
-#  include "js/ProfilingStack.h"
+#  include "BaseProfilingStack.h"
 
 #  include "mozilla/IntegerRange.h"
 #  include "mozilla/UniquePtr.h"
 #  include "mozilla/UniquePtrExtensions.h"
 
 #  include <algorithm>
 
 using namespace js;
--- a/mozglue/baseprofiler/core/RegisteredThread.cpp
+++ b/mozglue/baseprofiler/core/RegisteredThread.cpp
@@ -5,36 +5,29 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "BaseProfiler.h"
 
 #ifdef MOZ_BASE_PROFILER
 
 #  include "RegisteredThread.h"
 
-RegisteredThread::RegisteredThread(ThreadInfo* aInfo, nsIEventTarget* aThread,
-                                   void* aStackTop)
+RegisteredThread::RegisteredThread(ThreadInfo* aInfo, void* aStackTop)
     : mRacyRegisteredThread(aInfo->ThreadId()),
       mPlatformData(AllocPlatformData(aInfo->ThreadId())),
       mStackTop(aStackTop),
-      mThreadInfo(aInfo),
-      mThread(aThread),
-      mContext(nullptr),
-      mJSSampling(INACTIVE),
-      mJSFlags(0) {
-  MOZ_COUNT_CTOR(RegisteredThread);
-
+      mThreadInfo(aInfo) {
   // We don't have to guess on mac
 #  if defined(GP_OS_darwin)
   pthread_t self = pthread_self();
   mStackTop = pthread_get_stackaddr_np(self);
 #  endif
 }
 
-RegisteredThread::~RegisteredThread() { MOZ_COUNT_DTOR(RegisteredThread); }
+RegisteredThread::~RegisteredThread() {}
 
 size_t RegisteredThread::SizeOfIncludingThis(
     mozilla::MallocSizeOf aMallocSizeOf) const {
   size_t n = aMallocSizeOf(this);
 
   // Measurement of the following members may be added later if DMD finds it
   // is worthwhile:
   // - mPlatformData
--- a/mozglue/baseprofiler/core/RegisteredThread.h
+++ b/mozglue/baseprofiler/core/RegisteredThread.h
@@ -7,34 +7,29 @@
 #ifndef RegisteredThread_h
 #define RegisteredThread_h
 
 #include "platform.h"
 #include "ProfilerMarker.h"
 #include "BaseProfilerMarkerPayload.h"
 #include "ThreadInfo.h"
 
-#include "js/TraceLoggerAPI.h"
-#include "jsapi.h"
 #include "mozilla/UniquePtr.h"
-#include "nsIEventTarget.h"
 
 // This class contains the state for a single thread that is accessible without
 // protection from gPSMutex in platform.cpp. Because there is no external
 // protection against data races, it must provide internal protection. Hence
 // the "Racy" prefix.
 //
 class RacyRegisteredThread final {
  public:
   explicit RacyRegisteredThread(int aThreadId)
-      : mThreadId(aThreadId), mSleep(AWAKE), mIsBeingProfiled(false) {
-    MOZ_COUNT_CTOR(RacyRegisteredThread);
-  }
+      : mThreadId(aThreadId), mSleep(AWAKE), mIsBeingProfiled(false) {}
 
-  ~RacyRegisteredThread() { MOZ_COUNT_DTOR(RacyRegisteredThread); }
+  ~RacyRegisteredThread() {}
 
   void SetIsBeingProfiled(bool aIsBeingProfiled) {
     mIsBeingProfiled = aIsBeingProfiled;
   }
 
   bool IsBeingProfiled() const { return mIsBeingProfiled; }
 
   void AddPendingMarker(const char* aMarkerName,
@@ -159,179 +154,35 @@ class RacyRegisteredThread final {
 };
 
 // This class contains information that's relevant to a single thread only
 // while that thread is running and registered with the profiler, but
 // regardless of whether the profiler is running. All accesses to it are
 // protected by the profiler state lock.
 class RegisteredThread final {
  public:
-  RegisteredThread(ThreadInfo* aInfo, nsIEventTarget* aThread, void* aStackTop);
+  RegisteredThread(ThreadInfo* aInfo, void* aStackTop);
   ~RegisteredThread();
 
   class RacyRegisteredThread& RacyRegisteredThread() {
     return mRacyRegisteredThread;
   }
   const class RacyRegisteredThread& RacyRegisteredThread() const {
     return mRacyRegisteredThread;
   }
 
   PlatformData* GetPlatformData() const { return mPlatformData.get(); }
   const void* StackTop() const { return mStackTop; }
 
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
-  // Set the JSContext of the thread to be sampled. Sampling cannot begin until
-  // this has been set.
-  void SetJSContext(JSContext* aContext) {
-    // This function runs on-thread.
-
-    MOZ_ASSERT(aContext && !mContext);
-
-    mContext = aContext;
-
-    // We give the JS engine a non-owning reference to the ProfilingStack. It's
-    // important that the JS engine doesn't touch this once the thread dies.
-    js::SetContextProfilingStack(aContext,
-                                 &RacyRegisteredThread().ProfilingStack());
-  }
-
-  void ClearJSContext() {
-    // This function runs on-thread.
-    mContext = nullptr;
-  }
-
-  JSContext* GetJSContext() const { return mContext; }
-
   const RefPtr<ThreadInfo> Info() const { return mThreadInfo; }
-  const nsCOMPtr<nsIEventTarget> GetEventTarget() const { return mThread; }
-
-  // Request that this thread start JS sampling. JS sampling won't actually
-  // start until a subsequent PollJSSampling() call occurs *and* mContext has
-  // been set.
-  void StartJSSampling(uint32_t aJSFlags) {
-    // This function runs on-thread or off-thread.
-
-    MOZ_RELEASE_ASSERT(mJSSampling == INACTIVE ||
-                       mJSSampling == INACTIVE_REQUESTED);
-    mJSSampling = ACTIVE_REQUESTED;
-    mJSFlags = aJSFlags;
-  }
-
-  // Request that this thread stop JS sampling. JS sampling won't actually stop
-  // until a subsequent PollJSSampling() call occurs.
-  void StopJSSampling() {
-    // This function runs on-thread or off-thread.
-
-    MOZ_RELEASE_ASSERT(mJSSampling == ACTIVE ||
-                       mJSSampling == ACTIVE_REQUESTED);
-    mJSSampling = INACTIVE_REQUESTED;
-  }
-
-  // Poll to see if JS sampling should be started/stopped.
-  void PollJSSampling() {
-    // This function runs on-thread.
-
-    // We can't start/stop profiling until we have the thread's JSContext.
-    if (mContext) {
-      // It is possible for mJSSampling to go through the following sequences.
-      //
-      // - INACTIVE, ACTIVE_REQUESTED, INACTIVE_REQUESTED, INACTIVE
-      //
-      // - ACTIVE, INACTIVE_REQUESTED, ACTIVE_REQUESTED, ACTIVE
-      //
-      // Therefore, the if and else branches here aren't always interleaved.
-      // This is ok because the JS engine can handle that.
-      //
-      if (mJSSampling == ACTIVE_REQUESTED) {
-        mJSSampling = ACTIVE;
-        js::EnableContextProfilingStack(mContext, true);
-        JS_SetGlobalJitCompilerOption(mContext,
-                                      JSJITCOMPILER_TRACK_OPTIMIZATIONS,
-                                      TrackOptimizationsEnabled());
-        if (JSTracerEnabled()) {
-          JS::StartTraceLogger(mContext);
-        }
-        js::RegisterContextProfilingEventMarker(mContext,
-                                                profiler_add_js_marker);
-
-      } else if (mJSSampling == INACTIVE_REQUESTED) {
-        mJSSampling = INACTIVE;
-        js::EnableContextProfilingStack(mContext, false);
-        if (JSTracerEnabled()) {
-          JS::StopTraceLogger(mContext);
-        }
-      }
-    }
-  }
 
  private:
   class RacyRegisteredThread mRacyRegisteredThread;
 
   const UniquePlatformData mPlatformData;
   const void* mStackTop;
 
   const RefPtr<ThreadInfo> mThreadInfo;
-  const nsCOMPtr<nsIEventTarget> mThread;
-
-  // If this is a JS thread, this is its JSContext, which is required for any
-  // JS sampling.
-  JSContext* mContext;
-
-  // The profiler needs to start and stop JS sampling of JS threads at various
-  // times. However, the JS engine can only do the required actions on the
-  // JS thread itself ("on-thread"), not from another thread ("off-thread").
-  // Therefore, we have the following two-step process.
-  //
-  // - The profiler requests (on-thread or off-thread) that the JS sampling be
-  //   started/stopped, by changing mJSSampling to the appropriate REQUESTED
-  //   state.
-  //
-  // - The relevant JS thread polls (on-thread) for changes to mJSSampling.
-  //   When it sees a REQUESTED state, it performs the appropriate actions to
-  //   actually start/stop JS sampling, and changes mJSSampling out of the
-  //   REQUESTED state.
-  //
-  // The state machine is as follows.
-  //
-  //             INACTIVE --> ACTIVE_REQUESTED
-  //                  ^       ^ |
-  //                  |     _/  |
-  //                  |   _/    |
-  //                  |  /      |
-  //                  | v       v
-  //   INACTIVE_REQUESTED <-- ACTIVE
-  //
-  // The polling is done in the following two ways.
-  //
-  // - Via the interrupt callback mechanism; the JS thread must call
-  //   profiler_js_interrupt_callback() from its own interrupt callback.
-  //   This is how sampling must be started/stopped for threads where the
-  //   request was made off-thread.
-  //
-  // - When {Start,Stop}JSSampling() is called on-thread, we can immediately
-  //   follow it with a PollJSSampling() call to avoid the delay between the
-  //   two steps. Likewise, setJSContext() calls PollJSSampling().
-  //
-  // One non-obvious thing about all this: these JS sampling requests are made
-  // on all threads, even non-JS threads. mContext needs to also be set (via
-  // setJSContext(), which can only happen for JS threads) for any JS sampling
-  // to actually happen.
-  //
-  enum {
-    INACTIVE = 0,
-    ACTIVE_REQUESTED = 1,
-    ACTIVE = 2,
-    INACTIVE_REQUESTED = 3,
-  } mJSSampling;
-
-  uint32_t mJSFlags;
-
-  bool TrackOptimizationsEnabled() {
-    return mJSFlags & uint32_t(JSSamplingFlags::TrackOptimizations);
-  }
-
-  bool JSTracerEnabled() {
-    return mJSFlags & uint32_t(JSSamplingFlags::TraceLogging);
-  }
 };
 
 #endif  // RegisteredThread_h
--- a/mozglue/baseprofiler/core/ThreadInfo.h
+++ b/mozglue/baseprofiler/core/ThreadInfo.h
@@ -2,47 +2,57 @@
 /* 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 ThreadInfo_h
 #define ThreadInfo_h
 
+#include "mozilla/Atomics.h"
 #include "mozilla/TimeStamp.h"
-#include "nsISupportsImpl.h"
-#include "nsString.h"
 
 // This class contains information about a thread which needs to be stored
 // across restarts of the profiler and which can be useful even after the
 // thread has stopped running.
 // It uses threadsafe refcounting and only contains immutable data.
 class ThreadInfo final {
  public:
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ThreadInfo)
-
   ThreadInfo(
       const char* aName, int aThreadId, bool aIsMainThread,
       const mozilla::TimeStamp& aRegisterTime = mozilla::TimeStamp::Now())
       : mName(aName),
         mRegisterTime(aRegisterTime),
         mThreadId(aThreadId),
-        mIsMainThread(aIsMainThread) {
+        mIsMainThread(aIsMainThread),
+        mRefCnt(0) {
     // I don't know if we can assert this. But we should warn.
     MOZ_ASSERT(aThreadId >= 0, "native thread ID is < 0");
     MOZ_ASSERT(aThreadId <= INT32_MAX, "native thread ID is > INT32_MAX");
   }
 
-  const char* Name() const { return mName.get(); }
+  // Using hand-rolled ref-counting, because RefCounted.h macros don't produce
+  // the same code between mozglue and libxul, see bug 1536656.
+  MFBT_API void AddRef() const { ++mRefCnt; }
+  MFBT_API void Release() const {
+    MOZ_ASSERT(int32_t(mRefCnt) > 0);
+    if (--mRefCnt == 0) {
+      delete this;
+    }
+  }
+
+  const char* Name() const { return mName.c_str(); }
   mozilla::TimeStamp RegisterTime() const { return mRegisterTime; }
   int ThreadId() const { return mThreadId; }
   bool IsMainThread() const { return mIsMainThread; }
 
  private:
-  ~ThreadInfo() {}
-
-  const nsCString mName;
+  const std::string mName;
   const mozilla::TimeStamp mRegisterTime;
   const int mThreadId;
   const bool mIsMainThread;
+
+  mutable mozilla::Atomic<int32_t, mozilla::MemoryOrdering::ReleaseAcquire,
+                          mozilla::recordreplay::Behavior::DontPreserve>
+      mRefCnt;
 };
 
 #endif  // ThreadInfo_h
--- a/mozglue/baseprofiler/core/VTuneProfiler.cpp
+++ b/mozglue/baseprofiler/core/VTuneProfiler.cpp
@@ -9,80 +9,84 @@
 #ifdef MOZ_BASE_PROFILER
 
 #  ifdef XP_WIN
 #    undef UNICODE
 #    undef _UNICODE
 #  endif
 
 #  include "VTuneProfiler.h"
-#  include "mozilla/Bootstrap.h"
+
 #  include <memory>
 
 using namespace std;
 
 VTuneProfiler* VTuneProfiler::mInstance = nullptr;
 
 void VTuneProfiler::Initialize() {
   // This is just a 'dirty trick' to find out if the ittnotify DLL was found.
   // If it wasn't this function always returns 0, otherwise it returns
   // incrementing numbers, if the library was found this wastes 2 events but
   // that should be okay.
-  __itt_event testEvent =
-      __itt_event_create("Test event", strlen("Test event"));
-  testEvent = __itt_event_create("Test event 2", strlen("Test event 2"));
+  // TODO re-implement here if vtune is needed
+  // __itt_event testEvent =
+  //     __itt_event_create("Test event", strlen("Test event"));
+  // testEvent = __itt_event_create("Test event 2", strlen("Test event 2"));
 
-  if (testEvent) {
-    mInstance = new VTuneProfiler();
-  }
+  // if (testEvent) {
+  //   mInstance = new VTuneProfiler();
+  // }
 }
 
 void VTuneProfiler::Shutdown() {}
 
 void VTuneProfiler::TraceInternal(const char* aName, TracingKind aKind) {
-  string str(aName);
+  // TODO re-implement here if vtune is needed
+  // string str(aName);
 
-  auto iter = mStrings.find(str);
+  // auto iter = mStrings.find(str);
 
-  __itt_event event;
-  if (iter != mStrings.end()) {
-    event = iter->second;
-  } else {
-    event = __itt_event_create(aName, str.length());
-    mStrings.insert({str, event});
-  }
+  // __itt_event event;
+  // if (iter != mStrings.end()) {
+  //   event = iter->second;
+  // } else {
+  //   event = __itt_event_create(aName, str.length());
+  //   mStrings.insert({str, event});
+  // }
 
-  if (aKind == TRACING_INTERVAL_START || aKind == TRACING_EVENT) {
-    // VTune will consider starts not matched with an end to be single point in
-    // time events.
-    __itt_event_start(event);
-  } else {
-    __itt_event_end(event);
-  }
+  // if (aKind == TRACING_INTERVAL_START || aKind == TRACING_EVENT) {
+  //   // VTune will consider starts not matched with an end to be single point
+  //   in
+  //   // time events.
+  //   __itt_event_start(event);
+  // } else {
+  //   __itt_event_end(event);
+  // }
 }
 
 void VTuneProfiler::RegisterThreadInternal(const char* aName) {
-  string str(aName);
+  // TODO re-implement here if vtune is needed
+  // string str(aName);
 
-  if (!str.compare("GeckoMain")) {
-    // Process main thread.
-    switch (XRE_GetProcessType()) {
-      case GeckoProcessType::GeckoProcessType_Default:
-        __itt_thread_set_name("Main Process");
-        break;
-      case GeckoProcessType::GeckoProcessType_Content:
-        __itt_thread_set_name("Content Process");
-        break;
-      case GeckoProcessType::GeckoProcessType_GMPlugin:
-        __itt_thread_set_name("Plugin Process");
-        break;
-      case GeckoProcessType::GeckoProcessType_GPU:
-        __itt_thread_set_name("GPU Process");
-        break;
-      default:
-        __itt_thread_set_name("Unknown Process");
-    }
-    return;
-  }
-  __itt_thread_set_name(aName);
+  // if (!str.compare("GeckoMain")) {
+  //   // Process main thread.
+  //   switch (XRE_GetProcessType()) {
+  //     case GeckoProcessType::GeckoProcessType_Default:
+  //       __itt_thread_set_name("Main Process");
+  //       break;
+  //     case GeckoProcessType::GeckoProcessType_Content:
+  //       __itt_thread_set_name("Content Process");
+  //       break;
+  //     case GeckoProcessType::GeckoProcessType_GMPlugin:
+  //       __itt_thread_set_name("Plugin Process");
+  //       break;
+  //     case GeckoProcessType::GeckoProcessType_GPU:
+  //       __itt_thread_set_name("GPU Process");
+  //       break;
+  //     default:
+  //       __itt_thread_set_name("Unknown Process");
+  //   }
+  //   return;
+  // }
+  // __itt_thread_set_name(aName);
 }
 
 #endif  // MOZ_BASE_PROFILER
--- a/mozglue/baseprofiler/core/platform-linux-android.cpp
+++ b/mozglue/baseprofiler/core/platform-linux-android.cpp
@@ -75,16 +75,22 @@ int profiler_current_thread_id() {
   // glibc doesn't provide a wrapper for gettid().
 #if defined(__GLIBC__)
   return static_cast<int>(static_cast<pid_t>(syscall(SYS_gettid)));
 #else
   return static_cast<int>(gettid());
 #endif
 }
 
+static int64_t MicrosecondsSince1970() {
+  struct timeval tv;
+  gettimeofday(&tv, NULL);
+  return int64_t(tv.tv_sec) * 1000000 + int64_t(tv.tv_usec);
+}
+
 void* GetStackTop(void* aGuess) { return aGuess; }
 
 static void PopulateRegsFromContext(Registers& aRegs, ucontext_t* aContext) {
   aRegs.mContext = aContext;
   mcontext_t& mcontext = aContext->uc_mcontext;
 
   // Extracting the sample from the context is extremely machine dependent.
 #if defined(GP_ARCH_x86)
@@ -122,19 +128,19 @@ static void PopulateRegsFromContext(Regi
 #endif
 
 int tgkill(pid_t tgid, pid_t tid, int signalno) {
   return syscall(SYS_tgkill, tgid, tid, signalno);
 }
 
 class PlatformData {
  public:
-  explicit PlatformData(int aThreadId) { MOZ_COUNT_CTOR(PlatformData); }
+  explicit PlatformData(int aThreadId) {}
 
-  ~PlatformData() { MOZ_COUNT_DTOR(PlatformData); }
+  ~PlatformData() {}
 };
 
 ////////////////////////////////////////////////////////////////////////
 // BEGIN Sampler target specifics
 
 // The only way to reliably interrupt a Linux thread and inspect its register
 // and stack state is by sending a signal to it, and doing the work inside the
 // signal handler.  But we don't want to run much code inside the signal
@@ -391,17 +397,17 @@ SamplerThread::SamplerThread(PSLockRef a
     read_procmaps(lul);
 
     // Switch into unwind mode. After this point, we can't add or remove any
     // unwind info to/from this LUL instance. The only thing we can do with
     // it is Unwind() calls.
     lul->EnableUnwinding();
 
     // Has a test been requested?
-    if (PR_GetEnv("MOZ_PROFILER_LUL_TEST")) {
+    if (getenv("MOZ_PROFILER_LUL_TEST")) {
       int nTests = 0, nTestsPassed = 0;
       RunLulUnitTests(&nTests, &nTestsPassed, lul);
     }
   }
 #endif
 
   // Start the sampling thread. It repeatedly sends a SIGPROF signal. Sending
   // the signal ourselves instead of relying on itimer provides much better
@@ -463,29 +469,29 @@ void SamplerThread::Stop(PSLockRef aLock
 //
 // Unfortunately all this is only doable on non-Android because Bionic doesn't
 // have pthread_atfork.
 
 // In the parent, before the fork, record IsPaused, and then pause.
 static void paf_prepare() {
   MOZ_RELEASE_ASSERT(CorePS::Exists());
 
-  PSAutoLock lock(gPSMutex);
+  PSAutoLock lock;
 
   if (ActivePS::Exists(lock)) {
     ActivePS::SetWasPaused(lock, ActivePS::IsPaused(lock));
     ActivePS::SetIsPaused(lock, true);
   }
 }
 
 // In the parent, after the fork, return IsPaused to the pre-fork state.
 static void paf_parent() {
   MOZ_RELEASE_ASSERT(CorePS::Exists());
 
-  PSAutoLock lock(gPSMutex);
+  PSAutoLock lock;
 
   if (ActivePS::Exists(lock)) {
     ActivePS::SetIsPaused(lock, ActivePS::WasPaused(lock));
     ActivePS::SetWasPaused(lock, false);
   }
 }
 
 static void PlatformInit(PSLockRef aLock) {
@@ -498,16 +504,18 @@ static void PlatformInit(PSLockRef aLock
 static void PlatformInit(PSLockRef aLock) {}
 
 #endif
 
 #if defined(HAVE_NATIVE_UNWIND)
 // Context used by synchronous samples. It's safe to have a single one because
 // only one synchronous sample can be taken at a time (due to
 // profiler_get_backtrace()'s PSAutoLock).
-ucontext_t sSyncUContext;
+// ucontext_t sSyncUContext;
 
 void Registers::SyncPopulate() {
-  if (!getcontext(&sSyncUContext)) {
-    PopulateRegsFromContext(*this, &sSyncUContext);
-  }
+  // TODO port getcontext from breakpad, if profiler_get_backtrace is needed.
+  MOZ_CRASH("profiler_get_backtrace() unsupported");
+  // if (!getcontext(&sSyncUContext)) {
+  //   PopulateRegsFromContext(*this, &sSyncUContext);
+  // }
 }
 #endif
--- a/mozglue/baseprofiler/core/platform-macos.cpp
+++ b/mozglue/baseprofiler/core/platform-macos.cpp
@@ -34,32 +34,34 @@
 // this port is based off of v8 svn revision 9837
 
 int profiler_current_process_id() { return getpid(); }
 
 int profiler_current_thread_id() {
   return static_cast<int>(static_cast<pid_t>(syscall(SYS_thread_selfid)));
 }
 
+static int64_t MicrosecondsSince1970() {
+  struct timeval tv;
+  gettimeofday(&tv, NULL);
+  return int64_t(tv.tv_sec) * 1000000 + int64_t(tv.tv_usec);
+}
+
 void* GetStackTop(void* aGuess) {
   pthread_t thread = pthread_self();
   return pthread_get_stackaddr_np(thread);
 }
 
 class PlatformData {
  public:
-  explicit PlatformData(int aThreadId) : mProfiledThread(mach_thread_self()) {
-    MOZ_COUNT_CTOR(PlatformData);
-  }
+  explicit PlatformData(int aThreadId) : mProfiledThread(mach_thread_self()) {}
 
   ~PlatformData() {
     // Deallocate Mach port for thread.
     mach_port_deallocate(mach_task_self(), mProfiledThread);
-
-    MOZ_COUNT_DTOR(PlatformData);
   }
 
   thread_act_t ProfiledThread() { return mProfiledThread; }
 
  private:
   // Note: for mProfiledThread Mach primitives are used instead of pthread's
   // because the latter doesn't provide thread manipulation primitives required.
   // For details, consult "Mac OS X Internals" book, Section 7.3.
--- a/mozglue/baseprofiler/core/platform-win32.cpp
+++ b/mozglue/baseprofiler/core/platform-win32.cpp
@@ -39,16 +39,31 @@
 int profiler_current_process_id() { return _getpid(); }
 
 int profiler_current_thread_id() {
   DWORD threadId = GetCurrentThreadId();
   MOZ_ASSERT(threadId <= INT32_MAX, "native thread ID is > INT32_MAX");
   return int(threadId);
 }
 
+static int64_t MicrosecondsSince1970() {
+  int64_t prt;
+  FILETIME ft;
+  SYSTEMTIME st;
+
+  GetSystemTime(&st);
+  SystemTimeToFileTime(&st, &ft);
+  static_assert(sizeof(ft) == sizeof(prt), "Expect FILETIME to be 64 bits");
+  memcpy(&prt, &ft, sizeof(prt));
+  const int64_t epochBias = 116444736000000000LL;
+  prt = (prt - epochBias) / 10;
+
+  return prt;
+}
+
 void* GetStackTop(void* aGuess) {
   PNT_TIB pTib = reinterpret_cast<PNT_TIB>(NtCurrentTeb());
   return reinterpret_cast<void*>(pTib->StackBase);
 }
 
 static void PopulateRegsFromContext(Registers& aRegs, CONTEXT* aContext) {
 #if defined(GP_ARCH_amd64)
   aRegs.mPC = reinterpret_cast<Address>(aContext->Rip);
@@ -73,26 +88,23 @@ class PlatformData {
   // Get a handle to the calling thread. This is the thread that we are
   // going to profile. We need to make a copy of the handle because we are
   // going to use it in the sampler thread. Using GetThreadHandle() will
   // not work in this case. We're using OpenThread because DuplicateHandle
   // for some reason doesn't work in Chrome's sandbox.
   explicit PlatformData(int aThreadId)
       : mProfiledThread(OpenThread(THREAD_GET_CONTEXT | THREAD_SUSPEND_RESUME |
                                        THREAD_QUERY_INFORMATION,
-                                   false, aThreadId)) {
-    MOZ_COUNT_CTOR(PlatformData);
-  }
+                                   false, aThreadId)) {}
 
   ~PlatformData() {
     if (mProfiledThread != nullptr) {
       CloseHandle(mProfiledThread);
       mProfiledThread = nullptr;
     }
-    MOZ_COUNT_DTOR(PlatformData);
   }
 
   HANDLE ProfiledThread() { return mProfiledThread; }
 
  private:
   HANDLE mProfiledThread;
 };
 
--- a/mozglue/baseprofiler/core/platform.cpp
+++ b/mozglue/baseprofiler/core/platform.cpp
@@ -27,77 +27,47 @@
 //   SuspendAndSampleAndResumeThread() to get the register values.
 
 #include "BaseProfiler.h"
 
 #ifdef MOZ_BASE_PROFILER
 
 #  include "platform.h"
 
-#  include "GeckoProfilerReporter.h"
 #  include "PageInformation.h"
 #  include "ProfiledThreadData.h"
 #  include "ProfilerBacktrace.h"
 #  include "ProfileBuffer.h"
-#  include "ProfilerIOInterposeObserver.h"
 #  include "BaseProfilerMarkerPayload.h"
-#  include "ProfilerParent.h"
 #  include "RegisteredThread.h"
 #  include "BaseProfilerSharedLibraries.h"
 #  include "ThreadInfo.h"
 #  include "VTuneProfiler.h"
 
-#  include "js/TraceLoggerAPI.h"
-#  include "memory_hooks.h"
+// #include "memory_hooks.h"
 #  include "mozilla/ArrayUtils.h"
 #  include "mozilla/Atomics.h"
-#  include "mozilla/AutoProfilerLabel.h"
-#  include "mozilla/ExtensionPolicyService.h"
-#  include "mozilla/extensions/WebExtensionPolicy.h"
 #  include "mozilla/Printf.h"
 #  include "mozilla/Services.h"
 #  include "mozilla/StackWalk.h"
 #  include "mozilla/StaticPtr.h"
-#  include "mozilla/SystemGroup.h"
 #  include "mozilla/ThreadLocal.h"
 #  include "mozilla/TimeStamp.h"
 #  include "mozilla/Tuple.h"
 #  include "mozilla/UniquePtr.h"
 #  include "mozilla/Vector.h"
-#  include "nsDirectoryServiceDefs.h"
-#  include "nsDirectoryServiceUtils.h"
-#  include "nsIHttpProtocolHandler.h"
-#  include "nsIObserverService.h"
-#  include "nsIPropertyBag2.h"
-#  include "nsIXULAppInfo.h"
-#  include "nsIXULRuntime.h"
-#  include "nsJSPrincipals.h"
-#  include "nsMemoryReporterManager.h"
-#  include "nsProfilerStartParams.h"
-#  include "nsScriptSecurityManager.h"
-#  include "nsThreadUtils.h"
-#  include "nsXULAppAPI.h"
 #  include "prdtoa.h"
 #  include "prtime.h"
 
 #  include <algorithm>
 #  include <errno.h>
 #  include <fstream>
 #  include <ostream>
 #  include <sstream>
 
-#  ifdef MOZ_TASK_TRACER
-#    include "GeckoTaskTracer.h"
-#  endif
-
-#  if defined(GP_OS_android)
-#    include "FennecJNINatives.h"
-#    include "FennecJNIWrappers.h"
-#  endif
-
 // Win32 builds always have frame pointers, so FramePointerStackWalk() always
 // works.
 #  if defined(GP_PLAT_x86_windows)
 #    define HAVE_NATIVE_UNWIND
 #    define USE_FRAME_POINTER_STACK_WALK
 #  endif
 
 // Win64 builds always omit frame pointers, so we use the slower
@@ -169,62 +139,50 @@
 
 #  if defined(GP_OS_linux) || defined(GP_OS_android)
 #    include <ucontext.h>
 #  endif
 
 using namespace mozilla;
 using mozilla::profiler::detail::RacyFeatures;
 
-LazyLogModule gProfilerLog("prof");
-
-#  if defined(GP_OS_android)
-class GeckoJavaSampler
-    : public java::GeckoJavaSampler::Natives<GeckoJavaSampler> {
- private:
-  GeckoJavaSampler();
-
- public:
-  static double GetProfilerTime() {
-    if (!profiler_is_active()) {
-      return 0.0;
-    }
-    return profiler_time();
-  };
-};
-#  endif
+bool BaseProfilerLogTest(int aLevelToTest) {
+  static const int maxLevel =
+      getenv("MOZ_BASE_PROFILER_VERBOSE_LOGGING")
+          ? 5
+          : getenv("MOZ_BASE_PROFILER_DEBUG_LOGGING")
+                ? 4
+                : getenv("MOZ_BASE_PROFILER_LOGGING") ? 3 : 0;
+  return aLevelToTest <= maxLevel;
+}
 
 // Return all features that are available on this platform.
 static uint32_t AvailableFeatures() {
   uint32_t features = 0;
 
 #  define ADD_FEATURE(n_, str_, Name_, desc_) \
     ProfilerFeature::Set##Name_(features);
 
   // Add all the possible features.
   PROFILER_FOR_EACH_FEATURE(ADD_FEATURE)
 
 #  undef ADD_FEATURE
 
   // Now remove features not supported on this platform/configuration.
-#  if !defined(GP_OS_android)
   ProfilerFeature::ClearJava(features);
-#  endif
+  ProfilerFeature::ClearJS(features);
+  ProfilerFeature::ClearMemory(features);
+  ProfilerFeature::ClearResponsiveness(features);
+  ProfilerFeature::ClearScreenshots(features);
 #  if !defined(HAVE_NATIVE_UNWIND)
   ProfilerFeature::ClearStackWalk(features);
 #  endif
-#  if !defined(MOZ_TASK_TRACER)
   ProfilerFeature::ClearTaskTracer(features);
-#  endif
-#  if !(defined(MOZ_REPLACE_MALLOC) && defined(MOZ_PROFILER_MEMORY))
-  ProfilerFeature::ClearMemory(features);
-#  endif
-  if (!JS::TraceLoggerSupported()) {
-    ProfilerFeature::ClearJSTracer(features);
-  }
+  ProfilerFeature::ClearTrackOptimizations(features);
+  ProfilerFeature::ClearJSTracer(features);
 
   return features;
 }
 
 // Default features common to all contexts (even if not available).
 static uint32_t DefaultFeatures() {
   return ProfilerFeature::Java | ProfilerFeature::JS | ProfilerFeature::Leaf |
          ProfilerFeature::StackWalk | ProfilerFeature::Threads |
@@ -234,19 +192,35 @@ static uint32_t DefaultFeatures() {
 // Extra default features when MOZ_PROFILER_STARTUP is set (even if not
 // available).
 static uint32_t StartupExtraDefaultFeatures() {
   // Enable mainthreadio by default for startup profiles as startup is heavy on
   // I/O operations, and main thread I/O is really important to see there.
   return ProfilerFeature::MainThreadIO | ProfilerFeature::Memory;
 }
 
-class PSMutex : public StaticMutex {};
-
-typedef BaseAutoLock<PSMutex&> PSAutoLock;
+// The auto-lock/unlock mutex that guards accesses to CorePS and ActivePS.
+// Use `PSAutoLock lock;` to take the lock until the end of the enclosing block.
+// External profilers may use this same lock for their own data, but as the lock
+// is non-recursive, *only* `f(PSLockRef, ...)` functions below should be
+// called, to avoid double-locking.
+class MOZ_RAII PSAutoLock {
+ public:
+  PSAutoLock() { gPSMutex.Lock(); }
+
+  ~PSAutoLock() { gPSMutex.Unlock(); }
+
+  PSAutoLock(const PSAutoLock&) = delete;
+  void operator=(const PSAutoLock&) = delete;
+
+ private:
+  static PSMutex gPSMutex;
+};
+
+PSMutex PSAutoLock::gPSMutex;
 
 // Only functions that take a PSLockRef arg can access CorePS's and ActivePS's
 // fields.
 typedef const PSAutoLock& PSLockRef;
 
 #  define PS_GET(type_, name_) \
     static type_ name_(PSLockRef) { return sInstance->m##name_; }
 
@@ -278,17 +252,18 @@ typedef const PSAutoLock& PSLockRef;
 //
 // - mProcessStartTime, because it's immutable;
 //
 // - each thread's RacyRegisteredThread object is accessible without locking via
 //   TLSRegisteredThread::RacyRegisteredThread().
 class CorePS {
  private:
   CorePS()
-      : mProcessStartTime(TimeStamp::ProcessCreation())
+      : mMainThreadId(profiler_current_thread_id()),
+        mProcessStartTime(TimeStamp::ProcessCreation())
 #  ifdef USE_LUL_STACKWALK
         ,
         mLul(nullptr)
 #  endif
   {
   }
 
   ~CorePS() {}
@@ -301,16 +276,21 @@ class CorePS {
     sInstance = nullptr;
   }
 
   // Unlike ActivePS::Exists(), CorePS::Exists() can be called without gPSMutex
   // being locked. This is because CorePS is instantiated so early on the main
   // thread that we don't have to worry about it being racy.
   static bool Exists() { return !!sInstance; }
 
+  static bool IsMainThread() {
+    MOZ_RELEASE_ASSERT(Exists());
+    return profiler_current_thread_id() == sInstance->mMainThreadId;
+  }
+
   static void AddSizeOf(PSLockRef, MallocSizeOf aMallocSizeOf,
                         size_t& aProfSize, size_t& aLulSize) {
     aProfSize += aMallocSizeOf(sInstance);
 
     for (auto& registeredThread : sInstance->mRegisteredThreads) {
       aProfSize += registeredThread->SizeOfIncludingThis(aMallocSizeOf);
     }
 
@@ -370,20 +350,20 @@ class CorePS {
         sInstance->mRegisteredPages.begin(), sInstance->mRegisteredPages.end(),
         RegisteredPageComparator{aRegisteredPage.get()}));
 #  endif
     MOZ_RELEASE_ASSERT(
         sInstance->mRegisteredPages.append(std::move(aRegisteredPage)));
   }
 
   static void RemoveRegisteredPages(PSLockRef,
-                                    const nsID& aRegisteredDocShellId) {
+                                    const std::string& aRegisteredDocShellId) {
     // Remove RegisteredPage from mRegisteredPages by given DocShell Id.
     sInstance->mRegisteredPages.eraseIf([&](const RefPtr<PageInformation>& rd) {
-      return rd->DocShellId().Equals(aRegisteredDocShellId);
+      return rd->DocShellId() == aRegisteredDocShellId;
     });
   }
 
   static void ClearRegisteredPages(PSLockRef) {
     sInstance->mRegisteredPages.clear();
   }
 
   PS_GET(const Vector<BaseProfilerCount*>&, Counters)
@@ -406,22 +386,25 @@ class CorePS {
 
 #  ifdef USE_LUL_STACKWALK
   static lul::LUL* Lul(PSLockRef) { return sInstance->mLul.get(); }
   static void SetLul(PSLockRef, UniquePtr<lul::LUL> aLul) {
     sInstance->mLul = std::move(aLul);
   }
 #  endif
 
-  PS_GET_AND_SET(const nsACString&, ProcessName)
+  PS_GET_AND_SET(const std::string&, ProcessName)
 
  private:
   // The singleton instance
   static CorePS* sInstance;
 
+  // ID of the main thread (assuming CorePS was started on the main thread).
+  const int mMainThreadId;
+
   // The time that the process started.
   const TimeStamp mProcessStartTime;
 
   // Info on all the registered threads.
   // ThreadIds in mRegisteredThreads are unique.
   Vector<UniquePtr<RegisteredThread>> mRegisteredThreads;
 
   // Info on all the registered pages.
@@ -432,17 +415,17 @@ class CorePS {
   Vector<BaseProfilerCount*> mCounters;
 
 #  ifdef USE_LUL_STACKWALK
   // LUL's state. Null prior to the first activation, non-null thereafter.
   UniquePtr<lul::LUL> mLul;
 #  endif
 
   // Process name, provided by child process initialization code.
-  nsAutoCString mProcessName;
+  std::string mProcessName;
 };
 
 CorePS* CorePS::sInstance = nullptr;
 
 class SamplerThread;
 
 static SamplerThread* NewSamplerThread(PSLockRef aLock, uint32_t aGeneration,
                                        double aInterval);
@@ -459,22 +442,16 @@ struct LiveProfiledThreadData {
 // CorePS.
 //
 class ActivePS {
  private:
   static uint32_t AdjustFeatures(uint32_t aFeatures, uint32_t aFilterCount) {
     // Filter out any features unavailable in this platform/configuration.
     aFeatures &= AvailableFeatures();
 
-#  if defined(GP_OS_android)
-    if (!jni::IsFennec()) {
-      aFeatures &= ~ProfilerFeature::Java;
-    }
-#  endif
-
     // Always enable ProfilerFeature::Threads if we have a filter, because
     // users sometimes ask to filter by a list of threads but forget to
     // explicitly specify ProfilerFeature::Threads.
     if (aFilterCount > 0) {
       aFeatures |= ProfilerFeature::Threads;
     }
 
     return aFeatures;
@@ -488,73 +465,33 @@ class ActivePS {
         mDuration(aDuration),
         mInterval(aInterval),
         mFeatures(AdjustFeatures(aFeatures, aFilterCount)),
         mBuffer(MakeUnique<ProfileBuffer>(aCapacity))
         // The new sampler thread doesn't start sampling immediately because the
         // main loop within Run() is blocked until this function's caller
         // unlocks gPSMutex.
         ,
-        mSamplerThread(NewSamplerThread(aLock, mGeneration, aInterval)),
-        mInterposeObserver(ProfilerFeature::HasMainThreadIO(aFeatures)
-                               ? new ProfilerIOInterposeObserver()
-                               : nullptr)
+        mSamplerThread(NewSamplerThread(aLock, mGeneration, aInterval))
 #  undef HAS_FEATURE
         ,
         mIsPaused(false)
 #  if defined(GP_OS_linux)
         ,
         mWasPaused(false)
 #  endif
   {
     // Deep copy aFilters.
     MOZ_ALWAYS_TRUE(mFilters.resize(aFilterCount));
     for (uint32_t i = 0; i < aFilterCount; ++i) {
       mFilters[i] = aFilters[i];
     }
-
-#  if !defined(RELEASE_OR_BETA)
-    if (mInterposeObserver) {
-      // We need to register the observer on the main thread, because we want
-      // to observe IO that happens on the main thread.
-      // IOInterposer needs to be initialized before calling
-      // IOInterposer::Register or our observer will be silently dropped.
-      if (NS_IsMainThread()) {
-        IOInterposer::Init();
-        IOInterposer::Register(IOInterposeObserver::OpAll, mInterposeObserver);
-      } else {
-        RefPtr<ProfilerIOInterposeObserver> observer = mInterposeObserver;
-        NS_DispatchToMainThread(
-            NS_NewRunnableFunction("ActivePS::ActivePS", [=]() {
-              IOInterposer::Init();
-              IOInterposer::Register(IOInterposeObserver::OpAll, observer);
-            }));
-      }
-    }
-#  endif
   }
 
-  ~ActivePS() {
-#  if !defined(RELEASE_OR_BETA)
-    if (mInterposeObserver) {
-      // We need to unregister the observer on the main thread, because that's
-      // where we've registered it.
-      if (NS_IsMainThread()) {
-        IOInterposer::Unregister(IOInterposeObserver::OpAll,
-                                 mInterposeObserver);
-      } else {
-        RefPtr<ProfilerIOInterposeObserver> observer = mInterposeObserver;
-        NS_DispatchToMainThread(
-            NS_NewRunnableFunction("ActivePS::~ActivePS", [=]() {
-              IOInterposer::Unregister(IOInterposeObserver::OpAll, observer);
-            }));
-      }
-    }
-#  endif
-  }
+  ~ActivePS() {}
 
   bool ThreadSelected(const char* aThreadName) {
     MOZ_RELEASE_ASSERT(sInstance);
 
     if (mFilters.empty()) {
       return true;
     }
 
@@ -655,27 +592,16 @@ class ActivePS {
     static bool Feature##Name_(PSLockRef) {                     \
       return ProfilerFeature::Has##Name_(sInstance->mFeatures); \
     }
 
   PROFILER_FOR_EACH_FEATURE(PS_GET_FEATURE)
 
 #  undef PS_GET_FEATURE
 
-  static uint32_t JSFlags(PSLockRef aLock) {
-    uint32_t Flags = 0;
-    Flags |= FeatureJS(aLock) ? uint32_t(JSSamplingFlags::StackSampling) : 0;
-    Flags |= FeatureTrackOptimizations(aLock)
-                 ? uint32_t(JSSamplingFlags::TrackOptimizations)
-                 : 0;
-    Flags |=
-        FeatureJSTracer(aLock) ? uint32_t(JSSamplingFlags::TraceLogging) : 0;
-    return Flags;
-  }
-
   PS_GET(const Vector<std::string>&, Filters)
 
   static ProfileBuffer& Buffer(PSLockRef) { return *sInstance->mBuffer.get(); }
 
   static const Vector<LiveProfiledThreadData>& LiveProfiledThreads(PSLockRef) {
     return sInstance->mLiveProfiledThreads;
   }
 
@@ -787,21 +713,21 @@ class ActivePS {
               aProfiledThreadData->BufferPositionWhenUnregistered();
           MOZ_RELEASE_ASSERT(bufferPosition,
                              "should have unregistered this thread");
           return *bufferPosition < bufferRangeStart;
         });
   }
 
   static void UnregisterPages(PSLockRef aLock,
-                              const nsID& aRegisteredDocShellId) {
+                              const std::string& aRegisteredDocShellId) {
     auto& registeredPages = CorePS::RegisteredPages(aLock);
     for (size_t i = 0; i < registeredPages.length(); i++) {
       RefPtr<PageInformation>& page = registeredPages[i];
-      if (page->DocShellId().Equals(aRegisteredDocShellId)) {
+      if (page->DocShellId() == aRegisteredDocShellId) {
         page->NotifyUnregistered(sInstance->mBuffer->mRangeEnd);
         MOZ_RELEASE_ASSERT(
             sInstance->mDeadProfiledPages.append(std::move(page)));
         registeredPages.erase(&registeredPages[i--]);
       }
     }
   }
 
@@ -818,67 +744,36 @@ class ActivePS {
           return *bufferPosition < bufferRangeStart;
         });
   }
 
   static void ClearUnregisteredPages(PSLockRef) {
     sInstance->mDeadProfiledPages.clear();
   }
 
-#  if !defined(RELEASE_OR_BETA)
-  static void UnregisterIOInterposer(PSLockRef) {
-    if (!sInstance->mInterposeObserver) {
-      return;
-    }
-
-    IOInterposer::Unregister(IOInterposeObserver::OpAll,
-                             sInstance->mInterposeObserver);
-
-    sInstance->mInterposeObserver = nullptr;
-  }
-
-  static void PauseIOInterposer(PSLockRef) {
-    if (!sInstance->mInterposeObserver) {
-      return;
-    }
-
-    IOInterposer::Unregister(IOInterposeObserver::OpAll,
-                             sInstance->mInterposeObserver);
-  }
-
-  static void ResumeIOInterposer(PSLockRef) {
-    if (!sInstance->mInterposeObserver) {
-      return;
-    }
-
-    IOInterposer::Register(IOInterposeObserver::OpAll,
-                           sInstance->mInterposeObserver);
-  }
-#  endif
-
   static void ClearExpiredExitProfiles(PSLockRef) {
     uint64_t bufferRangeStart = sInstance->mBuffer->mRangeStart;
     // Discard exit profiles that were gathered before our buffer RangeStart.
     sInstance->mExitProfiles.eraseIf(
         [bufferRangeStart](const ExitProfile& aExitProfile) {
           return aExitProfile.mBufferPositionAtGatherTime < bufferRangeStart;
         });
   }
 
-  static void AddExitProfile(PSLockRef aLock, const nsCString& aExitProfile) {
+  static void AddExitProfile(PSLockRef aLock, const std::string& aExitProfile) {
     ClearExpiredExitProfiles(aLock);
 
     MOZ_RELEASE_ASSERT(sInstance->mExitProfiles.append(
         ExitProfile{aExitProfile, sInstance->mBuffer->mRangeEnd}));
   }
 
-  static Vector<nsCString> MoveExitProfiles(PSLockRef aLock) {
+  static Vector<std::string> MoveExitProfiles(PSLockRef aLock) {
     ClearExpiredExitProfiles(aLock);
 
-    Vector<nsCString> profiles;
+    Vector<std::string> profiles;
     MOZ_RELEASE_ASSERT(
         profiles.initCapacity(sInstance->mExitProfiles.length()));
     for (auto& profile : sInstance->mExitProfiles) {
       MOZ_RELEASE_ASSERT(profiles.append(std::move(profile.mJSON)));
     }
     sInstance->mExitProfiles.clear();
     return profiles;
   }
@@ -940,45 +835,39 @@ class ActivePS {
   // We are removing them when we ensure that we won't need them anymore.
   Vector<RefPtr<PageInformation>> mDeadProfiledPages;
 
   // The current sampler thread. This class is not responsible for destroying
   // the SamplerThread object; the Destroy() method returns it so the caller
   // can destroy it.
   SamplerThread* const mSamplerThread;
 
-  // The interposer that records main thread I/O.
-  RefPtr<ProfilerIOInterposeObserver> mInterposeObserver;
-
   // Is the profiler paused?
   bool mIsPaused;
 
 #  if defined(GP_OS_linux)
   // Used to record whether the profiler was paused just before forking. False
   // at all times except just before/after forking.
   bool mWasPaused;
 #  endif
 
   struct ExitProfile {
-    nsCString mJSON;
+    std::string mJSON;
     uint64_t mBufferPositionAtGatherTime;
   };
   Vector<ExitProfile> mExitProfiles;
 };
 
 ActivePS* ActivePS::sInstance = nullptr;
 uint32_t ActivePS::sNextGeneration = 0;
 
 #  undef PS_GET
 #  undef PS_GET_LOCKLESS
 #  undef PS_GET_AND_SET
 
-// The mutex that guards accesses to CorePS and ActivePS.
-static PSMutex gPSMutex;
-
 Atomic<uint32_t, MemoryOrdering::Relaxed, recordreplay::Behavior::DontPreserve>
     RacyFeatures::sActiveAndFeatures(0);
 
 // Each live thread has a RegisteredThread, and we store a reference to it in
 // TLS. This class encapsulates that TLS.
 class TLSRegisteredThread {
  public:
   static bool Init(PSLockRef) {
@@ -1020,16 +909,21 @@ class TLSRegisteredThread {
   // CorePS::mRegisteredThreads is the owning reference. On thread
   // deregistration, this reference is cleared and the RegisteredThread is
   // destroyed.
   static MOZ_THREAD_LOCAL(class RegisteredThread*) sRegisteredThread;
 };
 
 MOZ_THREAD_LOCAL(RegisteredThread*) TLSRegisteredThread::sRegisteredThread;
 
+/* static */
+ProfilingStack* AutoProfilerLabel::GetProfilingStack() {
+  return sProfilingStack.get();
+}
+
 // Although you can access a thread's ProfilingStack via
 // TLSRegisteredThread::sRegisteredThread, we also have a second TLS pointer
 // directly to the ProfilingStack. Here's why.
 //
 // - We need to be able to push to and pop from the ProfilingStack in
 //   AutoProfilerLabel.
 //
 // - The class functions are hot and must be defined in BaseProfiler.h so they
@@ -1073,128 +967,62 @@ class Registers {
   // above. This is ok.
   ucontext_t* mContext;  // The context from the signal handler.
 #  endif
 };
 
 // Setting MAX_NATIVE_FRAMES too high risks the unwinder wasting a lot of time
 // looping on corrupted stacks.
 static const size_t MAX_NATIVE_FRAMES = 1024;
-static const size_t MAX_JS_FRAMES = 1024;
 
 struct NativeStack {
   void* mPCs[MAX_NATIVE_FRAMES];
   void* mSPs[MAX_NATIVE_FRAMES];
   size_t mCount;  // Number of frames filled.
 
   NativeStack() : mPCs(), mSPs(), mCount(0) {}
 };
 
-Atomic<bool> WALKING_JS_STACK(false);
-
-struct AutoWalkJSStack {
-  bool walkAllowed;
-
-  AutoWalkJSStack() : walkAllowed(false) {
-    walkAllowed = WALKING_JS_STACK.compareExchange(false, true);
-  }
-
-  ~AutoWalkJSStack() {
-    if (walkAllowed) {
-      WALKING_JS_STACK = false;
-    }
-  }
-};
-
-// Merges the profiling stack, native stack, and JS stack, outputting the
-// details to aCollector.
+// Merges the profiling stack and native stack, outputting the details to
+// aCollector.
 static void MergeStacks(uint32_t aFeatures, bool aIsSynchronous,
                         const RegisteredThread& aRegisteredThread,
                         const Registers& aRegs, const NativeStack& aNativeStack,
                         ProfilerStackCollector& aCollector) {
   // WARNING: this function runs within the profiler's "critical section".
   // WARNING: this function might be called while the profiler is inactive, and
   //          cannot rely on ActivePS.
 
   const ProfilingStack& profilingStack =
       aRegisteredThread.RacyRegisteredThread().ProfilingStack();
   const js::ProfilingStackFrame* profilingStackFrames = profilingStack.frames;
   uint32_t profilingStackFrameCount = profilingStack.stackSize();
-  JSContext* context = aRegisteredThread.GetJSContext();
-
-  // Make a copy of the JS stack into a JSFrame array. This is necessary since,
-  // like the native stack, the JS stack is iterated youngest-to-oldest and we
-  // need to iterate oldest-to-youngest when adding frames to aInfo.
-
-  // Non-periodic sampling passes Nothing() as the buffer write position to
-  // ProfilingFrameIterator to avoid incorrectly resetting the buffer position
-  // of sampled JIT frames inside the JS engine.
+
   Maybe<uint64_t> samplePosInBuffer;
   if (!aIsSynchronous) {
     // aCollector.SamplePositionInBuffer() will return Nothing() when
     // profiler_suspend_and_sample_thread is called from the background hang
     // reporter.
     samplePosInBuffer = aCollector.SamplePositionInBuffer();
   }
-  uint32_t jsCount = 0;
-  JS::ProfilingFrameIterator::Frame jsFrames[MAX_JS_FRAMES];
-
-  // Only walk jit stack if profiling frame iterator is turned on.
-  if (context && JS::IsProfilingEnabledForContext(context)) {
-    AutoWalkJSStack autoWalkJSStack;
-    const uint32_t maxFrames = ArrayLength(jsFrames);
-
-    if (autoWalkJSStack.walkAllowed) {
-      JS::ProfilingFrameIterator::RegisterState registerState;
-      registerState.pc = aRegs.mPC;
-      registerState.sp = aRegs.mSP;
-      registerState.lr = aRegs.mLR;
-      registerState.fp = aRegs.mFP;
-
-      JS::ProfilingFrameIterator jsIter(context, registerState,
-                                        samplePosInBuffer);
-      for (; jsCount < maxFrames && !jsIter.done(); ++jsIter) {
-        if (aIsSynchronous || jsIter.isWasm()) {
-          uint32_t extracted =
-              jsIter.extractStack(jsFrames, jsCount, maxFrames);
-          jsCount += extracted;
-          if (jsCount == maxFrames) {
-            break;
-          }
-        } else {
-          Maybe<JS::ProfilingFrameIterator::Frame> frame =
-              jsIter.getPhysicalFrameWithoutLabel();
-          if (frame.isSome()) {
-            jsFrames[jsCount++] = frame.value();
-          }
-        }
-      }
-    }
-  }
-
   // While the profiling stack array is ordered oldest-to-youngest, the JS and
   // native arrays are ordered youngest-to-oldest. We must add frames to aInfo
   // oldest-to-youngest. Thus, iterate over the profiling stack forwards and JS
   // and native arrays backwards. Note: this means the terminating condition
   // jsIndex and nativeIndex is being < 0.
   uint32_t profilingStackIndex = 0;
-  int32_t jsIndex = jsCount - 1;
   int32_t nativeIndex = aNativeStack.mCount - 1;
 
   uint8_t* lastLabelFrameStackAddr = nullptr;
-  uint8_t* jitEndStackAddr = nullptr;
 
   // Iterate as long as there is at least one frame remaining.
-  while (profilingStackIndex != profilingStackFrameCount || jsIndex >= 0 ||
-         nativeIndex >= 0) {
+  while (profilingStackIndex != profilingStackFrameCount || nativeIndex >= 0) {
     // There are 1 to 3 frames available. Find and add the oldest.
     uint8_t* profilingStackAddr = nullptr;
-    uint8_t* jsStackAddr = nullptr;
     uint8_t* nativeStackAddr = nullptr;
-    uint8_t* jsActivationAddr = nullptr;
 
     if (profilingStackIndex != profilingStackFrameCount) {
       const js::ProfilingStackFrame& profilingStackFrame =
           profilingStackFrames[profilingStackIndex];
 
       if (profilingStackFrame.isLabelFrame() ||
           profilingStackFrame.isSpMarkerFrame()) {
         lastLabelFrameStackAddr = (uint8_t*)profilingStackFrame.stackAddress();
@@ -1209,130 +1037,61 @@ static void MergeStacks(uint32_t aFeatur
         profilingStackIndex++;
         continue;
       }
 
       MOZ_ASSERT(lastLabelFrameStackAddr);
       profilingStackAddr = lastLabelFrameStackAddr;
     }
 
-    if (jsIndex >= 0) {
-      jsStackAddr = (uint8_t*)jsFrames[jsIndex].stackAddress;
-      jsActivationAddr = (uint8_t*)jsFrames[jsIndex].activation;
-    }
-
     if (nativeIndex >= 0) {
       nativeStackAddr = (uint8_t*)aNativeStack.mSPs[nativeIndex];
     }
 
     // If there's a native stack frame which has the same SP as a profiling
     // stack frame, pretend we didn't see the native stack frame.  Ditto for a
     // native stack frame which has the same SP as a JS stack frame.  In effect
     // this means profiling stack frames or JS frames trump conflicting native
     // frames.
-    if (nativeStackAddr && (profilingStackAddr == nativeStackAddr ||
-                            jsStackAddr == nativeStackAddr)) {
+    if (nativeStackAddr && (profilingStackAddr == nativeStackAddr)) {
       nativeStackAddr = nullptr;
       nativeIndex--;
-      MOZ_ASSERT(profilingStackAddr || jsStackAddr);
+      MOZ_ASSERT(profilingStackAddr);
     }
 
     // Sanity checks.
-    MOZ_ASSERT_IF(profilingStackAddr,
-                  profilingStackAddr != jsStackAddr &&
-                      profilingStackAddr != nativeStackAddr);
-    MOZ_ASSERT_IF(jsStackAddr, jsStackAddr != profilingStackAddr &&
-                                   jsStackAddr != nativeStackAddr);
-    MOZ_ASSERT_IF(nativeStackAddr, nativeStackAddr != profilingStackAddr &&
-                                       nativeStackAddr != jsStackAddr);
+    MOZ_ASSERT_IF(profilingStackAddr, profilingStackAddr != nativeStackAddr);
+    MOZ_ASSERT_IF(nativeStackAddr, nativeStackAddr != profilingStackAddr);
 
     // Check to see if profiling stack frame is top-most.
-    if (profilingStackAddr > jsStackAddr &&
-        profilingStackAddr > nativeStackAddr) {
+    if (profilingStackAddr > nativeStackAddr) {
       MOZ_ASSERT(profilingStackIndex < profilingStackFrameCount);
       const js::ProfilingStackFrame& profilingStackFrame =
           profilingStackFrames[profilingStackIndex];
 
       // Sp marker frames are just annotations and should not be recorded in
       // the profile.
       if (!profilingStackFrame.isSpMarkerFrame()) {
-        // The JIT only allows the top-most frame to have a nullptr pc.
-        MOZ_ASSERT_IF(
-            profilingStackFrame.isJsFrame() && profilingStackFrame.script() &&
-                !profilingStackFrame.pc(),
-            &profilingStackFrame ==
-                &profilingStack.frames[profilingStack.stackSize() - 1]);
         aCollector.CollectProfilingStackFrame(profilingStackFrame);
       }
       profilingStackIndex++;
       continue;
     }
 
-    // Check to see if JS jit stack frame is top-most
-    if (jsStackAddr > nativeStackAddr) {
-      MOZ_ASSERT(jsIndex >= 0);
-      const JS::ProfilingFrameIterator::Frame& jsFrame = jsFrames[jsIndex];
-      jitEndStackAddr = (uint8_t*)jsFrame.endStackAddress;
-      // Stringifying non-wasm JIT frames is delayed until streaming time. To
-      // re-lookup the entry in the JitcodeGlobalTable, we need to store the
-      // JIT code address (OptInfoAddr) in the circular buffer.
-      //
-      // Note that we cannot do this when we are sychronously sampling the
-      // current thread; that is, when called from profiler_get_backtrace. The
-      // captured backtrace is usually externally stored for an indeterminate
-      // amount of time, such as in nsRefreshDriver. Problematically, the
-      // stored backtrace may be alive across a GC during which the profiler
-      // itself is disabled. In that case, the JS engine is free to discard its
-      // JIT code. This means that if we inserted such OptInfoAddr entries into
-      // the buffer, nsRefreshDriver would now be holding on to a backtrace
-      // with stale JIT code return addresses.
-      if (aIsSynchronous ||
-          jsFrame.kind == JS::ProfilingFrameIterator::Frame_Wasm) {
-        aCollector.CollectWasmFrame(jsFrame.label);
-      } else {
-        MOZ_ASSERT(jsFrame.kind == JS::ProfilingFrameIterator::Frame_Ion ||
-                   jsFrame.kind == JS::ProfilingFrameIterator::Frame_Baseline);
-        aCollector.CollectJitReturnAddr(jsFrame.returnAddress);
-      }
-
-      jsIndex--;
-      continue;
-    }
-
     // If we reach here, there must be a native stack frame and it must be the
     // greatest frame.
-    if (nativeStackAddr &&
-        // If the latest JS frame was JIT, this could be the native frame that
-        // corresponds to it. In that case, skip the native frame, because
-        // there's no need for the same frame to be present twice in the stack.
-        // The JS frame can be considered the symbolicated version of the native
-        // frame.
-        (!jitEndStackAddr || nativeStackAddr < jitEndStackAddr) &&
-        // This might still be a JIT operation, check to make sure that is not
-        // in range of the NEXT JavaScript's stacks' activation address.
-        (!jsActivationAddr || nativeStackAddr > jsActivationAddr)) {
+    if (nativeStackAddr) {
       MOZ_ASSERT(nativeIndex >= 0);
       void* addr = (void*)aNativeStack.mPCs[nativeIndex];
       aCollector.CollectNativeLeafAddr(addr);
     }
     if (nativeIndex >= 0) {
       nativeIndex--;
     }
   }
-
-  // Update the JS context with the current profile sample buffer generation.
-  //
-  // Only do this for periodic samples. We don't want to do this for
-  // synchronous samples, and we also don't want to do it for calls to
-  // profiler_suspend_and_sample_thread() from the background hang reporter -
-  // in that case, aCollector.BufferRangeStart() will return Nothing().
-  if (!aIsSynchronous && context && aCollector.BufferRangeStart()) {
-    uint64_t bufferRangeStart = *aCollector.BufferRangeStart();
-    JS::SetJSContextProfilerSampleBufferRangeStart(context, bufferRangeStart);
-  }
 }
 
 #  if defined(GP_OS_windows) && defined(USE_MOZ_STACK_WALK)
 static HANDLE GetThreadHandle(PlatformData* aData);
 #  endif
 
 #  if defined(USE_FRAME_POINTER_STACK_WALK) || defined(USE_MOZ_STACK_WALK)
 static void StackWalkCallback(uint32_t aFrameNumber, void* aPC, void* aSP,
@@ -1404,57 +1163,17 @@ static void DoEHABIBacktrace(PSLockRef a
   // WARNING: this function might be called while the profiler is inactive, and
   //          cannot rely on ActivePS.
 
   const mcontext_t* mcontext = &aRegs.mContext->uc_mcontext;
   mcontext_t savedContext;
   const ProfilingStack& profilingStack =
       aRegisteredThread.RacyRegisteredThread().ProfilingStack();
 
-  // The profiling stack contains an "EnterJIT" frame whenever we enter
-  // JIT code with profiling enabled; the stack pointer value points
-  // the saved registers.  We use this to unwind resume unwinding
-  // after encounting JIT code.
-  for (uint32_t i = profilingStack.stackSize(); i > 0; --i) {
-    // The profiling stack grows towards higher indices, so we iterate
-    // backwards (from callee to caller).
-    const js::ProfilingStackFrame& frame = profilingStack.frames[i - 1];
-    if (!frame.isJsFrame() && strcmp(frame.label(), "EnterJIT") == 0) {
-      // Found JIT entry frame.  Unwind up to that point (i.e., force
-      // the stack walk to stop before the block of saved registers;
-      // note that it yields nondecreasing stack pointers), then restore
-      // the saved state.
-      uint32_t* vSP = reinterpret_cast<uint32_t*>(frame.stackAddress());
-
-      aNativeStack.mCount +=
-          EHABIStackWalk(*mcontext, /* stackBase = */ vSP,
-                         aNativeStack.mSPs + aNativeStack.mCount,
-                         aNativeStack.mPCs + aNativeStack.mCount,
-                         MAX_NATIVE_FRAMES - aNativeStack.mCount);
-
-      memset(&savedContext, 0, sizeof(savedContext));
-
-      // See also: struct EnterJITStack in js/src/jit/arm/Trampoline-arm.cpp
-      savedContext.arm_r4 = *vSP++;
-      savedContext.arm_r5 = *vSP++;
-      savedContext.arm_r6 = *vSP++;
-      savedContext.arm_r7 = *vSP++;
-      savedContext.arm_r8 = *vSP++;
-      savedContext.arm_r9 = *vSP++;
-      savedContext.arm_r10 = *vSP++;
-      savedContext.arm_fp = *vSP++;
-      savedContext.arm_lr = *vSP++;
-      savedContext.arm_sp = reinterpret_cast<uint32_t>(vSP);
-      savedContext.arm_pc = savedContext.arm_lr;
-      mcontext = &savedContext;
-    }
-  }
-
-  // Now unwind whatever's left (starting from either the last EnterJIT frame
-  // or, if no EnterJIT was found, the original registers).
+  // Now unwind whatever's left (starting from the original registers).
   aNativeStack.mCount +=
       EHABIStackWalk(*mcontext, const_cast<void*>(aRegisteredThread.StackTop()),
                      aNativeStack.mSPs + aNativeStack.mCount,
                      aNativeStack.mPCs + aNativeStack.mCount,
                      MAX_NATIVE_FRAMES - aNativeStack.mCount);
 }
 #  endif
 
@@ -1710,23 +1429,16 @@ static void DoPeriodicSample(PSLockRef a
 
   ProfilerMarkerLinkedList* pendingMarkersList =
       aRegisteredThread.RacyRegisteredThread().GetPendingMarkers();
   while (pendingMarkersList && pendingMarkersList->peek()) {
     ProfilerMarker* marker = pendingMarkersList->popHead();
     buffer.AddStoredMarker(marker);
     buffer.AddEntry(ProfileBufferEntry::Marker(marker));
   }
-
-  ThreadResponsiveness* resp = aProfiledThreadData.GetThreadResponsiveness();
-  if (resp && resp->HasData()) {
-    double delta = resp->GetUnresponsiveDuration(
-        (aNow - CorePS::ProcessStartTime()).ToMilliseconds());
-    buffer.AddEntry(ProfileBufferEntry::Responsiveness(delta));
-  }
 }
 
 // END sampling/unwinding code
 ////////////////////////////////////////////////////////////////////////
 
 ////////////////////////////////////////////////////////////////////////
 // BEGIN saving/streaming code
 
@@ -1737,85 +1449,33 @@ static int64_t SafeJSInteger(uint64_t aV
 }
 
 static void AddSharedLibraryInfoToStream(JSONWriter& aWriter,
                                          const SharedLibrary& aLib) {
   aWriter.StartObjectElement();
   aWriter.IntProperty("start", SafeJSInteger(aLib.GetStart()));
   aWriter.IntProperty("end", SafeJSInteger(aLib.GetEnd()));
   aWriter.IntProperty("offset", SafeJSInteger(aLib.GetOffset()));
-  aWriter.StringProperty("name",
-                         NS_ConvertUTF16toUTF8(aLib.GetModuleName()).get());
-  aWriter.StringProperty("path",
-                         NS_ConvertUTF16toUTF8(aLib.GetModulePath()).get());
-  aWriter.StringProperty("debugName",
-                         NS_ConvertUTF16toUTF8(aLib.GetDebugName()).get());
-  aWriter.StringProperty("debugPath",
-                         NS_ConvertUTF16toUTF8(aLib.GetDebugPath()).get());
-  aWriter.StringProperty("breakpadId", aLib.GetBreakpadId().get());
+  aWriter.StringProperty("name", aLib.GetModuleName().c_str());
+  aWriter.StringProperty("path", aLib.GetModulePath().c_str());
+  aWriter.StringProperty("debugName", aLib.GetDebugName().c_str());
+  aWriter.StringProperty("debugPath", aLib.GetDebugPath().c_str());
+  aWriter.StringProperty("breakpadId", aLib.GetBreakpadId().c_str());
   aWriter.StringProperty("arch", aLib.GetArch().c_str());
   aWriter.EndObject();
 }
 
 void AppendSharedLibraries(JSONWriter& aWriter) {
   SharedLibraryInfo info = SharedLibraryInfo::GetInfoForSelf();
   info.SortByAddress();
   for (size_t i = 0; i < info.GetSize(); i++) {
     AddSharedLibraryInfoToStream(aWriter, info.GetEntry(i));
   }
 }
 
-#  ifdef MOZ_TASK_TRACER
-static void StreamNameAndThreadId(JSONWriter& aWriter, const char* aName,
-                                  int aThreadId) {
-  aWriter.StartObjectElement();
-  {
-    if (XRE_GetProcessType() == GeckoProcessType_Plugin) {
-      // TODO Add the proper plugin name
-      aWriter.StringProperty("name", "Plugin");
-    } else {
-      aWriter.StringProperty("name", aName);
-    }
-    aWriter.IntProperty("tid", aThreadId);
-  }
-  aWriter.EndObject();
-}
-#  endif
-
-static void StreamTaskTracer(PSLockRef aLock, SpliceableJSONWriter& aWriter) {
-#  ifdef MOZ_TASK_TRACER
-  MOZ_RELEASE_ASSERT(CorePS::Exists() && ActivePS::Exists(aLock));
-
-  aWriter.StartArrayProperty("data");
-  {
-    UniquePtr<Vector<nsCString>> data =
-        tasktracer::GetLoggedData(CorePS::ProcessStartTime());
-    for (const nsCString& dataString : *data) {
-      aWriter.StringElement(dataString.get());
-    }
-  }
-  aWriter.EndArray();
-
-  aWriter.StartArrayProperty("threads");
-  {
-    ActivePS::DiscardExpiredDeadProfiledThreads(aLock);
-    Vector<Pair<RegisteredThread*, ProfiledThreadData*>> threads =
-        ActivePS::ProfiledThreads(aLock);
-    for (auto& thread : threads) {
-      RefPtr<ThreadInfo> info = thread.second()->Info();
-      StreamNameAndThreadId(aWriter, info->Name(), info->ThreadId());
-    }
-  }
-  aWriter.EndArray();
-
-  aWriter.DoubleProperty("start",
-                         static_cast<double>(tasktracer::GetStartTime()));
-#  endif
-}
-
 static void StreamCategories(SpliceableJSONWriter& aWriter) {
   // Same order as ProfilingCategory.
 
 #  define CATEGORY_JSON_BEGIN_CATEGORY(name, labelAsString, color) \
     aWriter.Start();                                               \
     aWriter.StringProperty("name", labelAsString);                 \
     aWriter.StringProperty("color", color);
 #  define CATEGORY_JSON_SUBCATEGORY(category, name, labelAsString)
@@ -1824,45 +1484,46 @@ static void StreamCategories(SpliceableJ
   PROFILING_CATEGORY_LIST(CATEGORY_JSON_BEGIN_CATEGORY,
                           CATEGORY_JSON_SUBCATEGORY, CATEGORY_JSON_END_CATEGORY)
 
 #  undef CATEGORY_JSON_BEGIN_CATEGORY
 #  undef CATEGORY_JSON_SUBCATEGORY
 #  undef CATEGORY_JSON_END_CATEGORY
 }
 
+static int64_t MicrosecondsSince1970();
+
 static void StreamMetaJSCustomObject(PSLockRef aLock,
                                      SpliceableJSONWriter& aWriter,
                                      bool aIsShuttingDown) {
   MOZ_RELEASE_ASSERT(CorePS::Exists() && ActivePS::Exists(aLock));
 
   aWriter.IntProperty("version", 15);
 
   // The "startTime" field holds the number of milliseconds since midnight
   // January 1, 1970 GMT. This grotty code computes (Now - (Now -
   // ProcessStartTime)) to convert CorePS::ProcessStartTime() into that form.
   TimeDuration delta = TimeStamp::Now() - CorePS::ProcessStartTime();
   aWriter.DoubleProperty(
-      "startTime",
-      static_cast<double>(PR_Now() / 1000.0 - delta.ToMilliseconds()));
+      "startTime", MicrosecondsSince1970() / 1000.0 - delta.ToMilliseconds());
 
   // Write the shutdownTime field. Unlike startTime, shutdownTime is not an
   // absolute time stamp: It's relative to startTime. This is consistent with
   // all other (non-"startTime") times anywhere in the profile JSON.
   if (aIsShuttingDown) {
     aWriter.DoubleProperty("shutdownTime", profiler_time());
   } else {
     aWriter.NullProperty("shutdownTime");
   }
 
   aWriter.StartArrayProperty("categories");
   StreamCategories(aWriter);
   aWriter.EndArray();
 
-  if (!NS_IsMainThread()) {
+  if (!CorePS::IsMainThread()) {
     // Leave the rest of the properties out if we're not on the main thread.
     // At the moment, the only case in which this function is called on a
     // background thread is if we're in a content process and are going to
     // send this profile to the parent process. In that case, the parent
     // process profile's "meta" object already has the rest of the properties,
     // and the parent process profile is dumped on that process's main thread.
     return;
   }
@@ -1871,185 +1532,31 @@ static void StreamMetaJSCustomObject(PSL
   aWriter.IntProperty("stackwalk", ActivePS::FeatureStackWalk(aLock));
 
 #  ifdef DEBUG
   aWriter.IntProperty("debug", 1);
 #  else
   aWriter.IntProperty("debug", 0);
 #  endif
 
-  aWriter.IntProperty("gcpoison", JS::IsGCPoisoning() ? 1 : 0);
-
-  bool asyncStacks = Preferences::GetBool("javascript.options.asyncstack");
-  aWriter.IntProperty("asyncstack", asyncStacks);
-
-  aWriter.IntProperty("processType", XRE_GetProcessType());
-
-  aWriter.StringProperty("updateChannel", NS_STRINGIFY(MOZ_UPDATE_CHANNEL));
-
-  nsresult res;
-  nsCOMPtr<nsIHttpProtocolHandler> http =
-      do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &res);
-
-  if (!NS_FAILED(res)) {
-    nsAutoCString string;
-
-    res = http->GetPlatform(string);
-    if (!NS_FAILED(res)) {
-      aWriter.StringProperty("platform", string.Data());
-    }
-
-    res = http->GetOscpu(string);
-    if (!NS_FAILED(res)) {
-      aWriter.StringProperty("oscpu", string.Data());
-    }
-
-    res = http->GetMisc(string);
-    if (!NS_FAILED(res)) {
-      aWriter.StringProperty("misc", string.Data());
-    }
-  }
-
-  nsCOMPtr<nsIXULRuntime> runtime = do_GetService("@mozilla.org/xre/runtime;1");
-  if (runtime) {
-    nsAutoCString string;
-
-    res = runtime->GetXPCOMABI(string);
-    if (!NS_FAILED(res)) aWriter.StringProperty("abi", string.Data());
-
-    res = runtime->GetWidgetToolkit(string);
-    if (!NS_FAILED(res)) aWriter.StringProperty("toolkit", string.Data());
-  }
-
-  nsCOMPtr<nsIXULAppInfo> appInfo =
-      do_GetService("@mozilla.org/xre/app-info;1");
-
-  if (appInfo) {
-    nsAutoCString string;
-    res = appInfo->GetName(string);
-    if (!NS_FAILED(res)) aWriter.StringProperty("product", string.Data());
-
-    res = appInfo->GetAppBuildID(string);
-    if (!NS_FAILED(res)) aWriter.StringProperty("appBuildID", string.Data());
-
-    res = appInfo->GetSourceURL(string);
-    if (!NS_FAILED(res)) aWriter.StringProperty("sourceURL", string.Data());
-  }
-
-  nsCOMPtr<nsIPropertyBag2> systemInfo =
-      do_GetService("@mozilla.org/system-info;1");
-  if (systemInfo) {
-    int32_t cpus;
-    res = systemInfo->GetPropertyAsInt32(NS_LITERAL_STRING("cpucores"), &cpus);
-    if (!NS_FAILED(res)) {
-      aWriter.IntProperty("physicalCPUs", cpus);
-    }
-    res = systemInfo->GetPropertyAsInt32(NS_LITERAL_STRING("cpucount"), &cpus);
-    if (!NS_FAILED(res)) {
-      aWriter.IntProperty("logicalCPUs", cpus);
-    }
-  }
-
-  // We should avoid collecting extension metadata for profiler while XPCOM is
-  // shutting down since it cannot create a new ExtensionPolicyService.
-  if (!gXPCOMShuttingDown) {
-    aWriter.StartObjectProperty("extensions");
-    {
-      {
-        JSONSchemaWriter schema(aWriter);
-        schema.WriteField("id");
-        schema.WriteField("name");
-        schema.WriteField("baseURL");
-      }
-
-      aWriter.StartArrayProperty("data");
-      {
-        nsTArray<RefPtr<WebExtensionPolicy>> exts;
-        ExtensionPolicyService::GetSingleton().GetAll(exts);
-
-        for (auto& ext : exts) {
-          aWriter.StartArrayElement(JSONWriter::SingleLineStyle);
-
-          nsAutoString id;
-          ext->GetId(id);
-          aWriter.StringElement(NS_ConvertUTF16toUTF8(id).get());
-
-          aWriter.StringElement(NS_ConvertUTF16toUTF8(ext->Name()).get());
-
-          auto url = ext->GetURL(NS_LITERAL_STRING(""));
-          if (url.isOk()) {
-            aWriter.StringElement(NS_ConvertUTF16toUTF8(url.unwrap()).get());
-          }
-
-          aWriter.EndArray();
-        }
-      }
-      aWriter.EndArray();
-    }
-    aWriter.EndObject();
-  }
+  aWriter.IntProperty("gcpoison", 0);
+
+  aWriter.IntProperty("asyncstack", 0);
+
+  aWriter.IntProperty("processType", 0);
 }
 
 static void StreamPages(PSLockRef aLock, SpliceableJSONWriter& aWriter) {
   MOZ_RELEASE_ASSERT(CorePS::Exists());
   ActivePS::DiscardExpiredPages(aLock);
   for (const auto& page : ActivePS::ProfiledPages(aLock)) {
     page->StreamJSON(aWriter);
   }
 }
 
-#  if defined(GP_OS_android)
-static UniquePtr<ProfileBuffer> CollectJavaThreadProfileData() {
-  // locked_profiler_start uses sample count is 1000 for Java thread.
-  // This entry size is enough now, but we might have to estimate it
-  // if we can customize it
-  auto buffer = MakeUnique<ProfileBuffer>(1000 * 1000);
-
-  int sampleId = 0;
-  while (true) {
-    double sampleTime = java::GeckoJavaSampler::GetSampleTime(0, sampleId);
-    if (sampleTime == 0.0) {
-      break;
-    }
-
-    buffer->AddThreadIdEntry(0);
-    buffer->AddEntry(ProfileBufferEntry::Time(sampleTime));
-    bool parentFrameWasIdleFrame = false;
-    int frameId = 0;
-    while (true) {
-      jni::String::LocalRef frameName =
-          java::GeckoJavaSampler::GetFrameName(0, sampleId, frameId++);
-      if (!frameName) {
-        break;
-      }
-      nsCString frameNameString = frameName->ToCString();
-
-      // Compute a category pair for the frame:
-      //  - IDLE for the wait function android.os.MessageQueue.nativePollOnce()
-      //  - OTHER for any function that's directly called by that wait function
-      //  - no category on everything else
-      Maybe<JS::ProfilingCategoryPair> categoryPair;
-      if (frameNameString.EqualsLiteral(
-              "android.os.MessageQueue.nativePollOnce()")) {
-        categoryPair = Some(JS::ProfilingCategoryPair::IDLE);
-        parentFrameWasIdleFrame = true;
-      } else if (parentFrameWasIdleFrame) {
-        categoryPair = Some(JS::ProfilingCategoryPair::OTHER);
-        parentFrameWasIdleFrame = false;
-      }
-
-      buffer->CollectCodeLocation("", frameNameString.get(), 0, Nothing(),
-                                  Nothing(), categoryPair);
-    }
-    sampleId++;
-  }
-  return buffer;
-}
-#  endif
-
 static void locked_profiler_stream_json_for_this_process(
     PSLockRef aLock, SpliceableJSONWriter& aWriter, double aSinceTime,
     bool aIsShuttingDown) {
   LOG("locked_profiler_stream_json_for_this_process");
 
   MOZ_RELEASE_ASSERT(CorePS::Exists() && ActivePS::Exists(aLock));
 
   double collectionStart = profiler_time();
@@ -2071,76 +1578,31 @@ static void locked_profiler_stream_json_
   { StreamPages(aLock, aWriter); }
   aWriter.EndArray();
 
   buffer.StreamProfilerOverheadToJSON(aWriter, CorePS::ProcessStartTime(),
                                       aSinceTime);
   buffer.StreamCountersToJSON(aWriter, CorePS::ProcessStartTime(), aSinceTime);
   buffer.StreamMemoryToJSON(aWriter, CorePS::ProcessStartTime(), aSinceTime);
 
-  // Data of TaskTracer doesn't belong in the circular buffer.
-  if (ActivePS::FeatureTaskTracer(aLock)) {
-    aWriter.StartObjectProperty("tasktracer");
-    StreamTaskTracer(aLock, aWriter);
-    aWriter.EndObject();
-  }
-
   // Lists the samples for each thread profile
   aWriter.StartArrayProperty("threads");
   {
     ActivePS::DiscardExpiredDeadProfiledThreads(aLock);
     Vector<Pair<RegisteredThread*, ProfiledThreadData*>> threads =
         ActivePS::ProfiledThreads(aLock);
     for (auto& thread : threads) {
-      RegisteredThread* registeredThread = thread.first();
-      JSContext* cx =
-          registeredThread ? registeredThread->GetJSContext() : nullptr;
       ProfiledThreadData* profiledThreadData = thread.second();
-      profiledThreadData->StreamJSON(buffer, cx, aWriter,
+      profiledThreadData->StreamJSON(buffer, aWriter,
                                      CorePS::ProcessName(aLock),
-                                     CorePS::ProcessStartTime(), aSinceTime,
-                                     ActivePS::FeatureJSTracer(aLock));
+                                     CorePS::ProcessStartTime(), aSinceTime);
     }
-
-#  if defined(GP_OS_android)
-    if (ActivePS::FeatureJava(aLock)) {
-      java::GeckoJavaSampler::Pause();
-
-      UniquePtr<ProfileBuffer> javaBuffer = CollectJavaThreadProfileData();
-
-      // Thread id of java Main thread is 0, if we support profiling of other
-      // java thread, we have to get thread id and name via JNI.
-      RefPtr<ThreadInfo> threadInfo = new ThreadInfo(
-          "Java Main Thread", 0, false, CorePS::ProcessStartTime());
-      ProfiledThreadData profiledThreadData(
-          threadInfo, nullptr, ActivePS::FeatureResponsiveness(aLock));
-      profiledThreadData.StreamJSON(*javaBuffer.get(), nullptr, aWriter,
-                                    CorePS::ProcessName(aLock),
-                                    CorePS::ProcessStartTime(), aSinceTime,
-                                    ActivePS::FeatureJSTracer(aLock));
-
-      java::GeckoJavaSampler::Unpause();
-    }
-#  endif
   }
   aWriter.EndArray();
 
-  if (ActivePS::FeatureJSTracer(aLock)) {
-    aWriter.StartArrayProperty("jsTracerDictionary");
-    {
-      JS::AutoTraceLoggerLockGuard lockGuard;
-      // Collect Event Dictionary
-      JS::TraceLoggerDictionaryBuffer collectionBuffer(lockGuard);
-      while (collectionBuffer.NextChunk()) {
-        aWriter.StringElement(collectionBuffer.internalBuffer());
-      }
-    }
-    aWriter.EndArray();
-  }
-
   aWriter.StartArrayProperty("pausedRanges");
   { buffer.StreamPausedRangesToJSON(aWriter, aSinceTime); }
   aWriter.EndArray();
 
   double collectionEnd = profiler_time();
 
   // Record timestamps for the collection into the buffer, so that consumers
   // know why we didn't collect any samples for its duration.
@@ -2153,32 +1615,24 @@ static void locked_profiler_stream_json_
 
 bool profiler_stream_json_for_this_process(SpliceableJSONWriter& aWriter,
                                            double aSinceTime,
                                            bool aIsShuttingDown) {
   LOG("profiler_stream_json_for_this_process");
 
   MOZ_RELEASE_ASSERT(CorePS::Exists());
 
-  PSAutoLock lock(gPSMutex);
+  PSAutoLock lock;
 
   if (!ActivePS::Exists(lock)) {
     return false;
   }
 
-#  if !defined(RELEASE_OR_BETA)
-  ActivePS::PauseIOInterposer(lock);
-#  endif
-
   locked_profiler_stream_json_for_this_process(lock, aWriter, aSinceTime,
                                                aIsShuttingDown);
-#  if !defined(RELEASE_OR_BETA)
-  ActivePS::ResumeIOInterposer(lock);
-#  endif
-
   return true;
 }
 
 // END saving/streaming code
 ////////////////////////////////////////////////////////////////////////
 
 static char FeatureCategory(uint32_t aFeature) {
   if (aFeature & DefaultFeatures()) {
@@ -2197,28 +1651,27 @@ static char FeatureCategory(uint32_t aFe
 
   if (aFeature & AvailableFeatures()) {
     return '-';
   }
   return 'x';
 }
 
 static void PrintUsageThenExit(int aExitCode) {
-  MOZ_RELEASE_ASSERT(NS_IsMainThread());
-
   printf(
       "\n"
       "Profiler environment variable usage:\n"
       "\n"
       "  MOZ_PROFILER_HELP\n"
       "  If set to any value, prints this message.\n"
       "\n"
-      "  MOZ_LOG\n"
-      "  Enables logging. The levels of logging available are\n"
-      "  'prof:3' (least verbose), 'prof:4', 'prof:5' (most verbose).\n"
+      "  MOZ_BASE_PROFILER_{,DEBUG_,VERBOSE}LOGGING\n"
+      "  Enables logging to stdout. The levels of logging available are\n"
+      "  'MOZ_BASE_PROFILER_LOGGING' (least verbose), '..._DEBUG_LOGGING',\n"
+      "  '..._VERBOSE_LOGGING' (most verbose)\n"
       "\n"
       "  MOZ_PROFILER_STARTUP\n"
       "  If set to any value, starts the profiler immediately on start-up.\n"
       "  Useful if you want profile code that runs very early.\n"
       "\n"
       "  MOZ_PROFILER_STARTUP_ENTRIES=<1..>\n"
       "  If MOZ_PROFILER_STARTUP is set, specifies the number of entries per\n"
       "  process in the profiler's circular buffer when the profiler is first\n"
@@ -2410,27 +1863,28 @@ class SamplerThread : public Sampler {
 static SamplerThread* NewSamplerThread(PSLockRef aLock, uint32_t aGeneration,
                                        double aInterval) {
   return new SamplerThread(aLock, aGeneration, aInterval);
 }
 
 // This function is the sampler thread.  This implementation is used for all
 // targets.
 void SamplerThread::Run() {
-  PR_SetCurrentThreadName("SamplerThread");
+  // TODO: If possible, name this thread later on, after NSPR becomes available.
+  // PR_SetCurrentThreadName("SamplerThread");
 
   // This will be positive if we are running behind schedule (sampling less
   // frequently than desired) and negative if we are ahead of schedule.
   TimeDuration lastSleepOvershoot = 0;
   TimeStamp sampleStart = TimeStamp::Now();
 
   while (true) {
     // This scope is for |lock|. It ends before we sleep below.
     {
-      PSAutoLock lock(gPSMutex);
+      PSAutoLock lock;
       TimeStamp lockAcquired = TimeStamp::Now();
 
       if (!ActivePS::Exists(lock)) {
         return;
       }
 
       // At this point profiler_stop() might have been called, and
       // profiler_start() might have been called on another thread. If this
@@ -2446,33 +1900,16 @@ void SamplerThread::Run() {
 
       if (!ActivePS::IsPaused(lock)) {
         const Vector<LiveProfiledThreadData>& liveThreads =
             ActivePS::LiveProfiledThreads(lock);
 
         TimeDuration delta = sampleStart - CorePS::ProcessStartTime();
         ProfileBuffer& buffer = ActivePS::Buffer(lock);
 
-        // Report memory use
-        int64_t rssMemory = 0;
-        int64_t ussMemory = 0;
-        if (ActivePS::FeatureMemory(lock)) {
-          rssMemory = nsMemoryReporterManager::ResidentFast();
-#  if defined(GP_OS_linux) || defined(GP_OS_android)
-          ussMemory = nsMemoryReporterManager::ResidentUnique();
-#  endif
-          if (rssMemory != 0) {
-            buffer.AddEntry(ProfileBufferEntry::ResidentMemory(rssMemory));
-            if (ussMemory != 0) {
-              buffer.AddEntry(ProfileBufferEntry::UnsharedMemory(ussMemory));
-            }
-          }
-          buffer.AddEntry(ProfileBufferEntry::Time(delta.ToMilliseconds()));
-        }
-
         // handle per-process generic counters
         const Vector<BaseProfilerCount*>& counters = CorePS::Counters(lock);
         TimeStamp now = TimeStamp::Now();
         for (auto& counter : counters) {
           // create Buffer entries for each counter
           buffer.AddEntry(ProfileBufferEntry::CounterId(counter));
           buffer.AddEntry(ProfileBufferEntry::Time(delta.ToMilliseconds()));
           // XXX support keyed maps of counts
@@ -2504,32 +1941,21 @@ void SamplerThread::Run() {
             bool dup_ok = ActivePS::Buffer(lock).DuplicateLastSample(
                 info->ThreadId(), CorePS::ProcessStartTime(),
                 profiledThreadData->LastSample());
             if (dup_ok) {
               continue;
             }
           }
 
-          ThreadResponsiveness* resp =
-              profiledThreadData->GetThreadResponsiveness();
-          if (resp) {
-            resp->Update();
-          }
-
           now = TimeStamp::Now();
           SuspendAndSampleAndResumeThread(
               lock, *registeredThread, [&](const Registers& aRegs) {
                 DoPeriodicSample(lock, *registeredThread, *profiledThreadData,
                                  now, aRegs);
-                // only report these once per sample-time (if 0 we don't put
-                // them in the buffer, so for the rest of the threads we won't
-                // insert them)
-                rssMemory = 0;
-                ussMemory = 0;
               });
         }
 
 #  if defined(USE_LUL_STACKWALK)
         // The LUL unwind object accumulates frame statistics. Periodically we
         // should poke it to give it a chance to print those statistics.  This
         // involves doing I/O (fprintf, __android_log_print, etc.) and so
         // can't safely be done from the critical section inside
@@ -2598,54 +2024,16 @@ UniquePlatformData AllocPlatformData(int
 void PlatformDataDestructor::operator()(PlatformData* aData) { delete aData; }
 
 // END SamplerThread
 ////////////////////////////////////////////////////////////////////////
 
 ////////////////////////////////////////////////////////////////////////
 // BEGIN externally visible functions
 
-MOZ_DEFINE_MALLOC_SIZE_OF(GeckoProfilerMallocSizeOf)
-
-NS_IMETHODIMP
-GeckoProfilerReporter::CollectReports(nsIHandleReportCallback* aHandleReport,
-                                      nsISupports* aData, bool aAnonymize) {
-  MOZ_RELEASE_ASSERT(NS_IsMainThread());
-
-  size_t profSize = 0;
-  size_t lulSize = 0;
-
-  {
-    PSAutoLock lock(gPSMutex);
-
-    if (CorePS::Exists()) {
-      CorePS::AddSizeOf(lock, GeckoProfilerMallocSizeOf, profSize, lulSize);
-    }
-
-    if (ActivePS::Exists(lock)) {
-      profSize += ActivePS::SizeOf(lock, GeckoProfilerMallocSizeOf);
-    }
-  }
-
-  MOZ_COLLECT_REPORT(
-      "explicit/profiler/profiler-state", KIND_HEAP, UNITS_BYTES, profSize,
-      "Memory used by the Gecko Profiler's global state (excluding memory used "
-      "by LUL).");
-
-#  if defined(USE_LUL_STACKWALK)
-  MOZ_COLLECT_REPORT(
-      "explicit/profiler/lul", KIND_HEAP, UNITS_BYTES, lulSize,
-      "Memory used by LUL, a stack unwinder used by the Gecko Profiler.");
-#  endif
-
-  return NS_OK;
-}
-
-NS_IMPL_ISUPPORTS(GeckoProfilerReporter, nsIMemoryReporter)
-
 static uint32_t ParseFeature(const char* aFeature, bool aIsStartup) {
   if (strcmp(aFeature, "default") == 0) {
     return (aIsStartup ? (DefaultFeatures() | StartupExtraDefaultFeatures())
                        : DefaultFeatures()) &
            AvailableFeatures();
   }
 
 #  define PARSE_FEATURE_BIT(n_, str_, Name_, desc_) \
@@ -2695,112 +2083,42 @@ static ProfilingStack* locked_register_t
   MOZ_RELEASE_ASSERT(!FindCurrentThreadRegisteredThread(aLock));
 
   VTUNE_REGISTER_THREAD(aName);
 
   if (!TLSRegisteredThread::Init(aLock)) {
     return nullptr;
   }
 
-  RefPtr<ThreadInfo> info =
-      new ThreadInfo(aName, profiler_current_thread_id(), NS_IsMainThread());
-  UniquePtr<RegisteredThread> registeredThread = MakeUnique<RegisteredThread>(
-      info, NS_GetCurrentThreadNoCreate(), aStackTop);
+  RefPtr<ThreadInfo> info = new ThreadInfo(aName, profiler_current_thread_id(),
+                                           CorePS::IsMainThread());
+  UniquePtr<RegisteredThread> registeredThread =
+      MakeUnique<RegisteredThread>(info, aStackTop);
 
   TLSRegisteredThread::SetRegisteredThread(aLock, registeredThread.get());
 
   if (ActivePS::Exists(aLock) && ActivePS::ShouldProfileThread(aLock, info)) {
     registeredThread->RacyRegisteredThread().SetIsBeingProfiled(true);
-    nsCOMPtr<nsIEventTarget> eventTarget = registeredThread->GetEventTarget();
-    ProfiledThreadData* profiledThreadData = ActivePS::AddLiveProfiledThread(
-        aLock, registeredThread.get(),
-        MakeUnique<ProfiledThreadData>(info, eventTarget,
-                                       ActivePS::FeatureResponsiveness(aLock)));
-
-    if (ActivePS::FeatureJS(aLock)) {
-      // This StartJSSampling() call is on-thread, so we can poll manually to
-      // start JS sampling immediately.
-      registeredThread->StartJSSampling(ActivePS::JSFlags(aLock));
-      registeredThread->PollJSSampling();
-      if (registeredThread->GetJSContext()) {
-        profiledThreadData->NotifyReceivedJSContext(
-            ActivePS::Buffer(aLock).mRangeEnd);
-      }
-    }
+    ActivePS::AddLiveProfiledThread(aLock, registeredThread.get(),
+                                    MakeUnique<ProfiledThreadData>(info));
   }
 
   ProfilingStack* profilingStack =
       &registeredThread->RacyRegisteredThread().ProfilingStack();
 
   CorePS::AppendRegisteredThread(aLock, std::move(registeredThread));
 
   return profilingStack;
 }
 
-static void NotifyObservers(const char* aTopic,
-                            nsISupports* aSubject = nullptr) {
-  if (!NS_IsMainThread()) {
-    // Dispatch a task to the main thread that notifies observers.
-    // If NotifyObservers is called both on and off the main thread within a
-    // short time, the order of the notifications can be different from the
-    // order of the calls to NotifyObservers.
-    // Getting the order 100% right isn't that important at the moment, because
-    // these notifications are only observed in the parent process, where the
-    // profiler_* functions are currently only called on the main thread.
-    nsCOMPtr<nsISupports> subject = aSubject;
-    NS_DispatchToMainThread(NS_NewRunnableFunction(
-        "NotifyObservers", [=] { NotifyObservers(aTopic, subject); }));
-    return;
-  }
-
-  if (nsCOMPtr<nsIObserverService> os = services::GetObserverService()) {
-    os->NotifyObservers(aSubject, aTopic, nullptr);
-  }
-}
-
-static void NotifyProfilerStarted(const int aCapacity,
-                                  const Maybe<double>& aDuration,
-                                  double aInterval, uint32_t aFeatures,
-                                  const char** aFilters,
-                                  uint32_t aFilterCount) {
-  nsTArray<nsCString> filtersArray;
-  for (size_t i = 0; i < aFilterCount; ++i) {
-    filtersArray.AppendElement(aFilters[i]);
-  }
-
-  nsCOMPtr<nsIProfilerStartParams> params = new nsProfilerStartParams(
-      aCapacity, aDuration, aInterval, aFeatures, std::move(filtersArray));
-
-  ProfilerParent::ProfilerStarted(params);
-  NotifyObservers("profiler-started", params);
-}
-
 static void locked_profiler_start(PSLockRef aLock, uint32_t aCapacity,
                                   double aInterval, uint32_t aFeatures,
                                   const char** aFilters, uint32_t aFilterCount,
                                   const Maybe<double>& aDuration);
 
-// This basically duplicates AutoProfilerLabel's constructor.
-ProfilingStack* MozGlueLabelEnter(const char* aLabel,
-                                  const char* aDynamicString, void* aSp) {
-  ProfilingStack* profilingStack = AutoProfilerLabel::sProfilingStack.get();
-  if (profilingStack) {
-    profilingStack->pushLabelFrame(aLabel, aDynamicString, aSp,
-                                   JS::ProfilingCategoryPair::OTHER);
-  }
-  return profilingStack;
-}
-
-// This basically duplicates AutoProfilerLabel's destructor.
-void MozGlueLabelExit(ProfilingStack* sProfilingStack) {
-  if (sProfilingStack) {
-    sProfilingStack->pop();
-  }
-}
-
 static Vector<const char*> SplitAtCommas(const char* aString,
                                          UniquePtr<char[]>& aStorage) {
   size_t len = strlen(aString);
   aStorage = MakeUnique<char[]>(len + 1);
   PodCopy(aStorage.get(), aString, len + 1);
 
   // Iterate over all characters in aStorage and split at commas, by
   // overwriting commas with the null char.
@@ -2831,49 +2149,34 @@ void profiler_init(void* aStackTop) {
 
   SharedLibraryInfo::Initialize();
 
   uint32_t features = DefaultFeatures() & AvailableFeatures();
 
   UniquePtr<char[]> filterStorage;
 
   Vector<const char*> filters;
-  MOZ_RELEASE_ASSERT(filters.append("GeckoMain"));
-  MOZ_RELEASE_ASSERT(filters.append("Compositor"));
-  MOZ_RELEASE_ASSERT(filters.append("DOM Worker"));
+  MOZ_RELEASE_ASSERT(filters.append(kMainThreadName));
 
   uint32_t capacity = PROFILER_DEFAULT_ENTRIES;
   Maybe<double> duration = Nothing();
   double interval = PROFILER_DEFAULT_INTERVAL;
 
   {
-    PSAutoLock lock(gPSMutex);
+    PSAutoLock lock;
 
     // We've passed the possible failure point. Instantiate CorePS, which
     // indicates that the profiler has initialized successfully.
     CorePS::Create(lock);
 
     locked_register_thread(lock, kMainThreadName, aStackTop);
 
     // Platform-specific initialization.
     PlatformInit(lock);
 
-#  ifdef MOZ_TASK_TRACER
-    tasktracer::InitTaskTracer();
-#  endif
-
-#  if defined(GP_OS_android)
-    if (jni::IsFennec()) {
-      GeckoJavaSampler::Init();
-    }
-#  endif
-
-    // Setup support for pushing/popping labels in mozglue.
-    RegisterProfilerLabelEnterExit(MozGlueLabelEnter, MozGlueLabelExit);
-
     // (Linux-only) We could create CorePS::mLul and read unwind info into it
     // at this point. That would match the lifetime implied by destruction of
     // it in profiler_shutdown() just below. However, that gives a big delay on
     // startup, even if no profiling is actually to be done. So, instead, it is
     // created on demand at the first call to PlatformStart().
 
     const char* startupEnv = getenv("MOZ_PROFILER_STARTUP");
     if (!startupEnv || startupEnv[0] == '\0') {
@@ -2900,41 +2203,45 @@ void profiler_init(void* aStackTop) {
         LOG("- MOZ_PROFILER_STARTUP_ENTRIES not a valid integer: %s",
             startupCapacity);
         PrintUsageThenExit(1);
       }
     }
 
     const char* startupDuration = getenv("MOZ_PROFILER_STARTUP_DURATION");
     if (startupDuration && startupDuration[0] != '\0') {
-      errno = 0;
-      double durationVal = PR_strtod(startupDuration, nullptr);
-      if (errno == 0 && durationVal >= 0.0) {
-        if (durationVal > 0.0) {
-          duration = Some(durationVal);
-        }
-        LOG("- MOZ_PROFILER_STARTUP_DURATION = %f", durationVal);
-      } else {
-        LOG("- MOZ_PROFILER_STARTUP_DURATION not a valid float: %s",
-            startupDuration);
-        PrintUsageThenExit(1);
-      }
+      // TODO implement if needed
+      MOZ_CRASH("MOZ_PROFILER_STARTUP_DURATION unsupported");
+      // errno = 0;
+      // double durationVal = PR_strtod(startupDuration, nullptr);
+      // if (errno == 0 && durationVal >= 0.0) {
+      //   if (durationVal > 0.0) {
+      //     duration = Some(durationVal);
+      //   }
+      //   LOG("- MOZ_PROFILER_STARTUP_DURATION = %f", durationVal);
+      // } else {
+      //   LOG("- MOZ_PROFILER_STARTUP_DURATION not a valid float: %s",
+      //       startupDuration);
+      //   PrintUsageThenExit(1);
+      // }
     }
 
     const char* startupInterval = getenv("MOZ_PROFILER_STARTUP_INTERVAL");
     if (startupInterval && startupInterval[0] != '\0') {
-      errno = 0;
-      interval = PR_strtod(startupInterval, nullptr);
-      if (errno == 0 && interval > 0.0 && interval <= 1000.0) {
-        LOG("- MOZ_PROFILER_STARTUP_INTERVAL = %f", interval);
-      } else {
-        LOG("- MOZ_PROFILER_STARTUP_INTERVAL not a valid float: %s",
-            startupInterval);
-        PrintUsageThenExit(1);
-      }
+      // TODO implement if needed
+      MOZ_CRASH("MOZ_PROFILER_STARTUP_INTERVAL unsupported");
+      // errno = 0;
+      // interval = PR_strtod(startupInterval, nullptr);
+      // if (errno == 0 && interval > 0.0 && interval <= 1000.0) {
+      //   LOG("- MOZ_PROFILER_STARTUP_INTERVAL = %f", interval);
+      // } else {
+      //   LOG("- MOZ_PROFILER_STARTUP_INTERVAL not a valid float: %s",
+      //       startupInterval);
+      //   PrintUsageThenExit(1);
+      // }
     }
 
     features |= StartupExtraDefaultFeatures() & AvailableFeatures();
 
     const char* startupFeaturesBitfield =
         getenv("MOZ_PROFILER_STARTUP_FEATURES_BITFIELD");
     if (startupFeaturesBitfield && startupFeaturesBitfield[0] != '\0') {
       errno = 0;
@@ -2966,82 +2273,68 @@ void profiler_init(void* aStackTop) {
       filters = SplitAtCommas(startupFilters, filterStorage);
       LOG("- MOZ_PROFILER_STARTUP_FILTERS = %s", startupFilters);
     }
 
     locked_profiler_start(lock, capacity, interval, features, filters.begin(),
                           filters.length(), duration);
   }
 
-#  if defined(MOZ_REPLACE_MALLOC) && defined(MOZ_PROFILER_MEMORY)
-  if (ProfilerFeature::HasMemory(features)) {
-    // start counting memory allocations (outside of lock because this may call
-    // profiler_add_sampled_counter which would attempt to take the lock.)
-    mozilla::profiler::install_memory_counter(true);
-  }
-#  endif
-
-  // We do this with gPSMutex unlocked. The comment in profiler_stop() explains
-  // why.
-  NotifyProfilerStarted(capacity, duration, interval, features, filters.begin(),
-                        filters.length());
+  // TODO: Install memory counter if it is possible from mozglue.
+  // #if defined(MOZ_REPLACE_MALLOC) && defined(MOZ_PROFILER_MEMORY)
+  //   if (ProfilerFeature::HasMemory(features)) {
+  //     // start counting memory allocations (outside of lock because this may
+  //     call
+  //     // profiler_add_sampled_counter which would attempt to take the lock.)
+  //     mozilla::profiler::install_memory_counter(true);
+  //   }
+  // #endif
 }
 
 static void locked_profiler_save_profile_to_file(PSLockRef aLock,
                                                  const char* aFilename,
                                                  bool aIsShuttingDown);
 
 static SamplerThread* locked_profiler_stop(PSLockRef aLock);
 
 void profiler_shutdown() {
   LOG("profiler_shutdown");
 
   VTUNE_SHUTDOWN();
 
-  MOZ_RELEASE_ASSERT(NS_IsMainThread());
+  MOZ_RELEASE_ASSERT(CorePS::IsMainThread());
   MOZ_RELEASE_ASSERT(CorePS::Exists());
 
   // If the profiler is active we must get a handle to the SamplerThread before
   // ActivePS is destroyed, in order to delete it.
   SamplerThread* samplerThread = nullptr;
   {
-    PSAutoLock lock(gPSMutex);
+    PSAutoLock lock;
 
     // Save the profile on shutdown if requested.
     if (ActivePS::Exists(lock)) {
       const char* filename = getenv("MOZ_PROFILER_SHUTDOWN");
       if (filename) {
-#  if !defined(RELEASE_OR_BETA)
-        // Attempting to record the I/O we are doing to the shutdown profile
-        // file while we are locked will deadlock.
-        ActivePS::UnregisterIOInterposer(lock);
-#  endif
         locked_profiler_save_profile_to_file(lock, filename,
                                              /* aIsShuttingDown */ true);
       }
 
       samplerThread = locked_profiler_stop(lock);
     }
 
     CorePS::Destroy(lock);
 
     // We just destroyed CorePS and the ThreadInfos it contains, so we can
     // clear this thread's TLSRegisteredThread.
     TLSRegisteredThread::SetRegisteredThread(lock, nullptr);
-
-#  ifdef MOZ_TASK_TRACER
-    tasktracer::ShutdownTaskTracer();
-#  endif
   }
 
   // We do these operations with gPSMutex unlocked. The comments in
   // profiler_stop() explain why.
   if (samplerThread) {
-    ProfilerParent::ProfilerStopped();
-    NotifyObservers("profiler-stopped");
     delete samplerThread;
   }
 }
 
 static bool WriteProfileToJSONWriter(SpliceableChunkedJSONWriter& aWriter,
                                      double aSinceTime, bool aIsShuttingDown) {
   LOG("WriteProfileToJSONWriter");
 
@@ -3058,19 +2351,19 @@ static bool WriteProfileToJSONWriter(Spl
     // synchronous function.
     aWriter.StartArrayProperty("processes");
     aWriter.EndArray();
   }
   aWriter.End();
   return true;
 }
 
-void profiler_set_process_name(const nsACString& aProcessName) {
-  LOG("profiler_set_process_name(\"%s\")", aProcessName.Data());
-  PSAutoLock lock(gPSMutex);
+void profiler_set_process_name(const std::string& aProcessName) {
+  LOG("profiler_set_process_name(\"%s\")", aProcessName.c_str());
+  PSAutoLock lock;
   CorePS::SetProcessName(lock, aProcessName);
 }
 
 UniquePtr<char[]> profiler_get_profile(double aSinceTime,
                                        bool aIsShuttingDown) {
   LOG("profiler_get_profile");
 
   SpliceableChunkedJSONWriter b;
@@ -3093,23 +2386,21 @@ void profiler_get_profile_json_into_lazi
   b.WriteFunc()->CopyDataIntoLazilyAllocatedBuffer(aAllocator);
 }
 
 void profiler_get_start_params(int* aCapacity, Maybe<double>* aDuration,
                                double* aInterval, uint32_t* aFeatures,
                                Vector<const char*>* aFilters) {
   MOZ_RELEASE_ASSERT(CorePS::Exists());
 
-  if (NS_WARN_IF(!aCapacity) || NS_WARN_IF(!aDuration) ||
-      NS_WARN_IF(!aInterval) || NS_WARN_IF(!aFeatures) ||
-      NS_WARN_IF(!aFilters)) {
+  if (!aCapacity || !aDuration || !aInterval || !aFeatures || !aFilters) {
     return;
   }
 
-  PSAutoLock lock(gPSMutex);
+  PSAutoLock lock;
 
   if (!ActivePS::Exists(lock)) {
     *aCapacity = 0;
     *aDuration = Nothing();
     *aInterval = 0;
     *aFeatures = 0;
     aFilters->clear();
     return;
@@ -3128,34 +2419,33 @@ void profiler_get_start_params(int* aCap
 }
 
 namespace mozilla {
 
 void GetProfilerEnvVarsForChildProcess(
     std::function<void(const char* key, const char* value)>&& aSetEnv) {
   MOZ_RELEASE_ASSERT(CorePS::Exists());
 
-  PSAutoLock lock(gPSMutex);
+  PSAutoLock lock;
 
   if (!ActivePS::Exists(lock)) {
     aSetEnv("MOZ_PROFILER_STARTUP", "");
     return;
   }
 
   aSetEnv("MOZ_PROFILER_STARTUP", "1");
   auto capacityString = Smprintf("%d", ActivePS::Capacity(lock));
   aSetEnv("MOZ_PROFILER_STARTUP_ENTRIES", capacityString.get());
 
   // Use AppendFloat instead of Smprintf with %f because the decimal
   // separator used by %f is locale-dependent. But the string we produce needs
   // to be parseable by strtod, which only accepts the period character as a
   // decimal separator. AppendFloat always uses the period character.
-  nsCString intervalString;
-  intervalString.AppendFloat(ActivePS::Interval(lock));
-  aSetEnv("MOZ_PROFILER_STARTUP_INTERVAL", intervalString.get());
+  std::string intervalString = std::to_string(ActivePS::Interval(lock));
+  aSetEnv("MOZ_PROFILER_STARTUP_INTERVAL", intervalString.c_str());
 
   auto featuresString = Smprintf("%d", ActivePS::Features(lock));
   aSetEnv("MOZ_PROFILER_STARTUP_FEATURES_BITFIELD", featuresString.get());
 
   std::string filtersString;
   const Vector<std::string>& filters = ActivePS::Filters(lock);
   for (uint32_t i = 0; i < filters.length(); ++i) {
     filtersString += filters[i];
@@ -3163,29 +2453,29 @@ void GetProfilerEnvVarsForChildProcess(
       filtersString += ",";
     }
   }
   aSetEnv("MOZ_PROFILER_STARTUP_FILTERS", filtersString.c_str());
 }
 
 }  // namespace mozilla
 
-void profiler_received_exit_profile(const nsCString& aExitProfile) {
+void profiler_received_exit_profile(const std::string& aExitProfile) {
   MOZ_RELEASE_ASSERT(CorePS::Exists());
-  PSAutoLock lock(gPSMutex);
+  PSAutoLock lock;
   if (!ActivePS::Exists(lock)) {
     return;
   }
   ActivePS::AddExitProfile(lock, aExitProfile);
 }
 
-Vector<nsCString> profiler_move_exit_profiles() {
+Vector<std::string> profiler_move_exit_profiles() {
   MOZ_RELEASE_ASSERT(CorePS::Exists());
-  PSAutoLock lock(gPSMutex);
-  Vector<nsCString> profiles;
+  PSAutoLock lock;
+  Vector<std::string> profiles;
   if (ActivePS::Exists(lock)) {
     profiles = ActivePS::MoveExitProfiles(lock);
   }
   return profiles;
 }
 
 static void locked_profiler_save_profile_to_file(PSLockRef aLock,
                                                  const char* aFilename,
@@ -3199,99 +2489,63 @@ static void locked_profiler_save_profile
   if (stream.is_open()) {
     SpliceableJSONWriter w(MakeUnique<OStreamJSONWriteFunc>(stream));
     w.Start();
     {
       locked_profiler_stream_json_for_this_process(aLock, w, /* sinceTime */ 0,
                                                    aIsShuttingDown);
 
       w.StartArrayProperty("processes");
-      Vector<nsCString> exitProfiles = ActivePS::MoveExitProfiles(aLock);
+      Vector<std::string> exitProfiles = ActivePS::MoveExitProfiles(aLock);
       for (auto& exitProfile : exitProfiles) {
-        if (!exitProfile.IsEmpty()) {
-          w.Splice(exitProfile.get());
+        if (!exitProfile.empty()) {
+          w.Splice(exitProfile.c_str());
         }
       }
       w.EndArray();
     }
     w.End();
 
     stream.close();
   }
 }
 
 void profiler_save_profile_to_file(const char* aFilename) {
   LOG("profiler_save_profile_to_file(%s)", aFilename);
 
   MOZ_RELEASE_ASSERT(CorePS::Exists());
 
-  PSAutoLock lock(gPSMutex);
+  PSAutoLock lock;
 
   if (!ActivePS::Exists(lock)) {
     return;
   }
 
   locked_profiler_save_profile_to_file(lock, aFilename);
 }
 
 uint32_t profiler_get_available_features() {
   MOZ_RELEASE_ASSERT(CorePS::Exists());
   return AvailableFeatures();
 }
 
 Maybe<ProfilerBufferInfo> profiler_get_buffer_info() {
   MOZ_RELEASE_ASSERT(CorePS::Exists());
 
-  PSAutoLock lock(gPSMutex);
+  PSAutoLock lock;
 
   if (!ActivePS::Exists(lock)) {
     return Nothing();
   }
 
   return Some(ProfilerBufferInfo{ActivePS::Buffer(lock).mRangeStart,
                                  ActivePS::Buffer(lock).mRangeEnd,
                                  ActivePS::Capacity(lock)});
 }
 
-static void PollJSSamplingForCurrentThread() {
-  MOZ_RELEASE_ASSERT(CorePS::Exists());
-
-  PSAutoLock lock(gPSMutex);
-
-  RegisteredThread* registeredThread =
-      TLSRegisteredThread::RegisteredThread(lock);
-  if (!registeredThread) {
-    return;
-  }
-
-  registeredThread->PollJSSampling();
-}
-
-// When the profiler is started on a background thread, we can't synchronously
-// call PollJSSampling on the main thread's ThreadInfo. And the next regular
-// call to PollJSSampling on the main thread would only happen once the main
-// thread triggers a JS interrupt callback.
-// This means that all the JS execution between profiler_start() and the first
-// JS interrupt would happen with JS sampling disabled, and we wouldn't get any
-// JS function information for that period of time.
-// So in order to start JS sampling as soon as possible, we dispatch a runnable
-// to the main thread which manually calls PollJSSamplingForCurrentThread().
-// In some cases this runnable will lose the race with the next JS interrupt.
-// That's fine; PollJSSamplingForCurrentThread() is immune to redundant calls.
-static void TriggerPollJSSamplingOnMainThread() {
-  nsCOMPtr<nsIThread> mainThread;
-  nsresult rv = NS_GetMainThread(getter_AddRefs(mainThread));
-  if (NS_SUCCEEDED(rv) && mainThread) {
-    nsCOMPtr<nsIRunnable> task =
-        NS_NewRunnableFunction("TriggerPollJSSamplingOnMainThread",
-                               []() { PollJSSamplingForCurrentThread(); });
-    SystemGroup::Dispatch(TaskCategory::Other, task.forget());
-  }
-}
-
 static void locked_profiler_start(PSLockRef aLock, uint32_t aCapacity,
                                   double aInterval, uint32_t aFeatures,
                                   const char** aFilters, uint32_t aFilterCount,
                                   const Maybe<double>& aDuration) {
   if (LOG_TEST) {
     LOG("locked_profiler_start");
     LOG("- capacity  = %d", aCapacity);
     LOG("- duration  = %.2f", aDuration ? *aDuration : -1);
@@ -3325,220 +2579,150 @@ static void locked_profiler_start(PSLock
     duration = Nothing();
   }
   double interval = aInterval > 0 ? aInterval : PROFILER_DEFAULT_INTERVAL;
 
   ActivePS::Create(aLock, capacity, interval, aFeatures, aFilters, aFilterCount,
                    duration);
 
   // Set up profiling for each registered thread, if appropriate.
-  int tid = profiler_current_thread_id();
   const Vector<UniquePtr<RegisteredThread>>& registeredThreads =
       CorePS::RegisteredThreads(aLock);
   for (auto& registeredThread : registeredThreads) {
     RefPtr<ThreadInfo> info = registeredThread->Info();
 
     if (ActivePS::ShouldProfileThread(aLock, info)) {
       registeredThread->RacyRegisteredThread().SetIsBeingProfiled(true);
-      nsCOMPtr<nsIEventTarget> eventTarget = registeredThread->GetEventTarget();
-      ProfiledThreadData* profiledThreadData = ActivePS::AddLiveProfiledThread(
-          aLock, registeredThread.get(),
-          MakeUnique<ProfiledThreadData>(
-              info, eventTarget, ActivePS::FeatureResponsiveness(aLock)));
-      if (ActivePS::FeatureJS(aLock)) {
-        registeredThread->StartJSSampling(ActivePS::JSFlags(aLock));
-        if (info->ThreadId() == tid) {
-          // We can manually poll the current thread so it starts sampling
-          // immediately.
-          registeredThread->PollJSSampling();
-        } else if (info->IsMainThread()) {
-          // Dispatch a runnable to the main thread to call PollJSSampling(),
-          // so that we don't have wait for the next JS interrupt callback in
-          // order to start profiling JS.
-          TriggerPollJSSamplingOnMainThread();
-        }
-      }
+      ActivePS::AddLiveProfiledThread(aLock, registeredThread.get(),
+                                      MakeUnique<ProfiledThreadData>(info));
       registeredThread->RacyRegisteredThread().ReinitializeOnResume();
-      if (registeredThread->GetJSContext()) {
-        profiledThreadData->NotifyReceivedJSContext(0);
-      }
     }
   }
 
-#  ifdef MOZ_TASK_TRACER
-  if (ActivePS::FeatureTaskTracer(aLock)) {
-    tasktracer::StartLogging();
-  }
-#  endif
-
-#  if defined(GP_OS_android)
-  if (ActivePS::FeatureJava(aLock)) {
-    int javaInterval = interval;
-    // Java sampling doesn't accurately keep up with 1ms sampling.
-    if (javaInterval < 10) {
-      javaInterval = 10;
-    }
-    java::GeckoJavaSampler::Start(javaInterval, 1000);
-  }
-#  endif
-
   // At the very end, set up RacyFeatures.
   RacyFeatures::SetActive(ActivePS::Features(aLock));
 }
 
 void profiler_start(uint32_t aCapacity, double aInterval, uint32_t aFeatures,
                     const char** aFilters, uint32_t aFilterCount,
                     const Maybe<double>& aDuration) {
   LOG("profiler_start");
 
   SamplerThread* samplerThread = nullptr;
   {
-    PSAutoLock lock(gPSMutex);
+    PSAutoLock lock;
 
     // Initialize if necessary.
     if (!CorePS::Exists()) {
       profiler_init(nullptr);
     }
 
     // Reset the current state if the profiler is running.
     if (ActivePS::Exists(lock)) {
       samplerThread = locked_profiler_stop(lock);
     }
 
     locked_profiler_start(lock, aCapacity, aInterval, aFeatures, aFilters,
                           aFilterCount, aDuration);
   }
 
-#  if defined(MOZ_REPLACE_MALLOC) && defined(MOZ_PROFILER_MEMORY)
-  if (ProfilerFeature::HasMemory(aFeatures)) {
-    // start counting memory allocations (outside of lock because this may call
-    // profiler_add_sampled_counter which would attempt to take the lock.)
-    mozilla::profiler::install_memory_counter(true);
-  }
-#  endif
+  // TODO: Install memory counter if it is possible from mozglue.
+  // #if defined(MOZ_REPLACE_MALLOC) && defined(MOZ_PROFILER_MEMORY)
+  //   if (ProfilerFeature::HasMemory(aFeatures)) {
+  //     // start counting memory allocations (outside of lock because this may
+  //     call
+  //     // profiler_add_sampled_counter which would attempt to take the lock.)
+  //     mozilla::profiler::install_memory_counter(true);
+  //   }
+  // #endif
 
   // We do these operations with gPSMutex unlocked. The comments in
   // profiler_stop() explain why.
   if (samplerThread) {
-    ProfilerParent::ProfilerStopped();
-    NotifyObservers("profiler-stopped");
     delete samplerThread;
   }
-  NotifyProfilerStarted(aCapacity, aDuration, aInterval, aFeatures, aFilters,
-                        aFilterCount);
 }
 
 void profiler_ensure_started(uint32_t aCapacity, double aInterval,
                              uint32_t aFeatures, const char** aFilters,
                              uint32_t aFilterCount,
                              const Maybe<double>& aDuration) {
   LOG("profiler_ensure_started");
 
   bool startedProfiler = false;
   SamplerThread* samplerThread = nullptr;
   {
-    PSAutoLock lock(gPSMutex);
+    PSAutoLock lock;
 
     // Initialize if necessary.
     if (!CorePS::Exists()) {
       profiler_init(nullptr);
     }
 
     if (ActivePS::Exists(lock)) {
       // The profiler is active.
       if (!ActivePS::Equals(lock, aCapacity, aDuration, aInterval, aFeatures,
                             aFilters, aFilterCount)) {
         // Stop and restart with different settings.
         samplerThread = locked_profiler_stop(lock);
-#  if defined(MOZ_REPLACE_MALLOC) && defined(MOZ_PROFILER_MEMORY)
-        if (!ProfilerFeature::HasMemory(aFeatures)) {
-          // Ensure we don't record memory measurements anymore (if we were).
-          mozilla::profiler::install_memory_counter(false);
-        }
-#  endif
+        // TODO: Uninstall memory counter if it is possible from mozglue.
+        // #if defined(MOZ_REPLACE_MALLOC) && defined(MOZ_PROFILER_MEMORY)
+        //         if (!ProfilerFeature::HasMemory(aFeatures)) {
+        //           // Ensure we don't record memory measurements anymore (if
+        //           we were). mozilla::profiler::install_memory_counter(false);
+        //         }
+        // #endif
         locked_profiler_start(lock, aCapacity, aInterval, aFeatures, aFilters,
                               aFilterCount, aDuration);
         startedProfiler = true;
       }
     } else {
       // The profiler is stopped.
       locked_profiler_start(lock, aCapacity, aInterval, aFeatures, aFilters,
                             aFilterCount, aDuration);
       startedProfiler = true;
     }
   }
 
-#  if defined(MOZ_REPLACE_MALLOC) && defined(MOZ_PROFILER_MEMORY)
-  if (startedProfiler && ProfilerFeature::HasMemory(aFeatures)) {
-    // start counting memory allocations (outside of lock because this may
-    // call profiler_add_sampled_counter which would attempt to take the
-    // lock.)
-    mozilla::profiler::install_memory_counter(true);
-  }
-#  endif
+  // TODO: Install memory counter if it is possible from mozglue.
+  // #if defined(MOZ_REPLACE_MALLOC) && defined(MOZ_PROFILER_MEMORY)
+  //   if (startedProfiler && ProfilerFeature::HasMemory(aFeatures)) {
+  //     // start counting memory allocations (outside of lock because this may
+  //     // call profiler_add_sampled_counter which would attempt to take the
+  //     // lock.)
+  //     mozilla::profiler::install_memory_counter(true);
+  //   }
+  // #endif
 
   // We do these operations with gPSMutex unlocked. The comments in
   // profiler_stop() explain why.
   if (samplerThread) {
-    ProfilerParent::ProfilerStopped();
-    NotifyObservers("profiler-stopped");
     delete samplerThread;
   }
-
-  if (startedProfiler) {
-    NotifyProfilerStarted(aCapacity, aDuration, aInterval, aFeatures, aFilters,
-                          aFilterCount);
-  }
 }
 
 static MOZ_MUST_USE SamplerThread* locked_profiler_stop(PSLockRef aLock) {
   LOG("locked_profiler_stop");
 
   MOZ_RELEASE_ASSERT(CorePS::Exists() && ActivePS::Exists(aLock));
 
   // At the very start, clear RacyFeatures.
   RacyFeatures::SetInactive();
 
-#  if defined(MOZ_REPLACE_MALLOC) && defined(MOZ_PROFILER_MEMORY)
-  mozilla::profiler::install_memory_counter(false);
-#  endif
-
-#  if defined(GP_OS_android)
-  if (ActivePS::FeatureJava(aLock)) {
-    java::GeckoJavaSampler::Stop();
-  }
-#  endif
-
-#  ifdef MOZ_TASK_TRACER
-  if (ActivePS::FeatureTaskTracer(aLock)) {
-    tasktracer::StopLogging();
-  }
-#  endif
+  // TODO: Uninstall memory counter if it is possible from mozglue.
+  // #if defined(MOZ_REPLACE_MALLOC) && defined(MOZ_PROFILER_MEMORY)
+  //   mozilla::profiler::install_memory_counter(false);
+  // #endif
 
   // Stop sampling live threads.
-  int tid = profiler_current_thread_id();
   const Vector<LiveProfiledThreadData>& liveProfiledThreads =
       ActivePS::LiveProfiledThreads(aLock);
   for (auto& thread : liveProfiledThreads) {
     RegisteredThread* registeredThread = thread.mRegisteredThread;
     registeredThread->RacyRegisteredThread().SetIsBeingProfiled(false);
-    if (ActivePS::FeatureJS(aLock)) {
-      registeredThread->StopJSSampling();
-      RefPtr<ThreadInfo> info = registeredThread->Info();
-      if (info->ThreadId() == tid) {
-        // We can manually poll the current thread so it stops profiling
-        // immediately.
-        registeredThread->PollJSSampling();
-      } else if (info->IsMainThread()) {
-        // Dispatch a runnable to the main thread to call PollJSSampling(),
-        // so that we don't have wait for the next JS interrupt callback in
-        // order to start profiling JS.
-        TriggerPollJSSamplingOnMainThread();
-      }
-    }
   }
 
   // The Stop() call doesn't actually stop Run(); that happens in this
   // function's caller when the sampler thread is destroyed. Stop() just gives
   // the SamplerThread a chance to do some cleanup with gPSMutex locked.
   SamplerThread* samplerThread = ActivePS::Destroy(aLock);
   samplerThread->Stop(aLock);
 
@@ -3547,150 +2731,126 @@ static MOZ_MUST_USE SamplerThread* locke
 
 void profiler_stop() {
   LOG("profiler_stop");
 
   MOZ_RELEASE_ASSERT(CorePS::Exists());
 
   SamplerThread* samplerThread;
   {
-    PSAutoLock lock(gPSMutex);
+    PSAutoLock lock;
 
     if (!ActivePS::Exists(lock)) {
       return;
     }
 
     samplerThread = locked_profiler_stop(lock);
   }
 
-  // We notify observers with gPSMutex unlocked. Otherwise we might get a
-  // deadlock, if code run by these functions calls a profiler function that
-  // locks gPSMutex, for example when it wants to insert a marker.
-  // (This has been seen in practise in bug 1346356, when we were still firing
-  // these notifications synchronously.)
-  ProfilerParent::ProfilerStopped();
-  NotifyObservers("profiler-stopped");
-
   // We delete with gPSMutex unlocked. Otherwise we would get a deadlock: we
   // would be waiting here with gPSMutex locked for SamplerThread::Run() to
   // return so the join operation within the destructor can complete, but Run()
   // needs to lock gPSMutex to return.
   //
   // Because this call occurs with gPSMutex unlocked, it -- including the final
   // iteration of Run()'s loop -- must be able detect deactivation and return
   // in a way that's safe with respect to other gPSMutex-locking operations
   // that may have occurred in the meantime.
   delete samplerThread;
 }
 
 bool profiler_is_paused() {
   MOZ_RELEASE_ASSERT(CorePS::Exists());
 
-  PSAutoLock lock(gPSMutex);
+  PSAutoLock lock;
 
   if (!ActivePS::Exists(lock)) {
     return false;
   }
 
   return ActivePS::IsPaused(lock);
 }
 
 void profiler_pause() {
   LOG("profiler_pause");
 
   MOZ_RELEASE_ASSERT(CorePS::Exists());
 
   {
-    PSAutoLock lock(gPSMutex);
+    PSAutoLock lock;
 
     if (!ActivePS::Exists(lock)) {
       return;
     }
 
     ActivePS::SetIsPaused(lock, true);
     ActivePS::Buffer(lock).AddEntry(ProfileBufferEntry::Pause(profiler_time()));
   }
-
-  // gPSMutex must be unlocked when we notify, to avoid potential deadlocks.
-  ProfilerParent::ProfilerPaused();
-  NotifyObservers("profiler-paused");
 }
 
 void profiler_resume() {
   LOG("profiler_resume");
 
   MOZ_RELEASE_ASSERT(CorePS::Exists());
 
   {
-    PSAutoLock lock(gPSMutex);
+    PSAutoLock lock;
 
     if (!ActivePS::Exists(lock)) {
       return;
     }
 
     ActivePS::Buffer(lock).AddEntry(
         ProfileBufferEntry::Resume(profiler_time()));
     ActivePS::SetIsPaused(lock, false);
   }
-
-  // gPSMutex must be unlocked when we notify, to avoid potential deadlocks.
-  ProfilerParent::ProfilerResumed();
-  NotifyObservers("profiler-resumed");
 }
 
 bool profiler_feature_active(uint32_t aFeature) {
   // This function runs both on and off the main thread.
 
   MOZ_RELEASE_ASSERT(CorePS::Exists());
 
   // This function is hot enough that we use RacyFeatures, not ActivePS.
   return RacyFeatures::IsActiveWithFeature(aFeature);
 }
 
 void profiler_add_sampled_counter(BaseProfilerCount* aCounter) {
   DEBUG_LOG("profiler_add_sampled_counter(%s)", aCounter->mLabel);
-  PSAutoLock lock(gPSMutex);
+  PSAutoLock lock;
   CorePS::AppendCounter(lock, aCounter);
 }
 
 void profiler_remove_sampled_counter(BaseProfilerCount* aCounter) {
   DEBUG_LOG("profiler_remove_sampled_counter(%s)", aCounter->mLabel);
-  PSAutoLock lock(gPSMutex);
+  PSAutoLock lock;
   // Note: we don't enforce a final sample, though we could do so if the
   // profiler was active
   CorePS::RemoveCounter(lock, aCounter);
 }
 
 ProfilingStack* profiler_register_thread(const char* aName,
                                          void* aGuessStackTop) {
   DEBUG_LOG("profiler_register_thread(%s)", aName);
 
   MOZ_RELEASE_ASSERT(CorePS::Exists());
 
-  // Make sure we have a nsThread wrapper for the current thread, and that NSPR
-  // knows its name.
-  (void)NS_GetCurrentThread();
-  NS_SetCurrentThreadName(aName);
-
-  PSAutoLock lock(gPSMutex);
+  PSAutoLock lock;
 
   void* stackTop = GetStackTop(aGuessStackTop);
   return locked_register_thread(lock, aName, stackTop);
 }
 
 void profiler_unregister_thread() {
   if (!CorePS::Exists()) {
     // This function can be called after the main thread has already shut down.
     return;
   }
 
-  PSAutoLock lock(gPSMutex);
-
-  // We don't call RegisteredThread::StopJSSampling() here; there's no point
-  // doing that for a JS thread that is in the process of disappearing.
+  PSAutoLock lock;
 
   RegisteredThread* registeredThread = FindCurrentThreadRegisteredThread(lock);
   MOZ_RELEASE_ASSERT(registeredThread ==
                      TLSRegisteredThread::RegisteredThread(lock));
   if (registeredThread) {
     RefPtr<ThreadInfo> info = registeredThread->Info();
 
     DEBUG_LOG("profiler_unregister_thread: %s", info->Name());
@@ -3714,25 +2874,24 @@ void profiler_unregister_thread() {
     // - We've already called profiler_unregister_thread() for this thread.
     //   (Whether or not it should, this does happen in practice.)
     //
     // Either way, TLSRegisteredThread should be empty.
     MOZ_RELEASE_ASSERT(!TLSRegisteredThread::RegisteredThread(lock));
   }
 }
 
-void profiler_register_page(const nsID& aDocShellId, uint32_t aHistoryId,
-                            const nsCString& aUrl, bool aIsSubFrame) {
-  DEBUG_LOG("profiler_register_page(%s, %u, %s, %d)",
-            nsIDToCString(aDocShellId).get(), aHistoryId, aUrl.get(),
-            aIsSubFrame);
+void profiler_register_page(const std::string& aDocShellId, uint32_t aHistoryId,
+                            const std::string& aUrl, bool aIsSubFrame) {
+  DEBUG_LOG("profiler_register_page(%s, %u, %s, %d)", aDocShellId.c_str(),
+            aHistoryId, aUrl.c_str(), aIsSubFrame);
 
   MOZ_RELEASE_ASSERT(CorePS::Exists());
 
-  PSAutoLock lock(gPSMutex);
+  PSAutoLock lock;
 
   // If profiler is not active, delete all the previous page entries of the
   // given DocShell since we won't need those.
   if (!ActivePS::Exists(lock)) {
     CorePS::RemoveRegisteredPages(lock, aDocShellId);
   }
 
   RefPtr<PageInformation> pageInfo =
@@ -3741,23 +2900,23 @@ void profiler_register_page(const nsID& 
 
   // After appending the given page to CorePS, look for the expired
   // pages and remove them if there are any.
   if (ActivePS::Exists(lock)) {
     ActivePS::DiscardExpiredPages(lock);
   }
 }
 
-void profiler_unregister_pages(const nsID& aRegisteredDocShellId) {
+void profiler_unregister_pages(const std::string& aRegisteredDocShellId) {
   if (!CorePS::Exists()) {
     // This function can be called after the main thread has already shut down.
     return;
   }
 
-  PSAutoLock lock(gPSMutex);
+  PSAutoLock lock;
 
   // During unregistration, if the profiler is active, we have to keep the
   // page information since there may be some markers associated with the given
   // page. But if profiler is not active. we have no reason to keep the
   // page information here because there can't be any marker associated with it.
   if (ActivePS::Exists(lock)) {
     ActivePS::UnregisterPages(lock, aRegisteredDocShellId);
   } else {
@@ -3767,25 +2926,22 @@ void profiler_unregister_pages(const nsI
 
 void profiler_clear_all_pages() {
   if (!CorePS::Exists()) {
     // This function can be called after the main thread has already shut down.
     return;
   }
 
   {
-    PSAutoLock lock(gPSMutex);
+    PSAutoLock lock;
     CorePS::ClearRegisteredPages(lock);
     if (ActivePS::Exists(lock)) {
       ActivePS::ClearUnregisteredPages(lock);
     }
   }
-
-  // gPSMutex must be unlocked when we notify, to avoid potential deadlocks.
-  ProfilerParent::ClearAllPages();
 }
 
 void profiler_thread_sleep() {
   // This function runs both on and off the main thread.
 
   MOZ_RELEASE_ASSERT(CorePS::Exists());
 
   RacyRegisteredThread* racyRegisteredThread =
@@ -3815,43 +2971,38 @@ bool mozilla::profiler::detail::IsThread
   MOZ_RELEASE_ASSERT(CorePS::Exists());
 
   const RacyRegisteredThread* racyRegisteredThread =
       TLSRegisteredThread::RacyRegisteredThread();
   return racyRegisteredThread && racyRegisteredThread->IsBeingProfiled();
 }
 
 bool profiler_thread_is_sleeping() {
-  MOZ_RELEASE_ASSERT(NS_IsMainThread());
+  MOZ_RELEASE_ASSERT(CorePS::IsMainThread());
   MOZ_RELEASE_ASSERT(CorePS::Exists());
 
   RacyRegisteredThread* racyRegisteredThread =
       TLSRegisteredThread::RacyRegisteredThread();
   if (!racyRegisteredThread) {
     return false;
   }
   return racyRegisteredThread->IsSleeping();
 }
 
-void profiler_js_interrupt_callback() {
-  // This function runs on JS threads being sampled.
-  PollJSSamplingForCurrentThread();
-}
-
 double profiler_time() {
   MOZ_RELEASE_ASSERT(CorePS::Exists());
 
   TimeDuration delta = TimeStamp::Now() - CorePS::ProcessStartTime();
   return delta.ToMilliseconds();
 }
 
 UniqueProfilerBacktrace profiler_get_backtrace() {
   MOZ_RELEASE_ASSERT(CorePS::Exists());
 
-  PSAutoLock lock(gPSMutex);
+  PSAutoLock lock;
 
   if (!ActivePS::Exists(lock) || ActivePS::FeaturePrivacy(lock)) {
     return nullptr;
   }
 
   RegisteredThread* registeredThread =
       TLSRegisteredThread::RegisteredThread(lock);
   if (!registeredThread) {
@@ -3928,54 +3079,25 @@ void profiler_add_marker(const char* aMa
 }
 
 // This is a simplified version of profiler_add_marker that can be easily passed
 // into the JS engine.
 void profiler_add_js_marker(const char* aMarkerName) {
   profiler_add_marker(aMarkerName, JS::ProfilingCategoryPair::JS, nullptr);
 }
 
-void profiler_add_network_marker(
-    nsIURI* aURI, int32_t aPriority, uint64_t aChannelId, NetworkLoadType aType,
-    mozilla::TimeStamp aStart, mozilla::TimeStamp aEnd, int64_t aCount,
-    mozilla::net::CacheDisposition aCacheDisposition,
-    const mozilla::net::TimingStruct* aTimings, nsIURI* aRedirectURI) {
-  if (!profiler_is_active()) {
-    return;
-  }
-  // These do allocations/frees/etc; avoid if not active
-  nsAutoCString spec;
-  nsAutoCString redirect_spec;
-  if (aURI) {
-    aURI->GetAsciiSpec(spec);
-  }
-  if (aRedirectURI) {
-    aRedirectURI->GetAsciiSpec(redirect_spec);
-  }
-  // top 32 bits are process id of the load
-  uint32_t id = static_cast<uint32_t>(aChannelId & 0xFFFFFFFF);
-  char name[2048];
-  SprintfLiteral(name, "Load %d: %s", id, PromiseFlatCString(spec).get());
-  profiler_add_marker(
-      name, JS::ProfilingCategoryPair::NETWORK,
-      MakeUnique<NetworkMarkerPayload>(
-          static_cast<int64_t>(aChannelId), PromiseFlatCString(spec).get(),
-          aType, aStart, aEnd, aPriority, aCount, aCacheDisposition, aTimings,
-          PromiseFlatCString(redirect_spec).get()));
-}
-
 // This logic needs to add a marker for a different thread, so we actually need
 // to lock here.
 void profiler_add_marker_for_thread(int aThreadId,
                                     JS::ProfilingCategoryPair aCategoryPair,
                                     const char* aMarkerName,
                                     UniquePtr<ProfilerMarkerPayload> aPayload) {
   MOZ_RELEASE_ASSERT(CorePS::Exists());
 
-  PSAutoLock lock(gPSMutex);
+  PSAutoLock lock;
   if (!ActivePS::Exists(lock)) {
     return;
   }
 
   // Create the ProfilerMarker which we're going to store.
   TimeStamp origin = (aPayload && !aPayload->GetStartTime().IsNull())
                          ? aPayload->GetStartTime()
                          : TimeStamp::Now();
@@ -4002,17 +3124,17 @@ void profiler_add_marker_for_thread(int 
   // Insert the marker into the buffer
   ProfileBuffer& buffer = ActivePS::Buffer(lock);
   buffer.AddStoredMarker(marker);
   buffer.AddEntry(ProfileBufferEntry::Marker(marker));
 }
 
 void profiler_tracing(const char* aCategoryString, const char* aMarkerName,
                       JS::ProfilingCategoryPair aCategoryPair,
-                      TracingKind aKind, const Maybe<nsID>& aDocShellId,
+                      TracingKind aKind, const Maybe<std::string>& aDocShellId,
                       const Maybe<uint32_t>& aDocShellHistoryId) {
   MOZ_RELEASE_ASSERT(CorePS::Exists());
 
   VTUNE_TRACING(aMarkerName, aKind);
 
   // This function is hot enough that we use RacyFeatures, notActivePS.
   if (!RacyFeatures::IsActiveWithoutPrivacy()) {
     return;
@@ -4021,17 +3143,17 @@ void profiler_tracing(const char* aCateg
   auto payload = MakeUnique<TracingMarkerPayload>(
       aCategoryString, aKind, aDocShellId, aDocShellHistoryId);
   racy_profiler_add_marker(aMarkerName, aCategoryPair, std::move(payload));
 }
 
 void profiler_tracing(const char* aCategoryString, const char* aMarkerName,
                       JS::ProfilingCategoryPair aCategoryPair,
                       TracingKind aKind, UniqueProfilerBacktrace aCause,
-                      const Maybe<nsID>& aDocShellId,
+                      const Maybe<std::string>& aDocShellId,
                       const Maybe<uint32_t>& aDocShellHistoryId) {
   MOZ_RELEASE_ASSERT(CorePS::Exists());
 
   VTUNE_TRACING(aMarkerName, aKind);
 
   // This function is hot enough that we use RacyFeatures, notActivePS.
   if (!RacyFeatures::IsActiveWithoutPrivacy()) {
     return;
@@ -4039,104 +3161,36 @@ void profiler_tracing(const char* aCateg
 
   auto payload =
       MakeUnique<TracingMarkerPayload>(aCategoryString, aKind, aDocShellId,
                                        aDocShellHistoryId, std::move(aCause));
   racy_profiler_add_marker(aMarkerName, aCategoryPair, std::move(payload));
 }
 
 void profiler_add_text_marker(
-    const char* aMarkerName, const nsACString& aText,
+    const char* aMarkerName, const std::string& aText,
     JS::ProfilingCategoryPair aCategoryPair,
     const mozilla::TimeStamp& aStartTime, const mozilla::TimeStamp& aEndTime,
-    const mozilla::Maybe<nsID>& aDocShellId,
+    const mozilla::Maybe<std::string>& aDocShellId,
     const mozilla::Maybe<uint32_t>& aDocShellHistoryId,
     UniqueProfilerBacktrace aCause) {
   profiler_add_marker(
       aMarkerName, aCategoryPair,
       MakeUnique<TextMarkerPayload>(aText, aStartTime, aEndTime, aDocShellId,
                                     aDocShellHistoryId, std::move(aCause)));
 }
 
-void profiler_set_js_context(JSContext* aCx) {
-  MOZ_ASSERT(aCx);
-
-  PSAutoLock lock(gPSMutex);
-
-  RegisteredThread* registeredThread =
-      TLSRegisteredThread::RegisteredThread(lock);
-  if (!registeredThread) {
-    return;
-  }
-
-  registeredThread->SetJSContext(aCx);
-
-  // This call is on-thread, so we can call PollJSSampling() to start JS
-  // sampling immediately.
-  registeredThread->PollJSSampling();
-
-  if (ActivePS::Exists(lock)) {
-    ProfiledThreadData* profiledThreadData =
-        ActivePS::GetProfiledThreadData(lock, registeredThread);
-    if (profiledThreadData) {
-      profiledThreadData->NotifyReceivedJSContext(
-          ActivePS::Buffer(lock).mRangeEnd);
-    }
-  }
-}
-
-void profiler_clear_js_context() {
-  MOZ_RELEASE_ASSERT(CorePS::Exists());
-
-  PSAutoLock lock(gPSMutex);
-
-  RegisteredThread* registeredThread =
-      TLSRegisteredThread::RegisteredThread(lock);
-  if (!registeredThread) {
-    return;
-  }
-
-  JSContext* cx = registeredThread->GetJSContext();
-  if (!cx) {
-    return;
-  }
-
-  if (ActivePS::Exists(lock) && ActivePS::FeatureJS(lock)) {
-    ProfiledThreadData* profiledThreadData =
-        ActivePS::GetProfiledThreadData(lock, registeredThread);
-    if (profiledThreadData) {
-      profiledThreadData->NotifyAboutToLoseJSContext(
-          cx, CorePS::ProcessStartTime(), ActivePS::Buffer(lock));
-
-      // Notify the JS context that profiling for this context has stopped.
-      // Do this by calling StopJSSampling and PollJSSampling before
-      // nulling out the JSContext.
-      registeredThread->StopJSSampling();
-      registeredThread->PollJSSampling();
-
-      registeredThread->ClearJSContext();
-
-      // Tell the thread that we'd like to have JS sampling on this
-      // thread again, once it gets a new JSContext (if ever).
-      registeredThread->StartJSSampling(ActivePS::JSFlags(lock));
-      return;
-    }
-  }
-
-  registeredThread->ClearJSContext();
-}
-
 // NOTE: aCollector's methods will be called while the target thread is paused.
 // Doing things in those methods like allocating -- which may try to claim
 // locks -- is a surefire way to deadlock.
 void profiler_suspend_and_sample_thread(int aThreadId, uint32_t aFeatures,
                                         ProfilerStackCollector& aCollector,
                                         bool aSampleNative /* = true */) {
   // Lock the profiler mutex
-  PSAutoLock lock(gPSMutex);
+  PSAutoLock lock;
 
   const Vector<UniquePtr<RegisteredThread>>& registeredThreads =
       CorePS::RegisteredThreads(lock);
   for (auto& thread : registeredThreads) {
     RefPtr<ThreadInfo> info = thread->Info();
     RegisteredThread& registeredThread = *thread.get();
 
     if (info->ThreadId() == aThreadId) {
--- a/mozglue/baseprofiler/core/platform.h
+++ b/mozglue/baseprofiler/core/platform.h
@@ -29,61 +29,84 @@
 #ifndef TOOLS_PLATFORM_H_
 #define TOOLS_PLATFORM_H_
 
 #include "PlatformMacros.h"
 
 #include "BaseProfiler.h"
 
 #include "mozilla/Logging.h"
+#include "mozilla/PlatformMutex.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/Vector.h"
-#include "nsString.h"
 
 #include <functional>
 #include <stdint.h>
+#include <string>
 
-extern mozilla::LazyLogModule gProfilerLog;
+bool BaseProfilerLogTest(int aLevelToTest);
+
+// These are for MOZ_BASE_PROFILER_LOGGING and above. It's the default logging
+// level for the profiler, and should be used sparingly.
+#define LOG_TEST BaseProfilerLogTest(3)
+#define LOG(arg, ...)                                              \
+  do {                                                             \
+    if (LOG_TEST) {                                                \
+      printf("[I %d/%d] " arg "\n", profiler_current_process_id(), \
+             profiler_current_thread_id(), ##__VA_ARGS__);         \
+    }                                                              \
+  } while (0)
 
-// These are for MOZ_LOG="prof:3" or higher. It's the default logging level for
-// the profiler, and should be used sparingly.
-#define LOG_TEST MOZ_LOG_TEST(gProfilerLog, mozilla::LogLevel::Info)
-#define LOG(arg, ...)                            \
-  MOZ_LOG(gProfilerLog, mozilla::LogLevel::Info, \
-          ("[%d] " arg, profiler_current_process_id(), ##__VA_ARGS__))
+// These are for MOZ_BASE_PROFILER_DEBUG_LOGGING. It should be used for logging
+// that is somewhat more verbose than LOG.
+#define DEBUG_LOG_TEST BaseProfilerLogTest(4)
+#define DEBUG_LOG(arg, ...)                                        \
+  do {                                                             \
+    if (DEBUG_LOG_TEST) {                                          \
+      printf("[D %d/%d] " arg "\n", profiler_current_process_id(), \
+             profiler_current_thread_id(), ##__VA_ARGS__);         \
+    }                                                              \
+  } while (0)
 
-// These are for MOZ_LOG="prof:4" or higher. It should be used for logging that
-// is somewhat more verbose than LOG.
-#define DEBUG_LOG_TEST MOZ_LOG_TEST(gProfilerLog, mozilla::LogLevel::Debug)
-#define DEBUG_LOG(arg, ...)                       \
-  MOZ_LOG(gProfilerLog, mozilla::LogLevel::Debug, \
-          ("[%d] " arg, profiler_current_process_id(), ##__VA_ARGS__))
+// These are for MOZ_BASE_PROFILER_VERBOSE_LOGGING. It should be used for
+// logging that is somewhat more verbose than DEBUG_LOG.
+#define VERBOSE_LOG_TEST BaseProfilerLogTest(5)
+#define VERBOSE_LOG(arg, ...)                                      \
+  do {                                                             \
+    if (VERBOSE_LOG_TEST) {                                        \
+      printf("[V %d/%d] " arg "\n", profiler_current_process_id(), \
+             profiler_current_thread_id(), ##__VA_ARGS__);         \
+    }                                                              \
+  } while (0)
+
+// Thin shell around mozglue PlatformMutex, for Base Profiler internal use.
+// Does not preserve behavior in JS record/replay.
+class PSMutex : private mozilla::detail::MutexImpl {
+ public:
+  PSMutex()
+      : mozilla::detail::MutexImpl(
+            mozilla::recordreplay::Behavior::DontPreserve) {}
+  void Lock() { mozilla::detail::MutexImpl::lock(); }
+  void Unlock() { mozilla::detail::MutexImpl::unlock(); }
+};
 
 typedef uint8_t* Address;
 
-// ----------------------------------------------------------------------------
-// Miscellaneous
-
 class PlatformData;
 
 // We can't new/delete the type safely without defining it
 // (-Wdelete-incomplete).  Use these to hide the details from clients.
 struct PlatformDataDestructor {
   void operator()(PlatformData*);
 };
 
 typedef mozilla::UniquePtr<PlatformData, PlatformDataDestructor>
     UniquePlatformData;
 UniquePlatformData AllocPlatformData(int aThreadId);
 
-namespace mozilla {
-class JSONWriter;
-}
-void AppendSharedLibraries(mozilla::JSONWriter& aWriter);
-
 // Convert the array of strings to a bitfield.
 uint32_t ParseFeaturesFromStringArray(const char** aFeatures,
                                       uint32_t aFeatureCount,
                                       bool aIsStartup = false);
 
 void profiler_get_profile_json_into_lazily_allocated_buffer(
     const std::function<char*(size_t)>& aAllocator, double aSinceTime,
     bool aIsShuttingDown);
@@ -91,15 +114,15 @@ void profiler_get_profile_json_into_lazi
 // Flags to conveniently track various JS features.
 enum class JSSamplingFlags {
   StackSampling = 0x1,
   TrackOptimizations = 0x2,
   TraceLogging = 0x4
 };
 
 // Record an exit profile from a child process.
-void profiler_received_exit_profile(const nsCString& aExitProfile);
+void profiler_received_exit_profile(const std::string& aExitProfile);
 
 // Extract all received exit profiles that have not yet expired (i.e., they
 // still intersect with this process' buffer range).
-mozilla::Vector<nsCString> profiler_move_exit_profiles();
+mozilla::Vector<std::string> profiler_move_exit_profiles();
 
 #endif /* ndef TOOLS_PLATFORM_H_ */
--- a/mozglue/baseprofiler/core/shared-libraries-linux.cc
+++ b/mozglue/baseprofiler/core/shared-libraries-linux.cc
@@ -16,75 +16,659 @@
 #  include <stdio.h>
 #  include <string.h>
 #  include <limits.h>
 #  include <unistd.h>
 #  include <fstream>
 #  include "platform.h"
 #  include "mozilla/Sprintf.h"
 #  include "mozilla/Unused.h"
-#  include "nsDebug.h"
-#  include "nsNativeCharsetUtils.h"
-#  include <nsTArray.h>
 
-#  include "common/linux/file_id.h"
 #  include <algorithm>
+#  include <arpa/inet.h>
 #  include <dlfcn.h>
+#  include <elf.h>
+#  include <fcntl.h>
 #  include <features.h>
+#  include <sys/mman.h>
+#  include <sys/stat.h>
 #  include <sys/types.h>
+#  include <vector>
 
 #  if defined(GP_OS_linux)
 #    include <link.h>  // dl_phdr_info
 #  elif defined(GP_OS_android)
 #    include "AutoObjectMapper.h"
 #    include "ElfLoader.h"  // dl_phdr_info
 extern "C" MOZ_EXPORT __attribute__((weak)) int dl_iterate_phdr(
     int (*callback)(struct dl_phdr_info* info, size_t size, void* data),
     void* data);
 #  else
 #    error "Unexpected configuration"
 #  endif
 
+// ----------------------------------------------------------------------------
+// Starting imports from toolkit/crashreporter/google-breakpad/, as needed by
+// this file when moved to mozglue.
+
+// Imported from
+// toolkit/crashreporter/google-breakpad/src/common/memory_range.h.
+// A lightweight wrapper with a pointer and a length to encapsulate a contiguous
+// range of memory. It provides helper methods for checked access of a subrange
+// of the memory. Its implemementation does not allocate memory or call into
+// libc functions, and is thus safer to use in a crashed environment.
+class MemoryRange {
+ public:
+  MemoryRange() : data_(NULL), length_(0) {}
+
+  MemoryRange(const void* data, size_t length) { Set(data, length); }
+
+  // Returns true if this memory range contains no data.
+  bool IsEmpty() const {
+    // Set() guarantees that |length_| is zero if |data_| is NULL.
+    return length_ == 0;
+  }
+
+  // Resets to an empty range.
+  void Reset() {
+    data_ = NULL;
+    length_ = 0;
+  }
+
+  // Sets this memory range to point to |data| and its length to |length|.
+  void Set(const void* data, size_t length) {
+    data_ = reinterpret_cast<const uint8_t*>(data);
+    // Always set |length_| to zero if |data_| is NULL.
+    length_ = data ? length : 0;
+  }
+
+  // Returns true if this range covers a subrange of |sub_length| bytes
+  // at |sub_offset| bytes of this memory range, or false otherwise.
+  bool Covers(size_t sub_offset, size_t sub_length) const {
+    // The following checks verify that:
+    // 1. sub_offset is within [ 0 .. length_ - 1 ]
+    // 2. sub_offset + sub_length is within
+    //    [ sub_offset .. length_ ]
+    return sub_offset < length_ && sub_offset + sub_length >= sub_offset &&
+           sub_offset + sub_length <= length_;
+  }
+
+  // Returns a raw data pointer to a subrange of |sub_length| bytes at
+  // |sub_offset| bytes of this memory range, or NULL if the subrange
+  // is out of bounds.
+  const void* GetData(size_t sub_offset, size_t sub_length) const {
+    return Covers(sub_offset, sub_length) ? (data_ + sub_offset) : NULL;
+  }
+
+  // Same as the two-argument version of GetData() but uses sizeof(DataType)
+  // as the subrange length and returns an |DataType| pointer for convenience.
+  template <typename DataType>
+  const DataType* GetData(size_t sub_offset) const {
+    return reinterpret_cast<const DataType*>(
+        GetData(sub_offset, sizeof(DataType)));
+  }
+
+  // Returns a raw pointer to the |element_index|-th element of an array
+  // of elements of length |element_size| starting at |sub_offset| bytes
+  // of this memory range, or NULL if the element is out of bounds.
+  const void* GetArrayElement(size_t element_offset, size_t element_size,
+                              unsigned element_index) const {
+    size_t sub_offset = element_offset + element_index * element_size;
+    return GetData(sub_offset, element_size);
+  }
+
+  // Same as the three-argument version of GetArrayElement() but deduces
+  // the element size using sizeof(ElementType) and returns an |ElementType|
+  // pointer for convenience.
+  template <typename ElementType>
+  const ElementType* GetArrayElement(size_t element_offset,
+                                     unsigned element_index) const {
+    return reinterpret_cast<const ElementType*>(
+        GetArrayElement(element_offset, sizeof(ElementType), element_index));
+  }
+
+  // Returns a subrange of |sub_length| bytes at |sub_offset| bytes of
+  // this memory range, or an empty range if the subrange is out of bounds.
+  MemoryRange Subrange(size_t sub_offset, size_t sub_length) const {
+    return Covers(sub_offset, sub_length)
+               ? MemoryRange(data_ + sub_offset, sub_length)
+               : MemoryRange();
+  }
+
+  // Returns a pointer to the beginning of this memory range.
+  const uint8_t* data() const { return data_; }
+
+  // Returns the length, in bytes, of this memory range.
+  size_t length() const { return length_; }
+
+ private:
+  // Pointer to the beginning of this memory range.
+  const uint8_t* data_;
+
+  // Length, in bytes, of this memory range.
+  size_t length_;
+};
+
+// Imported from
+// toolkit/crashreporter/google-breakpad/src/common/linux/memory_mapped_file.h
+// and inlined .cc.
+// A utility class for mapping a file into memory for read-only access of the
+// file content. Its implementation avoids calling into libc functions by
+// directly making system calls for open, close, mmap, and munmap.
+class MemoryMappedFile {
+ public:
+  MemoryMappedFile() {}
+
+  // Constructor that calls Map() to map a file at |path| into memory.
+  // If Map() fails, the object behaves as if it is default constructed.
+  MemoryMappedFile(const char* path, size_t offset) { Map(path, offset); }
+
+  MemoryMappedFile(const MemoryMappedFile&) = delete;
+  MemoryMappedFile& operator=(const MemoryMappedFile&) = delete;
+
+  ~MemoryMappedFile() {}
+
+  // Maps a file at |path| into memory, which can then be accessed via
+  // content() as a MemoryRange object or via data(), and returns true on
+  // success. Mapping an empty file will succeed but with data() and size()
+  // returning NULL and 0, respectively. An existing mapping is unmapped
+  // before a new mapping is created.
+  bool Map(const char* path, size_t offset) {
+    Unmap();
+
+    int fd = open(path, O_RDONLY, 0);
+    if (fd == -1) {
+      return false;
+    }
+
+#  if defined(__x86_64__) || defined(__aarch64__) || \
+      (defined(__mips__) && _MIPS_SIM == _ABI64)
+
+    struct stat st;
+    if (fstat(fd, &st) == -1 || st.st_size < 0) {
+#  else
+    struct stat64 st;
+    if (fstat64(fd, &st) == -1 || st.st_size < 0) {
+#  endif
+      close(fd);
+      return false;
+    }
+
+    // Strangely file size can be negative, but we check above that it is not.
+    size_t file_len = static_cast<size_t>(st.st_size);
+    // If the file does not extend beyond the offset, simply use an empty
+    // MemoryRange and return true. Don't bother to call mmap()
+    // even though mmap() can handle an empty file on some platforms.
+    if (offset >= file_len) {
+      close(fd);
+      return true;
+    }
+
+    void* data = mmap(NULL, file_len, PROT_READ, MAP_PRIVATE, fd, offset);
+    close(fd);
+    if (data == MAP_FAILED) {
+      return false;
+    }
+
+    content_.Set(data, file_len - offset);
+    return true;
+  }
+
+  // Unmaps the memory for the mapped file. It's a no-op if no file is
+  // mapped.
+  void Unmap() {
+    if (content_.data()) {
+      munmap(const_cast<uint8_t*>(content_.data()), content_.length());
+      content_.Set(NULL, 0);
+    }
+  }
+
+  // Returns a MemoryRange object that covers the memory for the mapped
+  // file. The MemoryRange object is empty if no file is mapped.
+  const MemoryRange& content() const { return content_; }
+
+  // Returns a pointer to the beginning of the memory for the mapped file.
+  // or NULL if no file is mapped or the mapped file is empty.
+  const void* data() const { return content_.data(); }
+
+  // Returns the size in bytes of the mapped file, or zero if no file
+  // is mapped.
+  size_t size() const { return content_.length(); }
+
+ private:
+  // Mapped file content as a MemoryRange object.
+  MemoryRange content_;
+};
+
+// Imported from
+// toolkit/crashreporter/google-breakpad/src/common/linux/file_id.h and inlined
+// .cc.
+// GNU binutils' ld defaults to 'sha1', which is 160 bits == 20 bytes,
+// so this is enough to fit that, which most binaries will use.
+// This is just a sensible default for vectors so most callers can get away with
+// stack allocation.
+static const size_t kDefaultBuildIdSize = 20;
+
+// Used in a few places for backwards-compatibility.
+typedef struct {
+  uint32_t data1;
+  uint16_t data2;
+  uint16_t data3;
+  uint8_t data4[8];
+} MDGUID; /* GUID */
+
+const size_t kMDGUIDSize = sizeof(MDGUID);
+
+class FileID {
+ public:
+  explicit FileID(const char* path) : path_(path) {}
+  ~FileID() {}
+
+  // Load the identifier for the elf file path specified in the constructor into
+  // |identifier|.
+  //
+  // The current implementation will look for a .note.gnu.build-id
+  // section and use that as the file id, otherwise it falls back to
+  // XORing the first 4096 bytes of the .text section to generate an identifier.
+  bool ElfFileIdentifier(std::vector<uint8_t>& identifier) {
+    MemoryMappedFile mapped_file(path_.c_str(), 0);
+    if (!mapped_file.data())  // Should probably check if size >= ElfW(Ehdr)?
+      return false;
+
+    return ElfFileIdentifierFromMappedFile(mapped_file.data(), identifier);
+  }
+
+  // Traits classes so consumers can write templatized code to deal
+  // with specific ELF bits.
+  struct ElfClass32 {
+    typedef Elf32_Addr Addr;
+    typedef Elf32_Ehdr Ehdr;
+    typedef Elf32_Nhdr Nhdr;
+    typedef Elf32_Phdr Phdr;
+    typedef Elf32_Shdr Shdr;
+    typedef Elf32_Half Half;
+    typedef Elf32_Off Off;
+    typedef Elf32_Sym Sym;
+    typedef Elf32_Word Word;
+
+    static const int kClass = ELFCLASS32;
+    static const uint16_t kMachine = EM_386;
+    static const size_t kAddrSize = sizeof(Elf32_Addr);
+    static constexpr const char* kMachineName = "x86";
+  };
+
+  struct ElfClass64 {
+    typedef Elf64_Addr Addr;
+    typedef Elf64_Ehdr Ehdr;
+    typedef Elf64_Nhdr Nhdr;
+    typedef Elf64_Phdr Phdr;
+    typedef Elf64_Shdr Shdr;
+    typedef Elf64_Half Half;
+    typedef Elf64_Off Off;
+    typedef Elf64_Sym Sym;
+    typedef Elf64_Word Word;
+
+    static const int kClass = ELFCLASS64;
+    static const uint16_t kMachine = EM_X86_64;
+    static const size_t kAddrSize = sizeof(Elf64_Addr);
+    static constexpr const char* kMachineName = "x86_64";
+  };
+
+  // Internal helper method, exposed for convenience for callers
+  // that already have more info.
+  template <typename ElfClass>
+  static const typename ElfClass::Shdr* FindElfSectionByName(
+      const char* name, typename ElfClass::Word section_type,
+      const typename ElfClass::Shdr* sections, const char* section_names,
+      const char* names_end, int nsection) {
+    if (!name || !sections || nsection == 0) {
+      return NULL;
+    }
+
+    int name_len = strlen(name);
+    if (name_len == 0) return NULL;
+
+    for (int i = 0; i < nsection; ++i) {
+      const char* section_name = section_names + sections[i].sh_name;
+      if (sections[i].sh_type == section_type &&
+          names_end - section_name >= name_len + 1 &&
+          strcmp(name, section_name) == 0) {
+        return sections + i;
+      }
+    }
+    return NULL;
+  }
+
+  struct ElfSegment {
+    const void* start;
+    size_t size;
+  };
+
+  // Convert an offset from an Elf header into a pointer to the mapped
+  // address in the current process. Takes an extra template parameter
+  // to specify the return type to avoid having to dynamic_cast the
+  // result.
+  template <typename ElfClass, typename T>
+  static const T* GetOffset(const typename ElfClass::Ehdr* elf_header,
+                            typename ElfClass::Off offset) {
+    return reinterpret_cast<const T*>(reinterpret_cast<uintptr_t>(elf_header) +
+                                      offset);
+  }
+
+// ELF note name and desc are 32-bits word padded.
+#  define NOTE_PADDING(a) ((a + 3) & ~3)
+
+  static bool ElfClassBuildIDNoteIdentifier(const void* section, size_t length,
+                                            std::vector<uint8_t>& identifier) {
+    static_assert(sizeof(ElfClass32::Nhdr) == sizeof(ElfClass64::Nhdr),
+                  "Elf32_Nhdr and Elf64_Nhdr should be the same");
+    typedef typename ElfClass32::Nhdr Nhdr;
+
+    const void* section_end = reinterpret_cast<const char*>(section) + length;
+    const Nhdr* note_header = reinterpret_cast<const Nhdr*>(section);
+    while (reinterpret_cast<const void*>(note_header) < section_end) {
+      if (note_header->n_type == NT_GNU_BUILD_ID) break;
+      note_header = reinterpret_cast<const Nhdr*>(
+          reinterpret_cast<const char*>(note_header) + sizeof(Nhdr) +
+          NOTE_PADDING(note_header->n_namesz) +
+          NOTE_PADDING(note_header->n_descsz));
+    }
+    if (reinterpret_cast<const void*>(note_header) >= section_end ||
+        note_header->n_descsz == 0) {
+      return false;
+    }
+
+    const uint8_t* build_id = reinterpret_cast<const uint8_t*>(note_header) +
+                              sizeof(Nhdr) +
+                              NOTE_PADDING(note_header->n_namesz);
+    identifier.insert(identifier.end(), build_id,
+                      build_id + note_header->n_descsz);
+
+    return true;
+  }
+
+  template <typename ElfClass>
+  static bool FindElfClassSection(const char* elf_base,
+                                  const char* section_name,
+                                  typename ElfClass::Word section_type,
+                                  const void** section_start,
+                                  size_t* section_size) {
+    typedef typename ElfClass::Ehdr Ehdr;
+    typedef typename ElfClass::Shdr Shdr;
+
+    if (!elf_base || !section_start || !section_size) {
+      return false;
+    }
+
+    if (strncmp(elf_base, ELFMAG, SELFMAG) != 0) {
+      return false;
+    }
+
+    const Ehdr* elf_header = reinterpret_cast<const Ehdr*>(elf_base);
+    if (elf_header->e_ident[EI_CLASS] != ElfClass::kClass) {
+      return false;
+    }
+
+    const Shdr* sections =
+        GetOffset<ElfClass, Shdr>(elf_header, elf_header->e_shoff);
+    const Shdr* section_names = sections + elf_header->e_shstrndx;
+    const char* names =
+        GetOffset<ElfClass, char>(elf_header, section_names->sh_offset);
+    const char* names_end = names + section_names->sh_size;
+
+    const Shdr* section =
+        FindElfSectionByName<ElfClass>(section_name, section_type, sections,
+                                       names, names_end, elf_header->e_shnum);
+
+    if (section != NULL && section->sh_size > 0) {
+      *section_start = elf_base + section->sh_offset;
+      *section_size = section->sh_size;
+    }
+
+    return true;
+  }
+
+  template <typename ElfClass>
+  static bool FindElfClassSegment(const char* elf_base,
+                                  typename ElfClass::Word segment_type,
+                                  std::vector<ElfSegment>* segments) {
+    typedef typename ElfClass::Ehdr Ehdr;
+    typedef typename ElfClass::Phdr Phdr;
+
+    if (!elf_base || !segments) {
+      return false;
+    }
+
+    if (strncmp(elf_base, ELFMAG, SELFMAG) != 0) {
+      return false;
+    }
+
+    const Ehdr* elf_header = reinterpret_cast<const Ehdr*>(elf_base);
+    if (elf_header->e_ident[EI_CLASS] != ElfClass::kClass) {
+      return false;
+    }
+
+    const Phdr* phdrs =
+        GetOffset<ElfClass, Phdr>(elf_header, elf_header->e_phoff);
+
+    for (int i = 0; i < elf_header->e_phnum; ++i) {
+      if (phdrs[i].p_type == segment_type) {
+        ElfSegment seg = {};
+        seg.start = elf_base + phdrs[i].p_offset;
+        seg.size = phdrs[i].p_filesz;
+        segments->push_back(seg);
+      }
+    }
+
+    return true;
+  }
+
+  static bool IsValidElf(const void* elf_base) {
+    return strncmp(reinterpret_cast<const char*>(elf_base), ELFMAG, SELFMAG) ==
+           0;
+  }
+
+  static int ElfClass(const void* elf_base) {
+    const ElfW(Ehdr)* elf_header =
+        reinterpret_cast<const ElfW(Ehdr)*>(elf_base);
+
+    return elf_header->e_ident[EI_CLASS];
+  }
+
+  static bool FindElfSection(const void* elf_mapped_base,
+                             const char* section_name, uint32_t section_type,
+                             const void** section_start, size_t* section_size) {
+    if (!elf_mapped_base || !section_start || !section_size) {
+      return false;
+    }
+
+    *section_start = NULL;
+    *section_size = 0;
+
+    if (!IsValidElf(elf_mapped_base)) return false;
+
+    int cls = ElfClass(elf_mapped_base);
+    const char* elf_base = static_cast<const char*>(elf_mapped_base);
+
+    if (cls == ELFCLASS32) {
+      return FindElfClassSection<ElfClass32>(elf_base, section_name,
+                                             section_type, section_start,
+                                             section_size) &&
+             *section_start != NULL;
+    } else if (cls == ELFCLASS64) {
+      return FindElfClassSection<ElfClass64>(elf_base, section_name,
+                                             section_type, section_start,
+                                             section_size) &&
+             *section_start != NULL;
+    }
+
+    return false;
+  }
+
+  static bool FindElfSegments(const void* elf_mapped_base,
+                              uint32_t segment_type,
+                              std::vector<ElfSegment>* segments) {
+    if (!elf_mapped_base || !segments) {
+      return false;
+    }
+
+    if (!IsValidElf(elf_mapped_base)) return false;
+
+    int cls = ElfClass(elf_mapped_base);
+    const char* elf_base = static_cast<const char*>(elf_mapped_base);
+
+    if (cls == ELFCLASS32) {
+      return FindElfClassSegment<ElfClass32>(elf_base, segment_type, segments);
+    } else if (cls == ELFCLASS64) {
+      return FindElfClassSegment<ElfClass64>(elf_base, segment_type, segments);
+    }
+
+    return false;
+  }
+
+  // Attempt to locate a .note.gnu.build-id section in an ELF binary
+  // and copy it into |identifier|.
+  static bool FindElfBuildIDNote(const void* elf_mapped_base,
+                                 std::vector<uint8_t>& identifier) {
+    // lld normally creates 2 PT_NOTEs, gold normally creates 1.
+    std::vector<ElfSegment> segs;
+    if (FindElfSegments(elf_mapped_base, PT_NOTE, &segs)) {
+      for (ElfSegment& seg : segs) {
+        if (ElfClassBuildIDNoteIdentifier(seg.start, seg.size, identifier)) {
+          return true;
+        }
+      }
+    }
+
+    void* note_section;
+    size_t note_size;
+    if (FindElfSection(elf_mapped_base, ".note.gnu.build-id", SHT_NOTE,
+                       (const void**)&note_section, &note_size)) {
+      return ElfClassBuildIDNoteIdentifier(note_section, note_size, identifier);
+    }
+
+    return false;
+  }
+
+  // Attempt to locate the .text section of an ELF binary and generate
+  // a simple hash by XORing the first page worth of bytes into |identifier|.
+  static bool HashElfTextSection(const void* elf_mapped_base,
+                                 std::vector<uint8_t>& identifier) {
+    identifier.resize(kMDGUIDSize);
+
+    void* text_section;
+    size_t text_size;
+    if (!FindElfSection(elf_mapped_base, ".text", SHT_PROGBITS,
+                        (const void**)&text_section, &text_size) ||
+        text_size == 0) {
+      return false;
+    }
+
+    // Only provide |kMDGUIDSize| bytes to keep identifiers produced by this
+    // function backwards-compatible.
+    memset(&identifier[0], 0, kMDGUIDSize);
+    const uint8_t* ptr = reinterpret_cast<const uint8_t*>(text_section);
+    const uint8_t* ptr_end =
+        ptr + std::min(text_size, static_cast<size_t>(4096));
+    while (ptr < ptr_end) {
+      for (unsigned i = 0; i < kMDGUIDSize; i++) identifier[i] ^= ptr[i];
+      ptr += kMDGUIDSize;
+    }
+    return true;
+  }
+
+  // Load the identifier for the elf file mapped into memory at |base| into
+  // |identifier|. Return false if the identifier could not be created for this
+  // file.
+  static bool ElfFileIdentifierFromMappedFile(
+      const void* base, std::vector<uint8_t>& identifier) {
+    // Look for a build id note first.
+    if (FindElfBuildIDNote(base, identifier)) return true;
+
+    // Fall back on hashing the first page of the text section.
+    return HashElfTextSection(base, identifier);
+  }
+
+  // These three functions are not ever called in an unsafe context, so it's OK
+  // to allocate memory and use libc.
+  static std::string bytes_to_hex_string(const uint8_t* bytes, size_t count) {
+    std::string result;
+    for (unsigned int idx = 0; idx < count; ++idx) {
+      char buf[3];
+      SprintfLiteral(buf, "%02X", bytes[idx]);
+      result.append(buf);
+    }
+    return result;
+  }
+
+  // Convert the |identifier| data to a string.  The string will
+  // be formatted as a UUID in all uppercase without dashes.
+  // (e.g., 22F065BBFC9C49F780FE26A7CEBD7BCE).
+  static std::string ConvertIdentifierToUUIDString(
+      const std::vector<uint8_t>& identifier) {
+    uint8_t identifier_swapped[kMDGUIDSize] = {0};
+
+    // Endian-ness swap to match dump processor expectation.
+    memcpy(identifier_swapped, &identifier[0],
+           std::min(kMDGUIDSize, identifier.size()));
+    uint32_t* data1 = reinterpret_cast<uint32_t*>(identifier_swapped);
+    *data1 = htonl(*data1);
+    uint16_t* data2 = reinterpret_cast<uint16_t*>(identifier_swapped + 4);
+    *data2 = htons(*data2);
+    uint16_t* data3 = reinterpret_cast<uint16_t*>(identifier_swapped + 6);
+    *data3 = htons(*data3);
+
+    return bytes_to_hex_string(identifier_swapped, kMDGUIDSize);
+  }
+
+  // Convert the entire |identifier| data to a hex string.
+  static std::string ConvertIdentifierToString(
+      const std::vector<uint8_t>& identifier) {
+    return bytes_to_hex_string(&identifier[0], identifier.size());
+  }
+
+ private:
+  // Storage for the path specified
+  std::string path_;
+};
+
+// End of imports from toolkit/crashreporter/google-breakpad/.
+// ----------------------------------------------------------------------------
+
 struct LoadedLibraryInfo {
   LoadedLibraryInfo(const char* aName, unsigned long aBaseAddress,
                     unsigned long aFirstMappingStart,
                     unsigned long aLastMappingEnd)
       : mName(aName),
         mBaseAddress(aBaseAddress),
         mFirstMappingStart(aFirstMappingStart),
         mLastMappingEnd(aLastMappingEnd) {}
 
-  nsCString mName;
+  std::string mName;
   unsigned long mBaseAddress;
   unsigned long mFirstMappingStart;
   unsigned long mLastMappingEnd;
 };
 
 #  if defined(GP_OS_android)
-static void outputMapperLog(const char* aBuf) { LOG("%s", aBuf); }
+static void outputMapperLog(const char* aBuf) { /* LOG("%s", aBuf); */
+}
 #  endif
 
-static nsCString IDtoUUIDString(
-    const google_breakpad::wasteful_vector<uint8_t>& aIdentifier) {
-  using namespace google_breakpad;
-
-  nsCString uuid;
-  const std::string str = FileID::ConvertIdentifierToUUIDString(aIdentifier);
-  uuid.Append(str.c_str(), str.size());
+static std::string IDtoUUIDString(const std::vector<uint8_t>& aIdentifier) {
+  std::string uuid = FileID::ConvertIdentifierToUUIDString(aIdentifier);
   // This is '0', not '\0', since it represents the breakpad id age.
-  uuid.Append('0');
+  uuid += '0';
   return uuid;
 }
 
 // Get the breakpad Id for the binary file pointed by bin_name
-static nsCString getId(const char* bin_name) {
-  using namespace google_breakpad;
-
-  PageAllocator allocator;
-  auto_wasteful_vector<uint8_t, kDefaultBuildIdSize> identifier(&allocator);
+static std::string getId(const char* bin_name) {
+  std::vector<uint8_t> identifier;
+  identifier.reserve(kDefaultBuildIdSize);
 
 #  if defined(GP_OS_android)
   if (nsDependentCString(bin_name).Find("!/") != kNotFound) {
     AutoObjectMapperFaultyLib mapper(outputMapperLog);
     void* image = nullptr;
     size_t size = 0;
     if (mapper.Map(&image, &size, bin_name) && image && size) {
       if (FileID::ElfFileIdentifierFromMappedFile(image, identifier)) {
@@ -94,40 +678,36 @@ static nsCString getId(const char* bin_n
   }
 #  endif
 
   FileID file_id(bin_name);
   if (file_id.ElfFileIdentifier(identifier)) {
     return IDtoUUIDString(identifier);
   }
 
-  return EmptyCString();
+  return {};
 }
 
 static SharedLibrary SharedLibraryAtPath(const char* path,
                                          unsigned long libStart,
                                          unsigned long libEnd,
                                          unsigned long offset = 0) {
-  nsAutoString pathStr;
-  mozilla::Unused << NS_WARN_IF(
-      NS_FAILED(NS_CopyNativeToUnicode(nsDependentCString(path), pathStr)));
+  std::string pathStr = path;
 
-  nsAutoString nameStr = pathStr;
-  int32_t pos = nameStr.RFindChar('/');
-  if (pos != kNotFound) {
-    nameStr.Cut(0, pos + 1);
-  }
+  size_t pos = pathStr.rfind('\\');
+  std::string nameStr =
+      (pos != std::string::npos) ? pathStr.substr(pos + 1) : pathStr;
 
   return SharedLibrary(libStart, libEnd, offset, getId(path), nameStr, pathStr,
-                       nameStr, pathStr, EmptyCString(), "");
+                       nameStr, pathStr, std::string{}, "");
 }
 
 static int dl_iterate_callback(struct dl_phdr_info* dl_info, size_t size,
                                void* data) {
-  auto libInfoList = reinterpret_cast<nsTArray<LoadedLibraryInfo>*>(data);
+  auto libInfoList = reinterpret_cast<std::vector<LoadedLibraryInfo>*>(data);
 
   if (dl_info->dlpi_phnum <= 0) return 0;
 
   unsigned long baseAddress = dl_info->dlpi_addr;
   unsigned long firstMappingStart = -1;
   unsigned long lastMappingEnd = 0;
 
   for (size_t i = 0; i < dl_info->dlpi_phnum; i++) {
@@ -139,18 +719,18 @@ static int dl_iterate_callback(struct dl
     if (start < firstMappingStart) {
       firstMappingStart = start;
     }
     if (end > lastMappingEnd) {
       lastMappingEnd = end;
     }
   }
 
-  libInfoList->AppendElement(LoadedLibraryInfo(
-      dl_info->dlpi_name, baseAddress, firstMappingStart, lastMappingEnd));
+  libInfoList->push_back(LoadedLibraryInfo(dl_info->dlpi_name, baseAddress,
+                                           firstMappingStart, lastMappingEnd));
 
   return 0;
 }
 
 SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
   SharedLibraryInfo info;
 
 #  if defined(GP_OS_linux)
@@ -159,17 +739,17 @@ SharedLibraryInfo SharedLibraryInfo::Get
   char exeName[PATH_MAX];
   memset(exeName, 0, sizeof(exeName));
 
   ssize_t exeNameLen = readlink("/proc/self/exe", exeName, sizeof(exeName) - 1);
   if (exeNameLen == -1) {
     // readlink failed for whatever reason.  Note this, but keep going.
     exeName[0] = '\0';
     exeNameLen = 0;
-    LOG("SharedLibraryInfo::GetInfoForSelf(): readlink failed");
+    // LOG("SharedLibraryInfo::GetInfoForSelf(): readlink failed");
   } else {
     // Assert no buffer overflow.
     MOZ_RELEASE_ASSERT(exeNameLen >= 0 &&
                        exeNameLen < static_cast<ssize_t>(sizeof(exeName)));
   }
 
   unsigned long exeExeAddr = 0;
 #  endif
@@ -201,61 +781,61 @@ SharedLibraryInfo SharedLibraryInfo::Get
     ret = sscanf(line.c_str(),
                  "%lx-%lx %6s %lx %*s %*x %" PATH_MAX_STRING(PATH_MAX) "s\n",
                  &start, &end, perm, &offset, modulePath);
     if (!strchr(perm, 'x')) {
       // Ignore non executable entries
       continue;
     }
     if (ret != 5 && ret != 4) {
-      LOG("SharedLibraryInfo::GetInfoForSelf(): "
-          "reading /proc/self/maps failed");
+      // LOG("SharedLibraryInfo::GetInfoForSelf(): "
+      //     "reading /proc/self/maps failed");
       continue;
     }
 
 #  if defined(GP_OS_linux)
     // Try to establish the main executable's load address.
     if (exeNameLen > 0 && strcmp(modulePath, exeName) == 0) {
       exeExeAddr = start;
     }
 #  elif defined(GP_OS_android)
     // Use /proc/pid/maps to get the dalvik-jit section since it has no
     // associated phdrs.
     if (0 == strcmp(modulePath, "/dev/ashmem/dalvik-jit-code-cache")) {
       info.AddSharedLibrary(
           SharedLibraryAtPath(modulePath, start, end, offset));
       if (info.GetSize() > 10000) {
-        LOG("SharedLibraryInfo::GetInfoForSelf(): "
-            "implausibly large number of mappings acquired");
+        // LOG("SharedLibraryInfo::GetInfoForSelf(): "
+        //     "implausibly large number of mappings acquired");
         break;
       }
     }
 #  endif
   }
 
-  nsTArray<LoadedLibraryInfo> libInfoList;
+  std::vector<LoadedLibraryInfo> libInfoList;
 
   // We collect the bulk of the library info using dl_iterate_phdr.
   dl_iterate_phdr(dl_iterate_callback, &libInfoList);
 
   for (const auto& libInfo : libInfoList) {
     info.AddSharedLibrary(
-        SharedLibraryAtPath(libInfo.mName.get(), libInfo.mFirstMappingStart,
+        SharedLibraryAtPath(libInfo.mName.c_str(), libInfo.mFirstMappingStart,
                             libInfo.mLastMappingEnd,
                             libInfo.mFirstMappingStart - libInfo.mBaseAddress));
   }
 
 #  if defined(GP_OS_linux)
   // Make another pass over the information we just harvested from
   // dl_iterate_phdr.  If we see a nameless object mapped at what we earlier
   // established to be the main executable's load address, attach the
   // executable's name to that entry.
   for (size_t i = 0; i < info.GetSize(); i++) {
     SharedLibrary& lib = info.GetMutableEntry(i);
-    if (lib.GetStart() == exeExeAddr && lib.GetNativeDebugPath().empty()) {
+    if (lib.GetStart() == exeExeAddr && lib.GetDebugPath().empty()) {
       lib = SharedLibraryAtPath(exeName, lib.GetStart(), lib.GetEnd(),
                                 lib.GetOffset());
 
       // We only expect to see one such entry.
       break;
     }
   }
 #  endif
--- a/mozglue/baseprofiler/core/shared-libraries-macos.cc
+++ b/mozglue/baseprofiler/core/shared-libraries-macos.cc
@@ -4,20 +4,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "BaseProfiler.h"
 
 #ifdef MOZ_BASE_PROFILER
 
 #  include "BaseProfilerSharedLibraries.h"
 
-#  include "ClearOnShutdown.h"
-#  include "mozilla/StaticMutex.h"
+#  include "platform.h"
+
 #  include "mozilla/Unused.h"
-#  include "nsNativeCharsetUtils.h"
 #  include <AvailabilityMacros.h>
 
 #  include <dlfcn.h>
 #  include <mach-o/arch.h>
 #  include <mach-o/dyld_images.h>
 #  include <mach-o/dyld.h>
 #  include <mach-o/loader.h>
 #  include <mach/mach_init.h>
@@ -44,47 +43,61 @@ typedef segment_command_64 mach_segment_
 #    define seg_size uint64_t
 #  endif
 
 struct NativeSharedLibrary {
   const platform_mach_header* header;
   std::string path;
 };
 static std::vector<NativeSharedLibrary>* sSharedLibrariesList = nullptr;
-static mozilla::StaticMutex sSharedLibrariesMutex;
+
+class MOZ_RAII SharedLibrariesLock {
+ public:
+  SharedLibrariesLock() { sSharedLibrariesMutex.Lock(); }
+
+  ~SharedLibrariesLock() { sSharedLibrariesMutex.Unlock(); }
+
+  SharedLibrariesLock(const SharedLibrariesLock&) = delete;
+  void operator=(const SharedLibrariesLock&) = delete;
+
+ private:
+  static mozilla::baseprofiler::PSMutex sSharedLibrariesMutex;
+};
+
+mozilla::baseprofiler::PSMutex SharedLibrariesLock::sSharedLibrariesMutex;
 
 static void SharedLibraryAddImage(const struct mach_header* mh,
                                   intptr_t vmaddr_slide) {
   // NOTE: Presumably for backwards-compatibility reasons, this function accepts
   // a mach_header even on 64-bit where it ought to be a mach_header_64. We cast
   // it to the right type here.
   auto header = reinterpret_cast<const platform_mach_header*>(mh);
 
   Dl_info info;
   if (!dladdr(header, &info)) {
     return;
   }
 
-  mozilla::StaticMutexAutoLock lock(sSharedLibrariesMutex);
+  SharedLibrariesLock lock;
   if (!sSharedLibrariesList) {
     return;
   }
 
   NativeSharedLibrary lib = {header, info.dli_fname};
   sSharedLibrariesList->push_back(lib);
 }
 
 static void SharedLibraryRemoveImage(const struct mach_header* mh,
                                      intptr_t vmaddr_slide) {
   // NOTE: Presumably for backwards-compatibility reasons, this function accepts
   // a mach_header even on 64-bit where it ought to be a mach_header_64. We cast
   // it to the right type here.
   auto header = reinterpret_cast<const platform_mach_header*>(mh);
 
-  mozilla::StaticMutexAutoLock lock(sSharedLibrariesMutex);
+  SharedLibrariesLock lock;
   if (!sSharedLibrariesList) {
     return;
   }
 
   uint32_t count = sSharedLibrariesList->size();
   for (uint32_t i = 0; i < count; ++i) {
     if ((*sSharedLibrariesList)[i].header == header) {
       sSharedLibrariesList->erase(sSharedLibrariesList->begin() + i);
@@ -126,64 +139,47 @@ static void addSharedLibrary(const platf
       const uuid_command* ucmd = reinterpret_cast<const uuid_command*>(cmd);
       uuid_bytes = ucmd->uuid;
     }
 
     cmd = reinterpret_cast<const struct load_command*>(
         reinterpret_cast<const char*>(cmd) + cmd->cmdsize);
   }
 
-  nsAutoCString uuid;
+  std::string uuid;
   if (uuid_bytes != nullptr) {
-    uuid.AppendPrintf(
-        "%02X"
-        "%02X"
-        "%02X"
-        "%02X"
-        "%02X"
-        "%02X"
-        "%02X"
-        "%02X"
-        "%02X"
-        "%02X"
-        "%02X"
-        "%02X"
-        "%02X"
-        "%02X"
-        "%02X"
-        "%02X"
-        "0" /* breakpad id age */,
-        uuid_bytes[0], uuid_bytes[1], uuid_bytes[2], uuid_bytes[3],
-        uuid_bytes[4], uuid_bytes[5], uuid_bytes[6], uuid_bytes[7],
-        uuid_bytes[8], uuid_bytes[9], uuid_bytes[10], uuid_bytes[11],
-        uuid_bytes[12], uuid_bytes[13], uuid_bytes[14], uuid_bytes[15]);
+    static constexpr char digits[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
+                                        '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+    for (int i = 0; i < 15; ++i) {
+      uint8_t byte = uuid_bytes[i];
+      uuid += digits[byte >> 4];
+      uuid += digits[byte & 0xFu];
+    }
+    // breakpad id age.
+    uuid += '0';
   }
 
-  nsAutoString pathStr;
-  mozilla::Unused << NS_WARN_IF(
-      NS_FAILED(NS_CopyNativeToUnicode(nsDependentCString(path), pathStr)));
+  std::string pathStr = path;
 
-  nsAutoString nameStr = pathStr;
-  int32_t pos = nameStr.RFindChar('/');
-  if (pos != kNotFound) {
-    nameStr.Cut(0, pos + 1);
-  }
+  size_t pos = pathStr.rfind('\\');
+  std::string nameStr =
+      (pos != std::string::npos) ? pathStr.substr(pos + 1) : pathStr;
 
   const NXArchInfo* archInfo =
       NXGetArchInfoFromCpuType(header->cputype, header->cpusubtype);
 
   info.AddSharedLibrary(SharedLibrary(start, start + size, 0, uuid, nameStr,
-                                      pathStr, nameStr, pathStr, EmptyCString(),
+                                      pathStr, nameStr, pathStr, std::string{},
                                       archInfo ? archInfo->name : ""));
 }
 
 // Translate the statically stored sSharedLibrariesList information into a
 // SharedLibraryInfo object.
 SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
-  mozilla::StaticMutexAutoLock lock(sSharedLibrariesMutex);
+  SharedLibrariesLock lock;
   SharedLibraryInfo sharedLibraryInfo;
 
   for (auto& info : *sSharedLibrariesList) {
     addSharedLibrary(info.header, info.path.c_str(), sharedLibraryInfo);
   }
 
   return sharedLibraryInfo;
 }
--- a/mozglue/baseprofiler/core/shared-libraries-win32.cc
+++ b/mozglue/baseprofiler/core/shared-libraries-win32.cc
@@ -8,36 +8,68 @@
 #ifdef MOZ_BASE_PROFILER
 
 #  include <windows.h>
 #  include <dbghelp.h>
 #  include <sstream>
 #  include <psapi.h>
 
 #  include "BaseProfilerSharedLibraries.h"
-#  include "nsWindowsHelpers.h"
+
 #  include "mozilla/UniquePtr.h"
 #  include "mozilla/Unused.h"
-#  include "nsNativeCharsetUtils.h"
-#  include "nsPrintfCString.h"
-#  include "nsReadableUtils.h"
+
+#  include <string>
 
 #  define CV_SIGNATURE 0x53445352  // 'SDSR'
 
 struct CodeViewRecord70 {
   uint32_t signature;
   GUID pdbSignature;
   uint32_t pdbAge;
   // A UTF-8 string, according to
   // https://github.com/Microsoft/microsoft-pdb/blob/082c5290e5aff028ae84e43affa8be717aa7af73/PDB/dbi/locator.cpp#L785
   char pdbFileName[1];
 };
 
-static bool GetPdbInfo(uintptr_t aStart, nsID& aSignature, uint32_t& aAge,
-                       char** aPdbName) {
+static constexpr char digits[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
+                                    '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+
+static void AppendHex(const unsigned char* aBegin, const unsigned char* aEnd,
+                      std::string& aOut) {
+  for (const unsigned char* p = aBegin; p < aEnd; ++p) {
+    unsigned char c = *p;
+    aOut += digits[c >> 4];
+    aOut += digits[c & 0xFu];
+  }
+}
+
+static constexpr bool WITH_PADDING = true;
+static constexpr bool WITHOUT_PADDING = false;
+template <typename T>
+static void AppendHex(T aValue, std::string& aOut, bool aWithPadding) {
+  for (int i = sizeof(T) * 2 - 1; i >= 0; --i) {
+    unsigned nibble = (aValue >> (i * 4)) & 0xFu;
+    // If no-padding requested, skip starting zeroes -- unless we're on the very
+    // last nibble (so we don't output a blank).
+    if (!aWithPadding && i != 0) {
+      if (nibble == 0) {
+        // Requested no padding, skip zeroes.
+        continue;
+      }
+      // Requested no padding, got first non-zero, pretend we now want padding
+      // so we don't skip zeroes anymore.
+      aWithPadding = true;
+    }
+    aOut += digits[nibble];
+  }
+}
+
+static bool GetPdbInfo(uintptr_t aStart, std::string& aSignature,
+                       uint32_t& aAge, char** aPdbName) {
   if (!aStart) {
     return false;
   }
 
   PIMAGE_DOS_HEADER dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(aStart);
   if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
     return false;
   }
@@ -64,54 +96,56 @@ static bool GetPdbInfo(uintptr_t aStart,
   CodeViewRecord70* debugInfo = reinterpret_cast<CodeViewRecord70*>(
       aStart + debugDirectory->AddressOfRawData);
   if (!debugInfo || debugInfo->signature != CV_SIGNATURE) {
     return false;
   }
 
   aAge = debugInfo->pdbAge;
   GUID& pdbSignature = debugInfo->pdbSignature;
-  aSignature.m0 = pdbSignature.Data1;
-  aSignature.m1 = pdbSignature.Data2;
-  aSignature.m2 = pdbSignature.Data3;
-  memcpy(aSignature.m3, pdbSignature.Data4, sizeof(pdbSignature.Data4));
+  AppendHex(pdbSignature.Data1, aSignature, WITH_PADDING);
+  AppendHex(pdbSignature.Data2, aSignature, WITH_PADDING);
+  AppendHex(pdbSignature.Data3, aSignature, WITH_PADDING);
+  AppendHex(reinterpret_cast<const unsigned char*>(&pdbSignature.Data4),
+            reinterpret_cast<const unsigned char*>(&pdbSignature.Data4) +
+                sizeof(pdbSignature.Data4),
+            aSignature);
 
   // The PDB file name could be different from module filename, so report both
   // e.g. The PDB for C:\Windows\SysWOW64\ntdll.dll is wntdll.pdb
   *aPdbName = debugInfo->pdbFileName;
 
   return true;
 }
 
-static nsCString GetVersion(WCHAR* dllPath) {
-  DWORD infoSize = GetFileVersionInfoSizeW(dllPath, nullptr);
+static std::string GetVersion(char* dllPath) {
+  DWORD infoSize = GetFileVersionInfoSizeA(dllPath, nullptr);
   if (infoSize == 0) {
-    return EmptyCString();
+    return {};
   }
 
   mozilla::UniquePtr<unsigned char[]> infoData =
       mozilla::MakeUnique<unsigned char[]>(infoSize);
-  if (!GetFileVersionInfoW(dllPath, 0, infoSize, infoData.get())) {
-    return EmptyCString();
+  if (!GetFileVersionInfoA(dllPath, 0, infoSize, infoData.get())) {
+    return {};
   }
 
   VS_FIXEDFILEINFO* vInfo;
   UINT vInfoLen;
   if (!VerQueryValueW(infoData.get(), L"\\", (LPVOID*)&vInfo, &vInfoLen)) {
-    return EmptyCString();
+    return {};
   }
   if (!vInfo) {
-    return EmptyCString();
+    return {};
   }
 
-  nsPrintfCString version("%d.%d.%d.%d", vInfo->dwFileVersionMS >> 16,
-                          vInfo->dwFileVersionMS & 0xFFFF,
-                          vInfo->dwFileVersionLS >> 16,
-                          vInfo->dwFileVersionLS & 0xFFFF);
-  return std::move(version);
+  return std::to_string(vInfo->dwFileVersionMS >> 16) + '.' +
+         std::to_string(vInfo->dwFileVersionMS & 0xFFFF) + '.' +
+         std::to_string(vInfo->dwFileVersionLS >> 16) + '.' +
+         std::to_string(vInfo->dwFileVersionLS & 0xFFFF);
 }
 
 SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
   SharedLibraryInfo sharedLibraryInfo;
 
   HANDLE hProcess = GetCurrentProcess();
   mozilla::UniquePtr<HMODULE[]> hMods;
   size_t modulesNum = 0;
@@ -128,78 +162,70 @@ SharedLibraryInfo SharedLibraryInfo::Get
     }
     // The list may have shrunk between calls
     if (modulesSize / sizeof(HMODULE) < modulesNum) {
       modulesNum = modulesSize / sizeof(HMODULE);
     }
   }
 
   for (unsigned int i = 0; i < modulesNum; i++) {
-    nsAutoString pdbPathStr;
-    nsAutoString pdbNameStr;
+    std::string pdbPathStr;
+    std::string pdbNameStr;
     char* pdbName = NULL;
-    WCHAR modulePath[MAX_PATH + 1];
+    char modulePath[MAX_PATH + 1];
 
     if (!GetModuleFileNameEx(hProcess, hMods[i], modulePath,
-                             sizeof(modulePath) / sizeof(WCHAR))) {
+                             sizeof(modulePath) / sizeof(char))) {
       continue;
     }
 
     MODULEINFO module = {0};
     if (!GetModuleInformation(hProcess, hMods[i], &module,
                               sizeof(MODULEINFO))) {
       continue;
     }
 
-    nsCString breakpadId;
+    std::string breakpadId;
     // Load the module again to make sure that its handle will remain
     // valid as we attempt to read the PDB information from it.  We load the
     // DLL as a datafile so that if the module actually gets unloaded between
-    // the call to EnumProcessModules and the following LoadLibraryEx, we don't
-    // end up running the now newly loaded module's DllMain function.  If the
-    // module is already loaded, LoadLibraryEx just increments its refcount.
+    // the call to EnumProcessModules and the following LoadLibraryEx, we
+    // don't end up running the now newly loaded module's DllMain function. If
+    // the module is already loaded, LoadLibraryEx just increments its
+    // refcount.
     //
     // Note that because of the race condition above, merely loading the DLL
     // again is not safe enough, therefore we also need to make sure that we
     // can read the memory mapped at the base address before we can safely
     // proceed to actually access those pages.
     HMODULE handleLock =
         LoadLibraryEx(modulePath, NULL, LOAD_LIBRARY_AS_DATAFILE);
     MEMORY_BASIC_INFORMATION vmemInfo = {0};
-    nsID pdbSig;
+    std::string pdbSig;
     uint32_t pdbAge;
     if (handleLock &&
         sizeof(vmemInfo) ==
             VirtualQuery(module.lpBaseOfDll, &vmemInfo, sizeof(vmemInfo)) &&
         vmemInfo.State == MEM_COMMIT &&
         GetPdbInfo((uintptr_t)module.lpBaseOfDll, pdbSig, pdbAge, &pdbName)) {
-      MOZ_ASSERT(breakpadId.IsEmpty());
-      breakpadId.AppendPrintf(
-          "%08X"                              // m0
-          "%04X%04X"                          // m1,m2
-          "%02X%02X%02X%02X%02X%02X%02X%02X"  // m3
-          "%X",                               // pdbAge
-          pdbSig.m0, pdbSig.m1, pdbSig.m2, pdbSig.m3[0], pdbSig.m3[1],
-          pdbSig.m3[2], pdbSig.m3[3], pdbSig.m3[4], pdbSig.m3[5], pdbSig.m3[6],
-          pdbSig.m3[7], pdbAge);
+      MOZ_ASSERT(breakpadId.empty());
+      breakpadId += pdbSig;
+      AppendHex(pdbAge, breakpadId, WITHOUT_PADDING);
 
-      pdbPathStr = NS_ConvertUTF8toUTF16(pdbName);
-      pdbNameStr = pdbPathStr;
-      int32_t pos = pdbNameStr.RFindChar('\\');
-      if (pos != kNotFound) {
-        pdbNameStr.Cut(0, pos + 1);
-      }
+      pdbPathStr = pdbName;
+      size_t pos = pdbPathStr.rfind('\\');
+      pdbNameStr =
+          (pos != std::string::npos) ? pdbPathStr.substr(pos + 1) : pdbPathStr;
     }
 
-    nsAutoString modulePathStr(modulePath);
-    nsAutoString moduleNameStr = modulePathStr;
-    int32_t pos = moduleNameStr.RFindChar('\\');
-    if (pos != kNotFound) {
-      moduleNameStr.Cut(0, pos + 1);
-    }
+    std::string modulePathStr(modulePath);
+    size_t pos = modulePathStr.rfind('\\');
+    std::string moduleNameStr = (pos != std::string::npos)
+                                    ? modulePathStr.substr(pos + 1)
+                                    : modulePathStr;
 
     SharedLibrary shlib((uintptr_t)module.lpBaseOfDll,
                         (uintptr_t)module.lpBaseOfDll + module.SizeOfImage,
                         0,  // DLLs are always mapped at offset 0 on Windows
                         breakpadId, moduleNameStr, modulePathStr, pdbNameStr,
                         pdbPathStr, GetVersion(modulePath), "");
     sharedLibraryInfo.AddSharedLibrary(shlib);
 
--- a/mozglue/baseprofiler/lul/AutoObjectMapper.cpp
+++ b/mozglue/baseprofiler/lul/AutoObjectMapper.cpp
@@ -26,20 +26,16 @@
 // FIXME move these out of mozglue/linker/ElfLoader.h into their
 // own header, so as to avoid conflicts arising from two definitions
 // of Array
 extern "C" {
 MFBT_API size_t __dl_get_mappable_length(void* handle);
 MFBT_API void* __dl_mmap(void* handle, void* addr, size_t length, off_t offset);
 MFBT_API void __dl_munmap(void* handle, void* addr, size_t length);
 }
-// The following are for get_installation_lib_dir()
-#    include "nsString.h"
-#    include "nsDirectoryServiceUtils.h"
-#    include "nsDirectoryServiceDefs.h"
 #  endif
 
 // A helper function for creating failure error messages in
 // AutoObjectMapper*::Map.
 static void failedToMessage(void (*aLog)(const char*), const char* aHowFailed,
                             std::string aFileName) {
   char buf[300];
   SprintfLiteral(buf, "AutoObjectMapper::Map: Failed to %s \'%s\'", aHowFailed,
@@ -95,38 +91,16 @@ bool AutoObjectMapperPOSIX::Map(/*OUT*/ 
   close(fd);
   mIsMapped = true;
   mImage = *start = image;
   mSize = *length = sz;
   return true;
 }
 
 #  if defined(GP_OS_android)
-// A helper function for AutoObjectMapperFaultyLib::Map.  Finds out
-// where the installation's lib directory is, since we'll have to look
-// in there to get hold of libmozglue.so.  Returned C string is heap
-// allocated and the caller must deallocate it.
-static char* get_installation_lib_dir() {
-  nsCOMPtr<nsIProperties> directoryService(
-      do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
-  if (!directoryService) {
-    return nullptr;
-  }
-  nsCOMPtr<nsIFile> greDir;
-  nsresult rv = directoryService->Get(NS_GRE_DIR, NS_GET_IID(nsIFile),
-                                      getter_AddRefs(greDir));
-  if (NS_FAILED(rv)) return nullptr;
-  nsCString path;
-  rv = greDir->GetNativePath(path);
-  if (NS_FAILED(rv)) {
-    return nullptr;
-  }
-  return strdup(path.get());
-}
-
 AutoObjectMapperFaultyLib::AutoObjectMapperFaultyLib(void (*aLog)(const char*))
     : AutoObjectMapperPOSIX(aLog), mHdl(nullptr) {}
 
 AutoObjectMapperFaultyLib::~AutoObjectMapperFaultyLib() {
   if (mHdl) {
     // We've got an object mapped by faulty.lib.  Unmap it via faulty.lib.
     MOZ_ASSERT(mSize > 0);
     // Assert on the basis that no valid mapping would start at page zero.
@@ -143,52 +117,14 @@ AutoObjectMapperFaultyLib::~AutoObjectMa
   // obvious way to enforce the requirement that the object is mapped
   // either by faulty.lib or by the parent class, but not by both.
 }
 
 bool AutoObjectMapperFaultyLib::Map(/*OUT*/ void** start,
                                     /*OUT*/ size_t* length,
                                     std::string fileName) {
   MOZ_ASSERT(!mHdl);
-
-  if (fileName == "libmozglue.so") {
-    // Do (2) in the comment above.
-    char* libdir = get_installation_lib_dir();
-    if (libdir) {
-      fileName = std::string(libdir) + "/lib/" + fileName;
-      free(libdir);
-    }
-    // Hand the problem off to the standard mapper.
-    return AutoObjectMapperPOSIX::Map(start, length, fileName);
-
-  } else {
-    // Do cases (1) and (3) in the comment above.  We have to
-    // grapple with faulty.lib directly.
-    void* hdl = dlopen(fileName.c_str(), RTLD_GLOBAL | RTLD_LAZY);
-    if (!hdl) {
-      failedToMessage(mLog, "get handle for ELF file", fileName);
-      return false;
-    }
-
-    size_t sz = __dl_get_mappable_length(hdl);
-    if (sz == 0) {
-      dlclose(hdl);
-      failedToMessage(mLog, "get size for ELF file", fileName);
-      return false;
-    }
-
-    void* image = __dl_mmap(hdl, nullptr, sz, 0);
-    if (image == MAP_FAILED) {
-      dlclose(hdl);
-      failedToMessage(mLog, "mmap ELF file", fileName);
-      return false;
-    }
-
-    mHdl = hdl;
-    mImage = *start = image;
-    mSize = *length = sz;
-    return true;
-  }
+  return false;
 }
 
 #  endif  // defined(GP_OS_android)
 
 #endif  // MOZ_BASE_PROFILER
--- a/mozglue/baseprofiler/lul/LulElf.cpp
+++ b/mozglue/baseprofiler/lul/LulElf.cpp
@@ -46,16 +46,17 @@
 //   src/common/linux/file_id.cc
 
 #include "BaseProfiler.h"
 
 #ifdef MOZ_BASE_PROFILER
 
 #  include <errno.h>
 #  include <fcntl.h>
+#  include <libgen.h>
 #  include <stdio.h>
 #  include <string.h>
 #  include <sys/mman.h>
 #  include <sys/stat.h>
 #  include <unistd.h>
 #  include <arpa/inet.h>
 
 #  include <set>
--- a/mozglue/baseprofiler/lul/platform-linux-lul.cpp
+++ b/mozglue/baseprofiler/lul/platform-linux-lul.cpp
@@ -29,17 +29,17 @@ void read_procmaps(lul::LUL* aLUL) {
   MOZ_ASSERT(aLUL->CountMappings() == 0);
 
 #  if defined(GP_OS_linux) || defined(GP_OS_android)
   SharedLibraryInfo info = SharedLibraryInfo::GetInfoForSelf();
 
   for (size_t i = 0; i < info.GetSize(); i++) {
     const SharedLibrary& lib = info.GetEntry(i);
 
-    std::string nativePath = lib.GetNativeDebugPath();
+    std::string nativePath = lib.GetDebugPath();
 
 #    if defined(GP_OS_android)
     // We're using faulty.lib.  Use a special-case object mapper.
     AutoObjectMapperFaultyLib mapper(aLUL->mLog);
 #    else
     // We can use the standard POSIX-based mapper.
     AutoObjectMapperPOSIX mapper(aLUL->mLog);
 #    endif
@@ -47,17 +47,17 @@ void read_procmaps(lul::LUL* aLUL) {
     // Ask |mapper| to map the object.  Then hand its mapped address
     // to NotifyAfterMap().
     void* image = nullptr;
     size_t size = 0;
     bool ok = mapper.Map(&image, &size, nativePath);
     if (ok && image && size > 0) {
       aLUL->NotifyAfterMap(lib.GetStart(), lib.GetEnd() - lib.GetStart(),
                            nativePath.c_str(), image);
-    } else if (!ok && lib.GetDebugName().IsEmpty()) {
+    } else if (!ok && lib.GetDebugName().empty()) {
       // The object has no name and (as a consequence) the mapper failed to map
       // it.  This happens on Linux, where GetInfoForSelf() produces such a
       // mapping for the VDSO.  This is a problem on x86-{linux,android} because
       // lack of knowledge about the mapped area inhibits LUL's special
       // __kernel_syscall handling.  Hence notify |aLUL| at least of the
       // mapping, even though it can't read any unwind information for the area.
       aLUL->NotifyExecutableArea(lib.GetStart(), lib.GetEnd() - lib.GetStart());
     }
@@ -69,16 +69,18 @@ void read_procmaps(lul::LUL* aLUL) {
 #  else
 #    error "Unknown platform"
 #  endif
 }
 
 // LUL needs a callback for its logging sink.
 void logging_sink_for_LUL(const char* str) {
   // These are only printed when Verbose logging is enabled (e.g. with
-  // MOZ_LOG="prof:5"). This is because LUL's logging is much more verbose than
-  // the rest of the profiler's logging, which occurs at the Info (3) and Debug
-  // (4) levels.
-  MOZ_LOG(gProfilerLog, mozilla::LogLevel::Verbose,
-          ("[%d] %s", profiler_current_process_id(), str));
+  // MOZ_BASE_PROFILER_VERBOSE_LOGGING=1). This is because LUL's logging is much
+  // more verbose than the rest of the profiler's logging, which occurs at the
+  // Info (3) and Debug (4) levels.
+  // FIXME: This causes a build failure in memory/replace/dmd/test/SmokeDMD (!)
+  // and other places, because it doesn't link the implementation in
+  // platform.cpp.
+  // VERBOSE_LOG("[%d] %s", profiler_current_process_id(), str);
 }
 
 #endif  // MOZ_BASE_PROFILER
--- a/mozglue/baseprofiler/lul/platform-linux-lul.h
+++ b/mozglue/baseprofiler/lul/platform-linux-lul.h
@@ -3,16 +3,18 @@
  * 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 MOZ_PLATFORM_LINUX_LUL_H
 #define MOZ_PLATFORM_LINUX_LUL_H
 
 #include "platform.h"
 
+#include "BaseProfiler.h"
+
 // Find out, in a platform-dependent way, where the code modules got
 // mapped in the process' virtual address space, and get |aLUL| to
 // load unwind info for them.
 void read_procmaps(lul::LUL* aLUL);
 
 // LUL needs a callback for its logging sink.
 void logging_sink_for_LUL(const char* str);
 
--- a/mozglue/baseprofiler/public/BaseProfileJSONWriter.h
+++ b/mozglue/baseprofiler/public/BaseProfileJSONWriter.h
@@ -1,15 +1,15 @@
 /* -*- 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
+#ifndef BASEPROFILEJSONWRITER_H
+#define BASEPROFILEJSONWRITER_H
 
 #include "BaseProfiler.h"
 
 #ifndef MOZ_BASE_PROFILER
 #  error Do not #include this header when MOZ_BASE_PROFILER is not #defined.
 #endif
 
 #include "mozilla/JSONWriter.h"
@@ -139,9 +139,9 @@ class JSONSchemaWriter {
                                 SpliceableJSONWriter::SingleLineStyle);
   }
 
   void WriteField(const char* aName) { mWriter.IntProperty(aName, mIndex++); }
 
   ~JSONSchemaWriter() { mWriter.EndObject(); }
 };
 
-#endif  // PROFILEJSONWRITER_H
+#endif  // BASEPROFILEJSONWRITER_H
--- a/mozglue/baseprofiler/public/BaseProfiler.h
+++ b/mozglue/baseprofiler/public/BaseProfiler.h
@@ -8,34 +8,34 @@
 // samples of the program execution using only userspace functionality for
 // portability. The goal of this module is to provide performance data in a
 // generic cross-platform way without requiring custom tools or kernel support.
 //
 // Samples are collected to form a timeline with optional timeline event
 // (markers) used for filtering. The samples include both native stacks and
 // platform-independent "label stack" frames.
 
-#ifndef GeckoProfiler_h
-#define GeckoProfiler_h
+#ifndef BaseProfiler_h
+#define BaseProfiler_h
 
 // Everything in here is also safe to include unconditionally, and only defines
 // empty macros if MOZ_GECKO_PROFILER or MOZ_BASE_PROFILER is unset.
 
 // MOZ_BASE_PROFILER is #defined (or not) in this header, so it should be
 // #included wherever Base Profiler may be used.
 
 #ifdef MOZ_GECKO_PROFILER
 // Disable Base Profiler for now; will be enabled on supported platforms in
 // later patches.
 #  if 0
 #    define MOZ_BASE_PROFILER
 #  else
 // Other platforms are currently not supported. But you may uncomment the
 // following line to enable Base Profiler in your build.
-//#  define MOZ_BASE_PROFILER
+//#    define MOZ_BASE_PROFILER
 #  endif
 #endif  // MOZ_GECKO_PROFILER
 
 // BaseProfilerCounts.h is also safe to include unconditionally, with empty
 // macros if MOZ_BASE_PROFILER is unset.
 #include "mozilla/BaseProfilerCounts.h"
 
 #ifndef MOZ_BASE_PROFILER
@@ -49,77 +49,59 @@
 
 #  define PROFILER_REGISTER_THREAD(name)
 #  define PROFILER_UNREGISTER_THREAD()
 #  define AUTO_PROFILER_REGISTER_THREAD(name)
 
 #  define AUTO_PROFILER_THREAD_SLEEP
 #  define AUTO_PROFILER_THREAD_WAKE
 
-#  define PROFILER_JS_INTERRUPT_CALLBACK()
-
-#  define PROFILER_SET_JS_CONTEXT(cx)
-#  define PROFILER_CLEAR_JS_CONTEXT()
-
 #  define AUTO_PROFILER_LABEL(label, categoryPair)
 #  define AUTO_PROFILER_LABEL_CATEGORY_PAIR(categoryPair)
 #  define AUTO_PROFILER_LABEL_DYNAMIC_CSTR(label, categoryPair, cStr)
-#  define AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING(label, categoryPair, nsCStr)
-#  define AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING(label, categoryPair, nsStr)
+#  define AUTO_PROFILER_LABEL_DYNAMIC_STRING(label, categoryPair, str)
 #  define AUTO_PROFILER_LABEL_FAST(label, categoryPair, ctx)
 #  define AUTO_PROFILER_LABEL_DYNAMIC_FAST(label, dynamicString, categoryPair, \
                                            ctx, flags)
 
 #  define PROFILER_ADD_MARKER(markerName, categoryPair)
-#  define PROFILER_ADD_NETWORK_MARKER(uri, pri, channel, type, start, end, \
-                                      count, cache, timings, redirect)
 
 #  define DECLARE_DOCSHELL_AND_HISTORY_ID(docShell)
 #  define PROFILER_TRACING(categoryString, markerName, categoryPair, kind)
 #  define PROFILER_TRACING_DOCSHELL(categoryString, markerName, categoryPair, \
                                     kind, docshell)
 #  define AUTO_PROFILER_TRACING(categoryString, markerName, categoryPair)
 #  define AUTO_PROFILER_TRACING_DOCSHELL(categoryString, markerName, \
                                          categoryPair, docShell)
 #  define AUTO_PROFILER_TEXT_MARKER_CAUSE(markerName, text, categoryPair, cause)
 #  define AUTO_PROFILER_TEXT_MARKER_DOCSHELL(markerName, text, categoryPair, \
                                              docShell)
 #  define AUTO_PROFILER_TEXT_MARKER_DOCSHELL_CAUSE( \
       markerName, text, categoryPair, docShell, cause)
 
 #else  // !MOZ_BASE_PROFILER
 
-#  include "js/ProfilingStack.h"
-#  include "js/RootingAPI.h"
-#  include "js/TypeDecls.h"
+#  include "BaseProfilingStack.h"
+
 #  include "mozilla/Assertions.h"
 #  include "mozilla/Atomics.h"
 #  include "mozilla/Attributes.h"
 #  include "mozilla/GuardObjects.h"
 #  include "mozilla/Maybe.h"
 #  include "mozilla/Sprintf.h"
 #  include "mozilla/ThreadLocal.h"
 #  include "mozilla/TimeStamp.h"
 #  include "mozilla/UniquePtr.h"
-#  include "nscore.h"
-#  include "nsID.h"
-#  include "nsString.h"
 
 #  include <stdint.h>
+#  include <string>
 
 class ProfilerBacktrace;
 class ProfilerMarkerPayload;
 class SpliceableJSONWriter;
-namespace mozilla {
-namespace net {
-struct TimingStruct;
-enum CacheDisposition : uint8_t;
-}  // namespace net
-}  // namespace mozilla
-class nsIURI;
 
 namespace mozilla {
 class MallocAllocPolicy;
 template <class T, size_t MinInlineCapacity, class AllocPolicy>
 class Vector;
 }  // namespace mozilla
 
 // Macros used by the AUTO_PROFILER_* macros below.
@@ -235,22 +217,22 @@ class RacyFeatures {
 
   PROFILER_FOR_EACH_FEATURE(NO_OVERLAP);
 
 #  undef NO_OVERLAP
 
   // We combine the active bit with the feature bits so they can be read or
   // written in a single atomic operation. Accesses to this atomic are not
   // recorded by web replay as they may occur at non-deterministic points.
-  static mozilla::Atomic<uint32_t, mozilla::MemoryOrdering::Relaxed,
-                         recordreplay::Behavior::DontPreserve>
+  MFBT_DATA static mozilla::Atomic<uint32_t, mozilla::MemoryOrdering::Relaxed,
+                                   recordreplay::Behavior::DontPreserve>
       sActiveAndFeatures;
 };
 
-bool IsThreadBeingProfiled();
+MFBT_API bool IsThreadBeingProfiled();
 
 }  // namespace detail
 }  // namespace profiler
 }  // namespace mozilla
 
 //---------------------------------------------------------------------------
 // Start and stop the profiler
 //---------------------------------------------------------------------------
@@ -273,24 +255,24 @@ static constexpr uint32_t PROFILER_DEFAU
 
 #  define PROFILER_DEFAULT_DURATION 20
 #  define PROFILER_DEFAULT_INTERVAL 1
 
 // Initialize the profiler. If MOZ_PROFILER_STARTUP is set the profiler will
 // also be started. This call must happen before any other profiler calls
 // (except profiler_start(), which will call profiler_init() if it hasn't
 // already run).
-void profiler_init(void* stackTop);
+MFBT_API void profiler_init(void* stackTop);
 
 #  define AUTO_PROFILER_INIT mozilla::AutoProfilerInit PROFILER_RAII
 
 // Clean up the profiler module, stopping it if required. This function may
 // also save a shutdown profile if requested. No profiler calls should happen
 // after this point and all profiling stack labels should have been popped.
-void profiler_shutdown();
+MFBT_API void profiler_shutdown();
 
 // Start the profiler -- initializing it first if necessary -- with the
 // selected options. Stops and restarts the profiler if it is already active.
 // After starting the profiler is "active". The samples will be recorded in a
 // circular buffer.
 //   "aCapacity" is the maximum number of entries in the profiler's circular
 //               buffer.
 //   "aInterval" the sampling interval, measured in millseconds.
@@ -298,49 +280,50 @@ void profiler_shutdown();
 //               platform/configuration are ignored.
 //   "aFilters" is the list of thread filters. Threads that do not match any
 //              of the filters are not profiled. A filter matches a thread if
 //              (a) the thread name contains the filter as a case-insensitive
 //                  substring, or
 //              (b) the filter is of the form "pid:<n>" where n is the process
 //                  id of the process that the thread is running in.
 //   "aDuration" is the duration of entries in the profiler's circular buffer.
-void profiler_start(
+MFBT_API void profiler_start(
     uint32_t aCapacity, double aInterval, uint32_t aFeatures,
     const char** aFilters, uint32_t aFilterCount,
     const mozilla::Maybe<double>& aDuration = mozilla::Nothing());
 
 // Stop the profiler and discard the profile without saving it. A no-op if the
 // profiler is inactive. After stopping the profiler is "inactive".
-void profiler_stop();
+MFBT_API void profiler_stop();
 
 // If the profiler is inactive, start it. If it's already active, restart it if
 // the requested settings differ from the current settings. Both the check and
 // the state change are performed while the profiler state is locked.
 // The only difference to profiler_start is that the current buffer contents are
 // not discarded if the profiler is already running with the requested settings.
-void profiler_ensure_started(
+MFBT_API void profiler_ensure_started(
     uint32_t aCapacity, double aInterval, uint32_t aFeatures,
     const char** aFilters, uint32_t aFilterCount,
     const mozilla::Maybe<double>& aDuration = mozilla::Nothing());
 
 //---------------------------------------------------------------------------
 // Control the profiler
 //---------------------------------------------------------------------------
 
 // Register/unregister threads with the profiler. Both functions operate the
 // same whether the profiler is active or inactive.
 #  define PROFILER_REGISTER_THREAD(name)         \
     do {                                         \
       char stackTop;                             \
       profiler_register_thread(name, &stackTop); \
     } while (0)
 #  define PROFILER_UNREGISTER_THREAD() profiler_unregister_thread()
-ProfilingStack* profiler_register_thread(const char* name, void* guessStackTop);
-void profiler_unregister_thread();
+MFBT_API ProfilingStack* profiler_register_thread(const char* name,
+                                                  void* guessStackTop);
+MFBT_API void profiler_unregister_thread();
 
 // Register pages with the profiler.
 //
 // The `page` means every new history entry for docShells.
 // DocShellId + HistoryID is a unique pair to identify these pages.
 // We also keep these pairs inside markers to associate with the pages.
 // That allows us to see which markers belong to a specific page and filter the
 // markers by a page.
@@ -350,68 +333,58 @@ void profiler_unregister_thread();
 // We do not register pages in these cases:
 // - If there is a history navigation through the back and forward buttons.
 // - If there is a navigation through `history.replaceState` or anchor scrolls.
 //
 //   "aDocShellId" is the ID of the docShell that page belongs to.
 //   "aHistoryId"  is the ID of the history entry on the given docShell.
 //   "aUrl"        is the URL of the page.
 //   "aIsSubFrame" is true if the page is a sub frame.
-void profiler_register_page(const nsID& aDocShellId, uint32_t aHistoryId,
-                            const nsCString& aUrl, bool aIsSubFrame);
+MFBT_API void profiler_register_page(const std::string& aDocShellId,
+                                     uint32_t aHistoryId,
+                                     const std::string& aUrl, bool aIsSubFrame);
 // Unregister pages with the profiler.
 //
 // Take a docShellId and unregister all the page entries that have the given ID.
-void profiler_unregister_pages(const nsID& aRegisteredDocShellId);
+MFBT_API void profiler_unregister_pages(
+    const std::string& aRegisteredDocShellId);
 
 // Remove all registered and unregistered pages in the profiler.
 void profiler_clear_all_pages();
 
 class BaseProfilerCount;
-void profiler_add_sampled_counter(BaseProfilerCount* aCounter);
-void profiler_remove_sampled_counter(BaseProfilerCount* aCounter);
+MFBT_API void profiler_add_sampled_counter(BaseProfilerCount* aCounter);
+MFBT_API void profiler_remove_sampled_counter(BaseProfilerCount* aCounter);
 
 // Register and unregister a thread within a scope.
 #  define AUTO_PROFILER_REGISTER_THREAD(name) \
     mozilla::AutoProfilerRegisterThread PROFILER_RAII(name)
 
 // Pause and resume the profiler. No-ops if the profiler is inactive. While
 // paused the profile will not take any samples and will not record any data
 // into its buffers. The profiler remains fully initialized in this state.
 // Timeline markers will still be stored. This feature will keep JavaScript
 // profiling enabled, thus allowing toggling the profiler without invalidating
 // the JIT.
-void profiler_pause();
-void profiler_resume();
+MFBT_API void profiler_pause();
+MFBT_API void profiler_resume();
 
 // These functions tell the profiler that a thread went to sleep so that we can
 // avoid sampling it while it's sleeping. Calling profiler_thread_sleep()
 // twice without an intervening profiler_thread_wake() is an error. All three
 // functions operate the same whether the profiler is active or inactive.
-void profiler_thread_sleep();
-void profiler_thread_wake();
+MFBT_API void profiler_thread_sleep();
+MFBT_API void profiler_thread_wake();
 
 // Mark a thread as asleep/awake within a scope.
 #  define AUTO_PROFILER_THREAD_SLEEP \
     mozilla::AutoProfilerThreadSleep PROFILER_RAII
 #  define AUTO_PROFILER_THREAD_WAKE \
     mozilla::AutoProfilerThreadWake PROFILER_RAII
 
-// Called by the JSRuntime's operation callback. This is used to start profiling
-// on auxiliary threads. Operates the same whether the profiler is active or
-// not.
-#  define PROFILER_JS_INTERRUPT_CALLBACK() profiler_js_interrupt_callback()
-void profiler_js_interrupt_callback();
-
-// Set and clear the current thread's JSContext.
-#  define PROFILER_SET_JS_CONTEXT(cx) profiler_set_js_context(cx)
-#  define PROFILER_CLEAR_JS_CONTEXT() profiler_clear_js_context()
-void profiler_set_js_context(JSContext* aCx);
-void profiler_clear_js_context();
-
 //---------------------------------------------------------------------------
 // Get information from the profiler
 //---------------------------------------------------------------------------
 
 // Is the profiler active? Note: the return value of this function can become
 // immediately out-of-date. E.g. the profile might be active but then
 // profiler_stop() is called immediately afterward. One common and reasonable
 // pattern of usage is the following:
@@ -434,50 +407,50 @@ inline bool profiler_is_active() {
 // Is the profiler active, and is the current thread being profiled?
 // (Same caveats and recommented usage as profiler_is_active().)
 inline bool profiler_thread_is_being_profiled() {
   return profiler_is_active() &&
          mozilla::profiler::detail::IsThreadBeingProfiled();
 }
 
 // Is the profiler active and paused? Returns false if the profiler is inactive.
-bool profiler_is_paused();
+MFBT_API bool profiler_is_paused();
 
 // Is the current thread sleeping?
-bool profiler_thread_is_sleeping();
+MFBT_API bool profiler_thread_is_sleeping();
 
 // Get all the features supported by the profiler that are accepted by
 // profiler_start(). The result is the same whether the profiler is active or
 // not.
-uint32_t profiler_get_available_features();
+MFBT_API uint32_t profiler_get_available_features();
 
 // Check if a profiler feature (specified via the ProfilerFeature type) is
 // active. Returns false if the profiler is inactive. Note: the return value
 // can become immediately out-of-date, much like the return value of
 // profiler_is_active().
-bool profiler_feature_active(uint32_t aFeature);
+MFBT_API bool profiler_feature_active(uint32_t aFeature);
 
 // Get the params used to start the profiler. Returns 0 and an empty vector
 // (via outparams) if the profile is inactive. It's possible that the features
 // returned may be slightly different to those requested due to required
 // adjustments.
-void profiler_get_start_params(
+MFBT_API void profiler_get_start_params(
     int* aEntrySize, mozilla::Maybe<double>* aDuration, double* aInterval,
     uint32_t* aFeatures,
     mozilla::Vector<const char*, 0, mozilla::MallocAllocPolicy>* aFilters);
 
 // The number of milliseconds since the process started. Operates the same
 // whether the profiler is active or inactive.
-double profiler_time();
+MFBT_API double profiler_time();
 
 // Get the current process's ID.
-int profiler_current_process_id();
+MFBT_API int profiler_current_process_id();
 
 // Get the current thread's ID.
-int profiler_current_thread_id();
+MFBT_API int profiler_current_thread_id();
 
 // An object of this class is passed to profiler_suspend_and_sample_thread().
 // For each stack frame, one of the Collect methods will be called.
 class ProfilerStackCollector {
  public:
   // Some collectors need to worry about possibly overwriting previous
   // generations of data. If that's not an issue, this can return Nothing,
   // which is the default behaviour.
@@ -494,56 +467,52 @@ class ProfilerStackCollector {
 
   // WARNING: The target thread is suspended when the Collect methods are
   // called. Do not try to allocate or acquire any locks, or you could
   // deadlock. The target thread will have resumed by the time this function
   // returns.
 
   virtual void CollectNativeLeafAddr(void* aAddr) = 0;
 
-  virtual void CollectJitReturnAddr(void* aAddr) = 0;
-
-  virtual void CollectWasmFrame(const char* aLabel) = 0;
-
   virtual void CollectProfilingStackFrame(
       const js::ProfilingStackFrame& aFrame) = 0;
 };
 
 // This method suspends the thread identified by aThreadId, samples its
 // profiling stack, JS stack, and (optionally) native stack, passing the
 // collected frames into aCollector. aFeatures dictates which compiler features
 // are used. |Privacy| and |Leaf| are the only relevant ones.
-void profiler_suspend_and_sample_thread(int aThreadId, uint32_t aFeatures,
-                                        ProfilerStackCollector& aCollector,
-                                        bool aSampleNative = true);
+MFBT_API void profiler_suspend_and_sample_thread(
+    int aThreadId, uint32_t aFeatures, ProfilerStackCollector& aCollector,
+    bool aSampleNative = true);
 
 struct ProfilerBacktraceDestructor {
-  void operator()(ProfilerBacktrace*);
+  MFBT_API void operator()(ProfilerBacktrace*);
 };
 
 using UniqueProfilerBacktrace =
     mozilla::UniquePtr<ProfilerBacktrace, ProfilerBacktraceDestructor>;
 
 // Immediately capture the current thread's call stack and return it. A no-op
 // if the profiler is inactive or in privacy mode.
-UniqueProfilerBacktrace profiler_get_backtrace();
+MFBT_API UniqueProfilerBacktrace profiler_get_backtrace();
 
 struct ProfilerBufferInfo {
   uint64_t mRangeStart;
   uint64_t mRangeEnd;
   uint32_t mEntryCount;
 };
 
 // Get information about the current buffer status.
 // Returns Nothing() if the profiler is inactive.
 //
 // This information may be useful to a user-interface displaying the current
 // status of the profiler, allowing the user to get a sense for how fast the
 // buffer is being written to, and how much data is visible.
-mozilla::Maybe<ProfilerBufferInfo> profiler_get_buffer_info();
+MFBT_API mozilla::Maybe<ProfilerBufferInfo> profiler_get_buffer_info();
 
 //---------------------------------------------------------------------------
 // Put profiling data into the profiler (labels and markers)
 //---------------------------------------------------------------------------
 
 // Insert an RAII object in this scope to enter a label stack frame. Any
 // samples collected in this scope will contain this label in their stack.
 // The label argument must be a static C string. It is usually of the
@@ -586,48 +555,30 @@ mozilla::Maybe<ProfilerBufferInfo> profi
 // AUTO_PROFILER_LABEL are sampled, no string copy needs to be made because the
 // profile buffer can just store the raw pointers to the literal strings.
 // Consequently, AUTO_PROFILER_LABEL frames take up considerably less space in
 // the profile buffer than AUTO_PROFILER_LABEL_DYNAMIC_* frames.
 #  define AUTO_PROFILER_LABEL_DYNAMIC_CSTR(label, categoryPair, cStr) \
     mozilla::AutoProfilerLabel PROFILER_RAII(                         \
         label, cStr, JS::ProfilingCategoryPair::categoryPair)
 
-// Similar to AUTO_PROFILER_LABEL_DYNAMIC_CSTR, but takes an nsACString.
+// Similar to AUTO_PROFILER_LABEL_DYNAMIC_CSTR, but takes an std::string.
 //
 // Note: The use of the Maybe<>s ensures the scopes for the dynamic string and
 // the AutoProfilerLabel are appropriate, while also not incurring the runtime
 // cost of the string assignment unless the profiler is active. Therefore,
 // unlike AUTO_PROFILER_LABEL and AUTO_PROFILER_LABEL_DYNAMIC_CSTR, this macro
 // doesn't push/pop a label when the profiler is inactive.
-#  define AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING(label, categoryPair, nsCStr) \
-    mozilla::Maybe<nsAutoCString> autoCStr;                                  \
-    mozilla::Maybe<mozilla::AutoProfilerLabel> raiiObjectNsCString;          \
-    if (profiler_is_active()) {                                              \
-      autoCStr.emplace(nsCStr);                                              \
-      raiiObjectNsCString.emplace(label, autoCStr->get(),                    \
-                                  JS::ProfilingCategoryPair::categoryPair);  \
-    }
-
-// Similar to AUTO_PROFILER_LABEL_DYNAMIC_CSTR, but takes an nsString that is
-// is lossily converted to an ASCII string.
-//
-// Note: The use of the Maybe<>s ensures the scopes for the converted dynamic
-// string and the AutoProfilerLabel are appropriate, while also not incurring
-// the runtime cost of the string conversion unless the profiler is active.
-// Therefore, unlike AUTO_PROFILER_LABEL and AUTO_PROFILER_LABEL_DYNAMIC_CSTR,
-// this macro doesn't push/pop a label when the profiler is inactive.
-#  define AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING(label, categoryPair,   \
-                                                     nsStr)                 \
-    mozilla::Maybe<NS_LossyConvertUTF16toASCII> asciiStr;                   \
-    mozilla::Maybe<mozilla::AutoProfilerLabel> raiiObjectLossyNsString;     \
-    if (profiler_is_active()) {                                             \
-      asciiStr.emplace(nsStr);                                              \
-      raiiObjectLossyNsString.emplace(                                      \
-          label, asciiStr->get(), JS::ProfilingCategoryPair::categoryPair); \
+#  define AUTO_PROFILER_LABEL_DYNAMIC_STRING(label, categoryPair, str)   \
+    mozilla::Maybe<std::string> autoStr;                                 \
+    mozilla::Maybe<mozilla::AutoProfilerLabel> raiiObjectString;         \
+    if (profiler_is_active()) {                                          \
+      autoStr.emplace(str);                                              \
+      raiiObjectString.emplace(label, autoStr->c_str(),                  \
+                               JS::ProfilingCategoryPair::categoryPair); \
     }
 
 // Similar to AUTO_PROFILER_LABEL, but accepting a JSContext* parameter, and a
 // no-op if the profiler is disabled.
 // Used to annotate functions for which overhead in the range of nanoseconds is
 // noticeable. It avoids overhead from the TLS lookup because it can get the
 // ProfilingStack from the JS context, and avoids almost all overhead in the
 // case where the profiler is disabled.
@@ -650,52 +601,38 @@ mozilla::Maybe<ProfilerBufferInfo> profi
 // on the label stack, markers will always be recorded in the profile buffer.
 // aMarkerName is copied, so the caller does not need to ensure it lives for a
 // certain length of time. A no-op if the profiler is inactive or in privacy
 // mode.
 
 #  define PROFILER_ADD_MARKER(markerName, categoryPair) \
     profiler_add_marker(markerName, JS::ProfilingCategoryPair::categoryPair)
 
-void profiler_add_marker(const char* aMarkerName,
-                         JS::ProfilingCategoryPair aCategoryPair);
-void profiler_add_marker(const char* aMarkerName,
-                         JS::ProfilingCategoryPair aCategoryPair,
-                         mozilla::UniquePtr<ProfilerMarkerPayload> aPayload);
-void profiler_add_js_marker(const char* aMarkerName);
+MFBT_API void profiler_add_marker(const char* aMarkerName,
+                                  JS::ProfilingCategoryPair aCategoryPair);
+MFBT_API void profiler_add_marker(
+    const char* aMarkerName, JS::ProfilingCategoryPair aCategoryPair,
+    mozilla::UniquePtr<ProfilerMarkerPayload> aPayload);
+MFBT_API void profiler_add_js_marker(const char* aMarkerName);
 
 // Insert a marker in the profile timeline for a specified thread.
-void profiler_add_marker_for_thread(
+MFBT_API void profiler_add_marker_for_thread(
     int aThreadId, JS::ProfilingCategoryPair aCategoryPair,
     const char* aMarkerName,
     mozilla::UniquePtr<ProfilerMarkerPayload> aPayload);
 
-enum class NetworkLoadType { LOAD_START, LOAD_STOP, LOAD_REDIRECT };
-
-#  define PROFILER_ADD_NETWORK_MARKER(uri, pri, channel, type, start, end,  \
-                                      count, cache, timings, redirect)      \
-    profiler_add_network_marker(uri, pri, channel, type, start, end, count, \
-                                cache, timings, redirect)
-
-void profiler_add_network_marker(
-    nsIURI* aURI, int32_t aPriority, uint64_t aChannelId, NetworkLoadType aType,
-    mozilla::TimeStamp aStart, mozilla::TimeStamp aEnd, int64_t aCount,
-    mozilla::net::CacheDisposition aCacheDisposition,
-    const mozilla::net::TimingStruct* aTimings = nullptr,
-    nsIURI* aRedirectURI = nullptr);
-
 enum TracingKind {
   TRACING_EVENT,
   TRACING_INTERVAL_START,
   TRACING_INTERVAL_END,
 };
 
 // Helper macro to retrieve DocShellId and DocShellHistoryId from docShell
 #  define DECLARE_DOCSHELL_AND_HISTORY_ID(docShell)      \
-    mozilla::Maybe<nsID> docShellId;                     \
+    mozilla::Maybe<std::string> docShellId;              \
     mozilla::Maybe<uint32_t> docShellHistoryId;          \
     if (docShell) {                                      \
       docShellId = mozilla::Some(docShell->HistoryID()); \
       uint32_t id;                                       \
       nsresult rv = docShell->GetOSHEId(&id);            \
       if (NS_SUCCEEDED(rv)) {                            \
         docShellHistoryId = mozilla::Some(id);           \
       } else {                                           \
@@ -714,26 +651,26 @@ enum TracingKind {
                      JS::ProfilingCategoryPair::categoryPair, kind)
 #  define PROFILER_TRACING_DOCSHELL(categoryString, markerName, categoryPair, \
                                     kind, docShell)                           \
     DECLARE_DOCSHELL_AND_HISTORY_ID(docShell);                                \
     profiler_tracing(categoryString, markerName,                              \
                      JS::ProfilingCategoryPair::categoryPair, kind,           \
                      docShellId, docShellHistoryId)
 
-void profiler_tracing(
+MFBT_API void profiler_tracing(
     const char* aCategoryString, const char* aMarkerName,
     JS::ProfilingCategoryPair aCategoryPair, TracingKind aKind,
-    const mozilla::Maybe<nsID>& aDocShellId = mozilla::Nothing(),
+    const mozilla::Maybe<std::string>& aDocShellId = mozilla::Nothing(),
     const mozilla::Maybe<uint32_t>& aDocShellHistoryId = mozilla::Nothing());
-void profiler_tracing(
+MFBT_API void profiler_tracing(
     const char* aCategoryString, const char* aMarkerName,
     JS::ProfilingCategoryPair aCategoryPair, TracingKind aKind,
     UniqueProfilerBacktrace aCause,
-    const mozilla::Maybe<nsID>& aDocShellId = mozilla::Nothing(),
+    const mozilla::Maybe<std::string>& aDocShellId = mozilla::Nothing(),
     const mozilla::Maybe<uint32_t>& aDocShellHistoryId = mozilla::Nothing());
 
 // Adds a START/END pair of tracing markers.
 #  define AUTO_PROFILER_TRACING(categoryString, markerName, categoryPair)    \
     mozilla::AutoProfilerTracing PROFILER_RAII(                              \
         categoryString, markerName, JS::ProfilingCategoryPair::categoryPair, \
         mozilla::Nothing(), mozilla::Nothing())
 #  define AUTO_PROFILER_TRACING_DOCSHELL(categoryString, markerName,         \
@@ -744,29 +681,29 @@ void profiler_tracing(
         docShellId, docShellHistoryId)
 
 // Add a text marker. Text markers are similar to tracing markers, with the
 // difference that text markers have their "text" separate from the marker name;
 // multiple text markers with the same name can have different text, and these
 // markers will still be displayed in the same "row" in the UI.
 // Another difference is that text markers combine the start and end markers
 // into one marker.
-void profiler_add_text_marker(
-    const char* aMarkerName, const nsACString& aText,
+MFBT_API void profiler_add_text_marker(
+    const char* aMarkerName, const std::string& aText,
     JS::ProfilingCategoryPair aCategoryPair,
     const mozilla::TimeStamp& aStartTime, const mozilla::TimeStamp& aEndTime,
-    const mozilla::Maybe<nsID>& aDocShellId = mozilla::Nothing(),
+    const mozilla::Maybe<std::string>& aDocShellId = mozilla::Nothing(),
     const mozilla::Maybe<uint32_t>& aDocShellHistoryId = mozilla::Nothing(),
     UniqueProfilerBacktrace aCause = nullptr);
 
 class MOZ_RAII AutoProfilerTextMarker {
  public:
-  AutoProfilerTextMarker(const char* aMarkerName, const nsACString& aText,
+  AutoProfilerTextMarker(const char* aMarkerName, const std::string& aText,
                          JS::ProfilingCategoryPair aCategoryPair,
-                         const mozilla::Maybe<nsID>& aDocShellId,
+                         const mozilla::Maybe<std::string>& aDocShellId,
                          const mozilla::Maybe<uint32_t>& aDocShellHistoryId,
                          UniqueProfilerBacktrace&& aCause =
                              nullptr MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
       : mMarkerName(aMarkerName),
         mText(aText),
         mCategoryPair(aCategoryPair),
         mStartTime(mozilla::TimeStamp::Now()),
         mCause(std::move(aCause)),
@@ -779,21 +716,21 @@ class MOZ_RAII AutoProfilerTextMarker {
     profiler_add_text_marker(mMarkerName, mText, mCategoryPair, mStartTime,
                              mozilla::TimeStamp::Now(), mDocShellId,
                              mDocShellHistoryId, std::move(mCause));
   }
 
  protected:
   MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
   const char* mMarkerName;
-  nsCString mText;
+  std::string mText;
   const JS::ProfilingCategoryPair mCategoryPair;
   mozilla::TimeStamp mStartTime;
   UniqueProfilerBacktrace mCause;
-  const mozilla::Maybe<nsID> mDocShellId;
+  const mozilla::Maybe<std::string> mDocShellId;
   const mozilla::Maybe<uint32_t> mDocShellHistoryId;
 };
 
 #  define AUTO_PROFILER_TEXT_MARKER_CAUSE(markerName, text, categoryPair, \
                                           cause)                          \
     AutoProfilerTextMarker PROFILER_RAII(                                 \
         markerName, text, JS::ProfilingCategoryPair::categoryPair,        \
         mozilla::Nothing(), mozilla::Nothing(), cause)
@@ -812,40 +749,34 @@ class MOZ_RAII AutoProfilerTextMarker {
         markerName, text, JS::ProfilingCategoryPair::categoryPair, docShellId, \
         docShellHistoryId, cause)
 
 //---------------------------------------------------------------------------
 // Output profiles
 //---------------------------------------------------------------------------
 
 // Set a user-friendly process name, used in JSON stream.
-void profiler_set_process_name(const nsACString& aProcessName);
+MFBT_API void profiler_set_process_name(const std::string& aProcessName);
 
 // Get the profile encoded as a JSON string. A no-op (returning nullptr) if the
 // profiler is inactive.
 // 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);
+MFBT_API 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,
-                                           bool aIsShuttingDown = false);
+MFBT_API bool profiler_stream_json_for_this_process(
+    SpliceableJSONWriter& aWriter, double aSinceTime = 0,
+    bool aIsShuttingDown = false);
 
 // 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
-// http://llvm.org/bugs/show_bug.cgi?id=22211).
-extern "C" {
-void profiler_save_profile_to_file(const char* aFilename);
-}
+MFBT_API void profiler_save_profile_to_file(const char* aFilename);
 
 //---------------------------------------------------------------------------
 // RAII classes
 //---------------------------------------------------------------------------
 
 namespace mozilla {
 
 class MOZ_RAII AutoProfilerInit {
@@ -925,29 +856,17 @@ class MOZ_RAII AutoProfilerLabel {
  public:
   // This is the AUTO_PROFILER_LABEL and AUTO_PROFILER_LABEL_DYNAMIC variant.
   AutoProfilerLabel(const char* aLabel, const char* aDynamicString,
                     JS::ProfilingCategoryPair aCategoryPair,
                     uint32_t aFlags = 0 MOZ_GUARD_OBJECT_NOTIFIER_PARAM) {
     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
 
     // Get the ProfilingStack from TLS.
-    Push(sProfilingStack.get(), aLabel, aDynamicString, aCategoryPair, aFlags);
-  }
-
-  // This is the AUTO_PROFILER_LABEL_FAST variant. It retrieves the
-  // ProfilingStack from the JSContext and does nothing if the profiler is
-  // inactive.
-  AutoProfilerLabel(JSContext* aJSContext, const char* aLabel,
-                    const char* aDynamicString,
-                    JS::ProfilingCategoryPair aCategoryPair,
-                    uint32_t aFlags MOZ_GUARD_OBJECT_NOTIFIER_PARAM) {
-    MOZ_GUARD_OBJECT_NOTIFIER_INIT;
-    Push(js::GetContextProfilingStackIfEnabled(aJSContext), aLabel,
-         aDynamicString, aCategoryPair, aFlags);
+    Push(GetProfilingStack(), aLabel, aDynamicString, aCategoryPair, aFlags);
   }
 
   void Push(ProfilingStack* aProfilingStack, const char* aLabel,
             const char* aDynamicString, JS::ProfilingCategoryPair aCategoryPair,
             uint32_t aFlags = 0) {
     // This function runs both on and off the main thread.
 
     mProfilingStack = aProfilingStack;
@@ -960,49 +879,51 @@ class MOZ_RAII AutoProfilerLabel {
   ~AutoProfilerLabel() {
     // This function runs both on and off the main thread.
 
     if (mProfilingStack) {
       mProfilingStack->pop();
     }
   }
 
+  MFBT_API static ProfilingStack* GetProfilingStack();
+
  private:
   MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 
   // We save a ProfilingStack pointer in the ctor so we don't have to redo the
   // TLS lookup in the dtor.
   ProfilingStack* mProfilingStack;
 
  public:
   // See the comment on the definition in platform.cpp for details about this.
   static MOZ_THREAD_LOCAL(ProfilingStack*) sProfilingStack;
 };
 
 class MOZ_RAII AutoProfilerTracing {
  public:
   AutoProfilerTracing(const char* aCategoryString, const char* aMarkerName,
                       JS::ProfilingCategoryPair aCategoryPair,
-                      const mozilla::Maybe<nsID>& aDocShellId,
+                      const mozilla::Maybe<std::string>& aDocShellId,
                       const mozilla::Maybe<uint32_t>& aDocShellHistoryId
                           MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
       : mCategoryString(aCategoryString),
         mMarkerName(aMarkerName),
         mCategoryPair(aCategoryPair),
         mDocShellId(aDocShellId),
         mDocShellHistoryId(aDocShellHistoryId) {
     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     profiler_tracing(mCategoryString, mMarkerName, aCategoryPair,
                      TRACING_INTERVAL_START, mDocShellId, mDocShellHistoryId);
   }
 
   AutoProfilerTracing(const char* aCategoryString, const char* aMarkerName,
                       JS::ProfilingCategoryPair aCategoryPair,
                       UniqueProfilerBacktrace aBacktrace,
-                      const mozilla::Maybe<nsID>& aDocShellId,
+                      const mozilla::Maybe<std::string>& aDocShellId,
                       const mozilla::Maybe<uint32_t>& aDocShellHistoryId
                           MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
       : mCategoryString(aCategoryString),
         mMarkerName(aMarkerName),
         mCategoryPair(aCategoryPair),
         mDocShellId(aDocShellId),
         mDocShellHistoryId(aDocShellHistoryId) {
     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
@@ -1016,25 +937,25 @@ class MOZ_RAII AutoProfilerTracing {
                      TRACING_INTERVAL_END, mDocShellId, mDocShellHistoryId);
   }
 
  protected:
   MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
   const char* mCategoryString;
   const char* mMarkerName;
   const JS::ProfilingCategoryPair mCategoryPair;
-  const mozilla::Maybe<nsID> mDocShellId;
+  const mozilla::Maybe<std::string> mDocShellId;
   const mozilla::Maybe<uint32_t> mDocShellHistoryId;
 };
 
 // Get the MOZ_PROFILER_STARTUP* environment variables that should be
 // supplied to a child process that is about to be launched, in order
 // to make that child process start with the same profiler settings as
 // in the current process.  The given function is invoked once for
 // each variable to be set.
-void GetProfilerEnvVarsForChildProcess(
+MFBT_API void GetProfilerEnvVarsForChildProcess(
     std::function<void(const char* key, const char* value)>&& aSetEnv);
 
 }  // namespace mozilla
 
 #endif  // !MOZ_BASE_PROFILER
 
-#endif  // GeckoProfiler_h
+#endif  // BaseProfiler_h
--- a/mozglue/baseprofiler/public/BaseProfilerCounts.h
+++ b/mozglue/baseprofiler/public/BaseProfilerCounts.h
@@ -1,33 +1,33 @@
 /* -*- 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/. */
 
-#ifndef ProfilerCounts_h
-#define ProfilerCounts_h
+#ifndef BaseProfilerCounts_h
+#define BaseProfilerCounts_h
 
 #ifndef MOZ_BASE_PROFILER
 
 #  define PROFILER_DEFINE_COUNT_TOTAL(label, category, description)
 #  define PROFILER_DEFINE_COUNT(label, category, description)
 #  define PROFILER_DEFINE_STATIC_COUNT_TOTAL(label, category, description)
 #  define AUTO_PROFILER_TOTAL(label, count)
 #  define AUTO_PROFILER_COUNT(label)
 #  define AUTO_PROFILER_STATIC_COUNT(label, count)
 
 #else
 
 #  include "mozilla/Atomics.h"
 
 class BaseProfilerCount;
-void profiler_add_sampled_counter(BaseProfilerCount* aCounter);
-void profiler_remove_sampled_counter(BaseProfilerCount* aCounter);
+MFBT_API void profiler_add_sampled_counter(BaseProfilerCount* aCounter);
+MFBT_API void profiler_remove_sampled_counter(BaseProfilerCount* aCounter);
 
 typedef mozilla::Atomic<int64_t, mozilla::MemoryOrdering::Relaxed>
     ProfilerAtomicSigned;
 typedef mozilla::Atomic<uint64_t, mozilla::MemoryOrdering::Relaxed>
     ProfilerAtomicUnsigned;
 
 // Counter support
 // There are two types of counters:
@@ -263,9 +263,9 @@ class ProfilerCounterTotal final : publi
         AutoCount_##label.reset(new BaseProfilerCount(                      \
             #label, &profiler_count_##label, &profiler_number_##label,      \
             profiler_category_##label, profiler_description_##label));      \
       }                                                                     \
     } while (0)
 
 #endif  // !MOZ_BASE_PROFILER
 
-#endif  // ProfilerCounts_h
+#endif  // BaseProfilerCounts_h
--- a/mozglue/baseprofiler/public/BaseProfilerMarkerPayload.h
+++ b/mozglue/baseprofiler/public/BaseProfilerMarkerPayload.h
@@ -1,64 +1,51 @@
 /* -*- Mode: C++; tab-width: 8; 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/. */
 
-#ifndef ProfilerMarkerPayload_h
-#define ProfilerMarkerPayload_h
+#ifndef BaseProfilerMarkerPayload_h
+#define BaseProfilerMarkerPayload_h
 
 #include "BaseProfiler.h"
 
 #ifndef MOZ_BASE_PROFILER
 #  error Do not #include this header when MOZ_BASE_PROFILER is not #defined.
 #endif
 
 #include "mozilla/Attributes.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/UniquePtrExtensions.h"
-#include "mozilla/net/TimingStruct.h"
-
-#include "nsString.h"
-
-#include "js/Utility.h"
-#include "gfxASurface.h"
-#include "mozilla/ServoTraversalStatistics.h"
-
-namespace mozilla {
-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 {
  public:
   explicit ProfilerMarkerPayload(
-      const mozilla::Maybe<nsID>& aDocShellId = mozilla::Nothing(),
+      const mozilla::Maybe<std::string>& aDocShellId = mozilla::Nothing(),
       const mozilla::Maybe<uint32_t>& aDocShellHistoryId = mozilla::Nothing(),
       UniqueProfilerBacktrace aStack = nullptr)
       : mStack(std::move(aStack)),
         mDocShellId(aDocShellId),
         mDocShellHistoryId(aDocShellHistoryId) {}
 
   ProfilerMarkerPayload(
       const mozilla::TimeStamp& aStartTime, const mozilla::TimeStamp& aEndTime,
-      const mozilla::Maybe<nsID>& aDocShellId = mozilla::Nothing(),
+      const mozilla::Maybe<std::string>& aDocShellId = mozilla::Nothing(),
       const mozilla::Maybe<uint32_t>& aDocShellHistoryId = mozilla::Nothing(),
       UniqueProfilerBacktrace aStack = nullptr)
       : mStartTime(aStartTime),
         mEndTime(aEndTime),
         mStack(std::move(aStack)),
         mDocShellId(aDocShellId),
         mDocShellHistoryId(aDocShellHistoryId) {}
 
@@ -66,52 +53,54 @@ class ProfilerMarkerPayload {
 
   virtual void StreamPayload(SpliceableJSONWriter& aWriter,
                              const mozilla::TimeStamp& aProcessStartTime,
                              UniqueStacks& aUniqueStacks) = 0;
 
   mozilla::TimeStamp GetStartTime() const { return mStartTime; }
 
  protected:
-  void StreamType(const char* aMarkerType, SpliceableJSONWriter& aWriter);
-  void StreamCommonProps(const char* aMarkerType, SpliceableJSONWriter& aWriter,
-                         const mozilla::TimeStamp& aProcessStartTime,
-                         UniqueStacks& aUniqueStacks);
+  MFBT_API void StreamType(const char* aMarkerType,
+                           SpliceableJSONWriter& aWriter);
+  MFBT_API void StreamCommonProps(const char* aMarkerType,
+                                  SpliceableJSONWriter& aWriter,
+                                  const mozilla::TimeStamp& aProcessStartTime,
+                                  UniqueStacks& aUniqueStacks);
 
   void SetStack(UniqueProfilerBacktrace aStack) { mStack = std::move(aStack); }
 
   void SetDocShellHistoryId(
       const mozilla::Maybe<uint32_t>& aDocShellHistoryId) {
     mDocShellHistoryId = aDocShellHistoryId;
   }
 
-  void SetDocShellId(const mozilla::Maybe<nsID>& aDocShellId) {
+  void SetDocShellId(const mozilla::Maybe<std::string>& aDocShellId) {
     mDocShellId = aDocShellId;
   }
 
  private:
   mozilla::TimeStamp mStartTime;
   mozilla::TimeStamp mEndTime;
   UniqueProfilerBacktrace mStack;
-  mozilla::Maybe<nsID> mDocShellId;
+  mozilla::Maybe<std::string> mDocShellId;
   mozilla::Maybe<uint32_t> mDocShellHistoryId;
 };
 
 #define DECL_STREAM_PAYLOAD                                               \
   virtual void StreamPayload(SpliceableJSONWriter& aWriter,               \
                              const mozilla::TimeStamp& aProcessStartTime, \
                              UniqueStacks& aUniqueStacks) override;
 
 // TODO: Increase the coverage of tracing markers that include DocShell
 // information
 class TracingMarkerPayload : public ProfilerMarkerPayload {
  public:
   TracingMarkerPayload(
       const char* aCategory, TracingKind aKind,
-      const mozilla::Maybe<nsID>& aDocShellId = mozilla::Nothing(),
+      const mozilla::Maybe<std::string>& aDocShellId = mozilla::Nothing(),
       const mozilla::Maybe<uint32_t>& aDocShellHistoryId = mozilla::Nothing(),
       UniqueProfilerBacktrace aCause = nullptr)
       : mCategory(aCategory), mKind(aKind) {
     if (aCause) {
       SetStack(std::move(aCause));
     }
     SetDocShellId(aDocShellId);
     SetDocShellHistoryId(aDocShellHistoryId);
@@ -142,280 +131,113 @@ class FileIOMarkerPayload : public Profi
   DECL_STREAM_PAYLOAD
 
  private:
   const char* mSource;
   mozilla::UniqueFreePtr<char> mOperation;
   mozilla::UniqueFreePtr<char> mFilename;
 };
 
-class DOMEventMarkerPayload : public TracingMarkerPayload {
- public:
-  DOMEventMarkerPayload(const nsAString& aEventType,
-                        const mozilla::TimeStamp& aTimeStamp,
-                        const char* aCategory, TracingKind aKind,
-                        const mozilla::Maybe<nsID>& aDocShellId,
-                        const mozilla::Maybe<uint32_t>& aDocShellHistoryId)
-      : TracingMarkerPayload(aCategory, aKind, aDocShellId, aDocShellHistoryId),
-        mTimeStamp(aTimeStamp),
-        mEventType(aEventType) {}
-
-  DECL_STREAM_PAYLOAD
-
- private:
-  mozilla::TimeStamp mTimeStamp;
-  nsString mEventType;
-};
-
 class UserTimingMarkerPayload : public ProfilerMarkerPayload {
  public:
-  UserTimingMarkerPayload(const nsAString& aName,
+  UserTimingMarkerPayload(const std::string& aName,
                           const mozilla::TimeStamp& aStartTime,
-                          const mozilla::Maybe<nsID>& aDocShellId,
+                          const mozilla::Maybe<std::string>& aDocShellId,
                           const mozilla::Maybe<uint32_t>& aDocShellHistoryId)
       : ProfilerMarkerPayload(aStartTime, aStartTime, aDocShellId,
                               aDocShellHistoryId),
         mEntryType("mark"),
         mName(aName) {}
 
-  UserTimingMarkerPayload(const nsAString& aName,
-                          const mozilla::Maybe<nsString>& aStartMark,
-                          const mozilla::Maybe<nsString>& aEndMark,
+  UserTimingMarkerPayload(const std::string& aName,
+                          const mozilla::Maybe<std::string>& aStartMark,
+                          const mozilla::Maybe<std::string>& aEndMark,
                           const mozilla::TimeStamp& aStartTime,
                           const mozilla::TimeStamp& aEndTime,
-                          const mozilla::Maybe<nsID>& aDocShellId,
+                          const mozilla::Maybe<std::string>& aDocShellId,
                           const mozilla::Maybe<uint32_t>& aDocShellHistoryId)
       : ProfilerMarkerPayload(aStartTime, aEndTime, aDocShellId,
                               aDocShellHistoryId),
         mEntryType("measure"),
         mName(aName),
         mStartMark(aStartMark),
         mEndMark(aEndMark) {}
 
   DECL_STREAM_PAYLOAD
 
  private:
   // Either "mark" or "measure".
   const char* mEntryType;
-  nsString mName;
-  mozilla::Maybe<nsString> mStartMark;
-  mozilla::Maybe<nsString> mEndMark;
-};
-
-// Contains the translation applied to a 2d layer so we can track the layer
-// position at each frame.
-class LayerTranslationMarkerPayload : public ProfilerMarkerPayload {
- public:
-  LayerTranslationMarkerPayload(mozilla::layers::Layer* aLayer,
-                                mozilla::gfx::Point aPoint,
-                                mozilla::TimeStamp aStartTime)
-      : ProfilerMarkerPayload(aStartTime, aStartTime),
-        mLayer(aLayer),
-        mPoint(aPoint) {}
-
-  DECL_STREAM_PAYLOAD
-
- private:
-  mozilla::layers::Layer* mLayer;
-  mozilla::gfx::Point mPoint;
-};
-
-#include "Units.h"  // For ScreenIntPoint
-
-// Tracks when a vsync occurs according to the HardwareComposer.
-class VsyncMarkerPayload : public ProfilerMarkerPayload {
- public:
-  explicit VsyncMarkerPayload(mozilla::TimeStamp aVsyncTimestamp)
-      : ProfilerMarkerPayload(aVsyncTimestamp, aVsyncTimestamp) {}
-
-  DECL_STREAM_PAYLOAD
-};
-
-class NetworkMarkerPayload : public ProfilerMarkerPayload {
- public:
-  NetworkMarkerPayload(int64_t aID, const char* aURI, NetworkLoadType aType,
-                       const mozilla::TimeStamp& aStartTime,
-                       const mozilla::TimeStamp& aEndTime, int32_t aPri,
-                       int64_t aCount,
-                       mozilla::net::CacheDisposition aCacheDisposition,
-                       const mozilla::net::TimingStruct* aTimings = nullptr,
-                       const char* aRedirectURI = nullptr)
-      : ProfilerMarkerPayload(aStartTime, aEndTime, mozilla::Nothing()),
-        mID(aID),
-        mURI(aURI ? strdup(aURI) : nullptr),
-        mRedirectURI(aRedirectURI && (strlen(aRedirectURI) > 0)
-                         ? strdup(aRedirectURI)
-                         : nullptr),
-        mType(aType),
-        mPri(aPri),
-        mCount(aCount),
-        mCacheDisposition(aCacheDisposition) {
-    if (aTimings) {
-      mTimings = *aTimings;
-    }
-  }
-
-  DECL_STREAM_PAYLOAD
-
- private:
-  int64_t mID;
-  mozilla::UniqueFreePtr<char> mURI;
-  mozilla::UniqueFreePtr<char> mRedirectURI;
-  NetworkLoadType mType;
-  int32_t mPri;
-  int64_t mCount;
-  mozilla::net::TimingStruct mTimings;
-  mozilla::net::CacheDisposition mCacheDisposition;
-};
-
-class ScreenshotPayload : public ProfilerMarkerPayload {
- public:
-  explicit ScreenshotPayload(mozilla::TimeStamp aTimeStamp,
-                             nsCString&& aScreenshotDataURL,
-                             const mozilla::gfx::IntSize& aWindowSize,
-                             uintptr_t aWindowIdentifier)
-      : ProfilerMarkerPayload(aTimeStamp, mozilla::TimeStamp()),
-        mScreenshotDataURL(std::move(aScreenshotDataURL)),
-        mWindowSize(aWindowSize),
-        mWindowIdentifier(aWindowIdentifier) {}
-
-  DECL_STREAM_PAYLOAD
-
- private:
-  nsCString mScreenshotDataURL;
-  mozilla::gfx::IntSize mWindowSize;
-  uintptr_t mWindowIdentifier;
-};
-
-class GCSliceMarkerPayload : public ProfilerMarkerPayload {
- public:
-  GCSliceMarkerPayload(const mozilla::TimeStamp& aStartTime,
-                       const mozilla::TimeStamp& aEndTime,
-                       JS::UniqueChars&& aTimingJSON)
-      : ProfilerMarkerPayload(aStartTime, aEndTime),
-        mTimingJSON(std::move(aTimingJSON)) {}
-
-  DECL_STREAM_PAYLOAD
-
- private:
-  JS::UniqueChars mTimingJSON;
-};
-
-class GCMajorMarkerPayload : public ProfilerMarkerPayload {
- public:
-  GCMajorMarkerPayload(const mozilla::TimeStamp& aStartTime,
-                       const mozilla::TimeStamp& aEndTime,
-                       JS::UniqueChars&& aTimingJSON)
-      : ProfilerMarkerPayload(aStartTime, aEndTime),
-        mTimingJSON(std::move(aTimingJSON)) {}
-
-  DECL_STREAM_PAYLOAD
-
- private:
-  JS::UniqueChars mTimingJSON;
-};
-
-class GCMinorMarkerPayload : public ProfilerMarkerPayload {
- public:
-  GCMinorMarkerPayload(const mozilla::TimeStamp& aStartTime,
-                       const mozilla::TimeStamp& aEndTime,
-                       JS::UniqueChars&& aTimingData)
-      : ProfilerMarkerPayload(aStartTime, aEndTime),
-        mTimingData(std::move(aTimingData)) {}
-
-  DECL_STREAM_PAYLOAD
-
- private:
-  JS::UniqueChars mTimingData;
+  std::string mName;
+  mozilla::Maybe<std::string> mStartMark;
+  mozilla::Maybe<std::string> mEndMark;
 };
 
 class HangMarkerPayload : public ProfilerMarkerPayload {
  public:
   HangMarkerPayload(const mozilla::TimeStamp& aStartTime,
                     const mozilla::TimeStamp& aEndTime)
       : ProfilerMarkerPayload(aStartTime, aEndTime) {}
 
   DECL_STREAM_PAYLOAD
  private:
 };
 
-class StyleMarkerPayload : public ProfilerMarkerPayload {
- public:
-  StyleMarkerPayload(const mozilla::TimeStamp& aStartTime,
-                     const mozilla::TimeStamp& aEndTime,
-                     UniqueProfilerBacktrace aCause,
-                     const mozilla::ServoTraversalStatistics& aStats,
-                     const mozilla::Maybe<nsID>& aDocShellId,
-                     const mozilla::Maybe<uint32_t>& aDocShellHistoryId)
-      : ProfilerMarkerPayload(aStartTime, aEndTime, aDocShellId,
-                              aDocShellHistoryId),
-        mStats(aStats) {
-    if (aCause) {
-      SetStack(std::move(aCause));
-    }
-  }
-
-  DECL_STREAM_PAYLOAD
-
- private:
-  mozilla::ServoTraversalStatistics mStats;
-};
-
 class LongTaskMarkerPayload : public ProfilerMarkerPayload {
  public:
   LongTaskMarkerPayload(const mozilla::TimeStamp& aStartTime,
                         const mozilla::TimeStamp& aEndTime)
       : ProfilerMarkerPayload(aStartTime, aEndTime) {}
 
   DECL_STREAM_PAYLOAD
 };
 
 class TextMarkerPayload : public ProfilerMarkerPayload {
  public:
-  TextMarkerPayload(const nsACString& aText,
+  TextMarkerPayload(const std::string& aText,
                     const mozilla::TimeStamp& aStartTime)
       : ProfilerMarkerPayload(aStartTime, aStartTime), mText(aText) {}
 
-  TextMarkerPayload(const nsACString& aText,
+  TextMarkerPayload(const std::string& aText,
                     const mozilla::TimeStamp& aStartTime,
                     const mozilla::TimeStamp& aEndTime)
       : ProfilerMarkerPayload(aStartTime, aEndTime), mText(aText) {}
 
-  TextMarkerPayload(const nsACString& aText,
+  TextMarkerPayload(const std::string& aText,
                     const mozilla::TimeStamp& aStartTime,
-                    const mozilla::Maybe<nsID>& aDocShellId,
+                    const mozilla::Maybe<std::string>& aDocShellId,
                     const mozilla::Maybe<uint32_t>& aDocShellHistoryId)
       : ProfilerMarkerPayload(aStartTime, aStartTime, aDocShellId,
                               aDocShellHistoryId),
         mText(aText) {}
 
-  TextMarkerPayload(const nsACString& aText,
+  TextMarkerPayload(const std::string& aText,
                     const mozilla::TimeStamp& aStartTime,
                     const mozilla::TimeStamp& aEndTime,
-                    const mozilla::Maybe<nsID>& aDocShellId,
+                    const mozilla::Maybe<std::string>& aDocShellId,
                     const mozilla::Maybe<uint32_t>& aDocShellHistoryId,
                     UniqueProfilerBacktrace aCause = nullptr)
       : ProfilerMarkerPayload(aStartTime, aEndTime, aDocShellId,
                               aDocShellHistoryId, std::move(aCause)),
         mText(aText) {}
 
   DECL_STREAM_PAYLOAD
 
  private:
-  nsCString mText;
+  std::string mText;
 };
 
 class LogMarkerPayload : public ProfilerMarkerPayload {
  public:
   LogMarkerPayload(const char* aModule, const char* aText,
                    const mozilla::TimeStamp& aStartTime)
       : ProfilerMarkerPayload(aStartTime, aStartTime),
         mModule(aModule),
         mText(aText) {}
 
   DECL_STREAM_PAYLOAD
 
  private:
-  nsAutoCStringN<32> mModule;  // longest known LazyLogModule name is ~24
-  nsCString mText;
+  std::string mModule;  // longest known LazyLogModule name is ~24
+  std::string mText;
 };
 
-#endif  // ProfilerMarkerPayload_h
+#endif  // BaseProfilerMarkerPayload_h
--- a/mozglue/baseprofiler/public/BaseProfilerSharedLibraries.h
+++ b/mozglue/baseprofiler/public/BaseProfilerSharedLibraries.h
@@ -8,32 +8,28 @@
 #define BASE_PROFILER_SHARED_LIBRARIES_H_
 
 #include "BaseProfiler.h"
 
 #ifndef MOZ_BASE_PROFILER
 #  error Do not #include this header when MOZ_BASE_PROFILER is not #defined.
 #endif
 
-#include "nsNativeCharsetUtils.h"
-#include "nsString.h"
-#include <nsID.h>
-
 #include <algorithm>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string>
 #include <vector>
 
 class SharedLibrary {
  public:
   SharedLibrary(uintptr_t aStart, uintptr_t aEnd, uintptr_t aOffset,
-                const nsCString& aBreakpadId, const nsString& aModuleName,
-                const nsString& aModulePath, const nsString& aDebugName,
-                const nsString& aDebugPath, const nsCString& aVersion,
+                const std::string& aBreakpadId, const std::string& aModuleName,
+                const std::string& aModulePath, const std::string& aDebugName,
+                const std::string& aDebugPath, const std::string& aVersion,
                 const char* aArch)
       : mStart(aStart),
         mEnd(aEnd),
         mOffset(aOffset),
         mBreakpadId(aBreakpadId),
         mModuleName(aModuleName),
         mModulePath(aModulePath),
         mDebugName(aDebugName),
@@ -78,43 +74,36 @@ class SharedLibrary {
            (mDebugPath == other.mDebugPath) &&
            (mBreakpadId == other.mBreakpadId) && (mVersion == other.mVersion) &&
            (mArch == other.mArch);
   }
 
   uintptr_t GetStart() const { return mStart; }
   uintptr_t GetEnd() const { return mEnd; }
   uintptr_t GetOffset() const { return mOffset; }
-  const nsCString& GetBreakpadId() const { return mBreakpadId; }
-  const nsString& GetModuleName() const { return mModuleName; }
-  const nsString& GetModulePath() const { return mModulePath; }
-  const std::string GetNativeDebugPath() const {
-    nsAutoCString debugPathStr;
-
-    NS_CopyUnicodeToNative(mDebugPath, debugPathStr);
-
-    return debugPathStr.get();
-  }
-  const nsString& GetDebugName() const { return mDebugName; }
-  const nsString& GetDebugPath() const { return mDebugPath; }
-  const nsCString& GetVersion() const { return mVersion; }
+  const std::string& GetBreakpadId() const { return mBreakpadId; }
+  const std::string& GetModuleName() const { return mModuleName; }
+  const std::string& GetModulePath() const { return mModulePath; }
+  const std::string& GetDebugName() const { return mDebugName; }
+  const std::string& GetDebugPath() const { return mDebugPath; }
+  const std::string& GetVersion() const { return mVersion; }
   const std::string& GetArch() const { return mArch; }
 
  private:
   SharedLibrary() : mStart{0}, mEnd{0}, mOffset{0} {}
 
   uintptr_t mStart;
   uintptr_t mEnd;
   uintptr_t mOffset;
-  nsCString mBreakpadId;
-  nsString mModuleName;
-  nsString mModulePath;
-  nsString mDebugName;
-  nsString mDebugPath;
-  nsCString mVersion;
+  std::string mBreakpadId;
+  std::string mModuleName;
+  std::string mModulePath;
+  std::string mDebugName;
+  std::string mDebugPath;
+  std::string mVersion;
   std::string mArch;
 };
 
 static bool CompareAddresses(const SharedLibrary& first,
                              const SharedLibrary& second) {
   return first.GetStart() < second.GetStart();
 }
 
--- a/mozglue/baseprofiler/public/BaseProfilingCategory.h
+++ b/mozglue/baseprofiler/public/BaseProfilingCategory.h
@@ -1,24 +1,26 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * 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 js_ProfilingCategory_h
-#define js_ProfilingCategory_h
+#ifndef BaseProfilingCategory_h
+#define BaseProfilingCategory_h
 
 #include "BaseProfiler.h"
 
 #ifndef MOZ_BASE_PROFILER
 #  error Do not #include this header when MOZ_BASE_PROFILER is not #defined.
 #endif
 
-#include "jstypes.h"  // JS_FRIEND_API
+#include "mozilla/Types.h"
+
+#include <cstdint>
 
 // clang-format off
 
 // This higher-order macro lists all categories with their subcategories.
 //
 // PROFILING_CATEGORY_LIST(BEGIN_CATEGORY, SUBCATEGORY, END_CATEGORY)
 //   BEGIN_CATEGORY(name, labelAsString, colorAsString)
 //   SUBCATEGORY(category, name, labelAsString)
@@ -116,14 +118,14 @@ enum class ProfilingCategory : uint32_t 
 // clang-format on
 
 struct ProfilingCategoryPairInfo {
   ProfilingCategory mCategory;
   uint32_t mSubcategoryIndex;
   const char* mLabel;
 };
 
-JS_FRIEND_API const ProfilingCategoryPairInfo& GetProfilingCategoryPairInfo(
+MFBT_API const ProfilingCategoryPairInfo& GetBaseProfilingCategoryPairInfo(
     ProfilingCategoryPair aCategoryPair);
 
 }  // namespace JS
 
-#endif /* js_ProfilingCategory_h */
+#endif /* BaseProfilingCategory_h */
--- a/mozglue/baseprofiler/public/BaseProfilingStack.h
+++ b/mozglue/baseprofiler/public/BaseProfilingStack.h
@@ -1,45 +1,30 @@
 /* -*- Mode: C++; tab-width: 8; 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/. */
 
-#ifndef js_ProfilingStack_h
-#define js_ProfilingStack_h
+#ifndef BaseProfilingStack_h
+#define BaseProfilingStack_h
+
+#include "BaseProfilingCategory.h"
+
+#include "mozilla/Atomics.h"
 
 #include "BaseProfiler.h"
 
 #ifndef MOZ_BASE_PROFILER
 #  error Do not #include this header when MOZ_BASE_PROFILER is not #defined.
 #endif
 
 #include <algorithm>
 #include <stdint.h>
 
-#include "jstypes.h"
-
-#include "js/ProfilingCategory.h"
-#include "js/TypeDecls.h"
-#include "js/Utility.h"
-
-#ifdef JS_BROKEN_GCC_ATTRIBUTE_WARNING
-#  pragma GCC diagnostic push
-#  pragma GCC diagnostic ignored "-Wattributes"
-#endif  // JS_BROKEN_GCC_ATTRIBUTE_WARNING
-
-class JS_PUBLIC_API JSTracer;
-
-#ifdef JS_BROKEN_GCC_ATTRIBUTE_WARNING
-#  pragma GCC diagnostic pop
-#endif  // JS_BROKEN_GCC_ATTRIBUTE_WARNING
-
-class ProfilingStack;
-
 // This file defines the classes ProfilingStack and ProfilingStackFrame.
 // The ProfilingStack manages an array of ProfilingStackFrames.
 // It keeps track of the "label stack" and the JS interpreter stack.
 // The two stack types are interleaved.
 //
 // Usage:
 //
 //  ProfilingStack* profilingStack = ...;
@@ -163,18 +148,16 @@ class ProfilingStackFrame {
                   mozilla::recordreplay::Behavior::DontPreserve>
       pcOffsetIfJS_;
 
   // Bits 0...8 hold the Flags. Bits 9...31 hold the category pair.
   mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire,
                   mozilla::recordreplay::Behavior::DontPreserve>
       flagsAndCategoryPair_;
 
-  static int32_t pcToOffset(JSScript* aScript, jsbytecode* aPc);
-
  public:
   ProfilingStackFrame() = default;
   ProfilingStackFrame& operator=(const ProfilingStackFrame& other) {
     label_ = other.label();
     dynamicString_ = other.dynamicString();
     void* spScript = other.spOrScript;
     spOrScript = spScript;
     int32_t offsetIfJS = other.pcOffsetIfJS_;
@@ -265,17 +248,17 @@ class ProfilingStackFrame {
   }
 
   const char* label() const {
     uint32_t flagsAndCategoryPair = flagsAndCategoryPair_;
     if (flagsAndCategoryPair &
         uint32_t(Flags::LABEL_DETERMINED_BY_CATEGORY_PAIR)) {
       auto categoryPair = JS::ProfilingCategoryPair(
           flagsAndCategoryPair >> uint32_t(Flags::FLAGS_BITCOUNT));
-      return JS::GetProfilingCategoryPairInfo(categoryPair).mLabel;
+      return JS::GetBaseProfilingCategoryPairInfo(categoryPair).mLabel;
     }
     return label_;
   }
 
   const char* dynamicString() const { return dynamicString_; }
 
   void initLabelFrame(const char* aLabel, const char* aDynamicString, void* sp,
                       JS::ProfilingCategoryPair aCategoryPair,
@@ -297,21 +280,21 @@ class ProfilingStackFrame {
     // pcOffsetIfJS_ is not set and must not be used on sp marker frames.
     flagsAndCategoryPair_ = uint32_t(Flags::IS_SP_MARKER_FRAME) |
                             (uint32_t(JS::ProfilingCategoryPair::OTHER)
                              << uint32_t(Flags::FLAGS_BITCOUNT));
     MOZ_ASSERT(isSpMarkerFrame());
   }
 
   void initJsFrame(const char* aLabel, const char* aDynamicString,
-                   JSScript* aScript, jsbytecode* aPc) {
+                   void* /* JSScript* */ aScript, int32_t aOffset) {
     label_ = aLabel;
     dynamicString_ = aDynamicString;
     spOrScript = aScript;
-    pcOffsetIfJS_ = pcToOffset(aScript, aPc);
+    pcOffsetIfJS_ = aOffset;
     flagsAndCategoryPair_ =
         uint32_t(Flags::IS_JS_FRAME) | (uint32_t(JS::ProfilingCategoryPair::JS)
                                         << uint32_t(Flags::FLAGS_BITCOUNT));
     MOZ_ASSERT(isJsFrame());
   }
 
   uint32_t flags() const {
     return uint32_t(flagsAndCategoryPair_) & uint32_t(Flags::FLAGS_MASK);
@@ -322,57 +305,54 @@ class ProfilingStackFrame {
                                      uint32_t(Flags::FLAGS_BITCOUNT));
   }
 
   void* stackAddress() const {
     MOZ_ASSERT(!isJsFrame());
     return spOrScript;
   }
 
-  JS_PUBLIC_API JSScript* script() const;
-
   // Note that the pointer returned might be invalid.
-  JSScript* rawScript() const {
+  void* rawScript() const {
     MOZ_ASSERT(isJsFrame());
-    void* script = spOrScript;
-    return static_cast<JSScript*>(script);
+    return spOrScript;
+  }
+  void setRawScript(void* aScript) {
+    MOZ_ASSERT(isJsFrame());
+    spOrScript = aScript;
   }
 
-  // We can't know the layout of JSScript, so look in vm/GeckoProfiler.cpp.
-  JS_FRIEND_API jsbytecode* pc() const;
-  void setPC(jsbytecode* pc);
+  int32_t pcOffset() const {
+    MOZ_ASSERT(isJsFrame());
+    return pcOffsetIfJS_;
+  }
 
-  void trace(JSTracer* trc);
+  void setPCOffset(int32_t aOffset) {
+    MOZ_ASSERT(isJsFrame());
+    pcOffsetIfJS_ = aOffset;
+  }
 
   // The offset of a pc into a script's code can actually be 0, so to
   // signify a nullptr pc, use a -1 index. This is checked against in
   // pc() and setPC() to set/get the right pc.
   static const int32_t NullPCOffset = -1;
 };
 
-JS_FRIEND_API void SetContextProfilingStack(JSContext* cx,
-                                            ProfilingStack* profilingStack);
-
-// GetContextProfilingStack also exists, but it's defined in RootingAPI.h.
+}  // namespace js
 
-JS_FRIEND_API void EnableContextProfilingStack(JSContext* cx, bool enabled);
-
-JS_FRIEND_API void RegisterContextProfilingEventMarker(JSContext* cx,
-                                                       void (*fn)(const char*));
-
-}  // namespace js
+class ProfilingStack;
 
 namespace JS {
 
 typedef ProfilingStack* (*RegisterThreadCallback)(const char* threadName,
                                                   void* stackBase);
 
 typedef void (*UnregisterThreadCallback)();
 
-JS_FRIEND_API void SetProfilingThreadCallbacks(
+MFBT_API void SetProfilingThreadCallbacks(
     RegisterThreadCallback registerThread,
     UnregisterThreadCallback unregisterThread);
 
 }  // namespace JS
 
 // Each thread has its own ProfilingStack. That thread modifies the
 // ProfilingStack, pushing and popping elements as necessary.
 //
@@ -391,17 +371,17 @@ JS_FRIEND_API void SetProfilingThreadCal
 //
 // - When popping an old frame, the only operation is the decrementing of the
 //   stack pointer, which is obviously atomic.
 //
 class ProfilingStack final {
  public:
   ProfilingStack() : stackPointer(0) {}
 
-  ~ProfilingStack();
+  MFBT_API ~ProfilingStack();
 
   void pushLabelFrame(const char* label, const char* dynamicString, void* sp,
                       JS::ProfilingCategoryPair categoryPair,
                       uint32_t flags = 0) {
     // This thread is the only one that ever changes the value of
     // stackPointer.
     // Store the value of the atomic in a non-atomic local variable so that
     // the compiler won't generate two separate loads from the atomic for
@@ -433,26 +413,26 @@ class ProfilingStack final {
       ensureCapacitySlow();
     }
     frames[oldStackPointer].initSpMarkerFrame(sp);
 
     // This must happen at the end, see the comment in pushLabelFrame.
     stackPointer = oldStackPointer + 1;
   }
 
-  void pushJsFrame(const char* label, const char* dynamicString,
-                   JSScript* script, jsbytecode* pc) {
+  void pushJsOffsetFrame(const char* label, const char* dynamicString,
+                         void* script, int32_t offset) {
     // This thread is the only one that ever changes the value of
     // stackPointer. Only load the atomic once.
     uint32_t oldStackPointer = stackPointer;
 
     if (MOZ_UNLIKELY(oldStackPointer >= capacity)) {
       ensureCapacitySlow();
     }
-    frames[oldStackPointer].initJsFrame(label, dynamicString, script, pc);
+    frames[oldStackPointer].initJsFrame(label, dynamicString, script, offset);
 
     // This must happen at the end, see the comment in pushLabelFrame.
     stackPointer = stackPointer + 1;
   }
 
   void pop() {
     MOZ_ASSERT(stackPointer > 0);
     // Do the read and the write as two separate statements, in order to
@@ -465,17 +445,17 @@ class ProfilingStack final {
   }
 
   uint32_t stackSize() const { return stackPointer; }
   uint32_t stackCapacity() const { return capacity; }
 
  private:
   // Out of line path for expanding the buffer, since otherwise this would get
   // inlined in every DOM WebIDL call.
-  MOZ_COLD void ensureCapacitySlow();
+  MFBT_API MOZ_COLD void ensureCapacitySlow();
 
   // No copying.
   ProfilingStack(const ProfilingStack&) = delete;
   void operator=(const ProfilingStack&) = delete;
 
   // No moving either.
   ProfilingStack(ProfilingStack&&) = delete;
   void operator=(ProfilingStack&&) = delete;
@@ -520,17 +500,17 @@ class GeckoProfilerThread {
 
   ProfilingStack* profilingStack_;
 
   // Same as profilingStack_ if the profiler is currently active, otherwise
   // null.
   ProfilingStack* profilingStackIfEnabled_;
 
  public:
-  GeckoProfilerThread();
+  MFBT_API GeckoProfilerThread();
 
   uint32_t stackPointer() {
     MOZ_ASSERT(infraInstalled());
     return profilingStack_->stackPointer;
   }
   ProfilingStackFrame* stack() { return profilingStack_->frames; }
   ProfilingStack* getProfilingStack() { return profilingStack_; }
   ProfilingStack* getProfilingStackIfEnabled() {
@@ -539,31 +519,17 @@ class GeckoProfilerThread {
 
   /*
    * True if the profiler infrastructure is setup.  Should be true in builds
    * that include profiler support except during early startup or late
    * shutdown.  Unrelated to the presence of the Gecko Profiler addon.
    */
   bool infraInstalled() { return profilingStack_ != nullptr; }
 
-  void setProfilingStack(ProfilingStack* profilingStack, bool enabled);
+  MFBT_API void setProfilingStack(ProfilingStack* profilingStack, bool enabled);
   void enable(bool enable) {
     profilingStackIfEnabled_ = enable ? profilingStack_ : nullptr;
   }
-  void trace(JSTracer* trc);
-
-  /*
-   * Functions which are the actual instrumentation to track run information
-   *
-   *   - enter: a function has started to execute
-   *   - updatePC: updates the pc information about where a function
-   *               is currently executing
-   *   - exit: this function has ceased execution, and no further
-   *           entries/exits will be made
-   */
-  bool enter(JSContext* cx, JSScript* script);
-  void exit(JSContext* cx, JSScript* script);
-  inline void updatePC(JSContext* cx, JSScript* script, jsbytecode* pc);
 };
 
 }  // namespace js
 
-#endif /* js_ProfilingStack_h */
+#endif /* BaseProfilingStack_h */