tor-browser

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

commit 326b02025ec685428465a45cf71972225f9ebdea
parent a8dfb8b4c814b294b02f737575a15810107c60c9
Author: Tooru Fujisawa <arai_a@mac.com>
Date:   Tue,  2 Dec 2025 08:27:53 +0000

Bug 1956867 - Take a snapshot of the load time before sorting the cached stencils. r=mccr8

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

Diffstat:
Mjs/xpconnect/loader/ScriptPreloader.cpp | 42+++++++++++++++++++++++++++++++++++++-----
Mjs/xpconnect/loader/ScriptPreloader.h | 19++++---------------
2 files changed, 41 insertions(+), 20 deletions(-)

diff --git a/js/xpconnect/loader/ScriptPreloader.cpp b/js/xpconnect/loader/ScriptPreloader.cpp @@ -675,6 +675,36 @@ void ScriptPreloader::PrepareCacheWrite() { PrepareCacheWriteInternal(); } +// A struct to hold reference to a CachedStencil and the snapshot of the +// CachedStencil::mLoadTime field. +// CachedStencil::mLoadTime field can be modified concurrently, and we need +// to create a snapshot, in order to sort scripts. +struct CachedStencilRefAndTime { + using CachedStencil = ScriptPreloader::CachedStencil; + CachedStencil* mStencil; + TimeStamp mLoadTime; + + explicit CachedStencilRefAndTime(CachedStencil* aStencil) + : mStencil(aStencil), mLoadTime(aStencil->mLoadTime) {} + + // For use with nsTArray::Sort. + // + // Orders scripts by script load time, so that scripts which are needed + // earlier are stored earlier, and scripts needed at approximately the + // same time are stored approximately contiguously. + struct Comparator { + bool Equals(const CachedStencilRefAndTime& a, + const CachedStencilRefAndTime& b) const { + return a.mLoadTime == b.mLoadTime; + } + + bool LessThan(const CachedStencilRefAndTime& a, + const CachedStencilRefAndTime& b) const { + return a.mLoadTime < b.mLoadTime; + } + }; +} JS_HAZ_NON_GC_POINTER; + // Writes out a script cache file for the scripts accessed during early // startup in this session. The cache file is a little-endian binary file with // the following format: @@ -727,19 +757,20 @@ Result<Ok, nsresult> ScriptPreloader::WriteCache() { mMonitor.AssertNotCurrentThreadOwns(); MonitorAutoLock mal(mMonitor); - nsTArray<CachedStencil*> scripts; + nsTArray<CachedStencilRefAndTime> scriptRefs; for (auto& script : IterHash(mScripts, Match<ScriptStatus::Saved>())) { - scripts.AppendElement(script); + scriptRefs.AppendElement(CachedStencilRefAndTime(script)); } // Sort scripts by load time, with async loaded scripts before sync scripts. // Since async scripts are always loaded immediately at startup, it helps to // have them stored contiguously. - scripts.Sort(CachedStencil::Comparator()); + scriptRefs.Sort(CachedStencilRefAndTime::Comparator()); OutputBuffer buf; size_t offset = 0; - for (auto script : scripts) { + for (auto& scriptRef : scriptRefs) { + auto* script = scriptRef.mStencil; script->mOffset = offset; MOZ_DIAGNOSTIC_ASSERT( JS::IsTranscodingBytecodeOffsetAligned(script->mOffset)); @@ -769,7 +800,8 @@ Result<Ok, nsresult> ScriptPreloader::WriteCache() { written += padding; } - for (auto script : scripts) { + for (auto& scriptRef : scriptRefs) { + auto* script = scriptRef.mStencil; MOZ_DIAGNOSTIC_ASSERT(JS::IsTranscodingBytecodeOffsetAligned(written)); MOZ_TRY(Write(fd, script->Range().begin().get(), script->mSize)); diff --git a/js/xpconnect/loader/ScriptPreloader.h b/js/xpconnect/loader/ScriptPreloader.h @@ -66,6 +66,8 @@ struct Matcher { using namespace mozilla::loader; +struct CachedStencilRefAndTime; + class ScriptPreloader : public nsIObserver, public nsIMemoryReporter, public nsIRunnable, @@ -215,21 +217,6 @@ class ScriptPreloader : public nsIObserver, : ScriptStatus::Saved; } - // For use with nsTArray::Sort. - // - // Orders scripts by script load time, so that scripts which are needed - // earlier are stored earlier, and scripts needed at approximately the - // same time are stored approximately contiguously. - struct Comparator { - bool Equals(const CachedStencil* a, const CachedStencil* b) const { - return a->mLoadTime == b->mLoadTime; - } - - bool LessThan(const CachedStencil* a, const CachedStencil* b) const { - return a->mLoadTime < b->mLoadTime; - } - }; - struct StatusMatcher final : public Matcher<CachedStencil*> { explicit StatusMatcher(ScriptStatus status) : mStatus(status) {} @@ -387,6 +374,8 @@ class ScriptPreloader : public nsIObserver, MaybeOneOf<JS::TranscodeBuffer, nsTArray<uint8_t>> mXDRData; } JS_HAZ_NON_GC_POINTER; + friend struct CachedStencilRefAndTime; + template <ScriptStatus status> static Matcher<CachedStencil*>* Match() { static CachedStencil::StatusMatcher matcher{status};