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