| Index: test/cctest/test-serialize.cc | 
| diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc | 
| index 4980fac725b59696706e29c59ee3d5da477ebc4e..550d5b8a128f168a15a52908bd2e918739fa44d2 100644 | 
| --- a/test/cctest/test-serialize.cc | 
| +++ b/test/cctest/test-serialize.cc | 
| @@ -286,7 +286,7 @@ static void PartiallySerializeObject(Vector<const byte>* startup_blob_out, | 
| startup_serializer.SerializeStrongReferences(); | 
|  | 
| PartialSerializer partial_serializer(isolate, &startup_serializer, nullptr); | 
| -    partial_serializer.Serialize(&raw_foo); | 
| +    partial_serializer.Serialize(&raw_foo, false); | 
|  | 
| startup_serializer.SerializeWeakReferencesAndDeferred(); | 
|  | 
| @@ -386,7 +386,7 @@ static void PartiallySerializeContext(Vector<const byte>* startup_blob_out, | 
|  | 
| SnapshotByteSink partial_sink; | 
| PartialSerializer partial_serializer(isolate, &startup_serializer, nullptr); | 
| -    partial_serializer.Serialize(&raw_context); | 
| +    partial_serializer.Serialize(&raw_context, false); | 
| startup_serializer.SerializeWeakReferencesAndDeferred(); | 
|  | 
| SnapshotData startup_snapshot(&startup_serializer); | 
| @@ -506,7 +506,7 @@ static void PartiallySerializeCustomContext( | 
|  | 
| SnapshotByteSink partial_sink; | 
| PartialSerializer partial_serializer(isolate, &startup_serializer, nullptr); | 
| -    partial_serializer.Serialize(&raw_context); | 
| +    partial_serializer.Serialize(&raw_context, false); | 
| startup_serializer.SerializeWeakReferencesAndDeferred(); | 
|  | 
| SnapshotData startup_snapshot(&startup_serializer); | 
| @@ -1962,19 +1962,19 @@ TEST(SnapshotCreatorMultipleContexts) { | 
| v8::Local<v8::Context> context = v8::Context::New(isolate); | 
| v8::Context::Scope context_scope(context); | 
| CompileRun("var f = function() { return 1; }"); | 
| -      CHECK_EQ(0u, creator.AddContext(context)); | 
| +      creator.SetDefaultContext(context); | 
| } | 
| { | 
| v8::HandleScope handle_scope(isolate); | 
| v8::Local<v8::Context> context = v8::Context::New(isolate); | 
| v8::Context::Scope context_scope(context); | 
| CompileRun("var f = function() { return 2; }"); | 
| -      CHECK_EQ(1u, creator.AddContext(context)); | 
| +      CHECK_EQ(0u, creator.AddContext(context)); | 
| } | 
| { | 
| v8::HandleScope handle_scope(isolate); | 
| v8::Local<v8::Context> context = v8::Context::New(isolate); | 
| -      CHECK_EQ(2u, creator.AddContext(context)); | 
| +      CHECK_EQ(1u, creator.AddContext(context)); | 
| } | 
| blob = | 
| creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear); | 
| @@ -1988,22 +1988,21 @@ TEST(SnapshotCreatorMultipleContexts) { | 
| v8::Isolate::Scope isolate_scope(isolate); | 
| { | 
| v8::HandleScope handle_scope(isolate); | 
| -      v8::Local<v8::Context> context = | 
| -          v8::Context::FromSnapshot(isolate, 0).ToLocalChecked(); | 
| +      v8::Local<v8::Context> context = v8::Context::New(isolate); | 
| v8::Context::Scope context_scope(context); | 
| ExpectInt32("f()", 1); | 
| } | 
| { | 
| v8::HandleScope handle_scope(isolate); | 
| v8::Local<v8::Context> context = | 
| -          v8::Context::FromSnapshot(isolate, 1).ToLocalChecked(); | 
| +          v8::Context::FromSnapshot(isolate, 0).ToLocalChecked(); | 
| v8::Context::Scope context_scope(context); | 
| ExpectInt32("f()", 2); | 
| } | 
| { | 
| v8::HandleScope handle_scope(isolate); | 
| v8::Local<v8::Context> context = | 
| -          v8::Context::FromSnapshot(isolate, 2).ToLocalChecked(); | 
| +          v8::Context::FromSnapshot(isolate, 1).ToLocalChecked(); | 
| v8::Context::Scope context_scope(context); | 
| ExpectUndefined("this.f"); | 
| } | 
| @@ -2013,24 +2012,68 @@ TEST(SnapshotCreatorMultipleContexts) { | 
| delete[] blob.data; | 
| } | 
|  | 
| -void SerializedCallback(const v8::FunctionCallbackInfo<v8::Value>& args) { | 
| +static void SerializedCallback( | 
| +    const v8::FunctionCallbackInfo<v8::Value>& args) { | 
| args.GetReturnValue().Set(v8_num(42)); | 
| } | 
|  | 
| -void SerializedCallbackReplacement( | 
| +static void SerializedCallbackReplacement( | 
| const v8::FunctionCallbackInfo<v8::Value>& args) { | 
| args.GetReturnValue().Set(v8_num(1337)); | 
| } | 
|  | 
| +static void NamedPropertyGetterForSerialization( | 
| +    v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) { | 
| +  if (name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("x")) | 
| +          .FromJust()) { | 
| +    info.GetReturnValue().Set(v8_num(2016)); | 
| +  } | 
| +} | 
| + | 
| +static void AccessorForSerialization( | 
| +    v8::Local<v8::String> property, | 
| +    const v8::PropertyCallbackInfo<v8::Value>& info) { | 
| +  info.GetReturnValue().Set(v8_num(2017)); | 
| +} | 
| + | 
| static int serialized_static_field = 314; | 
|  | 
| +class SerializedExtension : public v8::Extension { | 
| + public: | 
| +  SerializedExtension() | 
| +      : v8::Extension("serialized extension", | 
| +                      "native function g();" | 
| +                      "function h() { return 13; };" | 
| +                      "function i() { return 14; };" | 
| +                      "var o = { p: 7 };") {} | 
| + | 
| +  virtual v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate( | 
| +      v8::Isolate* isolate, v8::Local<v8::String> name) { | 
| +    CHECK(name->Equals(isolate->GetCurrentContext(), v8_str("g")).FromJust()); | 
| +    return v8::FunctionTemplate::New(isolate, FunctionCallback); | 
| +  } | 
| + | 
| +  static void FunctionCallback( | 
| +      const v8::FunctionCallbackInfo<v8::Value>& args) { | 
| +    args.GetReturnValue().Set(v8_num(12)); | 
| +  } | 
| +}; | 
| + | 
| intptr_t original_external_references[] = { | 
| reinterpret_cast<intptr_t>(SerializedCallback), | 
| -    reinterpret_cast<intptr_t>(&serialized_static_field), 0}; | 
| +    reinterpret_cast<intptr_t>(&serialized_static_field), | 
| +    reinterpret_cast<intptr_t>(&NamedPropertyGetterForSerialization), | 
| +    reinterpret_cast<intptr_t>(&AccessorForSerialization), | 
| +    reinterpret_cast<intptr_t>(&SerializedExtension::FunctionCallback), | 
| +    0}; | 
|  | 
| intptr_t replaced_external_references[] = { | 
| reinterpret_cast<intptr_t>(SerializedCallbackReplacement), | 
| -    reinterpret_cast<intptr_t>(&serialized_static_field), 0}; | 
| +    reinterpret_cast<intptr_t>(&serialized_static_field), | 
| +    reinterpret_cast<intptr_t>(&NamedPropertyGetterForSerialization), | 
| +    reinterpret_cast<intptr_t>(&AccessorForSerialization), | 
| +    reinterpret_cast<intptr_t>(&SerializedExtension::FunctionCallback), | 
| +    0}; | 
|  | 
| TEST(SnapshotCreatorExternalReferences) { | 
| DisableAlwaysOpt(); | 
| @@ -2048,7 +2091,7 @@ TEST(SnapshotCreatorExternalReferences) { | 
| callback->GetFunction(context).ToLocalChecked(); | 
| CHECK(context->Global()->Set(context, v8_str("f"), function).FromJust()); | 
| ExpectInt32("f()", 42); | 
| -      CHECK_EQ(0u, creator.AddContext(context)); | 
| +      creator.SetDefaultContext(context); | 
| } | 
| blob = | 
| creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear); | 
| @@ -2064,8 +2107,7 @@ TEST(SnapshotCreatorExternalReferences) { | 
| { | 
| v8::Isolate::Scope isolate_scope(isolate); | 
| v8::HandleScope handle_scope(isolate); | 
| -      v8::Local<v8::Context> context = | 
| -          v8::Context::FromSnapshot(isolate, 0).ToLocalChecked(); | 
| +      v8::Local<v8::Context> context = v8::Context::New(isolate); | 
| v8::Context::Scope context_scope(context); | 
| ExpectInt32("f()", 42); | 
| } | 
| @@ -2082,8 +2124,7 @@ TEST(SnapshotCreatorExternalReferences) { | 
| { | 
| v8::Isolate::Scope isolate_scope(isolate); | 
| v8::HandleScope handle_scope(isolate); | 
| -      v8::Local<v8::Context> context = | 
| -          v8::Context::FromSnapshot(isolate, 0).ToLocalChecked(); | 
| +      v8::Local<v8::Context> context = v8::Context::New(isolate); | 
| v8::Context::Scope context_scope(context); | 
| ExpectInt32("f()", 1337); | 
| } | 
| @@ -2108,7 +2149,7 @@ TEST(SnapshotCreatorUnknownExternalReferences) { | 
| CHECK(context->Global()->Set(context, v8_str("f"), function).FromJust()); | 
| ExpectInt32("f()", 42); | 
|  | 
| -    CHECK_EQ(0u, creator.AddContext(context)); | 
| +    creator.SetDefaultContext(context); | 
| } | 
| v8::StartupData blob = | 
| creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear); | 
| @@ -2185,7 +2226,7 @@ TEST(SnapshotCreatorTemplates) { | 
| c->SetInternalField(2, field_external); | 
| CHECK(context->Global()->Set(context, v8_str("a"), a).FromJust()); | 
|  | 
| -      CHECK_EQ(0u, creator.AddContext(context)); | 
| +      creator.SetDefaultContext(context); | 
| CHECK_EQ(0u, creator.AddTemplate(callback)); | 
| CHECK_EQ(1u, creator.AddTemplate(global_template)); | 
| } | 
| @@ -2209,8 +2250,7 @@ TEST(SnapshotCreatorTemplates) { | 
| { | 
| // Create a new context without a new object template. | 
| v8::HandleScope handle_scope(isolate); | 
| -        v8::Local<v8::Context> context = | 
| -            v8::Context::FromSnapshot(isolate, 0).ToLocalChecked(); | 
| +        v8::Local<v8::Context> context = v8::Context::New(isolate); | 
| v8::Context::Scope context_scope(context); | 
| ExpectInt32("f()", 42); | 
|  | 
| @@ -2272,7 +2312,7 @@ TEST(SnapshotCreatorTemplates) { | 
| // Accessing out of bound returns empty MaybeHandle. | 
| CHECK(v8::ObjectTemplate::FromSnapshot(isolate, 2).IsEmpty()); | 
| CHECK(v8::FunctionTemplate::FromSnapshot(isolate, 2).IsEmpty()); | 
| -        CHECK(v8::Context::FromSnapshot(isolate, 2).IsEmpty()); | 
| +        CHECK(v8::Context::FromSnapshot(isolate, 1).IsEmpty()); | 
|  | 
| delete a1; | 
| delete b0; | 
| @@ -2290,8 +2330,7 @@ TEST(SnapshotCreatorTemplates) { | 
| v8_str("g"), | 
| v8::FunctionTemplate::New(isolate, SerializedCallbackReplacement)); | 
| v8::Local<v8::Context> context = | 
| -            v8::Context::FromSnapshot(isolate, 0, no_extension, global_template) | 
| -                .ToLocalChecked(); | 
| +            v8::Context::New(isolate, no_extension, global_template); | 
| v8::Context::Scope context_scope(context); | 
| ExpectInt32("g()", 1337); | 
| ExpectInt32("f()", 42); | 
| @@ -2302,6 +2341,124 @@ TEST(SnapshotCreatorTemplates) { | 
| delete[] blob.data; | 
| } | 
|  | 
| +TEST(SnapshotCreatorIncludeGlobalProxy) { | 
| +  DisableAlwaysOpt(); | 
| +  v8::StartupData blob; | 
| + | 
| +  { | 
| +    v8::SnapshotCreator creator(original_external_references); | 
| +    v8::Isolate* isolate = creator.GetIsolate(); | 
| +    v8::RegisterExtension(new SerializedExtension); | 
| +    const char* extension_names[] = {"serialized extension"}; | 
| +    v8::ExtensionConfiguration extensions(1, extension_names); | 
| +    { | 
| +      // Set default context. This context implicitly does *not* serialize | 
| +      // the global proxy, and upon deserialization one has to be created | 
| +      // in the bootstrapper from the global object template. | 
| +      // Side effects from extensions are persisted though. | 
| +      v8::HandleScope handle_scope(isolate); | 
| +      v8::Local<v8::ObjectTemplate> global_template = | 
| +          v8::ObjectTemplate::New(isolate); | 
| +      v8::Local<v8::FunctionTemplate> callback = | 
| +          v8::FunctionTemplate::New(isolate, SerializedCallback); | 
| +      global_template->Set(v8_str("f"), callback); | 
| +      global_template->SetHandler(v8::NamedPropertyHandlerConfiguration( | 
| +          NamedPropertyGetterForSerialization)); | 
| +      v8::Local<v8::Context> context = | 
| +          v8::Context::New(isolate, &extensions, global_template); | 
| +      v8::Context::Scope context_scope(context); | 
| +      ExpectInt32("f()", 42); | 
| +      ExpectInt32("g()", 12); | 
| +      ExpectInt32("h()", 13); | 
| +      ExpectInt32("o.p", 7); | 
| +      ExpectInt32("x", 2016); | 
| +      creator.SetDefaultContext(context); | 
| +    } | 
| +    { | 
| +      // Add additional context. This context implicitly *does* serialize | 
| +      // the global proxy, and upon deserialization one has to be created | 
| +      // in the bootstrapper from the global object template. | 
| +      // Side effects from extensions are persisted. | 
| +      v8::HandleScope handle_scope(isolate); | 
| +      v8::Local<v8::ObjectTemplate> global_template = | 
| +          v8::ObjectTemplate::New(isolate); | 
| +      v8::Local<v8::FunctionTemplate> callback = | 
| +          v8::FunctionTemplate::New(isolate, SerializedCallback); | 
| +      global_template->Set(v8_str("f"), callback); | 
| +      global_template->SetHandler(v8::NamedPropertyHandlerConfiguration( | 
| +          NamedPropertyGetterForSerialization)); | 
| +      global_template->SetAccessor(v8_str("y"), AccessorForSerialization); | 
| +      v8::Local<v8::Context> context = | 
| +          v8::Context::New(isolate, &extensions, global_template); | 
| +      v8::Context::Scope context_scope(context); | 
| +      ExpectInt32("f()", 42); | 
| +      ExpectInt32("g()", 12); | 
| +      ExpectInt32("h()", 13); | 
| +      ExpectInt32("o.p", 7); | 
| +      ExpectInt32("x", 2016); | 
| +      ExpectInt32("y", 2017); | 
| +      CHECK_EQ(0u, creator.AddContext(context)); | 
| +    } | 
| +    blob = creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear, | 
| +                              SerializeInternalFields); | 
| +  } | 
| + | 
| +  { | 
| +    v8::Isolate::CreateParams params; | 
| +    params.snapshot_blob = &blob; | 
| +    params.array_buffer_allocator = CcTest::array_buffer_allocator(); | 
| +    params.external_references = original_external_references; | 
| +    params.deserialize_internal_fields_callback = DeserializeInternalFields; | 
| +    v8::Isolate* isolate = v8::Isolate::New(params); | 
| +    { | 
| +      v8::Isolate::Scope isolate_scope(isolate); | 
| +      // We can introduce new extensions, which could override the already | 
| +      // snapshotted extension. | 
| +      v8::Extension* extension = new v8::Extension("new extension", | 
| +                                                   "function i() { return 24; }" | 
| +                                                   "function j() { return 25; }" | 
| +                                                   "if (o.p == 7) o.p++;"); | 
| +      extension->set_auto_enable(true); | 
| +      v8::RegisterExtension(extension); | 
| +      { | 
| +        // Create a new context from default context snapshot. This will | 
| +        // create a new global object from a new global object template | 
| +        // without the interceptor. | 
| +        v8::HandleScope handle_scope(isolate); | 
| +        v8::Local<v8::Context> context = v8::Context::New(isolate); | 
| +        v8::Context::Scope context_scope(context); | 
| +        ExpectInt32("f()", 42); | 
| +        ExpectInt32("g()", 12); | 
| +        ExpectInt32("h()", 13); | 
| +        ExpectInt32("i()", 24); | 
| +        ExpectInt32("j()", 25); | 
| +        ExpectInt32("o.p", 8); | 
| +        v8::TryCatch try_catch(isolate); | 
| +        CHECK(CompileRun("x").IsEmpty()); | 
| +        CHECK(try_catch.HasCaught()); | 
| +      } | 
| +      { | 
| +        // Create a new context from first additional context snapshot. This | 
| +        // will use the global object from the snapshot, including interceptor. | 
| +        v8::HandleScope handle_scope(isolate); | 
| +        v8::Local<v8::Context> context = | 
| +            v8::Context::FromSnapshot(isolate, 0).ToLocalChecked(); | 
| +        v8::Context::Scope context_scope(context); | 
| +        ExpectInt32("f()", 42); | 
| +        ExpectInt32("g()", 12); | 
| +        ExpectInt32("h()", 13); | 
| +        ExpectInt32("i()", 24); | 
| +        ExpectInt32("j()", 25); | 
| +        ExpectInt32("o.p", 8); | 
| +        ExpectInt32("x", 2016); | 
| +        ExpectInt32("y", 2017); | 
| +      } | 
| +    } | 
| +    isolate->Dispose(); | 
| +  } | 
| +  delete[] blob.data; | 
| +} | 
| + | 
| TEST(SerializationMemoryStats) { | 
| FLAG_profile_deserialization = true; | 
| FLAG_always_opt = false; | 
|  |