@@ -149,7 +149,8 @@ StartupCache::StartupCache()
149149 mCurTableReferenced(false ),
150150 mRequestedCount(0 ),
151151 mCacheEntriesBaseOffset(0 ),
152- mWriteThread(nullptr ) {}
152+ mWriteThread(nullptr ),
153+ mPrefetchThread(nullptr ) {}
153154
154155StartupCache::~StartupCache () {
155156 if (mTimer ) {
@@ -160,6 +161,7 @@ StartupCache::~StartupCache() {
160161 // but an early shutdown means either mTimer didn't run
161162 // or the write thread is still running.
162163 WaitOnWriteThread ();
164+ WaitOnPrefetchThread ();
163165
164166 // If we shutdown quickly timer wont have fired. Instead of writing
165167 // it on the main thread and block the shutdown we simply wont update
@@ -243,6 +245,15 @@ nsresult StartupCache::Init() {
243245 return NS_OK ;
244246}
245247
248+ void StartupCache::StartPrefetchMemoryThread () {
249+ // XXX: It would be great for this to not create its own thread, unfortunately
250+ // there doesn't seem to be an existing thread that makes sense for this, so
251+ // barring a coordinated global scheduling system this is the best we get.
252+ mPrefetchThread = PR_CreateThread (
253+ PR_USER_THREAD , StartupCache::ThreadedPrefetch, this , PR_PRIORITY_NORMAL ,
254+ PR_GLOBAL_THREAD , PR_JOINABLE_THREAD , 0 );
255+ }
256+
246257/* *
247258 * LoadArchive can be called from the main thread or while reloading cache on
248259 * write thread.
@@ -252,6 +263,9 @@ Result<Ok, nsresult> StartupCache::LoadArchive() {
252263
253264 MOZ_TRY (mCacheData .init (mFile ));
254265 auto size = mCacheData .size ();
266+ if (CanPrefetchMemory ()) {
267+ StartPrefetchMemoryThread ();
268+ }
255269
256270 uint32_t headerSize;
257271 if (size < sizeof (MAGIC ) + sizeof (headerSize)) {
@@ -365,9 +379,6 @@ nsresult StartupCache::GetBuffer(const char* id, const char** outbuf,
365379 Span<const char > compressed = MakeSpan (
366380 mCacheData .get <char >().get () + mCacheEntriesBaseOffset + value.mOffset ,
367381 value.mCompressedSize );
368- if (CanPrefetchMemory ()) {
369- PrefetchMemory ((uint8_t *)compressed.Elements (), compressed.Length ());
370- }
371382 value.mData = MakeUnique<char []>(value.mUncompressedSize );
372383 Span<char > uncompressed =
373384 MakeSpan (value.mData .get (), value.mUncompressedSize );
@@ -611,6 +622,23 @@ void StartupCache::WaitOnWriteThread() {
611622 mWriteThread = nullptr ;
612623}
613624
625+ void StartupCache::WaitOnPrefetchThread () {
626+ if (!mPrefetchThread || mPrefetchThread == PR_GetCurrentThread ()) return ;
627+
628+ PR_JoinThread (mPrefetchThread );
629+ mPrefetchThread = nullptr ;
630+ }
631+
632+ void StartupCache::ThreadedPrefetch (void * aClosure) {
633+ AUTO_PROFILER_REGISTER_THREAD (" StartupCache" );
634+ NS_SetCurrentThreadName (" StartupCache" );
635+ mozilla::IOInterposer::RegisterCurrentThread ();
636+ StartupCache* startupCacheObj = static_cast <StartupCache*>(aClosure);
637+ PrefetchMemory (startupCacheObj->mCacheData .get <uint8_t >().get (),
638+ startupCacheObj->mCacheData .size ());
639+ mozilla::IOInterposer::UnregisterCurrentThread ();
640+ }
641+
614642void StartupCache::ThreadedWrite (void * aClosure) {
615643 AUTO_PROFILER_REGISTER_THREAD (" StartupCache" );
616644 NS_SetCurrentThreadName (" StartupCache" );
@@ -660,6 +688,7 @@ void StartupCache::WriteTimeout(nsITimer* aTimer, void* aClosure) {
660688 return ;
661689 }
662690
691+ startupCacheObj->WaitOnPrefetchThread ();
663692 startupCacheObj->mStartupWriteInitiated = false ;
664693 startupCacheObj->mDirty = true ;
665694 startupCacheObj->mCacheData .reset ();
0 commit comments