| 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 |