diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /tools/profiler/core/RegisteredThread.cpp | |
parent | Initial commit. (diff) | |
download | firefox-upstream.tar.xz firefox-upstream.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tools/profiler/core/RegisteredThread.cpp')
-rw-r--r-- | tools/profiler/core/RegisteredThread.cpp | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/tools/profiler/core/RegisteredThread.cpp b/tools/profiler/core/RegisteredThread.cpp new file mode 100644 index 0000000000..ffbeb782da --- /dev/null +++ b/tools/profiler/core/RegisteredThread.cpp @@ -0,0 +1,129 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "RegisteredThread.h" + +#include "js/AllocationRecording.h" +#include "js/ProfilingStack.h" +#include "js/TraceLoggerAPI.h" + +RacyRegisteredThread::RacyRegisteredThread(int aThreadId) + : mProfilingStackOwner( + mozilla::MakeNotNull<RefPtr<mozilla::ProfilingStackOwner>>()), + mThreadId(aThreadId), + mSleep(AWAKE), + mIsBeingProfiled(false) { + MOZ_COUNT_CTOR(RacyRegisteredThread); +} + +RegisteredThread::RegisteredThread(ThreadInfo* aInfo, nsIThread* aThread, + void* aStackTop) + : mRacyRegisteredThread(aInfo->ThreadId()), + mPlatformData(AllocPlatformData(aInfo->ThreadId())), + mStackTop(aStackTop), + mThreadInfo(aInfo), + mThread(aThread), + mContext(nullptr), + mJSSampling(INACTIVE), + mJSFlags(0) { + MOZ_COUNT_CTOR(RegisteredThread); + + // NOTE: aThread can be null for the first thread, before the ThreadManager + // is initialized. + + // 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 +} + +RegisteredThread::~RegisteredThread() { MOZ_COUNT_DTOR(RegisteredThread); } + +size_t RegisteredThread::SizeOfIncludingThis( + mozilla::MallocSizeOf aMallocSizeOf) const { + size_t n = aMallocSizeOf(this); + + // Measurement of the following members may be added later if DMD finds it + // is worthwhile: + // - mPlatformData + // + // The following members are not measured: + // - mThreadInfo: because it is non-owning + + return n; +} + +void RegisteredThread::GetRunningEventDelay(const mozilla::TimeStamp& aNow, + mozilla::TimeDuration& aDelay, + mozilla::TimeDuration& aRunning) { + if (mThread) { // can be null right at the start of a process + mozilla::TimeStamp start; + mThread->GetRunningEventDelay(&aDelay, &start); + if (!start.IsNull()) { + // Note: the timestamp used here will be from when we started to + // suspend and sample the thread; which is also the timestamp + // associated with the sample. + aRunning = aNow - start; + return; + } + } + aDelay = mozilla::TimeDuration(); + aRunning = mozilla::TimeDuration(); +} + +void RegisteredThread::SetJSContext(JSContext* aContext) { + // This function runs on-thread. + + MOZ_ASSERT(aContext && !mContext); + + mContext = aContext; + + // We give the JS engine a non-owning reference to the ProfilingStack. It's + // important that the JS engine doesn't touch this once the thread dies. + js::SetContextProfilingStack(aContext, + &RacyRegisteredThread().ProfilingStack()); +} + +void RegisteredThread::PollJSSampling() { + // This function runs on-thread. + + // We can't start/stop profiling until we have the thread's JSContext. + if (mContext) { + // It is possible for mJSSampling to go through the following sequences. + // + // - INACTIVE, ACTIVE_REQUESTED, INACTIVE_REQUESTED, INACTIVE + // + // - 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); + if (JSTracerEnabled()) { + JS::StartTraceLogger(mContext); + } + if (JSAllocationsEnabled()) { + // TODO - This probability should not be hardcoded. See Bug 1547284. + JS::EnableRecordingAllocations(mContext, + profiler_add_js_allocation_marker, 0.01); + } + js::RegisterContextProfilingEventMarker(mContext, profiler_add_js_marker); + + } else if (mJSSampling == INACTIVE_REQUESTED) { + mJSSampling = INACTIVE; + js::EnableContextProfilingStack(mContext, false); + if (JSTracerEnabled()) { + JS::StopTraceLogger(mContext); + } + if (JSAllocationsEnabled()) { + JS::DisableRecordingAllocations(mContext); + } + } + } +} |