Chromium Code Reviews| Index: gin/v8_initializer.cc |
| diff --git a/gin/v8_initializer.cc b/gin/v8_initializer.cc |
| index 0568fe77db9300785c3830a0461028d93e89b47c..af44164b325257f7d280133fafa6ad58c3a3aaeb 100644 |
| --- a/gin/v8_initializer.cc |
| +++ b/gin/v8_initializer.cc |
| @@ -27,10 +27,32 @@ 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; |
| +// Jump through hoops here to avoid introducing static initializers. |
| +char g_natives_region_data[sizeof(base::MemoryMappedFile::Region)] = {0}; |
| +char g_snapshot_region_data[sizeof(base::MemoryMappedFile::Region)] = {0}; |
| +base::MemoryMappedFile::Region& g_natives_region = |
| + *reinterpret_cast<base::MemoryMappedFile::Region*>(g_natives_region_data); |
| +base::MemoryMappedFile::Region& g_snapshot_region = |
| + *reinterpret_cast<base::MemoryMappedFile::Region*>(g_snapshot_region_data); |
|
rmcilroy
2015/06/17 08:00:50
This seems a bit hacky personally. I would prefer
|
| + |
| #if !defined(OS_MACOSX) |
| const int kV8SnapshotBasePathKey = |
| #if defined(OS_ANDROID) |
| @@ -65,13 +87,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 +102,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 +116,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 +145,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 +200,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 +222,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 +238,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 +257,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 +268,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 +285,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 +294,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 +305,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) { |