Bug 1439014 - Add a profiler feature to enable JIT optimization tracking. r=njn,sfink
☠☠ backed out by 4d09e6d03883 ☠ ☠
authorMarkus Stange <mstange@themasta.com>
Sat, 17 Feb 2018 19:38:14 -0500
changeset 466069 84c9b5ab7de94b7acccf1bfb1ad9821cc9015efe
parent 466068 b18052510dcd5f5427601ed0f0dce42d3ce9e1a4
child 466070 226c8c740c34e5e53be3282196032504a9665c2e
push id1728
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:12:27 +0000
treeherdermozilla-release@c296fde26f5f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnjn, sfink
bugs1439014
milestone61.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 1439014 - Add a profiler feature to enable JIT optimization tracking. r=njn,sfink MozReview-Commit-ID: LDxiLVp7e9v
browser/components/extensions/schemas/geckoProfiler.json
js/src/jsapi.cpp
js/src/jsapi.h
tools/profiler/core/RegisteredThread.cpp
tools/profiler/core/RegisteredThread.h
tools/profiler/core/platform.cpp
tools/profiler/public/GeckoProfiler.h
--- a/browser/components/extensions/schemas/geckoProfiler.json
+++ b/browser/components/extensions/schemas/geckoProfiler.json
@@ -27,17 +27,18 @@
           "js",
           "leaf",
           "mainthreadio",
           "memory",
           "privacy",
           "restyle",
           "stackwalk",
           "tasktracer",
-          "threads"
+          "threads",
+          "trackopts"
         ]
       }
     ],
     "functions": [
       {
        "name": "start",
        "type": "function",
        "description": "Starts the profiler with the specified settings.",
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -7255,16 +7255,19 @@ JS_SetGlobalJitCompilerOption(JSContext*
         break;
       case JSJITCOMPILER_JUMP_THRESHOLD:
         if (value == uint32_t(-1)) {
             jit::DefaultJitOptions defaultValues;
             value = defaultValues.jumpThreshold;
         }
         jit::JitOptions.jumpThreshold = value;
         break;
+      case JSJITCOMPILER_TRACK_OPTIMIZATIONS:
+        jit::JitOptions.disableOptimizationTracking = !value;
+        break;
       case JSJITCOMPILER_SPECTRE_INDEX_MASKING:
         jit::JitOptions.spectreIndexMasking = !!value;
         break;
       case JSJITCOMPILER_SPECTRE_OBJECT_MITIGATIONS_BARRIERS:
         jit::JitOptions.spectreObjectMitigationsBarriers = !!value;
         break;
       case JSJITCOMPILER_SPECTRE_OBJECT_MITIGATIONS_MISC:
         jit::JitOptions.spectreObjectMitigationsMisc = !!value;
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -5862,16 +5862,17 @@ JS_SetOffthreadIonCompilationEnabled(JSC
     Register(ION_FORCE_IC, "ion.forceinlineCaches")                         \
     Register(ION_ENABLE, "ion.enable")                                      \
     Register(ION_INTERRUPT_WITHOUT_SIGNAL, "ion.interrupt-without-signals") \
     Register(ION_CHECK_RANGE_ANALYSIS, "ion.check-range-analysis")          \
     Register(BASELINE_ENABLE, "baseline.enable")                            \
     Register(OFFTHREAD_COMPILATION_ENABLE, "offthread-compilation.enable")  \
     Register(FULL_DEBUG_CHECKS, "jit.full-debug-checks")                    \
     Register(JUMP_THRESHOLD, "jump-threshold")                              \
+    Register(TRACK_OPTIMIZATIONS, "jit.track-optimizations")                \
     Register(SIMULATOR_ALWAYS_INTERRUPT, "simulator.always-interrupt")      \
     Register(SPECTRE_INDEX_MASKING, "spectre.index-masking")                \
     Register(SPECTRE_OBJECT_MITIGATIONS_BARRIERS, "spectre.object-mitigations.barriers") \
     Register(SPECTRE_OBJECT_MITIGATIONS_MISC, "spectre.object-mitigations.misc") \
     Register(SPECTRE_STRING_MITIGATIONS, "spectre.string-mitigations")      \
     Register(SPECTRE_VALUE_MASKING, "spectre.value-masking")                \
     Register(SPECTRE_JIT_TO_CXX_CALLS, "spectre.jit-to-C++-calls")          \
     Register(ASMJS_ATOMICS_ENABLE, "asmjs.atomics.enable")                  \
--- a/tools/profiler/core/RegisteredThread.cpp
+++ b/tools/profiler/core/RegisteredThread.cpp
@@ -10,16 +10,17 @@ RegisteredThread::RegisteredThread(Threa
                                    void* aStackTop)
   : mRacyRegisteredThread(aInfo->ThreadId())
   , mPlatformData(AllocPlatformData(aInfo->ThreadId()))
   , mStackTop(aStackTop)
   , mThreadInfo(aInfo)
   , mThread(aThread)
   , mContext(nullptr)
   , mJSSampling(INACTIVE)
+  , mJSTrackOptimizations(false)
 {
   MOZ_COUNT_CTOR(RegisteredThread);
 
   // 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
--- a/tools/profiler/core/RegisteredThread.h
+++ b/tools/profiler/core/RegisteredThread.h
@@ -192,23 +192,24 @@ public:
   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()
+  void StartJSSampling(bool aTrackOptimizations)
   {
     // This function runs on-thread or off-thread.
 
     MOZ_RELEASE_ASSERT(mJSSampling == INACTIVE ||
                        mJSSampling == INACTIVE_REQUESTED);
     mJSSampling = ACTIVE_REQUESTED;
+    mJSTrackOptimizations = aTrackOptimizations;
   }
 
   // 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.
 
@@ -231,16 +232,18 @@ public:
       // - 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,
+                                      mJSTrackOptimizations);
         js::RegisterContextProfilingEventMarker(mContext, profiler_add_marker);
 
       } else if (mJSSampling == INACTIVE_REQUESTED) {
         mJSSampling = INACTIVE;
         js::EnableContextProfilingStack(mContext, false);
       }
     }
   }
@@ -299,11 +302,13 @@ private:
   // to actually happen.
   //
   enum {
     INACTIVE = 0,
     ACTIVE_REQUESTED = 1,
     ACTIVE = 2,
     INACTIVE_REQUESTED = 3,
   } mJSSampling;
+
+  bool mJSTrackOptimizations;
 };
 
 #endif  // RegisteredThread_h
--- a/tools/profiler/core/platform.cpp
+++ b/tools/profiler/core/platform.cpp
@@ -2248,17 +2248,18 @@ locked_register_thread(PSLockRef aLock, 
     nsCOMPtr<nsIEventTarget> eventTarget = registeredThread->GetEventTarget();
     ProfiledThreadData* profiledThreadData =
       ActivePS::AddLiveProfiledThread(aLock, registeredThread.get(),
         MakeUnique<ProfiledThreadData>(info, eventTarget));
 
     if (ActivePS::FeatureJS(aLock)) {
       // This StartJSSampling() call is on-thread, so we can poll manually to
       // start JS sampling immediately.
-      registeredThread->StartJSSampling();
+      registeredThread->StartJSSampling(
+        ActivePS::FeatureTrackOptimizations(aLock));
       registeredThread->PollJSSampling();
       if (registeredThread->GetJSContext()) {
         profiledThreadData->NotifyReceivedJSContext(ActivePS::Buffer(aLock).mRangeEnd);
       }
     }
   }
 
   CorePS::AppendRegisteredThread(aLock, Move(registeredThread));
@@ -2847,17 +2848,18 @@ locked_profiler_start(PSLockRef aLock, u
     RefPtr<ThreadInfo> info = registeredThread->Info();
 
     if (ActivePS::ShouldProfileThread(aLock, info)) {
       nsCOMPtr<nsIEventTarget> eventTarget = registeredThread->GetEventTarget();
       ProfiledThreadData* profiledThreadData =
         ActivePS::AddLiveProfiledThread(aLock, registeredThread.get(),
           MakeUnique<ProfiledThreadData>(info, eventTarget));
       if (ActivePS::FeatureJS(aLock)) {
-        registeredThread->StartJSSampling();
+        registeredThread->StartJSSampling(
+          ActivePS::FeatureTrackOptimizations(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.
@@ -3475,17 +3477,18 @@ profiler_clear_js_context()
       // 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();
+      registeredThread->StartJSSampling(
+        ActivePS::FeatureTrackOptimizations(lock));
       return;
     }
   }
 
   registeredThread->ClearJSContext();
 }
 
 int
--- a/tools/profiler/public/GeckoProfiler.h
+++ b/tools/profiler/public/GeckoProfiler.h
@@ -123,17 +123,20 @@ class TimeStamp;
   \
   /* Walk the C++ stack. Not available on all platforms. */ \
   macro(7, "stackwalk", StackWalk) \
   \
   /* Start profiling with feature TaskTracer. */ \
   macro(8, "tasktracer", TaskTracer) \
   \
   /* Profile the registered secondary threads. */ \
-  macro(9, "threads", Threads)
+  macro(9, "threads", Threads) \
+  \
+  /* Have the JavaScript engine track JIT optimizations. */ \
+  macro(10, "trackopts", TrackOptimizations)
 
 struct ProfilerFeature
 {
   #define DECLARE(n_, str_, Name_) \
     static const uint32_t Name_ = (1u << n_); \
     static bool Has##Name_(uint32_t aFeatures) { return aFeatures & Name_; } \
     static void Set##Name_(uint32_t& aFeatures) { aFeatures |= Name_; } \
     static void Clear##Name_(uint32_t& aFeatures) { aFeatures &= ~Name_; }