OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "gin/v8_initializer.h" | 5 #include "gin/v8_initializer.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <memory> | 10 #include <memory> |
11 | 11 |
12 #include "base/debug/alias.h" | 12 #include "base/debug/alias.h" |
13 #include "base/debug/crash_logging.h" | 13 #include "base/debug/crash_logging.h" |
14 #include "base/feature_list.h" | 14 #include "base/feature_list.h" |
15 #include "base/files/file.h" | 15 #include "base/files/file.h" |
16 #include "base/files/file_path.h" | 16 #include "base/files/file_path.h" |
17 #include "base/files/memory_mapped_file.h" | 17 #include "base/files/memory_mapped_file.h" |
18 #include "base/lazy_instance.h" | 18 #include "base/lazy_instance.h" |
19 #include "base/logging.h" | 19 #include "base/logging.h" |
20 #include "base/metrics/histogram_macros.h" | 20 #include "base/metrics/histogram_macros.h" |
21 #include "base/path_service.h" | |
21 #include "base/rand_util.h" | 22 #include "base/rand_util.h" |
22 #include "base/strings/sys_string_conversions.h" | 23 #include "base/strings/sys_string_conversions.h" |
23 #include "base/sys_info.h" | 24 #include "base/sys_info.h" |
24 #include "base/threading/platform_thread.h" | 25 #include "base/threading/platform_thread.h" |
25 #include "base/time/time.h" | 26 #include "base/time/time.h" |
26 | 27 |
27 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) | 28 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) |
28 #if defined(OS_ANDROID) | 29 #if defined(OS_ANDROID) |
29 #include "base/android/apk_assets.h" | 30 #include "base/android/apk_assets.h" |
31 #elif defined(OS_MACOSX) | |
32 #include "base/mac/foundation_util.h" | |
30 #endif | 33 #endif |
31 #if defined(OS_MACOSX) | |
32 #include "base/mac/foundation_util.h" | |
33 #endif // OS_MACOSX | |
34 #include "base/path_service.h" | |
35 #endif // V8_USE_EXTERNAL_STARTUP_DATA | 34 #endif // V8_USE_EXTERNAL_STARTUP_DATA |
36 | 35 |
37 namespace gin { | 36 namespace gin { |
38 | 37 |
39 namespace { | 38 namespace { |
40 | 39 |
41 // None of these globals are ever freed nor closed. | 40 // None of these globals are ever freed nor closed. |
42 base::MemoryMappedFile* g_mapped_natives = nullptr; | 41 base::MemoryMappedFile* g_mapped_natives = nullptr; |
43 base::MemoryMappedFile* g_mapped_snapshot = nullptr; | 42 base::MemoryMappedFile* g_mapped_snapshot = nullptr; |
43 base::MemoryMappedFile* g_mapped_blink_v8_snapshot = nullptr; | |
44 | 44 |
45 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) | 45 const char kBlinkV8SnapshotFileName[] = "blink_v8_snapshot.bin"; |
46 | 46 |
47 // File handles intentionally never closed. Not using File here because its | 47 // File handles intentionally never closed. Not using File here because its |
48 // Windows implementation guards against two instances owning the same | 48 // Windows implementation guards against two instances owning the same |
49 // PlatformFile (which we allow since we know it is never freed). | 49 // PlatformFile (which we allow since we know it is never freed). |
50 typedef std::map<const char*, | 50 using OpenedFileMap = |
51 std::pair<base::PlatformFile, base::MemoryMappedFile::Region>> | 51 std::map<const char*, |
52 OpenedFileMap; | 52 std::pair<base::PlatformFile, base::MemoryMappedFile::Region>>; |
53 static base::LazyInstance<OpenedFileMap>::Leaky g_opened_files = | 53 base::LazyInstance<OpenedFileMap>::Leaky g_opened_files = |
54 LAZY_INSTANCE_INITIALIZER; | 54 LAZY_INSTANCE_INITIALIZER; |
55 | 55 |
56 OpenedFileMap::mapped_type& GetOpenedFile(const char* file) { | 56 OpenedFileMap::mapped_type& GetOpenedFile(const char* file) { |
57 OpenedFileMap& opened_files(g_opened_files.Get()); | 57 OpenedFileMap& opened_files(g_opened_files.Get()); |
58 if (opened_files.find(file) == opened_files.end()) { | 58 if (opened_files.find(file) == opened_files.end()) { |
59 opened_files[file] = std::make_pair(base::kInvalidPlatformFile, | 59 opened_files[file] = std::make_pair(base::kInvalidPlatformFile, |
60 base::MemoryMappedFile::Region()); | 60 base::MemoryMappedFile::Region()); |
61 } | 61 } |
62 return opened_files[file]; | 62 return opened_files[file]; |
63 } | 63 } |
64 | 64 |
65 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) | |
66 | |
65 const char kNativesFileName[] = "natives_blob.bin"; | 67 const char kNativesFileName[] = "natives_blob.bin"; |
66 | 68 |
67 #if defined(OS_ANDROID) | 69 #if defined(OS_ANDROID) |
68 const char kSnapshotFileName64[] = "snapshot_blob_64.bin"; | 70 const char kSnapshotFileName64[] = "snapshot_blob_64.bin"; |
69 const char kSnapshotFileName32[] = "snapshot_blob_32.bin"; | 71 const char kSnapshotFileName32[] = "snapshot_blob_32.bin"; |
70 | 72 |
71 #if defined(__LP64__) | 73 #if defined(__LP64__) |
72 #define kSnapshotFileName kSnapshotFileName64 | 74 #define kSnapshotFileName kSnapshotFileName64 |
73 #else | 75 #else |
74 #define kSnapshotFileName kSnapshotFileName32 | 76 #define kSnapshotFileName kSnapshotFileName32 |
75 #endif | 77 #endif |
76 | 78 |
77 #else // defined(OS_ANDROID) | 79 #else // defined(OS_ANDROID) |
78 const char kSnapshotFileName[] = "snapshot_blob.bin"; | 80 const char kSnapshotFileName[] = "snapshot_blob.bin"; |
79 #endif // defined(OS_ANDROID) | 81 #endif // defined(OS_ANDROID) |
80 | 82 |
83 #endif // defined(V8_USE_EXTERNAL_STATUP_DATA) | |
84 | |
81 void GetV8FilePath(const char* file_name, base::FilePath* path_out) { | 85 void GetV8FilePath(const char* file_name, base::FilePath* path_out) { |
82 #if !defined(OS_MACOSX) | 86 #if !defined(OS_MACOSX) |
83 base::FilePath data_path; | 87 base::FilePath data_path; |
84 #if defined(OS_ANDROID) | 88 #if defined(OS_ANDROID) |
85 // This is the path within the .apk. | 89 // This is the path within the .apk. |
86 data_path = base::FilePath(FILE_PATH_LITERAL("assets")); | 90 data_path = base::FilePath(FILE_PATH_LITERAL("assets")); |
87 #elif defined(OS_POSIX) | 91 #elif defined(OS_POSIX) |
88 PathService::Get(base::DIR_EXE, &data_path); | 92 PathService::Get(base::DIR_EXE, &data_path); |
89 #elif defined(OS_WIN) | 93 #elif defined(OS_WIN) |
90 PathService::Get(base::DIR_MODULE, &data_path); | 94 PathService::Get(base::DIR_MODULE, &data_path); |
91 #endif | 95 #endif |
92 DCHECK(!data_path.empty()); | 96 DCHECK(!data_path.empty()); |
93 | 97 |
94 *path_out = data_path.AppendASCII(file_name); | 98 *path_out = data_path.AppendASCII(file_name); |
95 #else // !defined(OS_MACOSX) | 99 #else // !defined(OS_MACOSX) |
96 base::ScopedCFTypeRef<CFStringRef> natives_file_name( | 100 base::ScopedCFTypeRef<CFStringRef> natives_file_name( |
97 base::SysUTF8ToCFStringRef(file_name)); | 101 base::SysUTF8ToCFStringRef(file_name)); |
98 *path_out = base::mac::PathForFrameworkBundleResource(natives_file_name); | 102 *path_out = base::mac::PathForFrameworkBundleResource(natives_file_name); |
99 #endif // !defined(OS_MACOSX) | 103 #endif // !defined(OS_MACOSX) |
100 DCHECK(!path_out->empty()); | |
101 } | 104 } |
102 | 105 |
103 static bool MapV8File(base::PlatformFile platform_file, | 106 bool MapV8File(base::PlatformFile platform_file, |
104 base::MemoryMappedFile::Region region, | 107 base::MemoryMappedFile::Region region, |
105 base::MemoryMappedFile** mmapped_file_out) { | 108 base::MemoryMappedFile** mmapped_file_out) { |
106 DCHECK(*mmapped_file_out == NULL); | 109 DCHECK(*mmapped_file_out == NULL); |
107 std::unique_ptr<base::MemoryMappedFile> mmapped_file( | 110 std::unique_ptr<base::MemoryMappedFile> mmapped_file( |
108 new base::MemoryMappedFile()); | 111 new base::MemoryMappedFile()); |
109 if (mmapped_file->Initialize(base::File(platform_file), region)) { | 112 if (mmapped_file->Initialize(base::File(platform_file), region)) { |
110 *mmapped_file_out = mmapped_file.release(); | 113 *mmapped_file_out = mmapped_file.release(); |
111 return true; | 114 return true; |
112 } | 115 } |
113 return false; | 116 return false; |
114 } | 117 } |
115 | 118 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
173 } | 176 } |
174 } | 177 } |
175 #endif // defined(OS_ANDROID) | 178 #endif // defined(OS_ANDROID) |
176 | 179 |
177 UMA_HISTOGRAM_ENUMERATION("V8.Initializer.OpenV8File.Result", | 180 UMA_HISTOGRAM_ENUMERATION("V8.Initializer.OpenV8File.Result", |
178 result, | 181 result, |
179 OpenV8FileResult::MAX_VALUE); | 182 OpenV8FileResult::MAX_VALUE); |
180 return file.TakePlatformFile(); | 183 return file.TakePlatformFile(); |
181 } | 184 } |
182 | 185 |
183 static const OpenedFileMap::mapped_type OpenFileIfNecessary( | 186 const OpenedFileMap::mapped_type OpenFileIfNecessary(const char* file_name) { |
184 const char* file_name) { | |
185 OpenedFileMap::mapped_type& opened = GetOpenedFile(file_name); | 187 OpenedFileMap::mapped_type& opened = GetOpenedFile(file_name); |
186 if (opened.first == base::kInvalidPlatformFile) { | 188 if (opened.first == base::kInvalidPlatformFile) { |
187 opened.first = OpenV8File(file_name, &opened.second); | 189 opened.first = OpenV8File(file_name, &opened.second); |
188 } | 190 } |
189 return opened; | 191 return opened; |
190 } | 192 } |
191 | 193 |
192 #endif // V8_USE_EXTERNAL_STARTUP_DATA | |
193 | |
194 bool GenerateEntropy(unsigned char* buffer, size_t amount) { | 194 bool GenerateEntropy(unsigned char* buffer, size_t amount) { |
195 base::RandBytes(buffer, amount); | 195 base::RandBytes(buffer, amount); |
196 return true; | 196 return true; |
197 } | 197 } |
198 | 198 |
199 } // namespace | |
200 | |
201 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) | |
202 | |
203 namespace { | |
204 | |
205 enum LoadV8FileResult { | 199 enum LoadV8FileResult { |
206 V8_LOAD_SUCCESS = 0, | 200 V8_LOAD_SUCCESS = 0, |
207 V8_LOAD_FAILED_OPEN, | 201 V8_LOAD_FAILED_OPEN, |
208 V8_LOAD_FAILED_MAP, | 202 V8_LOAD_FAILED_MAP, |
209 V8_LOAD_FAILED_VERIFY, // Deprecated. | 203 V8_LOAD_FAILED_VERIFY, // Deprecated. |
210 V8_LOAD_MAX_VALUE | 204 V8_LOAD_MAX_VALUE |
211 }; | 205 }; |
212 | 206 |
213 static LoadV8FileResult MapOpenedFile( | 207 LoadV8FileResult MapOpenedFile(const OpenedFileMap::mapped_type& file_region, |
214 const OpenedFileMap::mapped_type& file_region, | 208 base::MemoryMappedFile** mmapped_file_out) { |
215 base::MemoryMappedFile** mmapped_file_out) { | |
216 if (file_region.first == base::kInvalidPlatformFile) | 209 if (file_region.first == base::kInvalidPlatformFile) |
217 return V8_LOAD_FAILED_OPEN; | 210 return V8_LOAD_FAILED_OPEN; |
218 if (!MapV8File(file_region.first, file_region.second, mmapped_file_out)) | 211 if (!MapV8File(file_region.first, file_region.second, mmapped_file_out)) |
219 return V8_LOAD_FAILED_MAP; | 212 return V8_LOAD_FAILED_MAP; |
220 return V8_LOAD_SUCCESS; | 213 return V8_LOAD_SUCCESS; |
221 } | 214 } |
222 | 215 |
223 } // namespace | 216 } // namespace |
224 | 217 |
218 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) | |
219 | |
225 // static | 220 // static |
226 void V8Initializer::LoadV8Snapshot() { | 221 void V8Initializer::LoadV8Snapshot() { |
227 if (g_mapped_snapshot) | 222 if (g_mapped_snapshot) |
228 return; | 223 return; |
229 | 224 |
230 OpenFileIfNecessary(kSnapshotFileName); | 225 OpenFileIfNecessary(kSnapshotFileName); |
231 LoadV8FileResult result = MapOpenedFile(GetOpenedFile(kSnapshotFileName), | 226 LoadV8FileResult result = MapOpenedFile(GetOpenedFile(kSnapshotFileName), |
232 &g_mapped_snapshot); | 227 &g_mapped_snapshot); |
233 // V8 can't start up without the source of the natives, but it can | 228 // V8 can't start up without the source of the natives, but it can |
234 // start up (slower) without the snapshot. | 229 // start up (slower) without the snapshot. |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
363 static const char flag[] = "--experimental_extras"; | 358 static const char flag[] = "--experimental_extras"; |
364 v8::V8::SetFlagsFromString(flag, sizeof(flag) - 1); | 359 v8::V8::SetFlagsFromString(flag, sizeof(flag) - 1); |
365 } | 360 } |
366 | 361 |
367 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) | 362 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) |
368 v8::StartupData natives; | 363 v8::StartupData natives; |
369 natives.data = reinterpret_cast<const char*>(g_mapped_natives->data()); | 364 natives.data = reinterpret_cast<const char*>(g_mapped_natives->data()); |
370 natives.raw_size = static_cast<int>(g_mapped_natives->length()); | 365 natives.raw_size = static_cast<int>(g_mapped_natives->length()); |
371 v8::V8::SetNativesDataBlob(&natives); | 366 v8::V8::SetNativesDataBlob(&natives); |
372 | 367 |
373 if (g_mapped_snapshot != NULL) { | 368 if (g_mapped_snapshot) { |
374 v8::StartupData snapshot; | 369 v8::StartupData snapshot; |
375 snapshot.data = reinterpret_cast<const char*>(g_mapped_snapshot->data()); | 370 snapshot.data = reinterpret_cast<const char*>(g_mapped_snapshot->data()); |
376 snapshot.raw_size = static_cast<int>(g_mapped_snapshot->length()); | 371 snapshot.raw_size = static_cast<int>(g_mapped_snapshot->length()); |
377 v8::V8::SetSnapshotDataBlob(&snapshot); | 372 v8::V8::SetSnapshotDataBlob(&snapshot); |
378 } | 373 } |
379 #endif // V8_USE_EXTERNAL_STARTUP_DATA | 374 #endif // V8_USE_EXTERNAL_STARTUP_DATA |
380 | 375 |
381 v8::V8::SetEntropySource(&GenerateEntropy); | 376 v8::V8::SetEntropySource(&GenerateEntropy); |
382 v8::V8::Initialize(); | 377 v8::V8::Initialize(); |
383 | 378 |
(...skipping 15 matching lines...) Expand all Loading... | |
399 if (g_mapped_snapshot) { | 394 if (g_mapped_snapshot) { |
400 *snapshot_data_out = | 395 *snapshot_data_out = |
401 reinterpret_cast<const char*>(g_mapped_snapshot->data()); | 396 reinterpret_cast<const char*>(g_mapped_snapshot->data()); |
402 *snapshot_size_out = static_cast<int>(g_mapped_snapshot->length()); | 397 *snapshot_size_out = static_cast<int>(g_mapped_snapshot->length()); |
403 } else { | 398 } else { |
404 *snapshot_data_out = NULL; | 399 *snapshot_data_out = NULL; |
405 *snapshot_size_out = 0; | 400 *snapshot_size_out = 0; |
406 } | 401 } |
407 } | 402 } |
408 | 403 |
404 // static | |
405 void V8Initializer::LoadBlinkV8Snapshot() { | |
406 if (g_mapped_blink_v8_snapshot) | |
407 return; | |
408 #if defined(CHROME_MULTIPLE_DLL_BROWSER) | |
Yuki
2017/06/20 14:20:10
Does this mean that, if we're building with is_com
peria
2017/06/21 07:19:15
This #if disables snasphot feature for non-compone
| |
409 return; | |
410 #endif | |
411 | |
412 OpenFileIfNecessary(kBlinkV8SnapshotFileName); | |
413 LoadV8FileResult result = MapOpenedFile( | |
414 GetOpenedFile(kBlinkV8SnapshotFileName), &g_mapped_blink_v8_snapshot); | |
415 | |
416 // The second condition is a workaround for unittests without resource | |
417 // bandles. | |
418 // TODO(peria): Remove the second condition in DCHECK() | |
419 DCHECK(g_mapped_blink_v8_snapshot || result == V8_LOAD_FAILED_OPEN); | |
420 } | |
421 | |
422 // static | |
423 void V8Initializer::LoadBlinkV8SnapshotFromFD(base::PlatformFile snapshot_pf, | |
424 int64_t snapshot_offset, | |
425 int64_t snapshot_size) { | |
426 if (g_mapped_blink_v8_snapshot) | |
427 return; | |
428 CHECK_NE(base::kInvalidPlatformFile, snapshot_pf); | |
429 | |
430 base::MemoryMappedFile::Region snapshot_region = | |
431 base::MemoryMappedFile::Region::kWholeFile; | |
432 if (snapshot_size != 0 || snapshot_offset != 0) { | |
433 snapshot_region.offset = snapshot_offset; | |
434 snapshot_region.size = snapshot_size; | |
435 } | |
436 | |
437 if (MapV8File(snapshot_pf, snapshot_region, &g_mapped_blink_v8_snapshot)) { | |
438 g_opened_files.Get()[kBlinkV8SnapshotFileName] = | |
439 std::make_pair(snapshot_pf, snapshot_region); | |
440 } | |
441 } | |
442 | |
443 // static | |
444 void V8Initializer::GetBlinkV8SnapshotData(const char** snapshot_data_out, | |
445 int* snapshot_size_out) { | |
446 if (g_mapped_blink_v8_snapshot) { | |
447 *snapshot_data_out = | |
448 reinterpret_cast<const char*>(g_mapped_blink_v8_snapshot->data()); | |
449 *snapshot_size_out = static_cast<int>(g_mapped_blink_v8_snapshot->length()); | |
450 } else { | |
451 *snapshot_data_out = nullptr; | |
452 *snapshot_size_out = 0; | |
453 } | |
454 } | |
455 | |
409 } // namespace gin | 456 } // namespace gin |
OLD | NEW |