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

Side by Side Diff: gin/v8_initializer.cc

Issue 1156873002: Load v8 snapshots directly from APK (and store them uncompressed) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@v8initializer
Patch Set: Keep extracting for components/ Created 5 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
« gin/v8_initializer.h ('K') | « gin/v8_initializer.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "base/basictypes.h" 7 #include "base/basictypes.h"
8 #include "base/files/file.h" 8 #include "base/files/file.h"
9 #include "base/files/file_path.h" 9 #include "base/files/file_path.h"
10 #include "base/files/memory_mapped_file.h" 10 #include "base/files/memory_mapped_file.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/metrics/histogram.h" 12 #include "base/metrics/histogram.h"
13 #include "base/rand_util.h" 13 #include "base/rand_util.h"
14 #include "base/strings/sys_string_conversions.h" 14 #include "base/strings/sys_string_conversions.h"
15 #include "base/threading/platform_thread.h" 15 #include "base/threading/platform_thread.h"
16 #include "base/time/time.h" 16 #include "base/time/time.h"
17 #include "crypto/sha2.h" 17 #include "crypto/sha2.h"
18 18
19 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) 19 #if defined(V8_USE_EXTERNAL_STARTUP_DATA)
20 #if defined(OS_ANDROID)
21 #include "base/android/apk_assets.h"
22 #endif
20 #if defined(OS_MACOSX) 23 #if defined(OS_MACOSX)
21 #include "base/mac/foundation_util.h" 24 #include "base/mac/foundation_util.h"
22 #endif // OS_MACOSX 25 #endif // OS_MACOSX
23 #include "base/path_service.h" 26 #include "base/path_service.h"
24 #endif // V8_USE_EXTERNAL_STARTUP_DATA 27 #endif // V8_USE_EXTERNAL_STARTUP_DATA
25 28
26 namespace gin { 29 namespace gin {
27 30
28 namespace { 31 namespace {
29 32
30 base::MemoryMappedFile* g_mapped_natives = nullptr; 33 base::MemoryMappedFile* g_mapped_natives = nullptr;
31 base::MemoryMappedFile* g_mapped_snapshot = nullptr; 34 base::MemoryMappedFile* g_mapped_snapshot = nullptr;
32 35
33 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) 36 #if defined(V8_USE_EXTERNAL_STARTUP_DATA)
34 #if !defined(OS_MACOSX) 37 #if !defined(OS_MACOSX)
35 const int kV8SnapshotBasePathKey = 38 const int kV8SnapshotBasePathKey =
36 #if defined(OS_ANDROID) 39 #if defined(OS_ANDROID)
37 base::DIR_ANDROID_APP_DATA; 40 base::DIR_ANDROID_APP_DATA;
38 #elif defined(OS_POSIX) 41 #elif defined(OS_POSIX)
39 base::DIR_EXE; 42 base::DIR_EXE;
40 #elif defined(OS_WIN) 43 #elif defined(OS_WIN)
41 base::DIR_MODULE; 44 base::DIR_MODULE;
42 #endif // OS_ANDROID 45 #endif // OS_ANDROID
43 #endif // !OS_MACOSX 46 #endif // !OS_MACOSX
44 47
48 #if defined(OS_ANDROID)
49 const char kNativesFileName[] = "assets/natives_blob.bin";
50 const char kSnapshotFileName[] = "assets/snapshot_blob.bin";
51 #else
45 const char kNativesFileName[] = "natives_blob.bin"; 52 const char kNativesFileName[] = "natives_blob.bin";
46 const char kSnapshotFileName[] = "snapshot_blob.bin"; 53 const char kSnapshotFileName[] = "snapshot_blob.bin";
54 #endif // defined(OS_ANDROID)
47 55
48 // Constants for snapshot loading retries taken from: 56 // Constants for snapshot loading retries taken from:
49 // https://support.microsoft.com/en-us/kb/316609. 57 // https://support.microsoft.com/en-us/kb/316609.
50 const int kMaxOpenAttempts = 5; 58 const int kMaxOpenAttempts = 5;
51 const int kOpenRetryDelayMillis = 250; 59 const int kOpenRetryDelayMillis = 250;
52 60
61 #if !defined(OS_ANDROID)
53 void GetV8FilePath(const char* file_name, base::FilePath* path_out) { 62 void GetV8FilePath(const char* file_name, base::FilePath* path_out) {
54 #if !defined(OS_MACOSX) 63 #if !defined(OS_MACOSX)
55 base::FilePath data_path; 64 base::FilePath data_path;
56 PathService::Get(kV8SnapshotBasePathKey, &data_path); 65 PathService::Get(kV8SnapshotBasePathKey, &data_path);
57 DCHECK(!data_path.empty()); 66 DCHECK(!data_path.empty());
58 67
59 *path_out = data_path.AppendASCII(file_name); 68 *path_out = data_path.AppendASCII(file_name);
60 #else // !defined(OS_MACOSX) 69 #else // !defined(OS_MACOSX)
61 base::ScopedCFTypeRef<CFStringRef> natives_file_name( 70 base::ScopedCFTypeRef<CFStringRef> natives_file_name(
62 base::SysUTF8ToCFStringRef(file_name)); 71 base::SysUTF8ToCFStringRef(file_name));
63 *path_out = base::mac::PathForFrameworkBundleResource(natives_file_name); 72 *path_out = base::mac::PathForFrameworkBundleResource(natives_file_name);
64 #endif // !defined(OS_MACOSX) 73 #endif // !defined(OS_MACOSX)
65 DCHECK(!path_out->empty()); 74 DCHECK(!path_out->empty());
66 } 75 }
76 #endif // !defined(OS_ANDROID)
67 77
68 static bool MapV8File(base::File file, 78 static bool MapV8File(base::File file,
69 base::MemoryMappedFile::Region region, 79 base::MemoryMappedFile::Region region,
70 base::MemoryMappedFile** mmapped_file_out) { 80 base::MemoryMappedFile** mmapped_file_out) {
71 DCHECK(*mmapped_file_out == NULL); 81 DCHECK(*mmapped_file_out == NULL);
72 base::MemoryMappedFile* mmapped_file = *mmapped_file_out = 82 base::MemoryMappedFile* mmapped_file = *mmapped_file_out =
73 new base::MemoryMappedFile; 83 new base::MemoryMappedFile;
74 if (!mmapped_file->Initialize(file.Pass(), region)) { 84 if (!mmapped_file->Initialize(file.Pass(), region)) {
75 delete mmapped_file; 85 delete mmapped_file;
76 *mmapped_file_out = NULL; 86 *mmapped_file_out = NULL;
77 return false; 87 return false;
78 } 88 }
79 89
80 return true; 90 return true;
81 } 91 }
82 92
83 static bool OpenV8File(const base::FilePath& path, 93 base::File OpenV8File(const char* file_name,
84 int flags, 94 base::MemoryMappedFile::Region* out_region) {
rmcilroy 2015/06/09 11:52:55 nit - usual convention is to suffix with "_out" ra
rmcilroy 2015/06/09 11:52:55 align arguments (or run "git cl format" :))
85 base::File& file) { 95 #if defined(OS_ANDROID)
96 return base::File(base::android::OpenApkAsset(file_name, out_region));
97 #else
86 // Re-try logic here is motivated by http://crbug.com/479537 98 // Re-try logic here is motivated by http://crbug.com/479537
87 // for A/V on Windows (https://support.microsoft.com/en-us/kb/316609). 99 // for A/V on Windows (https://support.microsoft.com/en-us/kb/316609).
88 100
89 // These match tools/metrics/histograms.xml 101 // These match tools/metrics/histograms.xml
90 enum OpenV8FileResult { 102 enum OpenV8FileResult {
91 OPENED = 0, 103 OPENED = 0,
92 OPENED_RETRY, 104 OPENED_RETRY,
93 FAILED_IN_USE, 105 FAILED_IN_USE,
94 FAILED_OTHER, 106 FAILED_OTHER,
95 MAX_VALUE 107 MAX_VALUE
96 }; 108 };
97 109
110 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ;
rmcilroy 2015/06/09 11:52:54 nit - move flags down below with OpenV8FileResult
111 base::FilePath path;
112 GetV8FilePath(file_name, &path);
98 OpenV8FileResult result = OpenV8FileResult::FAILED_IN_USE; 113 OpenV8FileResult result = OpenV8FileResult::FAILED_IN_USE;
114 base::File file;
99 for (int attempt = 0; attempt < kMaxOpenAttempts; attempt++) { 115 for (int attempt = 0; attempt < kMaxOpenAttempts; attempt++) {
100 file.Initialize(path, flags); 116 file.Initialize(path, flags);
101 if (file.IsValid()) { 117 if (file.IsValid()) {
118 *out_region = base::MemoryMappedFile::Region::kWholeFile;
102 if (attempt == 0) { 119 if (attempt == 0) {
103 result = OpenV8FileResult::OPENED; 120 result = OpenV8FileResult::OPENED;
104 break; 121 break;
105 } else { 122 } else {
106 result = OpenV8FileResult::OPENED_RETRY; 123 result = OpenV8FileResult::OPENED_RETRY;
107 break; 124 break;
108 } 125 }
109 } else if (file.error_details() != base::File::FILE_ERROR_IN_USE) { 126 } else if (file.error_details() != base::File::FILE_ERROR_IN_USE) {
110 result = OpenV8FileResult::FAILED_OTHER; 127 result = OpenV8FileResult::FAILED_OTHER;
111 break; 128 break;
112 } else if (kMaxOpenAttempts - 1 != attempt) { 129 } else if (kMaxOpenAttempts - 1 != attempt) {
113 base::PlatformThread::Sleep( 130 base::PlatformThread::Sleep(
114 base::TimeDelta::FromMilliseconds(kOpenRetryDelayMillis)); 131 base::TimeDelta::FromMilliseconds(kOpenRetryDelayMillis));
115 } 132 }
116 } 133 }
117 134
118 UMA_HISTOGRAM_ENUMERATION("V8.Initializer.OpenV8File.Result", 135 UMA_HISTOGRAM_ENUMERATION("V8.Initializer.OpenV8File.Result",
119 result, 136 result,
120 OpenV8FileResult::MAX_VALUE); 137 OpenV8FileResult::MAX_VALUE);
121 138 return file.Pass();
122 return result == OpenV8FileResult::OPENED 139 #endif // defined(OS_ANDROID)
123 || result == OpenV8FileResult::OPENED_RETRY;
124 } 140 }
125 141
126 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) 142 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA)
127 bool VerifyV8StartupFile(base::MemoryMappedFile** file, 143 bool VerifyV8StartupFile(base::MemoryMappedFile** file,
128 const unsigned char* fingerprint) { 144 const unsigned char* fingerprint) {
129 unsigned char output[crypto::kSHA256Length]; 145 unsigned char output[crypto::kSHA256Length];
130 crypto::SHA256HashString( 146 crypto::SHA256HashString(
131 base::StringPiece(reinterpret_cast<const char*>((*file)->data()), 147 base::StringPiece(reinterpret_cast<const char*>((*file)->data()),
132 (*file)->length()), 148 (*file)->length()),
133 output, sizeof(output)); 149 output, sizeof(output));
(...skipping 28 matching lines...) Expand all
162 V8_LOAD_FAILED_VERIFY, 178 V8_LOAD_FAILED_VERIFY,
163 V8_LOAD_MAX_VALUE 179 V8_LOAD_MAX_VALUE
164 }; 180 };
165 181
166 static LoadV8FileResult OpenMapVerify( 182 static LoadV8FileResult OpenMapVerify(
167 const char* file_name, 183 const char* file_name,
168 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) 184 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA)
169 const unsigned char* fingerprint, 185 const unsigned char* fingerprint,
170 #endif 186 #endif
171 base::MemoryMappedFile** mmapped_file_out) { 187 base::MemoryMappedFile** mmapped_file_out) {
172 base::FilePath path; 188 base::MemoryMappedFile::Region region;
173 GetV8FilePath(file_name, &path);
174 189
175 base::File file; 190 base::File file(OpenV8File(file_name, &region));
176 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ; 191 if (!file.IsValid())
177
178 if (!OpenV8File(path, flags, file))
179 return V8_LOAD_FAILED_OPEN; 192 return V8_LOAD_FAILED_OPEN;
180 if (!MapV8File(file.Pass(), base::MemoryMappedFile::Region::kWholeFile, 193 if (!MapV8File(file.Pass(), region, mmapped_file_out))
181 mmapped_file_out))
182 return V8_LOAD_FAILED_MAP; 194 return V8_LOAD_FAILED_MAP;
183 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) 195 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA)
184 if (!VerifyV8StartupFile(mmapped_file_out, fingerprint)) 196 if (!VerifyV8StartupFile(mmapped_file_out, fingerprint))
185 return V8_LOAD_FAILED_VERIFY; 197 return V8_LOAD_FAILED_VERIFY;
186 #endif // V8_VERIFY_EXTERNAL_STARTUP_DATA 198 #endif // V8_VERIFY_EXTERNAL_STARTUP_DATA
187 return V8_LOAD_SUCCESS; 199 return V8_LOAD_SUCCESS;
188 } 200 }
189 201
190 // static 202 // static
191 void V8Initializer::LoadV8Snapshot() { 203 void V8Initializer::LoadV8Snapshot() {
192 if (g_mapped_snapshot) 204 if (g_mapped_snapshot)
193 return; 205 return;
194 206
195 LoadV8FileResult result = OpenMapVerify(kSnapshotFileName, 207 LoadV8FileResult result = OpenMapVerify(kSnapshotFileName,
196 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) 208 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA)
197 g_snapshot_fingerprint, 209 g_snapshot_fingerprint,
198 #endif 210 #endif
199 &g_mapped_snapshot); 211 &g_mapped_snapshot);
212 // V8 can't start up without the source of the natives, but it can
213 // start up (slower) without the snapshot.
rmcilroy 2015/06/09 11:52:54 nit - probably clearer as "Failure to load the V8
200 UMA_HISTOGRAM_ENUMERATION("V8.Initializer.LoadV8Snapshot.Result", result, 214 UMA_HISTOGRAM_ENUMERATION("V8.Initializer.LoadV8Snapshot.Result", result,
201 V8_LOAD_MAX_VALUE); 215 V8_LOAD_MAX_VALUE);
202 } 216 }
203 217
204 void V8Initializer::LoadV8Natives() { 218 void V8Initializer::LoadV8Natives() {
205 if (g_mapped_natives) 219 if (g_mapped_natives)
206 return; 220 return;
207 221
208 LoadV8FileResult result = OpenMapVerify(kNativesFileName, 222 LoadV8FileResult result = OpenMapVerify(kNativesFileName,
209 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) 223 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA)
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 if (!MapV8File(base::File(natives_pf), natives_region, &g_mapped_natives)) { 277 if (!MapV8File(base::File(natives_pf), natives_region, &g_mapped_natives)) {
264 LOG(FATAL) << "Couldn't mmap v8 natives data file"; 278 LOG(FATAL) << "Couldn't mmap v8 natives data file";
265 } 279 }
266 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) 280 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA)
267 if (!VerifyV8StartupFile(&g_mapped_natives, g_natives_fingerprint)) { 281 if (!VerifyV8StartupFile(&g_mapped_natives, g_natives_fingerprint)) {
268 LOG(FATAL) << "Couldn't verify contents of v8 natives data file"; 282 LOG(FATAL) << "Couldn't verify contents of v8 natives data file";
269 } 283 }
270 #endif // V8_VERIFY_EXTERNAL_STARTUP_DATA 284 #endif // V8_VERIFY_EXTERNAL_STARTUP_DATA
271 } 285 }
272 286
273 // static 287 #if defined(OS_POSIX)
274 bool V8Initializer::OpenV8FilesForChildProcesses( 288 V8Initializer::V8Files::V8Files() {
rmcilroy 2015/06/09 11:52:54 initialize the fds to "-1"
275 base::PlatformFile* natives_fd_out,
276 base::PlatformFile* snapshot_fd_out) {
277 base::FilePath natives_data_path;
278 base::FilePath snapshot_data_path;
279 GetV8FilePath(kNativesFileName, &natives_data_path);
280 GetV8FilePath(kSnapshotFileName, &snapshot_data_path);
281
282 base::File natives_data_file;
283 base::File snapshot_data_file;
284 int file_flags = base::File::FLAG_OPEN | base::File::FLAG_READ;
285
286 bool natives_success =
287 OpenV8File(natives_data_path, file_flags, natives_data_file);
288 if (natives_success) {
289 *natives_fd_out = natives_data_file.TakePlatformFile();
290 }
291 bool snapshot_success =
292 OpenV8File(snapshot_data_path, file_flags, snapshot_data_file);
293 if (snapshot_success) {
294 *snapshot_fd_out = snapshot_data_file.TakePlatformFile();
295 }
296 // We can start up without the snapshot file, but not without the natives.
297 return natives_success;
298 } 289 }
299 290
300 #endif // V8_USE_EXTERNAL_STARTUP_DATA 291 V8Initializer::V8Files::~V8Files() {
292 }
293
294 // static
295 void V8Initializer::OpenV8FilesForChildProcesses(
296 V8Initializer::V8Files* files_out) {
297 base::File natives_file =
298 OpenV8File(kNativesFileName, &files_out->natives_region);
299 files_out->natives_fd.reset(natives_file.TakePlatformFile());
300 base::File snapshot_file =
301 OpenV8File(kSnapshotFileName, &files_out->snapshot_region);
302 files_out->snapshot_fd.reset(snapshot_file.TakePlatformFile());
303 }
304 #endif // defined(OS_POSIX)
305 #endif // defined(V8_USE_EXTERNAL_STARTUP_DATA)
301 306
302 // static 307 // static
303 void V8Initializer::Initialize(gin::IsolateHolder::ScriptMode mode) { 308 void V8Initializer::Initialize(gin::IsolateHolder::ScriptMode mode) {
304 static bool v8_is_initialized = false; 309 static bool v8_is_initialized = false;
305 if (v8_is_initialized) 310 if (v8_is_initialized)
306 return; 311 return;
307 312
308 v8::V8::InitializePlatform(V8Platform::Get()); 313 v8::V8::InitializePlatform(V8Platform::Get());
309 314
310 if (gin::IsolateHolder::kStrictMode == mode) { 315 if (gin::IsolateHolder::kStrictMode == mode) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 *snapshot_data_out = 353 *snapshot_data_out =
349 reinterpret_cast<const char*>(g_mapped_snapshot->data()); 354 reinterpret_cast<const char*>(g_mapped_snapshot->data());
350 *snapshot_size_out = static_cast<int>(g_mapped_snapshot->length()); 355 *snapshot_size_out = static_cast<int>(g_mapped_snapshot->length());
351 } else { 356 } else {
352 *snapshot_data_out = NULL; 357 *snapshot_data_out = NULL;
353 *snapshot_size_out = 0; 358 *snapshot_size_out = 0;
354 } 359 }
355 } 360 }
356 361
357 } // namespace gin 362 } // namespace gin
OLDNEW
« gin/v8_initializer.h ('K') | « gin/v8_initializer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698