Bug 1656261 - Back out all recent StartupCache work r=RyanVM
authorDoug Thayer <dothayer@mozilla.com>
Mon, 14 Sep 2020 17:00:53 +0000
changeset 548593 6450088b6b73ffc17c79cd7097b1bfe30d00e207
parent 548592 b0fabcd604300d90544aa626daf1c60637148349
child 548594 c3cac1b4501625875a08050a58f681d64d3553af
push id126280
push userdothayer@mozilla.com
push dateMon, 14 Sep 2020 17:55:10 +0000
treeherderautoland@6450088b6b73 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersRyanVM
bugs1656261, 1627075
milestone82.0a1
first release with
nightly linux32
6450088b6b73 / 82.0a1 / 20200914212941 / files
nightly linux64
6450088b6b73 / 82.0a1 / 20200914212941 / files
nightly mac
6450088b6b73 / 82.0a1 / 20200914212941 / files
nightly win32
6450088b6b73 / 82.0a1 / 20200914212941 / files
nightly win64
6450088b6b73 / 82.0a1 / 20200914212941 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1656261 - Back out all recent StartupCache work r=RyanVM This backs out all work from bug 1627075 as well as all of its descendents. There were a few conflicts when backing this out but overall it was pretty clean, so I would say it's a fairly mild level of risk. Historically Nathan Froyd has reviewed these patches, but he is no longer at Mozilla, and no one else is particularly familiar with the code, so I am passing this off to RyanVM who has at least been familiar with the history of the bug. Differential Revision: https://phabricator.services.mozilla.com/D90096
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/ContentProcess.cpp
dom/ipc/PContent.ipdl
gfx/thebes/gfxFT2FontList.cpp
gfx/thebes/gfxFT2FontList.h
intl/hyphenation/glue/nsHyphenationManager.cpp
intl/hyphenation/glue/nsHyphenator.cpp
intl/locale/LocaleService.cpp
js/xpconnect/loader/IOBuffers.h
js/xpconnect/loader/URLPreloader.cpp
js/xpconnect/loader/URLPreloader.h
js/xpconnect/loader/mozJSComponentLoader.cpp
js/xpconnect/loader/mozJSSubScriptLoader.cpp
modules/libjar/nsJAR.cpp
modules/libjar/nsJAR.h
modules/libjar/nsJARInputStream.cpp
modules/libjar/nsJARInputStream.h
modules/libjar/nsZipArchive.cpp
modules/libjar/nsZipArchive.h
modules/libpref/Preferences.cpp
startupcache/PStartupCache.ipdl
startupcache/StartupCache.cpp
startupcache/StartupCache.h
startupcache/StartupCacheChild.cpp
startupcache/StartupCacheChild.h
startupcache/StartupCacheParent.cpp
startupcache/StartupCacheParent.h
startupcache/moz.build
startupcache/test/TestStartupCache.cpp
toolkit/xre/nsAppRunner.cpp
xpcom/base/AppShutdown.cpp
xpcom/build/FileLocation.cpp
xpcom/build/FileLocation.h
xpcom/build/Omnijar.cpp
xpcom/build/Omnijar.h
xpcom/build/XPCOMInit.cpp
xpcom/components/nsComponentManager.cpp
xpcom/threads/Mutex.h
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -95,17 +95,16 @@
 #include "mozilla/net/NeckoChild.h"
 #include "mozilla/net/CookieServiceChild.h"
 #include "mozilla/net/CaptivePortalService.h"
 #include "mozilla/PerformanceMetricsCollector.h"
 #include "mozilla/PerformanceUtils.h"
 #include "mozilla/plugins/PluginInstanceParent.h"
 #include "mozilla/plugins/PluginModuleParent.h"
 #include "mozilla/RemoteLazyInputStreamChild.h"
-#include "mozilla/scache/StartupCacheChild.h"
 #include "mozilla/widget/ScreenManager.h"
 #include "mozilla/widget/WidgetMessageUtils.h"
 #include "nsBaseDragService.h"
 #include "mozilla/media/MediaChild.h"
 #include "mozilla/BasePrincipal.h"
 #include "mozilla/WebBrowserPersistDocumentChild.h"
 #include "mozilla/HangDetails.h"
 #include "mozilla/LoadInfo.h"
@@ -1905,32 +1904,16 @@ mozilla::ipc::IPCResult ContentChild::Re
   if (cacheFile.type() == cacheFile.TFileDescriptor) {
     fd.emplace(cacheFile.get_FileDescriptor());
   }
 
   static_cast<loader::ScriptCacheChild*>(actor)->Init(fd, wantCacheData);
   return IPC_OK();
 }
 
-scache::PStartupCacheChild* ContentChild::AllocPStartupCacheChild() {
-  return new scache::StartupCacheChild();
-}
-
-bool ContentChild::DeallocPStartupCacheChild(
-    scache::PStartupCacheChild* cache) {
-  delete static_cast<scache::StartupCacheChild*>(cache);
-  return true;
-}
-
-mozilla::ipc::IPCResult ContentChild::RecvPStartupCacheConstructor(
-    scache::PStartupCacheChild* actor) {
-  static_cast<scache::StartupCacheChild*>(actor)->Init();
-  return IPC_OK();
-}
-
 PNeckoChild* ContentChild::AllocPNeckoChild() { return new NeckoChild(); }
 
 mozilla::ipc::IPCResult ContentChild::RecvNetworkLinkTypeChange(
     const uint32_t& aType) {
   mNetworkLinkType = aType;
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (obs) {
     obs->NotifyObservers(nullptr, "contentchild:network-link-type-changed",
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -231,23 +231,16 @@ class ContentChild final : public PConte
                                             const bool& wantCacheData);
 
   bool DeallocPScriptCacheChild(PScriptCacheChild*);
 
   virtual mozilla::ipc::IPCResult RecvPScriptCacheConstructor(
       PScriptCacheChild*, const FileDescOrError& cacheFile,
       const bool& wantCacheData) override;
 
-  PStartupCacheChild* AllocPStartupCacheChild();
-
-  bool DeallocPStartupCacheChild(PStartupCacheChild*);
-
-  virtual mozilla::ipc::IPCResult RecvPStartupCacheConstructor(
-      PStartupCacheChild*) override;
-
   PNeckoChild* AllocPNeckoChild();
 
   bool DeallocPNeckoChild(PNeckoChild*);
 
   PPrintingChild* AllocPPrintingChild();
 
   bool DeallocPPrintingChild(PPrintingChild*);
 
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -63,17 +63,16 @@
 #include "mozilla/NullPrincipal.h"
 #include "mozilla/PerformanceMetricsCollector.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/PresShell.h"
 #include "mozilla/ProcessHangMonitor.h"
 #include "mozilla/ProcessHangMonitorIPC.h"
 #include "mozilla/RDDProcessManager.h"
 #include "mozilla/ScopeExit.h"
-#include "mozilla/scache/StartupCache.h"
 #include "mozilla/ScriptPreloader.h"
 #include "mozilla/Services.h"
 #include "mozilla/Sprintf.h"
 #include "mozilla/StaticPrefs_dom.h"
 #include "mozilla/StaticPrefs_media.h"
 #include "mozilla/StyleSheet.h"
 #include "mozilla/StyleSheetInlines.h"
 #include "mozilla/Telemetry.h"
@@ -155,17 +154,16 @@
 #include "mozilla/mozSpellChecker.h"
 #include "mozilla/net/CookieServiceParent.h"
 #include "mozilla/net/NeckoMessageUtils.h"
 #include "mozilla/net/NeckoParent.h"
 #include "mozilla/net/PCookieServiceParent.h"
 #include "mozilla/plugins/PluginBridge.h"
 #include "mozilla/RemoteLazyInputStreamParent.h"
 #include "mozilla/widget/ScreenManager.h"
-#include "mozilla/scache/StartupCacheParent.h"
 #include "nsAnonymousTemporaryFile.h"
 #include "nsAppRunner.h"
 #include "nsCExternalHandlerService.h"
 #include "nsCOMPtr.h"
 #include "nsChromeRegistryChrome.h"
 #include "nsConsoleMessage.h"
 #include "nsConsoleService.h"
 #include "nsContentPermissionHelper.h"
@@ -2300,22 +2298,16 @@ bool ContentParent::BeginSubprocessLaunc
   // `LaunchSubprocessReject`/`LaunchSubprocessResolve`.
   mPrefSerializer = MakeUnique<mozilla::ipc::SharedPreferenceSerializer>();
   if (!mPrefSerializer->SerializeToSharedMemory()) {
     MarkAsDead();
     return false;
   }
   mPrefSerializer->AddSharedPrefCmdLineArgs(*mSubprocess, extraArgs);
 
-  auto startupCache = mozilla::scache::StartupCache::GetSingleton();
-  if (startupCache) {
-    startupCache->AddStartupCacheCmdLineArgs(*mSubprocess, GetRemoteType(),
-                                             extraArgs);
-  }
-
   // Register ContentParent as an observer for changes to any pref
   // whose prefix matches the empty string, i.e. all of them.  The
   // observation starts here in order to capture pref updates that
   // happen during async launch.
   Preferences::AddStrongObserver(this, "");
 
   if (gSafeMode) {
     extraArgs.push_back("-safeMode");
@@ -2740,17 +2732,16 @@ bool ContentParent::InitInternal(Process
   }
 
   // Send the child its remote type. On Mac, this needs to be sent prior
   // to the message we send to enable the Sandbox (SendStartProcessSandbox)
   // because different remote types require different sandbox privileges.
   Unused << SendRemoteType(mRemoteType);
 
   ScriptPreloader::InitContentChild(*this);
-  scache::StartupCache::InitContentChild(*this);
 
   // Initialize the message manager (and load delayed scripts) now that we
   // have established communications with the child.
   mMessageManager->InitWithCallback(this);
   mMessageManager->SetOsPid(Pid());
 
   // Set the subprocess's priority.  We do this early on because we're likely
   // /lowering/ the process's CPU and memory priority, which it has inherited
@@ -3852,25 +3843,16 @@ PScriptCacheParent* ContentParent::Alloc
   return new loader::ScriptCacheParent(wantCacheData);
 }
 
 bool ContentParent::DeallocPScriptCacheParent(PScriptCacheParent* cache) {
   delete static_cast<loader::ScriptCacheParent*>(cache);
   return true;
 }
 
-PStartupCacheParent* ContentParent::AllocPStartupCacheParent() {
-  return new scache::StartupCacheParent();
-}
-
-bool ContentParent::DeallocPStartupCacheParent(PStartupCacheParent* cache) {
-  delete static_cast<scache::StartupCacheParent*>(cache);
-  return true;
-}
-
 PNeckoParent* ContentParent::AllocPNeckoParent() { return new NeckoParent(); }
 
 bool ContentParent::DeallocPNeckoParent(PNeckoParent* necko) {
   delete necko;
   return true;
 }
 
 PPrintingParent* ContentParent::AllocPPrintingParent() {
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -66,17 +66,16 @@ class PRemoteSpellcheckEngineParent;
 class SandboxBroker;
 class SandboxBrokerPolicyFactory;
 #endif
 
 class PreallocatedProcessManagerImpl;
 class BenchmarkStorageParent;
 
 using mozilla::loader::PScriptCacheParent;
-using mozilla::scache::PStartupCacheParent;
 
 namespace embedding {
 class PrintingParent;
 }
 
 namespace ipc {
 class CrashReporterHost;
 class PFileDescriptorSetParent;
@@ -932,20 +931,16 @@ class ContentParent final
 
   bool DeallocPTestShellParent(PTestShellParent* shell);
 
   PScriptCacheParent* AllocPScriptCacheParent(const FileDescOrError& cacheFile,
                                               const bool& wantCacheData);
 
   bool DeallocPScriptCacheParent(PScriptCacheParent* shell);
 
-  PStartupCacheParent* AllocPStartupCacheParent();
-
-  bool DeallocPStartupCacheParent(PStartupCacheParent* shell);
-
   bool DeallocPNeckoParent(PNeckoParent* necko);
 
   already_AddRefed<PExternalHelperAppParent> AllocPExternalHelperAppParent(
       nsIURI* aUri, const Maybe<mozilla::net::LoadInfoArgs>& aLoadInfoArgs,
       const nsCString& aMimeContentType, const nsCString& aContentDisposition,
       const uint32_t& aContentDispositionHint,
       const nsString& aContentDispositionFilename, const bool& aForceSave,
       const int64_t& aContentLength, const bool& aWasFileChannel,
--- a/dom/ipc/ContentProcess.cpp
+++ b/dom/ipc/ContentProcess.cpp
@@ -79,19 +79,16 @@ static void SetUpSandboxEnvironment() {
 bool ContentProcess::Init(int aArgc, char* aArgv[]) {
   Maybe<uint64_t> childID;
   Maybe<bool> isForBrowser;
   Maybe<const char*> parentBuildID;
   char* prefsHandle = nullptr;
   char* prefMapHandle = nullptr;
   char* prefsLen = nullptr;
   char* prefMapSize = nullptr;
-  char* scacheHandle = nullptr;
-  char* scacheSize = nullptr;
-  bool wantsScache = true;
 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
   nsCOMPtr<nsIFile> profileDir;
 #endif
 
   for (int i = 1; i < aArgc; i++) {
     if (!aArgv[i]) {
       continue;
     }
@@ -125,40 +122,28 @@ bool ContentProcess::Init(int aArgc, cha
         return false;
       }
       prefsHandle = aArgv[i];
     } else if (strcmp(aArgv[i], "-prefMapHandle") == 0) {
       if (++i == aArgc) {
         return false;
       }
       prefMapHandle = aArgv[i];
-    } else if (strcmp(aArgv[i], "-scacheHandle") == 0) {
-      if (++i == aArgc) {
-        return false;
-      }
-      scacheHandle = aArgv[i];
 #endif
 
     } else if (strcmp(aArgv[i], "-prefsLen") == 0) {
       if (++i == aArgc) {
         return false;
       }
       prefsLen = aArgv[i];
     } else if (strcmp(aArgv[i], "-prefMapSize") == 0) {
       if (++i == aArgc) {
         return false;
       }
       prefMapSize = aArgv[i];
-    } else if (strcmp(aArgv[i], "-scacheSize") == 0) {
-      if (++i == aArgc) {
-        return false;
-      }
-      scacheSize = aArgv[i];
-    } else if (strcmp(aArgv[i], "-noScache") == 0) {
-      wantsScache = false;
     } else if (strcmp(aArgv[i], "-safeMode") == 0) {
       gSafeMode = true;
 
     } else if (strcmp(aArgv[i], "-parentBuildID") == 0) {
       if (++i == aArgc) {
         return false;
       }
       parentBuildID = Some(aArgv[i]);
@@ -185,21 +170,16 @@ bool ContentProcess::Init(int aArgc, cha
   }
 
   SharedPreferenceDeserializer deserializer;
   if (!deserializer.DeserializeFromSharedMemory(prefsHandle, prefMapHandle,
                                                 prefsLen, prefMapSize)) {
     return false;
   }
 
-  if (wantsScache) {
-    Unused << mozilla::scache::StartupCache::InitChildSingleton(scacheHandle,
-                                                                scacheSize);
-  }
-
   mContent.Init(IOThreadChild::message_loop(), ParentPid(), *parentBuildID,
                 IOThreadChild::TakeChannel(), *childID, *isForBrowser);
 
   mXREEmbed.Start();
 #if (defined(XP_MACOSX)) && defined(MOZ_SANDBOX)
   mContent.SetProfileDir(profileDir);
 #  if defined(DEBUG)
   if (IsContentSandboxEnabled()) {
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -39,17 +39,16 @@ include protocol PWebrtcGlobal;
 include protocol PWindowGlobal;
 include protocol PPresentation;
 include protocol PURLClassifier;
 include protocol PURLClassifierLocal;
 include protocol PVRManager;
 include protocol PRemoteDecoderManager;
 include protocol PProfiler;
 include protocol PScriptCache;
-include protocol PStartupCache;
 include protocol PSessionStorageObserver;
 include protocol PBenchmarkStorage;
 include DOMTypes;
 include WindowGlobalTypes;
 include IPCBlob;
 include IPCStream;
 include PTabContext;
 include PluginTypes;
@@ -411,17 +410,16 @@ nested(upto inside_cpow) sync protocol P
     manages PTestShell;
     manages PRemoteSpellcheckEngine;
     manages PWebBrowserPersistDocument;
     manages PWebrtcGlobal;
     manages PPresentation;
     manages PURLClassifier;
     manages PURLClassifierLocal;
     manages PScriptCache;
-    manages PStartupCache;
     manages PLoginReputation;
     manages PSessionStorageObserver;
     manages PBenchmarkStorage;
 
     // Depending on exactly how the new browser is being created, it might be
     // created from either the child or parent process!
     //
     // The child creates the PBrowser as part of
@@ -541,18 +539,16 @@ child:
     async PCycleCollectWithLogs(bool dumpAllTraces,
                                 FileDescriptor gcLog,
                                 FileDescriptor ccLog);
 
     async PTestShell();
 
     async PScriptCache(FileDescOrError cacheFile, bool wantCacheData);
 
-    async PStartupCache();
-
     async RegisterChrome(ChromePackage[] packages, SubstitutionMapping[] substitutions,
                          OverrideMapping[] overrides, nsCString locale, bool reset);
     async RegisterChromeItem(ChromeRegistryItem item);
 
     async ClearImageCache(bool privateLoader, bool chrome);
 
     async ClearStyleSheetCache(nsIPrincipal? aForPrincipal);
 
--- a/gfx/thebes/gfxFT2FontList.cpp
+++ b/gfx/thebes/gfxFT2FontList.cpp
@@ -90,24 +90,24 @@ already_AddRefed<SharedFTFace> FT2FontEn
   // A relative path (no initial "/") means this is a resource in
   // omnijar, not an installed font on the device.
   // The NS_ASSERTIONs here should never fail, as the resource must have
   // been read successfully during font-list initialization or we'd never
   // have created the font entry. The only legitimate runtime failure
   // here would be memory allocation, in which case mFace remains null.
   RefPtr<SharedFTFace> face;
   if (mFilename[0] != '/') {
-    RefPtr<CacheAwareZipReader> reader = Omnijar::GetReader(Omnijar::Type::GRE);
+    RefPtr<nsZipArchive> reader = Omnijar::GetReader(Omnijar::Type::GRE);
     nsZipItem* item = reader->GetItem(mFilename.get());
     NS_ASSERTION(item, "failed to find zip entry");
 
     uint32_t bufSize = item->RealSize();
     uint8_t* fontDataBuf = static_cast<uint8_t*>(malloc(bufSize));
     if (fontDataBuf) {
-      CacheAwareZipCursor cursor(item, reader, fontDataBuf, bufSize);
+      nsZipCursor cursor(item, reader, fontDataBuf, bufSize);
       cursor.Copy(&bufSize);
       NS_ASSERTION(bufSize == item->RealSize(), "error reading bundled font");
       RefPtr<FTUserFontData> ufd = new FTUserFontData(fontDataBuf, bufSize);
       face = ufd->CloneFace(mFTFontIndex);
       if (!face) {
         NS_WARNING("failed to create freetype face");
         return nullptr;
       }
@@ -465,29 +465,28 @@ hb_blob_t* FT2FontEntry::GetFontTable(ui
         hb_face_t* face = hb_face_create(fileBlob, mFTFontIndex);
         result = hb_face_reference_table(face, aTableTag);
         hb_face_destroy(face);
       }
       hb_blob_destroy(fileBlob);
     } else {
       // A relative path means an omnijar resource, which we may need to
       // decompress to a temporary buffer.
-      RefPtr<CacheAwareZipReader> reader =
-          Omnijar::GetReader(Omnijar::Type::GRE);
+      RefPtr<nsZipArchive> reader = Omnijar::GetReader(Omnijar::Type::GRE);
       nsZipItem* item = reader->GetItem(mFilename.get());
       MOZ_ASSERT(item, "failed to find zip entry");
       if (item) {
         // TODO(jfkthame):
         // Check whether the item is compressed; if not, we could just get a
         // pointer without needing to allocate a buffer and copy the data.
         // (Currently this configuration isn't used for Gecko on Android.)
         uint32_t length = item->RealSize();
         uint8_t* buffer = static_cast<uint8_t*>(malloc(length));
         if (buffer) {
-          CacheAwareZipCursor cursor(item, reader, buffer, length);
+          nsZipCursor cursor(item, reader, buffer, length);
           cursor.Copy(&length);
           MOZ_ASSERT(length == item->RealSize(), "error reading font");
           if (length == item->RealSize()) {
             hb_blob_t* blob =
                 hb_blob_create((const char*)buffer, length,
                                HB_MEMORY_MODE_READONLY, buffer, free);
             hb_face_t* face = hb_face_create(blob, mFTFontIndex);
             result = hb_face_reference_table(face, aTableTag);
@@ -1167,17 +1166,17 @@ void gfxFT2FontList::FindFontsInOmnijar(
     if (mJarModifiedTime > LittleEndian::readInt64(cachedModifiedTimeBuf)) {
       jarChanged = true;
     }
   }
 
   static const char* sJarSearchPaths[] = {
       "res/fonts/*.ttf$",
   };
-  RefPtr<CacheAwareZipReader> reader = Omnijar::GetReader(Omnijar::Type::GRE);
+  RefPtr<nsZipArchive> reader = Omnijar::GetReader(Omnijar::Type::GRE);
   for (unsigned i = 0; i < ArrayLength(sJarSearchPaths); i++) {
     nsZipFind* find;
     if (NS_SUCCEEDED(reader->FindInit(sJarSearchPaths[i], &find))) {
       const char* path;
       uint16_t len;
       while (NS_SUCCEEDED(find->FindNext(&path, &len))) {
         nsCString entryName(path, len);
         AppendFacesFromOmnijarEntry(reader, entryName, aCache, jarChanged);
@@ -1282,17 +1281,17 @@ void gfxFT2FontList::AddFaceToList(const
            " with style: %s weight: %s stretch: %s",
            fe->Name().get(), familyName.get(),
            fe->IsItalic() ? "italic" : "normal", weightString.get(),
            stretchString.get()));
     }
   }
 }
 
-void gfxFT2FontList::AppendFacesFromOmnijarEntry(CacheAwareZipReader* aArchive,
+void gfxFT2FontList::AppendFacesFromOmnijarEntry(nsZipArchive* aArchive,
                                                  const nsCString& aEntryName,
                                                  FontNameCache* aCache,
                                                  bool aJarChanged) {
   nsCString faceList;
   if (aCache && !aJarChanged) {
     uint32_t filesize, timestamp;
     aCache->GetInfoForFile(aEntryName, faceList, &timestamp, &filesize);
     if (faceList.Length() > 0) {
@@ -1321,17 +1320,17 @@ void gfxFT2FontList::AppendFacesFromOmni
 
   // We use fallible allocation here; if there's not enough RAM, we'll simply
   // ignore the bundled fonts and fall back to the device's installed fonts.
   char* buffer = static_cast<char*>(malloc(bufSize));
   if (!buffer) {
     return;
   }
 
-  CacheAwareZipCursor cursor(item, aArchive, (uint8_t*)buffer, bufSize);
+  nsZipCursor cursor(item, aArchive, (uint8_t*)buffer, bufSize);
   uint8_t* data = cursor.Copy(&bufSize);
   MOZ_ASSERT(data && bufSize == item->RealSize(), "error reading bundled font");
   if (!data) {
     return;
   }
 
   hb_blob_t* blob =
       hb_blob_create(buffer, bufSize, HB_MEMORY_MODE_READONLY, buffer, free);
--- a/gfx/thebes/gfxFT2FontList.h
+++ b/gfx/thebes/gfxFT2FontList.h
@@ -6,19 +6,16 @@
 #ifndef GFX_FT2FONTLIST_H
 #define GFX_FT2FONTLIST_H
 
 #include "mozilla/MemoryReporting.h"
 #include "gfxFT2FontBase.h"
 #include "gfxPlatformFontList.h"
 
 namespace mozilla {
-
-class CacheAwareZipReader;
-
 namespace dom {
 class SystemFontListEntry;
 };
 };  // namespace mozilla
 
 class FontNameCache;
 typedef struct FT_FaceRec_* FT_Face;
 class nsZipArchive;
@@ -172,17 +169,17 @@ class gfxFT2FontList final : public gfxP
 
   void AppendFacesFromBlob(const nsCString& aFileName, StandardFile aStdFile,
                            hb_blob_t* aBlob, FontNameCache* aCache,
                            uint32_t aTimestamp, uint32_t aFilesize);
 
   void AppendFacesFromFontFile(const nsCString& aFileName,
                                FontNameCache* aCache, StandardFile aStdFile);
 
-  void AppendFacesFromOmnijarEntry(mozilla::CacheAwareZipReader* aArchive,
+  void AppendFacesFromOmnijarEntry(nsZipArchive* aReader,
                                    const nsCString& aEntryName,
                                    FontNameCache* aCache, bool aJarChanged);
 
   void InitSharedFontListForPlatform() override;
   void CollectInitData(const FontListEntry& aFLE, const nsCString& aPSName,
                        const nsCString& aFullName, StandardFile aStdFile);
 
   /**
--- a/intl/hyphenation/glue/nsHyphenationManager.cpp
+++ b/intl/hyphenation/glue/nsHyphenationManager.cpp
@@ -222,17 +222,17 @@ static already_AddRefed<nsAtom> LocaleAt
 
 void nsHyphenationManager::LoadPatternListFromOmnijar(Omnijar::Type aType) {
   nsCString base;
   nsresult rv = Omnijar::GetURIString(aType, base);
   if (NS_FAILED(rv)) {
     return;
   }
 
-  RefPtr<CacheAwareZipReader> zip = Omnijar::GetReader(aType);
+  RefPtr<nsZipArchive> zip = Omnijar::GetReader(aType);
   if (!zip) {
     return;
   }
 
   nsZipFind* find;
   zip->FindInit("hyphenation/hyph_*.hyf", &find);
   if (!find) {
     return;
--- a/intl/hyphenation/glue/nsHyphenator.cpp
+++ b/intl/hyphenation/glue/nsHyphenator.cpp
@@ -36,21 +36,30 @@ static const void* GetItemPtrFromJarURI(
   if (!fileUrl) {
     return nullptr;
   }
   nsCOMPtr<nsIFile> file;
   fileUrl->GetFile(getter_AddRefs(file));
   if (!file) {
     return nullptr;
   }
-  RefPtr<CacheAwareZipReader> archive = Omnijar::GetReader(file);
+  RefPtr<nsZipArchive> archive = Omnijar::GetReader(file);
   if (archive) {
     nsCString path;
     aJAR->GetJAREntry(path);
-    return archive->GetData(path.get(), aLength);
+    nsZipItem* item = archive->GetItem(path.get());
+    if (item && item->Compression() == 0 && item->Size() > 0) {
+      // We do NOT own this data, but it won't go away until the omnijar
+      // file is closed during shutdown.
+      const uint8_t* data = archive->GetData(item);
+      if (data) {
+        *aLength = item->Size();
+        return data;
+      }
+    }
   }
   return nullptr;
 }
 
 already_AddRefed<ipc::SharedMemoryBasic> GetHyphDictFromParent(
     nsIURI* aURI, uint32_t* aLength) {
   MOZ_ASSERT(!XRE_IsParentProcess());
   ipc::SharedMemoryBasic::Handle handle = ipc::SharedMemoryBasic::NULLHandle();
--- a/intl/locale/LocaleService.cpp
+++ b/intl/locale/LocaleService.cpp
@@ -290,36 +290,23 @@ bool LocaleService::LanguagesMatch(const
   Locale available = Locale(aAvailable);
   return requested.GetLanguage().Equals(available.GetLanguage());
 }
 
 bool LocaleService::IsServer() { return mIsServer; }
 
 static bool GetGREFileContents(const char* aFilePath, nsCString* aOutString) {
   // Look for the requested file in omnijar.
-  RefPtr<CacheAwareZipReader> zip = Omnijar::GetReader(Omnijar::GRE);
+  RefPtr<nsZipArchive> zip = Omnijar::GetReader(Omnijar::GRE);
   if (zip) {
-    const auto item = zip->GetItem(aFilePath);
+    nsZipItemPtr<char> item(zip, aFilePath);
     if (!item) {
       return false;
     }
-
-    MOZ_ASSERT(item->RealSize());
-
-    auto buf = MakeUnique<uint8_t[]>(item->RealSize());
-    CacheAwareZipCursor cursor(item, zip, buf.get(), item->RealSize());
-
-    uint32_t count;
-    uint8_t* data = cursor.Read(&count);
-
-    if (count != item->RealSize()) {
-      return false;
-    }
-
-    aOutString->Assign(reinterpret_cast<const char*>(data), count);
+    aOutString->Assign(item.Buffer(), item.Length());
     return true;
   }
 
   // If we didn't have an omnijar (i.e. we're running a non-packaged
   // build), then look in the GRE directory.
   nsCOMPtr<nsIFile> path;
   if (NS_FAILED(nsDirectoryService::gService->Get(
           NS_GRE_DIR, NS_GET_IID(nsIFile), getter_AddRefs(path)))) {
--- a/js/xpconnect/loader/IOBuffers.h
+++ b/js/xpconnect/loader/IOBuffers.h
@@ -59,92 +59,16 @@ class OutputBuffer {
 
   const uint8_t* Get() const { return data.Elements(); }
 
  private:
   nsTArray<uint8_t> data;
   size_t cursor_ = 0;
 };
 
-// This is similar to OutputBuffer, but with a fixed-size buffer, rather than
-// a dynamically growing one. This is currently used in order to share
-// StartupCache data across processes.
-class PreallocatedOutputBuffer {
- public:
-  explicit PreallocatedOutputBuffer(Range<uint8_t>& buffer) : data(buffer) {}
-
-  uint8_t* write(size_t size) {
-    MOZ_ASSERT(checkCapacity(size));
-
-    auto buf = &data[cursor_];
-    cursor_ += size;
-    return buf;
-  }
-
-  bool codeUint8(const uint8_t& val) {
-    if (checkCapacity(sizeof val)) {
-      *write(sizeof val) = val;
-    }
-    return !error_;
-  }
-
-  template <typename T>
-  bool codeUint8(const EnumSet<T>& val) {
-    return codeUint8(val.serialize());
-  }
-
-  bool codeUint16(const uint16_t& val) {
-    if (checkCapacity(sizeof val)) {
-      LittleEndian::writeUint16(write(sizeof val), val);
-    }
-    return !error_;
-  }
-
-  bool codeUint32(const uint32_t& val) {
-    if (checkCapacity(sizeof val)) {
-      LittleEndian::writeUint32(write(sizeof val), val);
-    }
-    return !error_;
-  }
-
-  bool codeString(const nsCString& str) {
-    uint16_t len = CheckedUint16(str.Length()).value();
-    if (codeUint16(len)) {
-      if (checkCapacity(len)) {
-        memcpy(write(len), str.get(), len);
-      }
-    }
-    return !error_;
-  }
-
-  bool error() { return error_; }
-
-  bool finished() { return error_ || !remainingCapacity(); }
-
-  size_t remainingCapacity() { return data.length() - cursor_; }
-
-  bool checkCapacity(size_t size) {
-    if (size > remainingCapacity()) {
-      error_ = true;
-    }
-    return !error_;
-  }
-
-  size_t cursor() const { return cursor_; }
-
-  const uint8_t* Get() const { return data.begin().get(); }
-
- private:
-  bool error_ = false;
-
- public:
-  Range<uint8_t>& data;
-  size_t cursor_ = 0;
-};
-
 class InputBuffer {
  public:
   explicit InputBuffer(const Range<uint8_t>& buffer) : data(buffer) {}
 
   const uint8_t* read(size_t size) {
     MOZ_ASSERT(checkCapacity(size));
 
     auto buf = &data[cursor_];
@@ -194,28 +118,28 @@ class InputBuffer {
   }
 
   bool error() { return error_; }
 
   bool finished() { return error_ || !remainingCapacity(); }
 
   size_t remainingCapacity() { return data.length() - cursor_; }
 
+  size_t cursor() const { return cursor_; }
+
+  const uint8_t* Get() const { return data.begin().get(); }
+
+ private:
   bool checkCapacity(size_t size) {
     if (size > remainingCapacity()) {
       error_ = true;
     }
     return !error_;
   }
 
-  size_t cursor() const { return cursor_; }
-
-  const uint8_t* Get() const { return data.begin().get(); }
-
- private:
   bool error_ = false;
 
  public:
   const Range<uint8_t>& data;
   size_t cursor_ = 0;
 };
 
 }  // namespace loader
--- a/js/xpconnect/loader/URLPreloader.cpp
+++ b/js/xpconnect/loader/URLPreloader.cpp
@@ -324,17 +324,17 @@ Result<Ok, nsresult> URLPreloader::ReadC
 
 void URLPreloader::BackgroundReadFiles() {
   auto cleanup = MakeScopeExit([&]() {
     NS_DispatchToMainThread(NewRunnableMethod(
         "nsIThread::AsyncShutdown", mReaderThread, &nsIThread::AsyncShutdown));
     mReaderThread = nullptr;
   });
 
-  Vector<CacheAwareZipCursor> cursors;
+  Vector<nsZipCursor> cursors;
   LinkedList<URLEntry> pendingURLs;
   {
     MonitorAutoLock mal(mMonitor);
 
     if (ReadCache(pendingURLs).isErr()) {
       mReaderInitialized = true;
       mal.NotifyAll();
       return;
@@ -354,24 +354,24 @@ void URLPreloader::BackgroundReadFiles()
     // until this segment is done. Once the cursors have been initialized,
     // the actual reading and decompression can safely be done off-thread,
     // as is the case for thread-retargeted jar: channels.
     for (auto entry : pendingURLs) {
       if (entry->mType == entry->TypeFile) {
         continue;
       }
 
-      RefPtr<CacheAwareZipReader> zip = entry->Archive();
+      RefPtr<nsZipArchive> zip = entry->Archive();
       if (!zip) {
         MOZ_CRASH_UNSAFE_PRINTF(
             "Failed to get Omnijar %s archive for entry (path: \"%s\")",
             entry->TypeString(), entry->mPath.get());
       }
 
-      auto* item = zip->GetItem(entry->mPath.get());
+      auto item = zip->GetItem(entry->mPath.get());
       if (!item) {
         entry->mResultCode = NS_ERROR_FILE_NOT_FOUND;
         continue;
       }
 
       size_t size = item->RealSize();
 
       entry->mData.SetLength(size);
@@ -497,35 +497,35 @@ Result<nsCString, nsresult> URLPreloader
     return URLEntry::ReadLocation(location);
   }
 
   nsCOMPtr<nsIFile> file = location.GetBaseFile();
   return ReadFile(file, readType);
 }
 
 /* static */ Result<nsCString, nsresult> URLPreloader::ReadZip(
-    CacheAwareZipReader* archive, const nsACString& path, ReadType readType) {
+    nsZipArchive* zip, const nsACString& path, ReadType readType) {
   // If the zip archive belongs to an Omnijar location, map it to a cache
   // entry, and cache it as normal. Otherwise, simply read the entry
   // synchronously, since other JAR archives are currently unsupported by the
   // cache.
-  RefPtr<CacheAwareZipReader> reader = Omnijar::GetReader(Omnijar::GRE);
-  if (reader == archive) {
+  RefPtr<nsZipArchive> reader = Omnijar::GetReader(Omnijar::GRE);
+  if (zip == reader) {
     CacheKey key(CacheKey::TypeGREJar, path);
     return Read(key, readType);
   }
 
   reader = Omnijar::GetReader(Omnijar::APP);
-  if (reader == archive) {
+  if (zip == reader) {
     CacheKey key(CacheKey::TypeAppJar, path);
     return Read(key, readType);
   }
 
   // Not an Omnijar archive, so just read it directly.
-  FileLocation location(archive, PromiseFlatCString(path).BeginReading());
+  FileLocation location(zip, PromiseFlatCString(path).BeginReading());
   return URLEntry::ReadLocation(location);
 }
 
 Result<URLPreloader::CacheKey, nsresult> URLPreloader::ResolveURI(nsIURI* uri) {
   nsCString spec;
   nsCString scheme;
   MOZ_TRY(uri->GetSpec(spec));
   MOZ_TRY(uri->GetScheme(scheme));
@@ -583,17 +583,17 @@ size_t URLPreloader::ShallowSizeOfInclud
 Result<FileLocation, nsresult> URLPreloader::CacheKey::ToFileLocation() {
   if (mType == TypeFile) {
     nsCOMPtr<nsIFile> file;
     MOZ_TRY(NS_NewLocalFile(NS_ConvertUTF8toUTF16(mPath), false,
                             getter_AddRefs(file)));
     return FileLocation(file);
   }
 
-  RefPtr<CacheAwareZipReader> zip = Archive();
+  RefPtr<nsZipArchive> zip = Archive();
   return FileLocation(zip, mPath.get());
 }
 
 Result<nsCString, nsresult> URLPreloader::URLEntry::Read() {
   FileLocation location;
   MOZ_TRY_VAR(location, ToFileLocation());
 
   MOZ_TRY_VAR(mData, ReadLocation(location));
--- a/js/xpconnect/loader/URLPreloader.h
+++ b/js/xpconnect/loader/URLPreloader.h
@@ -21,16 +21,18 @@
 #include "nsIFile.h"
 #include "nsIURI.h"
 #include "nsIMemoryReporter.h"
 #include "nsIObserver.h"
 #include "nsIResProtocolHandler.h"
 #include "nsIThread.h"
 #include "nsReadableUtils.h"
 
+class nsZipArchive;
+
 namespace mozilla {
 namespace loader {
 class InputBuffer;
 }
 
 using namespace mozilla::loader;
 
 class ScriptPreloader;
@@ -70,17 +72,17 @@ class URLPreloader final : public nsIObs
                                           ReadType readType = Forget);
 
   static Result<nsCString, nsresult> ReadURI(nsIURI* uri,
                                              ReadType readType = Forget);
 
   static Result<nsCString, nsresult> ReadFile(nsIFile* file,
                                               ReadType readType = Forget);
 
-  static Result<nsCString, nsresult> ReadZip(CacheAwareZipReader* archive,
+  static Result<nsCString, nsresult> ReadZip(nsZipArchive* archive,
                                              const nsACString& path,
                                              ReadType readType = Forget);
 
  private:
   struct CacheKey;
 
   Result<nsCString, nsresult> ReadInternal(const CacheKey& key,
                                            ReadType readType);
@@ -190,17 +192,17 @@ class URLPreloader final : public nsIObs
           return "GREJar";
         case TypeFile:
           return "File";
       }
       MOZ_ASSERT_UNREACHABLE("no such type");
       return "";
     }
 
-    already_AddRefed<CacheAwareZipReader> Archive() {
+    already_AddRefed<nsZipArchive> Archive() {
       return Omnijar::GetReader(OmnijarType());
     }
 
     Result<FileLocation, nsresult> ToFileLocation();
 
     EntryType mType = TypeFile;
 
     // The path of the entry. For Type*Jar entries, this is the path within
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -17,17 +17,17 @@
 #  include <windows.h>
 #endif
 
 #include "jsapi.h"
 #include "js/Array.h"  // JS::GetArrayLength, JS::IsArrayObject
 #include "js/CharacterEncoding.h"
 #include "js/CompilationAndEvaluation.h"
 #include "js/friend/JSMEnvironment.h"  // JS::ExecuteInJSMEnvironment, JS::GetJSMEnvironmentOfScriptedCaller, JS::NewJSMEnvironment
-#include "js/Object.h"  // JS::GetCompartment
+#include "js/Object.h"                 // JS::GetCompartment
 #include "js/Printf.h"
 #include "js/PropertySpec.h"
 #include "js/SourceText.h"  // JS::SourceText
 #include "nsCOMPtr.h"
 #include "nsExceptionHandler.h"
 #include "nsIComponentManager.h"
 #include "mozilla/Module.h"
 #include "nsIFile.h"
@@ -49,17 +49,16 @@
 #include "AutoMemMap.h"
 #include "ScriptPreloader-inl.h"
 
 #include "mozilla/scache/StartupCache.h"
 #include "mozilla/scache/StartupCacheUtils.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/MacroForEach.h"
 #include "mozilla/Preferences.h"
-#include "mozilla/Omnijar.h"
 #include "mozilla/ResultExtensions.h"
 #include "mozilla/ScriptPreloader.h"
 #include "mozilla/ScopeExit.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/ResultExtensions.h"
 #include "mozilla/UniquePtrExtensions.h"
 #include "mozilla/Unused.h"
 
@@ -660,20 +659,16 @@ JSObject* mozJSComponentLoader::PrepareO
     return nullptr;
   }
 
   return thisObj;
 }
 
 static mozilla::Result<nsCString, nsresult> ReadScript(
     ComponentLoaderInfo& aInfo) {
-  // We're going to cache the XDR encoded script data - suspend writes via the
-  // CacheAwareZipReader, otherwise we'll end up redundantly caching scripts.
-  AutoSuspendStartupCacheWrites suspendScache;
-
   MOZ_TRY(aInfo.EnsureScriptChannel());
 
   nsCOMPtr<nsIInputStream> scriptStream;
   MOZ_TRY(NS_MaybeOpenChannelUsingOpen(aInfo.ScriptChannel(),
                                        getter_AddRefs(scriptStream)));
 
   uint64_t len64;
   uint32_t bytesRead;
@@ -725,25 +720,17 @@ nsresult mozJSComponentLoader::ObjectFor
   rv = aInfo.URI()->GetSpec(nativePath);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Before compiling the script, first check to see if we have it in
   // the startupcache.  Note: as a rule, startupcache errors are not fatal
   // to loading the script, since we can always slow-load.
 
   bool writeToCache = false;
-
-  // Since we are intending to cache these buffers in the script preloader
-  // already, caching them in the StartupCache tends to be redundant. This
-  // ought to be addressed, but as in bug 1627075 we extended the
-  // StartupCache to be multi-process, we just didn't want to propagate
-  // this problem into yet more processes, so we pretend the StartupCache
-  // doesn't exist if we're not the parent process.
-  StartupCache* cache =
-      XRE_IsParentProcess() ? StartupCache::GetSingleton() : nullptr;
+  StartupCache* cache = StartupCache::GetSingleton();
 
   aInfo.EnsureResolvedURI();
 
   nsAutoCString cachePath(JS_CACHE_PREFIX("non-syntactic"));
   rv = PathifyURI(aInfo.ResolvedURI(), cachePath);
   NS_ENSURE_SUCCESS(rv, rv);
 
   script = ScriptPreloader::GetSingleton().GetCachedScript(cx, cachePath);
--- a/js/xpconnect/loader/mozJSSubScriptLoader.cpp
+++ b/js/xpconnect/loader/mozJSSubScriptLoader.cpp
@@ -15,22 +15,21 @@
 #include "nsNetCID.h"
 #include "nsNetUtil.h"
 
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "xpcprivate.h"                   // xpc::OptionsBase
 #include "js/CompilationAndEvaluation.h"  // JS::Compile
 #include "js/friend/JSMEnvironment.h"  // JS::ExecuteInJSMEnvironment, JS::IsJSMEnvironment
-#include "js/SourceText.h"                // JS::Source{Ownership,Text}
+#include "js/SourceText.h"             // JS::Source{Ownership,Text}
 #include "js/Wrapper.h"
 
 #include "mozilla/ContentPrincipal.h"
 #include "mozilla/dom/ScriptLoader.h"
-#include "mozilla/Omnijar.h"
 #include "mozilla/ScriptPreloader.h"
 #include "mozilla/SystemPrincipal.h"
 #include "mozilla/scache/StartupCache.h"
 #include "mozilla/scache/StartupCacheUtils.h"
 #include "mozilla/Unused.h"
 #include "mozilla/Utf8.h"  // mozilla::Utf8Unit
 #include "nsContentUtils.h"
 #include "nsString.h"
@@ -246,20 +245,16 @@ static bool EvalScript(JSContext* cx, Ha
 }
 
 bool mozJSSubScriptLoader::ReadScript(JS::MutableHandle<JSScript*> script,
                                       nsIURI* uri, JSContext* cx,
                                       HandleObject targetObj,
                                       const char* uriStr, nsIIOService* serv,
                                       bool wantReturnValue,
                                       bool useCompilationScope) {
-  // We're going to cache the XDR encoded script data - suspend writes via the
-  // CacheAwareZipReader, otherwise we'll end up redundantly caching scripts.
-  AutoSuspendStartupCacheWrites suspendScache;
-
   // We create a channel and call SetContentType, to avoid expensive MIME type
   // lookups (bug 632490).
   nsCOMPtr<nsIChannel> chan;
   nsCOMPtr<nsIInputStream> instream;
   nsresult rv;
   rv = NS_NewChannel(getter_AddRefs(chan), uri,
                      nsContentUtils::GetSystemPrincipal(),
                      nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
@@ -467,25 +462,17 @@ nsresult mozJSSubScriptLoader::DoLoadSub
                             filePath.EqualsLiteral("newtab") ||
                             filePath.EqualsLiteral("welcome");
       isSystem = true;
     }
   }
   bool ignoreCache =
       options.ignoreCache || !isSystem || scheme.EqualsLiteral("blob");
 
-  // Since we are intending to cache these buffers in the script preloader
-  // already, caching them in the StartupCache tends to be redundant. This
-  // ought to be addressed, but as in bug 1627075 we extended the
-  // StartupCache to be multi-process, we just didn't want to propagate
-  // this problem into yet more processes, so we pretend the StartupCache
-  // doesn't exist if we're not the parent process.
-  StartupCache* cache = (ignoreCache || !XRE_IsParentProcess())
-                            ? nullptr
-                            : StartupCache::GetSingleton();
+  StartupCache* cache = ignoreCache ? nullptr : StartupCache::GetSingleton();
 
   nsAutoCString cachePath;
   SubscriptCachePath(cx, uri, targetObj, cachePath);
 
   RootedScript script(cx);
   if (!options.ignoreCache) {
     if (!options.wantReturnValue) {
       script = ScriptPreloader::GetSingleton().GetCachedScript(cx, cachePath);
--- a/modules/libjar/nsJAR.cpp
+++ b/modules/libjar/nsJAR.cpp
@@ -21,17 +21,17 @@
 using namespace mozilla;
 
 //----------------------------------------------
 // nsJAR constructor/destructor
 //----------------------------------------------
 
 // The following initialization makes a guess of 10 entries per jarfile.
 nsJAR::nsJAR()
-    : mZip(nullptr),
+    : mZip(new nsZipArchive()),
       mReleaseTime(PR_INTERVAL_NO_TIMEOUT),
       mCache(nullptr),
       mLock("nsJAR::mLock"),
       mMtime(0),
       mOpened(false),
       mSkipArchiveClosing(false) {}
 
 nsJAR::~nsJAR() { Close(); }
@@ -82,33 +82,32 @@ nsJAR::Open(nsIFile* zipFile) {
   if (mOpened) return NS_ERROR_FAILURE;  // Already open!
 
   mZipFile = zipFile;
   mOuterZipEntry.Truncate();
   mOpened = true;
 
   // The omnijar is special, it is opened early on and closed late
   // this avoids reopening it
-  RefPtr<CacheAwareZipReader> zip = mozilla::Omnijar::GetReader(zipFile);
+  RefPtr<nsZipArchive> zip = mozilla::Omnijar::GetReader(zipFile);
   if (zip) {
     mZip = zip;
     mSkipArchiveClosing = true;
     return NS_OK;
   }
-  mZip = new CacheAwareZipReader();
   return mZip->OpenArchive(zipFile);
 }
 
 NS_IMETHODIMP
 nsJAR::OpenInner(nsIZipReader* aZipReader, const nsACString& aZipEntry) {
   NS_ENSURE_ARG_POINTER(aZipReader);
   if (mOpened) return NS_ERROR_FAILURE;  // Already open!
 
   nsJAR* outerJAR = static_cast<nsJAR*>(aZipReader);
-  RefPtr<CacheAwareZipReader> innerZip =
+  RefPtr<nsZipArchive> innerZip =
       mozilla::Omnijar::GetInnerReader(outerJAR->mZipFile, aZipEntry);
   if (innerZip) {
     mOpened = true;
     mZip = innerZip;
     mSkipArchiveClosing = true;
     return NS_OK;
   }
 
@@ -120,38 +119,36 @@ nsJAR::OpenInner(nsIZipReader* aZipReade
   rv = aZipReader->GetFile(getter_AddRefs(mZipFile));
   NS_ENSURE_SUCCESS(rv, rv);
 
   mOpened = true;
 
   mOuterZipEntry.Assign(aZipEntry);
 
   RefPtr<nsZipHandle> handle;
-  rv = nsZipHandle::Init(static_cast<nsJAR*>(aZipReader)->mZip->GetZipArchive(),
+  rv = nsZipHandle::Init(static_cast<nsJAR*>(aZipReader)->mZip.get(),
                          PromiseFlatCString(aZipEntry).get(),
                          getter_AddRefs(handle));
   if (NS_FAILED(rv)) return rv;
 
-  mZip = new CacheAwareZipReader();
   return mZip->OpenArchive(handle);
 }
 
 NS_IMETHODIMP
 nsJAR::OpenMemory(void* aData, uint32_t aLength) {
   NS_ENSURE_ARG_POINTER(aData);
   if (mOpened) return NS_ERROR_FAILURE;  // Already open!
 
   mOpened = true;
 
   RefPtr<nsZipHandle> handle;
   nsresult rv = nsZipHandle::Init(static_cast<uint8_t*>(aData), aLength,
                                   getter_AddRefs(handle));
   if (NS_FAILED(rv)) return rv;
 
-  mZip = new CacheAwareZipReader();
   return mZip->OpenArchive(handle);
 }
 
 NS_IMETHODIMP
 nsJAR::GetFile(nsIFile** result) {
   *result = mZipFile;
   NS_IF_ADDREF(*result);
   return NS_OK;
@@ -163,17 +160,17 @@ nsJAR::Close() {
     return NS_ERROR_FAILURE;  // Never opened or already closed.
   }
 
   mOpened = false;
 
   if (mSkipArchiveClosing) {
     // Reset state, but don't close the omnijar because we did not open it.
     mSkipArchiveClosing = false;
-    mZip = nullptr;
+    mZip = new nsZipArchive();
     return NS_OK;
   }
 
   return mZip->CloseArchive();
 }
 
 NS_IMETHODIMP
 nsJAR::Test(const nsACString& aEntryName) {
@@ -299,17 +296,17 @@ nsresult nsJAR::GetNSPRFileDesc(PRFileDe
     return NS_ERROR_ILLEGAL_VALUE;
   }
   *aNSPRFileDesc = nullptr;
 
   if (!mZip) {
     return NS_ERROR_FAILURE;
   }
 
-  RefPtr<nsZipHandle> handle = mZip->GetZipArchive()->GetFD();
+  RefPtr<nsZipHandle> handle = mZip->GetFD();
   if (!handle) {
     return NS_ERROR_FAILURE;
   }
 
   return handle->GetNSPRFileDesc(aNSPRFileDesc);
 }
 
 //----------------------------------------------
--- a/modules/libjar/nsJAR.h
+++ b/modules/libjar/nsJAR.h
@@ -18,27 +18,23 @@
 #include "nsClassHashtable.h"
 #include "nsString.h"
 #include "nsIFile.h"
 #include "nsStringEnumerator.h"
 #include "nsHashKeys.h"
 #include "nsRefPtrHashtable.h"
 #include "nsTHashtable.h"
 #include "nsIZipReader.h"
+#include "nsZipArchive.h"
 #include "nsWeakReference.h"
 #include "nsIObserver.h"
 #include "mozilla/Attributes.h"
-#include "nsZipArchive.h"
 
 class nsZipReaderCache;
 
-namespace mozilla {
-class CacheAwareZipReader;
-}  // namespace mozilla
-
 /*-------------------------------------------------------------------------
  * Class nsJAR declaration.
  * nsJAR serves as an XPCOM wrapper for nsZipArchive with the addition of
  * JAR manifest file parsing.
  *------------------------------------------------------------------------*/
 class nsJAR final : public nsIZipReader {
   // Allows nsJARInputStream to call the verification functions
   friend class nsJARInputStream;
@@ -71,19 +67,19 @@ class nsJAR final : public nsIZipReader 
     mozilla::MutexAutoLock lock(mLock);
     mCache = aCache;
   }
 
   nsresult GetNSPRFileDesc(PRFileDesc** aNSPRFileDesc);
 
  protected:
   //-- Private data members
-  nsCOMPtr<nsIFile> mZipFile;  // The zip/jar file on disk
-  nsCString mOuterZipEntry;    // The entry in the zip this zip is reading from
-  RefPtr<mozilla::CacheAwareZipReader> mZip;  // The underlying zip archive
+  nsCOMPtr<nsIFile> mZipFile;   // The zip/jar file on disk
+  nsCString mOuterZipEntry;     // The entry in the zip this zip is reading from
+  RefPtr<nsZipArchive> mZip;    // The underlying zip archive
   PRIntervalTime mReleaseTime;  // used by nsZipReaderCache for flushing entries
   nsZipReaderCache*
       mCache;  // if cached, this points to the cache it's contained in
   mozilla::Mutex mLock;  // protect mCache and mZip
   int64_t mMtime;
   bool mOpened;
 
   // true if mZip was adopted from elsewhere and should not be closed by us.
--- a/modules/libjar/nsJARInputStream.cpp
+++ b/modules/libjar/nsJARInputStream.cpp
@@ -62,25 +62,18 @@ nsresult nsJARInputStream::InitFile(nsJA
 #endif
 
     default:
       return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   // Must keep handle to filepointer and mmap structure as long as we need
   // access to the mmapped data
-  rv = aJar->mZip->GetPersistentHandle(item, &mItemHandle,
-                                       CacheAwareZipReader::DeferCaching);
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-
-  mZs.next_in =
-      (Bytef*)aJar->mZip->GetData(item, CacheAwareZipReader::DeferCaching);
-
+  mFd = aJar->mZip->GetFD();
+  mZs.next_in = (Bytef*)aJar->mZip->GetData(item);
   if (!mZs.next_in) {
     return NS_ERROR_FILE_CORRUPTED;
   }
   mZs.avail_in = item->Size();
   mOutSize = item->RealSize();
   mZs.total_out = 0;
   return NS_OK;
 }
@@ -194,17 +187,17 @@ nsJARInputStream::Available(uint64_t* _r
 NS_IMETHODIMP
 nsJARInputStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytesRead) {
   NS_ENSURE_ARG_POINTER(aBuffer);
   NS_ENSURE_ARG_POINTER(aBytesRead);
 
   *aBytesRead = 0;
 
   nsresult rv = NS_OK;
-  MMAP_FAULT_HANDLER_BEGIN_HANDLE(mItemHandle.UnderlyingFD())
+  MMAP_FAULT_HANDLER_BEGIN_HANDLE(mFd)
   switch (mMode) {
     case MODE_NOTINITED:
       return NS_OK;
 
     case MODE_CLOSED:
       return NS_BASE_STREAM_CLOSED;
 
     case MODE_DIRECTORY:
@@ -213,37 +206,36 @@ nsJARInputStream::Read(char* aBuffer, ui
     case MODE_INFLATE:
 #ifdef MOZ_JAR_BROTLI
     case MODE_BROTLI:
 #endif
       if (mZs.total_out < mOutSize) {
         rv = ContinueInflate(aBuffer, aCount, aBytesRead);
       }
       // be aggressive about releasing the file!
-      // note that sometimes, we will release mItemHandle before we've finished
+      // note that sometimes, we will release  mFd before we've finished
       // deflating - this is because zlib buffers the input
       if (mZs.avail_in == 0) {
-        mItemHandle.ReleaseHandle();
+        mFd = nullptr;
       }
       break;
 
     case MODE_COPY:
-      if (mItemHandle) {
+      if (mFd) {
         uint32_t count = std::min(aCount, mOutSize - uint32_t(mZs.total_out));
         if (count) {
           memcpy(aBuffer, mZs.next_in + mZs.total_out, count);
           mZs.total_out += count;
         }
         *aBytesRead = count;
       }
       // be aggressive about releasing the file!
-      // note that sometimes, we will release mItemHandle before we've finished
-      // copying.
+      // note that sometimes, we will release mFd before we've finished copying.
       if (mZs.total_out >= mOutSize) {
-        mItemHandle.ReleaseHandle();
+        mFd = nullptr;
       }
       break;
   }
   MMAP_FAULT_HANDLER_CATCH(NS_ERROR_FAILURE)
   return rv;
 }
 
 NS_IMETHODIMP
@@ -265,17 +257,17 @@ nsJARInputStream::Close() {
     inflateEnd(&mZs);
   }
 #ifdef MOZ_JAR_BROTLI
   if (mMode == MODE_BROTLI) {
     BrotliDecoderDestroyInstance(mBrotliState);
   }
 #endif
   mMode = MODE_CLOSED;
-  mItemHandle.ReleaseHandle();
+  mFd = nullptr;
   return NS_OK;
 }
 
 nsresult nsJARInputStream::ContinueInflate(char* aBuffer, uint32_t aCount,
                                            uint32_t* aBytesRead) {
   bool finished = false;
 
   // No need to check the args, ::Read did that, but assert them at least
--- a/modules/libjar/nsJARInputStream.h
+++ b/modules/libjar/nsJARInputStream.h
@@ -6,17 +6,16 @@
 
 #ifndef nsJARINPUTSTREAM_h__
 #define nsJARINPUTSTREAM_h__
 
 #include "nsIInputStream.h"
 #include "nsJAR.h"
 #include "nsTArray.h"
 #include "mozilla/Attributes.h"
-#include "mozilla/Omnijar.h"
 
 #ifdef MOZ_JAR_BROTLI
 struct BrotliDecoderStateStruct;
 #endif
 
 /*-------------------------------------------------------------------------
  * Class nsJARInputStream declaration. This class defines the type of the
  * object returned by calls to nsJAR::GetInputStream(filename) for the
@@ -47,21 +46,21 @@ class nsJARInputStream final : public ns
   nsresult InitFile(nsJAR* aJar, nsZipItem* item);
 
   nsresult InitDirectory(nsJAR* aJar, const nsACString& aJarDirSpec,
                          const char* aDir);
 
  private:
   ~nsJARInputStream() { Close(); }
 
-  mozilla::CacheAwareZipHandle mItemHandle;  // handle for reading
-  uint32_t mOutSize;                         // inflated size
-  uint32_t mInCrc;                           // CRC as provided by the zipentry
-  uint32_t mOutCrc;                          // CRC as calculated by me
-  z_stream mZs;                              // zip data structure
+  RefPtr<nsZipHandle> mFd;  // handle for reading
+  uint32_t mOutSize;        // inflated size
+  uint32_t mInCrc;          // CRC as provided by the zipentry
+  uint32_t mOutCrc;         // CRC as calculated by me
+  z_stream mZs;             // zip data structure
 #ifdef MOZ_JAR_BROTLI
   BrotliDecoderStateStruct* mBrotliState;  // Brotli decoder state
 #endif
 
   /* For directory reading */
   RefPtr<nsJAR> mJar;          // string reference to zipreader
   uint32_t mNameLen;           // length of dirname
   nsCString mBuffer;           // storage for generated text of stream
--- a/modules/libjar/nsZipArchive.cpp
+++ b/modules/libjar/nsZipArchive.cpp
@@ -336,31 +336,21 @@ nsZipHandle::~nsZipHandle() {
 
 //***********************************************************
 //      nsZipArchive  --  public methods
 //***********************************************************
 
 //---------------------------------------------
 //  nsZipArchive::OpenArchive
 //---------------------------------------------
-nsresult nsZipArchive::OpenArchive(nsZipHandle* aZipHandle, PRFileDesc* aFd,
-                                   Span<const uint8_t> aCachedCentral) {
+nsresult nsZipArchive::OpenArchive(nsZipHandle* aZipHandle, PRFileDesc* aFd) {
   mFd = aZipHandle;
 
   //-- get table of contents for archive
-  nsresult rv = NS_OK;
-  if (!mBuiltFileList) {
-    if (!aCachedCentral.IsEmpty()) {
-      auto* start = aCachedCentral.Elements();
-      auto* end = start + aCachedCentral.Length();
-      rv = BuildFileListFromBuffer(start, end);
-    } else {
-      rv = BuildFileList(aFd);
-    }
-  }
+  nsresult rv = BuildFileList(aFd);
   if (NS_SUCCEEDED(rv)) {
     if (aZipHandle->mFile && XRE_IsParentProcess()) {
       static char* env = PR_GetEnv("MOZ_JAR_LOG_FILE");
       if (env) {
         mUseZipLog = true;
 
         zipLog.Init(env);
         // We only log accesses in jar/zip archives within the NS_GRE_DIR
@@ -404,31 +394,30 @@ nsresult nsZipArchive::OpenArchive(nsZip
           }
         }
       }
     }
   }
   return rv;
 }
 
-nsresult nsZipArchive::OpenArchive(nsIFile* aFile,
-                                   Span<const uint8_t> aCachedCentral) {
+nsresult nsZipArchive::OpenArchive(nsIFile* aFile) {
   RefPtr<nsZipHandle> handle;
 #if defined(XP_WIN)
   mozilla::AutoFDClose fd;
   nsresult rv = nsZipHandle::Init(aFile, getter_AddRefs(handle), &fd.rwget());
 #else
   nsresult rv = nsZipHandle::Init(aFile, getter_AddRefs(handle));
 #endif
   if (NS_FAILED(rv)) return rv;
 
 #if defined(XP_WIN)
-  return OpenArchive(handle, fd.get(), aCachedCentral);
+  return OpenArchive(handle, fd.get());
 #else
-  return OpenArchive(handle, nullptr, aCachedCentral);
+  return OpenArchive(handle);
 #endif
 }
 
 //---------------------------------------------
 //  nsZipArchive::Test
 //---------------------------------------------
 nsresult nsZipArchive::Test(const char* aEntryName) {
   nsZipItem* currItem;
@@ -468,85 +457,23 @@ nsresult nsZipArchive::CloseArchive() {
   // We don't need to delete each of the nsZipItem as the memory for
   // the zip item and the filename it holds are both allocated from the Arena.
   // Hence, destroying the Arena is like destroying all the memory
   // for all the nsZipItem in one shot. But if the ~nsZipItem is doing
   // anything more than cleaning up memory, we should start calling it.
   // Let us also cleanup the mFiles table for re-use on the next 'open' call
   memset(mFiles, 0, sizeof(mFiles));
   mBuiltSynthetics = false;
-
-  AutoWriteLock lock(mLazyOpenLock);
-  mLazyOpenParams = Nothing();
-
   return NS_OK;
 }
 
-nsresult nsZipArchive::EnsureArchiveOpenedOnDisk() {
-  {
-    AutoReadLock lock(mLazyOpenLock);
-    if (!mLazyOpenParams) {
-      return NS_OK;
-    }
-  }
-
-  AutoWriteLock lock(mLazyOpenLock);
-  if (!mLazyOpenParams) {
-    // Another thread beat us to opening the archive while we were waiting on
-    // the mutex.
-    return NS_OK;
-  }
-
-  nsresult rv = OpenArchive(mLazyOpenParams->mFile);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return NS_ERROR_UNEXPECTED;
-  }
-  mLazyOpenParams = Nothing();
-
-  return NS_OK;
-}
-
-nsresult nsZipArchive::EnsureFileListBuilt() {
-  {
-    AutoReadLock lock(mLazyOpenLock);
-    if (!mLazyOpenParams || mBuiltFileList) {
-      return NS_OK;
-    }
-  }
-
-  AutoWriteLock lock(mLazyOpenLock);
-  if (!mLazyOpenParams || mBuiltFileList) {
-    // Another thread beat us to building the file list while we were waiting
-    // on the mutex.
-    return NS_OK;
-  }
-
-  nsresult rv;
-  if (!mLazyOpenParams->mCachedCentral.IsEmpty()) {
-    auto* start = mLazyOpenParams->mCachedCentral.Elements();
-    auto* end = start + mLazyOpenParams->mCachedCentral.Length();
-    rv = BuildFileListFromBuffer(start, end);
-  } else {
-    rv = OpenArchive(mLazyOpenParams->mFile);
-    mLazyOpenParams = Nothing();
-  }
-
-  return rv;
-}
-
 //---------------------------------------------
 // nsZipArchive::GetItem
 //---------------------------------------------
 nsZipItem* nsZipArchive::GetItem(const char* aEntryName) {
-  nsresult rv = EnsureFileListBuilt();
-
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return nullptr;
-  }
-
   if (aEntryName) {
     uint32_t len = strlen(aEntryName);
     //-- If the request is for a directory, make sure that synthetic entries
     //-- are created for the directories without their own entry.
     if (!mBuiltSynthetics) {
       if ((len > 0) && (aEntryName[len - 1] == '/')) {
         if (BuildSynthetics() != NS_OK) return 0;
       }
@@ -620,30 +547,24 @@ nsresult nsZipArchive::ExtractFile(nsZip
 }
 
 //---------------------------------------------
 // nsZipArchive::FindInit
 //---------------------------------------------
 nsresult nsZipArchive::FindInit(const char* aPattern, nsZipFind** aFind) {
   if (!aFind) return NS_ERROR_ILLEGAL_VALUE;
 
-  nsresult rv = EnsureFileListBuilt();
-
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return NS_ERROR_UNEXPECTED;
-  }
-
   // null out param in case an error happens
   *aFind = nullptr;
 
   bool regExp = false;
   char* pattern = 0;
 
   // Create synthetic directory entries on demand
-  rv = BuildSynthetics();
+  nsresult rv = BuildSynthetics();
   if (rv != NS_OK) return rv;
 
   // validate the pattern
   if (aPattern) {
     switch (NS_WildCardValid((char*)aPattern)) {
       case INVALID_SXP:
         return NS_ERROR_ILLEGAL_VALUE;
 
@@ -677,22 +598,17 @@ nsresult nsZipArchive::FindInit(const ch
 //---------------------------------------------
 // nsZipFind::FindNext
 //---------------------------------------------
 nsresult nsZipFind::FindNext(const char** aResult, uint16_t* aNameLen) {
   if (!mArchive || !aResult || !aNameLen) return NS_ERROR_ILLEGAL_VALUE;
 
   *aResult = 0;
   *aNameLen = 0;
-
-  // NOTE: don't use GetFD here. if mFd is not null, then we need to have this
-  // fault handler, as we may be reading from the memory mapped file. However
-  // if it is null, then we can guarantee that we're reading here from a cached
-  // buffer, which we assume is not mapped to a file.
-  MMAP_FAULT_HANDLER_BEGIN_HANDLE(mArchive->mFd)
+  MMAP_FAULT_HANDLER_BEGIN_HANDLE(mArchive->GetFD())
   // we start from last match, look for next
   while (mSlot < ZIP_TABSIZE) {
     // move to next in current chain, or move to new slot
     mItem = mItem ? mItem->next : mArchive->mFiles[mSlot];
 
     bool found = false;
     if (!mItem)
       ++mSlot;  // no more in this chain, move to next slot
@@ -728,23 +644,20 @@ nsZipItem* nsZipArchive::CreateZipItem()
   // Arena allocate the nsZipItem
   return (nsZipItem*)mArena.Allocate(sizeof(nsZipItem), mozilla::fallible);
 }
 
 //---------------------------------------------
 //  nsZipArchive::BuildFileList
 //---------------------------------------------
 nsresult nsZipArchive::BuildFileList(PRFileDesc* aFd) {
-  mBuiltFileList = true;
   // Get archive size using end pos
   const uint8_t* buf;
   const uint8_t* startp = mFd->mFileData;
   const uint8_t* endp = startp + mFd->mLen;
-
-  nsresult rv;
   MMAP_FAULT_HANDLER_BEGIN_HANDLE(mFd)
   uint32_t centralOffset = 4;
   // Only perform readahead in the parent process. Children processes
   // don't need readahead when the file has already been readahead by
   // the parent process, and readahead only really happens for omni.ja,
   // which is used in the parent process.
   if (XRE_IsParentProcess() && mFd->mLen > ZIPCENTRAL_SIZE &&
       xtolong(startp + centralOffset) == CENTRALSIG) {
@@ -759,73 +672,30 @@ nsresult nsZipArchive::BuildFileList(PRF
       }
     }
   }
 
   if (!centralOffset) {
     return NS_ERROR_FILE_CORRUPTED;
   }
 
-  uintptr_t startpInt = reinterpret_cast<uintptr_t>(startp);
-  if (startpInt + centralOffset < startpInt || centralOffset > mFd->mLen) {
+  buf = startp + centralOffset;
+
+  // avoid overflow of startp + centralOffset.
+  if (buf < startp) {
     return NS_ERROR_FILE_CORRUPTED;
   }
 
-  buf = startp + centralOffset;
-
-  mZipCentralOffset = centralOffset;
-  rv = BuildFileListFromBuffer(buf, endp);
-
-  MMAP_FAULT_HANDLER_CATCH(NS_ERROR_FAILURE)
-  return rv;
-}
-
-UniquePtr<uint8_t[]> nsZipArchive::CopyCentralDirectoryBuffer(size_t* aSize) {
-  *aSize = 0;
-
-  // mZipCentralOffset could in theory be 0. In practice though, we likely
-  // won't ever see this. If the end result is that we can't cache the buffer
-  // in these cases, that's fine.
-  if (!mZipCentralOffset || !mZipCentralSize) {
-    return nullptr;
-  }
-
-  const uint8_t* buf;
-  const uint8_t* startp = mFd->mFileData;
-  buf = startp + mZipCentralOffset;
-
-  // Just a sanity check to make sure these values haven't overflowed the
-  // buffer mapped to our file. Technically the pointer could overflow the max
-  // pointer value, but that could only happen with this check succeeding if
-  // mFd->mLen is incorrect, which we will here assume is impossible.
-  if (mZipCentralOffset + mZipCentralSize > mFd->mLen) {
-    return nullptr;
-  }
-
-  auto resultBuf = MakeUnique<uint8_t[]>(mZipCentralSize);
-
-  MMAP_FAULT_HANDLER_BEGIN_HANDLE(mFd)
-  memcpy(resultBuf.get(), buf, mZipCentralSize);
-  MMAP_FAULT_HANDLER_CATCH(nullptr)
-
-  *aSize = mZipCentralSize;
-  return resultBuf;
-}
-
-nsresult nsZipArchive::BuildFileListFromBuffer(const uint8_t* aBuf,
-                                               const uint8_t* aEnd) {
-  mBuiltFileList = true;
-  const uint8_t* buf = aBuf;
   //-- Read the central directory headers
   uint32_t sig = 0;
   while ((buf + int32_t(sizeof(uint32_t)) > buf) &&
-         (buf + int32_t(sizeof(uint32_t)) <= aEnd) &&
+         (buf + int32_t(sizeof(uint32_t)) <= endp) &&
          ((sig = xtolong(buf)) == CENTRALSIG)) {
     // Make sure there is enough data available.
-    if ((buf > aEnd) || (aEnd - buf < ZIPCENTRAL_SIZE)) {
+    if ((buf > endp) || (endp - buf < ZIPCENTRAL_SIZE)) {
       return NS_ERROR_FILE_CORRUPTED;
     }
 
     // Read the fixed-size data.
     ZipCentral* central = (ZipCentral*)buf;
 
     uint16_t namelen = xtoint(central->filename_len);
     uint16_t extralen = xtoint(central->extrafield_len);
@@ -833,17 +703,17 @@ nsresult nsZipArchive::BuildFileListFrom
     uint32_t diff = ZIPCENTRAL_SIZE + namelen + extralen + commentlen;
 
     // Sanity check variable sizes and refuse to deal with
     // anything too big: it's likely a corrupt archive.
     if (namelen < 1 || namelen > kMaxNameLength) {
       return NS_ERROR_FILE_CORRUPTED;
     }
     if (buf >= buf + diff ||  // No overflow
-        buf >= aEnd - diff) {
+        buf >= endp - diff) {
       return NS_ERROR_FILE_CORRUPTED;
     }
 
     // Point to the next item at the top of loop
     buf += diff;
 
     nsZipItem* item = CreateZipItem();
     if (!item) return NS_ERROR_OUT_OF_MEMORY;
@@ -860,28 +730,28 @@ nsresult nsZipArchive::BuildFileListFrom
     sig = 0;
   } /* while reading central directory records */
 
   if (sig != ENDSIG) {
     return NS_ERROR_FILE_CORRUPTED;
   }
 
   // Make the comment available for consumers.
-  if ((aEnd >= buf) && (aEnd - buf >= ZIPEND_SIZE)) {
+  if ((endp >= buf) && (endp - buf >= ZIPEND_SIZE)) {
     ZipEnd* zipend = (ZipEnd*)buf;
 
     buf += ZIPEND_SIZE;
     uint16_t commentlen = xtoint(zipend->commentfield_len);
-    if (aEnd - buf >= commentlen) {
-      mCommentPtr = (const char*)aBuf;
+    if (endp - buf >= commentlen) {
+      mCommentPtr = (const char*)buf;
       mCommentLen = commentlen;
     }
   }
 
-  mZipCentralSize = buf - aBuf;
+  MMAP_FAULT_HANDLER_CATCH(NS_ERROR_FAILURE)
   return NS_OK;
 }
 
 //---------------------------------------------
 //  nsZipArchive::BuildSynthetics
 //---------------------------------------------
 nsresult nsZipArchive::BuildSynthetics() {
   if (mBuiltSynthetics) return NS_OK;
@@ -941,74 +811,25 @@ nsresult nsZipArchive::BuildSynthetics()
       } /* end processing of dirs in item's name */
     }
   }
   MMAP_FAULT_HANDLER_CATCH(NS_ERROR_FAILURE)
   return NS_OK;
 }
 
 nsZipHandle* nsZipArchive::GetFD() {
-  nsresult rv = EnsureArchiveOpenedOnDisk();
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return nullptr;
-  }
+  if (!mFd) return nullptr;
   return mFd.get();
 }
 
-void nsZipArchive::GetURIString(nsACString& result) {
-  {
-    AutoReadLock lock(mLazyOpenLock);
-    if (!mLazyOpenParams) {
-      mFd->mFile.GetURIString(result);
-      return;
-    }
-  }
-  AutoReadLock lock(mLazyOpenLock);
-  if (!mLazyOpenParams) {
-    // Another thread consumed mLazyOpenParams while we were waiting.
-    mFd->mFile.GetURIString(result);
-    return;
-  }
-
-  // This is a bit tricky - typically, we could just
-  // NS_GetURLSpecFromActualFile from mLazyOpenParams->mFile or from
-  // mFd->mFile.GetBaseFile(), depending on which we currently have. However,
-  // this won't actually be correct if this zip archive is nested inside
-  // another archive. However, at present, we know that mLazyOpenParams can
-  // only be here if we were opened from a real underlying file, so we assume
-  // that we're safe to do this. Any future code that breaks this assumption
-  // will need to update things here.
-  NS_GetURLSpecFromActualFile(mLazyOpenParams->mFile, result);
-}
-
-already_AddRefed<nsIFile> nsZipArchive::GetBaseFile() {
-  {
-    AutoReadLock lock(mLazyOpenLock);
-    if (!mLazyOpenParams) {
-      return mFd->mFile.GetBaseFile();
-    }
-  }
-  AutoReadLock lock(mLazyOpenLock);
-  if (!mLazyOpenParams) {
-    // Another thread consumed mLazyOpenParams while we were waiting.
-    return mFd->mFile.GetBaseFile();
-  }
-
-  nsCOMPtr<nsIFile> file = mLazyOpenParams->mFile;
-  return file.forget();
-}
-
 //---------------------------------------------
 // nsZipArchive::GetDataOffset
 //---------------------------------------------
 uint32_t nsZipArchive::GetDataOffset(nsZipItem* aItem) {
   MOZ_ASSERT(aItem);
-  nsresult rv = EnsureArchiveOpenedOnDisk();
-  MOZ_RELEASE_ASSERT(!NS_FAILED(rv),
-                     "Should have been able to open the zip archive");
 
   uint32_t offset;
   MMAP_FAULT_HANDLER_BEGIN_HANDLE(mFd)
   //-- read local header to get variable length values and calculate
   //-- the real data offset
   uint32_t len = mFd->mLen;
   const uint8_t* data = mFd->mFileData;
   offset = aItem->LocalOffset();
@@ -1029,20 +850,16 @@ uint32_t nsZipArchive::GetDataOffset(nsZ
   return offset;
 }
 
 //---------------------------------------------
 // nsZipArchive::GetData
 //---------------------------------------------
 const uint8_t* nsZipArchive::GetData(nsZipItem* aItem) {
   MOZ_ASSERT(aItem);
-  nsresult rv = EnsureArchiveOpenedOnDisk();
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return nullptr;
-  }
   uint32_t offset = GetDataOffset(aItem);
 
   MMAP_FAULT_HANDLER_BEGIN_HANDLE(mFd)
   // -- check if there is enough source data in the file
   if (!offset || mFd->mLen < aItem->Size() ||
       offset > mFd->mLen - aItem->Size() ||
       (aItem->Compression() == STORED && aItem->Size() != aItem->RealSize())) {
     return nullptr;
@@ -1067,22 +884,18 @@ int64_t nsZipArchive::SizeOfMapping() { 
 
 //------------------------------------------
 // nsZipArchive constructor and destructor
 //------------------------------------------
 
 nsZipArchive::nsZipArchive()
     : mRefCnt(0),
       mCommentPtr(nullptr),
-      mZipCentralOffset(0),
-      mZipCentralSize(0),
       mCommentLen(0),
       mBuiltSynthetics(false),
-      mBuiltFileList(false),
-      mLazyOpenLock("nsZipArchive::mLazyOpenLock"),
       mUseZipLog(false) {
   // initialize the table to nullptr
   memset(mFiles, 0, sizeof(mFiles));
 }
 
 NS_IMPL_ADDREF(nsZipArchive)
 NS_IMPL_RELEASE(nsZipArchive)
 
@@ -1380,24 +1193,22 @@ uint8_t* nsZipCursor::ReadOrCopy(uint32_
   }
   MMAP_FAULT_HANDLER_CATCH(nullptr)
   return buf;
 }
 
 nsZipItemPtr_base::nsZipItemPtr_base(nsZipArchive* aZip, const char* aEntryName,
                                      bool doCRC)
     : mReturnBuf(nullptr), mReadlen(0) {
-  nsZipItem* item = aZip->GetItem(aEntryName);
-  if (!item) {
-    return;
-  }
-
   // make sure the ziparchive hangs around
   mZipHandle = aZip->GetFD();
 
+  nsZipItem* item = aZip->GetItem(aEntryName);
+  if (!item) return;
+
   uint32_t size = 0;
   bool compressed = (item->Compression() == DEFLATED);
 #ifdef MOZ_JAR_BROTLI
   compressed |= (item->Compression() == MOZ_JAR_BROTLI);
 #endif
   if (compressed) {
     size = item->RealSize();
     mAutoBuf = MakeUniqueFallible<uint8_t[]>(size);
--- a/modules/libjar/nsZipArchive.h
+++ b/modules/libjar/nsZipArchive.h
@@ -12,21 +12,19 @@
 #define ZIP_BUFLEN \
   (4 * 1024) /* Used as output buffer when deflating items to a file */
 
 #include "zlib.h"
 #include "zipstruct.h"
 #include "nsIFile.h"
 #include "nsISupportsImpl.h"  // For mozilla::ThreadSafeAutoRefCnt
 #include "mozilla/ArenaAllocator.h"
-#include "mozilla/Atomics.h"
 #include "mozilla/FileUtils.h"
 #include "mozilla/FileLocation.h"
 #include "mozilla/UniquePtr.h"
-#include "mozilla/RWLock.h"
 
 class nsZipFind;
 struct PRFileDesc;
 #ifdef MOZ_JAR_BROTLI
 struct BrotliDecoderStateStruct;
 #endif
 
 /**
@@ -81,102 +79,44 @@ class nsZipHandle;
  *
  */
 class nsZipArchive final {
   friend class nsZipFind;
 
   /** destructing the object closes the archive */
   ~nsZipArchive();
 
-  /**
-   * LazyOpenArchiveParams is a class which is used to store cached
-   * contents of omnijars.
-   *
-   */
-  struct LazyOpenArchiveParams {
-    nsCOMPtr<nsIFile> mFile;
-    mozilla::Span<const uint8_t> mCachedCentral;
-
-    LazyOpenArchiveParams(nsIFile* aFile,
-                          mozilla::Span<const uint8_t> aCachedCentral)
-        : mFile(nullptr), mCachedCentral(aCachedCentral) {
-      aFile->Clone(getter_AddRefs(mFile));
-    }
-  };
-
  public:
   static const char* sFileCorruptedReason;
 
   /** constructing does not open the archive. See OpenArchive() */
   nsZipArchive();
 
   /**
    * OpenArchive
    *
    * It's an error to call this more than once on the same nsZipArchive
    * object. If we were allowed to use exceptions this would have been
    * part of the constructor
    *
-   * @param   aZipHandle      The nsZipHandle used to access the zip
-   * @param   aFd             Optional PRFileDesc for Windows readahead
-                              optimization
-   * @param   aCachedCentral  Optional cached buffer containing the zip central
-                              for this zip.
+   * @param   aZipHandle  The nsZipHandle used to access the zip
+   * @param   aFd         Optional PRFileDesc for Windows readahead optimization
    * @return  status code
    */
-  nsresult OpenArchive(nsZipHandle* aZipHandle, PRFileDesc* aFd = nullptr,
-                       mozilla::Span<const uint8_t> aCachedCentral =
-                           mozilla::Span<const uint8_t>());
+  nsresult OpenArchive(nsZipHandle* aZipHandle, PRFileDesc* aFd = nullptr);
 
   /**
    * OpenArchive
    *
    * Convenience function that generates nsZipHandle
    *
    * @param   aFile         The file used to access the zip
-   * @param   aCachedCentral  Optional cached buffer containing the zip central
-                              for this zip.
-   * @return  status code
-   */
-  nsresult OpenArchive(nsIFile* aFile,
-                       mozilla::Span<const uint8_t> aCachedCentral =
-                           mozilla::Span<const uint8_t>());
-
-  /**
-   * Ensures underlying archive is opened, if it was opened with
-   * LazyOpenArchive.
-   *
-   * Convenience function that generates nsZipHandle
-   *
-   * @param   aFile         The file used to access the zip
    * @return  status code
    */
-  nsresult EnsureArchiveOpenedOnDisk();
-
-  /**
-   * OpenArchive
-   *
-   * Lazily opens the zip archive on the first request to get data from it.
-   * NOTE: The buffer provided for aCachedCentral must outlive this
-   * nsZipArchive. This is presently true for the StartupCache, as it ensures
-   * that even past cache invalidation, all accessed buffers persist for the
-   * lifetime of the application, but we will need to ensure that this remains
-   * true.
-   *
-   * @param   aFile               The file used to access the zip
-   * @param   aCachedCentral      Cached buffer containing the zip central
-                                  for this zip.
-   * @return  status code
-   */
-  nsresult LazyOpenArchive(nsIFile* aFile,
-                           mozilla::Span<const uint8_t> aCachedCentral) {
-    mozilla::AutoWriteLock lock(mLazyOpenLock);
-    mLazyOpenParams.emplace(aFile, aCachedCentral);
-    return NS_OK;
-  }
+  nsresult OpenArchive(nsIFile* aFile);
 
   /**
    * Test the integrity of items in this archive by running
    * a CRC check after extracting each item into a memory
    * buffer.  If an entry name is supplied only the
    * specified item is tested.  Else, if null is supplied
    * then all the items in the archive are tested.
    *
@@ -222,56 +162,30 @@ class nsZipArchive final {
    */
   nsresult FindInit(const char* aPattern, nsZipFind** aFind);
 
   /*
    * Gets an undependent handle to the mapped file.
    */
   nsZipHandle* GetFD();
 
-  /*
-   * Gets the URI string to the mapped file. One could get this URI string
-   * in a roundabout way using GetFD, but GetFD requires opening the file for
-   * read access, which can be expensive.
-   */
-  void GetURIString(nsACString& result);
-
-  /*
-   * Gets the underlying nsIFile pointer. Like GetURIString, this is to be
-   * preferred over GetFD where possible, because it does not require opening
-   * the file for read access, which can be expensive, and is to be avoided
-   * when possible during application startup.
-   */
-  already_AddRefed<nsIFile> GetBaseFile();
-
   /**
    * Gets the data offset.
    * @param   aItem       Pointer to nsZipItem
    * returns 0 on failure.
    */
   uint32_t GetDataOffset(nsZipItem* aItem);
 
   /**
    * Get pointer to the data of the item.
    * @param   aItem       Pointer to nsZipItem
    * reutrns null when zip file is corrupt.
    */
   const uint8_t* GetData(nsZipItem* aItem);
 
-  /**
-   * Copies the contents of the zip central directory, and returns it to the
-   * caller to take ownership. This is useful for caching the contents of the
-   * central directory, which can be compressed and stored elsewhere, and
-   * passed back into OpenArchive when this archive is opened in the future.
-   *
-   * @param   aSize       size_t pointer to be filled with the size of the
-                          returned buffer.
-   */
-  mozilla::UniquePtr<uint8_t[]> CopyCentralDirectoryBuffer(size_t* aSize);
-
   bool GetComment(nsACString& aComment);
 
   /**
    * Gets the amount of memory taken up by the archive's mapping.
    * @return the size
    */
   int64_t SizeOfMapping();
 
@@ -285,44 +199,36 @@ class nsZipArchive final {
   //--- private members ---
   mozilla::ThreadSafeAutoRefCnt mRefCnt; /* ref count */
   NS_DECL_OWNINGTHREAD
 
   nsZipItem* mFiles[ZIP_TABSIZE];
   mozilla::ArenaAllocator<1024, sizeof(void*)> mArena;
 
   const char* mCommentPtr;
-  size_t mZipCentralOffset;
-  size_t mZipCentralSize;
   uint16_t mCommentLen;
 
   // Whether we synthesized the directory entries
   bool mBuiltSynthetics;
-  bool mBuiltFileList;
 
   // file handle
   RefPtr<nsZipHandle> mFd;
 
-  mozilla::Maybe<LazyOpenArchiveParams> mLazyOpenParams;
-  mozilla::RWLock mLazyOpenLock;
-
   // file URI, for logging
   nsCString mURI;
 
   // Is true if we use zipLog to log accesses in jar/zip archives. This helper
   // variable avoids grabbing zipLog's lock when not necessary.
   bool mUseZipLog;
 
  private:
   //--- private methods ---
   nsZipItem* CreateZipItem();
   nsresult BuildFileList(PRFileDesc* aFd = nullptr);
-  nsresult BuildFileListFromBuffer(const uint8_t* aBuf, const uint8_t* aEnd);
   nsresult BuildSynthetics();
-  nsresult EnsureFileListBuilt();
 
   nsZipArchive& operator=(const nsZipArchive& rhs) = delete;
   nsZipArchive(const nsZipArchive& rhs) = delete;
 };
 
 /**
  * nsZipFind
  *
--- a/modules/libpref/Preferences.cpp
+++ b/modules/libpref/Preferences.cpp
@@ -76,16 +76,17 @@
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsThreadUtils.h"
 #include "nsUTF8Utils.h"
 #include "nsWeakReference.h"
 #include "nsXPCOMCID.h"
 #include "nsXPCOM.h"
 #include "nsXULAppAPI.h"
+#include "nsZipArchive.h"
 #include "plbase64.h"
 #include "PLDHashTable.h"
 #include "plstr.h"
 #include "prlink.h"
 #include "xpcpublic.h"
 
 #ifdef DEBUG
 #  include <map>
@@ -4213,32 +4214,32 @@ static nsresult pref_LoadPrefsInDir(nsIF
         rv = rv2;
       }
     }
   }
 
   return rv;
 }
 
-static nsresult pref_ReadPrefFromJar(CacheAwareZipReader* aJarReader,
+static nsresult pref_ReadPrefFromJar(nsZipArchive* aJarReader,
                                      const char* aName) {
   nsCString manifest;
   MOZ_TRY_VAR(manifest,
               URLPreloader::ReadZip(aJarReader, nsDependentCString(aName)));
 
   Parser parser;
   if (!parser.Parse(PrefValueKind::Default, aName, manifest)) {
     return NS_ERROR_FILE_CORRUPTED;
   }
 
   return NS_OK;
 }
 
-static nsresult pref_ReadDefaultPrefs(
-    const RefPtr<CacheAwareZipReader>& jarReader, const char* path) {
+static nsresult pref_ReadDefaultPrefs(const RefPtr<nsZipArchive> jarReader,
+                                      const char* path) {
   UniquePtr<nsZipFind> find;
   nsTArray<nsCString> prefEntries;
   const char* entryName;
   uint16_t entryNameLen;
 
   nsresult rv = jarReader->FindInit(path, getter_Transfers(find));
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -4393,17 +4394,17 @@ nsresult Preferences::InitInitialObjects
   // preferences from omni.jar, whether or not `$app == $gre`.
 
   nsresult rv = NS_ERROR_FAILURE;
   UniquePtr<nsZipFind> find;
   nsTArray<nsCString> prefEntries;
   const char* entryName;
   uint16_t entryNameLen;
 
-  RefPtr<CacheAwareZipReader> jarReader = Omnijar::GetReader(Omnijar::GRE);
+  RefPtr<nsZipArchive> jarReader = Omnijar::GetReader(Omnijar::GRE);
   if (jarReader) {
 #ifdef MOZ_WIDGET_ANDROID
     // Try to load an architecture-specific greprefs.js first. This will be
     // present in FAT AAR builds of GeckoView on Android.
     const char* abi = getenv("MOZ_ANDROID_CPU_ABI");
     if (abi) {
       nsAutoCString path;
       path.AppendPrintf("%s/greprefs.js", abi);
@@ -4475,17 +4476,17 @@ nsresult Preferences::InitInitialObjects
   rv = pref_LoadPrefsInDir(defaultPrefDir, specialFiles,
                            ArrayLength(specialFiles));
   if (NS_FAILED(rv)) {
     NS_WARNING("Error parsing application default preferences.");
   }
 
   // Load jar:$app/omni.jar!/defaults/preferences/*.js
   // or jar:$gre/omni.jar!/defaults/preferences/*.js.
-  RefPtr<CacheAwareZipReader> appJarReader = Omnijar::GetReader(Omnijar::APP);
+  RefPtr<nsZipArchive> appJarReader = Omnijar::GetReader(Omnijar::APP);
 
   // GetReader(Omnijar::APP) returns null when `$app == $gre`, in
   // which case we look for app-specific default preferences in $gre.
   if (!appJarReader) {
     appJarReader = Omnijar::GetReader(Omnijar::GRE);
   }
 
   if (appJarReader) {
deleted file mode 100644
--- a/startupcache/PStartupCache.ipdl
+++ /dev/null
@@ -1,31 +0,0 @@
-/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8 -*- */
-/* vim: set sw=4 ts=8 et tw=80 ft=cpp : */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-include protocol PContent;
-
-using class mozilla::TimeStamp from "mozilla/TimeStamp.h";
-using mozilla::void_t from "ipc/IPCMessageUtils.h";
-
-namespace mozilla {
-namespace scache {
-
-struct EntryData {
-    nsCString key;
-    // This will be an empty array if data is present in the previous
-    // session's cache.
-    uint8_t[] data;
-};
-
-protocol PStartupCache
-{
-    manager PContent;
-
-parent:
-    async __delete__(EntryData[] entries);
-};
-
-} // namespace scache
-} // namespace mozilla
--- a/startupcache/StartupCache.cpp
+++ b/startupcache/StartupCache.cpp
@@ -2,31 +2,24 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "prio.h"
 #include "PLDHashTable.h"
 #include "mozilla/IOInterposer.h"
-#include "mozilla/AppShutdown.h"
 #include "mozilla/AutoMemMap.h"
 #include "mozilla/IOBuffers.h"
-#include "mozilla/ipc/FileDescriptor.h"
-#include "mozilla/ipc/GeckoChildProcessHost.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/MemUtils.h"
 #include "mozilla/MmapFaultHandler.h"
 #include "mozilla/ResultExtensions.h"
 #include "mozilla/scache/StartupCache.h"
-#include "mozilla/scache/StartupCacheChild.h"
 #include "mozilla/ScopeExit.h"
-#include "mozilla/dom/ContentChild.h"
-#include "mozilla/dom/ContentParent.h"
-#include "mozilla/dom/ipc/MemMapSnapshot.h"
 
 #include "nsClassHashtable.h"
 #include "nsComponentManagerUtils.h"
 #include "nsCRT.h"
 #include "nsDirectoryServiceUtils.h"
 #include "nsIClassInfo.h"
 #include "nsIFile.h"
 #include "nsIObserver.h"
@@ -53,65 +46,37 @@
 #endif
 
 #if PR_BYTES_PER_WORD == 4
 #  define SC_WORDSIZE "4"
 #else
 #  define SC_WORDSIZE "8"
 #endif
 
-#define DOC_ELEM_INSERTED_TOPIC "document-element-inserted"
-#define CONTENT_DOCUMENT_LOADED_TOPIC "content-document-loaded"
-
 using namespace mozilla::Compression;
 
 namespace mozilla {
 namespace scache {
 
-// This is included here, rather than as a member of the StartupCache
-// singleton, because including it there would mean we need to pull
-// in the chromium IPC headers everywhere we reference StartupCache.h
-static ipc::FileDescriptor sSharedDataFD;
-
 MOZ_DEFINE_MALLOC_SIZE_OF(StartupCacheMallocSizeOf)
 
 NS_IMETHODIMP
 StartupCache::CollectReports(nsIHandleReportCallback* aHandleReport,
                              nsISupports* aData, bool aAnonymize) {
-  MutexAutoLock lock(mLock);
-  if (XRE_IsParentProcess()) {
-    MOZ_COLLECT_REPORT(
-        "explicit/startup-cache/mapping", KIND_NONHEAP, UNITS_BYTES,
-        mCacheData.nonHeapSizeOfExcludingThis(),
-        "Memory used to hold the mapping of the startup cache from file. "
-        "This memory is likely to be swapped out shortly after start-up.");
-  } else {
-    // In the child process, mCacheData actually points to the parent's
-    // mSharedData. We just want to report this once as explicit under
-    // the parent process's report.
-    MOZ_COLLECT_REPORT(
-        "startup-cache-shared-mapping", KIND_NONHEAP, UNITS_BYTES,
-        mCacheData.nonHeapSizeOfExcludingThis(),
-        "Memory used to hold the decompressed contents of part of the "
-        "startup cache, to be used by child processes. This memory is "
-        "likely to be swapped out shortly after start-up.");
-  }
+  MOZ_COLLECT_REPORT(
+      "explicit/startup-cache/mapping", KIND_NONHEAP, UNITS_BYTES,
+      mCacheData.nonHeapSizeOfExcludingThis(),
+      "Memory used to hold the mapping of the startup cache from file. "
+      "This memory is likely to be swapped out shortly after start-up.");
 
   MOZ_COLLECT_REPORT("explicit/startup-cache/data", KIND_HEAP, UNITS_BYTES,
                      HeapSizeOfIncludingThis(StartupCacheMallocSizeOf),
                      "Memory used by the startup cache for things other than "
                      "the file mapping.");
 
-  MOZ_COLLECT_REPORT(
-      "explicit/startup-cache/shared-mapping", KIND_NONHEAP, UNITS_BYTES,
-      mSharedData.nonHeapSizeOfExcludingThis(),
-      "Memory used to hold the decompressed contents of part of the "
-      "startup cache, to be used by child processes. This memory is "
-      "likely to be swapped out shortly after start-up.");
-
   return NS_OK;
 }
 
 static const uint8_t MAGIC[] = "startupcache0002";
 // This is a heuristic value for how much to reserve for mTable to avoid
 // rehashing. This is not a hard limit in release builds, but it is in
 // debug builds as it should be stable. If we exceed this number we should
 // just increase it.
@@ -139,157 +104,87 @@ static inline Result<Ok, nsresult> Seek(
   }
   return Ok();
 }
 
 static nsresult MapLZ4ErrorToNsresult(size_t aError) {
   return NS_ERROR_FAILURE;
 }
 
+StartupCache* StartupCache::GetSingletonNoInit() {
+  return StartupCache::gStartupCache;
+}
+
 StartupCache* StartupCache::GetSingleton() {
+  if (!gStartupCache) {
+    if (!XRE_IsParentProcess()) {
+      return nullptr;
+    }
+#ifdef MOZ_DISABLE_STARTUPCACHE
+    return nullptr;
+#else
+    StartupCache::InitSingleton();
+#endif
+  }
+
   return StartupCache::gStartupCache;
 }
 
 void StartupCache::DeleteSingleton() { StartupCache::gStartupCache = nullptr; }
 
-nsresult StartupCache::PartialInitSingleton(nsIFile* aProfileLocalDir) {
-#ifdef MOZ_DISABLE_STARTUPCACHE
-  return NS_OK;
-#else
-  if (!XRE_IsParentProcess()) {
-    return NS_OK;
-  }
-
+nsresult StartupCache::InitSingleton() {
   nsresult rv;
   StartupCache::gStartupCache = new StartupCache();
 
-  rv = StartupCache::gStartupCache->PartialInit(aProfileLocalDir);
+  rv = StartupCache::gStartupCache->Init();
   if (NS_FAILED(rv)) {
     StartupCache::gStartupCache = nullptr;
   }
   return rv;
-#endif
-}
-
-nsresult StartupCache::InitChildSingleton(char* aScacheHandleStr,
-                                          char* aScacheSizeStr) {
-#ifdef MOZ_DISABLE_STARTUPCACHE
-  return NS_OK;
-#else
-  MOZ_ASSERT(!XRE_IsParentProcess());
-
-  nsresult rv;
-  StartupCache::gStartupCache = new StartupCache();
-
-  rv = StartupCache::gStartupCache->ParseStartupCacheCmdLineArgs(
-      aScacheHandleStr, aScacheSizeStr);
-  if (NS_FAILED(rv)) {
-    StartupCache::gStartupCache = nullptr;
-  }
-  return rv;
-#endif
-}
-
-nsresult StartupCache::FullyInitSingleton() {
-  if (!StartupCache::gStartupCache) {
-    return NS_OK;
-  }
-  return StartupCache::gStartupCache->FullyInit();
 }
 
 StaticRefPtr<StartupCache> StartupCache::gStartupCache;
-ProcessType sProcessType;
+bool StartupCache::gShutdownInitiated;
 bool StartupCache::gIgnoreDiskCache;
 bool StartupCache::gFoundDiskCacheOnInit;
 
 NS_IMPL_ISUPPORTS(StartupCache, nsIMemoryReporter)
 
 StartupCache::StartupCache()
-    : mLock("StartupCache::mLock"),
+    : mTableLock("StartupCache::mTableLock"),
       mDirty(false),
       mWrittenOnce(false),
       mCurTableReferenced(false),
-      mLoaded(false),
-      mFullyInitialized(false),
       mRequestedCount(0),
-      mPrefetchSize(0),
-      mSharedDataSize(0),
       mCacheEntriesBaseOffset(0),
       mPrefetchThread(nullptr) {}
 
 StartupCache::~StartupCache() { UnregisterWeakMemoryReporter(this); }
 
-nsresult StartupCache::InitChild(StartupCacheChild* cacheChild) {
-  mChildActor = cacheChild;
-  sProcessType =
-      GetChildProcessType(dom::ContentChild::GetSingleton()->GetRemoteType());
-
-  mObserverService = do_GetService("@mozilla.org/observer-service;1");
-
-  if (!mObserverService) {
-    NS_WARNING("Could not get observerService.");
-    return NS_ERROR_UNEXPECTED;
-  }
-
-  mListener = new StartupCacheListener();
-  nsresult rv = mObserverService->AddObserver(
-      mListener, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
-  NS_ENSURE_SUCCESS(rv, rv);
-  rv = mObserverService->AddObserver(mListener, "startupcache-invalidate",
-                                     false);
-
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (mChildActor) {
-    if (sProcessType == ProcessType::PrivilegedAbout) {
-      // Since we control all of the documents loaded in the privileged
-      // content process, we can increase the window of active time for the
-      // StartupCache to include the scripts that are loaded until the
-      // first document finishes loading.
-      mContentStartupFinishedTopic.AssignLiteral(CONTENT_DOCUMENT_LOADED_TOPIC);
-    } else {
-      // In the child process, we need to freeze the startup cache before any
-      // untrusted code has been executed. The insertion of the first DOM
-      // document element may sometimes be earlier than is ideal, but at
-      // least it should always be safe.
-      mContentStartupFinishedTopic.AssignLiteral(DOC_ELEM_INSERTED_TOPIC);
-    }
-
-    mObserverService->AddObserver(mListener, mContentStartupFinishedTopic.get(),
-                                  false);
-  }
-
-  mFullyInitialized = true;
-  RegisterWeakMemoryReporter(this);
-  return NS_OK;
-}
-
-nsresult StartupCache::PartialInit(nsIFile* aProfileLocalDir) {
-  MutexAutoLock lock(mLock);
+nsresult StartupCache::Init() {
   // workaround for bug 653936
   nsCOMPtr<nsIProtocolHandler> jarInitializer(
       do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "jar"));
 
-  sProcessType = ProcessType::Parent;
   nsresult rv;
 
   if (mozilla::RunningGTest()) {
     STARTUP_CACHE_WRITE_TIMEOUT = 3;
   }
 
   // This allows to override the startup cache filename
   // which is useful from xpcshell, when there is no ProfLDS directory to keep
   // cache in.
   char* env = PR_GetEnv("MOZ_STARTUP_CACHE");
   if (env && *env) {
     rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(env), false,
                          getter_AddRefs(mFile));
-  } else if (aProfileLocalDir) {
+  } else {
     nsCOMPtr<nsIFile> file;
-    rv = aProfileLocalDir->Clone(getter_AddRefs(file));
+    rv = NS_GetSpecialDirectory("ProfLDS", getter_AddRefs(file));
     if (NS_FAILED(rv)) {
       // return silently, this will fail in mochitests's xpcshell process.
       return rv;
     }
 
     rv = file->AppendNative("startupCache"_ns);
     NS_ENSURE_SUCCESS(rv, rv);
 
@@ -297,716 +192,286 @@ nsresult StartupCache::PartialInit(nsIFi
     rv = file->Create(nsIFile::DIRECTORY_TYPE, 0777);
     if (NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS) return rv;
 
     rv = file->AppendNative(nsLiteralCString(STARTUP_CACHE_NAME));
 
     NS_ENSURE_SUCCESS(rv, rv);
 
     mFile = file;
-  } else {
-    return NS_ERROR_INVALID_ARG;
   }
 
   NS_ENSURE_TRUE(mFile, NS_ERROR_UNEXPECTED);
 
-  mDecompressionContext = MakeUnique<LZ4FrameDecompressionContext>(true);
+  mObserverService = do_GetService("@mozilla.org/observer-service;1");
+
+  if (!mObserverService) {
+    NS_WARNING("Could not get observerService.");
+    return NS_ERROR_UNEXPECTED;
+  }
 
-  Unused << mCacheData.init(mFile);
+  mListener = new StartupCacheListener();
+  rv = mObserverService->AddObserver(mListener, NS_XPCOM_SHUTDOWN_OBSERVER_ID,
+                                     false);
+  NS_ENSURE_SUCCESS(rv, rv);
+  rv = mObserverService->AddObserver(mListener, "startupcache-invalidate",
+                                     false);
+  NS_ENSURE_SUCCESS(rv, rv);
+
   auto result = LoadArchive();
   rv = result.isErr() ? result.unwrapErr() : NS_OK;
 
   gFoundDiskCacheOnInit = rv != NS_ERROR_FILE_NOT_FOUND;
 
   // Sometimes we don't have a cache yet, that's ok.
   // If it's corrupted, just remove it and start over.
   if (gIgnoreDiskCache || (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND)) {
     NS_WARNING("Failed to load startupcache file correctly, removing!");
-    InvalidateCacheImpl();
-  }
-
-  return NS_OK;
-}
-
-nsresult StartupCache::FullyInit() {
-  mObserverService = do_GetService("@mozilla.org/observer-service;1");
-
-  if (!mObserverService) {
-    NS_WARNING("Could not get observerService.");
-    return NS_ERROR_UNEXPECTED;
-  }
-
-  mListener = new StartupCacheListener();
-  nsresult rv = mObserverService->AddObserver(
-      mListener, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-  rv = mObserverService->AddObserver(mListener, "startupcache-invalidate",
-                                     false);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
+    InvalidateCache();
   }
 
   RegisterWeakMemoryReporter(this);
-  mFullyInitialized = true;
-  return NS_OK;
-}
-
-void StartupCache::InitContentChild(dom::ContentParent& parent) {
-  auto* cache = GetSingleton();
-  if (!cache) {
-    return;
-  }
-
-  Unused << parent.SendPStartupCacheConstructor();
-}
-
-void StartupCache::AddStartupCacheCmdLineArgs(
-    mozilla::ipc::GeckoChildProcessHost& procHost,
-    const nsACString& aRemoteType, std::vector<std::string>& aExtraOpts) {
-#ifndef ANDROID
-  // Don't send original cache data to new processes if the cache has been
-  // invalidated.
-  if (!mSharedData.initialized() || gIgnoreDiskCache) {
-    auto processType = GetChildProcessType(aRemoteType);
-    bool wantScriptData = !mInitializedProcesses.contains(processType);
-    mInitializedProcesses += processType;
-    if (!wantScriptData) {
-      aExtraOpts.push_back("-noScache");
-    }
-    return;
-  }
-
-  // Formats a pointer or pointer-sized-integer as a string suitable for
-  // passing in an arguments list.
-  auto formatPtrArg = [](auto arg) {
-    return nsPrintfCString("%zu", uintptr_t(arg));
-  };
-  if (!mSharedDataHandle) {
-    auto fd = mSharedData.cloneHandle();
-    MOZ_ASSERT(fd.IsValid());
-
-    mSharedDataHandle = fd.TakePlatformHandle();
-  }
-
-#  if defined(XP_WIN)
-  procHost.AddHandleToShare(mSharedDataHandle.get());
-  aExtraOpts.push_back("-scacheHandle");
-  aExtraOpts.push_back(formatPtrArg(mSharedDataHandle.get()).get());
-#  else
-  procHost.AddFdToRemap(mSharedDataHandle.get(), kStartupCacheFd);
-#  endif
-
-  aExtraOpts.push_back("-scacheSize");
-  aExtraOpts.push_back(formatPtrArg(mSharedDataSize).get());
-#endif
-}
-
-nsresult StartupCache::ParseStartupCacheCmdLineArgs(char* aScacheHandleStr,
-                                                    char* aScacheSizeStr) {
-  // Parses an arg containing a pointer-sized-integer.
-  auto parseUIntPtrArg = [](char*& aArg) {
-    // ContentParent uses %zu to print a word-sized unsigned integer. So
-    // even though strtoull() returns a long long int, it will fit in a
-    // uintptr_t.
-    return uintptr_t(strtoull(aArg, &aArg, 10));
-  };
-
-  MutexAutoLock lock(mLock);
-  if (aScacheHandleStr) {
-#ifdef XP_WIN
-    auto parseHandleArg = [&](char*& aArg) {
-      return HANDLE(parseUIntPtrArg(aArg));
-    };
-
-    sSharedDataFD = FileDescriptor(parseHandleArg(aScacheHandleStr));
-#endif
-
-#ifdef XP_UNIX
-    sSharedDataFD = FileDescriptor(UniqueFileHandle(kStartupCacheFd));
-#endif
-    MOZ_TRY(mCacheData.initWithHandle(sSharedDataFD,
-                                      parseUIntPtrArg(aScacheSizeStr)));
-    mCacheData.setPersistent();
-  }
-
-  nsresult rv;
-  auto result = LoadArchive();
-  rv = result.isErr() ? result.unwrapErr() : NS_OK;
-
-  // Sometimes we don't have a cache yet, that's ok.
-  // If it's corrupted, just remove it and start over.
-  if (gIgnoreDiskCache || (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND)) {
-    NS_WARNING("Failed to load startupcache file correctly, removing!");
-    InvalidateCacheImpl();
-  }
+  mDecompressionContext = MakeUnique<LZ4FrameDecompressionContext>(true);
 
   return NS_OK;
 }
 
-ProcessType StartupCache::GetChildProcessType(const nsACString& remoteType) {
-  if (remoteType == EXTENSION_REMOTE_TYPE) {
-    return ProcessType::Extension;
-  }
-  if (remoteType == PRIVILEGEDABOUT_REMOTE_TYPE) {
-    return ProcessType::PrivilegedAbout;
-  }
-  return ProcessType::Web;
-}
-
 void StartupCache::StartPrefetchMemoryThread() {
   // XXX: It would be great for this to not create its own thread, unfortunately
   // there doesn't seem to be an existing thread that makes sense for this, so
   // barring a coordinated global scheduling system this is the best we get.
   mPrefetchThread = PR_CreateThread(
       PR_USER_THREAD, StartupCache::ThreadedPrefetch, this, PR_PRIORITY_NORMAL,
       PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 256 * 1024);
 }
 
-Result<Ok, nsresult> StartupCache::LoadEntriesOffDisk() {
-  mLock.AssertCurrentThreadOwns();
+/**
+ * LoadArchive can only be called from the main thread.
+ */
+Result<Ok, nsresult> StartupCache::LoadArchive() {
+  MOZ_ASSERT(NS_IsMainThread(), "Can only load startup cache on main thread");
+  if (gIgnoreDiskCache) return Err(NS_ERROR_FAILURE);
+
+  MOZ_TRY(mCacheData.init(mFile));
   auto size = mCacheData.size();
+  if (CanPrefetchMemory()) {
+    StartPrefetchMemoryThread();
+  }
 
   uint32_t headerSize;
-  uint32_t prefetchSize;
-  size_t headerOffset =
-      sizeof(MAGIC) + sizeof(headerSize) + sizeof(prefetchSize);
-  if (size < headerOffset) {
+  if (size < sizeof(MAGIC) + sizeof(headerSize)) {
     return Err(NS_ERROR_UNEXPECTED);
   }
 
   auto data = mCacheData.get<uint8_t>();
   auto end = data + size;
 
-  auto cleanup = MakeScopeExit([&]() {
-    WaitOnPrefetchThread();
-    mTable.clear();
-    mCacheData.reset();
-    mSharedDataSize = 0;
-  });
-
   MMAP_FAULT_HANDLER_BEGIN_BUFFER(data.get(), size)
 
   if (memcmp(MAGIC, data.get(), sizeof(MAGIC))) {
     return Err(NS_ERROR_UNEXPECTED);
   }
   data += sizeof(MAGIC);
 
   headerSize = LittleEndian::readUint32(data.get());
   data += sizeof(headerSize);
 
-  prefetchSize = LittleEndian::readUint32(data.get());
-  data += sizeof(prefetchSize);
-
-  if (size < prefetchSize) {
+  if (headerSize > end - data) {
     MOZ_ASSERT(false, "StartupCache file is corrupt.");
     return Err(NS_ERROR_UNEXPECTED);
   }
 
-  if (size < headerOffset + headerSize) {
-    MOZ_ASSERT(false, "StartupCache file is corrupt.");
-    return Err(NS_ERROR_UNEXPECTED);
-  }
-
-  if (CanPrefetchMemory()) {
-    mPrefetchSize = prefetchSize;
-    StartPrefetchMemoryThread();
-  }
-
   Range<uint8_t> header(data, data + headerSize);
   data += headerSize;
 
-  uint32_t numSharedEntries = 0;
-
-  mCacheEntriesBaseOffset = headerOffset + headerSize;
+  mCacheEntriesBaseOffset = sizeof(MAGIC) + sizeof(headerSize) + headerSize;
   {
     if (!mTable.reserve(STARTUP_CACHE_RESERVE_CAPACITY)) {
       return Err(NS_ERROR_UNEXPECTED);
     }
+    auto cleanup = MakeScopeExit([&]() {
+      WaitOnPrefetchThread();
+      mTable.clear();
+      mCacheData.reset();
+    });
     loader::InputBuffer buf(header);
 
     uint32_t currentOffset = 0;
-    mSharedDataSize = sizeof(MAGIC) + sizeof(numSharedEntries);
     while (!buf.finished()) {
       uint32_t offset = 0;
       uint32_t compressedSize = 0;
       uint32_t uncompressedSize = 0;
-      uint8_t sharedToChild = 0;
-      uint16_t keyLenWithNullTerm;
+      nsCString key;
       buf.codeUint32(offset);
       buf.codeUint32(compressedSize);
       buf.codeUint32(uncompressedSize);
-      buf.codeUint8(sharedToChild);
-      buf.codeUint16(keyLenWithNullTerm);
-      if (!buf.checkCapacity(keyLenWithNullTerm)) {
-        MOZ_ASSERT(false, "StartupCache file is corrupt.");
-        return Err(NS_ERROR_UNEXPECTED);
-      }
-
-      const char* keyBuf =
-          reinterpret_cast<const char*>(buf.read(keyLenWithNullTerm));
-      if (keyBuf[keyLenWithNullTerm - 1] != 0) {
-        MOZ_ASSERT(false, "StartupCache file is corrupt.");
-        return Err(NS_ERROR_UNEXPECTED);
-      }
-
-      MaybeOwnedCharPtr key(MakeUnique<char[]>(keyLenWithNullTerm));
-      memcpy(key.get(), keyBuf, keyLenWithNullTerm);
+      buf.codeString(key);
 
       if (offset + compressedSize > end - data) {
-        if (XRE_IsParentProcess()) {
-          MOZ_ASSERT(false, "StartupCache file is corrupt.");
-          return Err(NS_ERROR_UNEXPECTED);
-        }
-
-        // If we're not the parent process, then we received a buffer with
-        // only data that was already prefetched. If that's the case, then
-        // just break because we've hit the end of that range.
-        break;
-      }
-
-      EnumSet<StartupCacheEntryFlags> entryFlags;
-      if (sharedToChild) {
-        // We encode the key as a u16 indicating the length, followed by the
-        // contents of the string, plus a null terminator (to simplify things
-        // by using existing c-string hashers). We encode the uncompressed data
-        // as simply a u32 length, followed by the contents of the string.
-        size_t sharedEntrySize = sizeof(uint16_t) + keyLenWithNullTerm +
-                                 sizeof(uint32_t) + uncompressedSize;
-        numSharedEntries++;
-        mSharedDataSize += sharedEntrySize;
-        entryFlags += StartupCacheEntryFlags::Shared;
+        MOZ_ASSERT(false, "StartupCache file is corrupt.");
+        return Err(NS_ERROR_UNEXPECTED);
       }
 
       // Make sure offsets match what we'd expect based on script ordering and
       // size, as a basic sanity check.
       if (offset != currentOffset) {
-        MOZ_ASSERT(false, "StartupCache file is corrupt.");
         return Err(NS_ERROR_UNEXPECTED);
       }
       currentOffset += compressedSize;
 
       // We could use mTable.putNew if we knew the file we're loading weren't
       // corrupt. However, we don't know that, so check if the key already
       // exists. If it does, we know the file must be corrupt.
-      decltype(mTable)::AddPtr p = mTable.lookupForAdd(key.get());
+      decltype(mTable)::AddPtr p = mTable.lookupForAdd(key);
       if (p) {
-        MOZ_ASSERT(false, "StartupCache file is corrupt.");
         return Err(NS_ERROR_UNEXPECTED);
       }
 
-      if (!mTable.add(p, std::move(key),
-                      StartupCacheEntry(offset, compressedSize,
-                                        uncompressedSize, entryFlags))) {
-        MOZ_ASSERT(false, "StartupCache file is corrupt.");
+      if (!mTable.add(
+              p, key,
+              StartupCacheEntry(offset, compressedSize, uncompressedSize))) {
         return Err(NS_ERROR_UNEXPECTED);
       }
     }
 
     if (buf.error()) {
-      MOZ_ASSERT(false, "StartupCache file is corrupt.");
       return Err(NS_ERROR_UNEXPECTED);
     }
 
-    // We only get to init mSharedData once - we can't edit it after we created
-    // it, otherwise we'd be pulling memory out from underneath our child
-    // processes.
-    if (!mSharedData.initialized()) {
-      ipc::MemMapSnapshot mem;
-      if (mem.Init(mSharedDataSize).isErr()) {
-        MOZ_ASSERT(false, "Failed to init shared StartupCache data.");
-        return Err(NS_ERROR_UNEXPECTED);
-      }
-
-      auto ptr = mem.Get<uint8_t>();
-      Range<uint8_t> ptrRange(ptr, ptr + mSharedDataSize);
-      loader::PreallocatedOutputBuffer sharedBuf(ptrRange);
-
-      if (sizeof(MAGIC) > sharedBuf.remainingCapacity()) {
-        MOZ_ASSERT(false);
-        return Err(NS_ERROR_UNEXPECTED);
-      }
-      uint8_t* sharedMagic = sharedBuf.write(sizeof(MAGIC));
-      memcpy(sharedMagic, MAGIC, sizeof(MAGIC));
-      sharedBuf.codeUint32(numSharedEntries);
-
-      for (auto iter = mTable.iter(); !iter.done(); iter.next()) {
-        const auto& key = iter.get().key();
-        auto& value = iter.get().value();
-
-        if (!value.mFlags.contains(StartupCacheEntryFlags::Shared)) {
-          continue;
-        }
-
-        uint16_t keyLenWithNullTerm =
-            strnlen(key.get(), kStartupCacheKeyLengthCap) + 1;
-        if (keyLenWithNullTerm >= kStartupCacheKeyLengthCap) {
-          MOZ_ASSERT(false, "StartupCache key too large or not terminated.");
-          return Err(NS_ERROR_UNEXPECTED);
-        }
-        sharedBuf.codeUint16(keyLenWithNullTerm);
-
-        if (!sharedBuf.checkCapacity(keyLenWithNullTerm)) {
-          MOZ_ASSERT(false, "Exceeded shared StartupCache buffer size.");
-          return Err(NS_ERROR_UNEXPECTED);
-        }
-        uint8_t* keyBuffer = sharedBuf.write(keyLenWithNullTerm);
-        memcpy(keyBuffer, key.get(), keyLenWithNullTerm);
-
-        sharedBuf.codeUint32(value.mUncompressedSize);
-
-        if (value.mUncompressedSize > sharedBuf.remainingCapacity()) {
-          MOZ_ASSERT(false);
-          return Err(NS_ERROR_UNEXPECTED);
-        }
-
-        auto sharedDataOffset = sharedBuf.cursor();
-        auto decompressionBuffer = MaybeOwnedCharPtr(
-            (char*)(sharedBuf.write(value.mUncompressedSize)));
-
-        if (sharedBuf.error()) {
-          MOZ_ASSERT(false, "Failed serializing to shared memory.");
-          return Err(NS_ERROR_UNEXPECTED);
-        }
-
-        // NOTE: we decompress the entry here, but we don't want to assign mData
-        // for the table entry, because all we have is a pointer into the
-        // ipc::MemMapSnapshot's buffer - once we've finalized the snapshot with
-        // mem.Finalize below, we can cut pointers into mSharedData's buffer.
-        // This happens inside GetBuffer, using value.mSharedDataOffset which we
-        // set here.
-        MOZ_TRY(DecompressEntry(value, decompressionBuffer));
-        value.mSharedDataOffset = sharedDataOffset;
-      }
-
-      if (mem.Finalize(mSharedData).isErr()) {
-        MOZ_ASSERT(false, "Failed to freeze shared StartupCache data.");
-        return Err(NS_ERROR_UNEXPECTED);
-      }
-
-      mSharedData.setPersistent();
-    }
+    cleanup.release();
   }
 
   MMAP_FAULT_HANDLER_CATCH(Err(NS_ERROR_UNEXPECTED))
-  cleanup.release();
-
-  return Ok();
-}
-
-Result<Ok, nsresult> StartupCache::LoadEntriesFromSharedMemory() {
-  mLock.AssertCurrentThreadOwns();
-  auto size = mCacheData.size();
-  auto start = mCacheData.get<uint8_t>();
-  auto end = start + size;
-
-  Range<uint8_t> range(start, end);
-  loader::InputBuffer buf(range);
-
-  if (sizeof(MAGIC) > buf.remainingCapacity()) {
-    MOZ_ASSERT(false, "Bad shared StartupCache buffer.");
-    return Err(NS_ERROR_UNEXPECTED);
-  }
-
-  const uint8_t* magic = buf.read(sizeof(MAGIC));
-  if (memcmp(magic, MAGIC, sizeof(MAGIC)) != 0) {
-    MOZ_ASSERT(false, "Bad shared StartupCache buffer.");
-    return Err(NS_ERROR_UNEXPECTED);
-  }
-
-  uint32_t numEntries = 0;
-  if (!buf.codeUint32(numEntries) || numEntries > STARTUP_CACHE_MAX_CAPACITY) {
-    MOZ_ASSERT(false, "Bad number of entries in shared StartupCache buffer.");
-    return Err(NS_ERROR_UNEXPECTED);
-  }
-
-  if (!mTable.reserve(STARTUP_CACHE_RESERVE_CAPACITY)) {
-    return Err(NS_ERROR_UNEXPECTED);
-  }
-
-  uint32_t entriesSeen = 0;
-  while (!buf.finished()) {
-    entriesSeen++;
-    if (entriesSeen > numEntries) {
-      MOZ_ASSERT(false, "More entries than expected in StartupCache buffer.");
-      return Err(NS_ERROR_UNEXPECTED);
-    }
-
-    uint16_t keyLenWithNullTerm = 0;
-    buf.codeUint16(keyLenWithNullTerm);
-    // NOTE: this will fail if the above codeUint16 call failed.
-    if (!buf.checkCapacity(keyLenWithNullTerm)) {
-      MOZ_ASSERT(false, "Corrupt StartupCache shared buffer.");
-      return Err(NS_ERROR_UNEXPECTED);
-    }
-    MaybeOwnedCharPtr key(const_cast<char*>(
-        reinterpret_cast<const char*>(buf.read(keyLenWithNullTerm))));
-    if (key.get()[keyLenWithNullTerm - 1] != 0) {
-      MOZ_ASSERT(false, "StartupCache key was not null-terminated");
-      return Err(NS_ERROR_UNEXPECTED);
-    }
-
-    uint32_t uncompressedSize = 0;
-    buf.codeUint32(uncompressedSize);
-
-    if (!buf.checkCapacity(uncompressedSize)) {
-      MOZ_ASSERT(false,
-                 "StartupCache entry larger than remaining buffer size.");
-      return Err(NS_ERROR_UNEXPECTED);
-    }
-    const char* data =
-        reinterpret_cast<const char*>(buf.read(uncompressedSize));
-
-    StartupCacheEntry entry(0, 0, uncompressedSize,
-                            StartupCacheEntryFlags::Shared);
-    // The const cast is unfortunate here. We have runtime guarantees via memory
-    // protections that mData will not be modified, but we do not have compile
-    // time guarantees.
-    entry.mData = MaybeOwnedCharPtr(const_cast<char*>(data));
-
-    if (!mTable.putNew(std::move(key), std::move(entry))) {
-      return Err(NS_ERROR_UNEXPECTED);
-    }
-  }
-
-  return Ok();
-}
-
-/**
- * LoadArchive can only be called from the main thread.
- */
-Result<Ok, nsresult> StartupCache::LoadArchive() {
-  mLock.AssertCurrentThreadOwns();
-
-  if (gIgnoreDiskCache) {
-    return Err(NS_ERROR_FAILURE);
-  }
-
-  mLoaded = true;
-
-  if (!mCacheData.initialized()) {
-    return Err(NS_ERROR_FILE_NOT_FOUND);
-  }
-
-  if (XRE_IsParentProcess()) {
-    MOZ_TRY(LoadEntriesOffDisk());
-  } else {
-    MOZ_TRY(LoadEntriesFromSharedMemory());
-  }
-
-  return Ok();
-}
-
-Result<Ok, nsresult> StartupCache::DecompressEntry(StartupCacheEntry& aEntry,
-                                                   MaybeOwnedCharPtr& aBuffer) {
-  MOZ_ASSERT(XRE_IsParentProcess());
-  mLock.AssertCurrentThreadOwns();
-
-  size_t totalRead = 0;
-  size_t totalWritten = 0;
-  Span<const char> compressed = Span(
-      mCacheData.get<char>().get() + mCacheEntriesBaseOffset + aEntry.mOffset,
-      aEntry.mCompressedSize);
-  Span<char> uncompressed = Span(aBuffer.get(), aEntry.mUncompressedSize);
-  bool finished = false;
-  while (!finished) {
-    auto result = mDecompressionContext->Decompress(
-        uncompressed.From(totalWritten), compressed.From(totalRead));
-    if (NS_WARN_IF(result.isErr())) {
-      InvalidateCacheImpl();
-      return Err(NS_ERROR_UNEXPECTED);
-    }
-    auto decompressionResult = result.unwrap();
-    totalRead += decompressionResult.mSizeRead;
-    totalWritten += decompressionResult.mSizeWritten;
-    finished = decompressionResult.mFinished;
-  }
 
   return Ok();
 }
 
 bool StartupCache::HasEntry(const char* id) {
   AUTO_PROFILER_LABEL("StartupCache::HasEntry", OTHER);
 
-  MOZ_ASSERT(
-      strnlen(id, kStartupCacheKeyLengthCap) + 1 < kStartupCacheKeyLengthCap,
-      "StartupCache key too large or not terminated.");
+  MOZ_ASSERT(NS_IsMainThread(), "Startup cache only available on main thread");
 
-  // The lock could be held here by the write thread, which could take a while.
-  // scache reads/writes are never critical enough to block waiting for the
-  // entire cache to be written to disk, so if we can't acquire the lock, we
-  // just exit.
-  Maybe<MutexAutoLock> tryLock;
-  if (!MutexAutoLock::TryMake(mLock, tryLock)) {
-    return false;
-  }
-
-  bool result = mTable.has(id);
-  return result;
+  return mTable.has(nsDependentCString(id));
 }
 
 nsresult StartupCache::GetBuffer(const char* id, const char** outbuf,
                                  uint32_t* length) {
+  AUTO_PROFILER_LABEL("StartupCache::GetBuffer", OTHER);
+
+  NS_ASSERTION(NS_IsMainThread(),
+               "Startup cache only available on main thread");
+
   Telemetry::LABELS_STARTUP_CACHE_REQUESTS label =
       Telemetry::LABELS_STARTUP_CACHE_REQUESTS::Miss;
   auto telemetry =
       MakeScopeExit([&label] { Telemetry::AccumulateCategorical(label); });
 
-  // The lock could be held here by the write thread, which could take a while.
-  // scache reads/writes are never critical enough to block waiting for the
-  // entire cache to be written to disk, so if we can't acquire the lock, we
-  // just exit.
-  Maybe<MutexAutoLock> tryLock;
-  if (!MutexAutoLock::TryMake(mLock, tryLock)) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  if (!mLoaded) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  MOZ_ASSERT(
-      strnlen(id, kStartupCacheKeyLengthCap) + 1 < kStartupCacheKeyLengthCap,
-      "StartupCache key too large or not terminated.");
-  decltype(mTable)::Ptr p = mTable.lookup(id);
+  decltype(mTable)::Ptr p = mTable.lookup(nsDependentCString(id));
   if (!p) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
-  // Track that something holds a reference into mTable, so we know to hold
-  // onto it in case the cache is invalidated.
-  mCurTableReferenced = true;
   auto& value = p->value();
   if (value.mData) {
     label = Telemetry::LABELS_STARTUP_CACHE_REQUESTS::HitMemory;
-  } else if (value.mSharedDataOffset != kStartupcacheEntryNotInSharedData) {
-    if (!XRE_IsParentProcess() || !mSharedData.initialized()) {
+  } else {
+    if (!mCacheData.initialized()) {
+      return NS_ERROR_NOT_AVAILABLE;
+    }
+#ifdef DEBUG
+    // It should be impossible for a write to be pending here. This is because
+    // we just checked mCacheData.initialized(), and this is reset before
+    // writing to the cache. It's not re-initialized unless we call
+    // LoadArchive(), either from Init() (which must have already happened) or
+    // InvalidateCache(). InvalidateCache() locks the mutex, so a write can't be
+    // happening. Really, we want to MOZ_ASSERT(!mTableLock.IsLocked()) here,
+    // but there is no such method. So we hack around by attempting to gain the
+    // lock. This should always succeed; if it fails, someone's broken the
+    // assumptions.
+    if (!mTableLock.TryLock()) {
+      MOZ_ASSERT(false, "Could not gain mTableLock - should never happen!");
       return NS_ERROR_NOT_AVAILABLE;
     }
-    value.mData = MaybeOwnedCharPtr(mSharedData.get<char>().get() +
-                                    value.mSharedDataOffset);
-    label = Telemetry::LABELS_STARTUP_CACHE_REQUESTS::HitMemory;
-  } else {
-    // We do not decompress entries in child processes: we receive them
-    // uncompressed in shared memory.
-    if (!XRE_IsParentProcess() || !mCacheData.initialized()) {
-      return NS_ERROR_NOT_AVAILABLE;
+    mTableLock.Unlock();
+#endif
+
+    size_t totalRead = 0;
+    size_t totalWritten = 0;
+    Span<const char> compressed = Span(
+        mCacheData.get<char>().get() + mCacheEntriesBaseOffset + value.mOffset,
+        value.mCompressedSize);
+    value.mData = MakeUnique<char[]>(value.mUncompressedSize);
+    Span<char> uncompressed = Span(value.mData.get(), value.mUncompressedSize);
+    MMAP_FAULT_HANDLER_BEGIN_BUFFER(uncompressed.Elements(),
+                                    uncompressed.Length())
+    bool finished = false;
+    while (!finished) {
+      auto result = mDecompressionContext->Decompress(
+          uncompressed.From(totalWritten), compressed.From(totalRead));
+      if (NS_WARN_IF(result.isErr())) {
+        value.mData = nullptr;
+        InvalidateCache();
+        return NS_ERROR_FAILURE;
+      }
+      auto decompressionResult = result.unwrap();
+      totalRead += decompressionResult.mSizeRead;
+      totalWritten += decompressionResult.mSizeWritten;
+      finished = decompressionResult.mFinished;
     }
 
-    MMAP_FAULT_HANDLER_BEGIN_BUFFER(value.mData.get(), value.mUncompressedSize)
-
-    auto decompressionBuffer = MaybeOwnedCharPtr(value.mUncompressedSize);
-    auto decompressionResult = DecompressEntry(value, decompressionBuffer);
-    if (decompressionResult.isErr()) {
-      return decompressionResult.unwrapErr();
-    }
-
-    value.mData = std::move(decompressionBuffer);
     MMAP_FAULT_HANDLER_CATCH(NS_ERROR_FAILURE)
 
     label = Telemetry::LABELS_STARTUP_CACHE_REQUESTS::HitDisk;
   }
 
-  if (value.mRequestedOrder == kStartupCacheEntryNotRequested) {
+  if (!value.mRequested) {
+    value.mRequested = true;
     value.mRequestedOrder = ++mRequestedCount;
     MOZ_ASSERT(mRequestedCount <= mTable.count(),
                "Somehow we requested more StartupCache items than exist.");
     ResetStartupWriteTimerCheckingReadCount();
   }
 
+  // Track that something holds a reference into mTable, so we know to hold
+  // onto it in case the cache is invalidated.
+  mCurTableReferenced = true;
   *outbuf = value.mData.get();
   *length = value.mUncompressedSize;
-
-  if (value.mData.IsOwned()) {
-    // We're returning a raw reference to this entry's owned buffer, so we can
-    // no longer free that buffer.
-    value.mFlags += StartupCacheEntryFlags::DoNotFree;
-  }
-
   return NS_OK;
 }
 
-// Client gives ownership of inbuf.
+// Makes a copy of the buffer, client retains ownership of inbuf.
 nsresult StartupCache::PutBuffer(const char* id, UniquePtr<char[]>&& inbuf,
-                                 uint32_t len, bool isFromChildProcess) {
-  // We use this to update the RequestedByChild flag.
-  MOZ_RELEASE_ASSERT(
-      inbuf || isFromChildProcess,
-      "Null input to PutBuffer should only be used by child actor.");
-
-  if (!XRE_IsParentProcess() && !mChildActor && mFullyInitialized) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  // If we've already written to disk, just go ahead and exit. There's no point
-  // in putting something in the cache since we're not going to write again.
-  if (mWrittenOnce) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  // The lock could be held here by the write thread, which could take a while.
-  // scache reads/writes are never critical enough to block waiting for the
-  // entire cache to be written to disk, so if we can't acquire the lock, we
-  // just exit.
-  Maybe<MutexAutoLock> tryLock;
-  if (!MutexAutoLock::TryMake(mLock, tryLock)) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  if (!mLoaded) {
+                                 uint32_t len) {
+  NS_ASSERTION(NS_IsMainThread(),
+               "Startup cache only available on main thread");
+  if (StartupCache::gShutdownInitiated) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
-  uint32_t keyLenWithNullTerm = strnlen(id, kStartupCacheKeyLengthCap) + 1;
-  if (keyLenWithNullTerm >= kStartupCacheKeyLengthCap) {
-    MOZ_ASSERT(false, "StartupCache key too large or not terminated.");
-    return NS_ERROR_UNEXPECTED;
-  }
-  decltype(mTable)::AddPtr p = mTable.lookupForAdd(id);
+  bool exists = mTable.has(nsDependentCString(id));
 
-  if (p) {
-    if (isFromChildProcess) {
-      auto& value = p->value();
-      value.mFlags += StartupCacheEntryFlags::RequestedByChild;
-      if (value.mRequestedOrder == kStartupCacheEntryNotRequested) {
-        value.mRequestedOrder = ++mRequestedCount;
-        MOZ_ASSERT(mRequestedCount <= mTable.count(),
-                   "Somehow we requested more StartupCache items than exist.");
-        ResetStartupWriteTimerCheckingReadCount();
-      }
-    } else {
-      NS_WARNING("Existing entry in StartupCache.");
-    }
-
+  if (exists) {
+    NS_WARNING("Existing entry in StartupCache.");
     // Double-caching is undesirable but not an error.
     return NS_OK;
   }
-
-  if (!inbuf) {
-    MOZ_ASSERT(false,
-               "Should only PutBuffer with null buffer for existing entries.");
-    return NS_ERROR_UNEXPECTED;
+  // Try to gain the table write lock. If the background task to write the
+  // cache is running, this will fail.
+  if (!mTableLock.TryLock()) {
+    return NS_ERROR_NOT_AVAILABLE;
   }
+  auto lockGuard = MakeScopeExit([&] { mTableLock.Unlock(); });
 
-  EnumSet<StartupCacheEntryFlags> flags =
-      StartupCacheEntryFlags::AddedThisSession;
-  if (isFromChildProcess) {
-    flags += StartupCacheEntryFlags::RequestedByChild;
-  }
-
-  UniquePtr<char[]> key = MakeUnique<char[]>(keyLenWithNullTerm);
-  memcpy(key.get(), id, keyLenWithNullTerm);
-  // add returns false on alloc failure - in the very unlikely event we hit
+  // putNew returns false on alloc failure - in the very unlikely event we hit
   // that and aren't going to crash elsewhere, there's no reason we need to
   // crash here.
-  if (mTable.add(
-          p, MaybeOwnedCharPtr(std::move(key)),
-          StartupCacheEntry(std::move(inbuf), len, ++mRequestedCount, flags))) {
-    return ResetStartupWriteTimerImpl();
+  if (mTable.putNew(nsCString(id), StartupCacheEntry(std::move(inbuf), len,
+                                                     ++mRequestedCount))) {
+    return ResetStartupWriteTimer();
   }
   MOZ_DIAGNOSTIC_ASSERT(mTable.count() < STARTUP_CACHE_MAX_CAPACITY,
                         "Too many StartupCache entries.");
   return NS_OK;
 }
 
 size_t StartupCache::HeapSizeOfIncludingThis(
     mozilla::MallocSizeOf aMallocSizeOf) const {
@@ -1015,338 +480,237 @@ size_t StartupCache::HeapSizeOfIncluding
 
   size_t n = aMallocSizeOf(this);
 
   n += mTable.shallowSizeOfExcludingThis(aMallocSizeOf);
   for (auto iter = mTable.iter(); !iter.done(); iter.next()) {
     if (iter.get().value().mData) {
       n += aMallocSizeOf(iter.get().value().mData.get());
     }
-    n += iter.get().key().SizeOfExcludingThis(aMallocSizeOf);
+    n += iter.get().key().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
   }
 
   return n;
 }
 
 /**
  * WriteToDisk writes the cache out to disk. Callers of WriteToDisk need to call
  * WaitOnWriteComplete to make sure there isn't a write
  * happening on another thread
  */
 Result<Ok, nsresult> StartupCache::WriteToDisk() {
-  MOZ_ASSERT(XRE_IsParentProcess());
-  mLock.AssertCurrentThreadOwns();
+  mTableLock.AssertCurrentThreadOwns();
 
   if (!mDirty || mWrittenOnce) {
     return Ok();
   }
 
   if (!mFile) {
     return Err(NS_ERROR_UNEXPECTED);
   }
 
-  nsCOMPtr<nsIFile> tmpFile;
-  nsresult rv = mFile->Clone(getter_AddRefs(tmpFile));
-  if (NS_FAILED(rv)) {
-    return Err(NS_ERROR_UNEXPECTED);
-  }
-
-  nsAutoCString leafName;
-  mFile->GetNativeLeafName(leafName);
-  tmpFile->SetNativeLeafName(leafName + "-tmp"_ns);
-
-  auto cleanup = MakeScopeExit([&]() {
-    mDirty = false;
-    mWrittenOnce = true;
-    mCacheData.reset();
-
-    // If we're shutting down, we do not care about freeing up memory right now.
-    if (AppShutdown::IsShuttingDown()) {
-      return;
-    }
+  AutoFDClose fd;
+  MOZ_TRY(mFile->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
+                                  0644, &fd.rwget()));
 
-    // We've just written (or attempted to write) our buffers to disk, and
-    // we're 60 seconds out from startup, so they're unlikely to be needed
-    // again any time soon; let's clean up what we can.
-    for (auto iter = mTable.iter(); !iter.done(); iter.next()) {
-      auto& value = iter.get().value();
-      if (!value.mFlags.contains(StartupCacheEntryFlags::DoNotFree)) {
-        value.mData = nullptr;
-      }
-    }
-  });
-
-  {
-    AutoFDClose fd;
-    MOZ_TRY(tmpFile->OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
-                                      0644, &fd.rwget()));
-
-    nsTArray<std::pair<const MaybeOwnedCharPtr*, StartupCacheEntry*>> entries;
-
-    for (auto iter = mTable.iter(); !iter.done(); iter.next()) {
+  nsTArray<std::pair<const nsCString*, StartupCacheEntry*>> entries;
+  for (auto iter = mTable.iter(); !iter.done(); iter.next()) {
+    if (iter.get().value().mRequested) {
       entries.AppendElement(
           std::make_pair(&iter.get().key(), &iter.get().value()));
     }
+  }
 
-    if (entries.IsEmpty()) {
-      return Ok();
-    }
+  if (entries.IsEmpty()) {
+    return Ok();
+  }
+
+  entries.Sort(StartupCacheEntry::Comparator());
+  loader::OutputBuffer buf;
+  for (auto& e : entries) {
+    auto key = e.first;
+    auto value = e.second;
+    auto uncompressedSize = value->mUncompressedSize;
+    // Set the mHeaderOffsetInFile so we can go back and edit the offset.
+    value->mHeaderOffsetInFile = buf.cursor();
+    // Write a 0 offset/compressed size as a placeholder until we get the real
+    // offset after compressing.
+    buf.codeUint32(0);
+    buf.codeUint32(0);
+    buf.codeUint32(uncompressedSize);
+    buf.codeString(*key);
+  }
+
+  uint8_t headerSize[4];
+  LittleEndian::writeUint32(headerSize, buf.cursor());
 
-    entries.Sort(StartupCacheEntry::Comparator());
-    loader::OutputBuffer buf;
-    for (auto& e : entries) {
-      const auto* key = e.first;
-      auto* value = e.second;
-      auto uncompressedSize = value->mUncompressedSize;
-      uint8_t sharedToChild =
-          value->mFlags.contains(StartupCacheEntryFlags::RequestedByChild);
-      // Set the mHeaderOffsetInFile so we can go back and edit the offset.
-      value->mHeaderOffsetInFile = buf.cursor();
-      // Write a 0 offset/compressed size as a placeholder until we get the real
-      // offset after compressing.
-      buf.codeUint32(0);
-      buf.codeUint32(0);
-      buf.codeUint32(uncompressedSize);
-      buf.codeUint8(sharedToChild);
-      uint32_t keyLenWithNullTerm =
-          strnlen(key->get(), kStartupCacheKeyLengthCap) + 1;
-      if (keyLenWithNullTerm >= kStartupCacheKeyLengthCap) {
-        MOZ_ASSERT(false, "StartupCache key too large or not terminated.");
-        return Err(NS_ERROR_UNEXPECTED);
-      }
+  MOZ_TRY(Write(fd, MAGIC, sizeof(MAGIC)));
+  MOZ_TRY(Write(fd, headerSize, sizeof(headerSize)));
+  size_t headerStart = sizeof(MAGIC) + sizeof(headerSize);
+  size_t dataStart = headerStart + buf.cursor();
+  MOZ_TRY(Seek(fd, dataStart));
+
+  size_t offset = 0;
+
+  const size_t chunkSize = 1024 * 16;
+  LZ4FrameCompressionContext ctx(6,         /* aCompressionLevel */
+                                 chunkSize, /* aReadBufLen */
+                                 true,      /* aChecksum */
+                                 true);     /* aStableSrc */
+  size_t writeBufLen = ctx.GetRequiredWriteBufferLength();
+  auto writeBuffer = MakeUnique<char[]>(writeBufLen);
+  auto writeSpan = Span(writeBuffer.get(), writeBufLen);
 
-      buf.codeUint16(keyLenWithNullTerm);
-      char* keyBuf = reinterpret_cast<char*>(buf.write(keyLenWithNullTerm));
-      memcpy(keyBuf, key->get(), keyLenWithNullTerm);
+  for (auto& e : entries) {
+    auto value = e.second;
+    value->mOffset = offset;
+    Span<const char> result;
+    MOZ_TRY_VAR(result,
+                ctx.BeginCompressing(writeSpan).mapErr(MapLZ4ErrorToNsresult));
+    MOZ_TRY(Write(fd, result.Elements(), result.Length()));
+    offset += result.Length();
+
+    for (size_t i = 0; i < value->mUncompressedSize; i += chunkSize) {
+      size_t size = std::min(chunkSize, value->mUncompressedSize - i);
+      char* uncompressed = value->mData.get() + i;
+      MOZ_TRY_VAR(result, ctx.ContinueCompressing(Span(uncompressed, size))
+                              .mapErr(MapLZ4ErrorToNsresult));
+      MOZ_TRY(Write(fd, result.Elements(), result.Length()));
+      offset += result.Length();
     }
 
-    uint8_t headerSize[4];
-    LittleEndian::writeUint32(headerSize, buf.cursor());
-
-    MOZ_TRY(Write(fd, MAGIC, sizeof(MAGIC)));
-    MOZ_TRY(Write(fd, headerSize, sizeof(headerSize)));
-    size_t prefetchSizeOffset = sizeof(MAGIC) + sizeof(headerSize);
-    size_t headerStart = prefetchSizeOffset + sizeof(uint32_t);
-    size_t dataStart = headerStart + buf.cursor();
-    MOZ_TRY(Seek(fd, dataStart));
-
-    size_t offset = 0;
-    size_t prefetchSize = 0;
-
-    const size_t chunkSize = 1024 * 16;
-    LZ4FrameCompressionContext ctx(6,         /* aCompressionLevel */
-                                   chunkSize, /* aReadBufLen */
-                                   true,      /* aChecksum */
-                                   true);     /* aStableSrc */
-    size_t writeBufLen = ctx.GetRequiredWriteBufferLength();
-    auto writeBuffer = MaybeOwnedCharPtr(writeBufLen);
-    auto writeSpan = Span(writeBuffer.get(), writeBufLen);
-
-    for (auto& e : entries) {
-      auto* value = e.second;
-
-      // If this is the first entry which was not requested, set the prefetch
-      // size to the offset before we include this item. We will then prefetch
-      // all items up to but not including this one during our next startup.
-      if (value->mRequestedOrder == kStartupCacheEntryNotRequested &&
-          prefetchSize == 0) {
-        prefetchSize = dataStart + offset;
-      }
-
-      // Reuse the existing compressed entry if possible
-      if (mCacheData.initialized() && value->mCompressedSize) {
-        Span<const char> compressed =
-            Span(mCacheData.get<char>().get() + mCacheEntriesBaseOffset +
-                     value->mOffset,
-                 value->mCompressedSize);
-        MOZ_TRY(Write(fd, compressed.Elements(), compressed.Length()));
-        value->mOffset = offset;
-        offset += compressed.Length();
-      } else {
-        value->mOffset = offset;
-        Span<const char> result;
-        MOZ_TRY_VAR(result, ctx.BeginCompressing(writeSpan).mapErr(
-                                MapLZ4ErrorToNsresult));
-        MOZ_TRY(Write(fd, result.Elements(), result.Length()));
-        offset += result.Length();
-
-        for (size_t i = 0; i < value->mUncompressedSize; i += chunkSize) {
-          size_t size = std::min(chunkSize, value->mUncompressedSize - i);
-          char* uncompressed = value->mData.get() + i;
-          MOZ_TRY_VAR(result, ctx.ContinueCompressing(Span(uncompressed, size))
-                                  .mapErr(MapLZ4ErrorToNsresult));
-          MOZ_TRY(Write(fd, result.Elements(), result.Length()));
-          offset += result.Length();
-        }
-
-        MOZ_TRY_VAR(result, ctx.EndCompressing().mapErr(MapLZ4ErrorToNsresult));
-        MOZ_TRY(Write(fd, result.Elements(), result.Length()));
-        offset += result.Length();
-        value->mCompressedSize = offset - value->mOffset;
-      }
-    }
-
-    if (prefetchSize == 0) {
-      prefetchSize = dataStart + offset;
-    }
-
-    for (auto& e : entries) {
-      auto* value = e.second;
-      uint8_t* headerEntry = buf.Get() + value->mHeaderOffsetInFile;
-      LittleEndian::writeUint32(headerEntry, value->mOffset);
-      LittleEndian::writeUint32(headerEntry + sizeof(value->mOffset),
-                                value->mCompressedSize);
-    }
-
-    uint8_t prefetchSizeBuf[4];
-    LittleEndian::writeUint32(prefetchSizeBuf, prefetchSize);
-
-    MOZ_TRY(Seek(fd, prefetchSizeOffset));
-    MOZ_TRY(Write(fd, prefetchSizeBuf, sizeof(prefetchSizeBuf)));
-    MOZ_TRY(Write(fd, buf.Get(), buf.cursor()));
+    MOZ_TRY_VAR(result, ctx.EndCompressing().mapErr(MapLZ4ErrorToNsresult));
+    MOZ_TRY(Write(fd, result.Elements(), result.Length()));
+    offset += result.Length();
+    value->mCompressedSize = offset - value->mOffset;
+    MOZ_TRY(Seek(fd, dataStart + offset));
   }
 
-  tmpFile->MoveToNative(nullptr, leafName);
+  for (auto& e : entries) {
+    auto value = e.second;
+    uint8_t* headerEntry = buf.Get() + value->mHeaderOffsetInFile;
+    LittleEndian::writeUint32(headerEntry, value->mOffset);
+    LittleEndian::writeUint32(headerEntry + sizeof(value->mOffset),
+                              value->mCompressedSize);
+  }
+  MOZ_TRY(Seek(fd, headerStart));
+  MOZ_TRY(Write(fd, buf.Get(), buf.cursor()));
+
+  mDirty = false;
+  mWrittenOnce = true;
 
   return Ok();
 }
 
-void StartupCache::InvalidateCache() {
-  MutexAutoLock lock(mLock);
-  InvalidateCacheImpl();
-}
+void StartupCache::InvalidateCache(bool memoryOnly) {
+  WaitOnPrefetchThread();
+  // Ensure we're not writing using mTable...
+  MutexAutoLock unlock(mTableLock);
 
-void StartupCache::InvalidateCacheImpl(bool memoryOnly) {
-  mLock.AssertCurrentThreadOwns();
-
-  WaitOnPrefetchThread();
   mWrittenOnce = false;
   if (memoryOnly) {
     // This should only be called in tests.
     auto writeResult = WriteToDisk();
     if (NS_WARN_IF(writeResult.isErr())) {
       gIgnoreDiskCache = true;
       return;
     }
   }
-
   if (mCurTableReferenced) {
-    // There should be no way for this assert to fail other than a user
-    // manually sending startupcache-invalidate messages through the Browser
-    // Toolbox.
+    // There should be no way for this assert to fail other than a user manually
+    // sending startupcache-invalidate messages through the Browser Toolbox.
     MOZ_DIAGNOSTIC_ASSERT(xpc::IsInAutomation() || mOldTables.Length() < 10,
                           "Startup cache invalidated too many times.");
     mOldTables.AppendElement(std::move(mTable));
     mCurTableReferenced = false;
   } else {
     mTable.clear();
   }
-
-  if (!XRE_IsParentProcess()) {
-    return;
-  }
   mRequestedCount = 0;
-  if (!XRE_IsParentProcess()) {
-    gIgnoreDiskCache = true;
-    return;
-  }
-
   if (!memoryOnly) {
     mCacheData.reset();
     nsresult rv = mFile->Remove(false);
     if (NS_FAILED(rv) && rv != NS_ERROR_FILE_TARGET_DOES_NOT_EXIST &&
         rv != NS_ERROR_FILE_NOT_FOUND) {
       gIgnoreDiskCache = true;
       return;
     }
   }
   gIgnoreDiskCache = false;
-  Unused << mCacheData.init(mFile);
   auto result = LoadArchive();
   if (NS_WARN_IF(result.isErr())) {
     gIgnoreDiskCache = true;
   }
 }
 
 void StartupCache::MaybeInitShutdownWrite() {
-  if (!XRE_IsParentProcess()) {
-    return;
+  if (mTimer) {
+    mTimer->Cancel();
   }
-  MutexAutoLock lock(mLock);
-  if (mWriteTimer) {
-    mWriteTimer->Cancel();
-  }
+  gShutdownInitiated = true;
 
   MaybeWriteOffMainThread();
 }
 
 void StartupCache::EnsureShutdownWriteComplete() {
-  if (!XRE_IsParentProcess()) {
+  // If we've already written or there's nothing to write,
+  // we don't need to do anything. This is the common case.
+  if (mWrittenOnce || (mCacheData.initialized() && !ShouldCompactCache())) {
     return;
   }
   // Otherwise, ensure the write happens. The timer should have been cancelled
   // already in MaybeInitShutdownWrite.
-  if (!mLock.TryLock()) {
+  if (!mTableLock.TryLock()) {
     // Uh oh, we're writing away from the main thread. Wait to gain the lock,
     // to ensure the write completes.
-    mLock.Lock();
+    mTableLock.Lock();
   } else {
     // We got the lock. Keep the following in sync with
     // MaybeWriteOffMainThread:
-
-    // If we've already written or there's nothing to write,
-    // we don't need to do anything. This is the common case.
-    if (mWrittenOnce || (mCacheData.initialized() && !ShouldCompactCache())) {
-      mLock.Unlock();
-      return;
-    }
-
     WaitOnPrefetchThread();
     mDirty = true;
+    mCacheData.reset();
     // Most of this should be redundant given MaybeWriteOffMainThread should
     // have run before now.
 
     auto writeResult = WriteToDisk();
     Unused << NS_WARN_IF(writeResult.isErr());
     // We've had the lock, and `WriteToDisk()` sets mWrittenOnce and mDirty
     // when done, and checks for them when starting, so we don't need to do
     // anything else.
   }
-  mLock.Unlock();
+  mTableLock.Unlock();
 }
 
 void StartupCache::IgnoreDiskCache() {
   gIgnoreDiskCache = true;
-  if (gStartupCache) {
-    gStartupCache->InvalidateCache();
-  }
+  if (gStartupCache) gStartupCache->InvalidateCache();
 }
 
 void StartupCache::WaitOnPrefetchThread() {
   if (!mPrefetchThread || mPrefetchThread == PR_GetCurrentThread()) return;
 
   PR_JoinThread(mPrefetchThread);
   mPrefetchThread = nullptr;
 }
 
 void StartupCache::ThreadedPrefetch(void* aClosure) {
   AUTO_PROFILER_REGISTER_THREAD("StartupCache");
   NS_SetCurrentThreadName("StartupCache");
   mozilla::IOInterposer::RegisterCurrentThread();
   StartupCache* startupCacheObj = static_cast<StartupCache*>(aClosure);
   uint8_t* buf = startupCacheObj->mCacheData.get<uint8_t>().get();
-  size_t size = startupCacheObj->mPrefetchSize;
+  size_t size = startupCacheObj->mCacheData.size();
   MMAP_FAULT_HANDLER_BEGIN_BUFFER(buf, size)
   PrefetchMemory(buf, size);
   MMAP_FAULT_HANDLER_CATCH()
   mozilla::IOInterposer::UnregisterCurrentThread();
 }
 
 bool StartupCache::ShouldCompactCache() {
-  mLock.AssertCurrentThreadOwns();
   // If we've requested less than 4/5 of the startup cache, then we should
   // probably compact it down. This can happen quite easily after the first run,
   // which seems to request quite a few more things than subsequent runs.
   CheckedInt<uint32_t> threshold = CheckedInt<uint32_t>(mTable.count()) * 4 / 5;
   MOZ_RELEASE_ASSERT(threshold.isValid(), "Runaway StartupCache size");
   return mRequestedCount < threshold.value();
 }
 
@@ -1358,51 +722,40 @@ void StartupCache::WriteTimeout(nsITimer
   /*
    * It is safe to use the pointer passed in aClosure to reference the
    * StartupCache object because the timer's lifetime is tightly coupled to
    * the lifetime of the StartupCache object; this timer is canceled in the
    * StartupCache destructor, guaranteeing that this function runs if and only
    * if the StartupCache object is valid.
    */
   StartupCache* startupCacheObj = static_cast<StartupCache*>(aClosure);
-  MutexAutoLock lock(startupCacheObj->mLock);
   startupCacheObj->MaybeWriteOffMainThread();
 }
 
-void StartupCache::SendEntriesTimeout(nsITimer* aTimer, void* aClosure) {
-  StartupCache* sc = static_cast<StartupCache*>(aClosure);
-  MutexAutoLock lock(sc->mLock);
-  ((StartupCacheChild*)sc->mChildActor)->SendEntriesAndFinalize(sc->mTable);
-}
-
 /*
  * See StartupCache::WriteTimeout above - this is just the non-static body.
  */
 void StartupCache::MaybeWriteOffMainThread() {
-  mLock.AssertCurrentThreadOwns();
-  if (!XRE_IsParentProcess()) {
-    return;
-  }
-
   if (mWrittenOnce) {
     return;
   }
 
   if (mCacheData.initialized() && !ShouldCompactCache()) {
     return;
   }
 
   // Keep this code in sync with EnsureShutdownWriteComplete.
   WaitOnPrefetchThread();
   mDirty = true;
+  mCacheData.reset();
 
   RefPtr<StartupCache> self = this;
   nsCOMPtr<nsIRunnable> runnable =
       NS_NewRunnableFunction("StartupCache::Write", [self]() mutable {
-        MutexAutoLock lock(self->mLock);
+        MutexAutoLock unlock(self->mTableLock);
         auto result = self->WriteToDisk();
         Unused << NS_WARN_IF(result.isErr());
       });
   NS_DispatchBackgroundTask(runnable.forget(), NS_DISPATCH_EVENT_MAY_BLOCK);
 }
 
 // We don't want to refcount StartupCache, so we'll just
 // hold a ref to this and pass it to observerService instead.
@@ -1411,37 +764,24 @@ NS_IMPL_ISUPPORTS(StartupCacheListener, 
 nsresult StartupCacheListener::Observe(nsISupports* subject, const char* topic,
                                        const char16_t* data) {
   StartupCache* sc = StartupCache::GetSingleton();
   if (!sc) return NS_OK;
 
   if (strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
     // Do not leave the thread running past xpcom shutdown
     sc->WaitOnPrefetchThread();
+    StartupCache::gShutdownInitiated = true;
     // Note that we don't do anything special for the background write
     // task; we expect the threadpool to finish running any tasks already
     // posted to it prior to shutdown. FastShutdown will call
     // EnsureShutdownWriteComplete() to ensure any pending writes happen
     // in that case.
   } else if (strcmp(topic, "startupcache-invalidate") == 0) {
-    MutexAutoLock lock(sc->mLock);
-    sc->InvalidateCacheImpl(data && nsCRT::strcmp(data, u"memoryOnly") == 0);
-  } else if (sc->mContentStartupFinishedTopic.Equals(topic) &&
-             sc->mChildActor) {
-    if (sProcessType == ProcessType::PrivilegedAbout) {
-      if (!sc->mSendEntriesTimer) {
-        sc->mSendEntriesTimer = NS_NewTimer();
-        sc->mSendEntriesTimer->InitWithNamedFuncCallback(
-            StartupCache::SendEntriesTimeout, sc, 10000,
-            nsITimer::TYPE_ONE_SHOT, "StartupCache::SendEntriesTimeout");
-      }
-    } else {
-      MutexAutoLock lock(sc->mLock);
-      ((StartupCacheChild*)sc->mChildActor)->SendEntriesAndFinalize(sc->mTable);
-    }
+    sc->InvalidateCache(data && nsCRT::strcmp(data, u"memoryOnly") == 0);
   }
   return NS_OK;
 }
 
 nsresult StartupCache::GetDebugObjectOutputStream(
     nsIObjectOutputStream* aStream, nsIObjectOutputStream** aOutStream) {
   NS_ENSURE_ARG_POINTER(aStream);
 #ifdef DEBUG
@@ -1450,59 +790,49 @@ nsresult StartupCache::GetDebugObjectOut
 #else
   NS_ADDREF(*aOutStream = aStream);
 #endif
 
   return NS_OK;
 }
 
 nsresult StartupCache::ResetStartupWriteTimerCheckingReadCount() {
-  mLock.AssertCurrentThreadOwns();
   nsresult rv = NS_OK;
-  if (!mWriteTimer) {
-    mWriteTimer = NS_NewTimer();
-  } else {
-    rv = mWriteTimer->Cancel();
-  }
+  if (!mTimer)
+    mTimer = NS_NewTimer();
+  else
+    rv = mTimer->Cancel();
   NS_ENSURE_SUCCESS(rv, rv);
   // Wait for the specified timeout, then write out the cache.
-  mWriteTimer->InitWithNamedFuncCallback(
+  mTimer->InitWithNamedFuncCallback(
       StartupCache::WriteTimeout, this, STARTUP_CACHE_WRITE_TIMEOUT * 1000,
       nsITimer::TYPE_ONE_SHOT, "StartupCache::WriteTimeout");
   return NS_OK;
 }
 
 nsresult StartupCache::ResetStartupWriteTimer() {
-  MutexAutoLock lock(mLock);
-  return ResetStartupWriteTimerImpl();
-}
-
-nsresult StartupCache::ResetStartupWriteTimerImpl() {
-  if (!XRE_IsParentProcess()) {
-    return NS_OK;
-  }
-
-  mLock.AssertCurrentThreadOwns();
   mDirty = true;
   nsresult rv = NS_OK;
-  if (!mWriteTimer) {
-    mWriteTimer = NS_NewTimer();
-  } else {
-    rv = mWriteTimer->Cancel();
-  }
+  if (!mTimer)
+    mTimer = NS_NewTimer();
+  else
+    rv = mTimer->Cancel();
   NS_ENSURE_SUCCESS(rv, rv);
   // Wait for the specified timeout, then write out the cache.
-  mWriteTimer->InitWithNamedFuncCallback(
+  mTimer->InitWithNamedFuncCallback(
       StartupCache::WriteTimeout, this, STARTUP_CACHE_WRITE_TIMEOUT * 1000,
       nsITimer::TYPE_ONE_SHOT, "StartupCache::WriteTimeout");
   return NS_OK;
 }
 
 // Used only in tests:
-bool StartupCache::StartupWriteComplete() { return !mDirty && mWrittenOnce; }
+bool StartupCache::StartupWriteComplete() {
+  // Need to have written to disk and not added new things since;
+  return !mDirty && mWrittenOnce;
+}
 
 // StartupCacheDebugOutputStream implementation
 #ifdef DEBUG
 NS_IMPL_ISUPPORTS(StartupCacheDebugOutputStream, nsIObjectOutputStream,
                   nsIBinaryOutputStream, nsIOutputStream)
 
 bool StartupCacheDebugOutputStream::CheckReferences(nsISupports* aObject) {
   nsresult rv;
--- a/startupcache/StartupCache.h
+++ b/startupcache/StartupCache.h
@@ -6,33 +6,31 @@
 #ifndef StartupCache_h_
 #define StartupCache_h_
 
 #include <utility>
 
 #include "nsClassHashtable.h"
 #include "nsComponentManagerUtils.h"
 #include "nsTArray.h"
+#include "nsTStringHasher.h"  // mozilla::DefaultHasher<nsCString>
 #include "nsZipArchive.h"
 #include "nsITimer.h"
 #include "nsIMemoryReporter.h"
 #include "nsIObserverService.h"
 #include "nsIObserver.h"
 #include "nsIObjectOutputStream.h"
 #include "nsIFile.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/AutoMemMap.h"
 #include "mozilla/Compression.h"
-#include "mozilla/EnumSet.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Mutex.h"
-#include "mozilla/Omnijar.h"
 #include "mozilla/Result.h"
 #include "mozilla/UniquePtr.h"
-#include "mozilla/UniquePtrExtensions.h"
 
 /**
  * The StartupCache is a persistent cache of simple key-value pairs,
  * where the keys are null-terminated c-strings and the values are
  * arbitrary data, passed as a (char*, size) tuple.
  *
  * Clients should use the GetSingleton() static method to access the cache. It
  * will be available from the end of XPCOM init (NS_InitXPCOM3 in
@@ -75,248 +73,90 @@
  * wrap the buffers into object streams, which may be useful for serializing
  * objects. Note the above caution about multiply-referenced objects, though --
  * the streams are just as 'dumb' as the underlying buffers about
  * multiply-referenced objects. They just provide some convenience in writing
  * out data.
  */
 
 namespace mozilla {
-namespace dom {
-class ContentParent;
-}
-namespace ipc {
-class GeckoChildProcessHost;
-}  // namespace ipc
 
 namespace scache {
 
-class StartupCacheChild;
-
-#ifdef XP_UNIX
-
-// Please see bug 1440207 about improving the problem of random fixed FDs,
-// which the addition of the below constant exacerbates.
-static const int kStartupCacheFd = 11;
-#endif
-
-// We use INT_MAX here just to simplify the sorting - we want to push
-// unrequested entries to the back, and have requested entries in the order
-// they came in.
-static const int kStartupCacheEntryNotRequested = INT_MAX;
-static const int kStartupcacheEntryNotInSharedData = -1;
-
-// Keys must be of length `kStartupCacheKeyLengthCap - 1` or shorter, which
-// will bring them to `kStartupCacheKeyLengthCap` or shorter with a null
-// terminator.
-static const int kStartupCacheKeyLengthCap = 1024;
-
-// StartupCache entries can be backed by a buffer which they allocate as
-// soon as they are requested, into which they decompress the contents out
-// of the memory mapped file, *or* they can be backed by a contiguous buffer
-// which we allocate up front and decompress into, in order to share it with
-// child processes. This class is a helper class to hold a buffer which the
-// entry itself may or may not own.
-//
-// Side note: it may be appropriate for StartupCache entries to never own
-// their underlying buffers. We explicitly work to ensure that anything the
-// StartupCache returns to a caller survives for the lifetime of the
-// application, so it may be preferable to have a set of large contiguous
-// buffers which we allocate on demand, and fill up with cache entry contents,
-// but at that point we're basically implementing our own hacky pseudo-malloc,
-// for relatively uncertain performance gains. For the time being, we just
-// keep the existing model unchanged.
-class MaybeOwnedCharPtr {
- private:
-  char* mPtr;
-  bool mOwned;
-
- public:
-  ~MaybeOwnedCharPtr() {
-    if (mOwned) {
-      delete[] mPtr;
-    }
-  }
-
-  // MaybeOwnedCharPtr(const MaybeOwnedCharPtr& other);
-  // MaybeOwnedCharPtr& operator=(const MaybeOwnedCharPtr& other);
-
-  MaybeOwnedCharPtr(MaybeOwnedCharPtr&& other)
-      : mPtr(std::exchange(other.mPtr, nullptr)),
-        mOwned(std::exchange(other.mOwned, false)) {}
-
-  MaybeOwnedCharPtr& operator=(MaybeOwnedCharPtr&& other) {
-    std::swap(mPtr, other.mPtr);
-    std::swap(mOwned, other.mOwned);
-    return *this;
-  }
-
-  MaybeOwnedCharPtr& operator=(decltype(nullptr)) {
-    if (mOwned) {
-      delete[] mPtr;
-    }
-    mPtr = nullptr;
-    mOwned = false;
-    return *this;
-  }
-
-  operator char*() const { return mPtr; }
-
-  explicit operator bool() const { return !!mPtr; }
-
-  char* get() const { return mPtr; }
-
-  bool IsOwned() const { return mOwned; }
-
-  explicit MaybeOwnedCharPtr(char* aBytes) : mPtr(aBytes), mOwned(false) {}
-
-  explicit MaybeOwnedCharPtr(UniquePtr<char[]>&& aBytes)
-      : mPtr(aBytes.release()), mOwned(true) {}
-
-  explicit MaybeOwnedCharPtr(size_t size)
-      : mPtr(new char[size]), mOwned(true) {}
-
-  size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
-    if (!mOwned) {
-      return 0;
-    }
-    return mallocSizeOf(mPtr);
-  }
-};
-
-struct StartupCacheKeyHasher {
-  using Key = MaybeOwnedCharPtr;
-  using Lookup = const char*;
-
-  static HashNumber hash(const Lookup& aLookup) { return HashString(aLookup); }
-
-  static bool match(const Key& aKey, const Lookup& aLookup) {
-    return strcmp(aKey.get(), aLookup) == 0;
-  }
-};
-
-enum class StartupCacheEntryFlags {
-  Shared,
-  RequestedByChild,
-  AddedThisSession,
-
-  // We want to track whether code outside the StartupCache has requested
-  // and gotten access to a pointer to this item's underlying buffer, and
-  // this flag is the mechanism for doing that.
-  DoNotFree,
-};
-
 struct StartupCacheEntry {
-  MaybeOwnedCharPtr mData;
+  UniquePtr<char[]> mData;
   uint32_t mOffset;
   uint32_t mCompressedSize;
   uint32_t mUncompressedSize;
-  int32_t mSharedDataOffset;
   int32_t mHeaderOffsetInFile;
   int32_t mRequestedOrder;
-  EnumSet<StartupCacheEntryFlags> mFlags;
+  bool mRequested;
 
   MOZ_IMPLICIT StartupCacheEntry(uint32_t aOffset, uint32_t aCompressedSize,
-                                 uint32_t aUncompressedSize,
-                                 EnumSet<StartupCacheEntryFlags> aFlags)
+                                 uint32_t aUncompressedSize)
       : mData(nullptr),
         mOffset(aOffset),
         mCompressedSize(aCompressedSize),
         mUncompressedSize(aUncompressedSize),
-        mSharedDataOffset(kStartupcacheEntryNotInSharedData),
         mHeaderOffsetInFile(0),
-        mRequestedOrder(kStartupCacheEntryNotRequested),
-        mFlags(aFlags) {}
+        mRequestedOrder(0),
+        mRequested(false) {}
 
   StartupCacheEntry(UniquePtr<char[]> aData, size_t aLength,
-                    int32_t aRequestedOrder,
-                    EnumSet<StartupCacheEntryFlags> aFlags)
+                    int32_t aRequestedOrder)
       : mData(std::move(aData)),
         mOffset(0),
         mCompressedSize(0),
         mUncompressedSize(aLength),
-        mSharedDataOffset(kStartupcacheEntryNotInSharedData),
         mHeaderOffsetInFile(0),
-        mRequestedOrder(aRequestedOrder),
-        mFlags(aFlags) {}
+        mRequestedOrder(0),
+        mRequested(true) {}
 
   struct Comparator {
-    using Value = std::pair<const MaybeOwnedCharPtr*, StartupCacheEntry*>;
+    using Value = std::pair<const nsCString*, StartupCacheEntry*>;
 
     bool Equals(const Value& a, const Value& b) const {
-      // This is a bit ugly. Here and below, just note that we want entries
-      // with the RequestedByChild flag to be sorted before any other entries,
-      // because we're going to want to decompress them and send them down to
-      // child processes pretty early during startup.
-      return a.second->mFlags.contains(
-                 StartupCacheEntryFlags::RequestedByChild) ==
-                 b.second->mFlags.contains(
-                     StartupCacheEntryFlags::RequestedByChild) &&
-             a.second->mRequestedOrder == b.second->mRequestedOrder;
+      return a.second->mRequestedOrder == b.second->mRequestedOrder;
     }
 
     bool LessThan(const Value& a, const Value& b) const {
-      bool requestedByChildA =
-          a.second->mFlags.contains(StartupCacheEntryFlags::RequestedByChild);
-      bool requestedByChildB =
-          b.second->mFlags.contains(StartupCacheEntryFlags::RequestedByChild);
-      if (requestedByChildA == requestedByChildB) {
-        return a.second->mRequestedOrder < b.second->mRequestedOrder;
-      } else {
-        return requestedByChildA;
-      }
+      return a.second->mRequestedOrder < b.second->mRequestedOrder;
     }
   };
 };
 
 // We don't want to refcount StartupCache, and ObserverService wants to
 // refcount its listeners, so we'll let it refcount this instead.
 class StartupCacheListener final : public nsIObserver {
   ~StartupCacheListener() = default;
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIOBSERVER
 };
 
-// This mirrors a bit of logic in the script preloader. Basically, there's
-// certainly some overhead in child processes sending us lists of requested
-// startup cache items, so we want to limit that. Accordingly, we only
-// request to be notified of requested cache items for the first occurrence
-// of each process type, enumerated below.
-enum class ProcessType : uint8_t {
-  Uninitialized,
-  Parent,
-  Web,
-  Extension,
-  PrivilegedAbout,
-};
-
 class StartupCache : public nsIMemoryReporter {
   friend class StartupCacheListener;
-  friend class StartupCacheChild;
 
  public:
-  using Table =
-      HashMap<MaybeOwnedCharPtr, StartupCacheEntry, StartupCacheKeyHasher>;
-
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIMEMORYREPORTER
 
   // StartupCache methods. See above comments for a more detailed description.
 
   // true if the archive has an entry for the buffer or not.
   bool HasEntry(const char* id);
 
   // Returns a buffer that was previously stored, caller does not take ownership
   nsresult GetBuffer(const char* id, const char** outbuf, uint32_t* length);
 
   // Stores a buffer. Caller yields ownership.
-  nsresult PutBuffer(const char* id, UniquePtr<char[]>&& inbuf, uint32_t length,
-                     bool isFromChildProcess = false);
+  nsresult PutBuffer(const char* id, UniquePtr<char[]>&& inbuf,
+                     uint32_t length);
 
-  void InvalidateCache();
+  // Removes the cache file.
+  void InvalidateCache(bool memoryOnly = false);
 
   // For use during shutdown - this will write the startupcache's data
   // to disk if the timer hasn't already gone off.
   void MaybeInitShutdownWrite();
 
   // For use during shutdown - ensure we complete the shutdown write
   // before shutdown, even in the FastShutdown case.
   void EnsureShutdownWriteComplete();
@@ -324,139 +164,79 @@ class StartupCache : public nsIMemoryRep
   // Signal that data should not be loaded from the cache file
   static void IgnoreDiskCache();
 
   // In DEBUG builds, returns a stream that will attempt to check for
   // and disallow multiple writes of the same object.
   nsresult GetDebugObjectOutputStream(nsIObjectOutputStream* aStream,
                                       nsIObjectOutputStream** outStream);
 
-  static ProcessType GetChildProcessType(const nsACString& remoteType);
+  static StartupCache* GetSingletonNoInit();
   static StartupCache* GetSingleton();
-
-  // This will get the StartupCache up and running to get cached entries, but
-  // it won't init some of the deferred things which require later services
-  // to be up and running.
-  static nsresult PartialInitSingleton(nsIFile* aProfileLocalDir);
-
-  // If the startup cache singleton exists (initialized via
-  // PartialInitSingleton), this will ensure that all of the ancillary
-  // requirements of the startup cache are met.
-  static nsresult FullyInitSingleton();
-
-  static nsresult InitChildSingleton(char* aScacheHandleStr,
-                                     char* aScacheSizeStr);
-
   static void DeleteSingleton();
-  static void InitContentChild(dom::ContentParent& parent);
-
-  void AddStartupCacheCmdLineArgs(ipc::GeckoChildProcessHost& procHost,
-                                  const nsACString& aRemoteType,
-                                  std::vector<std::string>& aExtraOpts);
-  nsresult ParseStartupCacheCmdLineArgs(char* aScacheHandleStr,
-                                        char* aScacheSizeStr);
 
   // This measures all the heap memory used by the StartupCache, i.e. it
   // excludes the mapping.
   size_t HeapSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
 
   bool ShouldCompactCache();
+  nsresult ResetStartupWriteTimerCheckingReadCount();
   nsresult ResetStartupWriteTimer();
   bool StartupWriteComplete();
 
  private:
   StartupCache();
   virtual ~StartupCache();
 
   friend class StartupCacheInfo;
 
   Result<Ok, nsresult> LoadArchive();
-  nsresult PartialInit(nsIFile* aProfileLocalDir);
-  nsresult FullyInit();
-  nsresult InitChild(StartupCacheChild* cacheChild);
-
-  // Removes the cache file.
-  void InvalidateCacheImpl(bool memoryOnly = false);
-
-  nsresult ResetStartupWriteTimerCheckingReadCount();
-  nsresult ResetStartupWriteTimerImpl();
+  nsresult Init();
 
   // Returns a file pointer for the cache file with the given name in the
   // current profile.
   Result<nsCOMPtr<nsIFile>, nsresult> GetCacheFile(const nsAString& suffix);
 
   // Opens the cache file for reading.
   Result<Ok, nsresult> OpenCache();
 
   // Writes the cache to disk
   Result<Ok, nsresult> WriteToDisk();
 
-  Result<Ok, nsresult> DecompressEntry(StartupCacheEntry& aEntry,
-                                       MaybeOwnedCharPtr& aBuffer);
-
-  Result<Ok, nsresult> LoadEntriesOffDisk();
-
-  Result<Ok, nsresult> LoadEntriesFromSharedMemory();
-
   void WaitOnPrefetchThread();
   void StartPrefetchMemoryThread();
 
+  static nsresult InitSingleton();
   static void WriteTimeout(nsITimer* aTimer, void* aClosure);
-  static void SendEntriesTimeout(nsITimer* aTimer, void* aClosure);
   void MaybeWriteOffMainThread();
   static void ThreadedPrefetch(void* aClosure);
 
-  EnumSet<ProcessType> mInitializedProcesses{};
-  nsCString mContentStartupFinishedTopic;
-
-  Table mTable;
+  HashMap<nsCString, StartupCacheEntry> mTable;
   // owns references to the contents of tables which have been invalidated.
   // In theory grows forever if the cache is continually filled and then
   // invalidated, but this should not happen in practice.
   nsTArray<decltype(mTable)> mOldTables;
   nsCOMPtr<nsIFile> mFile;
   loader::AutoMemMap mCacheData;
-  loader::AutoMemMap mSharedData;
-  UniqueFileHandle mSharedDataHandle;
-
-  // This lock must protect a few members of the StartupCache. Essentially,
-  // we want to protect everything accessed by GetBuffer and PutBuffer. This
-  // includes:
-  // - mTable
-  // - mCacheData
-  // - mDecompressionContext
-  // - mCurTableReferenced
-  // - mOldTables
-  // - mWrittenOnce
-  // - gIgnoreDiskCache
-  // - mFile
-  // - mWriteTimer
-  // - mStartupWriteInitiated
-  mutable Mutex mLock;
+  Mutex mTableLock;
 
   nsCOMPtr<nsIObserverService> mObserverService;
   RefPtr<StartupCacheListener> mListener;
-  nsCOMPtr<nsITimer> mWriteTimer;
-  nsCOMPtr<nsITimer> mSendEntriesTimer;
+  nsCOMPtr<nsITimer> mTimer;
 
   Atomic<bool> mDirty;
   Atomic<bool> mWrittenOnce;
   bool mCurTableReferenced;
-  bool mLoaded;
-  bool mFullyInitialized;
   uint32_t mRequestedCount;
-  uint32_t mPrefetchSize;
-  uint32_t mSharedDataSize;
   size_t mCacheEntriesBaseOffset;
 
   static StaticRefPtr<StartupCache> gStartupCache;
+  static bool gShutdownInitiated;
   static bool gIgnoreDiskCache;
   static bool gFoundDiskCacheOnInit;
-
-  Atomic<StartupCacheChild*> mChildActor;
   PRThread* mPrefetchThread;
   UniquePtr<Compression::LZ4FrameDecompressionContext> mDecompressionContext;
 #ifdef DEBUG
   nsTHashtable<nsISupportsHashKey> mWriteObjectMap;
 #endif
 };
 
 // This debug outputstream attempts to detect if clients are writing multiple
deleted file mode 100644
--- a/startupcache/StartupCacheChild.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/scache/StartupCacheChild.h"
-
-#include "mozilla/scache/StartupCache.h"
-#include "mozilla/dom/ContentParent.h"
-
-namespace mozilla {
-namespace scache {
-
-void StartupCacheChild::Init() {
-  auto* cache = StartupCache::GetSingleton();
-  if (cache) {
-    Unused << cache->InitChild(this);
-  } else {
-    Send__delete__(this, AutoTArray<EntryData, 0>());
-  }
-}
-
-void StartupCacheChild::SendEntriesAndFinalize(StartupCache::Table& entries) {
-  nsTArray<EntryData> dataArray;
-  for (auto iter = entries.iter(); !iter.done(); iter.next()) {
-    const auto& key = iter.get().key();
-    auto& value = iter.get().value();
-
-    if (!value.mData ||
-        value.mRequestedOrder == kStartupCacheEntryNotRequested) {
-      continue;
-    }
-
-    auto data = dataArray.AppendElement();
-
-    MOZ_ASSERT(strnlen(key.get(), kStartupCacheKeyLengthCap) <
-                   kStartupCacheKeyLengthCap,
-               "StartupCache key over the size limit.");
-    data->key() = nsCString(key.get());
-    if (value.mFlags.contains(StartupCacheEntryFlags::AddedThisSession)) {
-      data->data().AppendElements(
-          reinterpret_cast<const uint8_t*>(value.mData.get()),
-          value.mUncompressedSize);
-    }
-  }
-
-  Send__delete__(this, dataArray);
-
-  for (auto iter = entries.iter(); !iter.done(); iter.next()) {
-    auto& value = iter.get().value();
-    if (!value.mFlags.contains(StartupCacheEntryFlags::DoNotFree)) {
-      value.mData = nullptr;
-    }
-  }
-}
-
-void StartupCacheChild::ActorDestroy(ActorDestroyReason aWhy) {
-  auto* cache = StartupCache::GetSingleton();
-  if (cache) {
-    cache->mChildActor = nullptr;
-  }
-}
-
-}  // namespace scache
-}  // namespace mozilla
\ No newline at end of file
deleted file mode 100644
--- a/startupcache/StartupCacheChild.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef StartupCacheChild_h
-#define StartupCacheChild_h
-
-#include "mozilla/scache/StartupCache.h"
-#include "mozilla/scache/PStartupCacheChild.h"
-#include "mozilla/scache/PStartupCacheParent.h"
-
-namespace mozilla {
-namespace ipc {
-class FileDescriptor;
-}
-
-namespace scache {
-
-using mozilla::ipc::FileDescriptor;
-
-class StartupCacheChild final : public PStartupCacheChild {
-  friend class mozilla::scache::StartupCache;
-  friend class mozilla::scache::StartupCacheListener;
-
- public:
-  StartupCacheChild() = default;
-
-  void Init();
-
- protected:
-  virtual void ActorDestroy(ActorDestroyReason aWhy) override;
-
-  void SendEntriesAndFinalize(StartupCache::Table& entries);
-};
-
-}  // namespace scache
-}  // namespace mozilla
-
-#endif  // StartupCacheChild_h
deleted file mode 100644
--- a/startupcache/StartupCacheParent.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/scache/StartupCacheParent.h"
-
-#include "mozilla/scache/StartupCache.h"
-#include "mozilla/dom/ContentParent.h"
-
-namespace mozilla {
-namespace scache {
-
-IPCResult StartupCacheParent::Recv__delete__(nsTArray<EntryData>&& entries) {
-  if (entries.Length()) {
-    auto* cache = StartupCache::GetSingleton();
-    for (auto& entry : entries) {
-      auto buffer = MakeUnique<char[]>(entry.data().Length());
-      memcpy(buffer.get(), entry.data().Elements(), entry.data().Length());
-      cache->PutBuffer(entry.key().get(), std::move(buffer),
-                       entry.data().Length(), /* isFromChildProcess:*/ true);
-    }
-  }
-
-  return IPC_OK();
-}
-
-void StartupCacheParent::ActorDestroy(ActorDestroyReason aWhy) {}
-
-}  // namespace scache
-}  // namespace mozilla
\ No newline at end of file
deleted file mode 100644
--- a/startupcache/StartupCacheParent.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef StartupCacheParent_h
-#define StartupCacheParent_h
-
-#include "mozilla/scache/StartupCache.h"
-#include "mozilla/scache/PStartupCacheParent.h"
-
-namespace mozilla {
-
-namespace scache {
-
-using mozilla::ipc::IPCResult;
-
-class StartupCacheParent final : public PStartupCacheParent {
-  friend class PStartupCacheParent;
-
- protected:
-  IPCResult Recv__delete__(nsTArray<EntryData>&& entries);
-
-  virtual void ActorDestroy(ActorDestroyReason aWhy) override;
-};
-
-}  // namespace scache
-}  // namespace mozilla
-
-#endif  // StartupCacheParent_h
--- a/startupcache/moz.build
+++ b/startupcache/moz.build
@@ -7,38 +7,28 @@
 with Files("**"):
     BUG_COMPONENT = ("Core", "XPCOM")
 
 TEST_DIRS += ['test']
 BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']
 
 EXPORTS.mozilla.scache += [
     'StartupCache.h',
-    'StartupCacheChild.h',
-    'StartupCacheParent.h',
     'StartupCacheUtils.h',
 ]
 
 UNIFIED_SOURCES += [
     'StartupCache.cpp',
-    'StartupCacheChild.cpp',
     'StartupCacheInfo.cpp',
-    'StartupCacheParent.cpp',
     'StartupCacheUtils.cpp',
 ]
 
 XPCOM_MANIFESTS += [
     'components.conf',
 ]
 
 XPIDL_MODULE = 'startupcache'
 
 XPIDL_SOURCES += [
     'nsIStartupCacheInfo.idl',
 ]
 
-IPDL_SOURCES += [
-    'PStartupCache.ipdl',
-]
-
-include('/ipc/chromium/chromium-config.mozbuild')
-
 FINAL_LIBRARY = 'xul'
--- a/startupcache/test/TestStartupCache.cpp
+++ b/startupcache/test/TestStartupCache.cpp
@@ -61,21 +61,16 @@ TestStartupCache::TestStartupCache() {
 #else
   nsAutoCString path;
   mSCFile->GetNativePath(path);
   char* env = mozilla::Smprintf("MOZ_STARTUP_CACHE=%s", path.get()).release();
   PR_SetEnv(env);
   // We intentionally leak `env` here because it is required by PR_SetEnv
   MOZ_LSAN_INTENTIONALLY_LEAK_OBJECT(env);
 #endif
-
-  if (!StartupCache::GetSingleton()) {
-    StartupCache::PartialInitSingleton(nullptr);
-    StartupCache::FullyInitSingleton();
-  }
   StartupCache::GetSingleton()->InvalidateCache();
 }
 TestStartupCache::~TestStartupCache() {
   PR_SetEnv("MOZ_STARTUP_CACHE=");
   StartupCache::GetSingleton()->InvalidateCache();
 }
 
 TEST_F(TestStartupCache, StartupWriteRead) {
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -4278,20 +4278,17 @@ int XREMain::XRE_mainStartup(bool* aExit
 
     // Rewrite compatibility.ini to match the current build. The next run
     // should attempt to invalidate the caches if either this run is safe mode
     // or the attempt to invalidate the caches this time failed.
     WriteVersion(mProfD, version, osABI, mDirProvider.GetGREDir(),
                  mAppData->directory, gSafeMode || !startupCacheValid);
   }
 
-  if (!startupCacheValid) {
-    StartupCache::IgnoreDiskCache();
-  }
-  StartupCache::PartialInitSingleton(mProfLD);
+  if (!startupCacheValid) StartupCache::IgnoreDiskCache();
 
   if (flagFile) {
     flagFile->Remove(true);
   }
 
   return 0;
 }
 
--- a/xpcom/base/AppShutdown.cpp
+++ b/xpcom/base/AppShutdown.cpp
@@ -137,27 +137,27 @@ void AppShutdown::Init(AppShutdownMode a
   int32_t fastShutdownPref = StaticPrefs::toolkit_shutdown_fastShutdownStage();
   sFastShutdownPhase = GetShutdownPhaseFromPrefValue(fastShutdownPref);
   int32_t lateWriteChecksPref =
       StaticPrefs::toolkit_shutdown_lateWriteChecksStage();
   sLateWriteChecksPhase = GetShutdownPhaseFromPrefValue(lateWriteChecksPref);
 
   // Very early shutdowns can happen before the startup cache is even
   // initialized; don't bother initializing it during shutdown.
-  if (auto* cache = scache::StartupCache::GetSingleton()) {
+  if (auto* cache = scache::StartupCache::GetSingletonNoInit()) {
     cache->MaybeInitShutdownWrite();
   }
 }
 
 void AppShutdown::MaybeFastShutdown(ShutdownPhase aPhase) {
   // For writes which we want to ensure are recorded, we don't want to trip
   // the late write checking code. Anything that writes to disk and which
   // we don't want to skip should be listed out explicitly in this section.
   if (aPhase == sFastShutdownPhase || aPhase == sLateWriteChecksPhase) {
-    if (auto* cache = scache::StartupCache::GetSingleton()) {
+    if (auto* cache = scache::StartupCache::GetSingletonNoInit()) {
       cache->EnsureShutdownWriteComplete();
     }
 
     nsresult rv;
 #ifdef MOZ_NEW_XULSTORE
     rv = XULStore::Shutdown();
     NS_ASSERTION(NS_SUCCEEDED(rv), "XULStore::Shutdown() failed.");
 #endif
--- a/xpcom/build/FileLocation.cpp
+++ b/xpcom/build/FileLocation.cpp
@@ -2,32 +2,31 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "FileLocation.h"
 #include "nsZipArchive.h"
 #include "nsURLHelper.h"
-#include "mozilla/Omnijar.h"
 
 namespace mozilla {
 
 FileLocation::FileLocation() = default;
 
 FileLocation::~FileLocation() = default;
 
 FileLocation::FileLocation(nsIFile* aFile) { Init(aFile); }
 
-FileLocation::FileLocation(CacheAwareZipReader* aZip, const char* aPath) {
-  Init(aZip, aPath);
+FileLocation::FileLocation(nsIFile* aFile, const char* aPath) {
+  Init(aFile, aPath);
 }
 
 FileLocation::FileLocation(nsZipArchive* aZip, const char* aPath) {
-  Init(new CacheAwareZipReader(aZip, nullptr), aPath);
+  Init(aZip, aPath);
 }
 
 FileLocation::FileLocation(const FileLocation& aOther)
 
     = default;
 
 FileLocation::FileLocation(FileLocation&& aOther)
     : mBaseFile(std::move(aOther.mBaseFile)),
@@ -84,75 +83,80 @@ void FileLocation::Init(nsIFile* aFile) 
 }
 
 void FileLocation::Init(nsIFile* aFile, const char* aPath) {
   mBaseZip = nullptr;
   mBaseFile = aFile;
   mPath = aPath;
 }
 
-void FileLocation::Init(CacheAwareZipReader* aZip, const char* aPath) {
+void FileLocation::Init(nsZipArchive* aZip, const char* aPath) {
   mBaseZip = aZip;
   mBaseFile = nullptr;
   mPath = aPath;
 }
 
-void FileLocation::Init(nsZipArchive* aZip, const char* aPath) {
-  mBaseZip = new CacheAwareZipReader(aZip, nullptr);
-  mBaseFile = nullptr;
-  mPath = aPath;
-}
-
 void FileLocation::GetURIString(nsACString& aResult) const {
   if (mBaseFile) {
     net_GetURLSpecFromActualFile(mBaseFile, aResult);
   } else if (mBaseZip) {
-    mBaseZip->GetURIString(aResult);
+    RefPtr<nsZipHandle> handler = mBaseZip->GetFD();
+    handler->mFile.GetURIString(aResult);
   }
   if (IsZip()) {
     aResult.InsertLiteral("jar:", 0);
     aResult += "!/";
     aResult += mPath;
   }
 }
 
 already_AddRefed<nsIFile> FileLocation::GetBaseFile() {
   if (IsZip() && mBaseZip) {
-    return mBaseZip->GetBaseFile();
+    RefPtr<nsZipHandle> handler = mBaseZip->GetFD();
+    if (handler) {
+      return handler->mFile.GetBaseFile();
+    }
+    return nullptr;
   }
 
   nsCOMPtr<nsIFile> file = mBaseFile;
   return file.forget();
 }
 
 bool FileLocation::Equals(const FileLocation& aFile) const {
   if (mPath != aFile.mPath) {
     return false;
   }
 
-  nsCOMPtr<nsIFile> a = mBaseFile;
-  nsCOMPtr<nsIFile> b = aFile.mBaseFile;
-  if (!mBaseFile && mBaseZip) {
-    a = mBaseZip->GetBaseFile();
-  }
-  if (!aFile.mBaseFile && aFile.mBaseZip) {
-    b = mBaseZip->GetBaseFile();
+  if (mBaseFile && aFile.mBaseFile) {
+    bool eq;
+    return NS_SUCCEEDED(mBaseFile->Equals(aFile.mBaseFile, &eq)) && eq;
   }
 
-  bool eq;
-  return NS_SUCCEEDED(a->Equals(b, &eq)) && eq;
+  const FileLocation* a = this;
+  const FileLocation* b = &aFile;
+  if (a->mBaseZip) {
+    RefPtr<nsZipHandle> handler = a->mBaseZip->GetFD();
+    a = &handler->mFile;
+  }
+  if (b->mBaseZip) {
+    RefPtr<nsZipHandle> handler = b->mBaseZip->GetFD();
+    b = &handler->mFile;
+  }
+
+  return a->Equals(*b);
 }
 
 nsresult FileLocation::GetData(Data& aData) {
   if (!IsZip()) {
     return mBaseFile->OpenNSPRFileDesc(PR_RDONLY, 0444, &aData.mFd.rwget());
   }
   aData.mZip = mBaseZip;
   if (!aData.mZip) {
-    aData.mZip = new CacheAwareZipReader();
+    aData.mZip = new nsZipArchive();
     aData.mZip->OpenArchive(mBaseFile);
   }
   aData.mItem = aData.mZip->GetItem(mPath.get());
   if (aData.mItem) {
     return NS_OK;
   }
   return NS_ERROR_FILE_UNRECOGNIZED_PATH;
 }
@@ -186,18 +190,18 @@ nsresult FileLocation::Data::Copy(char* 
       if (read < 0) {
         return NS_ErrorAccordingToNSPR();
       }
       totalRead += read;
     }
     return NS_OK;
   }
   if (mItem) {
-    CacheAwareZipCursor cursor(mItem, mZip, reinterpret_cast<uint8_t*>(aBuf),
-                               aLen, true);
+    nsZipCursor cursor(mItem, mZip, reinterpret_cast<uint8_t*>(aBuf), aLen,
+                       true);
     uint32_t readLen;
     cursor.Copy(&readLen);
     if (readLen != aLen) {
       return NS_ERROR_FILE_CORRUPTED;
     }
     return NS_OK;
   }
   return NS_ERROR_NOT_INITIALIZED;
--- a/xpcom/build/FileLocation.h
+++ b/xpcom/build/FileLocation.h
@@ -12,29 +12,27 @@
 #include "nsIFile.h"
 #include "FileUtils.h"
 
 class nsZipArchive;
 class nsZipItem;
 
 namespace mozilla {
 
-class CacheAwareZipReader;
-
 class FileLocation {
  public:
   /**
    * FileLocation is an helper to handle different kind of file locations
    * within Gecko:
    * - on filesystems
    * - in archives
    * - in archives within archives
    * As such, it stores a path within an archive, as well as the archive
    * path itself, or the complete file path alone when on a filesystem.
-   * When the archive is in an archive, an CacheAwareZipReader is stored instead
+   * When the archive is in an archive, an nsZipArchive is stored instead
    * of a file path.
    */
   FileLocation();
   ~FileLocation();
 
   FileLocation(const FileLocation& aOther);
   FileLocation(FileLocation&& aOther);
 
@@ -42,57 +40,50 @@ class FileLocation {
 
   /**
    * Constructor for plain files
    */
   explicit FileLocation(nsIFile* aFile);
 
   /**
    * Constructors for path within an archive. The archive can be given either
-   * as nsIFile or CacheAwareZipReader.
+   * as nsIFile or nsZipArchive.
    */
-  FileLocation(nsIFile* aFile, const char* aPath);
-
-  /**
-   * Constructors for path within a zip archive.
-   */
-  FileLocation(CacheAwareZipReader* aZip, const char* aPath);
+  FileLocation(nsIFile* aZip, const char* aPath);
 
   FileLocation(nsZipArchive* aZip, const char* aPath);
 
   /**
    * Creates a new file location relative to another one.
    */
   FileLocation(const FileLocation& aFile, const char* aPath);
 
   /**
    * Initialization functions corresponding to constructors
    */
   void Init(nsIFile* aFile);
 
-  void Init(nsIFile* aFile, const char* aPath);
+  void Init(nsIFile* aZip, const char* aPath);
 
   void Init(nsZipArchive* aZip, const char* aPath);
 
-  void Init(CacheAwareZipReader* aZip, const char* aPath);
-
   /**
    * Returns an URI string corresponding to the file location
    */
   void GetURIString(nsACString& aResult) const;
 
   /**
    * Returns the base file of the location, where base file is defined as:
    * - The file itself when the location is on a filesystem
    * - The archive file when the location is in an archive
    * - The outer archive file when the location is in an archive in an archive
    */
   already_AddRefed<nsIFile> GetBaseFile();
 
-  CacheAwareZipReader* GetBaseZip() { return mBaseZip; }
+  nsZipArchive* GetBaseZip() { return mBaseZip; }
 
   /**
    * Returns whether the "base file" (see GetBaseFile) is an archive
    */
   bool IsZip() const { return !mPath.IsEmpty(); }
 
   /**
    * Returns the path within the archive, when within an archive
@@ -123,27 +114,27 @@ class FileLocation {
     /**
      * Copies the data in the given buffer
      */
     nsresult Copy(char* aBuf, uint32_t aLen);
 
    protected:
     friend class FileLocation;
     nsZipItem* mItem;
-    RefPtr<CacheAwareZipReader> mZip;
+    RefPtr<nsZipArchive> mZip;
     mozilla::AutoFDClose mFd;
   };
 
   /**
    * Returns the data associated with the resource pointed at by the file
    * location.
    */
   nsresult GetData(Data& aData);
 
  private:
   nsCOMPtr<nsIFile> mBaseFile;
-  RefPtr<CacheAwareZipReader> mBaseZip;
+  RefPtr<nsZipArchive> mBaseZip;
   nsCString mPath;
 }; /* class FileLocation */
 
 } /* namespace mozilla */
 
 #endif /* mozilla_FileLocation_h */
--- a/xpcom/build/Omnijar.cpp
+++ b/xpcom/build/Omnijar.cpp
@@ -1,45 +1,31 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- */
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "Omnijar.h"
 
 #include "nsDirectoryService.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsIFile.h"
 #include "nsZipArchive.h"
 #include "nsNetUtil.h"
-#include "mozilla/scache/StartupCache.h"
-#include "mozilla/MmapFaultHandler.h"
-#include "mozilla/UniquePtrExtensions.h"
 
 namespace mozilla {
 
 StaticRefPtr<nsIFile> Omnijar::sPath[2];
-StaticRefPtr<CacheAwareZipReader> Omnijar::sReader[2];
-StaticRefPtr<CacheAwareZipReader> Omnijar::sOuterReader[2];
+StaticRefPtr<nsZipArchive> Omnijar::sReader[2];
+StaticRefPtr<nsZipArchive> Omnijar::sOuterReader[2];
 bool Omnijar::sInitialized = false;
 bool Omnijar::sIsUnified = false;
 
-static MOZ_THREAD_LOCAL(int) tlsSuspendStartupCacheWrites;
-
-bool SuspendingStartupCacheWritesForCurrentThread() {
-  if (!tlsSuspendStartupCacheWrites.init()) {
-    return true;
-  }
-  return tlsSuspendStartupCacheWrites.get() > 0;
-}
-
 static const char* sProp[2] = {NS_GRE_DIR, NS_XPCOM_CURRENT_PROCESS_DIR};
-static const char* sCachePrefixes[2] = {"GreOmnijar:", "AppOmnijar:"};
 
 #define SPROP(Type) ((Type == mozilla::Omnijar::GRE) ? sProp[GRE] : sProp[APP])
 
 void Omnijar::CleanUpOne(Type aType) {
   if (sReader[aType]) {
     sReader[aType]->CloseArchive();
     sReader[aType] = nullptr;
   }
@@ -103,35 +89,34 @@ void Omnijar::InitOne(nsIFile* aPath, Ty
     outerReader = zipReader;
     zipReader = new nsZipArchive();
     if (NS_FAILED(zipReader->OpenArchive(handle))) {
       return;
     }
   }
 
   CleanUpOne(aType);
-  sReader[aType] = new CacheAwareZipReader(zipReader, sCachePrefixes[aType]);
-  sOuterReader[aType] =
-      outerReader ? new CacheAwareZipReader(outerReader, nullptr) : nullptr;
+  sReader[aType] = zipReader;
+  sOuterReader[aType] = outerReader;
   sPath[aType] = file;
 }
 
 void Omnijar::Init(nsIFile* aGrePath, nsIFile* aAppPath) {
   InitOne(aGrePath, GRE);
   InitOne(aAppPath, APP);
   sInitialized = true;
 }
 
 void Omnijar::CleanUp() {
   CleanUpOne(GRE);
   CleanUpOne(APP);
   sInitialized = false;
 }
 
-already_AddRefed<CacheAwareZipReader> Omnijar::GetReader(nsIFile* aPath) {
+already_AddRefed<nsZipArchive> Omnijar::GetReader(nsIFile* aPath) {
   MOZ_ASSERT(IsInitialized(), "Omnijar not initialized");
 
   bool equals;
   nsresult rv;
 
   if (sPath[GRE]) {
     rv = sPath[GRE]->Equals(aPath, &equals);
     if (NS_SUCCEEDED(rv) && equals) {
@@ -142,17 +127,17 @@ already_AddRefed<CacheAwareZipReader> Om
     rv = sPath[APP]->Equals(aPath, &equals);
     if (NS_SUCCEEDED(rv) && equals) {
       return IsNested(APP) ? GetOuterReader(APP) : GetReader(APP);
     }
   }
   return nullptr;
 }
 
-already_AddRefed<CacheAwareZipReader> Omnijar::GetInnerReader(
+already_AddRefed<nsZipArchive> Omnijar::GetInnerReader(
     nsIFile* aPath, const nsACString& aEntry) {
   MOZ_ASSERT(IsInitialized(), "Omnijar not initialized");
 
   if (!aEntry.EqualsLiteral(MOZ_STRINGIFY(OMNIJAR_NAME))) {
     return nullptr;
   }
 
   bool equals;
@@ -207,247 +192,9 @@ nsresult Omnijar::GetURIString(Type aTyp
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
   aResult += "/";
   return NS_OK;
 }
 
-CacheAwareZipReader::CacheAwareZipReader(nsZipArchive* aZip,
-                                         const char* aCacheKeyPrefix)
-    : mZip(aZip), mCacheKeyPrefix(aCacheKeyPrefix) {}
-
-nsresult CacheAwareZipReader::FindInit(const char* aPattern,
-                                       nsZipFind** aFind) {
-  return mZip->FindInit(aPattern, aFind);
-}
-
-const uint8_t* CacheAwareZipReader::GetData(
-    nsZipItem* aItem, CacheAwareZipReader::Caching aCaching) {
-  nsAutoCString cacheKey;
-  uint32_t size;
-  const uint8_t* cached =
-      GetCachedBuffer(aItem->Name(), aItem->nameLength, &size, cacheKey);
-  if (cached) {
-    MOZ_ASSERT(size == aItem->RealSize());
-    return cached;
-  }
-
-  const uint8_t* zipItemData = mZip->GetData(aItem);
-  if (!zipItemData) {
-    return nullptr;
-  }
-
-  // If the data is compressed, it is somewhat silly to store it in the startup
-  // cache, as the startup cache will try to double compress it.
-  if (aCaching == Default && aItem->Compression() == STORED &&
-      !cacheKey.IsEmpty()) {
-    MOZ_ASSERT(aItem->RealSize() == aItem->Size());
-    PutBufferIntoCache(cacheKey, zipItemData, aItem->Size());
-  }
-
-  return zipItemData;
-}
-
-const uint8_t* CacheAwareZipReader::GetData(
-    const char* aEntryName, uint32_t* aResultSize,
-    CacheAwareZipReader::Caching aCaching) {
-  nsAutoCString cacheKey;
-  const uint8_t* cached =
-      GetCachedBuffer(aEntryName, strlen(aEntryName), aResultSize, cacheKey);
-  if (cached) {
-    return cached;
-  }
-
-  nsZipItem* zipItem = mZip->GetItem(aEntryName);
-  if (!zipItem) {
-    *aResultSize = 0;
-    return nullptr;
-  }
-  const uint8_t* zipItemData = mZip->GetData(zipItem);
-  if (!zipItemData) {
-    return nullptr;
-  }
-
-  *aResultSize = zipItem->Size();
-
-  // If the data is compressed, it is somewhat silly to store it in the startup
-  // cache, as the startup cache will try to double compress it.
-  if (aCaching == Default && zipItem->Compression() == STORED &&
-      !cacheKey.IsEmpty()) {
-    MOZ_ASSERT(zipItem->RealSize() == *aResultSize);
-    PutBufferIntoCache(cacheKey, zipItemData, *aResultSize);
-  }
-
-  return zipItemData;
-}
-
-nsZipItem* CacheAwareZipReader::GetItem(const char* aEntryName) {
-  return mZip->GetItem(aEntryName);
-}
-
-nsresult CacheAwareZipReader::CloseArchive() { return mZip->CloseArchive(); }
-
-CacheAwareZipCursor::CacheAwareZipCursor(nsZipItem* aItem,
-                                         CacheAwareZipReader* aReader,
-                                         uint8_t* aBuf, uint32_t aBufSize,
-                                         bool aDoCRC)
-    : mItem(aItem),
-      mReader(aReader),
-      mBuf(aBuf),
-      mBufSize(aBufSize),
-      mDoCRC(aDoCRC) {}
-
-uint8_t* CacheAwareZipCursor::ReadOrCopy(uint32_t* aBytesRead, bool aCopy) {
-  nsCString cacheKey;
-  const uint8_t* cached = mReader->GetCachedBuffer(
-      mItem->Name(), mItem->nameLength, aBytesRead, cacheKey);
-  if (cached && *aBytesRead <= mBufSize) {
-    if (aCopy) {
-      memcpy(mBuf, cached, *aBytesRead);
-      return mBuf;
-    }
-
-    // The const cast is unfortunate, but it matches existing consumers'
-    // uses. We ought to file a bug to make Read return a const uint8_t*
-    return const_cast<uint8_t*>(cached);
-  }
-
-  nsZipCursor cursor(mItem, mReader->mZip, mBuf, mBufSize, mDoCRC);
-  uint8_t* buf = nullptr;
-  if (aCopy) {
-    cursor.Copy(aBytesRead);
-    buf = mBuf;
-  } else {
-    buf = cursor.Read(aBytesRead);
-  }
-
-  if (!buf) {
-    return nullptr;
-  }
-
-  if (!cacheKey.IsEmpty() && *aBytesRead == mItem->RealSize()) {
-    CacheAwareZipReader::PutBufferIntoCache(cacheKey, buf, *aBytesRead);
-  }
-
-  return buf;
-}
-
-nsresult CacheAwareZipReader::GetPersistentHandle(
-    nsZipItem* aItem, CacheAwareZipHandle* aHandle,
-    CacheAwareZipReader::Caching aCaching) {
-  nsCString cacheKey;
-  if (!mCacheKeyPrefix.IsEmpty() && aItem->Compression() == STORED) {
-    auto* cache = scache::StartupCache::GetSingleton();
-    if (cache) {
-      cacheKey.Append(mCacheKeyPrefix);
-      cacheKey.Append(aItem->Name(), aItem->nameLength);
-
-      if (cache->HasEntry(cacheKey.get())) {
-        aHandle->mDataIsCached = true;
-        aHandle->mFd = nullptr;
-        return NS_OK;
-      }
-      if (aCaching == DeferCaching) {
-        aHandle->mDeferredCachingKey = std::move(cacheKey);
-      }
-    }
-  }
-
-  nsresult rv = mZip->EnsureArchiveOpenedOnDisk();
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-
-  aHandle->mDataIsCached = false;
-  aHandle->mFd = mZip->GetFD();
-
-  if (!aHandle->mDeferredCachingKey.IsEmpty() &&
-      aItem->Compression() == STORED) {
-    MOZ_ASSERT(aItem->RealSize() == aItem->Size());
-    const uint8_t* data = mZip->GetData(aItem);
-    if (data) {
-      aHandle->mDataToCache = Span(data, aItem->Size());
-    }
-  }
-
-  return NS_OK;
-}
-
-const uint8_t* CacheAwareZipReader::GetCachedBuffer(const char* aEntryName,
-                                                    uint32_t aEntryNameLength,
-                                                    uint32_t* aResultSize,
-                                                    nsCString& aCacheKey) {
-  *aResultSize = 0;
-  if (mCacheKeyPrefix.IsEmpty()) {
-    return nullptr;
-  }
-  auto* cache = scache::StartupCache::GetSingleton();
-  if (!cache) {
-    return nullptr;
-  }
-
-  aCacheKey.Append(mCacheKeyPrefix);
-  aCacheKey.Append(aEntryName, aEntryNameLength);
-
-  const char* cached;
-  nsresult rv = cache->GetBuffer(aCacheKey.get(), &cached, aResultSize);
-  if (NS_FAILED(rv)) {
-    return nullptr;
-  }
-
-  return reinterpret_cast<const uint8_t*>(cached);
-}
-
-void CacheAwareZipReader::PutBufferIntoCache(const nsCString& aCacheKey,
-                                             const uint8_t* aBuffer,
-                                             uint32_t aSize) {
-  if (SuspendingStartupCacheWritesForCurrentThread() || aSize == 0) {
-    return;
-  }
-
-  auto* cache = scache::StartupCache::GetSingleton();
-  auto dataCopy = MakeUniqueFallible<char[]>(aSize);
-
-  if (dataCopy) {
-    MMAP_FAULT_HANDLER_BEGIN_BUFFER(aBuffer, aSize)
-    memcpy(dataCopy.get(), aBuffer, aSize);
-    MMAP_FAULT_HANDLER_CATCH()
-    Unused << cache->PutBuffer(aCacheKey.get(), std::move(dataCopy), aSize);
-  }
-}
-
-void CacheAwareZipReader::PushSuspendStartupCacheWrites() {
-  if (!tlsSuspendStartupCacheWrites.init()) {
-    return;
-  }
-  tlsSuspendStartupCacheWrites.set(tlsSuspendStartupCacheWrites.get() + 1);
-}
-
-void CacheAwareZipReader::PopSuspendStartupCacheWrites() {
-  if (!tlsSuspendStartupCacheWrites.init()) {
-    return;
-  }
-  int current = tlsSuspendStartupCacheWrites.get();
-  MOZ_ASSERT(current > 0);
-  tlsSuspendStartupCacheWrites.set(current - 1);
-}
-
-void CacheAwareZipHandle::ReleaseHandle() {
-  if (!mDataToCache.IsEmpty()) {
-    MOZ_ASSERT(mFd);
-    MOZ_ASSERT(!mDeferredCachingKey.IsEmpty());
-    MOZ_ASSERT(!mDataIsCached);
-
-    auto* cache = scache::StartupCache::GetSingleton();
-    MOZ_ASSERT(cache);
-    if (cache) {
-      CacheAwareZipReader::PutBufferIntoCache(
-          mDeferredCachingKey, mDataToCache.Elements(), mDataToCache.Length());
-      mDataToCache = Span<const uint8_t>();
-    }
-  }
-
-  mFd = nullptr;
-}
-
 } /* namespace mozilla */
--- a/xpcom/build/Omnijar.h
+++ b/xpcom/build/Omnijar.h
@@ -8,44 +8,40 @@
 #define mozilla_Omnijar_h
 
 #include "nscore.h"
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "nsIFile.h"
 #include "nsZipArchive.h"
 
-#include "mozilla/Span.h"
 #include "mozilla/StaticPtr.h"
-#include "mozilla/UniquePtr.h"
 
 namespace mozilla {
 
-class CacheAwareZipReader;
-
 class Omnijar {
  private:
   /**
    * Store an nsIFile for an omni.jar. We can store two paths here, one
    * for GRE (corresponding to resource://gre/) and one for APP
    * (corresponding to resource:/// and resource://app/), but only
    * store one when both point to the same location (unified).
    */
   static StaticRefPtr<nsIFile> sPath[2];
 
   /**
-   * Cached CacheAwareZipReaders for the corresponding sPath
+   * Cached nsZipArchives for the corresponding sPath
    */
-  static StaticRefPtr<CacheAwareZipReader> sReader[2];
+  static StaticRefPtr<nsZipArchive> sReader[2];
 
   /**
-   * Cached CacheAwareZipReaders for the outer jar, when using nested jars.
+   * Cached nsZipArchives for the outer jar, when using nested jars.
    * Otherwise nullptr.
    */
-  static StaticRefPtr<CacheAwareZipReader> sOuterReader[2];
+  static StaticRefPtr<nsZipArchive> sOuterReader[2];
 
   /**
    * Has Omnijar::Init() been called?
    */
   static bool sInitialized;
 
   /**
    * Is using unified GRE/APP jar?
@@ -60,24 +56,23 @@ class Omnijar {
    * Returns whether we are using nested jars.
    */
   static inline bool IsNested(Type aType) {
     MOZ_ASSERT(IsInitialized(), "Omnijar not initialized");
     return !!sOuterReader[aType];
   }
 
   /**
-   * Returns an CacheAwareZipReader pointer for the outer jar file when using
-   * nested jars. Returns nullptr in the same cases GetPath() would, or if not
-   * using nested jars.
+   * Returns a nsZipArchive pointer for the outer jar file when using nested
+   * jars. Returns nullptr in the same cases GetPath() would, or if not using
+   * nested jars.
    */
-  static inline already_AddRefed<CacheAwareZipReader> GetOuterReader(
-      Type aType) {
+  static inline already_AddRefed<nsZipArchive> GetOuterReader(Type aType) {
     MOZ_ASSERT(IsInitialized(), "Omnijar not initialized");
-    RefPtr<CacheAwareZipReader> reader = sOuterReader[aType].get();
+    RefPtr<nsZipArchive> reader = sOuterReader[aType].get();
     return reader.forget();
   }
 
  public:
   /**
    * Returns whether SetBase has been called at least once with
    * a valid nsIFile
    */
@@ -113,40 +108,40 @@ class Omnijar {
    * APP when using an omni.jar in the unified case.
    */
   static inline bool HasOmnijar(Type aType) {
     MOZ_ASSERT(IsInitialized(), "Omnijar not initialized");
     return !!sPath[aType];
   }
 
   /**
-   * Returns an CacheAwareZipReader pointer for the omni.jar file for GRE or
+   * Returns a nsZipArchive pointer for the omni.jar file for GRE or
    * APP. Returns nullptr in the same cases GetPath() would.
    */
-  static inline already_AddRefed<CacheAwareZipReader> GetReader(Type aType) {
+  static inline already_AddRefed<nsZipArchive> GetReader(Type aType) {
     MOZ_ASSERT(IsInitialized(), "Omnijar not initialized");
-    RefPtr<CacheAwareZipReader> reader = sReader[aType].get();
+    RefPtr<nsZipArchive> reader = sReader[aType].get();
     return reader.forget();
   }
 
   /**
-   * Returns an CacheAwareZipReader pointer for the given path IAOI the given
+   * Returns a nsZipArchive pointer for the given path IAOI the given
    * path is the omni.jar for either GRE or APP.
    */
-  static already_AddRefed<CacheAwareZipReader> GetReader(nsIFile* aPath);
+  static already_AddRefed<nsZipArchive> GetReader(nsIFile* aPath);
 
   /**
    * In the case of a nested omnijar, this returns the inner reader for the
    * omnijar if aPath points to the outer archive and aEntry is the omnijar
    * entry name. Returns null otherwise.
    * In concrete terms: On Android the omnijar is nested inside the apk archive.
    * GetReader("path/to.apk") returns the outer reader and GetInnerReader(
    * "path/to.apk", "assets/omni.ja") returns the inner reader.
    */
-  static already_AddRefed<CacheAwareZipReader> GetInnerReader(
+  static already_AddRefed<nsZipArchive> GetInnerReader(
       nsIFile* aPath, const nsACString& aEntry);
 
   /**
    * Returns the URI string corresponding to the omni.jar or directory
    * for GRE or APP. i.e. jar:/path/to/omni.jar!/ for omni.jar and
    * /path/to/base/dir/ otherwise. Returns an empty string for APP in
    * the unified case.
    * The returned URI is guaranteed to end with a slash.
@@ -156,137 +151,11 @@ class Omnijar {
  private:
   /**
    * Used internally, respectively by Init() and CleanUp()
    */
   static void InitOne(nsIFile* aPath, Type aType);
   static void CleanUpOne(Type aType);
 }; /* class Omnijar */
 
-class CacheAwareZipCursor {
- public:
-  CacheAwareZipCursor(nsZipItem* aItem, CacheAwareZipReader* aReader,
-                      uint8_t* aBuf = nullptr, uint32_t aBufSize = 0,
-                      bool aDoCRC = false);
-
-  uint8_t* Read(uint32_t* aBytesRead) { return ReadOrCopy(aBytesRead, false); }
-  uint8_t* Copy(uint32_t* aBytesRead) { return ReadOrCopy(aBytesRead, true); }
-
- private:
-  /* Actual implementation for both Read and Copy above */
-  uint8_t* ReadOrCopy(uint32_t* aBytesRead, bool aCopy);
-
-  nsZipItem* mItem;
-  CacheAwareZipReader* mReader;
-
-  uint8_t* mBuf;
-  uint32_t mBufSize;
-
-  bool mDoCRC;
-};
-
-// This class wraps an nsZipHandle, which may be null, if the data is
-// cached
-class CacheAwareZipHandle {
-  friend class CacheAwareZipReader;
-
- public:
-  CacheAwareZipHandle() : mFd(nullptr), mDataIsCached(false) {}
-  ~CacheAwareZipHandle() { ReleaseHandle(); }
-
-  nsZipHandle* UnderlyingFD() { return mFd; }
-  void ReleaseHandle();
-
-  explicit operator bool() const { return mDataIsCached || mFd; }
-
- private:
-  RefPtr<nsZipHandle> mFd;
-  nsCString mDeferredCachingKey;
-  Span<const uint8_t> mDataToCache;
-  bool mDataIsCached;
-};
-
-class CacheAwareZipReader {
-  friend class CacheAwareZipCursor;
-  friend class CacheAwareZipHandle;
-
- public:
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CacheAwareZipReader)
-
-  enum Caching {
-    Default,
-    DeferCaching,
-  };
-
-  // Constructor for CacheAwareZipReader. aCacheKeyPrefix will be a prefix
-  // which the wrapper will prepend to any requested entries prior to
-  // requesting the entry from the StartupCache. However, if aCacheKeyPrefix
-  // is null, we will simply pass through to the underlying zip archive
-  // without caching.
-  explicit CacheAwareZipReader(nsZipArchive* aZip, const char* aCacheKeyPrefix);
-
-  // The default constructor should be used for an nsZipArchive which doesn't
-  // want to cache any entries. Consumers will need to call `OpenArchive`
-  // explicitly after constructing.
-  CacheAwareZipReader() : mZip(new nsZipArchive()) {}
-
-  nsresult OpenArchive(nsIFile* aFile) { return mZip->OpenArchive(aFile); }
-  nsresult OpenArchive(nsZipHandle* aHandle) {
-    return mZip->OpenArchive(aHandle);
-  }
-
-  const uint8_t* GetData(const char* aEntryName, uint32_t* aResultSize,
-                         Caching aCaching = Default);
-  const uint8_t* GetData(nsZipItem* aItem, Caching aCaching = Default);
-
-  nsresult GetPersistentHandle(nsZipItem* aItem, CacheAwareZipHandle* aHandle,
-                               Caching aCaching);
-
-  already_AddRefed<nsIFile> GetBaseFile() { return mZip->GetBaseFile(); }
-
-  void GetURIString(nsACString& result) { mZip->GetURIString(result); }
-
-  nsZipArchive* GetZipArchive() { return mZip; }
-
-  nsresult FindInit(const char* aPattern, nsZipFind** aFind);
-  bool IsForZip(nsZipArchive* aArchive) { return aArchive == mZip; }
-  nsZipItem* GetItem(const char* aEntryName);
-
-  nsresult CloseArchive();
-
-  nsresult Test(const char* aEntryName) { return mZip->Test(aEntryName); }
-
-  nsresult ExtractFile(nsZipItem* zipEntry, nsIFile* outFile,
-                       PRFileDesc* outFD) {
-    return mZip->ExtractFile(zipEntry, outFile, outFD);
-  }
-
-  static void PushSuspendStartupCacheWrites();
-  static void PopSuspendStartupCacheWrites();
-
- protected:
-  ~CacheAwareZipReader() = default;
-
- private:
-  const uint8_t* GetCachedBuffer(const char* aEntryName,
-                                 uint32_t aEntryNameLength,
-                                 uint32_t* aResultSize, nsCString& aCacheKey);
-  static void PutBufferIntoCache(const nsCString& aCacheKey,
-                                 const uint8_t* aBuffer, uint32_t aSize);
-
-  RefPtr<nsZipArchive> mZip;
-  nsCString mCacheKeyPrefix;
-};
-
-class MOZ_RAII AutoSuspendStartupCacheWrites {
- public:
-  AutoSuspendStartupCacheWrites() {
-    CacheAwareZipReader::PushSuspendStartupCacheWrites();
-  }
-
-  ~AutoSuspendStartupCacheWrites() {
-    CacheAwareZipReader::PopSuspendStartupCacheWrites();
-  }
-};
-
 } /* namespace mozilla */
 
 #endif /* mozilla_Omnijar_h */
--- a/xpcom/build/XPCOMInit.cpp
+++ b/xpcom/build/XPCOMInit.cpp
@@ -457,17 +457,17 @@ NS_InitXPCOM(nsIServiceManager** aResult
   // After autoreg, but before we actually instantiate any components,
   // add any services listed in the "xpcom-directory-providers" category
   // to the directory service.
   nsDirectoryService::gService->RegisterCategoryProviders();
 
   // Init mozilla::SharedThreadPool (which needs the service manager).
   mozilla::SharedThreadPool::InitStatics();
 
-  mozilla::scache::StartupCache::FullyInitSingleton();
+  mozilla::scache::StartupCache::GetSingleton();
   mozilla::AvailableMemoryTracker::Init();
 
   // Notify observers of xpcom autoregistration start
   NS_CreateServicesFromCategory(NS_XPCOM_STARTUP_CATEGORY, nullptr,
                                 NS_XPCOM_STARTUP_OBSERVER_ID);
 #ifdef XP_WIN
   CreateAnonTempFileRemover();
 #endif
--- a/xpcom/components/nsComponentManager.cpp
+++ b/xpcom/components/nsComponentManager.cpp
@@ -488,26 +488,26 @@ nsresult nsComponentManagerImpl::Init() 
     // The overall order in which chrome.manifests are expected to be treated
     // is the following:
     // - greDir's omni.ja or greDir
     // - appDir's omni.ja or appDir
 
     InitializeModuleLocations();
     ComponentLocation* cl = sModuleLocations->AppendElement();
     cl->type = NS_APP_LOCATION;
-    RefPtr<CacheAwareZipReader> greOmnijar =
+    RefPtr<nsZipArchive> greOmnijar =
         mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE);
     if (greOmnijar) {
       cl->location.Init(greOmnijar, "chrome.manifest");
     } else {
       nsCOMPtr<nsIFile> lf = CloneAndAppend(greDir, "chrome.manifest"_ns);
       cl->location.Init(lf);
     }
 
-    RefPtr<CacheAwareZipReader> appOmnijar =
+    RefPtr<nsZipArchive> appOmnijar =
         mozilla::Omnijar::GetReader(mozilla::Omnijar::APP);
     if (appOmnijar) {
       cl = sModuleLocations->AppendElement();
       cl->type = NS_APP_LOCATION;
       cl->location.Init(appOmnijar, "chrome.manifest");
     } else {
       bool equals = false;
       appDir->Equals(greDir, &equals);
--- a/xpcom/threads/Mutex.h
+++ b/xpcom/threads/Mutex.h
@@ -3,19 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_Mutex_h
 #define mozilla_Mutex_h
 
 #include "mozilla/BlockingResourceBase.h"
-#include "mozilla/Maybe.h"
 #include "mozilla/PlatformMutex.h"
-#include "mozilla/Unused.h"
 
 //
 // Provides:
 //
 //  - Mutex, a non-recursive mutex
 //  - MutexAutoLock, an RAII class for ensuring that Mutexes are properly
 //    locked and unlocked
 //  - MutexAutoUnlock, complementary sibling to MutexAutoLock
@@ -155,35 +153,16 @@ class MOZ_RAII BaseAutoLock {
    *
    * @param aLock A valid mozilla::Mutex* returned by
    *              mozilla::Mutex::NewMutex.
    **/
   explicit BaseAutoLock(T aLock) : mLock(aLock) { mLock.Lock(); }
 
   ~BaseAutoLock(void) { mLock.Unlock(); }
 
-  /**
-   * TryMake
-   * Tries to lock the mutex with TryLock, and returns true with aOutAutoLock
-   * containing the BaseAutoLock if TryLock was successful. Otherwise returns
-   * false.
-   *
-   * @param aLock A valid mozilla::Mutex* returned by
-   *              mozilla::Mutex::NewMutex.
-   * @param aOutAutoLock A Maybe<BaseAutoLock<T>> to fill if TryLock succeeds.
-   **/
-  [[nodiscard]] static bool TryMake(T aLock,
-                                    Maybe<BaseAutoLock<T>>& aOutAutoLock) {
-    if (aLock.TryLock()) {
-      aOutAutoLock.emplace(aLock, /* aPlaceholder: */ true);
-      return true;
-    }
-    return false;
-  }
-
   // Assert that aLock is the mutex passed to the constructor and that the
   // current thread owns the mutex.  In coding patterns such as:
   //
   // void LockedMethod(const BaseAutoLock<T>& aProofOfLock)
   // {
   //   aProofOfLock.AssertOwns(mMutex);
   //   ...
   // }
@@ -210,28 +189,18 @@ class MOZ_RAII BaseAutoLock {
   }
 
  private:
   BaseAutoLock();
   BaseAutoLock(BaseAutoLock&);
   BaseAutoLock& operator=(BaseAutoLock&);
   static void* operator new(size_t) noexcept(true);
 
-  // This is the internal cconstructor used by TryMake. We need it to be a
-  // constructor to distinguish it from the public constructor, so we add a
-  // dummy variable to track that.
-  BaseAutoLock(T aLock, bool aPlaceholder) : mLock(aLock) {
-    Unused << aPlaceholder;
-  }
-
   friend class BaseAutoUnlock<T>;
 
-  // So that Maybe can access our private constructor
-  friend class Maybe<BaseAutoLock<T>>;
-
   T mLock;
 };
 
 template <typename MutexType>
 BaseAutoLock(MutexType&) -> BaseAutoLock<MutexType&>;
 }  // namespace detail
 
 typedef detail::BaseAutoLock<Mutex&> MutexAutoLock;