tor-browser

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

commit 3f9a88662a74b47bd9537afd770f7d62fd7b5f3b
parent 1257f9e671118460579b981196eee71de00ea5cc
Author: Tooru Fujisawa <arai_a@mac.com>
Date:   Thu, 16 Oct 2025 09:03:22 +0000

Bug 1991081 - Part 2: Store stencil to LoadedScript also in text and bytecode variants. r=nbp

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

Diffstat:
Mdom/script/ModuleLoader.cpp | 8++++++--
Mdom/script/ScriptLoader.cpp | 34+++++++++++++++++++++-------------
Mdom/script/ScriptLoader.h | 4+---
Mjs/loader/LoadedScript.h | 46++++++++++++++++++++++++++++++++++++++++------
4 files changed, 68 insertions(+), 24 deletions(-)

diff --git a/dom/script/ModuleLoader.cpp b/dom/script/ModuleLoader.cpp @@ -262,6 +262,8 @@ nsresult ModuleLoader::CompileJavaScriptModule( return NS_ERROR_FAILURE; } + aRequest->SetStencil(stencil); + JS::InstantiateOptions instantiateOptions(aOptions); aModuleOut.set(JS::InstantiateModuleStencil(aCx, instantiateOptions, stencil, &storage)); @@ -278,7 +280,7 @@ nsresult ModuleLoader::CompileJavaScriptModule( MOZ_ASSERT(!alreadyStarted); } - GetScriptLoader()->TryCacheRequest(aRequest, stencil); + GetScriptLoader()->TryCacheRequest(aRequest); return NS_OK; } @@ -311,6 +313,8 @@ nsresult ModuleLoader::CompileJavaScriptModule( return NS_ERROR_FAILURE; } + aRequest->SetStencil(stencil); + JS::InstantiateOptions instantiateOptions(aOptions); aModuleOut.set( JS::InstantiateModuleStencil(aCx, instantiateOptions, stencil)); @@ -327,7 +331,7 @@ nsresult ModuleLoader::CompileJavaScriptModule( MOZ_ASSERT(!alreadyStarted); } - GetScriptLoader()->TryCacheRequest(aRequest, stencil); + GetScriptLoader()->TryCacheRequest(aRequest); return NS_OK; } diff --git a/dom/script/ScriptLoader.cpp b/dom/script/ScriptLoader.cpp @@ -3065,7 +3065,6 @@ static void InstantiateStencil( void ScriptLoader::InstantiateClassicScriptFromMaybeEncodedSource( JSContext* aCx, JS::CompileOptions& aCompileOptions, ScriptLoadRequest* aRequest, JS::MutableHandle<JSScript*> aScript, - RefPtr<JS::Stencil>& aStencilOut, JS::Handle<JS::Value> aDebuggerPrivateValue, JS::Handle<JSScript*> aDebuggerIntroductionScript, ErrorResult& aRv) { nsAutoCString profilerLabelString; @@ -3086,7 +3085,8 @@ void ScriptLoader::InstantiateClassicScriptFromMaybeEncodedSource( aRv.NoteJSContextException(aCx); return; } - aStencilOut = stencil.get(); + + aRequest->SetStencil(stencil); InstantiateStencil(aCx, aCompileOptions, stencil, aScript, aDebuggerPrivateValue, aDebuggerIntroductionScript, @@ -3099,9 +3099,10 @@ void ScriptLoader::InstantiateClassicScriptFromMaybeEncodedSource( RefPtr<JS::Stencil> stencil; Decode(aCx, aCompileOptions, aRequest->Bytecode(), stencil, aRv); - aStencilOut = stencil.get(); if (stencil) { + aRequest->SetStencil(stencil); + InstantiateStencil(aCx, aCompileOptions, stencil, aScript, aDebuggerPrivateValue, aDebuggerIntroductionScript, aRv); @@ -3135,7 +3136,8 @@ void ScriptLoader::InstantiateClassicScriptFromMaybeEncodedSource( aRv.NoteJSContextException(aCx); return; } - aStencilOut = stencil.get(); + + aRequest->SetStencil(stencil); InstantiateStencil(aCx, aCompileOptions, stencil, aScript, aDebuggerPrivateValue, aDebuggerIntroductionScript, aRv, @@ -3163,9 +3165,10 @@ void ScriptLoader::InstantiateClassicScriptFromMaybeEncodedSource( MOZ_ASSERT(!maybeSource.empty()); maybeSource.mapNonEmpty(compile); - aStencilOut = stencil.get(); if (stencil) { + aRequest->SetStencil(stencil); + InstantiateStencil(aCx, aCompileOptions, stencil, aScript, aDebuggerPrivateValue, aDebuggerIntroductionScript, erv, /* aStorage = */ nullptr, @@ -3222,15 +3225,14 @@ void ScriptLoader::InstantiateClassicScriptFromAny( return; } - RefPtr<JS::Stencil> stencil; InstantiateClassicScriptFromMaybeEncodedSource( - aCx, aCompileOptions, aRequest, aScript, stencil, aDebuggerPrivateValue, + aCx, aCompileOptions, aRequest, aScript, aDebuggerPrivateValue, aDebuggerIntroductionScript, aRv); if (aRv.Failed()) { return; } - TryCacheRequest(aRequest, stencil); + TryCacheRequest(aRequest); } ScriptLoader::CacheBehavior ScriptLoader::GetCacheBehavior( @@ -3276,24 +3278,26 @@ ScriptLoader::CacheBehavior ScriptLoader::GetCacheBehavior( return CacheBehavior::Insert; } -void ScriptLoader::TryCacheRequest(ScriptLoadRequest* aRequest, - RefPtr<JS::Stencil>& aStencil) { +void ScriptLoader::TryCacheRequest(ScriptLoadRequest* aRequest) { + MOZ_ASSERT(aRequest->HasStencil()); CacheBehavior cacheBehavior = GetCacheBehavior(aRequest); if (cacheBehavior == CacheBehavior::DoNothing) { + if (!aRequest->PassedConditionForEitherCache()) { + aRequest->ClearStencil(); + } return; } MOZ_ASSERT(mCache); - MOZ_ASSERT(aStencil); - if (!JS::IsStencilCacheable(aStencil)) { + if (!JS::IsStencilCacheable(aRequest->GetStencil())) { // If the stencil is not compatible with the cache (e.g. contains asm.js), // this should also evict any the existing cache if any. cacheBehavior = CacheBehavior::Evict; } - aRequest->SetCachedStencil(aStencil.forget()); + aRequest->ConvertToCachedStencil(); if (cacheBehavior == CacheBehavior::Insert) { auto loadData = MakeRefPtr<ScriptLoadData>(this, aRequest); @@ -3309,6 +3313,10 @@ void ScriptLoader::TryCacheRequest(ScriptLoadRequest* aRequest, mCache->Evict(key); LOG(("ScriptLoader (%p): Evicting in-memory cache for %s.", this, aRequest->mURI->GetSpecOrDefault().get())); + + if (!aRequest->PassedConditionForEitherCache()) { + aRequest->ClearStencil(); + } } } diff --git a/dom/script/ScriptLoader.h b/dom/script/ScriptLoader.h @@ -526,8 +526,7 @@ class ScriptLoader final : public JS::loader::ScriptLoaderInterface { CacheBehavior GetCacheBehavior(ScriptLoadRequest* aRequest); - void TryCacheRequest(ScriptLoadRequest* aRequest, - RefPtr<JS::Stencil>& aStencil); + void TryCacheRequest(ScriptLoadRequest* aRequest); JS::loader::ScriptLoadRequest* LookupPreloadRequest( nsIScriptElement* aElement, JS::loader::ScriptKind aScriptKind, @@ -695,7 +694,6 @@ class ScriptLoader final : public JS::loader::ScriptLoaderInterface { void InstantiateClassicScriptFromMaybeEncodedSource( JSContext* aCx, JS::CompileOptions& aCompileOptions, ScriptLoadRequest* aRequest, JS::MutableHandle<JSScript*> aScript, - RefPtr<JS::Stencil>& aStencilOut, JS::Handle<JS::Value> aDebuggerPrivateValue, JS::Handle<JSScript*> aDebuggerIntroductionScript, ErrorResult& aRv); diff --git a/js/loader/LoadedScript.h b/js/loader/LoadedScript.h @@ -118,9 +118,23 @@ class LoadedScript : public nsIMemoryReporter { // Type of data this instance holds, which is either provided by the nsChannel // or retrieved from the cache. enum class DataType : uint8_t { + // This script haven't yet received the data. eUnknown, + + // This script is received as a plain text from the channel. + // mScriptData holds the text source, and mStencil holds the compiled + // stencil. + // mScriptBytecode holds the SRI. eTextSource, + + // This script is received as a bytecode from the channel. + // mScriptBytecode holds the SRI and the bytecode, and mStencil holds the + // decoded stencil. eBytecode, + + // This script is cached from the previous load. + // mStencil holds the cached stencil, and mSRI holds the SRI. + // mScriptData and mScriptBytecode are unused. eCachedStencil }; @@ -155,10 +169,10 @@ class LoadedScript : public nsIMemoryReporter { mDataType = DataType::eBytecode; } - void SetCachedStencil(already_AddRefed<Stencil> aStencil) { + void ConvertToCachedStencil() { + MOZ_ASSERT(HasStencil()); SetUnknownDataType(); mDataType = DataType::eCachedStencil; - mStencil = aStencil; } bool IsUTF16Text() const { @@ -241,15 +255,29 @@ class LoadedScript : public nsIMemoryReporter { mScriptBytecode.clearAndFree(); } + bool HasStencil() const { return mStencil; } + Stencil* GetStencil() const { - MOZ_ASSERT(IsCachedStencil()); + MOZ_ASSERT(!IsUnknownDataType()); + MOZ_ASSERT(HasStencil()); return mStencil; } + void SetStencil(Stencil* aStencil) { + MOZ_ASSERT(aStencil); + MOZ_ASSERT(!HasStencil()); + mStencil = aStencil; + } + + void ClearStencil() { + mStencil = nullptr; + } + public: // Fields. // Determine whether the mScriptData or mScriptBytecode is used. + // See DataType description for more info. DataType mDataType; // The consumer-defined number of times that this loaded script is used. @@ -288,6 +316,7 @@ class LoadedScript : public nsIMemoryReporter { // or, if compression is enabled, ScriptBytecodeCompressedDataLayout. TranscodeBuffer mScriptBytecode; + // Holds the stencil for the script. This field is used in all DataType. RefPtr<Stencil> mStencil; // The cache info channel used when saving the bytecode to the necko cache. @@ -337,9 +366,7 @@ class LoadedScriptDelegate { void SetBytecode() { GetLoadedScript()->SetBytecode(); } - void SetCachedStencil(already_AddRefed<Stencil> aStencil) { - GetLoadedScript()->SetCachedStencil(std::move(aStencil)); - } + void ConvertToCachedStencil() { GetLoadedScript()->ConvertToCachedStencil(); } bool IsUTF16Text() const { return GetLoadedScript()->IsUTF16Text(); } bool IsUTF8Text() const { return GetLoadedScript()->IsUTF8Text(); } @@ -390,7 +417,14 @@ class LoadedScriptDelegate { void DropBytecode() { GetLoadedScript()->DropBytecode(); } + bool HasStencil() const { return GetLoadedScript()->HasStencil(); } Stencil* GetStencil() const { return GetLoadedScript()->GetStencil(); } + void SetStencil(Stencil* aStencil) { + GetLoadedScript()->SetStencil(aStencil); + } + void ClearStencil() { + GetLoadedScript()->ClearStencil(); + } }; class ClassicScript final : public LoadedScript {