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