OLD | NEW |
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 "base/debug/alias.h" | 10 #include "base/debug/alias.h" |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 const base::PlatformFile kInvalidPlatformFile = | 43 const base::PlatformFile kInvalidPlatformFile = |
44 #if defined(OS_WIN) | 44 #if defined(OS_WIN) |
45 INVALID_HANDLE_VALUE; | 45 INVALID_HANDLE_VALUE; |
46 #else | 46 #else |
47 -1; | 47 -1; |
48 #endif | 48 #endif |
49 | 49 |
50 // File handles intentionally never closed. Not using File here because its | 50 // File handles intentionally never closed. Not using File here because its |
51 // Windows implementation guards against two instances owning the same | 51 // Windows implementation guards against two instances owning the same |
52 // PlatformFile (which we allow since we know it is never freed). | 52 // PlatformFile (which we allow since we know it is never freed). |
53 base::PlatformFile g_natives_pf = kInvalidPlatformFile; | 53 typedef std::map<const char*, |
54 base::PlatformFile g_snapshot_pf = kInvalidPlatformFile; | 54 std::pair<base::PlatformFile, base::MemoryMappedFile::Region>> |
55 base::MemoryMappedFile::Region g_natives_region; | 55 OpenedFileMap; |
56 base::MemoryMappedFile::Region g_snapshot_region; | 56 OpenedFileMap g_opened_files; |
| 57 |
| 58 OpenedFileMap::mapped_type& GetOpenedFile(const char* file) { |
| 59 if (g_opened_files.find(file) == g_opened_files.end()) { |
| 60 g_opened_files[file] = |
| 61 std::make_pair(kInvalidPlatformFile, base::MemoryMappedFile::Region()); |
| 62 } |
| 63 return g_opened_files[file]; |
| 64 } |
57 | 65 |
58 #if defined(OS_ANDROID) | 66 #if defined(OS_ANDROID) |
59 #ifdef __LP64__ | 67 const char kNativesFileName64[] = "natives_blob_64.bin"; |
60 const char kNativesFileName[] = "natives_blob_64.bin"; | 68 const char kSnapshotFileName64[] = "snapshot_blob_64.bin"; |
61 const char kSnapshotFileName[] = "snapshot_blob_64.bin"; | 69 const char kNativesFileName32[] = "natives_blob_32.bin"; |
| 70 const char kSnapshotFileName32[] = "snapshot_blob_32.bin"; |
| 71 |
| 72 #if defined(__LP64__) |
| 73 #define kNativesFileName kNativesFileName64 |
| 74 #define kSnapshotFileName kSnapshotFileName64 |
62 #else | 75 #else |
63 const char kNativesFileName[] = "natives_blob_32.bin"; | 76 #define kNativesFileName kNativesFileName32 |
64 const char kSnapshotFileName[] = "snapshot_blob_32.bin"; | 77 #define kSnapshotFileName kSnapshotFileName32 |
65 #endif // __LP64__ | 78 #endif |
66 | 79 |
67 #else // defined(OS_ANDROID) | 80 #else // defined(OS_ANDROID) |
68 const char kNativesFileName[] = "natives_blob.bin"; | 81 const char kNativesFileName[] = "natives_blob.bin"; |
69 const char kSnapshotFileName[] = "snapshot_blob.bin"; | 82 const char kSnapshotFileName[] = "snapshot_blob.bin"; |
70 #endif // defined(OS_ANDROID) | 83 #endif // defined(OS_ANDROID) |
71 | 84 |
72 void GetV8FilePath(const char* file_name, base::FilePath* path_out) { | 85 void GetV8FilePath(const char* file_name, base::FilePath* path_out) { |
73 #if !defined(OS_MACOSX) | 86 #if !defined(OS_MACOSX) |
74 base::FilePath data_path; | 87 base::FilePath data_path; |
75 #if defined(OS_ANDROID) | 88 #if defined(OS_ANDROID) |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 } | 176 } |
164 } | 177 } |
165 #endif // defined(OS_ANDROID) | 178 #endif // defined(OS_ANDROID) |
166 | 179 |
167 UMA_HISTOGRAM_ENUMERATION("V8.Initializer.OpenV8File.Result", | 180 UMA_HISTOGRAM_ENUMERATION("V8.Initializer.OpenV8File.Result", |
168 result, | 181 result, |
169 OpenV8FileResult::MAX_VALUE); | 182 OpenV8FileResult::MAX_VALUE); |
170 return file.TakePlatformFile(); | 183 return file.TakePlatformFile(); |
171 } | 184 } |
172 | 185 |
173 void OpenNativesFileIfNecessary() { | 186 static const OpenedFileMap::mapped_type OpenFileIfNecessary( |
174 if (g_natives_pf == kInvalidPlatformFile) { | 187 const char* file_name) { |
175 g_natives_pf = OpenV8File(kNativesFileName, &g_natives_region); | 188 OpenedFileMap::mapped_type& opened = GetOpenedFile(file_name); |
| 189 if (opened.first == kInvalidPlatformFile) { |
| 190 opened.first = OpenV8File(file_name, &opened.second); |
176 } | 191 } |
177 } | 192 return opened; |
178 | |
179 void OpenSnapshotFileIfNecessary() { | |
180 if (g_snapshot_pf == kInvalidPlatformFile) { | |
181 g_snapshot_pf = OpenV8File(kSnapshotFileName, &g_snapshot_region); | |
182 } | |
183 } | 193 } |
184 | 194 |
185 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) | 195 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) |
186 bool VerifyV8StartupFile(base::MemoryMappedFile** file, | 196 bool VerifyV8StartupFile(base::MemoryMappedFile** file, |
187 const unsigned char* fingerprint) { | 197 const unsigned char* fingerprint) { |
188 unsigned char output[crypto::kSHA256Length]; | 198 unsigned char output[crypto::kSHA256Length]; |
189 crypto::SHA256HashString( | 199 crypto::SHA256HashString( |
190 base::StringPiece(reinterpret_cast<const char*>((*file)->data()), | 200 base::StringPiece(reinterpret_cast<const char*>((*file)->data()), |
191 (*file)->length()), | 201 (*file)->length()), |
192 output, sizeof(output)); | 202 output, sizeof(output)); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
229 #endif // V8_VERIFY_EXTERNAL_STARTUP_DATA | 239 #endif // V8_VERIFY_EXTERNAL_STARTUP_DATA |
230 | 240 |
231 enum LoadV8FileResult { | 241 enum LoadV8FileResult { |
232 V8_LOAD_SUCCESS = 0, | 242 V8_LOAD_SUCCESS = 0, |
233 V8_LOAD_FAILED_OPEN, | 243 V8_LOAD_FAILED_OPEN, |
234 V8_LOAD_FAILED_MAP, | 244 V8_LOAD_FAILED_MAP, |
235 V8_LOAD_FAILED_VERIFY, | 245 V8_LOAD_FAILED_VERIFY, |
236 V8_LOAD_MAX_VALUE | 246 V8_LOAD_MAX_VALUE |
237 }; | 247 }; |
238 | 248 |
239 static LoadV8FileResult MapVerify(base::PlatformFile platform_file, | 249 static LoadV8FileResult MapVerify(const OpenedFileMap::mapped_type& file_region, |
240 const base::MemoryMappedFile::Region& region, | |
241 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) | 250 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) |
242 const unsigned char* fingerprint, | 251 const unsigned char* fingerprint, |
243 #endif | 252 #endif |
244 base::MemoryMappedFile** mmapped_file_out) { | 253 base::MemoryMappedFile** mmapped_file_out) { |
245 if (platform_file == kInvalidPlatformFile) | 254 if (file_region.first == kInvalidPlatformFile) |
246 return V8_LOAD_FAILED_OPEN; | 255 return V8_LOAD_FAILED_OPEN; |
247 if (!MapV8File(platform_file, region, mmapped_file_out)) | 256 if (!MapV8File(file_region.first, file_region.second, mmapped_file_out)) |
248 return V8_LOAD_FAILED_MAP; | 257 return V8_LOAD_FAILED_MAP; |
249 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) | 258 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) |
250 if (!VerifyV8StartupFile(mmapped_file_out, fingerprint)) | 259 if (!VerifyV8StartupFile(mmapped_file_out, fingerprint)) |
251 return V8_LOAD_FAILED_VERIFY; | 260 return V8_LOAD_FAILED_VERIFY; |
252 #endif // V8_VERIFY_EXTERNAL_STARTUP_DATA | 261 #endif // V8_VERIFY_EXTERNAL_STARTUP_DATA |
253 return V8_LOAD_SUCCESS; | 262 return V8_LOAD_SUCCESS; |
254 } | 263 } |
255 | 264 |
256 // static | 265 // static |
257 void V8Initializer::LoadV8Snapshot() { | 266 void V8Initializer::LoadV8Snapshot() { |
258 if (g_mapped_snapshot) | 267 if (g_mapped_snapshot) |
259 return; | 268 return; |
260 | 269 |
261 OpenSnapshotFileIfNecessary(); | 270 OpenFileIfNecessary(kSnapshotFileName); |
262 LoadV8FileResult result = MapVerify(g_snapshot_pf, g_snapshot_region, | 271 LoadV8FileResult result = MapVerify(GetOpenedFile(kSnapshotFileName), |
263 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) | 272 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) |
264 g_snapshot_fingerprint, | 273 g_snapshot_fingerprint, |
265 #endif | 274 #endif |
266 &g_mapped_snapshot); | 275 &g_mapped_snapshot); |
267 // V8 can't start up without the source of the natives, but it can | 276 // V8 can't start up without the source of the natives, but it can |
268 // start up (slower) without the snapshot. | 277 // start up (slower) without the snapshot. |
269 UMA_HISTOGRAM_ENUMERATION("V8.Initializer.LoadV8Snapshot.Result", result, | 278 UMA_HISTOGRAM_ENUMERATION("V8.Initializer.LoadV8Snapshot.Result", result, |
270 V8_LOAD_MAX_VALUE); | 279 V8_LOAD_MAX_VALUE); |
271 } | 280 } |
272 | 281 |
273 void V8Initializer::LoadV8Natives() { | 282 void V8Initializer::LoadV8Natives() { |
274 if (g_mapped_natives) | 283 if (g_mapped_natives) |
275 return; | 284 return; |
276 | 285 |
277 OpenNativesFileIfNecessary(); | 286 OpenFileIfNecessary(kNativesFileName); |
278 LoadV8FileResult result = MapVerify(g_natives_pf, g_natives_region, | 287 LoadV8FileResult result = MapVerify(GetOpenedFile(kNativesFileName), |
279 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) | 288 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) |
280 g_natives_fingerprint, | 289 g_natives_fingerprint, |
281 #endif | 290 #endif |
282 &g_mapped_natives); | 291 &g_mapped_natives); |
283 if (result != V8_LOAD_SUCCESS) { | 292 if (result != V8_LOAD_SUCCESS) { |
284 LOG(FATAL) << "Couldn't mmap v8 natives data file, status code is " | 293 LOG(FATAL) << "Couldn't mmap v8 natives data file, status code is " |
285 << static_cast<int>(result); | 294 << static_cast<int>(result); |
286 } | 295 } |
287 } | 296 } |
288 | 297 |
(...skipping 15 matching lines...) Expand all Loading... |
304 } | 313 } |
305 | 314 |
306 LoadV8FileResult result = V8_LOAD_SUCCESS; | 315 LoadV8FileResult result = V8_LOAD_SUCCESS; |
307 if (!MapV8File(snapshot_pf, snapshot_region, &g_mapped_snapshot)) | 316 if (!MapV8File(snapshot_pf, snapshot_region, &g_mapped_snapshot)) |
308 result = V8_LOAD_FAILED_MAP; | 317 result = V8_LOAD_FAILED_MAP; |
309 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) | 318 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) |
310 if (!VerifyV8StartupFile(&g_mapped_snapshot, g_snapshot_fingerprint)) | 319 if (!VerifyV8StartupFile(&g_mapped_snapshot, g_snapshot_fingerprint)) |
311 result = V8_LOAD_FAILED_VERIFY; | 320 result = V8_LOAD_FAILED_VERIFY; |
312 #endif // V8_VERIFY_EXTERNAL_STARTUP_DATA | 321 #endif // V8_VERIFY_EXTERNAL_STARTUP_DATA |
313 if (result == V8_LOAD_SUCCESS) { | 322 if (result == V8_LOAD_SUCCESS) { |
314 g_snapshot_pf = snapshot_pf; | 323 g_opened_files[kSnapshotFileName] = |
315 g_snapshot_region = snapshot_region; | 324 std::make_pair(snapshot_pf, snapshot_region); |
316 } | 325 } |
317 UMA_HISTOGRAM_ENUMERATION("V8.Initializer.LoadV8Snapshot.Result", result, | 326 UMA_HISTOGRAM_ENUMERATION("V8.Initializer.LoadV8Snapshot.Result", result, |
318 V8_LOAD_MAX_VALUE); | 327 V8_LOAD_MAX_VALUE); |
319 } | 328 } |
320 | 329 |
321 // static | 330 // static |
322 void V8Initializer::LoadV8NativesFromFD(base::PlatformFile natives_pf, | 331 void V8Initializer::LoadV8NativesFromFD(base::PlatformFile natives_pf, |
323 int64_t natives_offset, | 332 int64_t natives_offset, |
324 int64_t natives_size) { | 333 int64_t natives_size) { |
325 if (g_mapped_natives) | 334 if (g_mapped_natives) |
326 return; | 335 return; |
327 | 336 |
328 CHECK_NE(natives_pf, kInvalidPlatformFile); | 337 CHECK_NE(natives_pf, kInvalidPlatformFile); |
329 | 338 |
330 base::MemoryMappedFile::Region natives_region = | 339 base::MemoryMappedFile::Region natives_region = |
331 base::MemoryMappedFile::Region::kWholeFile; | 340 base::MemoryMappedFile::Region::kWholeFile; |
332 if (natives_size != 0 || natives_offset != 0) { | 341 if (natives_size != 0 || natives_offset != 0) { |
333 natives_region.offset = natives_offset; | 342 natives_region.offset = natives_offset; |
334 natives_region.size = natives_size; | 343 natives_region.size = natives_size; |
335 } | 344 } |
336 | 345 |
337 if (!MapV8File(natives_pf, natives_region, &g_mapped_natives)) { | 346 if (!MapV8File(natives_pf, natives_region, &g_mapped_natives)) { |
338 LOG(FATAL) << "Couldn't mmap v8 natives data file"; | 347 LOG(FATAL) << "Couldn't mmap v8 natives data file"; |
339 } | 348 } |
340 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) | 349 #if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) |
341 if (!VerifyV8StartupFile(&g_mapped_natives, g_natives_fingerprint)) { | 350 if (!VerifyV8StartupFile(&g_mapped_natives, g_natives_fingerprint)) { |
342 LOG(FATAL) << "Couldn't verify contents of v8 natives data file"; | 351 LOG(FATAL) << "Couldn't verify contents of v8 natives data file"; |
343 } | 352 } |
344 #endif // V8_VERIFY_EXTERNAL_STARTUP_DATA | 353 #endif // V8_VERIFY_EXTERNAL_STARTUP_DATA |
345 g_natives_pf = natives_pf; | 354 g_opened_files[kNativesFileName] = std::make_pair(natives_pf, natives_region); |
346 g_natives_region = natives_region; | |
347 } | 355 } |
348 | 356 |
349 // static | 357 // static |
350 base::PlatformFile V8Initializer::GetOpenNativesFileForChildProcesses( | 358 base::PlatformFile V8Initializer::GetOpenNativesFileForChildProcesses( |
351 base::MemoryMappedFile::Region* region_out) { | 359 base::MemoryMappedFile::Region* region_out) { |
352 OpenNativesFileIfNecessary(); | 360 const OpenedFileMap::mapped_type& opened = |
353 *region_out = g_natives_region; | 361 OpenFileIfNecessary(kNativesFileName); |
354 return g_natives_pf; | 362 *region_out = opened.second; |
| 363 return opened.first; |
355 } | 364 } |
356 | 365 |
357 // static | 366 // static |
358 base::PlatformFile V8Initializer::GetOpenSnapshotFileForChildProcesses( | 367 base::PlatformFile V8Initializer::GetOpenSnapshotFileForChildProcesses( |
359 base::MemoryMappedFile::Region* region_out) { | 368 base::MemoryMappedFile::Region* region_out) { |
360 OpenSnapshotFileIfNecessary(); | 369 const OpenedFileMap::mapped_type& opened = |
361 *region_out = g_snapshot_region; | 370 OpenFileIfNecessary(kSnapshotFileName); |
362 return g_snapshot_pf; | 371 *region_out = opened.second; |
| 372 return opened.first; |
363 } | 373 } |
| 374 |
| 375 #if defined(OS_ANDROID) |
| 376 // static |
| 377 base::PlatformFile V8Initializer::GetOpenNativesFileForChildProcesses( |
| 378 base::MemoryMappedFile::Region* region_out, |
| 379 bool abi_32_bit) { |
| 380 const char* natives_file = |
| 381 abi_32_bit ? kNativesFileName32 : kNativesFileName64; |
| 382 const OpenedFileMap::mapped_type& opened = OpenFileIfNecessary(natives_file); |
| 383 *region_out = opened.second; |
| 384 return opened.first; |
| 385 } |
| 386 |
| 387 // static |
| 388 base::PlatformFile V8Initializer::GetOpenSnapshotFileForChildProcesses( |
| 389 base::MemoryMappedFile::Region* region_out, |
| 390 bool abi_32_bit) { |
| 391 const char* snapshot_file = |
| 392 abi_32_bit ? kSnapshotFileName32 : kSnapshotFileName64; |
| 393 const OpenedFileMap::mapped_type& opened = OpenFileIfNecessary(snapshot_file); |
| 394 *region_out = opened.second; |
| 395 return opened.first; |
| 396 } |
| 397 #endif // defined(OS_ANDROID) |
364 #endif // defined(V8_USE_EXTERNAL_STARTUP_DATA) | 398 #endif // defined(V8_USE_EXTERNAL_STARTUP_DATA) |
365 | 399 |
366 // static | 400 // static |
367 void V8Initializer::Initialize(IsolateHolder::ScriptMode mode, | 401 void V8Initializer::Initialize(IsolateHolder::ScriptMode mode, |
368 IsolateHolder::V8ExtrasMode v8_extras_mode) { | 402 IsolateHolder::V8ExtrasMode v8_extras_mode) { |
369 static bool v8_is_initialized = false; | 403 static bool v8_is_initialized = false; |
370 if (v8_is_initialized) | 404 if (v8_is_initialized) |
371 return; | 405 return; |
372 | 406 |
373 v8::V8::InitializePlatform(V8Platform::Get()); | 407 v8::V8::InitializePlatform(V8Platform::Get()); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
416 if (g_mapped_snapshot) { | 450 if (g_mapped_snapshot) { |
417 *snapshot_data_out = | 451 *snapshot_data_out = |
418 reinterpret_cast<const char*>(g_mapped_snapshot->data()); | 452 reinterpret_cast<const char*>(g_mapped_snapshot->data()); |
419 *snapshot_size_out = static_cast<int>(g_mapped_snapshot->length()); | 453 *snapshot_size_out = static_cast<int>(g_mapped_snapshot->length()); |
420 } else { | 454 } else { |
421 *snapshot_data_out = NULL; | 455 *snapshot_data_out = NULL; |
422 *snapshot_size_out = 0; | 456 *snapshot_size_out = 0; |
423 } | 457 } |
424 } | 458 } |
425 | 459 |
| 460 #if defined(OS_ANDROID) |
| 461 // static |
| 462 base::FilePath V8Initializer::GetNativesFilePath(bool abi_32_bit) { |
| 463 base::FilePath path; |
| 464 GetV8FilePath(abi_32_bit ? kNativesFileName32 : kNativesFileName64, &path); |
| 465 return path; |
| 466 } |
| 467 |
| 468 // static |
| 469 base::FilePath V8Initializer::GetSnapshotFilePath(bool abi_32_bit) { |
| 470 base::FilePath path; |
| 471 GetV8FilePath(abi_32_bit ? kSnapshotFileName32 : kSnapshotFileName64, &path); |
| 472 return path; |
| 473 } |
| 474 #endif // defined(OS_ANDROID) |
| 475 |
426 } // namespace gin | 476 } // namespace gin |
OLD | NEW |