tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 9681c29277f9bd20aded112340cd1615d65dbb31
parent e36f6ef970230e50cc02e765b83ee25df61ab104
Author: Nazım Can Altınova <canaltinova@gmail.com>
Date:   Tue, 21 Oct 2025 23:59:07 +0000

Bug 1979114 - Collect the JS sources during profile serialization r=mstange,profiler-reviewers

Finally, we implement the place where we actually request the JS sources
from the JS engine to the profiler land.

We find the JSContext for the main thread just for being able to access
the GeckoProfilerRuntime in the JS engine. Sources are shared across
threads and JSContexts. Otherwise the JSContext is not used for other
things.

Differential Revision: https://phabricator.services.mozilla.com/D259267

Diffstat:
Mtools/profiler/core/platform.cpp | 47+++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 45 insertions(+), 2 deletions(-)

diff --git a/tools/profiler/core/platform.cpp b/tools/profiler/core/platform.cpp @@ -49,6 +49,9 @@ #include "mozilla/Maybe.h" #include "mozilla/MozPromise.h" #include "mozilla/Perfetto.h" +#include "nsID.h" +#include "nsIDUtils.h" +#include "nsString.h" #include "nsCExternalHandlerService.h" #include "nsCOMPtr.h" #include "nsDebug.h" @@ -1597,6 +1600,44 @@ class ActivePS { return array; } + // Collect JS sources from the main thread, since script source storage is + // shared between all threads. + static nsTArray<mozilla::JSSourceEntry> GatherJSSources(PSLockRef aLock) { + nsTArray<mozilla::JSSourceEntry> jsSourceEntries; + if (!ProfilerFeature::HasJSSources(ActivePS::Features(aLock))) { + return jsSourceEntries; + } + + ThreadRegistry::LockedRegistry lockedRegistry; + ActivePS::ProfiledThreadList threads = + ActivePS::ProfiledThreads(lockedRegistry, aLock); + + // Get the JS context of the main thread. We don't need to get the + // JSContext of others because the script source storage is shared between + // threads. + auto* mainThread = + std::find_if(threads.begin(), threads.end(), [](const auto& thread) { + return thread.mProfiledThreadData->Info().IsMainThread(); + }); + + if (mainThread == threads.end() || !mainThread->mJSContext) { + return jsSourceEntries; + } + JSContext* jsContext = mainThread->mJSContext; + + js::ProfilerJSSources threadSources = + js::GetProfilerScriptSources(JS_GetRuntime(jsContext)); + + // Generate UUIDs and build mappings for each source + for (ProfilerJSSourceData& sourceData : threadSources) { + // Generate UUID for this source and store it in the global array. + jsSourceEntries.AppendElement(JSSourceEntry( + NSID_TrimBracketsASCII(nsID::GenerateUUID()), std::move(sourceData))); + } + + return jsSourceEntries; + } + static ProfiledThreadData* AddLiveProfiledThread( PSLockRef, UniquePtr<ProfiledThreadData>&& aProfiledThreadData) { MOZ_ASSERT(sInstance); @@ -3828,8 +3869,10 @@ locked_profiler_stream_json_for_this_process( } SLOW_DOWN_FOR_TESTING(); - // FIXME: Build the JS sources - nsTArray<mozilla::JSSourceEntry> jsSourceEntries; + // Collect JS sources from the main thread, since script source storage is + // shared between all threads. + nsTArray<mozilla::JSSourceEntry> jsSourceEntries = + ActivePS::GatherJSSources(aLock); // Lists the samples for each thread profile aWriter.StartArrayProperty("threads");