Bug 785440 - Move profiler_is_active() implementation (and RacyFeatures) into GeckoProfiler.h. r?njn draft
authorMarkus Stange <mstange@themasta.com>
Wed, 02 Aug 2017 14:39:55 -0400
changeset 752760 b0f22ad41945e727e3e137a8a8509d0be5840b6e
parent 752759 312763fe4f7e91e1a6bb7366389186f68950e9c1
child 752761 4ff98962d0b9c6e2fed035d36b918d306dca7717
push id98367
push userbmo:mstange@themasta.com
push dateThu, 08 Feb 2018 21:45:52 +0000
reviewersnjn
bugs785440
milestone60.0a1
Bug 785440 - Move profiler_is_active() implementation (and RacyFeatures) into GeckoProfiler.h. r?njn MozReview-Commit-ID: D8y5RK2t6N4
tools/profiler/core/platform.cpp
tools/profiler/public/GeckoProfiler.h
--- a/tools/profiler/core/platform.cpp
+++ b/tools/profiler/core/platform.cpp
@@ -146,16 +146,17 @@
 # define VALGRIND_MAKE_MEM_DEFINED(_addr,_len)   ((void)0)
 #endif
 
 #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();
@@ -579,60 +580,16 @@ 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;
 
-// The preferred way to check profiler activeness and features is via
-// ActivePS(). However, that requires locking gPSMutex. There are some hot
-// operations where absolute precision isn't required, so we duplicate the
-// activeness/feature state in a lock-free manner in this class.
-class RacyFeatures
-{
-public:
-  static void SetActive(uint32_t aFeatures)
-  {
-    sActiveAndFeatures = Active | aFeatures;
-  }
-
-  static void SetInactive() { sActiveAndFeatures = 0; }
-
-  static bool IsActive() { return uint32_t(sActiveAndFeatures) & Active; }
-
-  static bool IsActiveWithFeature(uint32_t aFeature)
-  {
-    uint32_t af = sActiveAndFeatures;  // copy it first
-    return (af & Active) && (af & aFeature);
-  }
-
-  static bool IsActiveWithoutPrivacy()
-  {
-    uint32_t af = sActiveAndFeatures;  // copy it first
-    return (af & Active) && !(af & ProfilerFeature::Privacy);
-  }
-
-private:
-  static const uint32_t Active = 1u << 31;
-
-  // Ensure Active doesn't overlap with any of the feature bits.
-  #define NO_OVERLAP(n_, str_, Name_) \
-    static_assert(ProfilerFeature::Name_ != Active, "bad Active value");
-
-  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.
-  static Atomic<uint32_t> sActiveAndFeatures;
-};
-
 Atomic<uint32_t> RacyFeatures::sActiveAndFeatures(0);
 
 // Each live thread has a ThreadInfo, and we store a reference to it in TLS.
 // This class encapsulates that TLS.
 class TLSInfo
 {
 public:
   static bool Init(PSLockRef)
@@ -3048,27 +3005,16 @@ profiler_feature_active(uint32_t aFeatur
   // 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);
 }
 
-bool
-profiler_is_active()
-{
-  // This function runs both on and off the main thread.
-
-  MOZ_RELEASE_ASSERT(CorePS::Exists());
-
-  // This function is hot enough that we use RacyFeatures, notActivePS.
-  return RacyFeatures::IsActive();
-}
-
 void
 profiler_register_thread(const char* aName, void* aGuessStackTop)
 {
   DEBUG_LOG("profiler_register_thread(%s)", aName);
 
   MOZ_ASSERT_IF(NS_IsMainThread(), Scheduler::IsCooperativeThread());
   MOZ_RELEASE_ASSERT(CorePS::Exists());
 
--- a/tools/profiler/public/GeckoProfiler.h
+++ b/tools/profiler/public/GeckoProfiler.h
@@ -137,16 +137,74 @@ struct ProfilerFeature
     static void Clear##Name_(uint32_t& aFeatures) { aFeatures &= ~Name_; }
 
   // Define a bitfield constant, a getter, and two setters for each feature.
   PROFILER_FOR_EACH_FEATURE(DECLARE)
 
   #undef DECLARE
 };
 
+#ifdef MOZ_GECKO_PROFILER
+namespace mozilla {
+namespace profiler {
+namespace detail {
+
+// RacyFeatures is only defined in this header file so that its methods can
+// be inlined into profiler_is_active(). Please do not use anything from the
+// detail namespace outside the profiler.
+
+// Within the profiler's code, the preferred way to check profiler activeness
+// and features is via ActivePS(). However, that requires locking gPSMutex.
+// There are some hot operations where absolute precision isn't required, so we
+// duplicate the activeness/feature state in a lock-free manner in this class.
+class RacyFeatures
+{
+public:
+  static void SetActive(uint32_t aFeatures)
+  {
+    sActiveAndFeatures = Active | aFeatures;
+  }
+
+  static void SetInactive() { sActiveAndFeatures = 0; }
+
+  static bool IsActive() { return uint32_t(sActiveAndFeatures) & Active; }
+
+  static bool IsActiveWithFeature(uint32_t aFeature)
+  {
+    uint32_t af = sActiveAndFeatures;  // copy it first
+    return (af & Active) && (af & aFeature);
+  }
+
+  static bool IsActiveWithoutPrivacy()
+  {
+    uint32_t af = sActiveAndFeatures;  // copy it first
+    return (af & Active) && !(af & ProfilerFeature::Privacy);
+  }
+
+private:
+  static const uint32_t Active = 1u << 31;
+
+  // Ensure Active doesn't overlap with any of the feature bits.
+  #define NO_OVERLAP(n_, str_, Name_) \
+    static_assert(ProfilerFeature::Name_ != Active, "bad Active value");
+
+  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.
+  static mozilla::Atomic<uint32_t> sActiveAndFeatures;
+};
+
+} // namespace detail
+} // namespace profiler
+} // namespace mozilla
+#endif
+
 //---------------------------------------------------------------------------
 // Start and stop the profiler
 //---------------------------------------------------------------------------
 
 #if !defined(ARCH_ARMV6)
 # define PROFILER_DEFAULT_ENTRIES 1000000
 #else
 # define PROFILER_DEFAULT_ENTRIES 100000
@@ -258,17 +316,24 @@ void profiler_clear_js_context();
 //   }
 //
 // where PROFILER_OPERATION is a no-op if the profiler is inactive. In this
 // case the profiler_is_active() check is just an optimization -- it prevents
 // us calling CreateExpensiveData() unnecessarily in most cases, but the
 // expensive data will end up being created but not used if another thread
 // stops the profiler between the CreateExpensiveData() and PROFILER_OPERATION
 // calls.
-bool profiler_is_active();
+inline bool profiler_is_active()
+{
+#ifdef MOZ_GECKO_PROFILER
+  return mozilla::profiler::detail::RacyFeatures::IsActive();
+#else
+  return false;
+#endif
+}
 
 // Is the profiler active and paused? Returns false if the profiler is inactive.
 bool profiler_is_paused();
 
 // Is the current thread sleeping?
 bool profiler_thread_is_sleeping();
 
 // Get all the features supported by the profiler that are accepted by