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 ArrayBufferAllocator allocator_; | |
396 Isolate* isolate_; | |
397 PersistentValueVector<Context> contexts_; | |
398 bool created_; | |
399 }; | |
400 | |
401 } // namespace | |
402 | |
403 SnapshotCreator::SnapshotCreator(StartupData* existing_snapshot) { | |
404 i::Isolate* internal_isolate = new i::Isolate(true); | |
405 Isolate* isolate = reinterpret_cast<Isolate*>(internal_isolate); | |
406 SnapshotCreatorData* data = new SnapshotCreatorData(isolate); | |
407 data->isolate_ = isolate; | |
408 internal_isolate->set_array_buffer_allocator(&data->allocator_); | |
409 isolate->Enter(); | |
410 if (existing_snapshot) { | |
411 internal_isolate->set_snapshot_blob(existing_snapshot); | |
412 i::Snapshot::Initialize(internal_isolate); | |
413 } else { | |
414 internal_isolate->Init(nullptr); | |
415 } | |
416 data_ = data; | |
417 } | |
418 | |
419 SnapshotCreator::~SnapshotCreator() { | |
420 SnapshotCreatorData* data = SnapshotCreatorData::cast(data_); | |
421 Isolate* isolate = data->isolate_; | |
422 isolate->Exit(); | |
423 isolate->Dispose(); | |
424 delete data; | |
425 } | |
426 | |
427 Isolate* SnapshotCreator::GetIsolate() { | |
428 return SnapshotCreatorData::cast(data_)->isolate_; | |
429 } | |
430 | |
431 void SnapshotCreator::AddContext(Local<Context> context) { | |
432 DCHECK(!context.IsEmpty()); | |
433 SnapshotCreatorData* data = SnapshotCreatorData::cast(data_); | |
434 Isolate* isolate = data->isolate_; | |
vogelheim
2016/06/09 13:42:07
maybe: DCHECK(!data->created_);
(I take it one co
| |
435 CHECK_EQ(isolate, context->GetIsolate()); | |
436 data->contexts_.Append(context); | |
437 } | |
438 | |
439 StartupData SnapshotCreator::CreateBlob( | |
440 SnapshotCreator::FunctionCodeHandling function_code_handling) { | |
441 SnapshotCreatorData* data = SnapshotCreatorData::cast(data_); | |
442 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(data->isolate_); | |
443 CHECK(!data->created_); | |
392 | 444 |
393 // If we don't do this then we end up with a stray root pointing at the | 445 // 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. | 446 // context even after we have disposed of the context. |
395 internal_isolate->heap()->CollectAllAvailableGarbage("mksnapshot"); | 447 isolate->heap()->CollectAllAvailableGarbage("mksnapshot"); |
448 isolate->heap()->CompactWeakFixedArrays(); | |
396 | 449 |
397 // GC may have cleared weak cells, so compact any WeakFixedArrays | 450 i::DisallowHeapAllocation no_gc_from_here_on; |
398 // found on the heap. | 451 |
399 i::HeapIterator iterator(internal_isolate->heap(), | 452 int num_contexts = static_cast<int>(data->contexts_.Size()); |
400 i::HeapIterator::kFilterUnreachable); | 453 i::List<i::Object*> contexts(num_contexts); |
401 for (i::HeapObject* o = iterator.next(); o != NULL; o = iterator.next()) { | 454 for (int i = 0; i < num_contexts; i++) { |
402 if (o->IsPrototypeInfo()) { | 455 i::HandleScope scope(isolate); |
403 i::Object* prototype_users = i::PrototypeInfo::cast(o)->prototype_users(); | 456 i::Handle<i::Context> context = |
404 if (prototype_users->IsWeakFixedArray()) { | 457 v8::Utils::OpenHandle(*data->contexts_.Get(i)); |
405 i::WeakFixedArray* array = i::WeakFixedArray::cast(prototype_users); | 458 contexts.Add(*context); |
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 = snapshot_creator.CreateBlob( |
462 result = SerializeIsolateAndContext( | 499 SnapshotCreator::FunctionCodeHandling::kClear); |
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 = snapshot_creator.CreateBlob( |
508 HandleScope handle_scope(isolate); | 540 SnapshotCreator::FunctionCodeHandling::kKeep); |
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 8249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8778 Address callback_address = | 8801 Address callback_address = |
8779 reinterpret_cast<Address>(reinterpret_cast<intptr_t>(callback)); | 8802 reinterpret_cast<Address>(reinterpret_cast<intptr_t>(callback)); |
8780 VMState<EXTERNAL> state(isolate); | 8803 VMState<EXTERNAL> state(isolate); |
8781 ExternalCallbackScope call_scope(isolate, callback_address); | 8804 ExternalCallbackScope call_scope(isolate, callback_address); |
8782 callback(info); | 8805 callback(info); |
8783 } | 8806 } |
8784 | 8807 |
8785 | 8808 |
8786 } // namespace internal | 8809 } // namespace internal |
8787 } // namespace v8 | 8810 } // namespace v8 |
OLD | NEW |