Bug 1130367 - Ensure profiler stack sampling is disabled when spsProfiler is disabled. r=shu
authorKannan Vijayan <kvijayan@mozilla.com>
Mon, 02 Mar 2015 17:46:13 -0500
changeset 231512 44efa0956b5315e9c92db79478f486d41dc64275
parent 231511 bc72e91be73809e4ee48e5f455e0d0c2a1e6eb9c
child 231513 cde1ceac078801a2c55de4574de2396f8aac4e31
push id28353
push usercbook@mozilla.com
push dateTue, 03 Mar 2015 12:54:59 +0000
treeherdermozilla-central@985070813323 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersshu
bugs1130367
milestone39.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 1130367 - Ensure profiler stack sampling is disabled when spsProfiler is disabled. r=shu
js/public/ProfilingFrameIterator.h
js/src/builtin/TestingFunctions.cpp
js/src/vm/Runtime.cpp
js/src/vm/SPSProfiler.cpp
js/src/vm/Stack.cpp
tools/profiler/TableTicker.cpp
--- a/js/public/ProfilingFrameIterator.h
+++ b/js/public/ProfilingFrameIterator.h
@@ -118,16 +118,19 @@ class JS_PUBLIC_API(ProfilingFrameIterat
     void iteratorConstruct();
     void iteratorDestroy();
     bool iteratorDone();
 
     bool isAsmJS() const;
     bool isJit() const;
 };
 
+JS_FRIEND_API(bool)
+IsProfilingEnabledForRuntime(JSRuntime *runtime);
+
 /**
  * After each sample run, this method should be called with the latest sample
  * buffer generation, and the lapCount.  It will update corresponding fields on
  * JSRuntime.
  *
  * See fields |profilerSampleBufferGen|, |profilerSampleBufferLapCount| on
  * JSRuntime for documentation about what these values are used for.
  */
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -1249,18 +1249,21 @@ DisableSPSProfiling(JSContext *cx, unsig
 }
 
 static bool
 ReadSPSProfilingStack(JSContext *cx, unsigned argc, jsval *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     args.rval().setUndefined();
 
-    if (!cx->runtime()->spsProfiler.enabled())
+    // Return boolean 'false' if profiler is not enabled.
+    if (!cx->runtime()->spsProfiler.enabled()) {
         args.rval().setBoolean(false);
+        return true;
+    }
 
     // Array holding physical jit stack frames.
     RootedObject stack(cx, NewDenseEmptyArray(cx));
     if (!stack)
         return false;
 
     RootedObject inlineStack(cx);
     RootedObject inlineFrameInfo(cx);
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -843,8 +843,14 @@ js::AssertCurrentThreadCanLock(RuntimeLo
 
 JS_FRIEND_API(void)
 JS::UpdateJSRuntimeProfilerSampleBufferGen(JSRuntime *runtime, uint32_t generation,
                                            uint32_t lapCount)
 {
     runtime->setProfilerSampleBufferGen(generation);
     runtime->updateProfilerSampleBufferLapCount(lapCount);
 }
+
+JS_FRIEND_API(bool)
+JS::IsProfilingEnabledForRuntime(JSRuntime *runtime)
+{
+    return runtime->spsProfiler.enabled();
+}
--- a/js/src/vm/SPSProfiler.cpp
+++ b/js/src/vm/SPSProfiler.cpp
@@ -82,16 +82,22 @@ SPSProfiler::enable(bool enabled)
         return;
 
     /*
      * Ensure all future generated code will be instrumented, or that all
      * currently instrumented code is discarded
      */
     ReleaseAllJITCode(rt->defaultFreeOp());
 
+    // Ensure that lastProfilingFrame is null before 'enabled' becomes true.
+    if (rt->jitActivation) {
+        rt->jitActivation->setLastProfilingFrame(nullptr);
+        rt->jitActivation->setLastProfilingCallSite(nullptr);
+    }
+
     enabled_ = enabled;
 
     /* Toggle SPS-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);
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -1713,27 +1713,30 @@ ActivationIterator::settle()
     while (!done() && activation_->isJit() && !activation_->asJit()->isActive())
         activation_ = activation_->prev();
 }
 
 JS::ProfilingFrameIterator::ProfilingFrameIterator(JSRuntime *rt, const RegisterState &state,
                                                    uint32_t sampleBufferGen)
   : rt_(rt),
     sampleBufferGen_(sampleBufferGen),
-    activation_(rt->profilingActivation()),
+    activation_(nullptr),
     savedPrevJitTop_(nullptr)
 {
-    if (!activation_)
+    if (!rt->spsProfiler.enabled())
+        MOZ_CRASH("ProfilingFrameIterator called when spsProfiler not enabled for runtime.");
+
+    if (!rt->profilingActivation())
         return;
 
     // If profiler sampling is not enabled, skip.
-    if (!rt_->isProfilerSamplingEnabled()) {
-        activation_ = nullptr;
+    if (!rt_->isProfilerSamplingEnabled())
         return;
-    }
+
+    activation_ = rt->profilingActivation();
 
     MOZ_ASSERT(activation_->isProfiling());
 
     static_assert(sizeof(AsmJSProfilingFrameIterator) <= StorageSpace &&
                   sizeof(jit::JitProfilingFrameIterator) <= StorageSpace,
                   "Need to increase storage");
 
     iteratorConstruct(state);
--- a/tools/profiler/TableTicker.cpp
+++ b/tools/profiler/TableTicker.cpp
@@ -484,17 +484,18 @@ void mergeStacksIntoProfile(ThreadProfil
 
   // 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 entries to aProfile.
 
   uint32_t startBufferGen = aProfile.bufferGeneration();
   uint32_t jsCount = 0;
   JS::ProfilingFrameIterator::Frame jsFrames[1000];
-  {
+  // Only walk jit stack if profiling frame iterator is turned on.
+  if (JS::IsProfilingEnabledForRuntime(pseudoStack->mRuntime)) {
     AutoWalkJSStack autoWalkJSStack;
     const uint32_t maxFrames = mozilla::ArrayLength(jsFrames);
 
     if (aSample && pseudoStack->mRuntime && autoWalkJSStack.walkAllowed) {
       JS::ProfilingFrameIterator::RegisterState registerState;
       registerState.pc = aSample->pc;
       registerState.sp = aSample->sp;
 #ifdef ENABLE_ARM_LR_SAVING