Index: gin/v8_initializer.cc |
diff --git a/gin/v8_initializer.cc b/gin/v8_initializer.cc |
index 0568fe77db9300785c3830a0461028d93e89b47c..2ba5106de2c61949702f516e9cbc09f7c07546b3 100644 |
--- a/gin/v8_initializer.cc |
+++ b/gin/v8_initializer.cc |
@@ -27,10 +27,27 @@ namespace gin { |
namespace { |
+// None of these globals are ever freed nor closed. |
base::MemoryMappedFile* g_mapped_natives = nullptr; |
base::MemoryMappedFile* g_mapped_snapshot = nullptr; |
#if defined(V8_USE_EXTERNAL_STARTUP_DATA) |
+ |
+const base::PlatformFile kInvalidPlatformFile = |
+#if defined(OS_WIN) |
+ INVALID_HANDLE_VALUE; |
+#else |
+ -1; |
+#endif |
+ |
+// File handles intentionally never closed. Not using File here because its |
+// Windows implementation guards against two instances owning the same |
+// PlatformFile (which we allow since we know it is never freed). |
+base::PlatformFile g_natives_pf = kInvalidPlatformFile; |
+base::PlatformFile g_snapshot_pf = kInvalidPlatformFile; |
+base::MemoryMappedFile::Region g_natives_region; |
+base::MemoryMappedFile::Region g_snapshot_region; |
+ |
#if !defined(OS_MACOSX) |
const int kV8SnapshotBasePathKey = |
#if defined(OS_ANDROID) |
@@ -65,13 +82,13 @@ void GetV8FilePath(const char* file_name, base::FilePath* path_out) { |
DCHECK(!path_out->empty()); |
} |
-static bool MapV8File(base::File file, |
+static bool MapV8File(base::PlatformFile platform_file, |
base::MemoryMappedFile::Region region, |
base::MemoryMappedFile** mmapped_file_out) { |
DCHECK(*mmapped_file_out == NULL); |
base::MemoryMappedFile* mmapped_file = *mmapped_file_out = |
new base::MemoryMappedFile; |
- if (!mmapped_file->Initialize(file.Pass(), region)) { |
+ if (!mmapped_file->Initialize(base::File(platform_file), region)) { |
delete mmapped_file; |
*mmapped_file_out = NULL; |
return false; |
@@ -80,9 +97,8 @@ static bool MapV8File(base::File file, |
return true; |
} |
-static bool OpenV8File(const base::FilePath& path, |
- int flags, |
- base::File& file) { |
+base::PlatformFile OpenV8File(const char* file_name, |
+ base::MemoryMappedFile::Region* region_out) { |
// Re-try logic here is motivated by http://crbug.com/479537 |
// for A/V on Windows (https://support.microsoft.com/en-us/kb/316609). |
@@ -95,10 +111,16 @@ static bool OpenV8File(const base::FilePath& path, |
MAX_VALUE |
}; |
+ base::FilePath path; |
+ GetV8FilePath(file_name, &path); |
+ |
OpenV8FileResult result = OpenV8FileResult::FAILED_IN_USE; |
+ int flags = base::File::FLAG_OPEN | base::File::FLAG_READ; |
+ base::File file; |
for (int attempt = 0; attempt < kMaxOpenAttempts; attempt++) { |
file.Initialize(path, flags); |
if (file.IsValid()) { |
+ *region_out = base::MemoryMappedFile::Region::kWholeFile; |
if (attempt == 0) { |
result = OpenV8FileResult::OPENED; |
break; |
@@ -118,9 +140,19 @@ static bool OpenV8File(const base::FilePath& path, |
UMA_HISTOGRAM_ENUMERATION("V8.Initializer.OpenV8File.Result", |
result, |
OpenV8FileResult::MAX_VALUE); |
+ return file.TakePlatformFile(); |
+} |
- return result == OpenV8FileResult::OPENED |
- || result == OpenV8FileResult::OPENED_RETRY; |
+void OpenNativesFileIfNecessary() { |
+ if (g_natives_pf == kInvalidPlatformFile) { |
+ g_natives_pf = OpenV8File(kNativesFileName, &g_natives_region); |
+ } |
+} |
+ |
+void OpenSnapshotFileIfNecessary() { |
+ if (g_snapshot_pf == kInvalidPlatformFile) { |
+ g_snapshot_pf = OpenV8File(kSnapshotFileName, &g_snapshot_region); |
+ } |
} |
#if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) |
@@ -163,22 +195,15 @@ enum LoadV8FileResult { |
V8_LOAD_MAX_VALUE |
}; |
-static LoadV8FileResult OpenMapVerify( |
- const char* file_name, |
+static LoadV8FileResult MapVerify(base::PlatformFile platform_file, |
+ const base::MemoryMappedFile::Region& region, |
#if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) |
- const unsigned char* fingerprint, |
+ const unsigned char* fingerprint, |
#endif |
- base::MemoryMappedFile** mmapped_file_out) { |
- base::FilePath path; |
- GetV8FilePath(file_name, &path); |
- |
- base::File file; |
- int flags = base::File::FLAG_OPEN | base::File::FLAG_READ; |
- |
- if (!OpenV8File(path, flags, file)) |
+ base::MemoryMappedFile** mmapped_file_out) { |
+ if (platform_file == kInvalidPlatformFile) |
return V8_LOAD_FAILED_OPEN; |
- if (!MapV8File(file.Pass(), base::MemoryMappedFile::Region::kWholeFile, |
- mmapped_file_out)) |
+ if (!MapV8File(platform_file, region, mmapped_file_out)) |
return V8_LOAD_FAILED_MAP; |
#if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) |
if (!VerifyV8StartupFile(mmapped_file_out, fingerprint)) |
@@ -192,11 +217,14 @@ void V8Initializer::LoadV8Snapshot() { |
if (g_mapped_snapshot) |
return; |
- LoadV8FileResult result = OpenMapVerify(kSnapshotFileName, |
+ OpenSnapshotFileIfNecessary(); |
+ LoadV8FileResult result = MapVerify(g_snapshot_pf, g_snapshot_region, |
#if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) |
- g_snapshot_fingerprint, |
+ g_snapshot_fingerprint, |
#endif |
- &g_mapped_snapshot); |
+ &g_mapped_snapshot); |
+ // V8 can't start up without the source of the natives, but it can |
+ // start up (slower) without the snapshot. |
UMA_HISTOGRAM_ENUMERATION("V8.Initializer.LoadV8Snapshot.Result", result, |
V8_LOAD_MAX_VALUE); |
} |
@@ -205,11 +233,12 @@ void V8Initializer::LoadV8Natives() { |
if (g_mapped_natives) |
return; |
- LoadV8FileResult result = OpenMapVerify(kNativesFileName, |
+ OpenNativesFileIfNecessary(); |
+ LoadV8FileResult result = MapVerify(g_natives_pf, g_natives_region, |
#if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) |
- g_natives_fingerprint, |
+ g_natives_fingerprint, |
#endif |
- &g_mapped_natives); |
+ &g_mapped_natives); |
if (result != V8_LOAD_SUCCESS) { |
LOG(FATAL) << "Couldn't mmap v8 natives data file, status code is " |
<< static_cast<int>(result); |
@@ -223,7 +252,7 @@ void V8Initializer::LoadV8SnapshotFromFD(base::PlatformFile snapshot_pf, |
if (g_mapped_snapshot) |
return; |
- if (snapshot_pf == reinterpret_cast<base::PlatformFile>(-1)) |
+ if (snapshot_pf == kInvalidPlatformFile) |
return; |
base::MemoryMappedFile::Region snapshot_region = |
@@ -234,7 +263,7 @@ void V8Initializer::LoadV8SnapshotFromFD(base::PlatformFile snapshot_pf, |
} |
LoadV8FileResult result = V8_LOAD_SUCCESS; |
- if (!MapV8File(base::File(snapshot_pf), snapshot_region, &g_mapped_snapshot)) |
+ if (!MapV8File(snapshot_pf, snapshot_region, &g_mapped_snapshot)) |
result = V8_LOAD_FAILED_MAP; |
#if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) |
if (!VerifyV8StartupFile(&g_mapped_snapshot, g_snapshot_fingerprint)) |
@@ -251,7 +280,7 @@ void V8Initializer::LoadV8NativesFromFD(base::PlatformFile natives_pf, |
if (g_mapped_natives) |
return; |
- CHECK_NE(natives_pf, reinterpret_cast<base::PlatformFile>(-1)); |
+ CHECK_NE(natives_pf, kInvalidPlatformFile); |
base::MemoryMappedFile::Region natives_region = |
base::MemoryMappedFile::Region::kWholeFile; |
@@ -260,7 +289,7 @@ void V8Initializer::LoadV8NativesFromFD(base::PlatformFile natives_pf, |
base::MemoryMappedFile::Region(natives_offset, natives_size); |
} |
- if (!MapV8File(base::File(natives_pf), natives_region, &g_mapped_natives)) { |
+ if (!MapV8File(natives_pf, natives_region, &g_mapped_natives)) { |
LOG(FATAL) << "Couldn't mmap v8 natives data file"; |
} |
#if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) |
@@ -271,33 +300,21 @@ void V8Initializer::LoadV8NativesFromFD(base::PlatformFile natives_pf, |
} |
// static |
-bool V8Initializer::OpenV8FilesForChildProcesses( |
- base::PlatformFile* natives_fd_out, |
- base::PlatformFile* snapshot_fd_out) { |
- base::FilePath natives_data_path; |
- base::FilePath snapshot_data_path; |
- GetV8FilePath(kNativesFileName, &natives_data_path); |
- GetV8FilePath(kSnapshotFileName, &snapshot_data_path); |
- |
- base::File natives_data_file; |
- base::File snapshot_data_file; |
- int file_flags = base::File::FLAG_OPEN | base::File::FLAG_READ; |
- |
- bool natives_success = |
- OpenV8File(natives_data_path, file_flags, natives_data_file); |
- if (natives_success) { |
- *natives_fd_out = natives_data_file.TakePlatformFile(); |
- } |
- bool snapshot_success = |
- OpenV8File(snapshot_data_path, file_flags, snapshot_data_file); |
- if (snapshot_success) { |
- *snapshot_fd_out = snapshot_data_file.TakePlatformFile(); |
- } |
- // We can start up without the snapshot file, but not without the natives. |
- return natives_success; |
+base::PlatformFile V8Initializer::GetOpenNativesFileForChildProcesses( |
+ base::MemoryMappedFile::Region* region_out) { |
+ OpenNativesFileIfNecessary(); |
+ *region_out = g_natives_region; |
+ return g_natives_pf; |
} |
-#endif // V8_USE_EXTERNAL_STARTUP_DATA |
+// static |
+base::PlatformFile V8Initializer::GetOpenSnapshotFileForChildProcesses( |
+ base::MemoryMappedFile::Region* region_out) { |
+ OpenSnapshotFileIfNecessary(); |
+ *region_out = g_snapshot_region; |
+ return g_snapshot_pf; |
+} |
+#endif // defined(V8_USE_EXTERNAL_STARTUP_DATA) |
// static |
void V8Initializer::Initialize(gin::IsolateHolder::ScriptMode mode) { |