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

Side by Side Diff: gin/v8_initializer.cc

Issue 1164483003: Allow startup with missing V8 snapshot file. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix misplaced ifdef for Windows 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
« no previous file with comments | « gin/v8_initializer.h ('k') | media/blink/run_all_unittests.cc » ('j') | 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"
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 #endif // !OS_MACOSX 43 #endif // !OS_MACOSX
44 44
45 const char kNativesFileName[] = "natives_blob.bin"; 45 const char kNativesFileName[] = "natives_blob.bin";
46 const char kSnapshotFileName[] = "snapshot_blob.bin"; 46 const char kSnapshotFileName[] = "snapshot_blob.bin";
47 47
48 // Constants for snapshot loading retries taken from: 48 // Constants for snapshot loading retries taken from:
49 // https://support.microsoft.com/en-us/kb/316609. 49 // https://support.microsoft.com/en-us/kb/316609.
50 const int kMaxOpenAttempts = 5; 50 const int kMaxOpenAttempts = 5;
51 const int kOpenRetryDelayMillis = 250; 51 const int kOpenRetryDelayMillis = 250;
52 52
53 void GetV8FilePaths(base::FilePath* natives_path_out, 53 void GetV8FilePath(const char* file_name, base::FilePath* path_out) {
54 base::FilePath* snapshot_path_out) {
55 #if !defined(OS_MACOSX) 54 #if !defined(OS_MACOSX)
56 base::FilePath data_path; 55 base::FilePath data_path;
57 PathService::Get(kV8SnapshotBasePathKey, &data_path); 56 PathService::Get(kV8SnapshotBasePathKey, &data_path);
58 DCHECK(!data_path.empty()); 57 DCHECK(!data_path.empty());
59 58
60 *natives_path_out = data_path.AppendASCII(kNativesFileName); 59 *path_out = data_path.AppendASCII(file_name);
61 *snapshot_path_out = data_path.AppendASCII(kSnapshotFileName);
62 #else // !defined(OS_MACOSX) 60 #else // !defined(OS_MACOSX)
63 base::ScopedCFTypeRef<CFStringRef> natives_file_name( 61 base::ScopedCFTypeRef<CFStringRef> natives_file_name(
64 base::SysUTF8ToCFStringRef(kNativesFileName)); 62 base::SysUTF8ToCFStringRef(file_name));
65 *natives_path_out = 63 *path_out = base::mac::PathForFrameworkBundleResource(natives_file_name);
66 base::mac::PathForFrameworkBundleResource(natives_file_name);
67 base::ScopedCFTypeRef<CFStringRef> snapshot_file_name(
68 base::SysUTF8ToCFStringRef(kSnapshotFileName));
69 *snapshot_path_out =
70 base::mac::PathForFrameworkBundleResource(snapshot_file_name);
71 DCHECK(!natives_path_out->empty());
72 DCHECK(!snapshot_path_out->empty());
73 #endif // !defined(OS_MACOSX) 64 #endif // !defined(OS_MACOSX)
65 DCHECK(!path_out->empty());
74 } 66 }
75 67
76 static bool MapV8Files(base::File natives_file, 68 static bool MapV8File(base::File file,
77 base::File snapshot_file, 69 base::MemoryMappedFile::Region region,
78 base::MemoryMappedFile::Region natives_region = 70 base::MemoryMappedFile** mmapped_file_out) {
79 base::MemoryMappedFile::Region::kWholeFile, 71 DCHECK(*mmapped_file_out == NULL);
80 base::MemoryMappedFile::Region snapshot_region = 72 base::MemoryMappedFile* mmapped_file = *mmapped_file_out =
81 base::MemoryMappedFile::Region::kWholeFile) { 73 new base::MemoryMappedFile;
82 g_mapped_natives = new base::MemoryMappedFile; 74 if (!mmapped_file->Initialize(file.Pass(), region)) {
83 if (!g_mapped_natives->IsValid()) { 75 delete mmapped_file;
84 if (!g_mapped_natives->Initialize(natives_file.Pass(), natives_region)) { 76 *mmapped_file_out = NULL;
85 delete g_mapped_natives; 77 return false;
86 g_mapped_natives = NULL;
87 LOG(FATAL) << "Couldn't mmap v8 natives data file";
88 return false;
89 }
90 }
91
92 g_mapped_snapshot = new base::MemoryMappedFile;
93 if (!g_mapped_snapshot->IsValid()) {
94 if (!g_mapped_snapshot->Initialize(snapshot_file.Pass(), snapshot_region)) {
95 delete g_mapped_snapshot;
96 g_mapped_snapshot = NULL;
97 LOG(ERROR) << "Couldn't mmap v8 snapshot data file";
98 return false;
99 }
100 } 78 }
101 79
102 return true; 80 return true;
103 } 81 }
104 82
105 static bool OpenV8File(const base::FilePath& path, 83 static bool OpenV8File(const base::FilePath& path,
106 int flags, 84 int flags,
107 base::File& file) { 85 base::File& file) {
108 // Re-try logic here is motivated by http://crbug.com/479537 86 // 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). 87 // for A/V on Windows (https://support.microsoft.com/en-us/kb/316609).
(...skipping 29 matching lines...) Expand all
139 117
140 UMA_HISTOGRAM_ENUMERATION("V8.Initializer.OpenV8File.Result", 118 UMA_HISTOGRAM_ENUMERATION("V8.Initializer.OpenV8File.Result",
141 result, 119 result,
142 OpenV8FileResult::MAX_VALUE); 120 OpenV8FileResult::MAX_VALUE);
143 121
144 return result == OpenV8FileResult::OPENED 122 return result == OpenV8FileResult::OPENED
145 || result == OpenV8FileResult::OPENED_RETRY; 123 || result == OpenV8FileResult::OPENED_RETRY;
146 } 124 }
147 125
148 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) 126 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA)
149 bool VerifyV8SnapshotFile(base::MemoryMappedFile* snapshot_file, 127 bool VerifyV8StartupFile(base::MemoryMappedFile** file,
150 const unsigned char* fingerprint) { 128 const unsigned char* fingerprint) {
151 unsigned char output[crypto::kSHA256Length]; 129 unsigned char output[crypto::kSHA256Length];
152 crypto::SHA256HashString( 130 crypto::SHA256HashString(
153 base::StringPiece(reinterpret_cast<const char*>(snapshot_file->data()), 131 base::StringPiece(reinterpret_cast<const char*>((*file)->data()),
154 snapshot_file->length()), 132 (*file)->length()),
155 output, sizeof(output)); 133 output, sizeof(output));
156 return !memcmp(fingerprint, output, sizeof(output)); 134 if (!memcmp(fingerprint, output, sizeof(output))) {
135 return true;
136 }
137 delete *file;
138 *file = NULL;
139 return false;
157 } 140 }
158 #endif // V8_VERIFY_EXTERNAL_STARTUP_DATA 141 #endif // V8_VERIFY_EXTERNAL_STARTUP_DATA
159 #endif // V8_USE_EXTERNAL_STARTUP_DATA 142 #endif // V8_USE_EXTERNAL_STARTUP_DATA
160 143
161 bool GenerateEntropy(unsigned char* buffer, size_t amount) { 144 bool GenerateEntropy(unsigned char* buffer, size_t amount) {
162 base::RandBytes(buffer, amount); 145 base::RandBytes(buffer, amount);
163 return true; 146 return true;
164 } 147 }
165 148
166 } // namespace 149 } // namespace
167 150
168 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) 151 #if defined(V8_USE_EXTERNAL_STARTUP_DATA)
169 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) 152 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA)
170 // Defined in gen/gin/v8_snapshot_fingerprint.cc 153 // Defined in gen/gin/v8_snapshot_fingerprint.cc
171 extern const unsigned char g_natives_fingerprint[]; 154 extern const unsigned char g_natives_fingerprint[];
172 extern const unsigned char g_snapshot_fingerprint[]; 155 extern const unsigned char g_snapshot_fingerprint[];
173 #endif // V8_VERIFY_EXTERNAL_STARTUP_DATA 156 #endif // V8_VERIFY_EXTERNAL_STARTUP_DATA
174 157
175 // static 158 enum LoadV8FileResult {
176 bool V8Initializer::LoadV8Snapshot() { 159 V8_LOAD_SUCCESS = 0,
160 V8_LOAD_FAILED_OPEN,
161 V8_LOAD_FAILED_MAP,
162 V8_LOAD_FAILED_VERIFY,
163 V8_LOAD_MAX_VALUE
164 };
177 165
178 enum LoadV8SnapshotResult { 166 static LoadV8FileResult OpenMapVerify(
179 SUCCESS = 0, 167 const char* file_name,
180 FAILED_OPEN, 168 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA)
181 FAILED_MAP, 169 const unsigned char* fingerprint,
182 FAILED_VERIFY, 170 #endif
183 MAX_VALUE 171 base::MemoryMappedFile** mmapped_file_out) {
184 }; 172 base::FilePath path;
173 GetV8FilePath(file_name, &path);
185 174
186 if (g_mapped_natives && g_mapped_snapshot) 175 base::File file;
187 return true;
188
189 base::FilePath natives_data_path;
190 base::FilePath snapshot_data_path;
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; 176 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ;
196 177
197 LoadV8SnapshotResult result; 178 if (!OpenV8File(path, flags, file))
198 if (!OpenV8File(natives_data_path, flags, natives_file) || 179 return V8_LOAD_FAILED_OPEN;
199 !OpenV8File(snapshot_data_path, flags, snapshot_file)) { 180 if (!MapV8File(file.Pass(), base::MemoryMappedFile::Region::kWholeFile,
200 result = LoadV8SnapshotResult::FAILED_OPEN; 181 mmapped_file_out))
201 } else if (!MapV8Files(natives_file.Pass(), snapshot_file.Pass())) { 182 return V8_LOAD_FAILED_MAP;
202 result = LoadV8SnapshotResult::FAILED_MAP;
203 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) 183 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA)
204 } else if (!VerifyV8SnapshotFile(g_mapped_natives, g_natives_fingerprint) || 184 if (!VerifyV8StartupFile(mmapped_file_out, fingerprint))
205 !VerifyV8SnapshotFile(g_mapped_snapshot, g_snapshot_fingerprint)) { 185 return V8_LOAD_FAILED_VERIFY;
206 result = LoadV8SnapshotResult::FAILED_VERIFY;
207 #endif // V8_VERIFY_EXTERNAL_STARTUP_DATA 186 #endif // V8_VERIFY_EXTERNAL_STARTUP_DATA
208 } else { 187 return V8_LOAD_SUCCESS;
209 result = LoadV8SnapshotResult::SUCCESS;
210 }
211
212 UMA_HISTOGRAM_ENUMERATION("V8.Initializer.LoadV8Snapshot.Result",
213 result,
214 LoadV8SnapshotResult::MAX_VALUE);
215 return result == LoadV8SnapshotResult::SUCCESS;
216 } 188 }
217 189
218 // static 190 // static
219 bool V8Initializer::LoadV8SnapshotFromFD(base::PlatformFile natives_pf, 191 void V8Initializer::LoadV8Snapshot() {
220 int64 natives_offset, 192 if (g_mapped_snapshot)
221 int64 natives_size, 193 return;
222 base::PlatformFile snapshot_pf, 194
195 LoadV8FileResult result = OpenMapVerify(kSnapshotFileName,
196 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA)
197 g_snapshot_fingerprint,
198 #endif
199 &g_mapped_snapshot);
200 UMA_HISTOGRAM_ENUMERATION("V8.Initializer.LoadV8Snapshot.Result", result,
201 V8_LOAD_MAX_VALUE);
202 }
203
204 void V8Initializer::LoadV8Natives() {
205 if (g_mapped_natives)
206 return;
207
208 LoadV8FileResult result = OpenMapVerify(kNativesFileName,
209 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA)
210 g_natives_fingerprint,
211 #endif
212 &g_mapped_natives);
213 if (result != V8_LOAD_SUCCESS) {
214 LOG(FATAL) << "Couldn't mmap v8 natives data file, status code is "
215 << static_cast<int>(result);
216 }
217 }
218
219 // static
220 void V8Initializer::LoadV8SnapshotFromFD(base::PlatformFile snapshot_pf,
223 int64 snapshot_offset, 221 int64 snapshot_offset,
224 int64 snapshot_size) { 222 int64 snapshot_size) {
225 if (g_mapped_natives && g_mapped_snapshot) 223 if (g_mapped_snapshot)
226 return true; 224 return;
225
226 if (snapshot_pf == reinterpret_cast<base::PlatformFile>(-1))
227 return;
228
229 base::MemoryMappedFile::Region snapshot_region =
230 base::MemoryMappedFile::Region::kWholeFile;
231 if (snapshot_size != 0 || snapshot_offset != 0) {
232 snapshot_region =
233 base::MemoryMappedFile::Region(snapshot_offset, snapshot_size);
234 }
235
236 LoadV8FileResult result = V8_LOAD_SUCCESS;
237 if (!MapV8File(base::File(snapshot_pf), snapshot_region, &g_mapped_snapshot))
238 result = V8_LOAD_FAILED_MAP;
239 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA)
240 if (!VerifyV8StartupFile(&g_mapped_snapshot, g_snapshot_fingerprint))
241 result = V8_LOAD_FAILED_VERIFY;
242 #endif // V8_VERIFY_EXTERNAL_STARTUP_DATA
243 UMA_HISTOGRAM_ENUMERATION("V8.Initializer.LoadV8Snapshot.Result", result,
244 V8_LOAD_MAX_VALUE);
245 }
246
247 // static
248 void V8Initializer::LoadV8NativesFromFD(base::PlatformFile natives_pf,
249 int64 natives_offset,
250 int64 natives_size) {
251 if (g_mapped_natives)
252 return;
253
254 CHECK_NE(natives_pf, reinterpret_cast<base::PlatformFile>(-1));
227 255
228 base::MemoryMappedFile::Region natives_region = 256 base::MemoryMappedFile::Region natives_region =
229 base::MemoryMappedFile::Region::kWholeFile; 257 base::MemoryMappedFile::Region::kWholeFile;
230 if (natives_size != 0 || natives_offset != 0) { 258 if (natives_size != 0 || natives_offset != 0) {
231 natives_region = 259 natives_region =
232 base::MemoryMappedFile::Region(natives_offset, natives_size); 260 base::MemoryMappedFile::Region(natives_offset, natives_size);
233 } 261 }
234 262
235 base::MemoryMappedFile::Region snapshot_region = 263 if (!MapV8File(base::File(natives_pf), natives_region, &g_mapped_natives)) {
236 base::MemoryMappedFile::Region::kWholeFile; 264 LOG(FATAL) << "Couldn't mmap v8 natives data file";
237 if (natives_size != 0 || natives_offset != 0) {
238 snapshot_region =
239 base::MemoryMappedFile::Region(snapshot_offset, snapshot_size);
240 } 265 }
241 266 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA)
242 return MapV8Files(base::File(natives_pf), base::File(snapshot_pf), 267 if (!VerifyV8StartupFile(&g_mapped_natives, g_natives_fingerprint)) {
243 natives_region, snapshot_region); 268 LOG(FATAL) << "Couldn't verify contents of v8 natives data file";
269 }
270 #endif // V8_VERIFY_EXTERNAL_STARTUP_DATA
244 } 271 }
245 272
246 // static 273 // static
247 bool V8Initializer::OpenV8FilesForChildProcesses( 274 bool V8Initializer::OpenV8FilesForChildProcesses(
248 base::PlatformFile* natives_fd_out, 275 base::PlatformFile* natives_fd_out,
249 base::PlatformFile* snapshot_fd_out) { 276 base::PlatformFile* snapshot_fd_out) {
250 base::FilePath natives_data_path; 277 base::FilePath natives_data_path;
251 base::FilePath snapshot_data_path; 278 base::FilePath snapshot_data_path;
252 GetV8FilePaths(&natives_data_path, &snapshot_data_path); 279 GetV8FilePath(kNativesFileName, &natives_data_path);
280 GetV8FilePath(kSnapshotFileName, &snapshot_data_path);
253 281
254 base::File natives_data_file; 282 base::File natives_data_file;
255 base::File snapshot_data_file; 283 base::File snapshot_data_file;
256 int file_flags = base::File::FLAG_OPEN | base::File::FLAG_READ; 284 int file_flags = base::File::FLAG_OPEN | base::File::FLAG_READ;
257 285
258 bool success = OpenV8File(natives_data_path, file_flags, natives_data_file) && 286 bool natives_success =
259 OpenV8File(snapshot_data_path, file_flags, snapshot_data_file); 287 OpenV8File(natives_data_path, file_flags, natives_data_file);
260 if (success) { 288 if (natives_success) {
261 *natives_fd_out = natives_data_file.TakePlatformFile(); 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) {
262 *snapshot_fd_out = snapshot_data_file.TakePlatformFile(); 294 *snapshot_fd_out = snapshot_data_file.TakePlatformFile();
263 } 295 }
264 return success; 296 // We can start up without the snapshot file, but not without the natives.
297 return natives_success;
265 } 298 }
266 299
267 #endif // V8_USE_EXTERNAL_STARTUP_DATA 300 #endif // V8_USE_EXTERNAL_STARTUP_DATA
268 301
269 // static 302 // static
270 void V8Initializer::Initialize(gin::IsolateHolder::ScriptMode mode) { 303 void V8Initializer::Initialize(gin::IsolateHolder::ScriptMode mode) {
271 static bool v8_is_initialized = false; 304 static bool v8_is_initialized = false;
272 if (v8_is_initialized) 305 if (v8_is_initialized)
273 return; 306 return;
274 307
275 v8::V8::InitializePlatform(V8Platform::Get()); 308 v8::V8::InitializePlatform(V8Platform::Get());
276 309
277 if (gin::IsolateHolder::kStrictMode == mode) { 310 if (gin::IsolateHolder::kStrictMode == mode) {
278 static const char use_strict[] = "--use_strict"; 311 static const char use_strict[] = "--use_strict";
279 v8::V8::SetFlagsFromString(use_strict, sizeof(use_strict) - 1); 312 v8::V8::SetFlagsFromString(use_strict, sizeof(use_strict) - 1);
280 } 313 }
281 314
282 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) 315 #if defined(V8_USE_EXTERNAL_STARTUP_DATA)
283 v8::StartupData natives; 316 v8::StartupData natives;
284 natives.data = reinterpret_cast<const char*>(g_mapped_natives->data()); 317 natives.data = reinterpret_cast<const char*>(g_mapped_natives->data());
285 natives.raw_size = static_cast<int>(g_mapped_natives->length()); 318 natives.raw_size = static_cast<int>(g_mapped_natives->length());
286 v8::V8::SetNativesDataBlob(&natives); 319 v8::V8::SetNativesDataBlob(&natives);
287 320
288 v8::StartupData snapshot; 321 if (g_mapped_snapshot != NULL) {
289 snapshot.data = reinterpret_cast<const char*>(g_mapped_snapshot->data()); 322 v8::StartupData snapshot;
290 snapshot.raw_size = static_cast<int>(g_mapped_snapshot->length()); 323 snapshot.data = reinterpret_cast<const char*>(g_mapped_snapshot->data());
291 v8::V8::SetSnapshotDataBlob(&snapshot); 324 snapshot.raw_size = static_cast<int>(g_mapped_snapshot->length());
325 v8::V8::SetSnapshotDataBlob(&snapshot);
326 }
292 #endif // V8_USE_EXTERNAL_STARTUP_DATA 327 #endif // V8_USE_EXTERNAL_STARTUP_DATA
293 328
294 v8::V8::SetEntropySource(&GenerateEntropy); 329 v8::V8::SetEntropySource(&GenerateEntropy);
295 v8::V8::Initialize(); 330 v8::V8::Initialize();
296 331
297 v8_is_initialized = true; 332 v8_is_initialized = true;
298 } 333 }
299 334
300 // static 335 // static
301 void V8Initializer::GetV8ExternalSnapshotData(const char** natives_data_out, 336 void V8Initializer::GetV8ExternalSnapshotData(const char** natives_data_out,
302 int* natives_size_out, 337 int* natives_size_out,
303 const char** snapshot_data_out, 338 const char** snapshot_data_out,
304 int* snapshot_size_out) { 339 int* snapshot_size_out) {
305 if (!g_mapped_natives || !g_mapped_snapshot) { 340 if (g_mapped_natives) {
306 *natives_data_out = *snapshot_data_out = NULL; 341 *natives_data_out = reinterpret_cast<const char*>(g_mapped_natives->data());
307 *natives_size_out = *snapshot_size_out = 0; 342 *natives_size_out = static_cast<int>(g_mapped_natives->length());
308 return; 343 } else {
344 *natives_data_out = NULL;
345 *natives_size_out = 0;
309 } 346 }
310 *natives_data_out = reinterpret_cast<const char*>(g_mapped_natives->data()); 347 if (g_mapped_snapshot) {
311 *snapshot_data_out = reinterpret_cast<const char*>(g_mapped_snapshot->data()); 348 *snapshot_data_out =
312 *natives_size_out = static_cast<int>(g_mapped_natives->length()); 349 reinterpret_cast<const char*>(g_mapped_snapshot->data());
313 *snapshot_size_out = static_cast<int>(g_mapped_snapshot->length()); 350 *snapshot_size_out = static_cast<int>(g_mapped_snapshot->length());
351 } else {
352 *snapshot_data_out = NULL;
353 *snapshot_size_out = 0;
354 }
314 } 355 }
315 356
316 } // namespace gin 357 } // namespace gin
OLDNEW
« no previous file with comments | « gin/v8_initializer.h ('k') | media/blink/run_all_unittests.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698