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

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: Pass FDs & Regions through to child process (Still has formatting errors) Created 5 years, 7 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
« no previous file with comments | « 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
(...skipping 13 matching lines...) Expand all
43 #endif // !OS_MACOSX 46 #endif // !OS_MACOSX
44 47
45 const char kNativesFileName[] = "natives_blob.bin"; 48 const char kNativesFileName[] = "natives_blob.bin";
46 const char kSnapshotFileName[] = "snapshot_blob.bin"; 49 const char kSnapshotFileName[] = "snapshot_blob.bin";
47 50
48 // Constants for snapshot loading retries taken from: 51 // Constants for snapshot loading retries taken from:
49 // https://support.microsoft.com/en-us/kb/316609. 52 // https://support.microsoft.com/en-us/kb/316609.
50 const int kMaxOpenAttempts = 5; 53 const int kMaxOpenAttempts = 5;
51 const int kOpenRetryDelayMillis = 250; 54 const int kOpenRetryDelayMillis = 250;
52 55
56 #if !defined(OS_ANDROID)
53 void GetV8FilePaths(base::FilePath* natives_path_out, 57 void GetV8FilePaths(base::FilePath* natives_path_out,
54 base::FilePath* snapshot_path_out) { 58 base::FilePath* snapshot_path_out) {
55 #if !defined(OS_MACOSX) 59 #if !defined(OS_MACOSX)
56 base::FilePath data_path; 60 base::FilePath data_path;
57 PathService::Get(kV8SnapshotBasePathKey, &data_path); 61 PathService::Get(kV8SnapshotBasePathKey, &data_path);
58 DCHECK(!data_path.empty()); 62 DCHECK(!data_path.empty());
59 63
60 *natives_path_out = data_path.AppendASCII(kNativesFileName); 64 *natives_path_out = data_path.AppendASCII(kNativesFileName);
61 *snapshot_path_out = data_path.AppendASCII(kSnapshotFileName); 65 *snapshot_path_out = data_path.AppendASCII(kSnapshotFileName);
62 #else // !defined(OS_MACOSX) 66 #else // !defined(OS_MACOSX)
63 base::ScopedCFTypeRef<CFStringRef> natives_file_name( 67 base::ScopedCFTypeRef<CFStringRef> natives_file_name(
64 base::SysUTF8ToCFStringRef(kNativesFileName)); 68 base::SysUTF8ToCFStringRef(kNativesFileName));
65 *natives_path_out = 69 *natives_path_out =
66 base::mac::PathForFrameworkBundleResource(natives_file_name); 70 base::mac::PathForFrameworkBundleResource(natives_file_name);
67 base::ScopedCFTypeRef<CFStringRef> snapshot_file_name( 71 base::ScopedCFTypeRef<CFStringRef> snapshot_file_name(
68 base::SysUTF8ToCFStringRef(kSnapshotFileName)); 72 base::SysUTF8ToCFStringRef(kSnapshotFileName));
69 *snapshot_path_out = 73 *snapshot_path_out =
70 base::mac::PathForFrameworkBundleResource(snapshot_file_name); 74 base::mac::PathForFrameworkBundleResource(snapshot_file_name);
71 DCHECK(!natives_path_out->empty()); 75 DCHECK(!natives_path_out->empty());
72 DCHECK(!snapshot_path_out->empty()); 76 DCHECK(!snapshot_path_out->empty());
73 #endif // !defined(OS_MACOSX) 77 #endif // !defined(OS_MACOSX)
74 } 78 }
79 #endif // !defined(OS_ANDROID)
75 80
76 static bool MapV8Files(base::File natives_file, 81 static bool MapV8Files(base::File natives_file,
77 base::File snapshot_file, 82 base::File snapshot_file,
78 base::MemoryMappedFile::Region natives_region = 83 base::MemoryMappedFile::Region natives_region,
79 base::MemoryMappedFile::Region::kWholeFile, 84 base::MemoryMappedFile::Region snapshot_region) {
80 base::MemoryMappedFile::Region snapshot_region =
81 base::MemoryMappedFile::Region::kWholeFile) {
82 g_mapped_natives = new base::MemoryMappedFile; 85 g_mapped_natives = new base::MemoryMappedFile;
83 if (!g_mapped_natives->IsValid()) { 86 if (!g_mapped_natives->IsValid()) {
84 if (!g_mapped_natives->Initialize(natives_file.Pass(), natives_region)) { 87 if (!g_mapped_natives->Initialize(natives_file.Pass(), natives_region)) {
85 delete g_mapped_natives; 88 delete g_mapped_natives;
86 g_mapped_natives = NULL; 89 g_mapped_natives = NULL;
87 LOG(FATAL) << "Couldn't mmap v8 natives data file"; 90 LOG(FATAL) << "Couldn't mmap v8 natives data file";
88 return false; 91 return false;
89 } 92 }
90 } 93 }
91 94
92 g_mapped_snapshot = new base::MemoryMappedFile; 95 g_mapped_snapshot = new base::MemoryMappedFile;
93 if (!g_mapped_snapshot->IsValid()) { 96 if (!g_mapped_snapshot->IsValid()) {
94 if (!g_mapped_snapshot->Initialize(snapshot_file.Pass(), snapshot_region)) { 97 if (!g_mapped_snapshot->Initialize(snapshot_file.Pass(), snapshot_region)) {
95 delete g_mapped_snapshot; 98 delete g_mapped_snapshot;
96 g_mapped_snapshot = NULL; 99 g_mapped_snapshot = NULL;
97 LOG(ERROR) << "Couldn't mmap v8 snapshot data file"; 100 LOG(ERROR) << "Couldn't mmap v8 snapshot data file";
98 return false; 101 return false;
99 } 102 }
100 } 103 }
101 104
102 return true; 105 return true;
103 } 106 }
104 107
108 #if !defined(OS_ANDROID)
109
105 static bool OpenV8File(const base::FilePath& path, 110 static bool OpenV8File(const base::FilePath& path,
106 int flags, 111 int flags,
107 base::File& file) { 112 base::File& file) {
108 // Re-try logic here is motivated by http://crbug.com/479537 113 // Re-try logic here is motivated by http://crbug.com/479537
109 // for A/V on Windows (https://support.microsoft.com/en-us/kb/316609). 114 // for A/V on Windows (https://support.microsoft.com/en-us/kb/316609).
110 115
111 // These match tools/metrics/histograms.xml 116 // These match tools/metrics/histograms.xml
112 enum OpenV8FileResult { 117 enum OpenV8FileResult {
113 OPENED = 0, 118 OPENED = 0,
114 OPENED_RETRY, 119 OPENED_RETRY,
(...skipping 22 matching lines...) Expand all
137 } 142 }
138 } 143 }
139 144
140 UMA_HISTOGRAM_ENUMERATION("V8.Initializer.OpenV8File.Result", 145 UMA_HISTOGRAM_ENUMERATION("V8.Initializer.OpenV8File.Result",
141 result, 146 result,
142 OpenV8FileResult::MAX_VALUE); 147 OpenV8FileResult::MAX_VALUE);
143 148
144 return result == OpenV8FileResult::OPENED 149 return result == OpenV8FileResult::OPENED
145 || result == OpenV8FileResult::OPENED_RETRY; 150 || result == OpenV8FileResult::OPENED_RETRY;
146 } 151 }
152 #endif // !defined(OS_ANDROID)
147 153
148 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) 154 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA)
149 bool VerifyV8SnapshotFile(base::MemoryMappedFile* snapshot_file, 155 bool VerifyV8SnapshotFile(base::MemoryMappedFile* snapshot_file,
150 const unsigned char* fingerprint) { 156 const unsigned char* fingerprint) {
151 unsigned char output[crypto::kSHA256Length]; 157 unsigned char output[crypto::kSHA256Length];
152 crypto::SHA256HashString( 158 crypto::SHA256HashString(
153 base::StringPiece(reinterpret_cast<const char*>(snapshot_file->data()), 159 base::StringPiece(reinterpret_cast<const char*>(snapshot_file->data()),
154 snapshot_file->length()), 160 snapshot_file->length()),
155 output, sizeof(output)); 161 output, sizeof(output));
156 return !memcmp(fingerprint, output, sizeof(output)); 162 return !memcmp(fingerprint, output, sizeof(output));
157 } 163 }
158 #endif // V8_VERIFY_EXTERNAL_STARTUP_DATA 164 #endif // V8_VERIFY_EXTERNAL_STARTUP_DATA
159 #endif // V8_USE_EXTERNAL_STARTUP_DATA 165 #endif // V8_USE_EXTERNAL_STARTUP_DATA
160 166
161 bool GenerateEntropy(unsigned char* buffer, size_t amount) { 167 bool GenerateEntropy(unsigned char* buffer, size_t amount) {
162 base::RandBytes(buffer, amount); 168 base::RandBytes(buffer, amount);
163 return true; 169 return true;
164 } 170 }
165 171
166 } // namespace 172 } // namespace
167 173
168 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) 174 #if defined(V8_USE_EXTERNAL_STARTUP_DATA)
175
176 bool V8Initializer::V8Files::IsLoaded() const {
177 return snapshot_fd.get() != -1 && natives_fd.get() != -1;
178 }
179
169 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) 180 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA)
170 // Defined in gen/gin/v8_snapshot_fingerprint.cc 181 // Defined in gen/gin/v8_snapshot_fingerprint.cc
171 extern const unsigned char g_natives_fingerprint[]; 182 extern const unsigned char g_natives_fingerprint[];
172 extern const unsigned char g_snapshot_fingerprint[]; 183 extern const unsigned char g_snapshot_fingerprint[];
173 #endif // V8_VERIFY_EXTERNAL_STARTUP_DATA 184 #endif // V8_VERIFY_EXTERNAL_STARTUP_DATA
174 185
175 // static 186 // static
176 bool V8Initializer::LoadV8Snapshot() { 187 bool V8Initializer::LoadV8Snapshot() {
177 188
178 enum LoadV8SnapshotResult { 189 enum LoadV8SnapshotResult {
179 SUCCESS = 0, 190 SUCCESS = 0,
180 FAILED_OPEN, 191 FAILED_OPEN,
181 FAILED_MAP, 192 FAILED_MAP,
182 FAILED_VERIFY, 193 FAILED_VERIFY,
183 MAX_VALUE 194 MAX_VALUE
184 }; 195 };
185 196
186 if (g_mapped_natives && g_mapped_snapshot) 197 if (g_mapped_natives && g_mapped_snapshot)
187 return true; 198 return true;
188 199
189 base::FilePath natives_data_path; 200 V8Files files;
190 base::FilePath snapshot_data_path; 201 OpenV8FilesForChildProcesses(&files);
rmcilroy 2015/05/28 12:03:29 I don't think you should be calling OpenV8FilesFor
agrieve 2015/06/13 02:21:29 I did this just because the two functions are copy
191 GetV8FilePaths(&natives_data_path, &snapshot_data_path);
192
193 base::File natives_file;
194 base::File snapshot_file;
195 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ;
196
197 LoadV8SnapshotResult result; 202 LoadV8SnapshotResult result;
198 if (!OpenV8File(natives_data_path, flags, natives_file) || 203 if (!files.IsLoaded()) {
199 !OpenV8File(snapshot_data_path, flags, snapshot_file)) {
200 result = LoadV8SnapshotResult::FAILED_OPEN; 204 result = LoadV8SnapshotResult::FAILED_OPEN;
201 } else if (!MapV8Files(natives_file.Pass(), snapshot_file.Pass())) { 205 } else if (!MapV8Files(base::File(files.natives_fd.release()),
206 base::File(files.snapshot_fd.release()),
207 files.natives_region, files.snapshot_region)) {
202 result = LoadV8SnapshotResult::FAILED_MAP; 208 result = LoadV8SnapshotResult::FAILED_MAP;
203 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) 209 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA)
204 } else if (!VerifyV8SnapshotFile(g_mapped_natives, g_natives_fingerprint) || 210 } else if (!VerifyV8SnapshotFile(g_mapped_natives, g_natives_fingerprint) ||
205 !VerifyV8SnapshotFile(g_mapped_snapshot, g_snapshot_fingerprint)) { 211 !VerifyV8SnapshotFile(g_mapped_snapshot, g_snapshot_fingerprint)) {
206 result = LoadV8SnapshotResult::FAILED_VERIFY; 212 result = LoadV8SnapshotResult::FAILED_VERIFY;
207 #endif // V8_VERIFY_EXTERNAL_STARTUP_DATA 213 #endif // V8_VERIFY_EXTERNAL_STARTUP_DATA
208 } else { 214 } else {
209 result = LoadV8SnapshotResult::SUCCESS; 215 result = LoadV8SnapshotResult::SUCCESS;
210 } 216 }
211 217
(...skipping 25 matching lines...) Expand all
237 if (natives_size != 0 || natives_offset != 0) { 243 if (natives_size != 0 || natives_offset != 0) {
238 snapshot_region = 244 snapshot_region =
239 base::MemoryMappedFile::Region(snapshot_offset, snapshot_size); 245 base::MemoryMappedFile::Region(snapshot_offset, snapshot_size);
240 } 246 }
241 247
242 return MapV8Files(base::File(natives_pf), base::File(snapshot_pf), 248 return MapV8Files(base::File(natives_pf), base::File(snapshot_pf),
243 natives_region, snapshot_region); 249 natives_region, snapshot_region);
244 } 250 }
245 251
246 // static 252 // static
247 bool V8Initializer::OpenV8FilesForChildProcesses( 253 void V8Initializer::OpenV8FilesForChildProcesses(
248 base::PlatformFile* natives_fd_out, 254 V8Initializer::V8Files* files_out) {
249 base::PlatformFile* snapshot_fd_out) { 255 #if defined(OS_ANDROID)
256 files_out->natives_fd.reset(base::android::OpenApkAsset(
257 kNativesFileName, &files_out->natives_region));
258 files_out->snapshot_fd.reset(base::android::OpenApkAsset(
259 kSnapshotFileName, &files_out->snapshot_region));
260 #else
250 base::FilePath natives_data_path; 261 base::FilePath natives_data_path;
251 base::FilePath snapshot_data_path; 262 base::FilePath snapshot_data_path;
252 GetV8FilePaths(&natives_data_path, &snapshot_data_path); 263 GetV8FilePaths(&natives_data_path, &snapshot_data_path);
253 264
254 base::File natives_data_file; 265 base::File natives_data_file;
255 base::File snapshot_data_file; 266 base::File snapshot_data_file;
256 int file_flags = base::File::FLAG_OPEN | base::File::FLAG_READ; 267 int file_flags = base::File::FLAG_OPEN | base::File::FLAG_READ;
257 268
258 bool success = OpenV8File(natives_data_path, file_flags, natives_data_file) && 269 bool success = OpenV8File(natives_data_path, file_flags, natives_data_file) &&
259 OpenV8File(snapshot_data_path, file_flags, snapshot_data_file); 270 OpenV8File(snapshot_data_path, file_flags, snapshot_data_file);
260 if (success) { 271 if (success) {
261 *natives_fd_out = natives_data_file.TakePlatformFile(); 272 files_out->natives_fd.reset(natives_data_file.TakePlatformFile());
262 *snapshot_fd_out = snapshot_data_file.TakePlatformFile(); 273 files_out->snapshot_fd.reset(snapshot_data_file.TakePlatformFile());
274 files_out->natives_region = base::MemoryMappedFile::Region::kWholeFile;
275 files_out->snapshot_region = base::MemoryMappedFile::Region::kWholeFile;
263 } 276 }
264 return success; 277 #endif
265 } 278 }
266 279
280
267 #endif // V8_USE_EXTERNAL_STARTUP_DATA 281 #endif // V8_USE_EXTERNAL_STARTUP_DATA
268 282
269 // static 283 // static
270 void V8Initializer::Initialize(gin::IsolateHolder::ScriptMode mode) { 284 void V8Initializer::Initialize(gin::IsolateHolder::ScriptMode mode) {
271 static bool v8_is_initialized = false; 285 static bool v8_is_initialized = false;
272 if (v8_is_initialized) 286 if (v8_is_initialized)
273 return; 287 return;
274 288
275 v8::V8::InitializePlatform(V8Platform::Get()); 289 v8::V8::InitializePlatform(V8Platform::Get());
276 290
(...skipping 30 matching lines...) Expand all
307 *natives_size_out = *snapshot_size_out = 0; 321 *natives_size_out = *snapshot_size_out = 0;
308 return; 322 return;
309 } 323 }
310 *natives_data_out = reinterpret_cast<const char*>(g_mapped_natives->data()); 324 *natives_data_out = reinterpret_cast<const char*>(g_mapped_natives->data());
311 *snapshot_data_out = reinterpret_cast<const char*>(g_mapped_snapshot->data()); 325 *snapshot_data_out = reinterpret_cast<const char*>(g_mapped_snapshot->data());
312 *natives_size_out = static_cast<int>(g_mapped_natives->length()); 326 *natives_size_out = static_cast<int>(g_mapped_natives->length());
313 *snapshot_size_out = static_cast<int>(g_mapped_snapshot->length()); 327 *snapshot_size_out = static_cast<int>(g_mapped_snapshot->length());
314 } 328 }
315 329
316 } // namespace gin 330 } // namespace gin
OLDNEW
« no previous file with comments | « gin/v8_initializer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698