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

Side by Side Diff: gin/v8_initializer.cc

Issue 2841443005: [Bindings] Create and use V8 context snapshots (Closed)
Patch Set: Work for all 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 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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698