Skip to content

Commit

Permalink
Bug 1627075 - Route Omnijar requests through StartupCache r=froydnj
Browse files Browse the repository at this point in the history
This should be a relatively straightforward patch. Essentially, we implement
a wrapper class (and friends) around nsZipArchive (and friends), which transparently
caches entries from the underlying zip archive in the StartupCache. This will break
without changes to the StartupCache, made in the patch after this, which allow it
to be used off of the main thread, and outside the main process.

Depends on D77635

Differential Revision: https://phabricator.services.mozilla.com/D77634
  • Loading branch information
squarewave committed Jul 7, 2020
1 parent 5ff30b6 commit e3f3b7b
Show file tree
Hide file tree
Showing 19 changed files with 517 additions and 131 deletions.
15 changes: 8 additions & 7 deletions gfx/thebes/gfxFT2FontList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,14 @@ already_AddRefed<SharedFTFace> FT2FontEntry::GetFTFace(bool aCommit) {
// here would be memory allocation, in which case mFace remains null.
RefPtr<SharedFTFace> face;
if (mFilename[0] != '/') {
RefPtr<nsZipArchive> reader = Omnijar::GetReader(Omnijar::Type::GRE);
RefPtr<CacheAwareZipReader> 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) {
nsZipCursor cursor(item, reader, fontDataBuf, bufSize);
CacheAwareZipCursor cursor(item, reader, fontDataBuf, bufSize);
cursor.Copy(&bufSize);
NS_ASSERTION(bufSize == item->RealSize(), "error reading bundled font");
RefPtr<FTUserFontData> ufd = new FTUserFontData(fontDataBuf, bufSize);
Expand Down Expand Up @@ -458,7 +458,8 @@ hb_blob_t* FT2FontEntry::GetFontTable(uint32_t aTableTag) {
} else {
// A relative path means an omnijar resource, which we may need to
// decompress to a temporary buffer.
RefPtr<nsZipArchive> reader = Omnijar::GetReader(Omnijar::Type::GRE);
RefPtr<CacheAwareZipReader> reader =
Omnijar::GetReader(Omnijar::Type::GRE);
nsZipItem* item = reader->GetItem(mFilename.get());
MOZ_ASSERT(item, "failed to find zip entry");
if (item) {
Expand All @@ -469,7 +470,7 @@ hb_blob_t* FT2FontEntry::GetFontTable(uint32_t aTableTag) {
uint32_t length = item->RealSize();
uint8_t* buffer = static_cast<uint8_t*>(malloc(length));
if (buffer) {
nsZipCursor cursor(item, reader, buffer, length);
CacheAwareZipCursor cursor(item, reader, buffer, length);
cursor.Copy(&length);
MOZ_ASSERT(length == item->RealSize(), "error reading font");
if (length == item->RealSize()) {
Expand Down Expand Up @@ -1159,7 +1160,7 @@ void gfxFT2FontList::FindFontsInOmnijar(FontNameCache* aCache) {
static const char* sJarSearchPaths[] = {
"res/fonts/*.ttf$",
};
RefPtr<nsZipArchive> reader = Omnijar::GetReader(Omnijar::Type::GRE);
RefPtr<CacheAwareZipReader> reader = Omnijar::GetReader(Omnijar::Type::GRE);
for (unsigned i = 0; i < ArrayLength(sJarSearchPaths); i++) {
nsZipFind* find;
if (NS_SUCCEEDED(reader->FindInit(sJarSearchPaths[i], &find))) {
Expand Down Expand Up @@ -1274,7 +1275,7 @@ void gfxFT2FontList::AddFaceToList(const nsCString& aEntryName, uint32_t aIndex,
}
}

void gfxFT2FontList::AppendFacesFromOmnijarEntry(nsZipArchive* aArchive,
void gfxFT2FontList::AppendFacesFromOmnijarEntry(CacheAwareZipReader* aArchive,
const nsCString& aEntryName,
FontNameCache* aCache,
bool aJarChanged) {
Expand Down Expand Up @@ -1313,7 +1314,7 @@ void gfxFT2FontList::AppendFacesFromOmnijarEntry(nsZipArchive* aArchive,
return;
}

nsZipCursor cursor(item, aArchive, (uint8_t*)buffer, bufSize);
CacheAwareZipCursor 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) {
Expand Down
5 changes: 4 additions & 1 deletion gfx/thebes/gfxFT2FontList.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
#include "gfxPlatformFontList.h"

namespace mozilla {

class CacheAwareZipReader;

namespace dom {
class SystemFontListEntry;
};
Expand Down Expand Up @@ -174,7 +177,7 @@ class gfxFT2FontList final : public gfxPlatformFontList {
void AppendFacesFromFontFile(const nsCString& aFileName,
FontNameCache* aCache, StandardFile aStdFile);

void AppendFacesFromOmnijarEntry(nsZipArchive* aReader,
void AppendFacesFromOmnijarEntry(mozilla::CacheAwareZipReader* aArchive,
const nsCString& aEntryName,
FontNameCache* aCache, bool aJarChanged);

Expand Down
2 changes: 1 addition & 1 deletion intl/hyphenation/glue/nsHyphenationManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ void nsHyphenationManager::LoadPatternListFromOmnijar(Omnijar::Type aType) {
return;
}

RefPtr<nsZipArchive> zip = Omnijar::GetReader(aType);
RefPtr<CacheAwareZipReader> zip = Omnijar::GetReader(aType);
if (!zip) {
return;
}
Expand Down
13 changes: 2 additions & 11 deletions intl/hyphenation/glue/nsHyphenator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,20 +41,11 @@ static const void* GetItemPtrFromJarURI(nsIJARURI* aJAR, uint32_t* aLength) {
if (!file) {
return nullptr;
}
RefPtr<nsZipArchive> archive = Omnijar::GetReader(file);
RefPtr<CacheAwareZipReader> archive = Omnijar::GetReader(file);
if (archive) {
nsCString path;
aJAR->GetJAREntry(path);
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 archive->GetData(path.get(), aLength);
}
return nullptr;
}
Expand Down
9 changes: 5 additions & 4 deletions intl/locale/LocaleService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -295,13 +295,14 @@ bool LocaleService::IsServer() { return mIsServer; }

static bool GetGREFileContents(const char* aFilePath, nsCString* aOutString) {
// Look for the requested file in omnijar.
RefPtr<nsZipArchive> zip = Omnijar::GetReader(Omnijar::GRE);
RefPtr<CacheAwareZipReader> zip = Omnijar::GetReader(Omnijar::GRE);
if (zip) {
nsZipItemPtr<char> item(zip, aFilePath);
if (!item) {
uint32_t length;
const uint8_t* data = zip->GetData(aFilePath, &length);
if (!data) {
return false;
}
aOutString->Assign(item.Buffer(), item.Length());
aOutString->Assign(reinterpret_cast<const char*>(data), length);
return true;
}

Expand Down
18 changes: 9 additions & 9 deletions js/xpconnect/loader/URLPreloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ void URLPreloader::BackgroundReadFiles() {
mReaderThread = nullptr;
});

Vector<nsZipCursor> cursors;
Vector<CacheAwareZipCursor> cursors;
LinkedList<URLEntry> pendingURLs;
{
MonitorAutoLock mal(mMonitor);
Expand Down Expand Up @@ -352,14 +352,14 @@ void URLPreloader::BackgroundReadFiles() {
continue;
}

RefPtr<nsZipArchive> zip = entry->Archive();
RefPtr<CacheAwareZipReader> 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;
Expand Down Expand Up @@ -495,25 +495,25 @@ Result<const nsCString, nsresult> URLPreloader::ReadURIInternal(
}

/* static */ Result<const nsCString, nsresult> URLPreloader::ReadZip(
nsZipArchive* zip, const nsACString& path, ReadType readType) {
CacheAwareZipReader* archive, 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<nsZipArchive> reader = Omnijar::GetReader(Omnijar::GRE);
if (zip == reader) {
RefPtr<CacheAwareZipReader> reader = Omnijar::GetReader(Omnijar::GRE);
if (reader == archive) {
CacheKey key(CacheKey::TypeGREJar, path);
return Read(key, readType);
}

reader = Omnijar::GetReader(Omnijar::APP);
if (zip == reader) {
if (reader == archive) {
CacheKey key(CacheKey::TypeAppJar, path);
return Read(key, readType);
}

// Not an Omnijar archive, so just read it directly.
FileLocation location(zip, PromiseFlatCString(path).BeginReading());
FileLocation location(archive, PromiseFlatCString(path).BeginReading());
return URLEntry::ReadLocation(location);
}

Expand Down Expand Up @@ -581,7 +581,7 @@ Result<FileLocation, nsresult> URLPreloader::CacheKey::ToFileLocation() {
return FileLocation(file);
}

RefPtr<nsZipArchive> zip = Archive();
RefPtr<CacheAwareZipReader> zip = Archive();
return FileLocation(zip, mPath.get());
}

Expand Down
6 changes: 2 additions & 4 deletions js/xpconnect/loader/URLPreloader.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@
#include "nsIThread.h"
#include "nsReadableUtils.h"

class nsZipArchive;

namespace mozilla {
namespace loader {
class InputBuffer;
Expand Down Expand Up @@ -77,7 +75,7 @@ class URLPreloader final : public nsIObserver, public nsIMemoryReporter {
static Result<const nsCString, nsresult> ReadFile(nsIFile* file,
ReadType readType = Forget);

static Result<const nsCString, nsresult> ReadZip(nsZipArchive* archive,
static Result<const nsCString, nsresult> ReadZip(CacheAwareZipReader* archive,
const nsACString& path,
ReadType readType = Forget);

Expand Down Expand Up @@ -198,7 +196,7 @@ class URLPreloader final : public nsIObserver, public nsIMemoryReporter {
return "";
}

already_AddRefed<nsZipArchive> Archive() {
already_AddRefed<CacheAwareZipReader> Archive() {
return Omnijar::GetReader(OmnijarType());
}

Expand Down
5 changes: 5 additions & 0 deletions js/xpconnect/loader/mozJSComponentLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#include "mozilla/scache/StartupCacheUtils.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"
Expand Down Expand Up @@ -670,6 +671,10 @@ JSObject* mozJSComponentLoader::PrepareObjectForLocation(

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;
Expand Down
5 changes: 5 additions & 0 deletions js/xpconnect/loader/mozJSSubScriptLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

#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"
Expand Down Expand Up @@ -248,6 +249,10 @@ bool mozJSSubScriptLoader::ReadScript(JS::MutableHandle<JSScript*> script,
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;
Expand Down
15 changes: 9 additions & 6 deletions modules/libjar/nsJAR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ using namespace mozilla;

// The following initialization makes a guess of 10 entries per jarfile.
nsJAR::nsJAR()
: mZip(new nsZipArchive()),
: mZip(nullptr),
mReleaseTime(PR_INTERVAL_NO_TIMEOUT),
mCache(nullptr),
mLock("nsJAR::mLock"),
Expand Down Expand Up @@ -87,12 +87,13 @@ nsJAR::Open(nsIFile* zipFile) {

// The omnijar is special, it is opened early on and closed late
// this avoids reopening it
RefPtr<nsZipArchive> zip = mozilla::Omnijar::GetReader(zipFile);
RefPtr<CacheAwareZipReader> zip = mozilla::Omnijar::GetReader(zipFile);
if (zip) {
mZip = zip;
mSkipArchiveClosing = true;
return NS_OK;
}
mZip = new CacheAwareZipReader();
return mZip->OpenArchive(zipFile);
}

Expand All @@ -102,7 +103,7 @@ nsJAR::OpenInner(nsIZipReader* aZipReader, const nsACString& aZipEntry) {
if (mOpened) return NS_ERROR_FAILURE; // Already open!

nsJAR* outerJAR = static_cast<nsJAR*>(aZipReader);
RefPtr<nsZipArchive> innerZip =
RefPtr<CacheAwareZipReader> innerZip =
mozilla::Omnijar::GetInnerReader(outerJAR->mZipFile, aZipEntry);
if (innerZip) {
mOpened = true;
Expand All @@ -124,11 +125,12 @@ nsJAR::OpenInner(nsIZipReader* aZipReader, const nsACString& aZipEntry) {
mOuterZipEntry.Assign(aZipEntry);

RefPtr<nsZipHandle> handle;
rv = nsZipHandle::Init(static_cast<nsJAR*>(aZipReader)->mZip.get(),
rv = nsZipHandle::Init(static_cast<nsJAR*>(aZipReader)->mZip->GetZipArchive(),
PromiseFlatCString(aZipEntry).get(),
getter_AddRefs(handle));
if (NS_FAILED(rv)) return rv;

mZip = new CacheAwareZipReader();
return mZip->OpenArchive(handle);
}

Expand All @@ -144,6 +146,7 @@ nsJAR::OpenMemory(void* aData, uint32_t aLength) {
getter_AddRefs(handle));
if (NS_FAILED(rv)) return rv;

mZip = new CacheAwareZipReader();
return mZip->OpenArchive(handle);
}

Expand All @@ -165,7 +168,7 @@ nsJAR::Close() {
if (mSkipArchiveClosing) {
// Reset state, but don't close the omnijar because we did not open it.
mSkipArchiveClosing = false;
mZip = new nsZipArchive();
mZip = nullptr;
return NS_OK;
}

Expand Down Expand Up @@ -301,7 +304,7 @@ nsresult nsJAR::GetNSPRFileDesc(PRFileDesc** aNSPRFileDesc) {
return NS_ERROR_FAILURE;
}

RefPtr<nsZipHandle> handle = mZip->GetFD();
RefPtr<nsZipHandle> handle = mZip->GetZipArchive()->GetFD();
if (!handle) {
return NS_ERROR_FAILURE;
}
Expand Down
12 changes: 8 additions & 4 deletions modules/libjar/nsJAR.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,17 @@
#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
Expand Down Expand Up @@ -72,9 +76,9 @@ class nsJAR final : public nsIZipReader {

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<nsZipArchive> 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<mozilla::CacheAwareZipReader> 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
Expand Down
Loading

0 comments on commit e3f3b7b

Please sign in to comment.