commit 7eaf4f425f15e3fec6e81e2041d78ed77ebc3600
parent a7a6ce8f6f42bf7d5c746a5c57ac4d9fca3e4644
Author: Tooru Fujisawa <arai_a@mac.com>
Date: Wed, 15 Oct 2025 09:41:50 +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:
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->PassedConditionForDiskCache()) {
+ 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->PassedConditionForDiskCache()) {
+ 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 {