Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(617)

Side by Side Diff: gin/v8_initializer.cc

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

Powered by Google App Engine
This is Rietveld 408576698