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

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>
(...skipping 15 matching lines...) Expand all
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698