commit adb38904a5a5714d61cc62c4cc4bb394e1a9c553
parent 4df889591754afec179b7cb419fb803d67bb6a06
Author: Cristian Tuns <ctuns@mozilla.com>
Date: Mon, 10 Nov 2025 07:11:21 -0500
Revert "Bug 1997870 - Part 4: Perform the encoding and the compression off main thread. r=bthrall" for causing build bustages in SharedScriptCache.cpp
This reverts commit c6b62c4029e36455ef0ab0613b6948f97eabb84b.
Revert "Bug 1997870 - Part 3: Split EncodeBytecodeAndSave into two steps. r=bthrall"
This reverts commit f6fed9057d96c3e39ccc612f64d840558ba8cc53.
Revert "Bug 1997870 - Part 2: Make BytecodeMimeTypeFor methods take const. r=bthrall"
This reverts commit 751adfcc4b6bce4e6a6343f7fc2e3882e588576a.
Revert "Bug 1997870 - Part 1: Remove obsolete comment. r=bthrall"
This reverts commit cc15fbf36578988b082ef2cea07ebf35de982dac.
Diffstat:
4 files changed, 57 insertions(+), 195 deletions(-)
diff --git a/dom/script/ScriptLoader.cpp b/dom/script/ScriptLoader.cpp
@@ -3347,8 +3347,7 @@ void ScriptLoader::TryCacheRequest(ScriptLoadRequest* aRequest) {
}
/* static */
-nsCString& ScriptLoader::BytecodeMimeTypeFor(
- const ScriptLoadRequest* aRequest) {
+nsCString& ScriptLoader::BytecodeMimeTypeFor(ScriptLoadRequest* aRequest) {
if (aRequest->IsModuleRequest()) {
return nsContentUtils::JSModuleBytecodeMimeType();
}
@@ -3357,7 +3356,7 @@ nsCString& ScriptLoader::BytecodeMimeTypeFor(
/* static */
nsCString& ScriptLoader::BytecodeMimeTypeFor(
- const JS::loader::LoadedScript* aLoadedScript) {
+ JS::loader::LoadedScript* aLoadedScript) {
if (aLoadedScript->IsModuleScript()) {
return nsContentUtils::JSModuleBytecodeMimeType();
}
@@ -3615,7 +3614,6 @@ void ScriptLoader::MaybeUpdateDiskCache() {
}
void ScriptLoader::UpdateDiskCache() {
- MOZ_ASSERT(!mCache);
LOG(("ScriptLoader (%p): Start bytecode encoding.", this));
// If any script got added in the previous loop cycle, wait until all
@@ -3637,31 +3635,20 @@ void ScriptLoader::UpdateDiskCache() {
for (auto& loadedScript : mDiskCacheQueue) {
// 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 requests.
+ // See also ScriptLoader::MaybePrepareModuleForDiskCacheAfterExecute.
+ //
+ // TODO: Move this to SharedScriptCache.
if (!loadedScript->HasDiskCacheReference()) {
continue;
}
- MOZ_ASSERT(loadedScript->HasStencil());
-
- Vector<uint8_t> compressed;
- if (!EncodeAndCompress(fc, loadedScript, loadedScript->GetStencil(),
- loadedScript->SRIAndBytecode(), compressed)) {
- loadedScript->DropDiskCacheReference();
- loadedScript->DropBytecode();
- TRACE_FOR_TEST(loadedScript, "diskcache:failed");
- continue;
- }
-
- if (!SaveToDiskCache(loadedScript, compressed)) {
- loadedScript->DropDiskCacheReference();
- loadedScript->DropBytecode();
- TRACE_FOR_TEST(loadedScript, "diskcache:failed");
- continue;
- }
+ EncodeBytecodeAndSave(fc, loadedScript);
loadedScript->DropDiskCacheReference();
loadedScript->DropBytecode();
- TRACE_FOR_TEST(loadedScript, "diskcache:saved");
}
mDiskCacheQueue.Clear();
@@ -3669,20 +3656,25 @@ void ScriptLoader::UpdateDiskCache() {
}
/* static */
-bool ScriptLoader::EncodeAndCompress(
- JS::FrontendContext* aFc, const JS::loader::LoadedScript* aLoadedScript,
- JS::Stencil* aStencil, const JS::TranscodeBuffer& aSRI,
- Vector<uint8_t>& aCompressed) {
- size_t SRILength = aSRI.length();
+void ScriptLoader::EncodeBytecodeAndSave(
+ JS::FrontendContext* aFc, JS::loader::LoadedScript* aLoadedScript) {
+ MOZ_ASSERT(aLoadedScript->HasDiskCacheReference());
+ MOZ_ASSERT(aLoadedScript->HasStencil());
+
+ auto bytecodeFailed = mozilla::MakeScopeExit(
+ [&]() { TRACE_FOR_TEST(aLoadedScript, "diskcache:failed"); });
+
+ size_t SRILength = aLoadedScript->SRIAndBytecode().length();
MOZ_ASSERT(JS::IsTranscodingBytecodeOffsetAligned(SRILength));
JS::TranscodeBuffer SRIAndBytecode;
- if (!SRIAndBytecode.appendAll(aSRI)) {
+ if (!SRIAndBytecode.appendAll(aLoadedScript->SRIAndBytecode())) {
LOG(("LoadedScript (%p): Cannot allocate buffer", aLoadedScript));
- return false;
+ return;
}
- JS::TranscodeResult result = JS::EncodeStencil(aFc, aStencil, SRIAndBytecode);
+ JS::TranscodeResult result =
+ JS::EncodeStencil(aFc, aLoadedScript->GetStencil(), SRIAndBytecode);
if (result != JS::TranscodeResult::Ok) {
// Encoding can be aborted for non-supported syntax (e.g. asm.js), or
@@ -3691,44 +3683,37 @@ bool ScriptLoader::EncodeAndCompress(
JS::ClearFrontendErrors(aFc);
LOG(("LoadedScript (%p): Cannot serialize bytecode", aLoadedScript));
- return false;
+ return;
}
+ Vector<uint8_t> compressedBytecode;
// TODO probably need to move this to a helper thread
- if (!ScriptBytecodeCompress(SRIAndBytecode, SRILength, aCompressed)) {
- return false;
+ if (!ScriptBytecodeCompress(SRIAndBytecode, SRILength, compressedBytecode)) {
+ return;
}
- if (aCompressed.length() >= UINT32_MAX) {
+ if (compressedBytecode.length() >= UINT32_MAX) {
LOG(
("LoadedScript (%p): Bytecode cache is too large to be decoded "
"correctly.",
aLoadedScript));
- return false;
+ return;
}
- return true;
-}
-
-/* static */
-bool ScriptLoader::SaveToDiskCache(
- const JS::loader::LoadedScript* aLoadedScript,
- const Vector<uint8_t>& aCompressed) {
- MOZ_ASSERT(NS_IsMainThread());
-
// Open the output stream to the cache entry alternate data storage. This
// might fail if the stream is already open by another request, in which
// case, we just ignore the current one.
nsCOMPtr<nsIAsyncOutputStream> output;
nsresult rv = aLoadedScript->mCacheInfo->OpenAlternativeOutputStream(
BytecodeMimeTypeFor(aLoadedScript),
- static_cast<int64_t>(aCompressed.length()), getter_AddRefs(output));
+ static_cast<int64_t>(compressedBytecode.length()),
+ getter_AddRefs(output));
if (NS_FAILED(rv)) {
LOG(
("LoadedScript (%p): Cannot open bytecode cache (rv = %X, output "
"= %p)",
aLoadedScript, unsigned(rv), output.get()));
- return false;
+ return;
}
MOZ_ASSERT(output);
@@ -3738,18 +3723,20 @@ bool ScriptLoader::SaveToDiskCache(
});
uint32_t n;
- rv = output->Write(reinterpret_cast<const char*>(aCompressed.begin()),
- aCompressed.length(), &n);
+ rv = output->Write(reinterpret_cast<char*>(compressedBytecode.begin()),
+ compressedBytecode.length(), &n);
LOG(
("LoadedScript (%p): Write bytecode cache (rv = %X, length = %u, "
"written = %u)",
- aLoadedScript, unsigned(rv), unsigned(aCompressed.length()), n));
+ aLoadedScript, unsigned(rv), unsigned(compressedBytecode.length()), n));
if (NS_FAILED(rv)) {
- return false;
+ return;
}
- MOZ_RELEASE_ASSERT(aCompressed.length() == n);
- return true;
+ MOZ_RELEASE_ASSERT(compressedBytecode.length() == n);
+
+ bytecodeFailed.release();
+ TRACE_FOR_TEST(aLoadedScript, "diskcache:saved");
}
void ScriptLoader::GiveUpDiskCaching() {
diff --git a/dom/script/ScriptLoader.h b/dom/script/ScriptLoader.h
@@ -709,9 +709,9 @@ class ScriptLoader final : public JS::loader::ScriptLoaderInterface {
JS::Handle<JS::Value> aDebuggerPrivateValue,
JS::Handle<JSScript*> aDebuggerIntroductionScript, ErrorResult& aRv);
- static nsCString& BytecodeMimeTypeFor(const ScriptLoadRequest* aRequest);
+ static nsCString& BytecodeMimeTypeFor(ScriptLoadRequest* aRequest);
static nsCString& BytecodeMimeTypeFor(
- const JS::loader::LoadedScript* aLoadedScript);
+ JS::loader::LoadedScript* aLoadedScript);
// Queue the script load request for caching if we decided to cache it, or
// cleanup the script load request fields otherwise.
@@ -757,21 +757,10 @@ class ScriptLoader final : public JS::loader::ScriptLoaderInterface {
public:
/**
- * Encode the stencils and compress it.
- * aLoadedScript is used only for logging purpose, in order to allow
- * performing this off main thread.
+ * Encode the stencils and save the bytecode to the necko cache.
*/
- static bool EncodeAndCompress(JS::FrontendContext* aFc,
- const JS::loader::LoadedScript* aLoadedScript,
- JS::Stencil* aStencil,
- const JS::TranscodeBuffer& aSRI,
- Vector<uint8_t>& aCompressed);
-
- /**
- * Save the bytecode to the necko cache.
- */
- static bool SaveToDiskCache(const JS::loader::LoadedScript* aLoadedScript,
- const Vector<uint8_t>& aCompressed);
+ static void EncodeBytecodeAndSave(JS::FrontendContext* aFc,
+ JS::loader::LoadedScript* aLoadedScript);
private:
/**
diff --git a/dom/script/SharedScriptCache.cpp b/dom/script/SharedScriptCache.cpp
@@ -10,7 +10,6 @@
#include "ScriptLoader.h" // ScriptLoader
#include "js/experimental/CompileScript.h" // JS::FrontendContext, JS::NewFrontendContext, JS::DestroyFrontendContext
#include "mozilla/Maybe.h" // Maybe, Some, Nothing
-#include "mozilla/TaskController.h" // TaskController, Task
#include "mozilla/dom/ContentParent.h" // dom::ContentParent
#include "nsIMemoryReporter.h" // nsIMemoryReporter, MOZ_DEFINE_MALLOC_SIZE_OF, RegisterWeakMemoryReporter, UnregisterWeakMemoryReporter, MOZ_COLLECT_REPORT, KIND_HEAP, UNITS_BYTES
#include "nsIPrefBranch.h" // nsIPrefBranch, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID
@@ -222,54 +221,13 @@ bool SharedScriptCache::MaybeScheduleUpdateDiskCache() {
return true;
}
-class ScriptEncodeAndCompressionTask : public mozilla::Task {
- public:
- ScriptEncodeAndCompressionTask()
- : Task(Kind::OffMainThreadOnly, EventQueuePriority::Idle) {}
- virtual ~ScriptEncodeAndCompressionTask() = default;
-
-#ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY
- bool GetName(nsACString& aName) override {
- aName.AssignLiteral("ScriptEncodeAndCompressionTask");
- return true;
- }
-#endif
-
- TaskResult Run() override {
- SharedScriptCache::Get()->EncodeAndCompress();
- return TaskResult::Complete;
- }
-};
-
-class ScriptSaveTask : public mozilla::Task {
- public:
- ScriptSaveTask() : Task(Kind::MainThreadOnly, EventQueuePriority::Idle) {}
- virtual ~ScriptSaveTask() = default;
-
-#ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY
- bool GetName(nsACString& aName) override {
- aName.AssignLiteral("ScriptSaveTask");
- return true;
- }
-#endif
-
- TaskResult Run() override {
- SharedScriptCache::Get()->SaveToDiskCache();
- return TaskResult::Complete;
- }
-};
-
void SharedScriptCache::UpdateDiskCache() {
auto strategy = ScriptLoader::GetDiskCacheStrategy();
if (strategy.mIsDisabled) {
return;
}
- mozilla::MutexAutoLock lock(mEncodeMutex);
-
- if (!mEncodeItems.empty()) {
- return;
- }
+ JS::FrontendContext* fc = nullptr;
for (auto iter = mComplete.Iter(); !iter.Done(); iter.Next()) {
JS::loader::LoadedScript* loadedScript = iter.Data().mResource;
@@ -277,69 +235,24 @@ void SharedScriptCache::UpdateDiskCache() {
continue;
}
- if (!mEncodeItems.emplaceBack(loadedScript->GetStencil(),
- std::move(loadedScript->SRIAndBytecode()),
- loadedScript)) {
- continue;
+ if (!fc) {
+ // Lazily create the context only when there's at least one script
+ // that needs to be saved.
+ fc = JS::NewFrontendContext();
+ if (!fc) {
+ return;
+ }
}
- }
-
- if (mEncodeItems.empty()) {
- return;
- }
- RefPtr<ScriptEncodeAndCompressionTask> encodeTask =
- new ScriptEncodeAndCompressionTask();
- RefPtr<ScriptSaveTask> saveTask = new ScriptSaveTask();
- saveTask->AddDependency(encodeTask);
+ ScriptLoader::EncodeBytecodeAndSave(fc, loadedScript);
- TaskController::Get()->AddTask(encodeTask.forget());
- TaskController::Get()->AddTask(saveTask.forget());
-}
-
-void SharedScriptCache::EncodeAndCompress() {
- JS::FrontendContext* fc = JS::NewFrontendContext();
- if (!fc) {
- return;
+ loadedScript->DropDiskCacheReference();
+ loadedScript->DropBytecode();
}
- mozilla::MutexAutoLock lock(mEncodeMutex);
-
- for (auto& item : mEncodeItems) {
- if (!ScriptLoader::EncodeAndCompress(fc, item.mLoadedScript, item.mStencil,
- item.mSRI, item.mCompressed)) {
- item.mCompressed.clear();
- }
+ if (fc) {
+ JS::DestroyFrontendContext(fc);
}
-
- JS::DestroyFrontendContext(fc);
-}
-
-void SharedScriptCache::SaveToDiskCache() {
- MOZ_ASSERT(NS_IsMainThread());
-
- mozilla::MutexAutoLock lock(mEncodeMutex);
-
- for (const auto& item : mEncodeItems) {
- if (item.mCompressed.empty()) {
- item.mLoadedScript->DropDiskCacheReference();
- item.mLoadedScript->DropBytecode();
- TRACE_FOR_TEST(item.mLoadedScript, "diskcache:failed");
- continue;
- }
-
- if (!ScriptLoader::SaveToDiskCache(item.mLoadedScript, item.mCompressed)) {
- item.mLoadedScript->DropDiskCacheReference();
- item.mLoadedScript->DropBytecode();
- TRACE_FOR_TEST(item.mLoadedScript, "diskcache:failed");
- }
-
- item.mLoadedScript->DropDiskCacheReference();
- item.mLoadedScript->DropBytecode();
- TRACE_FOR_TEST(item.mLoadedScript, "diskcache:saved");
- }
-
- mEncodeItems.clear();
}
} // namespace mozilla::dom
diff --git a/dom/script/SharedScriptCache.h b/dom/script/SharedScriptCache.h
@@ -14,10 +14,8 @@
#include "js/loader/ScriptLoadRequest.h" // JS::loader::ScriptLoadRequest
#include "mozilla/CORSMode.h" // mozilla::CORSMode
#include "mozilla/MemoryReporting.h" // MallocSizeOf
-#include "mozilla/Mutex.h" // Mutex, GUARDED_BY, MutexAutoLock
#include "mozilla/RefPtr.h" // RefPtr
#include "mozilla/SharedSubResourceCache.h" // SharedSubResourceCache, SharedSubResourceCacheLoadingValueBase, SubResourceNetworkMetadataHolder
-#include "mozilla/ThreadSafety.h" // MOZ_GUARDED_BY
#include "mozilla/WeakPtr.h" // SupportsWeakPtr
#include "mozilla/dom/CacheExpirationTime.h" // CacheExpirationTime
#include "mozilla/dom/SRIMetadata.h" // mozilla::dom::SRIMetadata
@@ -198,9 +196,6 @@ class SharedScriptCache final
bool MaybeScheduleUpdateDiskCache();
void UpdateDiskCache();
- void EncodeAndCompress();
- void SaveToDiskCache();
-
// This has to be static because it's also called for loaders that don't have
// a sheet cache (loaders that are not owned by a document).
static void LoadCompleted(SharedScriptCache*, ScriptLoadData&);
@@ -215,28 +210,6 @@ class SharedScriptCache final
protected:
~SharedScriptCache();
-
- private:
- class EncodeItem {
- public:
- EncodeItem(JS::Stencil* aStencil, JS::TranscodeBuffer&& aSRI,
- JS::loader::LoadedScript* aLoadedScript)
- : mStencil(aStencil),
- mSRI(std::move(aSRI)),
- mLoadedScript(aLoadedScript) {}
-
- // These fields can be touched from multiple threads.
- RefPtr<JS::Stencil> mStencil;
- JS::TranscodeBuffer mSRI;
- Vector<uint8_t> mCompressed;
-
- // This can be dereferenced only from the main thread.
- // Reading the pointer itself is allowed also off main thread.
- RefPtr<JS::loader::LoadedScript> mLoadedScript;
- };
-
- Mutex mEncodeMutex{"SharedScriptCache::mEncodeMutex"};
- Vector<EncodeItem> mEncodeItems MOZ_GUARDED_BY(mEncodeMutex);
};
} // namespace dom