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

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

Powered by Google App Engine
This is Rietveld 408576698