Backed out 6 changesets (bug 1358074) for Assertion failure: NS_IsMainThread and valgrind failures
authorIris Hsiao <ihsiao@mozilla.com>
Mon, 24 Apr 2017 16:50:50 +0800
changeset 402721 265931fd5e5a0b3b7a4625fc517bfa18e86c2291
parent 402720 6efe7915f97b389c51b85bb2e1e45004f33ca680
child 402722 8bd40784fb5ba47389a8f6aa064a8f3ea590d48d
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1358074
milestone55.0a1
backs outc3f35f8a1f219f47437f63bb87e9308870a151d9
1d214f8ac8fdf99766b975ad6e9c20d82c61900b
3221b215b080881d3a31b4b6464e3a529bb4d5d4
adec21069065815d50cc16dba70bec4cd7cfefc8
9baa76979a717579ad43a9814d0fed9c73717b5a
8375b7a4be084a1be30a90c7a6df089f8b1682e0
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
Backed out 6 changesets (bug 1358074) for Assertion failure: NS_IsMainThread and valgrind failures Backed out changeset c3f35f8a1f21 (bug 1358074) Backed out changeset 1d214f8ac8fd (bug 1358074) Backed out changeset 3221b215b080 (bug 1358074) Backed out changeset adec21069065 (bug 1358074) Backed out changeset 9baa76979a71 (bug 1358074) Backed out changeset 8375b7a4be08 (bug 1358074)
tools/profiler/core/ThreadInfo.h
tools/profiler/core/platform-linux-android.cpp
tools/profiler/core/platform-macos.cpp
tools/profiler/core/platform-win32.cpp
tools/profiler/core/platform.cpp
tools/profiler/public/GeckoProfiler.h
--- a/tools/profiler/core/ThreadInfo.h
+++ b/tools/profiler/core/ThreadInfo.h
@@ -85,18 +85,18 @@ private:
   // into the final stream.
   mozilla::UniquePtr<char[]> mSavedStreamedSamples;
   mozilla::UniquePtr<char[]> mSavedStreamedMarkers;
   mozilla::Maybe<UniqueStacks> mUniqueStacks;
 
   // This is only used for the main thread.
   mozilla::Maybe<ThreadResponsiveness> mResponsiveness;
 
-  // When sampling, this holds the generation number and offset in PS::mBuffer
-  // of the most recent sample for this thread.
+  // When sampling, this holds the generation number and offset in
+  // ProfilerState::mBuffer of the most recent sample for this thread.
   ProfileBuffer::LastSample mLastSample;
 };
 
 void
 StreamSamplesAndMarkers(const char* aName, int aThreadId,
                         ProfileBuffer* aBuffer,
                         SpliceableJSONWriter& aWriter,
                         const mozilla::TimeStamp& aStartTime,
--- a/tools/profiler/core/platform-linux-android.cpp
+++ b/tools/profiler/core/platform-linux-android.cpp
@@ -274,17 +274,17 @@ ThreadEntry(void* aArg)
 {
   auto thread = static_cast<SamplerThread*>(aArg);
   prctl(PR_SET_NAME, "SamplerThread", 0, 0, 0);
   thread->mSamplerTid = gettid();
   thread->Run();
   return nullptr;
 }
 
-SamplerThread::SamplerThread(PSLockRef aLock, uint32_t aActivityGeneration,
+SamplerThread::SamplerThread(PS::LockRef aLock, uint32_t aActivityGeneration,
                              double aIntervalMilliseconds)
   : mActivityGeneration(aActivityGeneration)
   , mIntervalMicroseconds(
       std::max(1, int(floor(aIntervalMilliseconds * 1000 + 0.5))))
   , mMyPid(getpid())
   // We don't know what the sampler thread's ID will be until it runs, so set
   // mSamplerTid to a dummy value and fill it in for real in ThreadEntry().
   , mSamplerTid(-1)
@@ -338,30 +338,30 @@ SamplerThread::SamplerThread(PSLockRef a
 }
 
 SamplerThread::~SamplerThread()
 {
   pthread_join(mThread, nullptr);
 }
 
 void
-SamplerThread::Stop(PSLockRef aLock)
+SamplerThread::Stop(PS::LockRef aLock)
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
 
   // Restore old signal handler. This is global state so it's important that
   // we do it now, while gPSMutex is locked. It's safe to do this now even
   // though this SamplerThread is still alive, because the next time the main
   // loop of Run() iterates it won't get past the mActivityGeneration check,
   // and so won't send any signals.
   sigaction(SIGPROF, &mOldSigprofHandler, 0);
 }
 
 void
-SamplerThread::SuspendAndSampleAndResumeThread(PSLockRef aLock,
+SamplerThread::SuspendAndSampleAndResumeThread(PS::LockRef aLock,
                                                TickSample& aSample)
 {
   // Only one sampler thread can be sampling at once.  So we expect to have
   // complete control over |sSigHandlerCoordinator|.
   MOZ_ASSERT(!sSigHandlerCoordinator);
 
   int sampleeTid = aSample.mThreadId;
   MOZ_RELEASE_ASSERT(sampleeTid != mSamplerTid);
@@ -461,47 +461,47 @@ SamplerThread::SuspendAndSampleAndResume
 // In the parent, before the fork, record IsPaused, and then pause.
 static void
 paf_prepare()
 {
   // This function can run off the main thread.
 
   MOZ_RELEASE_ASSERT(gPS);
 
-  PSAutoLock lock(gPSMutex);
+  PS::AutoLock lock(gPSMutex);
 
   gPS->SetWasPaused(lock, gPS->IsPaused(lock));
   gPS->SetIsPaused(lock, true);
 }
 
 // In the parent, after the fork, return IsPaused to the pre-fork state.
 static void
 paf_parent()
 {
   // This function can run off the main thread.
 
   MOZ_RELEASE_ASSERT(gPS);
 
-  PSAutoLock lock(gPSMutex);
+  PS::AutoLock lock(gPSMutex);
 
   gPS->SetIsPaused(lock, gPS->WasPaused(lock));
   gPS->SetWasPaused(lock, false);
 }
 
 static void
-PlatformInit(PSLockRef aLock)
+PlatformInit(PS::LockRef aLock)
 {
   // Set up the fork handlers.
   pthread_atfork(paf_prepare, paf_parent, nullptr);
 }
 
 #else
 
 static void
-PlatformInit(PSLockRef aLock)
+PlatformInit(PS::LockRef aLock)
 {
 }
 
 #endif
 
 void
 TickSample::PopulateContext(ucontext_t* aContext)
 {
--- a/tools/profiler/core/platform-macos.cpp
+++ b/tools/profiler/core/platform-macos.cpp
@@ -96,17 +96,17 @@ static void*
 ThreadEntry(void* aArg)
 {
   auto thread = static_cast<SamplerThread*>(aArg);
   SetThreadName();
   thread->Run();
   return nullptr;
 }
 
-SamplerThread::SamplerThread(PSLockRef aLock, uint32_t aActivityGeneration,
+SamplerThread::SamplerThread(PS::LockRef aLock, uint32_t aActivityGeneration,
                              double aIntervalMilliseconds)
   : mActivityGeneration(aActivityGeneration)
   , mIntervalMicroseconds(
       std::max(1, int(floor(aIntervalMilliseconds * 1000 + 0.5))))
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
 
   pthread_attr_t* attr_ptr = nullptr;
@@ -116,23 +116,23 @@ SamplerThread::SamplerThread(PSLockRef a
 }
 
 SamplerThread::~SamplerThread()
 {
   pthread_join(mThread, nullptr);
 }
 
 void
-SamplerThread::Stop(PSLockRef aLock)
+SamplerThread::Stop(PS::LockRef aLock)
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
 }
 
 void
-SamplerThread::SuspendAndSampleAndResumeThread(PSLockRef aLock,
+SamplerThread::SuspendAndSampleAndResumeThread(PS::LockRef aLock,
                                                TickSample& aSample)
 {
   thread_act_t samplee_thread = aSample.mPlatformData->ProfiledThread();
 
   //----------------------------------------------------------------//
   // Suspend the samplee thread and get its context.
 
   // We're using thread_suspend on OS X because pthread_kill (which is what we
@@ -199,17 +199,17 @@ SamplerThread::SuspendAndSampleAndResume
   //
   // WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
 }
 
 // END SamplerThread target specifics
 ////////////////////////////////////////////////////////////////////////
 
 static void
-PlatformInit(PSLockRef aLock)
+PlatformInit(PS::LockRef aLock)
 {
 }
 
 void
 TickSample::PopulateContext(void* aContext)
 {
   MOZ_ASSERT(mIsSynchronous);
   MOZ_ASSERT(!aContext);
--- a/tools/profiler/core/platform-win32.cpp
+++ b/tools/profiler/core/platform-win32.cpp
@@ -93,17 +93,17 @@ static const HANDLE kNoThread = INVALID_
 static unsigned int __stdcall
 ThreadEntry(void* aArg)
 {
   auto thread = static_cast<SamplerThread*>(aArg);
   thread->Run();
   return 0;
 }
 
-SamplerThread::SamplerThread(PSLockRef aLock, uint32_t aActivityGeneration,
+SamplerThread::SamplerThread(PS::LockRef aLock, uint32_t aActivityGeneration,
                              double aIntervalMilliseconds)
     : mActivityGeneration(aActivityGeneration)
     , mIntervalMicroseconds(
         std::max(1, int(floor(aIntervalMilliseconds * 1000 + 0.5))))
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
 
   // By default we'll not adjust the timer resolution which tends to be
@@ -134,17 +134,17 @@ SamplerThread::~SamplerThread()
 
   // Close our own handle for the thread.
   if (mThread != kNoThread) {
     CloseHandle(mThread);
   }
 }
 
 void
-SamplerThread::Stop(PSLockRef aLock)
+SamplerThread::Stop(PS::LockRef aLock)
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
 
   // Disable any timer resolution changes we've made. Do it now while
   // gPSMutex is locked, i.e. before any other SamplerThread can be created
   // and call ::timeBeginPeriod().
   //
   // It's safe to do this now even though this SamplerThread is still alive,
@@ -152,17 +152,17 @@ SamplerThread::Stop(PSLockRef aLock)
   // the mActivityGeneration check, and so it won't make any more ::Sleep()
   // calls.
   if (mIntervalMicroseconds < 10 * 1000) {
     ::timeEndPeriod(mIntervalMicroseconds / 1000);
   }
 }
 
 void
-SamplerThread::SuspendAndSampleAndResumeThread(PSLockRef aLock,
+SamplerThread::SuspendAndSampleAndResumeThread(PS::LockRef aLock,
                                                TickSample& aSample)
 {
   HANDLE profiled_thread = aSample.mPlatformData->ProfiledThread();
   if (profiled_thread == nullptr)
     return;
 
   // Context used for sampling the register state of the profiled thread.
   CONTEXT context;
@@ -224,17 +224,17 @@ SamplerThread::SuspendAndSampleAndResume
   //
   // WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
 }
 
 // END SamplerThread target specifics
 ////////////////////////////////////////////////////////////////////////
 
 static void
-PlatformInit(PSLockRef aLock)
+PlatformInit(PS::LockRef aLock)
 {
 }
 
 void
 TickSample::PopulateContext(CONTEXT* aContext)
 {
   MOZ_ASSERT(mIsSynchronous);
   MOZ_ASSERT(aContext);
--- a/tools/profiler/core/platform.cpp
+++ b/tools/profiler/core/platform.cpp
@@ -105,43 +105,44 @@ public:
 };
 #endif
 
 class SamplerThread;
 
 // Per-thread state.
 MOZ_THREAD_LOCAL(PseudoStack *) tlsPseudoStack;
 
-class PSMutex : public mozilla::StaticMutex {};
-
-typedef mozilla::BaseAutoLock<PSMutex> PSAutoLock;
-
-// Only functions that take a PSLockRef arg can modify this class's fields.
-typedef const PSAutoLock& PSLockRef;
-
 // This class contains most of the profiler's global state. gPS is the single
 // instance. Most profile operations can't do anything useful when gPS is not
 // instantiated, so we release-assert its non-nullness in all such operations.
 //
 // Accesses to gPS are guarded by gPSMutex. Every getter and setter takes a
-// PSAutoLock reference as an argument as proof that the gPSMutex is currently
-// locked. This makes it clear when gPSMutex is locked and helps avoid
-// accidental unlocked accesses to global state. There are ways to circumvent
-// this mechanism, but please don't do so without *very* good reason and a
-// detailed explanation.
+// PS::AutoLock reference as an argument as proof that the gPSMutex is
+// currently locked. This makes it clear when gPSMutex is locked and helps
+// avoid accidental unlocked accesses to global state. There are ways to
+// circumvent this mechanism, but please don't do so without *very* good reason
+// and a detailed explanation.
 //
 // Other from the lock protection, this class is essentially a thin wrapper and
 // contains very little "smarts" itself.
 //
-class PS
+class ProfilerState
 {
 public:
+  // Shorter names for local use.
+  class Mutex : public mozilla::StaticMutex {};
+
+  typedef mozilla::BaseAutoLock<Mutex> AutoLock;
+
+  // Only functions that take a LockRef arg can modify this class's fields.
+  typedef const AutoLock& LockRef;
+
   typedef std::vector<ThreadInfo*> ThreadVector;
 
-  PS()
+  ProfilerState()
     : mEntries(0)
     , mInterval(0)
     , mFeatureDisplayListDump(false)
     , mFeatureGPU(false)
     , mFeatureJava(false)
     , mFeatureJS(false)
     , mFeatureLayersDump(false)
     , mFeatureLeaf(false)
@@ -149,41 +150,41 @@ public:
     , mFeatureMemory(false)
     , mFeaturePrivacy(false)
     , mFeatureRestyle(false)
     , mFeatureStackWalk(false)
     , mFeatureTaskTracer(false)
     , mFeatureThreads(false)
     , mBuffer(nullptr)
     , mIsPaused(false)
-#if defined(GP_OS_linux)
+#if defined(GP_OS_linux) || defined(GP_OS_android)
     , mWasPaused(false)
 #endif
     , mSamplerThread(nullptr)
 #ifdef USE_LUL_STACKWALK
     , mLUL(nullptr)
 #endif
     , mInterposeObserver(nullptr)
     , mFrameNumber(0)
     , mLatestRecordedFrameNumber(0)
   {}
 
   #define GET_AND_SET(type_, name_) \
-    type_ name_(PSLockRef) const { return m##name_; } \
-    void Set##name_(PSLockRef, type_ a##name_) { m##name_ = a##name_; }
-
-  GET_AND_SET(TimeStamp, ProcessStartTime)
+    type_ name_(LockRef) const { return m##name_; } \
+    void Set##name_(LockRef, type_ a##name_) { m##name_ = a##name_; }
+
+  GET_AND_SET(TimeStamp, StartTime)
 
   GET_AND_SET(int, Entries)
 
   GET_AND_SET(double, Interval)
 
-  Vector<std::string>& Features(PSLockRef) { return mFeatures; }
-
-  Vector<std::string>& Filters(PSLockRef) { return mFilters; }
+  Vector<std::string>& Features(LockRef) { return mFeatures; }
+
+  Vector<std::string>& ThreadNameFilters(LockRef) { return mThreadNameFilters; }
 
   GET_AND_SET(bool, FeatureDisplayListDump)
   GET_AND_SET(bool, FeatureGPU)
   GET_AND_SET(bool, FeatureJava)
   GET_AND_SET(bool, FeatureJS)
   GET_AND_SET(bool, FeatureLayersDump)
   GET_AND_SET(bool, FeatureLeaf)
   GET_AND_SET(bool, FeatureMainThreadIO)
@@ -191,34 +192,34 @@ public:
   GET_AND_SET(bool, FeaturePrivacy)
   GET_AND_SET(bool, FeatureRestyle)
   GET_AND_SET(bool, FeatureStackWalk)
   GET_AND_SET(bool, FeatureTaskTracer)
   GET_AND_SET(bool, FeatureThreads)
 
   GET_AND_SET(ProfileBuffer*, Buffer)
 
-  ThreadVector& LiveThreads(PSLockRef) { return mLiveThreads; }
-  ThreadVector& DeadThreads(PSLockRef) { return mDeadThreads; }
-
-  static bool IsActive(PSLockRef) { return sActivityGeneration > 0; }
-  static uint32_t ActivityGeneration(PSLockRef) { return sActivityGeneration; }
-  static void SetInactive(PSLockRef) { sActivityGeneration = 0; }
-  static void SetActive(PSLockRef)
+  ThreadVector& LiveThreads(LockRef) { return mLiveThreads; }
+  ThreadVector& DeadThreads(LockRef) { return mDeadThreads; }
+
+  static bool IsActive(LockRef) { return sActivityGeneration > 0; }
+  static uint32_t ActivityGeneration(LockRef) { return sActivityGeneration; }
+  static void SetInactive(LockRef) { sActivityGeneration = 0; }
+  static void SetActive(LockRef)
   {
     sActivityGeneration = sNextActivityGeneration;
     // On overflow, reset to 1 instead of 0, because 0 means inactive.
     sNextActivityGeneration = (sNextActivityGeneration == 0xffffffff)
                             ? 1
                             : sNextActivityGeneration + 1;
   }
 
   GET_AND_SET(bool, IsPaused)
 
-#if defined(GP_OS_linux)
+#if defined(GP_OS_linux) || defined(GP_OS_android)
   GET_AND_SET(bool, WasPaused)
 #endif
 
   GET_AND_SET(class SamplerThread*, SamplerThread)
 
 #ifdef USE_LUL_STACKWALK
   GET_AND_SET(lul::LUL*, LUL)
 #endif
@@ -226,33 +227,33 @@ public:
   GET_AND_SET(mozilla::ProfilerIOInterposeObserver*, InterposeObserver)
 
   GET_AND_SET(int, FrameNumber)
   GET_AND_SET(int, LatestRecordedFrameNumber)
 
   #undef GET_AND_SET
 
 private:
-  // The time that the process started.
-  mozilla::TimeStamp mProcessStartTime;
+  // When profiler_init() or profiler_start() was most recently called.
+  mozilla::TimeStamp mStartTime;
 
   // The number of entries in mBuffer. Zeroed when the profiler is inactive.
   int mEntries;
 
   // The interval between samples, measured in milliseconds. Zeroed when the
   // profiler is inactive.
   double mInterval;
 
   // The profile features that are enabled. Cleared when the profiler is
   // inactive.
   Vector<std::string> mFeatures;
 
   // Substrings of names of threads we want to profile. Cleared when the
   // profiler is inactive
-  Vector<std::string> mFilters;
+  Vector<std::string> mThreadNameFilters;
 
   // Configuration flags derived from mFeatures. Cleared when the profiler is
   // inactive.
   bool mFeatureDisplayListDump;
   bool mFeatureGPU;
   bool mFeatureJava;
   bool mFeatureJS;
   bool mFeatureLayersDump;
@@ -300,17 +301,17 @@ private:
   // SamplerThread::Run() even after gPS has been destroyed by
   // profiler_shutdown().
   static uint32_t sActivityGeneration;
   static uint32_t sNextActivityGeneration;
 
   // Is the profiler paused? False when the profiler is inactive.
   bool mIsPaused;
 
-#if defined(GP_OS_linux)
+#if defined(GP_OS_linux) || defined(GP_OS_android)
   // Used to record whether the profiler was paused just before forking. False
   // at all times except just before/after forking.
   bool mWasPaused;
 #endif
 
   // The current sampler thread. Null when the profiler is inactive.
   class SamplerThread* mSamplerThread;
 
@@ -324,27 +325,27 @@ private:
   mozilla::ProfilerIOInterposeObserver* mInterposeObserver;
 
   // The current frame number and the most recent frame number recorded in a
   // sample.
   int mFrameNumber;
   int mLatestRecordedFrameNumber;
 };
 
+// A shorter name for use within this compilation unit.
+typedef ProfilerState PS;
+
 uint32_t PS::sActivityGeneration = 0;
 uint32_t PS::sNextActivityGeneration = 1;
 
-// The core profiler state. Null at process startup, it is set to a non-null
-// value in profiler_init() and stays that way until profiler_shutdown() is
-// called. Therefore it can be checked to determine if the profiler has been
-// initialized but not yet shut down.
-static PS* gPS = nullptr;
+// The profiler state. Set by profiler_init(), cleared by profiler_shutdown().
+PS* gPS = nullptr;
 
 // The mutex that guards accesses to gPS.
-static PSMutex gPSMutex;
+static PS::Mutex gPSMutex;
 
 // The name of the main thread.
 static const char* const kMainThreadName = "GeckoMain";
 
 static bool
 CanNotifyObservers()
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
@@ -467,17 +468,17 @@ AddDynamicCodeLocationTag(ProfileBuffer*
     // Cast to *((void**) to pass the text data to a void*.
     aBuffer->addTag(ProfileBufferEntry::EmbeddedString(*((void**)(&text[0]))));
   }
 }
 
 static const int SAMPLER_MAX_STRING_LENGTH = 128;
 
 static void
-AddPseudoEntry(PSLockRef aLock, ProfileBuffer* aBuffer,
+AddPseudoEntry(PS::LockRef aLock, ProfileBuffer* aBuffer,
                volatile js::ProfileEntry& entry, PseudoStack* stack,
                void* lastpc)
 {
   // Pseudo-frames with the BEGIN_PSEUDO_JS flag are just annotations and
   // should not be recorded in the profile.
   if (entry.hasFlag(js::ProfileEntry::BEGIN_PSEUDO_JS)) {
     return;
   }
@@ -569,17 +570,17 @@ struct AutoWalkJSStack
   ~AutoWalkJSStack() {
     if (walkAllowed) {
       WALKING_JS_STACK = false;
     }
   }
 };
 
 static void
-MergeStacksIntoProfile(PSLockRef aLock, ProfileBuffer* aBuffer,
+MergeStacksIntoProfile(PS::LockRef aLock, ProfileBuffer* aBuffer,
                        const TickSample& aSample, NativeStack& aNativeStack)
 {
   NotNull<PseudoStack*> pseudoStack = aSample.mPseudoStack;
   volatile js::ProfileEntry* pseudoFrames = pseudoStack->mStack;
   uint32_t pseudoCount = pseudoStack->stackSize();
 
   // 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
@@ -753,17 +754,17 @@ MergeStacksIntoProfile(PSLockRef aLock, 
     if (nativeIndex >= 0) {
       nativeIndex--;
     }
   }
 
   // Update the JS context with the current profile sample buffer generation.
   //
   // Do not do this for synchronous samples, which use their own
-  // ProfileBuffers instead of the global one in PS.
+  // ProfileBuffers instead of the global one in ProfilerState.
   if (!aSample.mIsSynchronous && pseudoStack->mContext) {
     MOZ_ASSERT(aBuffer->mGeneration >= startBufferGen);
     uint32_t lapCount = aBuffer->mGeneration - startBufferGen;
     JS::UpdateJSContextProfilerSampleBufferGen(pseudoStack->mContext,
                                                aBuffer->mGeneration,
                                                lapCount);
   }
 }
@@ -779,17 +780,17 @@ StackWalkCallback(uint32_t aFrameNumber,
   NativeStack* nativeStack = static_cast<NativeStack*>(aClosure);
   MOZ_ASSERT(nativeStack->count < nativeStack->size);
   nativeStack->sp_array[nativeStack->count] = aSP;
   nativeStack->pc_array[nativeStack->count] = aPC;
   nativeStack->count++;
 }
 
 static void
-DoNativeBacktrace(PSLockRef aLock, ProfileBuffer* aBuffer,
+DoNativeBacktrace(PS::LockRef aLock, ProfileBuffer* aBuffer,
                   const TickSample& aSample)
 {
   void* pc_array[1000];
   void* sp_array[1000];
   NativeStack nativeStack = {
     pc_array,
     sp_array,
     mozilla::ArrayLength(pc_array),
@@ -821,17 +822,17 @@ DoNativeBacktrace(PSLockRef aLock, Profi
 #endif
 
   MergeStacksIntoProfile(aLock, aBuffer, aSample, nativeStack);
 }
 #endif
 
 #ifdef USE_EHABI_STACKWALK
 static void
-DoNativeBacktrace(PSLockRef aLock, ProfileBuffer* aBuffer,
+DoNativeBacktrace(PS::LockRef aLock, ProfileBuffer* aBuffer,
                   const TickSample& aSample)
 {
   void* pc_array[1000];
   void* sp_array[1000];
   NativeStack nativeStack = {
     pc_array,
     sp_array,
     mozilla::ArrayLength(pc_array),
@@ -910,17 +911,17 @@ ASAN_memcpy(void* aDst, const void* aSrc
 
   for (size_t i = 0; i < aLen; i++) {
     dst[i] = src[i];
   }
 }
 #endif
 
 static void
-DoNativeBacktrace(PSLockRef aLock, ProfileBuffer* aBuffer,
+DoNativeBacktrace(PS::LockRef aLock, ProfileBuffer* aBuffer,
                   const TickSample& aSample)
 {
   const mcontext_t* mc =
     &reinterpret_cast<ucontext_t*>(aSample.mContext)->uc_mcontext;
 
   lul::UnwindRegs startRegs;
   memset(&startRegs, 0, sizeof(startRegs));
 
@@ -1053,36 +1054,35 @@ DoNativeBacktrace(PSLockRef aLock, Profi
   lul->mStats.mContext += 1;
   lul->mStats.mCFI     += framesUsed - 1 - scannedFramesAcquired;
   lul->mStats.mScanned += scannedFramesAcquired;
 }
 
 #endif
 
 static void
-DoSampleStackTrace(PSLockRef aLock, ProfileBuffer* aBuffer,
+DoSampleStackTrace(PS::LockRef aLock, ProfileBuffer* aBuffer,
                    const TickSample& aSample)
 {
   NativeStack nativeStack = { nullptr, nullptr, 0, 0 };
   MergeStacksIntoProfile(aLock, aBuffer, aSample, nativeStack);
 
   if (gPS->FeatureLeaf(aLock)) {
     aBuffer->addTag(ProfileBufferEntry::NativeLeafAddr((void*)aSample.mPC));
   }
 }
 
 // This function is called for each sampling period with the current program
 // counter. It is called within a signal and so must be re-entrant.
 static void
-Tick(PSLockRef aLock, ProfileBuffer* aBuffer, const TickSample& aSample)
+Tick(PS::LockRef aLock, ProfileBuffer* aBuffer, const TickSample& aSample)
 {
   aBuffer->addTagThreadId(aSample.mThreadId, aSample.mLastSample);
 
-  mozilla::TimeDuration delta =
-    aSample.mTimeStamp - gPS->ProcessStartTime(aLock);
+  mozilla::TimeDuration delta = aSample.mTimeStamp - gPS->StartTime(aLock);
   aBuffer->addTag(ProfileBufferEntry::Time(delta.ToMilliseconds()));
 
   NotNull<PseudoStack*> pseudoStack = aSample.mPseudoStack;
 
 #if defined(HAVE_NATIVE_UNWIND)
   if (gPS->FeatureStackWalk(aLock)) {
     DoNativeBacktrace(aLock, aBuffer, aSample);
   } else
@@ -1181,23 +1181,23 @@ StreamNameAndThreadId(JSONWriter& aWrite
     }
     aWriter.IntProperty("tid", aThreadId);
   }
   aWriter.EndObject();
 }
 #endif
 
 static void
-StreamTaskTracer(PSLockRef aLock, SpliceableJSONWriter& aWriter)
+StreamTaskTracer(PS::LockRef aLock, SpliceableJSONWriter& aWriter)
 {
 #ifdef MOZ_TASK_TRACER
   aWriter.StartArrayProperty("data");
   {
     UniquePtr<nsTArray<nsCString>> data =
-      mozilla::tasktracer::GetLoggedData(gPS->ProcessStartTime(aLock));
+      mozilla::tasktracer::GetLoggedData(gPS->StartTime(aLock));
     for (uint32_t i = 0; i < data->Length(); ++i) {
       aWriter.StringElement((data->ElementAt(i)).get());
     }
   }
   aWriter.EndArray();
 
   aWriter.StartArrayProperty("threads");
   {
@@ -1216,17 +1216,17 @@ StreamTaskTracer(PSLockRef aLock, Splice
   aWriter.EndArray();
 
   aWriter.DoubleProperty(
     "start", static_cast<double>(mozilla::tasktracer::GetStartTime()));
 #endif
 }
 
 static void
-StreamMetaJSCustomObject(PSLockRef aLock, SpliceableJSONWriter& aWriter)
+StreamMetaJSCustomObject(PS::LockRef aLock, SpliceableJSONWriter& aWriter)
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
 
   aWriter.IntProperty("version", 5);
   aWriter.DoubleProperty("interval", gPS->Interval(aLock));
   aWriter.IntProperty("stackwalk", gPS->FeatureStackWalk(aLock));
 
 #ifdef DEBUG
@@ -1236,20 +1236,20 @@ StreamMetaJSCustomObject(PSLockRef aLock
 #endif
 
   aWriter.IntProperty("gcpoison", JS::IsGCPoisoning() ? 1 : 0);
 
   bool asyncStacks = Preferences::GetBool("javascript.options.asyncstack");
   aWriter.IntProperty("asyncstack", asyncStacks);
 
   // The "startTime" field holds the number of milliseconds since midnight
-  // January 1, 1970 GMT. This grotty code computes (Now - (Now -
-  // ProcessStartTime)) to convert gPS->ProcessStartTime() into that form.
+  // January 1, 1970 GMT. This grotty code computes (Now - (Now - StartTime))
+  // to convert gPS->StartTime() into that form.
   mozilla::TimeDuration delta =
-    mozilla::TimeStamp::Now() - gPS->ProcessStartTime(aLock);
+    mozilla::TimeStamp::Now() - gPS->StartTime(aLock);
   aWriter.DoubleProperty(
     "startTime", static_cast<double>(PR_Now()/1000.0 - delta.ToMilliseconds()));
 
   aWriter.IntProperty("processType", XRE_GetProcessType());
 
   nsresult res;
   nsCOMPtr<nsIHttpProtocolHandler> http =
     do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &res);
@@ -1348,19 +1348,17 @@ BuildJavaThreadJSObject(SpliceableJSONWr
       }
     }
   }
   aWriter.EndArray();
 }
 #endif
 
 static void
-locked_profiler_stream_json_for_this_process(PSLockRef aLock,
-                                             SpliceableJSONWriter& aWriter,
-                                             double aSinceTime)
+locked_profiler_stream_json_for_this_process(PS::LockRef aLock, SpliceableJSONWriter& aWriter, double aSinceTime)
 {
   LOG("locked_profiler_stream_json_for_this_process");
 
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   MOZ_RELEASE_ASSERT(gPS && gPS->IsActive(aLock));
 
   // Put shared library info
   aWriter.StartArrayProperty("libs");
@@ -1381,33 +1379,33 @@ locked_profiler_stream_json_for_this_pro
     aWriter.EndObject();
   }
 
   // Lists the samples for each thread profile
   aWriter.StartArrayProperty("threads");
   {
     gPS->SetIsPaused(aLock, true);
 
-    const PS::ThreadVector& liveThreads = gPS->LiveThreads(aLock);
-    for (size_t i = 0; i < liveThreads.size(); i++) {
-      ThreadInfo* info = liveThreads.at(i);
-      if (!info->IsBeingProfiled()) {
-        continue;
+      const PS::ThreadVector& liveThreads = gPS->LiveThreads(aLock);
+      for (size_t i = 0; i < liveThreads.size(); i++) {
+        ThreadInfo* info = liveThreads.at(i);
+        if (!info->IsBeingProfiled()) {
+          continue;
+        }
+        info->StreamJSON(gPS->Buffer(aLock), aWriter, gPS->StartTime(aLock),
+                         aSinceTime);
       }
-      info->StreamJSON(gPS->Buffer(aLock), aWriter,
-                       gPS->ProcessStartTime(aLock), aSinceTime);
-    }
-
-    const PS::ThreadVector& deadThreads = gPS->DeadThreads(aLock);
-    for (size_t i = 0; i < deadThreads.size(); i++) {
-      ThreadInfo* info = deadThreads.at(i);
-      MOZ_ASSERT(info->IsBeingProfiled());
-      info->StreamJSON(gPS->Buffer(aLock), aWriter,
-                       gPS->ProcessStartTime(aLock), aSinceTime);
-    }
+
+      const PS::ThreadVector& deadThreads = gPS->DeadThreads(aLock);
+      for (size_t i = 0; i < deadThreads.size(); i++) {
+        ThreadInfo* info = deadThreads.at(i);
+        MOZ_ASSERT(info->IsBeingProfiled());
+        info->StreamJSON(gPS->Buffer(aLock), aWriter, gPS->StartTime(aLock),
+                         aSinceTime);
+      }
 
 #if defined(PROFILE_JAVA)
     if (gPS->FeatureJava(aLock)) {
       java::GeckoJavaSampler::Pause();
 
       aWriter.Start();
       {
         BuildJavaThreadJSObject(aWriter);
@@ -1426,17 +1424,17 @@ locked_profiler_stream_json_for_this_pro
 bool
 profiler_stream_json_for_this_process(SpliceableJSONWriter& aWriter, double aSinceTime)
 {
   LOG("profiler_stream_json_for_this_process");
 
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   MOZ_RELEASE_ASSERT(gPS);
 
-  PSAutoLock lock(gPSMutex);
+  PS::AutoLock lock(gPSMutex);
 
   if (!gPS->IsActive(lock)) {
     return false;
   }
 
   locked_profiler_stream_json_for_this_process(lock, aWriter, aSinceTime);
   return true;
 }
@@ -1464,33 +1462,33 @@ ProfilerMarker::SetGeneration(uint32_t a
 }
 
 double
 ProfilerMarker::GetTime() const {
   return mTime;
 }
 
 void ProfilerMarker::StreamJSON(SpliceableJSONWriter& aWriter,
-                                const TimeStamp& aProcessStartTime,
+                                const TimeStamp& aStartTime,
                                 UniqueStacks& aUniqueStacks) const
 {
   // Schema:
   //   [name, time, data]
 
   aWriter.StartArrayElement();
   {
     aUniqueStacks.mUniqueStrings.WriteElement(aWriter, GetMarkerName());
     aWriter.DoubleElement(mTime);
     // TODO: Store the callsite for this marker if available:
     // if have location data
     //   b.NameValue(marker, "location", ...);
     if (mPayload) {
       aWriter.StartObjectElement();
       {
-        mPayload->StreamPayload(aWriter, aProcessStartTime, aUniqueStacks);
+          mPayload->StreamPayload(aWriter, aStartTime, aUniqueStacks);
       }
       aWriter.EndObject();
     }
   }
   aWriter.EndArray();
 }
 
 static void
@@ -1555,29 +1553,29 @@ struct SigHandlerCoordinator;
 // The sampler thread controls sampling and runs whenever the profiler is
 // active. It periodically runs through all registered threads, finds those
 // that should be sampled, then pauses and samples them.
 
 class SamplerThread
 {
 public:
   // Creates a sampler thread, but doesn't start it.
-  SamplerThread(PSLockRef aLock, uint32_t aActivityGeneration,
+  SamplerThread(PS::LockRef aLock, uint32_t aActivityGeneration,
                 double aIntervalMilliseconds);
   ~SamplerThread();
 
   // This runs on the sampler thread.  It suspends and resumes the samplee
   // threads.
-  void SuspendAndSampleAndResumeThread(PSLockRef aLock, TickSample& aSample);
+  void SuspendAndSampleAndResumeThread(PS::LockRef aLock, TickSample& aSample);
 
   // This runs on (is!) the sampler thread.
   void Run();
 
   // This runs on the main thread.
-  void Stop(PSLockRef aLock);
+  void Stop(PS::LockRef aLock);
 
 private:
   // The activity generation, for detecting when the sampler thread must stop.
   const uint32_t mActivityGeneration;
 
   // The interval between samples, measured in microseconds.
   const int mIntervalMicroseconds;
 
@@ -1621,17 +1619,17 @@ SamplerThread::Run()
   // 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);
+      PS::AutoLock lock(gPSMutex);
 
       // At this point profiler_stop() might have been called, and
       // profiler_start() might have been called on another thread.
       // Alternatively, profiler_shutdown() might have been called and gPS
       // may be null. In all these cases, PS::sActivityGeneration will no
       // longer equal mActivityGeneration, so we must exit immediately, but
       // without touching gPS. (This is why PS::sActivityGeneration must be
       // static.)
@@ -1651,19 +1649,19 @@ SamplerThread::Run()
             continue;
           }
 
           // If the thread is asleep and has been sampled before in the same
           // sleep episode, find and copy the previous sample, as that's
           // cheaper than taking a new sample.
           if (info->Stack()->CanDuplicateLastSampleDueToSleep()) {
             bool dup_ok =
-              gPS->Buffer(lock)->DuplicateLastSample(
-                info->ThreadId(), gPS->ProcessStartTime(lock),
-                info->LastSample());
+              gPS->Buffer(lock)->DuplicateLastSample(info->ThreadId(),
+                                                     gPS->StartTime(lock),
+                                                     info->LastSample());
             if (dup_ok) {
               continue;
             }
           }
 
           // We only track responsiveness for the main thread.
           if (info->IsMainThread()) {
             info->GetThreadResponsiveness()->Update();
@@ -1754,17 +1752,17 @@ GeckoProfilerReporter::CollectReports(ns
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
 
   size_t profSize = 0;
 #if defined(USE_LUL_STACKWALK)
   size_t lulSize = 0;
 #endif
 
   {
-    PSAutoLock lock(gPSMutex);
+    PS::AutoLock lock(gPSMutex);
 
     if (gPS) {
       profSize = GeckoProfilerMallocSizeOf(gPS);
 
       const PS::ThreadVector& liveThreads = gPS->LiveThreads(lock);
       for (uint32_t i = 0; i < liveThreads.size(); i++) {
         ThreadInfo* info = liveThreads.at(i);
         profSize += info->SizeOfIncludingThis(GeckoProfilerMallocSizeOf);
@@ -1779,88 +1777,88 @@ GeckoProfilerReporter::CollectReports(ns
       if (gPS->IsActive(lock)) {
         profSize +=
           gPS->Buffer(lock)->SizeOfIncludingThis(GeckoProfilerMallocSizeOf);
       }
 
       // Measurement of the following things may be added later if DMD finds it
       // is worthwhile:
       // - gPS->mFeatures
-      // - gPS->mFilters
+      // - gPS->mThreadNameFilters
       // - gPS->mLiveThreads itself (its elements' children are measured above)
       // - gPS->mDeadThreads itself (ditto)
       // - gPS->mInterposeObserver
 
 #if defined(USE_LUL_STACKWALK)
       lul::LUL* lul = gPS->LUL(lock);
       lulSize = lul ? lul->SizeOfIncludingThis(GeckoProfilerMallocSizeOf) : 0;
 #endif
     }
   }
 
   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).");
+    "Memory used by the Gecko Profiler's ProfilerState object (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 bool
-ThreadSelected(PSLockRef aLock, const char* aThreadName)
+ThreadSelected(PS::LockRef aLock, const char* aThreadName)
 {
   // This function runs both on and off the main thread.
 
   MOZ_RELEASE_ASSERT(gPS);
 
-  const Vector<std::string>& filters = gPS->Filters(aLock);
-
-  if (filters.empty()) {
+  const Vector<std::string>& threadNameFilters = gPS->ThreadNameFilters(aLock);
+
+  if (threadNameFilters.empty()) {
     return true;
   }
 
   std::string name = aThreadName;
   std::transform(name.begin(), name.end(), name.begin(), ::tolower);
 
-  for (uint32_t i = 0; i < filters.length(); ++i) {
-    std::string filter = filters[i];
+  for (uint32_t i = 0; i < threadNameFilters.length(); ++i) {
+    std::string filter = threadNameFilters[i];
     std::transform(filter.begin(), filter.end(), filter.begin(), ::tolower);
 
     // Crude, non UTF-8 compatible, case insensitive substring search
     if (name.find(filter) != std::string::npos) {
       return true;
     }
   }
 
   return false;
 }
 
 static bool
-ShouldProfileThread(PSLockRef aLock, ThreadInfo* aInfo)
+ShouldProfileThread(PS::LockRef aLock, ThreadInfo* aInfo)
 {
   // This function runs both on and off the main thread.
 
   MOZ_RELEASE_ASSERT(gPS);
 
   return ((aInfo->IsMainThread() || gPS->FeatureThreads(aLock)) &&
           ThreadSelected(aLock, aInfo->Name()));
 }
 
 // Find the ThreadInfo for the current thread. On success, *aIndexOut is set to
 // the index if it is non-null.
 static ThreadInfo*
-FindLiveThreadInfo(PSLockRef aLock, int* aIndexOut = nullptr)
+FindLiveThreadInfo(PS::LockRef aLock, int* aIndexOut = nullptr)
 {
   // This function runs both on and off the main thread.
 
   Thread::tid_t id = Thread::GetCurrentId();
   const PS::ThreadVector& liveThreads = gPS->LiveThreads(aLock);
   for (uint32_t i = 0; i < liveThreads.size(); i++) {
     ThreadInfo* info = liveThreads.at(i);
     if (info->ThreadId() == id) {
@@ -1869,17 +1867,17 @@ FindLiveThreadInfo(PSLockRef aLock, int*
       }
       return info;
     }
   }
   return nullptr;
 }
 
 static void
-locked_register_thread(PSLockRef aLock, const char* aName, void* stackTop)
+locked_register_thread(PS::LockRef aLock, const char* aName, void* stackTop)
 {
   // This function runs both on and off the main thread.
 
   MOZ_RELEASE_ASSERT(gPS);
 
   MOZ_RELEASE_ASSERT(!FindLiveThreadInfo(aLock));
 
   if (!tlsPseudoStack.init()) {
@@ -1903,39 +1901,40 @@ locked_register_thread(PSLockRef aLock, 
   }
 
   gPS->LiveThreads(aLock).push_back(info);
 }
 
 static void
 NotifyProfilerStarted(const int aEntries, double aInterval,
                       const char** aFeatures, uint32_t aFeatureCount,
-                      const char** aFilters, uint32_t aFilterCount)
+                      const char** aThreadNameFilters, uint32_t aFilterCount)
 {
   if (!CanNotifyObservers()) {
     return;
   }
 
   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
   if (!os) {
     return;
   }
 
   nsTArray<nsCString> featuresArray;
   for (size_t i = 0; i < aFeatureCount; ++i) {
     featuresArray.AppendElement(aFeatures[i]);
   }
 
-  nsTArray<nsCString> filtersArray;
+  nsTArray<nsCString> threadNameFiltersArray;
   for (size_t i = 0; i < aFilterCount; ++i) {
-    filtersArray.AppendElement(aFilters[i]);
+    threadNameFiltersArray.AppendElement(aThreadNameFilters[i]);
   }
 
   nsCOMPtr<nsIProfilerStartParams> params =
-    new nsProfilerStartParams(aEntries, aInterval, featuresArray, filtersArray);
+    new nsProfilerStartParams(aEntries, aInterval, featuresArray,
+                              threadNameFiltersArray);
 
   os->NotifyObservers(params, "profiler-started", nullptr);
 }
 
 static void
 NotifyObservers(const char* aTopic)
 {
   if (!CanNotifyObservers()) {
@@ -1946,19 +1945,19 @@ NotifyObservers(const char* aTopic)
   if (!os) {
     return;
   }
 
   os->NotifyObservers(nullptr, aTopic, nullptr);
 }
 
 static void
-locked_profiler_start(PSLockRef aLock, const int aEntries, double aInterval,
+locked_profiler_start(PS::LockRef aLock, const int aEntries, double aInterval,
                       const char** aFeatures, uint32_t aFeatureCount,
-                      const char** aFilters, uint32_t aFilterCount);
+                      const char** aThreadNameFilters, uint32_t aFilterCount);
 
 void
 profiler_init(void* aStackTop)
 {
   LOG("profiler_init");
 
   MOZ_RELEASE_ASSERT(!gPS);
 
@@ -1975,24 +1974,24 @@ profiler_init(void* aStackTop)
 
   const char* threadFilters[] = { "GeckoMain", "Compositor" };
 
   if (getenv("MOZ_PROFILER_HELP")) {
     PrintUsageThenExit(0); // terminates execution
   }
 
   {
-    PSAutoLock lock(gPSMutex);
+    PS::AutoLock lock(gPSMutex);
 
     // We've passed the possible failure point. Instantiate gPS, which
     // indicates that the profiler has initialized successfully.
     gPS = new PS();
 
     bool ignore;
-    gPS->SetProcessStartTime(lock, mozilla::TimeStamp::ProcessCreation(ignore));
+    gPS->SetStartTime(lock, mozilla::TimeStamp::ProcessCreation(ignore));
 
     locked_register_thread(lock, kMainThreadName, aStackTop);
 
     // Platform-specific initialization.
     PlatformInit(lock);
 
 #ifdef MOZ_TASK_TRACER
     mozilla::tasktracer::InitTaskTracer();
@@ -2048,34 +2047,34 @@ profiler_init(void* aStackTop)
   // We do this with gPSMutex unlocked. The comment in profiler_stop() explains
   // why.
   NotifyProfilerStarted(PROFILE_DEFAULT_ENTRIES, PROFILE_DEFAULT_INTERVAL,
                         features, MOZ_ARRAY_LENGTH(features),
                         threadFilters, MOZ_ARRAY_LENGTH(threadFilters));
 }
 
 static void
-locked_profiler_save_profile_to_file(PSLockRef aLock, const char* aFilename);
+locked_profiler_save_profile_to_file(PS::LockRef aLock, const char* aFilename);
 
 static SamplerThread*
-locked_profiler_stop(PSLockRef aLock);
+locked_profiler_stop(PS::LockRef aLock);
 
 void
 profiler_shutdown()
 {
   LOG("profiler_shutdown");
 
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   MOZ_RELEASE_ASSERT(gPS);
 
   // If the profiler is active we must get a handle to the SamplerThread before
   // gPS is destroyed, in order to delete it.
   SamplerThread* samplerThread = nullptr;
   {
-    PSAutoLock lock(gPSMutex);
+    PS::AutoLock lock(gPSMutex);
 
     // Save the profile on shutdown if requested.
     if (gPS->IsActive(lock)) {
       const char* filename = getenv("MOZ_PROFILER_SHUTDOWN");
       if (filename) {
         locked_profiler_save_profile_to_file(lock, filename);
       }
 
@@ -2156,36 +2155,36 @@ profiler_get_start_params(int* aEntries,
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   MOZ_RELEASE_ASSERT(gPS);
 
   if (NS_WARN_IF(!aEntries) || NS_WARN_IF(!aInterval) ||
       NS_WARN_IF(!aFeatures) || NS_WARN_IF(!aFilters)) {
     return;
   }
 
-  PSAutoLock lock(gPSMutex);
+  PS::AutoLock lock(gPSMutex);
 
   *aEntries = gPS->Entries(lock);
   *aInterval = gPS->Interval(lock);
 
   const Vector<std::string>& features = gPS->Features(lock);
   MOZ_ALWAYS_TRUE(aFeatures->resize(features.length()));
   for (size_t i = 0; i < features.length(); ++i) {
     (*aFeatures)[i] = features[i].c_str();
   }
 
-  const Vector<std::string>& filters = gPS->Filters(lock);
-  MOZ_ALWAYS_TRUE(aFilters->resize(filters.length()));
-  for (uint32_t i = 0; i < filters.length(); ++i) {
-    (*aFilters)[i] = filters[i].c_str();
+  const Vector<std::string>& threadNameFilters = gPS->ThreadNameFilters(lock);
+  MOZ_ALWAYS_TRUE(aFilters->resize(threadNameFilters.length()));
+  for (uint32_t i = 0; i < threadNameFilters.length(); ++i) {
+    (*aFilters)[i] = threadNameFilters[i].c_str();
   }
 }
 
 static void
-locked_profiler_save_profile_to_file(PSLockRef aLock, const char* aFilename)
+locked_profiler_save_profile_to_file(PS::LockRef aLock, const char* aFilename)
 {
   LOG("locked_profiler_save_profile_to_file(%s)", aFilename);
 
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   MOZ_RELEASE_ASSERT(gPS && gPS->IsActive(aLock));
 
   std::ofstream stream;
   stream.open(aFilename);
@@ -2209,17 +2208,17 @@ locked_profiler_save_profile_to_file(PSL
 void
 profiler_save_profile_to_file(const char* aFilename)
 {
   LOG("profiler_save_profile_to_file(%s)", aFilename);
 
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   MOZ_RELEASE_ASSERT(gPS);
 
-  PSAutoLock lock(gPSMutex);
+  PS::AutoLock lock(gPSMutex);
 
   if (!gPS->IsActive(lock)) {
     return;
   }
 
   locked_profiler_save_profile_to_file(lock, aFilename);
 }
 
@@ -2273,17 +2272,17 @@ profiler_get_buffer_info_helper(uint32_t
                                 uint32_t* aGeneration)
 {
   // This function is called by profiler_get_buffer_info(), which has already
   // zeroed the outparams.
 
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   MOZ_RELEASE_ASSERT(gPS);
 
-  PSAutoLock lock(gPSMutex);
+  PS::AutoLock lock(gPSMutex);
 
   if (!gPS->IsActive(lock)) {
     return;
   }
 
   *aCurrentPosition = gPS->Buffer(lock)->mWritePos;
   *aEntries = gPS->Entries(lock);
   *aGeneration = gPS->Buffer(lock)->mGeneration;
@@ -2296,55 +2295,59 @@ hasFeature(const char** aFeatures, uint3
     if (strcmp(aFeatures[i], aFeature) == 0) {
       return true;
     }
   }
   return false;
 }
 
 static void
-locked_profiler_start(PSLockRef aLock, int aEntries, double aInterval,
+locked_profiler_start(PS::LockRef aLock, int aEntries, double aInterval,
                       const char** aFeatures, uint32_t aFeatureCount,
-                      const char** aFilters, uint32_t aFilterCount)
+                      const char** aThreadNameFilters, uint32_t aFilterCount)
 {
   if (LOG_TEST) {
     LOG("locked_profiler_start");
     LOG("- entries  = %d", aEntries);
     LOG("- interval = %.2f", aInterval);
     for (uint32_t i = 0; i < aFeatureCount; i++) {
       LOG("- feature  = %s", aFeatures[i]);
     }
     for (uint32_t i = 0; i < aFilterCount; i++) {
-      LOG("- threads  = %s", aFilters[i]);
+      LOG("- threads  = %s", aThreadNameFilters[i]);
     }
   }
 
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   MOZ_RELEASE_ASSERT(gPS && !gPS->IsActive(aLock));
 
+  bool ignore;
+  gPS->SetStartTime(aLock, mozilla::TimeStamp::ProcessCreation(ignore));
+
   // Fall back to the default value if the passed-in value is unreasonable.
   int entries = aEntries > 0 ? aEntries : PROFILE_DEFAULT_ENTRIES;
   gPS->SetEntries(aLock, entries);
 
   // Ditto.
   double interval = aInterval > 0 ? aInterval : PROFILE_DEFAULT_INTERVAL;
   gPS->SetInterval(aLock, interval);
 
   // Deep copy aFeatures. Must precede the ShouldProfileThread() call below.
   Vector<std::string>& features = gPS->Features(aLock);
   MOZ_ALWAYS_TRUE(features.resize(aFeatureCount));
   for (uint32_t i = 0; i < aFeatureCount; ++i) {
     features[i] = aFeatures[i];
   }
 
-  // Deep copy aFilters. Must precede the ShouldProfileThread() call below.
-  Vector<std::string>& filters = gPS->Filters(aLock);
-  MOZ_ALWAYS_TRUE(filters.resize(aFilterCount));
+  // Deep copy aThreadNameFilters. Must precede the ShouldProfileThread() call
+  // below.
+  Vector<std::string>& threadNameFilters = gPS->ThreadNameFilters(aLock);
+  MOZ_ALWAYS_TRUE(threadNameFilters.resize(aFilterCount));
   for (uint32_t i = 0; i < aFilterCount; ++i) {
-    filters[i] = aFilters[i];
+    threadNameFilters[i] = aThreadNameFilters[i];
   }
 
 #define HAS_FEATURE(feature) hasFeature(aFeatures, aFeatureCount, feature)
 
   gPS->SetFeatureDisplayListDump(aLock, HAS_FEATURE("displaylistdump"));
   gPS->SetFeatureGPU(aLock, HAS_FEATURE("gpu"));
 #if defined(PROFILE_JAVA)
   gPS->SetFeatureJava(aLock, mozilla::jni::IsFennec() && HAS_FEATURE("java"));
@@ -2433,52 +2436,52 @@ locked_profiler_start(PSLockRef aLock, i
     mozilla::IOInterposer::Register(mozilla::IOInterposeObserver::OpAll,
                                     interposeObserver);
   }
 }
 
 void
 profiler_start(int aEntries, double aInterval,
                const char** aFeatures, uint32_t aFeatureCount,
-               const char** aFilters, uint32_t aFilterCount)
+               const char** aThreadNameFilters, uint32_t aFilterCount)
 {
   LOG("profiler_start");
 
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
 
   SamplerThread* samplerThread = nullptr;
   {
-    PSAutoLock lock(gPSMutex);
+    PS::AutoLock lock(gPSMutex);
 
     // Initialize if necessary.
     if (!gPS) {
       profiler_init(nullptr);
     }
 
     // Reset the current state if the profiler is running.
     if (gPS->IsActive(lock)) {
       samplerThread = locked_profiler_stop(lock);
     }
 
     locked_profiler_start(lock, aEntries, aInterval, aFeatures, aFeatureCount,
-                          aFilters, aFilterCount);
+                          aThreadNameFilters, aFilterCount);
   }
 
   // We do these operations with gPSMutex unlocked. The comments in
   // profiler_stop() explain why.
   if (samplerThread) {
     NotifyObservers("profiler-stopped");
     delete samplerThread;
   }
   NotifyProfilerStarted(aEntries, aInterval, aFeatures, aFeatureCount,
-                        aFilters, aFilterCount);
+                        aThreadNameFilters, aFilterCount);
 }
 
 static MOZ_MUST_USE SamplerThread*
-locked_profiler_stop(PSLockRef aLock)
+locked_profiler_stop(PS::LockRef aLock)
 {
   LOG("locked_profiler_stop");
 
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   MOZ_RELEASE_ASSERT(gPS && gPS->IsActive(aLock));
 
   // We clear things in roughly reverse order to their setting in
   // locked_profiler_start().
@@ -2546,17 +2549,17 @@ locked_profiler_stop(PSLockRef aLock)
   gPS->SetFeatureLeaf(aLock, false);
   gPS->SetFeatureMemory(aLock, false);
   gPS->SetFeaturePrivacy(aLock, false);
   gPS->SetFeatureRestyle(aLock, false);
   gPS->SetFeatureStackWalk(aLock, false);
   gPS->SetFeatureTaskTracer(aLock, false);
   gPS->SetFeatureThreads(aLock, false);
 
-  gPS->Filters(aLock).clear();
+  gPS->ThreadNameFilters(aLock).clear();
 
   gPS->Features(aLock).clear();
 
   gPS->SetInterval(aLock, 0.0);
 
   gPS->SetEntries(aLock, 0);
 
   return samplerThread;
@@ -2567,17 +2570,17 @@ profiler_stop()
 {
   LOG("profiler_stop");
 
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   MOZ_RELEASE_ASSERT(gPS);
 
   SamplerThread* samplerThread;
   {
-    PSAutoLock lock(gPSMutex);
+    PS::AutoLock lock(gPSMutex);
 
     if (!gPS->IsActive(lock)) {
       return;
     }
 
     samplerThread = locked_profiler_stop(lock);
   }
 
@@ -2599,17 +2602,17 @@ profiler_stop()
 }
 
 bool
 profiler_is_paused()
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   MOZ_RELEASE_ASSERT(gPS);
 
-  PSAutoLock lock(gPSMutex);
+  PS::AutoLock lock(gPSMutex);
 
   if (!gPS->IsActive(lock)) {
     return false;
   }
 
   return gPS->IsPaused(lock);
 }
 
@@ -2617,17 +2620,17 @@ void
 profiler_pause()
 {
   LOG("profiler_pause");
 
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   MOZ_RELEASE_ASSERT(gPS);
 
   {
-    PSAutoLock lock(gPSMutex);
+    PS::AutoLock lock(gPSMutex);
 
     if (!gPS->IsActive(lock)) {
       return;
     }
 
     gPS->SetIsPaused(lock, true);
   }
 
@@ -2638,17 +2641,17 @@ profiler_pause()
 void
 profiler_resume()
 {
   LOG("profiler_resume");
 
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   MOZ_RELEASE_ASSERT(gPS);
 
-  PSAutoLock lock(gPSMutex);
+  PS::AutoLock lock(gPSMutex);
 
   {
     if (!gPS->IsActive(lock)) {
       return;
     }
 
     gPS->SetIsPaused(lock, false);
   }
@@ -2659,17 +2662,17 @@ profiler_resume()
 
 bool
 profiler_feature_active(const char* aName)
 {
   // This function runs both on and off the main thread.
 
   MOZ_RELEASE_ASSERT(gPS);
 
-  PSAutoLock lock(gPSMutex);
+  PS::AutoLock lock(gPSMutex);
 
   if (!gPS->IsActive(lock)) {
     return false;
   }
 
   if (strcmp(aName, "displaylistdump") == 0) {
     return gPS->FeatureDisplayListDump(lock);
   }
@@ -2691,54 +2694,54 @@ profiler_feature_active(const char* aNam
 
 bool
 profiler_is_active()
 {
   // This function runs both on and off the main thread.
 
   MOZ_RELEASE_ASSERT(gPS);
 
-  PSAutoLock lock(gPSMutex);
+  PS::AutoLock lock(gPSMutex);
 
   return gPS->IsActive(lock);
 }
 
 void
 profiler_set_frame_number(int aFrameNumber)
 {
   // This function runs both on (via tests) and off the main thread.
 
   MOZ_RELEASE_ASSERT(gPS);
 
-  PSAutoLock lock(gPSMutex);
+  PS::AutoLock lock(gPSMutex);
 
   gPS->SetFrameNumber(lock, aFrameNumber);
 }
 
 void
 profiler_register_thread(const char* aName, void* aGuessStackTop)
 {
   DEBUG_LOG("profiler_register_thread(%s)", aName);
 
   MOZ_RELEASE_ASSERT(!NS_IsMainThread());
   MOZ_RELEASE_ASSERT(gPS);
 
-  PSAutoLock lock(gPSMutex);
+  PS::AutoLock lock(gPSMutex);
 
   void* stackTop = GetStackTop(aGuessStackTop);
   locked_register_thread(lock, aName, stackTop);
 }
 
 void
 profiler_unregister_thread()
 {
   MOZ_RELEASE_ASSERT(!NS_IsMainThread());
   MOZ_RELEASE_ASSERT(gPS);
 
-  PSAutoLock lock(gPSMutex);
+  PS::AutoLock lock(gPSMutex);
 
   // We don't call PseudoStack::stopJSSampling() here; there's no point doing
   // that for a JS thread that is in the process of disappearing.
 
   int i;
   ThreadInfo* info = FindLiveThreadInfo(lock, &i);
   if (info) {
     DEBUG_LOG("profiler_unregister_thread: %s", info->Name());
@@ -2826,30 +2829,30 @@ profiler_js_interrupt_callback()
 
 double
 profiler_time()
 {
   // This function runs both on and off the main thread.
 
   MOZ_RELEASE_ASSERT(gPS);
 
-  PSAutoLock lock(gPSMutex);
+  PS::AutoLock lock(gPSMutex);
 
   mozilla::TimeDuration delta =
-    mozilla::TimeStamp::Now() - gPS->ProcessStartTime(lock);
+    mozilla::TimeStamp::Now() - gPS->StartTime(lock);
   return delta.ToMilliseconds();
 }
 
 UniqueProfilerBacktrace
 profiler_get_backtrace()
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   MOZ_RELEASE_ASSERT(gPS);
 
-  PSAutoLock lock(gPSMutex);
+  PS::AutoLock lock(gPSMutex);
 
   if (!gPS->IsActive(lock) || gPS->FeaturePrivacy(lock)) {
     return nullptr;
   }
 
   PseudoStack* stack = tlsPseudoStack.get();
   if (!stack) {
     MOZ_ASSERT(stack);
@@ -2902,17 +2905,17 @@ profiler_get_backtrace_noalloc(char *out
 
   PseudoStack *pseudoStack = tlsPseudoStack.get();
   if (!pseudoStack) {
     return;
   }
 
   bool includeDynamicString = true;
   {
-    PSAutoLock lock(gPSMutex);
+    PS::AutoLock lock(gPSMutex);
     includeDynamicString = !gPS->FeaturePrivacy(lock);
   }
 
   volatile js::ProfileEntry *pseudoFrames = pseudoStack->mStack;
   uint32_t pseudoCount = pseudoStack->stackSize();
 
   for (uint32_t i = 0; i < pseudoCount; i++) {
     const char* label = pseudoFrames[i].label();
@@ -2939,17 +2942,17 @@ profiler_get_backtrace_noalloc(char *out
       output += labelLength;
     }
     *output++ = '\0';
     *output = '\0';
   }
 }
 
 static void
-locked_profiler_add_marker(PSLockRef aLock, const char* aMarker,
+locked_profiler_add_marker(PS::LockRef aLock, const char* aMarker,
                            ProfilerMarkerPayload* aPayload)
 {
   // This function runs both on and off the main thread.
 
   MOZ_RELEASE_ASSERT(gPS);
   MOZ_RELEASE_ASSERT(gPS->IsActive(aLock) && !gPS->FeaturePrivacy(aLock));
 
   // aPayload must be freed if we return early.
@@ -2958,28 +2961,28 @@ locked_profiler_add_marker(PSLockRef aLo
   PseudoStack *stack = tlsPseudoStack.get();
   if (!stack) {
     return;
   }
 
   mozilla::TimeStamp origin = (payload && !payload->GetStartTime().IsNull())
                             ? payload->GetStartTime()
                             : mozilla::TimeStamp::Now();
-  mozilla::TimeDuration delta = origin - gPS->ProcessStartTime(aLock);
+  mozilla::TimeDuration delta = origin - gPS->StartTime(aLock);
   stack->addMarker(aMarker, payload.release(), delta.ToMilliseconds());
 }
 
 void
 profiler_add_marker(const char* aMarker, ProfilerMarkerPayload* aPayload)
 {
   // This function runs both on and off the main thread.
 
   MOZ_RELEASE_ASSERT(gPS);
 
-  PSAutoLock lock(gPSMutex);
+  PS::AutoLock lock(gPSMutex);
 
   // aPayload must be freed if we return early.
   mozilla::UniquePtr<ProfilerMarkerPayload> payload(aPayload);
 
   if (!gPS->IsActive(lock) || gPS->FeaturePrivacy(lock)) {
     return;
   }
 
@@ -2989,17 +2992,17 @@ profiler_add_marker(const char* aMarker,
 void
 profiler_tracing(const char* aCategory, const char* aInfo,
                  TracingKind aKind)
 {
   // This function runs both on and off the main thread.
 
   MOZ_RELEASE_ASSERT(gPS);
 
-  PSAutoLock lock(gPSMutex);
+  PS::AutoLock lock(gPSMutex);
 
   if (!gPS->IsActive(lock) || gPS->FeaturePrivacy(lock)) {
     return;
   }
 
   auto marker = new ProfilerMarkerTracing(aCategory, aKind);
   locked_profiler_add_marker(lock, aInfo, marker);
 }
@@ -3007,17 +3010,17 @@ profiler_tracing(const char* aCategory, 
 void
 profiler_tracing(const char* aCategory, const char* aInfo,
                  UniqueProfilerBacktrace aCause, TracingKind aKind)
 {
   // This function runs both on and off the main thread.
 
   MOZ_RELEASE_ASSERT(gPS);
 
-  PSAutoLock lock(gPSMutex);
+  PS::AutoLock lock(gPSMutex);
 
   if (!gPS->IsActive(lock) || gPS->FeaturePrivacy(lock)) {
     return;
   }
 
   auto marker =
     new ProfilerMarkerTracing(aCategory, aKind, mozilla::Move(aCause));
   locked_profiler_add_marker(lock, aInfo, marker);
@@ -3060,27 +3063,26 @@ profiler_clear_js_context()
 
   if (!stack->mContext) {
     return;
   }
 
   // On JS shut down, flush the current buffer as stringifying JIT samples
   // requires a live JSContext.
 
-  PSAutoLock lock(gPSMutex);
+  PS::AutoLock lock(gPSMutex);
 
   if (gPS->IsActive(lock)) {
     gPS->SetIsPaused(lock, true);
 
     // Flush this thread's ThreadInfo, if it is being profiled.
     ThreadInfo* info = FindLiveThreadInfo(lock);
     MOZ_RELEASE_ASSERT(info);
     if (info->IsBeingProfiled()) {
-      info->FlushSamplesAndMarkers(gPS->Buffer(lock),
-                                   gPS->ProcessStartTime(lock));
+      info->FlushSamplesAndMarkers(gPS->Buffer(lock), gPS->StartTime(lock));
     }
 
     gPS->SetIsPaused(lock, false);
   }
 
   // We don't call stack->stopJSSampling() here; there's no point doing
   // that for a JS thread that is in the process of disappearing.
 
--- a/tools/profiler/public/GeckoProfiler.h
+++ b/tools/profiler/public/GeckoProfiler.h
@@ -284,18 +284,18 @@ PROFILER_FUNC_VOID(profiler_thread_sleep
 PROFILER_FUNC_VOID(profiler_thread_wake())
 PROFILER_FUNC(bool profiler_thread_is_sleeping(), false)
 
 // Call 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.
 PROFILER_FUNC_VOID(profiler_js_interrupt_callback())
 
-// The number of milliseconds since the process started. Operates the same
-// whether the profiler is active or inactive.
+// Gets the time since the last profiler_init() or profiler_start() call.
+// Operates the same whether the profiler is active or inactive.
 PROFILER_FUNC(double profiler_time(), 0)
 
 PROFILER_FUNC_VOID(profiler_log(const char *str))
 
 // End of the functions defined whether the profiler is enabled or not.
 
 #if defined(MOZ_GECKO_PROFILER)
 
@@ -324,16 +324,24 @@ class ProfilerMarkerPayload;
 // Non-owning PseudoStack references are also temporarily used by
 // profiler_call_{enter,exit}() pairs. RAII classes ensure these calls are
 // balanced, and they occur on the thread itself, which means they are
 // necessarily bounded by the lifetime of the thread, which ensures they can't
 // be used after the PseudoStack is destroyed.
 //
 extern MOZ_THREAD_LOCAL(PseudoStack*) tlsPseudoStack;
 
+class ProfilerState;
+
+// The core profiler state. Null at process startup, it is set to a non-null
+// value in profiler_init() and stays that way until profiler_shutdown() is
+// called. Therefore it can be checked to determine if the profiler has been
+// initialized but not yet shut down.
+extern ProfilerState* gPS;
+
 #ifndef SAMPLE_FUNCTION_NAME
 # if defined(__GNUC__) || defined(_MSC_VER)
 #  define SAMPLE_FUNCTION_NAME __FUNCTION__
 # else
 #  define SAMPLE_FUNCTION_NAME __func__  // defined in C99, supported in various C++ compilers. Just raw function name.
 # endif
 #endif
 
@@ -342,32 +350,36 @@ extern MOZ_THREAD_LOCAL(PseudoStack*) tl
 static inline void*
 profiler_call_enter(const char* aInfo,
                     js::ProfileEntry::Category aCategory,
                     void *aFrameAddress, bool aCopy, uint32_t line,
                     const char* aDynamicString = nullptr)
 {
   // This function runs both on and off the main thread.
 
+  MOZ_RELEASE_ASSERT(gPS);
+
   PseudoStack* stack = tlsPseudoStack.get();
   if (!stack) {
     return stack;
   }
   stack->push(aInfo, aCategory, aFrameAddress, aCopy, line, aDynamicString);
 
   // The handle is meant to support future changes but for now it is simply
   // used to avoid having to call tlsPseudoStack.get() in profiler_call_exit().
   return stack;
 }
 
 static inline void
 profiler_call_exit(void* aHandle)
 {
   // This function runs both on and off the main thread.
 
+  MOZ_RELEASE_ASSERT(gPS);
+
   if (!aHandle) {
     return;
   }
 
   PseudoStack *stack = (PseudoStack*)aHandle;
   stack->pop();
 }
 
@@ -481,16 +493,18 @@ private:
 
 } // namespace mozilla
 
 inline PseudoStack*
 profiler_get_pseudo_stack(void)
 {
   // This function runs both on and off the main thread.
 
+  MOZ_RELEASE_ASSERT(gPS);
+
   return tlsPseudoStack.get();
 }
 
 void profiler_set_js_context(JSContext* aCx);
 void profiler_clear_js_context();
 
 class GeckoProfilerReporter final : public nsIMemoryReporter
 {