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

Side by Side Diff: gin/v8_initializer.cc

Issue 2841443005: [Bindings] Create and use V8 context snapshots (Closed)
Patch Set: Disable on ChromeOS and reduce size of table Created 3 years, 5 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"
27 #include "build/build_config.h"
26 28
27 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) 29 #if defined(V8_USE_EXTERNAL_STARTUP_DATA)
28 #if defined(OS_ANDROID) 30 #if defined(OS_ANDROID)
29 #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"
30 #endif 34 #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 35 #endif // V8_USE_EXTERNAL_STARTUP_DATA
36 36
37 namespace gin { 37 namespace gin {
38 38
39 namespace { 39 namespace {
40 40
41 // None of these globals are ever freed nor closed. 41 // None of these globals are ever freed nor closed.
42 base::MemoryMappedFile* g_mapped_natives = nullptr; 42 base::MemoryMappedFile* g_mapped_natives = nullptr;
43 base::MemoryMappedFile* g_mapped_snapshot = nullptr; 43 base::MemoryMappedFile* g_mapped_snapshot = nullptr;
44 base::MemoryMappedFile* g_mapped_blink_v8_snapshot = nullptr;
haraken 2017/07/04 15:04:19 blink_v8_snapshot => v8_context_snapshot
peria 2017/07/07 06:21:51 Done.
44 45
45 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) 46 const char kBlinkV8SnapshotFileName[] = "blink_v8_snapshot.bin";
haraken 2017/07/04 15:04:19 blink_v8_snapshot.bin => v8_context_snapshot.bin
peria 2017/07/07 06:21:51 Done.
46 47
47 // File handles intentionally never closed. Not using File here because its 48 // File handles intentionally never closed. Not using File here because its
48 // Windows implementation guards against two instances owning the same 49 // Windows implementation guards against two instances owning the same
49 // PlatformFile (which we allow since we know it is never freed). 50 // PlatformFile (which we allow since we know it is never freed).
50 typedef std::map<const char*, 51 using OpenedFileMap =
51 std::pair<base::PlatformFile, base::MemoryMappedFile::Region>> 52 std::map<const char*,
52 OpenedFileMap; 53 std::pair<base::PlatformFile, base::MemoryMappedFile::Region>>;
53 static base::LazyInstance<OpenedFileMap>::Leaky g_opened_files = 54 base::LazyInstance<OpenedFileMap>::Leaky g_opened_files =
54 LAZY_INSTANCE_INITIALIZER; 55 LAZY_INSTANCE_INITIALIZER;
55 56
56 OpenedFileMap::mapped_type& GetOpenedFile(const char* file) { 57 OpenedFileMap::mapped_type& GetOpenedFile(const char* file) {
57 OpenedFileMap& opened_files(g_opened_files.Get()); 58 OpenedFileMap& opened_files(g_opened_files.Get());
58 if (opened_files.find(file) == opened_files.end()) { 59 if (opened_files.find(file) == opened_files.end()) {
59 opened_files[file] = std::make_pair(base::kInvalidPlatformFile, 60 opened_files[file] = std::make_pair(base::kInvalidPlatformFile,
60 base::MemoryMappedFile::Region()); 61 base::MemoryMappedFile::Region());
61 } 62 }
62 return opened_files[file]; 63 return opened_files[file];
63 } 64 }
64 65
66 #if defined(V8_USE_EXTERNAL_STARTUP_DATA)
67
65 const char kNativesFileName[] = "natives_blob.bin"; 68 const char kNativesFileName[] = "natives_blob.bin";
66 69
67 #if defined(OS_ANDROID) 70 #if defined(OS_ANDROID)
68 const char kSnapshotFileName64[] = "snapshot_blob_64.bin"; 71 const char kSnapshotFileName64[] = "snapshot_blob_64.bin";
69 const char kSnapshotFileName32[] = "snapshot_blob_32.bin"; 72 const char kSnapshotFileName32[] = "snapshot_blob_32.bin";
70 73
71 #if defined(__LP64__) 74 #if defined(__LP64__)
72 #define kSnapshotFileName kSnapshotFileName64 75 #define kSnapshotFileName kSnapshotFileName64
73 #else 76 #else
74 #define kSnapshotFileName kSnapshotFileName32 77 #define kSnapshotFileName kSnapshotFileName32
75 #endif 78 #endif
76 79
77 #else // defined(OS_ANDROID) 80 #else // defined(OS_ANDROID)
78 const char kSnapshotFileName[] = "snapshot_blob.bin"; 81 const char kSnapshotFileName[] = "snapshot_blob.bin";
79 #endif // defined(OS_ANDROID) 82 #endif // defined(OS_ANDROID)
80 83
84 #endif // defined(V8_USE_EXTERNAL_STATUP_DATA)
85
81 void GetV8FilePath(const char* file_name, base::FilePath* path_out) { 86 void GetV8FilePath(const char* file_name, base::FilePath* path_out) {
82 #if !defined(OS_MACOSX) 87 #if !defined(OS_MACOSX)
83 base::FilePath data_path; 88 base::FilePath data_path;
84 #if defined(OS_ANDROID) 89 #if defined(OS_ANDROID)
85 // This is the path within the .apk. 90 // This is the path within the .apk.
86 data_path = base::FilePath(FILE_PATH_LITERAL("assets")); 91 data_path = base::FilePath(FILE_PATH_LITERAL("assets"));
87 #elif defined(OS_POSIX) 92 #elif defined(OS_POSIX)
88 PathService::Get(base::DIR_EXE, &data_path); 93 PathService::Get(base::DIR_EXE, &data_path);
89 #elif defined(OS_WIN) 94 #elif defined(OS_WIN)
90 PathService::Get(base::DIR_MODULE, &data_path); 95 PathService::Get(base::DIR_MODULE, &data_path);
91 #endif 96 #endif
92 DCHECK(!data_path.empty()); 97 DCHECK(!data_path.empty());
93 98
94 *path_out = data_path.AppendASCII(file_name); 99 *path_out = data_path.AppendASCII(file_name);
95 #else // !defined(OS_MACOSX) 100 #else // !defined(OS_MACOSX)
96 base::ScopedCFTypeRef<CFStringRef> natives_file_name( 101 base::ScopedCFTypeRef<CFStringRef> natives_file_name(
97 base::SysUTF8ToCFStringRef(file_name)); 102 base::SysUTF8ToCFStringRef(file_name));
98 *path_out = base::mac::PathForFrameworkBundleResource(natives_file_name); 103 *path_out = base::mac::PathForFrameworkBundleResource(natives_file_name);
99 #endif // !defined(OS_MACOSX) 104 #endif // !defined(OS_MACOSX)
100 DCHECK(!path_out->empty());
101 } 105 }
102 106
103 static bool MapV8File(base::PlatformFile platform_file, 107 bool MapV8File(base::PlatformFile platform_file,
104 base::MemoryMappedFile::Region region, 108 base::MemoryMappedFile::Region region,
105 base::MemoryMappedFile** mmapped_file_out) { 109 base::MemoryMappedFile** mmapped_file_out) {
106 DCHECK(*mmapped_file_out == NULL); 110 DCHECK(*mmapped_file_out == NULL);
107 std::unique_ptr<base::MemoryMappedFile> mmapped_file( 111 std::unique_ptr<base::MemoryMappedFile> mmapped_file(
108 new base::MemoryMappedFile()); 112 new base::MemoryMappedFile());
109 if (mmapped_file->Initialize(base::File(platform_file), region)) { 113 if (mmapped_file->Initialize(base::File(platform_file), region)) {
110 *mmapped_file_out = mmapped_file.release(); 114 *mmapped_file_out = mmapped_file.release();
111 return true; 115 return true;
112 } 116 }
113 return false; 117 return false;
114 } 118 }
115 119
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 } 177 }
174 } 178 }
175 #endif // defined(OS_ANDROID) 179 #endif // defined(OS_ANDROID)
176 180
177 UMA_HISTOGRAM_ENUMERATION("V8.Initializer.OpenV8File.Result", 181 UMA_HISTOGRAM_ENUMERATION("V8.Initializer.OpenV8File.Result",
178 result, 182 result,
179 OpenV8FileResult::MAX_VALUE); 183 OpenV8FileResult::MAX_VALUE);
180 return file.TakePlatformFile(); 184 return file.TakePlatformFile();
181 } 185 }
182 186
183 static const OpenedFileMap::mapped_type OpenFileIfNecessary( 187 const OpenedFileMap::mapped_type OpenFileIfNecessary(const char* file_name) {
184 const char* file_name) {
185 OpenedFileMap::mapped_type& opened = GetOpenedFile(file_name); 188 OpenedFileMap::mapped_type& opened = GetOpenedFile(file_name);
186 if (opened.first == base::kInvalidPlatformFile) { 189 if (opened.first == base::kInvalidPlatformFile) {
187 opened.first = OpenV8File(file_name, &opened.second); 190 opened.first = OpenV8File(file_name, &opened.second);
188 } 191 }
189 return opened; 192 return opened;
190 } 193 }
191 194
192 #endif // V8_USE_EXTERNAL_STARTUP_DATA
193
194 bool GenerateEntropy(unsigned char* buffer, size_t amount) { 195 bool GenerateEntropy(unsigned char* buffer, size_t amount) {
195 base::RandBytes(buffer, amount); 196 base::RandBytes(buffer, amount);
196 return true; 197 return true;
197 } 198 }
198 199
199 } // namespace
200
201 #if defined(V8_USE_EXTERNAL_STARTUP_DATA)
202
203 namespace {
204
205 enum LoadV8FileResult { 200 enum LoadV8FileResult {
206 V8_LOAD_SUCCESS = 0, 201 V8_LOAD_SUCCESS = 0,
207 V8_LOAD_FAILED_OPEN, 202 V8_LOAD_FAILED_OPEN,
208 V8_LOAD_FAILED_MAP, 203 V8_LOAD_FAILED_MAP,
209 V8_LOAD_FAILED_VERIFY, // Deprecated. 204 V8_LOAD_FAILED_VERIFY, // Deprecated.
210 V8_LOAD_MAX_VALUE 205 V8_LOAD_MAX_VALUE
211 }; 206 };
212 207
213 static LoadV8FileResult MapOpenedFile( 208 LoadV8FileResult MapOpenedFile(const OpenedFileMap::mapped_type& file_region,
214 const OpenedFileMap::mapped_type& file_region, 209 base::MemoryMappedFile** mmapped_file_out) {
215 base::MemoryMappedFile** mmapped_file_out) {
216 if (file_region.first == base::kInvalidPlatformFile) 210 if (file_region.first == base::kInvalidPlatformFile)
217 return V8_LOAD_FAILED_OPEN; 211 return V8_LOAD_FAILED_OPEN;
218 if (!MapV8File(file_region.first, file_region.second, mmapped_file_out)) 212 if (!MapV8File(file_region.first, file_region.second, mmapped_file_out))
219 return V8_LOAD_FAILED_MAP; 213 return V8_LOAD_FAILED_MAP;
220 return V8_LOAD_SUCCESS; 214 return V8_LOAD_SUCCESS;
221 } 215 }
222 216
223 } // namespace 217 } // namespace
224 218
219 #if defined(V8_USE_EXTERNAL_STARTUP_DATA)
220
225 // static 221 // static
226 void V8Initializer::LoadV8Snapshot() { 222 void V8Initializer::LoadV8Snapshot() {
227 if (g_mapped_snapshot) 223 if (g_mapped_snapshot)
228 return; 224 return;
229 225
230 OpenFileIfNecessary(kSnapshotFileName); 226 OpenFileIfNecessary(kSnapshotFileName);
231 LoadV8FileResult result = MapOpenedFile(GetOpenedFile(kSnapshotFileName), 227 LoadV8FileResult result = MapOpenedFile(GetOpenedFile(kSnapshotFileName),
232 &g_mapped_snapshot); 228 &g_mapped_snapshot);
233 // 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
234 // start up (slower) without the snapshot. 230 // 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"; 359 static const char flag[] = "--experimental_extras";
364 v8::V8::SetFlagsFromString(flag, sizeof(flag) - 1); 360 v8::V8::SetFlagsFromString(flag, sizeof(flag) - 1);
365 } 361 }
366 362
367 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) 363 #if defined(V8_USE_EXTERNAL_STARTUP_DATA)
368 v8::StartupData natives; 364 v8::StartupData natives;
369 natives.data = reinterpret_cast<const char*>(g_mapped_natives->data()); 365 natives.data = reinterpret_cast<const char*>(g_mapped_natives->data());
370 natives.raw_size = static_cast<int>(g_mapped_natives->length()); 366 natives.raw_size = static_cast<int>(g_mapped_natives->length());
371 v8::V8::SetNativesDataBlob(&natives); 367 v8::V8::SetNativesDataBlob(&natives);
372 368
373 if (g_mapped_snapshot != NULL) { 369 if (g_mapped_snapshot) {
374 v8::StartupData snapshot; 370 v8::StartupData snapshot;
375 snapshot.data = reinterpret_cast<const char*>(g_mapped_snapshot->data()); 371 snapshot.data = reinterpret_cast<const char*>(g_mapped_snapshot->data());
376 snapshot.raw_size = static_cast<int>(g_mapped_snapshot->length()); 372 snapshot.raw_size = static_cast<int>(g_mapped_snapshot->length());
377 v8::V8::SetSnapshotDataBlob(&snapshot); 373 v8::V8::SetSnapshotDataBlob(&snapshot);
378 } 374 }
379 #endif // V8_USE_EXTERNAL_STARTUP_DATA 375 #endif // V8_USE_EXTERNAL_STARTUP_DATA
380 376
381 v8::V8::SetEntropySource(&GenerateEntropy); 377 v8::V8::SetEntropySource(&GenerateEntropy);
382 v8::V8::Initialize(); 378 v8::V8::Initialize();
383 379
(...skipping 15 matching lines...) Expand all
399 if (g_mapped_snapshot) { 395 if (g_mapped_snapshot) {
400 *snapshot_data_out = 396 *snapshot_data_out =
401 reinterpret_cast<const char*>(g_mapped_snapshot->data()); 397 reinterpret_cast<const char*>(g_mapped_snapshot->data());
402 *snapshot_size_out = static_cast<int>(g_mapped_snapshot->length()); 398 *snapshot_size_out = static_cast<int>(g_mapped_snapshot->length());
403 } else { 399 } else {
404 *snapshot_data_out = NULL; 400 *snapshot_data_out = NULL;
405 *snapshot_size_out = 0; 401 *snapshot_size_out = 0;
406 } 402 }
407 } 403 }
408 404
405 // static
406 void V8Initializer::LoadBlinkV8Snapshot() {
407 if (g_mapped_blink_v8_snapshot)
408 return;
409
410 OpenFileIfNecessary(kBlinkV8SnapshotFileName);
411 MapOpenedFile(GetOpenedFile(kBlinkV8SnapshotFileName),
412 &g_mapped_blink_v8_snapshot);
413
414 // TODO(peria): Check if the snapshot file is loaded successfully.
415 }
416
417 // static
418 void V8Initializer::LoadBlinkV8SnapshotFromFD(base::PlatformFile snapshot_pf,
419 int64_t snapshot_offset,
420 int64_t snapshot_size) {
421 if (g_mapped_blink_v8_snapshot)
422 return;
423 CHECK_NE(base::kInvalidPlatformFile, snapshot_pf);
424
425 base::MemoryMappedFile::Region snapshot_region =
426 base::MemoryMappedFile::Region::kWholeFile;
427 if (snapshot_size != 0 || snapshot_offset != 0) {
428 snapshot_region.offset = snapshot_offset;
429 snapshot_region.size = snapshot_size;
430 }
431
432 if (MapV8File(snapshot_pf, snapshot_region, &g_mapped_blink_v8_snapshot)) {
433 g_opened_files.Get()[kBlinkV8SnapshotFileName] =
434 std::make_pair(snapshot_pf, snapshot_region);
435 }
436 }
437
438 // static
439 void V8Initializer::GetBlinkV8SnapshotData(const char** snapshot_data_out,
440 int* snapshot_size_out) {
441 if (g_mapped_blink_v8_snapshot) {
442 *snapshot_data_out =
443 reinterpret_cast<const char*>(g_mapped_blink_v8_snapshot->data());
444 *snapshot_size_out = static_cast<int>(g_mapped_blink_v8_snapshot->length());
445 } else {
446 *snapshot_data_out = nullptr;
447 *snapshot_size_out = 0;
448 }
449 }
450
409 } // namespace gin 451 } // namespace gin
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698