| Index: src/api.cc
|
| diff --git a/src/api.cc b/src/api.cc
|
| index 2679a363f7fc0c0b8227348378e471cfbdd75f0f..d37e0c34dca964d5542301de0a8360f2e5180ab6 100644
|
| --- a/src/api.cc
|
| +++ b/src/api.cc
|
| @@ -15,6 +15,7 @@
|
| #include "include/v8-experimental.h"
|
| #include "include/v8-profiler.h"
|
| #include "include/v8-testing.h"
|
| +#include "include/v8-util.h"
|
| #include "src/accessors.h"
|
| #include "src/api-experimental.h"
|
| #include "src/api-natives.h"
|
| @@ -383,87 +384,122 @@ bool RunExtraCode(Isolate* isolate, Local<Context> context,
|
| return true;
|
| }
|
|
|
| -StartupData SerializeIsolateAndContext(
|
| - Isolate* isolate, Persistent<Context>* context,
|
| - i::StartupSerializer::FunctionCodeHandling function_code_handling) {
|
| - if (context->IsEmpty()) return {NULL, 0};
|
| +struct SnapshotCreatorData {
|
| + explicit SnapshotCreatorData(Isolate* isolate)
|
| + : isolate_(isolate), contexts_(isolate), created_(false) {}
|
|
|
| - i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
|
| + static SnapshotCreatorData* cast(void* data) {
|
| + return reinterpret_cast<SnapshotCreatorData*>(data);
|
| + }
|
| +
|
| + ArrayBufferAllocator allocator_;
|
| + Isolate* isolate_;
|
| + PersistentValueVector<Context> contexts_;
|
| + bool created_;
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +SnapshotCreator::SnapshotCreator(StartupData* existing_snapshot) {
|
| + i::Isolate* internal_isolate = new i::Isolate(true);
|
| + Isolate* isolate = reinterpret_cast<Isolate*>(internal_isolate);
|
| + SnapshotCreatorData* data = new SnapshotCreatorData(isolate);
|
| + data->isolate_ = isolate;
|
| + internal_isolate->set_array_buffer_allocator(&data->allocator_);
|
| + isolate->Enter();
|
| + if (existing_snapshot) {
|
| + internal_isolate->set_snapshot_blob(existing_snapshot);
|
| + i::Snapshot::Initialize(internal_isolate);
|
| + } else {
|
| + internal_isolate->Init(nullptr);
|
| + }
|
| + data_ = data;
|
| +}
|
| +
|
| +SnapshotCreator::~SnapshotCreator() {
|
| + SnapshotCreatorData* data = SnapshotCreatorData::cast(data_);
|
| + DCHECK(data->created_);
|
| + Isolate* isolate = data->isolate_;
|
| + isolate->Exit();
|
| + isolate->Dispose();
|
| + delete data;
|
| +}
|
| +
|
| +Isolate* SnapshotCreator::GetIsolate() {
|
| + return SnapshotCreatorData::cast(data_)->isolate_;
|
| +}
|
| +
|
| +void SnapshotCreator::AddContext(Local<Context> context) {
|
| + DCHECK(!context.IsEmpty());
|
| + SnapshotCreatorData* data = SnapshotCreatorData::cast(data_);
|
| + DCHECK(!data->created_);
|
| + Isolate* isolate = data->isolate_;
|
| + CHECK_EQ(isolate, context->GetIsolate());
|
| + data->contexts_.Append(context);
|
| +}
|
| +
|
| +StartupData SnapshotCreator::CreateBlob(
|
| + SnapshotCreator::FunctionCodeHandling function_code_handling) {
|
| + SnapshotCreatorData* data = SnapshotCreatorData::cast(data_);
|
| + i::Isolate* isolate = reinterpret_cast<i::Isolate*>(data->isolate_);
|
| + DCHECK(!data->created_);
|
|
|
| // If we don't do this then we end up with a stray root pointing at the
|
| // context even after we have disposed of the context.
|
| - internal_isolate->heap()->CollectAllAvailableGarbage("mksnapshot");
|
| -
|
| - // GC may have cleared weak cells, so compact any WeakFixedArrays
|
| - // found on the heap.
|
| - i::HeapIterator iterator(internal_isolate->heap(),
|
| - i::HeapIterator::kFilterUnreachable);
|
| - for (i::HeapObject* o = iterator.next(); o != NULL; o = iterator.next()) {
|
| - if (o->IsPrototypeInfo()) {
|
| - i::Object* prototype_users = i::PrototypeInfo::cast(o)->prototype_users();
|
| - if (prototype_users->IsWeakFixedArray()) {
|
| - i::WeakFixedArray* array = i::WeakFixedArray::cast(prototype_users);
|
| - array->Compact<i::JSObject::PrototypeRegistryCompactionCallback>();
|
| - }
|
| - } else if (o->IsScript()) {
|
| - i::Object* shared_list = i::Script::cast(o)->shared_function_infos();
|
| - if (shared_list->IsWeakFixedArray()) {
|
| - i::WeakFixedArray* array = i::WeakFixedArray::cast(shared_list);
|
| - array->Compact<i::WeakFixedArray::NullCallback>();
|
| - }
|
| - }
|
| - }
|
| + isolate->heap()->CollectAllAvailableGarbage("mksnapshot");
|
| + isolate->heap()->CompactWeakFixedArrays();
|
|
|
| - i::Object* raw_context = *v8::Utils::OpenPersistent(*context);
|
| - context->Reset();
|
| + i::DisallowHeapAllocation no_gc_from_here_on;
|
| +
|
| + int num_contexts = static_cast<int>(data->contexts_.Size());
|
| + i::List<i::Object*> contexts(num_contexts);
|
| + for (int i = 0; i < num_contexts; i++) {
|
| + i::HandleScope scope(isolate);
|
| + i::Handle<i::Context> context =
|
| + v8::Utils::OpenHandle(*data->contexts_.Get(i));
|
| + contexts.Add(*context);
|
| + }
|
| + data->contexts_.Clear();
|
|
|
| i::SnapshotByteSink snapshot_sink;
|
| - i::StartupSerializer ser(internal_isolate, &snapshot_sink,
|
| - function_code_handling);
|
| - ser.SerializeStrongReferences();
|
| + i::StartupSerializer startup_serializer(isolate, &snapshot_sink,
|
| + function_code_handling);
|
| + startup_serializer.SerializeStrongReferences();
|
|
|
| i::SnapshotByteSink context_sink;
|
| - i::PartialSerializer context_ser(internal_isolate, &ser, &context_sink);
|
| - context_ser.Serialize(&raw_context);
|
| - ser.SerializeWeakReferencesAndDeferred();
|
| + i::PartialSerializer context_serializer(isolate, &startup_serializer,
|
| + &context_sink);
|
| + // TODO(yangguo): support multiple contexts in the snapshot.
|
| + DCHECK_EQ(1, contexts.length());
|
| + context_serializer.Serialize(&contexts[0]);
|
| + startup_serializer.SerializeWeakReferencesAndDeferred();
|
|
|
| - return i::Snapshot::CreateSnapshotBlob(ser, context_ser);
|
| + data->created_ = true;
|
| + return i::Snapshot::CreateSnapshotBlob(startup_serializer,
|
| + context_serializer);
|
| }
|
|
|
| -} // namespace
|
| -
|
| StartupData V8::CreateSnapshotDataBlob(const char* embedded_source) {
|
| // Create a new isolate and a new context from scratch, optionally run
|
| // a script to embed, and serialize to create a snapshot blob.
|
| - StartupData result = {NULL, 0};
|
| -
|
| + StartupData result = {nullptr, 0};
|
| base::ElapsedTimer timer;
|
| timer.Start();
|
| -
|
| - ArrayBufferAllocator allocator;
|
| - i::Isolate* internal_isolate = new i::Isolate(true);
|
| - internal_isolate->set_array_buffer_allocator(&allocator);
|
| - Isolate* isolate = reinterpret_cast<Isolate*>(internal_isolate);
|
| -
|
| {
|
| - Isolate::Scope isolate_scope(isolate);
|
| - internal_isolate->Init(NULL);
|
| - Persistent<Context> context;
|
| + SnapshotCreator snapshot_creator;
|
| + Isolate* isolate = snapshot_creator.GetIsolate();
|
| {
|
| - HandleScope handle_scope(isolate);
|
| - Local<Context> new_context = Context::New(isolate);
|
| - context.Reset(isolate, new_context);
|
| + HandleScope scope(isolate);
|
| + Local<Context> context = Context::New(isolate);
|
| if (embedded_source != NULL &&
|
| - !RunExtraCode(isolate, new_context, embedded_source, "<embedded>")) {
|
| - context.Reset();
|
| + !RunExtraCode(isolate, context, embedded_source, "<embedded>")) {
|
| + return result;
|
| }
|
| + snapshot_creator.AddContext(context);
|
| }
|
| -
|
| - result = SerializeIsolateAndContext(
|
| - isolate, &context, i::StartupSerializer::CLEAR_FUNCTION_CODE);
|
| - DCHECK(context.IsEmpty());
|
| + result = snapshot_creator.CreateBlob(
|
| + SnapshotCreator::FunctionCodeHandling::kClear);
|
| }
|
| - isolate->Dispose();
|
|
|
| if (i::FLAG_profile_deserialization) {
|
| i::PrintF("Creating snapshot took %0.3f ms\n",
|
| @@ -483,39 +519,28 @@ StartupData V8::WarmUpSnapshotDataBlob(StartupData cold_snapshot_blob,
|
| // compilation of executed functions.
|
| // - Create a new context. This context will be unpolluted.
|
| // - Serialize the isolate and the second context into a new snapshot blob.
|
| - StartupData result = {NULL, 0};
|
| -
|
| + StartupData result = {nullptr, 0};
|
| base::ElapsedTimer timer;
|
| timer.Start();
|
| -
|
| - ArrayBufferAllocator allocator;
|
| - i::Isolate* internal_isolate = new i::Isolate(true);
|
| - internal_isolate->set_array_buffer_allocator(&allocator);
|
| - internal_isolate->set_snapshot_blob(&cold_snapshot_blob);
|
| - Isolate* isolate = reinterpret_cast<Isolate*>(internal_isolate);
|
| -
|
| {
|
| - Isolate::Scope isolate_scope(isolate);
|
| - i::Snapshot::Initialize(internal_isolate);
|
| - Persistent<Context> context;
|
| - bool success;
|
| + SnapshotCreator snapshot_creator(&cold_snapshot_blob);
|
| + Isolate* isolate = snapshot_creator.GetIsolate();
|
| {
|
| - HandleScope handle_scope(isolate);
|
| - Local<Context> new_context = Context::New(isolate);
|
| - success = RunExtraCode(isolate, new_context, warmup_source, "<warm-up>");
|
| + HandleScope scope(isolate);
|
| + Local<Context> context = Context::New(isolate);
|
| + if (!RunExtraCode(isolate, context, warmup_source, "<warm-up>")) {
|
| + return result;
|
| + }
|
| }
|
| - if (success) {
|
| + {
|
| HandleScope handle_scope(isolate);
|
| isolate->ContextDisposedNotification(false);
|
| - Local<Context> new_context = Context::New(isolate);
|
| - context.Reset(isolate, new_context);
|
| + Local<Context> context = Context::New(isolate);
|
| + snapshot_creator.AddContext(context);
|
| }
|
| -
|
| - result = SerializeIsolateAndContext(
|
| - isolate, &context, i::StartupSerializer::KEEP_FUNCTION_CODE);
|
| - DCHECK(context.IsEmpty());
|
| + result = snapshot_creator.CreateBlob(
|
| + SnapshotCreator::FunctionCodeHandling::kKeep);
|
| }
|
| - isolate->Dispose();
|
|
|
| if (i::FLAG_profile_deserialization) {
|
| i::PrintF("Warming up snapshot took %0.3f ms\n",
|
|
|