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> |
(...skipping 15 matching lines...) Expand all Loading... | |
26 #include "crypto/sha2.h" | 26 #include "crypto/sha2.h" |
27 #include "gin/public/gin_features.h" | 27 #include "gin/public/gin_features.h" |
28 | 28 |
29 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) | 29 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) |
30 #if defined(OS_ANDROID) | 30 #if defined(OS_ANDROID) |
31 #include "base/android/apk_assets.h" | 31 #include "base/android/apk_assets.h" |
32 #endif | 32 #endif |
33 #if defined(OS_MACOSX) | 33 #if defined(OS_MACOSX) |
34 #include "base/mac/foundation_util.h" | 34 #include "base/mac/foundation_util.h" |
35 #endif // OS_MACOSX | 35 #endif // OS_MACOSX |
36 #endif // V8_USE_EXTERNAL_STARTUP_DATA | |
36 #include "base/path_service.h" | 37 #include "base/path_service.h" |
Yuki
2017/05/30 14:35:56
Should this #include be moved up?
peria
2017/06/01 08:33:32
Done.
| |
37 #endif // V8_USE_EXTERNAL_STARTUP_DATA | |
38 | 38 |
39 namespace gin { | 39 namespace gin { |
40 | 40 |
41 namespace { | 41 namespace { |
42 | 42 |
43 // None of these globals are ever freed nor closed. | 43 // None of these globals are ever freed nor closed. |
44 base::MemoryMappedFile* g_mapped_natives = nullptr; | 44 base::MemoryMappedFile* g_mapped_natives = nullptr; |
45 base::MemoryMappedFile* g_mapped_snapshot = nullptr; | 45 base::MemoryMappedFile* g_mapped_snapshot = nullptr; |
46 base::MemoryMappedFile* g_mapped_context = nullptr; | |
46 | 47 |
47 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) | 48 const char kV8ContextFileName[] = "context_blob.bin"; |
48 | 49 |
49 // File handles intentionally never closed. Not using File here because its | 50 // File handles intentionally never closed. Not using File here because its |
50 // Windows implementation guards against two instances owning the same | 51 // Windows implementation guards against two instances owning the same |
51 // PlatformFile (which we allow since we know it is never freed). | 52 // PlatformFile (which we allow since we know it is never freed). |
52 typedef std::map<const char*, | 53 using OpenedFileMap = |
53 std::pair<base::PlatformFile, base::MemoryMappedFile::Region>> | 54 std::map<const char*, |
54 OpenedFileMap; | 55 std::pair<base::PlatformFile, base::MemoryMappedFile::Region>>; |
55 static base::LazyInstance<OpenedFileMap>::Leaky g_opened_files = | 56 base::LazyInstance<OpenedFileMap>::Leaky g_opened_files = |
56 LAZY_INSTANCE_INITIALIZER; | 57 LAZY_INSTANCE_INITIALIZER; |
57 | 58 |
58 OpenedFileMap::mapped_type& GetOpenedFile(const char* file) { | 59 OpenedFileMap::mapped_type& GetOpenedFile(const char* file) { |
59 OpenedFileMap& opened_files(g_opened_files.Get()); | 60 OpenedFileMap& opened_files(g_opened_files.Get()); |
60 if (opened_files.find(file) == opened_files.end()) { | 61 if (opened_files.find(file) == opened_files.end()) { |
61 opened_files[file] = std::make_pair(base::kInvalidPlatformFile, | 62 opened_files[file] = std::make_pair(base::kInvalidPlatformFile, |
62 base::MemoryMappedFile::Region()); | 63 base::MemoryMappedFile::Region()); |
63 } | 64 } |
64 return opened_files[file]; | 65 return opened_files[file]; |
65 } | 66 } |
66 | 67 |
68 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) | |
69 | |
67 const char kNativesFileName[] = "natives_blob.bin"; | 70 const char kNativesFileName[] = "natives_blob.bin"; |
68 | 71 |
69 #if defined(OS_ANDROID) | 72 #if defined(OS_ANDROID) |
70 const char kSnapshotFileName64[] = "snapshot_blob_64.bin"; | 73 const char kSnapshotFileName64[] = "snapshot_blob_64.bin"; |
71 const char kSnapshotFileName32[] = "snapshot_blob_32.bin"; | 74 const char kSnapshotFileName32[] = "snapshot_blob_32.bin"; |
72 | 75 |
73 #if defined(__LP64__) | 76 #if defined(__LP64__) |
74 #define kSnapshotFileName kSnapshotFileName64 | 77 #define kSnapshotFileName kSnapshotFileName64 |
75 #else | 78 #else |
76 #define kSnapshotFileName kSnapshotFileName32 | 79 #define kSnapshotFileName kSnapshotFileName32 |
77 #endif | 80 #endif |
78 | 81 |
79 #else // defined(OS_ANDROID) | 82 #else // defined(OS_ANDROID) |
80 const char kSnapshotFileName[] = "snapshot_blob.bin"; | 83 const char kSnapshotFileName[] = "snapshot_blob.bin"; |
81 #endif // defined(OS_ANDROID) | 84 #endif // defined(OS_ANDROID) |
82 | 85 |
86 #endif // defined(V8_USE_EXTERNAL_STATUP_DATA) | |
87 | |
83 void GetV8FilePath(const char* file_name, base::FilePath* path_out) { | 88 void GetV8FilePath(const char* file_name, base::FilePath* path_out) { |
84 #if !defined(OS_MACOSX) | 89 #if !defined(OS_MACOSX) |
85 base::FilePath data_path; | 90 base::FilePath data_path; |
86 #if defined(OS_ANDROID) | 91 #if defined(OS_ANDROID) |
87 // This is the path within the .apk. | 92 // This is the path within the .apk. |
88 data_path = base::FilePath(FILE_PATH_LITERAL("assets")); | 93 data_path = base::FilePath(FILE_PATH_LITERAL("assets")); |
89 #elif defined(OS_POSIX) | 94 #elif defined(OS_POSIX) |
90 PathService::Get(base::DIR_EXE, &data_path); | 95 PathService::Get(base::DIR_EXE, &data_path); |
91 #elif defined(OS_WIN) | 96 #elif defined(OS_WIN) |
92 PathService::Get(base::DIR_MODULE, &data_path); | 97 PathService::Get(base::DIR_MODULE, &data_path); |
93 #endif | 98 #endif |
94 DCHECK(!data_path.empty()); | 99 DCHECK(!data_path.empty()); |
95 | 100 |
96 *path_out = data_path.AppendASCII(file_name); | 101 *path_out = data_path.AppendASCII(file_name); |
97 #else // !defined(OS_MACOSX) | 102 #else // !defined(OS_MACOSX) |
98 base::ScopedCFTypeRef<CFStringRef> natives_file_name( | 103 base::ScopedCFTypeRef<CFStringRef> natives_file_name( |
99 base::SysUTF8ToCFStringRef(file_name)); | 104 base::SysUTF8ToCFStringRef(file_name)); |
100 *path_out = base::mac::PathForFrameworkBundleResource(natives_file_name); | 105 *path_out = base::mac::PathForFrameworkBundleResource(natives_file_name); |
101 #endif // !defined(OS_MACOSX) | 106 #endif // !defined(OS_MACOSX) |
102 DCHECK(!path_out->empty()); | |
103 } | 107 } |
104 | 108 |
105 static bool MapV8File(base::PlatformFile platform_file, | 109 bool MapV8File(base::PlatformFile platform_file, |
106 base::MemoryMappedFile::Region region, | 110 base::MemoryMappedFile::Region region, |
107 base::MemoryMappedFile** mmapped_file_out) { | 111 base::MemoryMappedFile** mmapped_file_out) { |
108 DCHECK(*mmapped_file_out == NULL); | 112 DCHECK(*mmapped_file_out == NULL); |
109 std::unique_ptr<base::MemoryMappedFile> mmapped_file( | 113 std::unique_ptr<base::MemoryMappedFile> mmapped_file( |
110 new base::MemoryMappedFile()); | 114 new base::MemoryMappedFile()); |
111 if (mmapped_file->Initialize(base::File(platform_file), region)) { | 115 if (mmapped_file->Initialize(base::File(platform_file), region)) { |
112 *mmapped_file_out = mmapped_file.release(); | 116 *mmapped_file_out = mmapped_file.release(); |
113 return true; | 117 return true; |
114 } | 118 } |
115 return false; | 119 return false; |
116 } | 120 } |
117 | 121 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
175 } | 179 } |
176 } | 180 } |
177 #endif // defined(OS_ANDROID) | 181 #endif // defined(OS_ANDROID) |
178 | 182 |
179 UMA_HISTOGRAM_ENUMERATION("V8.Initializer.OpenV8File.Result", | 183 UMA_HISTOGRAM_ENUMERATION("V8.Initializer.OpenV8File.Result", |
180 result, | 184 result, |
181 OpenV8FileResult::MAX_VALUE); | 185 OpenV8FileResult::MAX_VALUE); |
182 return file.TakePlatformFile(); | 186 return file.TakePlatformFile(); |
183 } | 187 } |
184 | 188 |
185 static const OpenedFileMap::mapped_type OpenFileIfNecessary( | 189 const OpenedFileMap::mapped_type OpenFileIfNecessary(const char* file_name) { |
186 const char* file_name) { | |
187 OpenedFileMap::mapped_type& opened = GetOpenedFile(file_name); | 190 OpenedFileMap::mapped_type& opened = GetOpenedFile(file_name); |
188 if (opened.first == base::kInvalidPlatformFile) { | 191 if (opened.first == base::kInvalidPlatformFile) { |
189 opened.first = OpenV8File(file_name, &opened.second); | 192 opened.first = OpenV8File(file_name, &opened.second); |
190 } | 193 } |
191 return opened; | 194 return opened; |
192 } | 195 } |
193 | 196 |
194 #endif // V8_USE_EXTERNAL_STARTUP_DATA | |
195 | |
196 bool GenerateEntropy(unsigned char* buffer, size_t amount) { | 197 bool GenerateEntropy(unsigned char* buffer, size_t amount) { |
197 base::RandBytes(buffer, amount); | 198 base::RandBytes(buffer, amount); |
198 return true; | 199 return true; |
199 } | 200 } |
200 | 201 |
201 } // namespace | |
202 | |
203 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) | |
204 | |
205 namespace { | |
206 | |
207 enum LoadV8FileResult { | 202 enum LoadV8FileResult { |
208 V8_LOAD_SUCCESS = 0, | 203 V8_LOAD_SUCCESS = 0, |
209 V8_LOAD_FAILED_OPEN, | 204 V8_LOAD_FAILED_OPEN, |
210 V8_LOAD_FAILED_MAP, | 205 V8_LOAD_FAILED_MAP, |
211 V8_LOAD_FAILED_VERIFY, // Deprecated. | 206 V8_LOAD_FAILED_VERIFY, // Deprecated. |
212 V8_LOAD_MAX_VALUE | 207 V8_LOAD_MAX_VALUE |
213 }; | 208 }; |
214 | 209 |
215 static LoadV8FileResult MapOpenedFile( | 210 LoadV8FileResult MapOpenedFile(const OpenedFileMap::mapped_type& file_region, |
216 const OpenedFileMap::mapped_type& file_region, | 211 base::MemoryMappedFile** mmapped_file_out) { |
217 base::MemoryMappedFile** mmapped_file_out) { | |
218 if (file_region.first == base::kInvalidPlatformFile) | 212 if (file_region.first == base::kInvalidPlatformFile) |
219 return V8_LOAD_FAILED_OPEN; | 213 return V8_LOAD_FAILED_OPEN; |
220 if (!MapV8File(file_region.first, file_region.second, mmapped_file_out)) | 214 if (!MapV8File(file_region.first, file_region.second, mmapped_file_out)) |
221 return V8_LOAD_FAILED_MAP; | 215 return V8_LOAD_FAILED_MAP; |
222 return V8_LOAD_SUCCESS; | 216 return V8_LOAD_SUCCESS; |
223 } | 217 } |
224 | 218 |
225 } // namespace | 219 } // namespace |
226 | 220 |
221 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) | |
222 | |
227 // static | 223 // static |
228 void V8Initializer::LoadV8Snapshot() { | 224 void V8Initializer::LoadV8Snapshot() { |
229 if (g_mapped_snapshot) | 225 if (g_mapped_snapshot) |
230 return; | 226 return; |
231 | 227 |
232 OpenFileIfNecessary(kSnapshotFileName); | 228 OpenFileIfNecessary(kSnapshotFileName); |
233 LoadV8FileResult result = MapOpenedFile(GetOpenedFile(kSnapshotFileName), | 229 LoadV8FileResult result = MapOpenedFile(GetOpenedFile(kSnapshotFileName), |
234 &g_mapped_snapshot); | 230 &g_mapped_snapshot); |
235 // V8 can't start up without the source of the natives, but it can | 231 // V8 can't start up without the source of the natives, but it can |
236 // start up (slower) without the snapshot. | 232 // start up (slower) without the snapshot. |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
381 base::debug::SetCrashKeyValue(kIgnitionEnabledKey, | 377 base::debug::SetCrashKeyValue(kIgnitionEnabledKey, |
382 ignition_enabled_crash_key); | 378 ignition_enabled_crash_key); |
383 | 379 |
384 | 380 |
385 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) | 381 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) |
386 v8::StartupData natives; | 382 v8::StartupData natives; |
387 natives.data = reinterpret_cast<const char*>(g_mapped_natives->data()); | 383 natives.data = reinterpret_cast<const char*>(g_mapped_natives->data()); |
388 natives.raw_size = static_cast<int>(g_mapped_natives->length()); | 384 natives.raw_size = static_cast<int>(g_mapped_natives->length()); |
389 v8::V8::SetNativesDataBlob(&natives); | 385 v8::V8::SetNativesDataBlob(&natives); |
390 | 386 |
391 if (g_mapped_snapshot != NULL) { | 387 if (g_mapped_snapshot) { |
392 v8::StartupData snapshot; | 388 v8::StartupData snapshot; |
393 snapshot.data = reinterpret_cast<const char*>(g_mapped_snapshot->data()); | 389 snapshot.data = reinterpret_cast<const char*>(g_mapped_snapshot->data()); |
394 snapshot.raw_size = static_cast<int>(g_mapped_snapshot->length()); | 390 snapshot.raw_size = static_cast<int>(g_mapped_snapshot->length()); |
395 v8::V8::SetSnapshotDataBlob(&snapshot); | 391 v8::V8::SetSnapshotDataBlob(&snapshot); |
396 } | 392 } |
397 #endif // V8_USE_EXTERNAL_STARTUP_DATA | 393 #endif // V8_USE_EXTERNAL_STARTUP_DATA |
398 | 394 |
399 v8::V8::SetEntropySource(&GenerateEntropy); | 395 v8::V8::SetEntropySource(&GenerateEntropy); |
400 v8::V8::Initialize(); | 396 v8::V8::Initialize(); |
401 | 397 |
(...skipping 15 matching lines...) Expand all Loading... | |
417 if (g_mapped_snapshot) { | 413 if (g_mapped_snapshot) { |
418 *snapshot_data_out = | 414 *snapshot_data_out = |
419 reinterpret_cast<const char*>(g_mapped_snapshot->data()); | 415 reinterpret_cast<const char*>(g_mapped_snapshot->data()); |
420 *snapshot_size_out = static_cast<int>(g_mapped_snapshot->length()); | 416 *snapshot_size_out = static_cast<int>(g_mapped_snapshot->length()); |
421 } else { | 417 } else { |
422 *snapshot_data_out = NULL; | 418 *snapshot_data_out = NULL; |
423 *snapshot_size_out = 0; | 419 *snapshot_size_out = 0; |
424 } | 420 } |
425 } | 421 } |
426 | 422 |
423 // static | |
424 void V8Initializer::LoadV8Context() { | |
425 if (g_mapped_context) | |
426 return; | |
427 | |
428 OpenFileIfNecessary(kV8ContextFileName); | |
429 MapOpenedFile(GetOpenedFile(kV8ContextFileName), &g_mapped_context); | |
430 } | |
431 | |
432 // static | |
433 void V8Initializer::LoadV8ContextFromFD(base::PlatformFile snapshot_pf, | |
434 int64_t snapshot_offset, | |
435 int64_t snapshot_size) { | |
436 if (g_mapped_context) | |
437 return; | |
438 CHECK_NE(base::kInvalidPlatformFile, snapshot_pf); | |
439 | |
440 base::MemoryMappedFile::Region snapshot_region = | |
441 base::MemoryMappedFile::Region::kWholeFile; | |
442 if (snapshot_size != 0 || snapshot_offset != 0) { | |
443 snapshot_region.offset = snapshot_offset; | |
444 snapshot_region.size = snapshot_size; | |
445 } | |
446 | |
447 if (MapV8File(snapshot_pf, snapshot_region, &g_mapped_context)) { | |
448 g_opened_files.Get()[kV8ContextFileName] = | |
449 std::make_pair(snapshot_pf, snapshot_region); | |
450 } | |
451 } | |
452 | |
453 // static | |
454 void V8Initializer::GetV8ContextData(const char** snapshot_data_out, | |
455 int* snapshot_size_out) { | |
456 if (g_mapped_context) { | |
457 *snapshot_data_out = | |
458 reinterpret_cast<const char*>(g_mapped_context->data()); | |
459 *snapshot_size_out = static_cast<int>(g_mapped_context->length()); | |
460 } else { | |
461 *snapshot_data_out = nullptr; | |
462 *snapshot_size_out = 0; | |
463 } | |
464 } | |
465 | |
427 } // namespace gin | 466 } // namespace gin |
OLD | NEW |