tor-browser

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

commit d26b0876c94ee1d266304563731c43ba9853e721
parent 01d03687c09ed5fc7e396af1b2081d74f1e209a2
Author: Tooru Fujisawa <arai_a@mac.com>
Date:   Thu, 23 Oct 2025 04:16:56 +0000

Bug 1992341 - Part 5: Stop using the cache queue for in-memory cache. r=nbp

Given the in-memory cache no longer need any operation once it's stored into
the in-memory cache and we start collecting the delazifications, the
cache queue needs to be used only for disk cache.

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

Diffstat:
Mdom/script/ScriptLoader.cpp | 105++++++++++++++++++++++++++++++++++++++++---------------------------------------
Mdom/script/ScriptLoader.h | 20++++++++------------
2 files changed, 61 insertions(+), 64 deletions(-)

diff --git a/dom/script/ScriptLoader.cpp b/dom/script/ScriptLoader.cpp @@ -175,7 +175,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ScriptLoader) NS_IMPL_CYCLE_COLLECTION_UNLINK( mNonAsyncExternalScriptInsertedRequests, mLoadingAsyncRequests, mLoadedAsyncRequests, mOffThreadCompilingRequests, mDeferRequests, - mXSLTRequests, mParserBlockingRequest, mCachingQueue, mPreloads, + mXSLTRequests, mParserBlockingRequest, mDiskCacheQueue, mPreloads, mPendingChildLoaders, mModuleLoader, mWebExtModuleLoaders, mShadowRealmModuleLoaders) NS_IMPL_CYCLE_COLLECTION_UNLINK_END @@ -184,7 +184,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ScriptLoader) NS_IMPL_CYCLE_COLLECTION_TRAVERSE( mNonAsyncExternalScriptInsertedRequests, mLoadingAsyncRequests, mLoadedAsyncRequests, mOffThreadCompilingRequests, mDeferRequests, - mXSLTRequests, mParserBlockingRequest, mCachingQueue, mPreloads, + mXSLTRequests, mParserBlockingRequest, mDiskCacheQueue, mPreloads, mPendingChildLoaders, mModuleLoader, mWebExtModuleLoaders, mShadowRealmModuleLoaders) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END @@ -2710,12 +2710,6 @@ void ScriptLoader::CalculateCacheFlag(ScriptLoadRequest* aRequest) { LOG(("ScriptLoadRequest (%p): Bytecode-cache: Mark in-memory: Stencil", aRequest)); aRequest->MarkPassedConditionForMemoryCache(); - - if (aRequest->IsModuleRequest() && - aRequest->AsModuleRequest()->IsStaticImport()) { - MOZ_ASSERT(!aRequest->isInList()); - mCacheableDependencyModules.AppendElement(aRequest); - } } else { aRequest->MarkSkippedMemoryCaching(); } @@ -2857,11 +2851,10 @@ void ScriptLoader::CalculateCacheFlag(ScriptLoadRequest* aRequest) { aRequest)); aRequest->MarkPassedConditionForDiskCache(); - if (!aRequest->PassedConditionForMemoryCache() && - aRequest->IsModuleRequest() && + if (aRequest->IsModuleRequest() && aRequest->AsModuleRequest()->IsStaticImport()) { MOZ_ASSERT(!aRequest->isInList()); - mCacheableDependencyModules.AppendElement(aRequest); + mDiskCacheableDependencyModules.AppendElement(aRequest); } } @@ -3203,13 +3196,13 @@ void ScriptLoader::InstantiateClassicScriptFromCachedStencil( LOG(("ScriptLoadRequest (%p): Bytecode-cache: Skip: IsAlreadyCollecting", aRequest)); - // NOTE: non-top-level modules are added to mCacheableDependencyModules + // NOTE: non-top-level modules are added to mDiskCacheableDependencyModules // at the same time as MarkPassedConditionForMemoryCache. // Undo it here. if (aRequest->IsModuleRequest() && !aRequest->AsModuleRequest()->IsTopLevel()) { MOZ_ASSERT(aRequest->isInList()); - mCacheableDependencyModules.Remove(aRequest); + mDiskCacheableDependencyModules.Remove(aRequest); } aRequest->MarkSkippedMemoryCaching(); @@ -3342,29 +3335,33 @@ nsCString& ScriptLoader::BytecodeMimeTypeFor( nsresult ScriptLoader::MaybePrepareForCacheAfterExecute( ScriptLoadRequest* aRequest, nsresult aRv) { - if (aRequest->PassedConditionForEitherCache() && aRequest->HasStencil()) { - TRACE_FOR_TEST(aRequest, "scriptloader_encode"); - // Bytecode-encoding branch is used for 2 purposes right now: - // * If the request is stencil, reflect delazifications to cached stencil - // * otherwise, encode the initial stencil and delazifications - // - // For latter case, check that the TranscodeBuffer which is going to - // receive the encoded bytecode only contains the SRI, and nothing more. - // - // NOTE: This assertion will fail once we start encoding more data after the - // first encode. - MOZ_ASSERT_IF( - !aRequest->IsCachedStencil(), - aRequest->GetSRILength() == aRequest->SRIAndBytecode().length()); - RegisterForCache(aRequest); + if (!aRequest->PassedConditionForDiskCache() || !aRequest->HasStencil()) { + LOG(("ScriptLoadRequest (%p): Bytecode-cache: disabled (rv = %X)", aRequest, + unsigned(aRv))); + TRACE_FOR_TEST_NONE(aRequest, "scriptloader_no_encode"); + + // For in-memory cached requests, the disk cache references are necessary + // for later load. + MOZ_ASSERT_IF(!aRequest->PassedConditionForMemoryCache(), + !aRequest->getLoadedScript()->HasDiskCacheReference()); return aRv; } - LOG(("ScriptLoadRequest (%p): Bytecode-cache: disabled (rv = %X)", aRequest, - unsigned(aRv))); - TRACE_FOR_TEST_NONE(aRequest, "scriptloader_no_encode"); - MOZ_ASSERT(!aRequest->getLoadedScript()->HasDiskCacheReference()); + TRACE_FOR_TEST(aRequest, "scriptloader_encode"); + // Bytecode-encoding branch is used for 2 purposes right now: + // * If the request is stencil, reflect delazifications to cached stencil + // * otherwise, encode the initial stencil and delazifications + // + // For latter case, check that the TranscodeBuffer which is going to + // receive the encoded bytecode only contains the SRI, and nothing more. + // + // NOTE: This assertion will fail once we start encoding more data after the + // first encode. + MOZ_ASSERT_IF( + !aRequest->IsCachedStencil(), + aRequest->GetSRILength() == aRequest->SRIAndBytecode().length()); + RegisterForDiskCache(aRequest); return aRv; } @@ -3376,7 +3373,7 @@ nsresult ScriptLoader::MaybePrepareModuleForCacheAfterExecute( if (aRequest->isInList()) { // Top-level modules are part of lists only while loading, or // after queued for cache. - // NOTE: Non-top-level modules are part of mCacheableDependencyModules + // NOTE: Non-top-level modules are part of mDiskCacheableDependencyModules // after it's loaded. // // This filters out modules which is already queued for cache. @@ -3385,9 +3382,9 @@ nsresult ScriptLoader::MaybePrepareModuleForCacheAfterExecute( aRv = MaybePrepareForCacheAfterExecute(aRequest, aRv); - for (auto* r = mCacheableDependencyModules.getFirst(); r;) { + for (auto* r = mDiskCacheableDependencyModules.getFirst(); r;) { auto* dep = r->AsModuleRequest(); - MOZ_ASSERT(dep->PassedConditionForEitherCache()); + MOZ_ASSERT(dep->PassedConditionForDiskCache()); r = r->getNext(); @@ -3395,7 +3392,7 @@ nsresult ScriptLoader::MaybePrepareModuleForCacheAfterExecute( continue; } - mCacheableDependencyModules.Remove(dep); + mDiskCacheableDependencyModules.Remove(dep); aRv = MaybePrepareForCacheAfterExecute(dep, aRv); } @@ -3497,13 +3494,12 @@ LoadedScript* ScriptLoader::GetActiveScript(JSContext* aCx) { return static_cast<LoadedScript*>(value.toPrivate()); } -void ScriptLoader::RegisterForCache(ScriptLoadRequest* aRequest) { - MOZ_ASSERT(aRequest->PassedConditionForEitherCache()); +void ScriptLoader::RegisterForDiskCache(ScriptLoadRequest* aRequest) { + MOZ_ASSERT(aRequest->PassedConditionForDiskCache()); MOZ_ASSERT(aRequest->HasStencil()); - MOZ_ASSERT_IF(aRequest->PassedConditionForDiskCache(), - aRequest->getLoadedScript()->HasDiskCacheReference()); + MOZ_ASSERT(aRequest->getLoadedScript()->HasDiskCacheReference()); MOZ_DIAGNOSTIC_ASSERT(!aRequest->isInList()); - mCachingQueue.AppendElement(aRequest); + mDiskCacheQueue.AppendElement(aRequest); } void ScriptLoader::LoadEventFired() { @@ -3540,8 +3536,9 @@ void ScriptLoader::MaybeUpdateCache() { } // No need to fire any event if there is no bytecode to be saved. - if (mCachingQueue.isEmpty()) { - LOG(("ScriptLoader (%p): No script in queue to be encoded.", this)); + if (mDiskCacheQueue.isEmpty()) { + LOG(("ScriptLoader (%p): No script in queue to be saved to the disk.", + this)); return; } @@ -3586,20 +3583,24 @@ void ScriptLoader::UpdateCache() { } RefPtr<ScriptLoadRequest> request; - while (!mCachingQueue.isEmpty()) { - request = mCachingQueue.StealFirst(); + while (!mDiskCacheQueue.isEmpty()) { + request = mDiskCacheQueue.StealFirst(); MOZ_ASSERT(!IsWebExtensionRequest(request), "Bytecode for web extension content scrips is not cached"); // The bytecode encoding is performed only when there was no // bytecode stored in the necko cache. // + // For in-memory cached case, the save might already be performed + // by other request. + // // TODO: Move this to SharedScriptCache. - if (request->PassedConditionForDiskCache() && - request->getLoadedScript()->HasDiskCacheReference()) { - EncodeBytecodeAndSave(fc, request->getLoadedScript()); + if (!request->getLoadedScript()->HasDiskCacheReference()) { + continue; } + EncodeBytecodeAndSave(fc, request->getLoadedScript()); + request->DropBytecode(); request->getLoadedScript()->DropDiskCacheReference(); } @@ -3689,8 +3690,8 @@ void ScriptLoader::GiveUpCaching() { // to avoid queuing more scripts. mGiveUpCaching = true; - while (!mCachingQueue.isEmpty()) { - RefPtr<ScriptLoadRequest> request = mCachingQueue.StealFirst(); + while (!mDiskCacheQueue.isEmpty()) { + RefPtr<ScriptLoadRequest> request = mDiskCacheQueue.StealFirst(); LOG(("ScriptLoadRequest (%p): Cannot serialize bytecode", request.get())); TRACE_FOR_TEST_NONE(request, "scriptloader_bytecode_failed"); MOZ_ASSERT(!IsWebExtensionRequest(request)); @@ -3699,9 +3700,9 @@ void ScriptLoader::GiveUpCaching() { request->getLoadedScript()->DropDiskCacheReference(); } - while (!mCacheableDependencyModules.isEmpty()) { + while (!mDiskCacheableDependencyModules.isEmpty()) { RefPtr<ScriptLoadRequest> request = - mCacheableDependencyModules.StealFirst(); + mDiskCacheableDependencyModules.StealFirst(); } } diff --git a/dom/script/ScriptLoader.h b/dom/script/ScriptLoader.h @@ -732,7 +732,7 @@ class ScriptLoader final : public JS::loader::ScriptLoaderInterface { ScriptLoadRequest* aRequest); /** - * Register the script load request to be cached. + * Register the script load request to be cached on the disk. * * The caller can call this at the same time instantiating the stencil, * and also start collecting delazifications. @@ -740,12 +740,8 @@ class ScriptLoader final : public JS::loader::ScriptLoaderInterface { * The cache handling will be performed when the page initialization ends. * The page initialization end is defined as being the time when the load * event got received, and when no more scripts are waiting to be executed. - * - * The initial stencil and collected delazifications will be stored into - * - the in-memory cache, and/or - * - the necko cache */ - void RegisterForCache(ScriptLoadRequest* aRequest); + void RegisterForDiskCache(ScriptLoadRequest* aRequest); /** * Check if all conditions are met, i-e that the onLoad event fired and that @@ -814,7 +810,7 @@ class ScriptLoader final : public JS::loader::ScriptLoaderInterface { // * necko alternative stream as Stencil XDR // // If the request is a non-top-level module request and it passed the - // condition, it's stored into mCacheableDependencyModules in order + // condition, it's stored into mDiskCacheableDependencyModules in order // to iterate over them later. void CalculateCacheFlag(ScriptLoadRequest* aRequest); @@ -861,15 +857,15 @@ class ScriptLoader final : public JS::loader::ScriptLoaderInterface { // the original list if any. JS::loader::ScriptLoadRequestList mOffThreadCompilingRequests; - // Holds non-top-level module requests which passed caching conditions, until - // it's queued to mCachingQueue. + // Holds non-top-level module requests which passed disk caching conditions, + // until it's queued to mDiskCacheQueue. // // TODO: Remove this and per-ScriptLoader caching queue (bug 1902951). - JS::loader::ScriptLoadRequestList mCacheableDependencyModules; + JS::loader::ScriptLoadRequestList mDiskCacheableDependencyModules; // Holds already-evaluted requests that are holding a buffer which has to be - // saved on the cache, until it's cached or the caching is aborted. - JS::loader::ScriptLoadRequestList mCachingQueue; + // saved on the disk cache, until it's cached or the caching is aborted. + JS::loader::ScriptLoadRequestList mDiskCacheQueue; // In mRequests, the additional information here is stored by the element. struct PreloadInfo {