OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project 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 "src/api.h" | 5 #include "src/api.h" |
6 | 6 |
7 #include <string.h> // For memcpy, strlen. | 7 #include <string.h> // For memcpy, strlen. |
8 #ifdef V8_USE_ADDRESS_SANITIZER | 8 #ifdef V8_USE_ADDRESS_SANITIZER |
9 #include <sanitizer/asan_interface.h> | 9 #include <sanitizer/asan_interface.h> |
10 #endif // V8_USE_ADDRESS_SANITIZER | 10 #endif // V8_USE_ADDRESS_SANITIZER |
11 #include <cmath> // For isnan. | 11 #include <cmath> // For isnan. |
12 #include <limits> | 12 #include <limits> |
13 #include <vector> | 13 #include <vector> |
14 #include "include/v8-debug.h" | 14 #include "include/v8-debug.h" |
15 #include "include/v8-experimental.h" | 15 #include "include/v8-experimental.h" |
16 #include "include/v8-profiler.h" | 16 #include "include/v8-profiler.h" |
17 #include "include/v8-testing.h" | 17 #include "include/v8-testing.h" |
| 18 #include "include/v8-util.h" |
18 #include "src/accessors.h" | 19 #include "src/accessors.h" |
19 #include "src/api-experimental.h" | 20 #include "src/api-experimental.h" |
20 #include "src/api-natives.h" | 21 #include "src/api-natives.h" |
21 #include "src/assert-scope.h" | 22 #include "src/assert-scope.h" |
22 #include "src/background-parsing-task.h" | 23 #include "src/background-parsing-task.h" |
23 #include "src/base/functional.h" | 24 #include "src/base/functional.h" |
24 #include "src/base/platform/platform.h" | 25 #include "src/base/platform/platform.h" |
25 #include "src/base/platform/time.h" | 26 #include "src/base/platform/time.h" |
26 #include "src/base/utils/random-number-generator.h" | 27 #include "src/base/utils/random-number-generator.h" |
27 #include "src/bootstrapper.h" | 28 #include "src/bootstrapper.h" |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
376 if (script->Run(context).IsEmpty()) return false; | 377 if (script->Run(context).IsEmpty()) return false; |
377 if (i::FLAG_profile_deserialization) { | 378 if (i::FLAG_profile_deserialization) { |
378 i::PrintF("Executing custom snapshot script %s took %0.3f ms\n", name, | 379 i::PrintF("Executing custom snapshot script %s took %0.3f ms\n", name, |
379 timer.Elapsed().InMillisecondsF()); | 380 timer.Elapsed().InMillisecondsF()); |
380 } | 381 } |
381 timer.Stop(); | 382 timer.Stop(); |
382 CHECK(!try_catch.HasCaught()); | 383 CHECK(!try_catch.HasCaught()); |
383 return true; | 384 return true; |
384 } | 385 } |
385 | 386 |
386 StartupData SerializeIsolateAndContext( | 387 struct SnapshotCreatorData { |
387 Isolate* isolate, Persistent<Context>* context, | 388 explicit SnapshotCreatorData(Isolate* isolate) |
388 i::StartupSerializer::FunctionCodeHandling function_code_handling) { | 389 : isolate_(isolate), contexts_(isolate), created_(false) {} |
389 if (context->IsEmpty()) return {NULL, 0}; | |
390 | 390 |
391 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); | 391 static SnapshotCreatorData* cast(void* data) { |
| 392 return reinterpret_cast<SnapshotCreatorData*>(data); |
| 393 } |
| 394 |
| 395 friend class v8::V8::SnapshotCreator; |
| 396 ArrayBufferAllocator allocator_; |
| 397 Isolate* isolate_; |
| 398 PersistentValueVector<Context> contexts_; |
| 399 bool created_; |
| 400 }; |
| 401 |
| 402 } // namespace |
| 403 |
| 404 V8::SnapshotCreator::SnapshotCreator(StartupData* existing_snapshot) { |
| 405 i::Isolate* internal_isolate = new i::Isolate(true); |
| 406 Isolate* isolate = reinterpret_cast<Isolate*>(internal_isolate); |
| 407 SnapshotCreatorData* data = new SnapshotCreatorData(isolate); |
| 408 data->isolate_ = isolate; |
| 409 internal_isolate->set_array_buffer_allocator(&data->allocator_); |
| 410 isolate->Enter(); |
| 411 if (existing_snapshot) { |
| 412 internal_isolate->set_snapshot_blob(existing_snapshot); |
| 413 i::Snapshot::Initialize(internal_isolate); |
| 414 } else { |
| 415 internal_isolate->Init(nullptr); |
| 416 } |
| 417 data_ = data; |
| 418 } |
| 419 |
| 420 V8::SnapshotCreator::~SnapshotCreator() { |
| 421 SnapshotCreatorData* data = SnapshotCreatorData::cast(data_); |
| 422 Isolate* isolate = data->isolate_; |
| 423 isolate->Exit(); |
| 424 isolate->Dispose(); |
| 425 delete data; |
| 426 } |
| 427 |
| 428 Isolate* V8::SnapshotCreator::GetIsolate() { |
| 429 return SnapshotCreatorData::cast(data_)->isolate_; |
| 430 } |
| 431 |
| 432 void V8::SnapshotCreator::AddContext(Local<Context> context) { |
| 433 DCHECK(!context.IsEmpty()); |
| 434 SnapshotCreatorData* data = SnapshotCreatorData::cast(data_); |
| 435 Isolate* isolate = data->isolate_; |
| 436 CHECK_EQ(isolate, context->GetIsolate()); |
| 437 data->contexts_.Append(context); |
| 438 } |
| 439 |
| 440 StartupData V8::SnapshotCreator::CreateBlob( |
| 441 V8::SnapshotCreator::FunctionCodeHandling function_code_handling) { |
| 442 SnapshotCreatorData* data = SnapshotCreatorData::cast(data_); |
| 443 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(data->isolate_); |
| 444 CHECK(!data->created_); |
392 | 445 |
393 // If we don't do this then we end up with a stray root pointing at the | 446 // If we don't do this then we end up with a stray root pointing at the |
394 // context even after we have disposed of the context. | 447 // context even after we have disposed of the context. |
395 internal_isolate->heap()->CollectAllAvailableGarbage("mksnapshot"); | 448 isolate->heap()->CollectAllAvailableGarbage("mksnapshot"); |
| 449 isolate->heap()->CompactWeakFixedArrays(); |
396 | 450 |
397 // GC may have cleared weak cells, so compact any WeakFixedArrays | 451 i::DisallowHeapAllocation no_gc_from_here_on; |
398 // found on the heap. | 452 |
399 i::HeapIterator iterator(internal_isolate->heap(), | 453 i::List<i::Object*> contexts(data->contexts_.Size()); |
400 i::HeapIterator::kFilterUnreachable); | 454 for (int i = 0; i < data->contexts_.Size(); i++) { |
401 for (i::HeapObject* o = iterator.next(); o != NULL; o = iterator.next()) { | 455 i::HandleScope scope(isolate); |
402 if (o->IsPrototypeInfo()) { | 456 i::Handle<i::Context> context = |
403 i::Object* prototype_users = i::PrototypeInfo::cast(o)->prototype_users(); | 457 v8::Utils::OpenHandle(*data->contexts_.Get(i)); |
404 if (prototype_users->IsWeakFixedArray()) { | 458 contexts.Add(*context); |
405 i::WeakFixedArray* array = i::WeakFixedArray::cast(prototype_users); | |
406 array->Compact<i::JSObject::PrototypeRegistryCompactionCallback>(); | |
407 } | |
408 } else if (o->IsScript()) { | |
409 i::Object* shared_list = i::Script::cast(o)->shared_function_infos(); | |
410 if (shared_list->IsWeakFixedArray()) { | |
411 i::WeakFixedArray* array = i::WeakFixedArray::cast(shared_list); | |
412 array->Compact<i::WeakFixedArray::NullCallback>(); | |
413 } | |
414 } | |
415 } | 459 } |
416 | 460 data->contexts_.Clear(); |
417 i::Object* raw_context = *v8::Utils::OpenPersistent(*context); | |
418 context->Reset(); | |
419 | 461 |
420 i::SnapshotByteSink snapshot_sink; | 462 i::SnapshotByteSink snapshot_sink; |
421 i::StartupSerializer ser(internal_isolate, &snapshot_sink, | 463 i::StartupSerializer startup_serializer(isolate, &snapshot_sink, |
422 function_code_handling); | 464 function_code_handling); |
423 ser.SerializeStrongReferences(); | 465 startup_serializer.SerializeStrongReferences(); |
424 | 466 |
425 i::SnapshotByteSink context_sink; | 467 i::SnapshotByteSink context_sink; |
426 i::PartialSerializer context_ser(internal_isolate, &ser, &context_sink); | 468 i::PartialSerializer context_serializer(isolate, &startup_serializer, |
427 context_ser.Serialize(&raw_context); | 469 &context_sink); |
428 ser.SerializeWeakReferencesAndDeferred(); | 470 // TODO(yangguo): support multiple contexts in the snapshot. |
| 471 DCHECK_EQ(1, contexts.length()); |
| 472 context_serializer.Serialize(&contexts[0]); |
| 473 startup_serializer.SerializeWeakReferencesAndDeferred(); |
429 | 474 |
430 return i::Snapshot::CreateSnapshotBlob(ser, context_ser); | 475 data->created_ = true; |
| 476 return i::Snapshot::CreateSnapshotBlob(startup_serializer, |
| 477 context_serializer); |
431 } | 478 } |
432 | 479 |
433 } // namespace | |
434 | |
435 StartupData V8::CreateSnapshotDataBlob(const char* embedded_source) { | 480 StartupData V8::CreateSnapshotDataBlob(const char* embedded_source) { |
436 // Create a new isolate and a new context from scratch, optionally run | 481 // Create a new isolate and a new context from scratch, optionally run |
437 // a script to embed, and serialize to create a snapshot blob. | 482 // a script to embed, and serialize to create a snapshot blob. |
438 StartupData result = {NULL, 0}; | 483 StartupData result = {nullptr, 0}; |
439 | |
440 base::ElapsedTimer timer; | 484 base::ElapsedTimer timer; |
441 timer.Start(); | 485 timer.Start(); |
442 | |
443 ArrayBufferAllocator allocator; | |
444 i::Isolate* internal_isolate = new i::Isolate(true); | |
445 internal_isolate->set_array_buffer_allocator(&allocator); | |
446 Isolate* isolate = reinterpret_cast<Isolate*>(internal_isolate); | |
447 | |
448 { | 486 { |
449 Isolate::Scope isolate_scope(isolate); | 487 SnapshotCreator snapshot_creator; |
450 internal_isolate->Init(NULL); | 488 Isolate* isolate = snapshot_creator.GetIsolate(); |
451 Persistent<Context> context; | |
452 { | 489 { |
453 HandleScope handle_scope(isolate); | 490 HandleScope scope(isolate); |
454 Local<Context> new_context = Context::New(isolate); | 491 Local<Context> context = Context::New(isolate); |
455 context.Reset(isolate, new_context); | |
456 if (embedded_source != NULL && | 492 if (embedded_source != NULL && |
457 !RunExtraCode(isolate, new_context, embedded_source, "<embedded>")) { | 493 !RunExtraCode(isolate, context, embedded_source, "<embedded>")) { |
458 context.Reset(); | 494 return result; |
459 } | 495 } |
| 496 snapshot_creator.AddContext(context); |
460 } | 497 } |
461 | 498 result = |
462 result = SerializeIsolateAndContext( | 499 snapshot_creator.CreateBlob(V8::SnapshotCreator::CLEAR_FUNCTION_CODE); |
463 isolate, &context, i::StartupSerializer::CLEAR_FUNCTION_CODE); | |
464 DCHECK(context.IsEmpty()); | |
465 } | 500 } |
466 isolate->Dispose(); | |
467 | 501 |
468 if (i::FLAG_profile_deserialization) { | 502 if (i::FLAG_profile_deserialization) { |
469 i::PrintF("Creating snapshot took %0.3f ms\n", | 503 i::PrintF("Creating snapshot took %0.3f ms\n", |
470 timer.Elapsed().InMillisecondsF()); | 504 timer.Elapsed().InMillisecondsF()); |
471 } | 505 } |
472 timer.Stop(); | 506 timer.Stop(); |
473 return result; | 507 return result; |
474 } | 508 } |
475 | 509 |
476 StartupData V8::WarmUpSnapshotDataBlob(StartupData cold_snapshot_blob, | 510 StartupData V8::WarmUpSnapshotDataBlob(StartupData cold_snapshot_blob, |
477 const char* warmup_source) { | 511 const char* warmup_source) { |
478 CHECK(cold_snapshot_blob.raw_size > 0 && cold_snapshot_blob.data != NULL); | 512 CHECK(cold_snapshot_blob.raw_size > 0 && cold_snapshot_blob.data != NULL); |
479 CHECK(warmup_source != NULL); | 513 CHECK(warmup_source != NULL); |
480 // Use following steps to create a warmed up snapshot blob from a cold one: | 514 // Use following steps to create a warmed up snapshot blob from a cold one: |
481 // - Create a new isolate from the cold snapshot. | 515 // - Create a new isolate from the cold snapshot. |
482 // - Create a new context to run the warmup script. This will trigger | 516 // - Create a new context to run the warmup script. This will trigger |
483 // compilation of executed functions. | 517 // compilation of executed functions. |
484 // - Create a new context. This context will be unpolluted. | 518 // - Create a new context. This context will be unpolluted. |
485 // - Serialize the isolate and the second context into a new snapshot blob. | 519 // - Serialize the isolate and the second context into a new snapshot blob. |
486 StartupData result = {NULL, 0}; | 520 StartupData result = {nullptr, 0}; |
487 | |
488 base::ElapsedTimer timer; | 521 base::ElapsedTimer timer; |
489 timer.Start(); | 522 timer.Start(); |
490 | |
491 ArrayBufferAllocator allocator; | |
492 i::Isolate* internal_isolate = new i::Isolate(true); | |
493 internal_isolate->set_array_buffer_allocator(&allocator); | |
494 internal_isolate->set_snapshot_blob(&cold_snapshot_blob); | |
495 Isolate* isolate = reinterpret_cast<Isolate*>(internal_isolate); | |
496 | |
497 { | 523 { |
498 Isolate::Scope isolate_scope(isolate); | 524 SnapshotCreator snapshot_creator(&cold_snapshot_blob); |
499 i::Snapshot::Initialize(internal_isolate); | 525 Isolate* isolate = snapshot_creator.GetIsolate(); |
500 Persistent<Context> context; | 526 { |
501 bool success; | 527 HandleScope scope(isolate); |
| 528 Local<Context> context = Context::New(isolate); |
| 529 if (!RunExtraCode(isolate, context, warmup_source, "<warm-up>")) { |
| 530 return result; |
| 531 } |
| 532 } |
502 { | 533 { |
503 HandleScope handle_scope(isolate); | 534 HandleScope handle_scope(isolate); |
504 Local<Context> new_context = Context::New(isolate); | 535 isolate->ContextDisposedNotification(false); |
505 success = RunExtraCode(isolate, new_context, warmup_source, "<warm-up>"); | 536 Local<Context> context = Context::New(isolate); |
| 537 snapshot_creator.AddContext(context); |
506 } | 538 } |
507 if (success) { | 539 result = |
508 HandleScope handle_scope(isolate); | 540 snapshot_creator.CreateBlob(V8::SnapshotCreator::KEEP_FUNCTION_CODE); |
509 isolate->ContextDisposedNotification(false); | |
510 Local<Context> new_context = Context::New(isolate); | |
511 context.Reset(isolate, new_context); | |
512 } | |
513 | |
514 result = SerializeIsolateAndContext( | |
515 isolate, &context, i::StartupSerializer::KEEP_FUNCTION_CODE); | |
516 DCHECK(context.IsEmpty()); | |
517 } | 541 } |
518 isolate->Dispose(); | |
519 | 542 |
520 if (i::FLAG_profile_deserialization) { | 543 if (i::FLAG_profile_deserialization) { |
521 i::PrintF("Warming up snapshot took %0.3f ms\n", | 544 i::PrintF("Warming up snapshot took %0.3f ms\n", |
522 timer.Elapsed().InMillisecondsF()); | 545 timer.Elapsed().InMillisecondsF()); |
523 } | 546 } |
524 timer.Stop(); | 547 timer.Stop(); |
525 return result; | 548 return result; |
526 } | 549 } |
527 | 550 |
528 | 551 |
(...skipping 8280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8809 Address callback_address = | 8832 Address callback_address = |
8810 reinterpret_cast<Address>(reinterpret_cast<intptr_t>(callback)); | 8833 reinterpret_cast<Address>(reinterpret_cast<intptr_t>(callback)); |
8811 VMState<EXTERNAL> state(isolate); | 8834 VMState<EXTERNAL> state(isolate); |
8812 ExternalCallbackScope call_scope(isolate, callback_address); | 8835 ExternalCallbackScope call_scope(isolate, callback_address); |
8813 callback(info); | 8836 callback(info); |
8814 } | 8837 } |
8815 | 8838 |
8816 | 8839 |
8817 } // namespace internal | 8840 } // namespace internal |
8818 } // namespace v8 | 8841 } // namespace v8 |
OLD | NEW |