diff --git a/modules/libjar/nsZipArchive.cpp b/modules/libjar/nsZipArchive.cpp index a25cfadb19a..e945091a313 100644 --- a/modules/libjar/nsZipArchive.cpp +++ b/modules/libjar/nsZipArchive.cpp @@ -30,6 +30,7 @@ #define ZIP_ARENABLOCKSIZE (1*1024) #ifdef XP_UNIX + #include #include #include #include @@ -165,10 +166,14 @@ nsZipHandle::nsZipHandle() NS_IMPL_THREADSAFE_ADDREF(nsZipHandle) NS_IMPL_THREADSAFE_RELEASE(nsZipHandle) -nsresult nsZipHandle::Init(nsIFile *file, nsZipHandle **ret) +nsresult nsZipHandle::Init(nsIFile *file, nsZipHandle **ret, PRFileDesc **aFd) { mozilla::AutoFDClose fd; - nsresult rv = file->OpenNSPRFileDesc(PR_RDONLY, 0000, &fd.rwget()); + int32_t flags = PR_RDONLY; +#if defined(XP_WIN) + flags |= nsIFile::OS_READAHEAD; +#endif + nsresult rv = file->OpenNSPRFileDesc(flags, 0000, &fd.rwget()); if (NS_FAILED(rv)) return rv; @@ -194,6 +199,11 @@ nsresult nsZipHandle::Init(nsIFile *file, nsZipHandle **ret) return NS_ERROR_OUT_OF_MEMORY; } +#if defined(XP_WIN) + if (aFd) { + *aFd = fd.forget(); + } +#endif handle->mMap = map; handle->mFile.Init(file); handle->mLen = (uint32_t) size; @@ -248,7 +258,7 @@ nsZipHandle::~nsZipHandle() //--------------------------------------------- // nsZipArchive::OpenArchive //--------------------------------------------- -nsresult nsZipArchive::OpenArchive(nsZipHandle *aZipHandle) +nsresult nsZipArchive::OpenArchive(nsZipHandle *aZipHandle, PRFileDesc *aFd) { mFd = aZipHandle; @@ -256,7 +266,7 @@ nsresult nsZipArchive::OpenArchive(nsZipHandle *aZipHandle) PL_INIT_ARENA_POOL(&mArena, "ZipArena", ZIP_ARENABLOCKSIZE); //-- get table of contents for archive - nsresult rv = BuildFileList(); + nsresult rv = BuildFileList(aFd); if (NS_SUCCEEDED(rv)) { if (aZipHandle->mFile) aZipHandle->mFile.GetURIString(mURI); @@ -267,11 +277,20 @@ nsresult nsZipArchive::OpenArchive(nsZipHandle *aZipHandle) nsresult nsZipArchive::OpenArchive(nsIFile *aFile) { nsRefPtr 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()); +#else return OpenArchive(handle); +#endif } //--------------------------------------------- @@ -559,7 +578,7 @@ nsZipItem* nsZipArchive::CreateZipItem() //--------------------------------------------- // nsZipArchive::BuildFileList //--------------------------------------------- -nsresult nsZipArchive::BuildFileList() +nsresult nsZipArchive::BuildFileList(PRFileDesc *aFd) { // Get archive size using end pos const uint8_t* buf; @@ -569,6 +588,17 @@ MOZ_WIN_MEM_TRY_BEGIN uint32_t centralOffset = 4; if (mFd->mLen > ZIPCENTRAL_SIZE && xtolong(startp + centralOffset) == CENTRALSIG) { // Success means optimized jar layout from bug 559961 is in effect + uint32_t readaheadLength = xtolong(startp); + if (readaheadLength) { +#if defined(XP_UNIX) + madvise(const_cast(startp), readaheadLength, MADV_WILLNEED); +#elif defined(XP_WIN) + if (aFd) { + HANDLE hFile = (HANDLE) PR_FileDesc2NativeHandle(aFd); + mozilla::ReadAhead(hFile, 0, readaheadLength); + } +#endif + } } else { for (buf = endp - ZIPEND_SIZE; buf > startp; buf--) { diff --git a/modules/libjar/nsZipArchive.h b/modules/libjar/nsZipArchive.h index 895a19ebd1d..991d19a1dc1 100644 --- a/modules/libjar/nsZipArchive.h +++ b/modules/libjar/nsZipArchive.h @@ -113,9 +113,10 @@ public: * part of the constructor * * @param aZipHandle The nsZipHandle used to access the zip + * @param aFd Optional PRFileDesc for Windows readahead optimization * @return status code */ - nsresult OpenArchive(nsZipHandle *aZipHandle); + nsresult OpenArchive(nsZipHandle *aZipHandle, PRFileDesc *aFd = nullptr); /** * OpenArchive @@ -223,7 +224,7 @@ private: private: //--- private methods --- nsZipItem* CreateZipItem(); - nsresult BuildFileList(); + nsresult BuildFileList(PRFileDesc *aFd = nullptr); nsresult BuildSynthetics(); nsZipArchive& operator=(const nsZipArchive& rhs) MOZ_DELETE; @@ -374,7 +375,8 @@ class nsZipHandle { friend class nsZipArchive; friend class mozilla::FileLocation; public: - static nsresult Init(nsIFile *file, nsZipHandle **ret); + static nsresult Init(nsIFile *file, nsZipHandle **ret, + PRFileDesc **aFd = nullptr); static nsresult Init(nsZipArchive *zip, const char *entry, nsZipHandle **ret);