diff --git a/js/xpconnect/loader/ScriptPreloader.cpp b/js/xpconnect/loader/ScriptPreloader.cpp index f1efab936f56..86f9c4d513db 100644 --- a/js/xpconnect/loader/ScriptPreloader.cpp +++ b/js/xpconnect/loader/ScriptPreloader.cpp @@ -176,6 +176,7 @@ void ScriptPreloader::DeleteCacheDataSingleton() { void ScriptPreloader::InitContentChild(ContentParent& parent) { auto& cache = GetChildSingleton(); + cache.mSaveMonitor.AssertOnWritingThread(); // We want startup script data from the first process of a given type. // That process sends back its script data before it executes any @@ -219,7 +220,7 @@ ProcessType ScriptPreloader::GetChildProcessType(const nsACString& remoteType) { ScriptPreloader::ScriptPreloader(AutoMemMap* cacheData) : mCacheData(cacheData), mMonitor("[ScriptPreloader.mMonitor]"), - mSaveMonitor("[ScriptPreloader.mSaveMonitor]") { + mSaveMonitor("[ScriptPreloader.mSaveMonitor]", this) { // We do not set the process type for child processes here because the // remoteType in ContentChild is not ready yet. if (XRE_IsParentProcess()) { @@ -288,7 +289,7 @@ void ScriptPreloader::InvalidateCache() { } { - MonitorAutoLock saveMonitorAutoLock(mSaveMonitor); + MonitorSingleWriterAutoLock saveMonitorAutoLock(mSaveMonitor); mCacheInvalidated = true; } @@ -428,6 +429,7 @@ Result ScriptPreloader::OpenCache() { // Opens the script cache file for this session, and initializes the script // cache based on its contents. See WriteCache for details of the cache file. Result ScriptPreloader::InitCache(const nsAString& basePath) { + mSaveMonitor.AssertOnWritingThread(); mCacheInitialized = true; mBaseName = basePath; @@ -453,6 +455,7 @@ Result ScriptPreloader::InitCache(const nsAString& basePath) { Result ScriptPreloader::InitCache( const Maybe& cacheFile, ScriptCacheChild* cacheChild) { + mSaveMonitor.AssertOnWritingThread(); MOZ_ASSERT(XRE_IsContentProcess()); mCacheInitialized = true; @@ -664,7 +667,7 @@ Result ScriptPreloader::WriteCache() { mSaveMonitor.AssertCurrentThreadOwns(); if (!mDataPrepared && !mSaveComplete) { - MonitorAutoUnlock mau(mSaveMonitor); + MonitorSingleWriterAutoUnlock mau(mSaveMonitor); NS_DispatchToMainThread( NewRunnableMethod("ScriptPreloader::PrepareCacheWrite", this, @@ -760,7 +763,7 @@ nsresult ScriptPreloader::GetName(nsACString& aName) { // Runs in the mSaveThread thread, and writes out the cache file for the next // session after a reasonable delay. nsresult ScriptPreloader::Run() { - MonitorAutoLock mal(mSaveMonitor); + MonitorSingleWriterAutoLock mal(mSaveMonitor); // Ideally wait about 10 seconds before saving, to avoid unnecessary IO // during early startup. But only if the cache hasn't been invalidated, @@ -777,7 +780,7 @@ nsresult ScriptPreloader::Run() { Unused << NS_WARN_IF(result.isErr()); { - MonitorAutoLock lock(mChildCache->mSaveMonitor); + MonitorSingleWriterAutoLock lock(mChildCache->mSaveMonitor); result = mChildCache->WriteCache(); } Unused << NS_WARN_IF(result.isErr()); diff --git a/js/xpconnect/loader/ScriptPreloader.h b/js/xpconnect/loader/ScriptPreloader.h index c41801953cd0..b98c0fd08020 100644 --- a/js/xpconnect/loader/ScriptPreloader.h +++ b/js/xpconnect/loader/ScriptPreloader.h @@ -71,7 +71,8 @@ class ScriptPreloader : public nsIObserver, public nsIMemoryReporter, public nsIRunnable, public nsINamed, - public nsIAsyncShutdownBlocker { + public nsIAsyncShutdownBlocker, + public SingleWriterLockOwner { MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf) friend class mozilla::loader::ScriptCacheChild; @@ -104,6 +105,8 @@ class ScriptPreloader : public nsIObserver, static void FillCompileOptionsForCachedStencil(JS::CompileOptions& options); static void FillDecodeOptionsForCachedStencil(JS::DecodeOptions& options); + bool OnWritingThread() const override { return NS_IsMainThread(); } + // Retrieves the stencil with the given cache key from the cache. // Returns null if the stencil is not cached. already_AddRefed GetCachedStencil( @@ -420,7 +423,7 @@ class ScriptPreloader : public nsIObserver, Result OpenCache(); // Writes a new cache file to disk. Must not be called on the main thread. - Result WriteCache(); + Result WriteCache() REQUIRES(mSaveMonitor); void StartCacheWrite(); @@ -485,7 +488,7 @@ class ScriptPreloader : public nsIObserver, bool mSaveComplete = false; bool mDataPrepared = false; // May only be changed on the main thread, while `mSaveMonitor` is held. - bool mCacheInvalidated = false; + bool mCacheInvalidated GUARDED_BY(mSaveMonitor) = false; // The list of scripts that we read from the initial startup cache file, // but have yet to initiate a decode task for. @@ -501,11 +504,11 @@ class ScriptPreloader : public nsIObserver, // True if a runnable has been dispatched to the main thread to finish an // off-thread decode operation. Access only while 'mMonitor' is held. - bool mFinishDecodeRunnablePending = false; + bool mFinishDecodeRunnablePending GUARDED_BY(mMonitor) = false; // True is main-thread is blocked and we should notify with Monitor. Access // only while `mMonitor` is held. - bool mWaitingForDecode = false; + bool mWaitingForDecode GUARDED_BY(mMonitor) = false; // The process type of the current process. static ProcessType sProcessType; @@ -530,8 +533,8 @@ class ScriptPreloader : public nsIObserver, // instance. AutoMemMap* mCacheData; - Monitor mMonitor MOZ_UNANNOTATED; - Monitor mSaveMonitor MOZ_UNANNOTATED; + Monitor mMonitor; + MonitorSingleWriter mSaveMonitor ACQUIRED_BEFORE(mMonitor); }; } // namespace mozilla