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 DCHECK(data->created_); |
| 422 Isolate* isolate = data->isolate_; |
| 423 isolate->Exit(); |
| 424 isolate->Dispose(); |
| 425 delete data; |
| 426 } |
| 427 |
| 428 Isolate* SnapshotCreator::GetIsolate() { |
| 429 return SnapshotCreatorData::cast(data_)->isolate_; |
| 430 } |
| 431 |
| 432 void SnapshotCreator::AddContext(Local<Context> context) { |
| 433 DCHECK(!context.IsEmpty()); |
| 434 SnapshotCreatorData* data = SnapshotCreatorData::cast(data_); |
| 435 DCHECK(!data->created_); |
| 436 Isolate* isolate = data->isolate_; |
| 437 CHECK_EQ(isolate, context->GetIsolate()); |
| 438 data->contexts_.Append(context); |
| 439 } |
| 440 |
| 441 StartupData SnapshotCreator::CreateBlob( |
| 442 SnapshotCreator::FunctionCodeHandling function_code_handling) { |
| 443 SnapshotCreatorData* data = SnapshotCreatorData::cast(data_); |
| 444 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(data->isolate_); |
| 445 DCHECK(!data->created_); |
392 | 446 |
393 // If we don't do this then we end up with a stray root pointing at the | 447 // 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. | 448 // context even after we have disposed of the context. |
395 internal_isolate->heap()->CollectAllAvailableGarbage("mksnapshot"); | 449 isolate->heap()->CollectAllAvailableGarbage("mksnapshot"); |
| 450 isolate->heap()->CompactWeakFixedArrays(); |
396 | 451 |
397 // GC may have cleared weak cells, so compact any WeakFixedArrays | 452 i::DisallowHeapAllocation no_gc_from_here_on; |
398 // found on the heap. | 453 |
399 i::HeapIterator iterator(internal_isolate->heap(), | 454 int num_contexts = static_cast<int>(data->contexts_.Size()); |
400 i::HeapIterator::kFilterUnreachable); | 455 i::List<i::Object*> contexts(num_contexts); |
401 for (i::HeapObject* o = iterator.next(); o != NULL; o = iterator.next()) { | 456 for (int i = 0; i < num_contexts; i++) { |
402 if (o->IsPrototypeInfo()) { | 457 i::HandleScope scope(isolate); |
403 i::Object* prototype_users = i::PrototypeInfo::cast(o)->prototype_users(); | 458 i::Handle<i::Context> context = |
404 if (prototype_users->IsWeakFixedArray()) { | 459 v8::Utils::OpenHandle(*data->contexts_.Get(i)); |
405 i::WeakFixedArray* array = i::WeakFixedArray::cast(prototype_users); | 460 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 } | 461 } |
416 | 462 data->contexts_.Clear(); |
417 i::Object* raw_context = *v8::Utils::OpenPersistent(*context); | |
418 context->Reset(); | |
419 | 463 |
420 i::SnapshotByteSink snapshot_sink; | 464 i::SnapshotByteSink snapshot_sink; |
421 i::StartupSerializer ser(internal_isolate, &snapshot_sink, | 465 i::StartupSerializer startup_serializer(isolate, &snapshot_sink, |
422 function_code_handling); | 466 function_code_handling); |
423 ser.SerializeStrongReferences(); | 467 startup_serializer.SerializeStrongReferences(); |
424 | 468 |
425 i::SnapshotByteSink context_sink; | 469 i::SnapshotByteSink context_sink; |
426 i::PartialSerializer context_ser(internal_isolate, &ser, &context_sink); | 470 i::PartialSerializer context_serializer(isolate, &startup_serializer, |
427 context_ser.Serialize(&raw_context); | 471 &context_sink); |
428 ser.SerializeWeakReferencesAndDeferred(); | 472 // TODO(yangguo): support multiple contexts in the snapshot. |
| 473 DCHECK_EQ(1, contexts.length()); |
| 474 context_serializer.Serialize(&contexts[0]); |
| 475 startup_serializer.SerializeWeakReferencesAndDeferred(); |
429 | 476 |
430 return i::Snapshot::CreateSnapshotBlob(ser, context_ser); | 477 data->created_ = true; |
| 478 return i::Snapshot::CreateSnapshotBlob(startup_serializer, |
| 479 context_serializer); |
431 } | 480 } |
432 | 481 |
433 } // namespace | |
434 | |
435 StartupData V8::CreateSnapshotDataBlob(const char* embedded_source) { | 482 StartupData V8::CreateSnapshotDataBlob(const char* embedded_source) { |
436 // Create a new isolate and a new context from scratch, optionally run | 483 // Create a new isolate and a new context from scratch, optionally run |
437 // a script to embed, and serialize to create a snapshot blob. | 484 // a script to embed, and serialize to create a snapshot blob. |
438 StartupData result = {NULL, 0}; | 485 StartupData result = {nullptr, 0}; |
439 | |
440 base::ElapsedTimer timer; | 486 base::ElapsedTimer timer; |
441 timer.Start(); | 487 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 { | 488 { |
449 Isolate::Scope isolate_scope(isolate); | 489 SnapshotCreator snapshot_creator; |
450 internal_isolate->Init(NULL); | 490 Isolate* isolate = snapshot_creator.GetIsolate(); |
451 Persistent<Context> context; | |
452 { | 491 { |
453 HandleScope handle_scope(isolate); | 492 HandleScope scope(isolate); |
454 Local<Context> new_context = Context::New(isolate); | 493 Local<Context> context = Context::New(isolate); |
455 context.Reset(isolate, new_context); | |
456 if (embedded_source != NULL && | 494 if (embedded_source != NULL && |
457 !RunExtraCode(isolate, new_context, embedded_source, "<embedded>")) { | 495 !RunExtraCode(isolate, context, embedded_source, "<embedded>")) { |
458 context.Reset(); | 496 return result; |
459 } | 497 } |
| 498 snapshot_creator.AddContext(context); |
460 } | 499 } |
461 | 500 result = snapshot_creator.CreateBlob( |
462 result = SerializeIsolateAndContext( | 501 SnapshotCreator::FunctionCodeHandling::kClear); |
463 isolate, &context, i::StartupSerializer::CLEAR_FUNCTION_CODE); | |
464 DCHECK(context.IsEmpty()); | |
465 } | 502 } |
466 isolate->Dispose(); | |
467 | 503 |
468 if (i::FLAG_profile_deserialization) { | 504 if (i::FLAG_profile_deserialization) { |
469 i::PrintF("Creating snapshot took %0.3f ms\n", | 505 i::PrintF("Creating snapshot took %0.3f ms\n", |
470 timer.Elapsed().InMillisecondsF()); | 506 timer.Elapsed().InMillisecondsF()); |
471 } | 507 } |
472 timer.Stop(); | 508 timer.Stop(); |
473 return result; | 509 return result; |
474 } | 510 } |
475 | 511 |
476 StartupData V8::WarmUpSnapshotDataBlob(StartupData cold_snapshot_blob, | 512 StartupData V8::WarmUpSnapshotDataBlob(StartupData cold_snapshot_blob, |
477 const char* warmup_source) { | 513 const char* warmup_source) { |
478 CHECK(cold_snapshot_blob.raw_size > 0 && cold_snapshot_blob.data != NULL); | 514 CHECK(cold_snapshot_blob.raw_size > 0 && cold_snapshot_blob.data != NULL); |
479 CHECK(warmup_source != NULL); | 515 CHECK(warmup_source != NULL); |
480 // Use following steps to create a warmed up snapshot blob from a cold one: | 516 // Use following steps to create a warmed up snapshot blob from a cold one: |
481 // - Create a new isolate from the cold snapshot. | 517 // - Create a new isolate from the cold snapshot. |
482 // - Create a new context to run the warmup script. This will trigger | 518 // - Create a new context to run the warmup script. This will trigger |
483 // compilation of executed functions. | 519 // compilation of executed functions. |
484 // - Create a new context. This context will be unpolluted. | 520 // - Create a new context. This context will be unpolluted. |
485 // - Serialize the isolate and the second context into a new snapshot blob. | 521 // - Serialize the isolate and the second context into a new snapshot blob. |
486 StartupData result = {NULL, 0}; | 522 StartupData result = {nullptr, 0}; |
487 | |
488 base::ElapsedTimer timer; | 523 base::ElapsedTimer timer; |
489 timer.Start(); | 524 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 { | 525 { |
498 Isolate::Scope isolate_scope(isolate); | 526 SnapshotCreator snapshot_creator(&cold_snapshot_blob); |
499 i::Snapshot::Initialize(internal_isolate); | 527 Isolate* isolate = snapshot_creator.GetIsolate(); |
500 Persistent<Context> context; | 528 { |
501 bool success; | 529 HandleScope scope(isolate); |
| 530 Local<Context> context = Context::New(isolate); |
| 531 if (!RunExtraCode(isolate, context, warmup_source, "<warm-up>")) { |
| 532 return result; |
| 533 } |
| 534 } |
502 { | 535 { |
503 HandleScope handle_scope(isolate); | 536 HandleScope handle_scope(isolate); |
504 Local<Context> new_context = Context::New(isolate); | 537 isolate->ContextDisposedNotification(false); |
505 success = RunExtraCode(isolate, new_context, warmup_source, "<warm-up>"); | 538 Local<Context> context = Context::New(isolate); |
| 539 snapshot_creator.AddContext(context); |
506 } | 540 } |
507 if (success) { | 541 result = snapshot_creator.CreateBlob( |
508 HandleScope handle_scope(isolate); | 542 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 } | 543 } |
518 isolate->Dispose(); | |
519 | 544 |
520 if (i::FLAG_profile_deserialization) { | 545 if (i::FLAG_profile_deserialization) { |
521 i::PrintF("Warming up snapshot took %0.3f ms\n", | 546 i::PrintF("Warming up snapshot took %0.3f ms\n", |
522 timer.Elapsed().InMillisecondsF()); | 547 timer.Elapsed().InMillisecondsF()); |
523 } | 548 } |
524 timer.Stop(); | 549 timer.Stop(); |
525 return result; | 550 return result; |
526 } | 551 } |
527 | 552 |
528 | 553 |
(...skipping 8249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8778 Address callback_address = | 8803 Address callback_address = |
8779 reinterpret_cast<Address>(reinterpret_cast<intptr_t>(callback)); | 8804 reinterpret_cast<Address>(reinterpret_cast<intptr_t>(callback)); |
8780 VMState<EXTERNAL> state(isolate); | 8805 VMState<EXTERNAL> state(isolate); |
8781 ExternalCallbackScope call_scope(isolate, callback_address); | 8806 ExternalCallbackScope call_scope(isolate, callback_address); |
8782 callback(info); | 8807 callback(info); |
8783 } | 8808 } |
8784 | 8809 |
8785 | 8810 |
8786 } // namespace internal | 8811 } // namespace internal |
8787 } // namespace v8 | 8812 } // namespace v8 |
OLD | NEW |