Bug 1546498 - Split out MaybePrefetchMemory's check into two functions r=aklotz
authorDoug Thayer <dothayer@mozilla.com>
Wed, 01 May 2019 02:08:28 +0000
changeset 530858 cbdf3fdfcbac59d4ccac118d2e6a96ac360a94a5
parent 530857 4d0cb443ef8b8ae84d8ea3dd65da1d923da3ff0e
child 530859 9242458b79d5ae6e9d48c9a2a591680d79c13211
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaklotz
bugs1546498
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1546498 - Split out MaybePrefetchMemory's check into two functions r=aklotz Temporarily just sidestep the issue in bug 1546498 (crash with latest SDK on startup in Windows 7) by just continuing to use the old method in Windows 7. We saw no wins in telemetry for Windows 7 anyway, so we should investigate why that is, and why we see a mysterious crash in the fallback code, in a followup bug. Differential Revision: https://phabricator.services.mozilla.com/D29239
modules/libjar/nsZipArchive.cpp
xpcom/glue/FileUtils.cpp
xpcom/glue/MemUtils.cpp
xpcom/glue/MemUtils.h
--- a/modules/libjar/nsZipArchive.cpp
+++ b/modules/libjar/nsZipArchive.cpp
@@ -646,18 +646,17 @@ nsresult nsZipArchive::BuildFileList(PRF
   // 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) {
     // Success means optimized jar layout from bug 559961 is in effect
     uint32_t readaheadLength = xtolong(startp);
-    mozilla::MaybePrefetchMemory(const_cast<uint8_t *>(startp),
-                                 readaheadLength);
+    mozilla::PrefetchMemory(const_cast<uint8_t *>(startp), readaheadLength);
   } else {
     for (buf = endp - ZIPEND_SIZE; buf > startp; buf--) {
       if (xtolong(buf) == ENDSIG) {
         centralOffset = xtolong(((ZipEnd *)buf)->offset_central_dir);
         break;
       }
     }
   }
--- a/xpcom/glue/FileUtils.cpp
+++ b/xpcom/glue/FileUtils.cpp
@@ -353,16 +353,20 @@ void mozilla::ReadAhead(mozilla::filedes
 #endif
 }
 
 void mozilla::ReadAheadLib(mozilla::pathstr_t aFilePath) {
   if (!aFilePath) {
     return;
   }
 #if defined(XP_WIN)
+  if (!CanPrefetchMemory()) {
+    ReadAheadFile(aFilePath);
+    return;
+  }
   nsAutoHandle fd(CreateFileW(aFilePath, GENERIC_READ, FILE_SHARE_READ, nullptr,
                               OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN,
                               nullptr));
   if (!fd) {
     return;
   }
   LARGE_INTEGER fileSize = {};
   BOOL success = GetFileSizeEx(fd, &fileSize);
@@ -377,21 +381,18 @@ void mozilla::ReadAheadLib(mozilla::path
   if (!mapping) {
     return;
   }
 
   PVOID data =
       MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, (size_t)fileSize.QuadPart);
   auto guard = MakeScopeExit([=]() { UnmapViewOfFile(data); });
 
-  if (data && !MaybePrefetchMemory((uint8_t*)data, (size_t)fileSize.QuadPart)) {
-    volatile uint8_t read = 0;
-    for (size_t i = 0; i < (size_t)fileSize.QuadPart; i += 4096) {
-      read += ((uint8_t*)data)[i];
-    }
+  if (data) {
+    PrefetchMemory((uint8_t*)data, (size_t)fileSize.QuadPart);
   }
 
 #elif defined(LINUX) && !defined(ANDROID)
   int fd = open(aFilePath, O_RDONLY);
   if (fd < 0) {
     return;
   }
 
--- a/xpcom/glue/MemUtils.cpp
+++ b/xpcom/glue/MemUtils.cpp
@@ -3,48 +3,65 @@
 /* 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/MemUtils.h"
 
 #if defined(XP_WIN)
 #  include <windows.h>
+#  include "mozilla/Maybe.h"
 #else
 #  include <sys/mman.h>
 #endif
 
-bool mozilla::MaybePrefetchMemory(uint8_t* aStart, size_t aNumBytes) {
+#if defined(XP_WIN)
+typedef BOOL(WINAPI* PrefetchVirtualMemoryFn)(HANDLE, ULONG_PTR, PVOID, ULONG);
+
+static mozilla::Maybe<PrefetchVirtualMemoryFn> sPrefetchVirtualMemory;
+
+void MaybeInitPrefetchVirtualMemory() {
+  if (sPrefetchVirtualMemory.isNothing()) {
+    sPrefetchVirtualMemory.emplace(
+        reinterpret_cast<PrefetchVirtualMemoryFn>(GetProcAddress(
+            GetModuleHandleW(L"kernel32.dll"), "PrefetchVirtualMemory")));
+  }
+}
+#endif
+
+bool mozilla::CanPrefetchMemory() {
+#if defined(XP_SOLARIS) || defined(XP_UNIX)
+  return true;
+#elif defined(XP_WIN)
+  MaybeInitPrefetchVirtualMemory();
+  return *sPrefetchVirtualMemory;
+#else
+  return false;
+#endif
+}
+
+void mozilla::PrefetchMemory(uint8_t* aStart, size_t aNumBytes) {
   if (aNumBytes == 0) {
-    return true;
+    return;
   }
 
 #if defined(XP_SOLARIS)
   posix_madvise(aStart, aNumBytes, POSIX_MADV_WILLNEED);
-  return true;
 #elif defined(XP_UNIX)
   madvise(aStart, aNumBytes, MADV_WILLNEED);
-  return true;
 #elif defined(XP_WIN)
-  static auto prefetchVirtualMemory =
-      reinterpret_cast<BOOL(WINAPI*)(HANDLE, ULONG_PTR, PVOID, ULONG)>(
-          GetProcAddress(GetModuleHandleW(L"kernel32.dll"),
-                         "PrefetchVirtualMemory"));
-
-  if (prefetchVirtualMemory) {
+  MaybeInitPrefetchVirtualMemory();
+  if (*sPrefetchVirtualMemory) {
     // Normally, we'd use WIN32_MEMORY_RANGE_ENTRY, but that requires
     // a different _WIN32_WINNT value before including windows.h, but
     // that causes complications with unified sources. It's a simple
     // enough struct anyways.
     struct {
       PVOID VirtualAddress;
       SIZE_T NumberOfBytes;
     } entry;
     entry.VirtualAddress = aStart;
     entry.NumberOfBytes = aNumBytes;
-    prefetchVirtualMemory(GetCurrentProcess(), 1, &entry, 0);
-    return true;
+    (*sPrefetchVirtualMemory)(GetCurrentProcess(), 1, &entry, 0);
+    return;
   }
-  return false;
-#else
-  return false;
 #endif
 }
--- a/xpcom/glue/MemUtils.h
+++ b/xpcom/glue/MemUtils.h
@@ -7,13 +7,14 @@
 #ifndef mozilla_MemUtils_h
 #define mozilla_MemUtils_h
 
 #include <stddef.h>
 #include <stdint.h>
 
 namespace mozilla {
 
-bool MaybePrefetchMemory(uint8_t* aStart, size_t aNumBytes);
+bool CanPrefetchMemory();
+void PrefetchMemory(uint8_t* aStart, size_t aNumBytes);
 
 }  // namespace mozilla
 
 #endif