tor-browser

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

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:
Mdom/script/ScriptLoader.cpp | 91++++++++++++++++++++++++++++++++++---------------------------------------------
Mdom/script/ScriptLoader.h | 21+++++----------------
Mdom/script/SharedScriptCache.cpp | 113+++++++++----------------------------------------------------------------------
Mdom/script/SharedScriptCache.h | 27---------------------------
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