diff --git a/js/public/ProfilingFrameIterator.h b/js/public/ProfilingFrameIterator.h index bc6ab2cbf1d2..6ebcb1648ceb 100644 --- a/js/public/ProfilingFrameIterator.h +++ b/js/public/ProfilingFrameIterator.h @@ -123,6 +123,9 @@ class JS_PUBLIC_API(ProfilingFrameIterator) 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 diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index eed496e5b33e..c098822280f1 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -1254,8 +1254,11 @@ 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)); diff --git a/js/src/vm/Runtime.cpp b/js/src/vm/Runtime.cpp index b0ef4d702991..49d7d542fcc7 100644 --- a/js/src/vm/Runtime.cpp +++ b/js/src/vm/Runtime.cpp @@ -848,3 +848,9 @@ JS::UpdateJSRuntimeProfilerSampleBufferGen(JSRuntime *runtime, uint32_t generati runtime->setProfilerSampleBufferGen(generation); runtime->updateProfilerSampleBufferLapCount(lapCount); } + +JS_FRIEND_API(bool) +JS::IsProfilingEnabledForRuntime(JSRuntime *runtime) +{ + return runtime->spsProfiler.enabled(); +} diff --git a/js/src/vm/SPSProfiler.cpp b/js/src/vm/SPSProfiler.cpp index 3eaf3d6151f2..332c2c2f8fde 100644 --- a/js/src/vm/SPSProfiler.cpp +++ b/js/src/vm/SPSProfiler.cpp @@ -87,6 +87,12 @@ SPSProfiler::enable(bool enabled) */ 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. diff --git a/js/src/vm/Stack.cpp b/js/src/vm/Stack.cpp index 7ebb906841cb..2f21611744cc 100644 --- a/js/src/vm/Stack.cpp +++ b/js/src/vm/Stack.cpp @@ -1718,17 +1718,20 @@ JS::ProfilingFrameIterator::ProfilingFrameIterator(JSRuntime *rt, const Register 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()); diff --git a/tools/profiler/TableTicker.cpp b/tools/profiler/TableTicker.cpp index eac7ead99b38..b5071eeff9e7 100644 --- a/tools/profiler/TableTicker.cpp +++ b/tools/profiler/TableTicker.cpp @@ -489,7 +489,8 @@ void mergeStacksIntoProfile(ThreadProfile& aProfile, TickSample* aSample, Native 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);