Merge V8 5.3.332.45.  DO NOT MERGE

Test: Manual

FPIIM-449

Change-Id: Id3254828b068abdea3cb10442e0172a8c9a98e03
(cherry picked from commit 13e2dadd00298019ed862f2b2fc5068bba730bcf)
diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc
index cd349f9..de36877 100644
--- a/test/cctest/test-serialize.cc
+++ b/test/cctest/test-serialize.cc
@@ -36,6 +36,7 @@
 #include "src/compilation-cache.h"
 #include "src/debug/debug.h"
 #include "src/heap/spaces.h"
+#include "src/macro-assembler.h"
 #include "src/objects.h"
 #include "src/parsing/parser.h"
 #include "src/runtime/runtime.h"
@@ -46,7 +47,7 @@
 #include "src/snapshot/snapshot.h"
 #include "src/snapshot/startup-serializer.h"
 #include "test/cctest/cctest.h"
-#include "test/cctest/heap/utils-inl.h"
+#include "test/cctest/heap/heap-utils.h"
 
 using namespace v8::internal;
 
@@ -91,11 +92,11 @@
 
   Isolate* internal_isolate = reinterpret_cast<Isolate*>(isolate);
   internal_isolate->heap()->CollectAllAvailableGarbage("serialize");
-  SnapshotByteSink sink;
-  StartupSerializer ser(internal_isolate, &sink);
+  StartupSerializer ser(internal_isolate,
+                        v8::SnapshotCreator::FunctionCodeHandling::kClear);
   ser.SerializeStrongReferences();
   ser.SerializeWeakReferencesAndDeferred();
-  SnapshotData snapshot_data(ser);
+  SnapshotData snapshot_data(&ser);
   return WritePayload(snapshot_data.RawData());
 }
 
@@ -280,19 +281,17 @@
     }
     env.Reset();
 
-    SnapshotByteSink startup_sink;
-    StartupSerializer startup_serializer(isolate, &startup_sink);
+    StartupSerializer startup_serializer(
+        isolate, v8::SnapshotCreator::FunctionCodeHandling::kClear);
     startup_serializer.SerializeStrongReferences();
 
-    SnapshotByteSink partial_sink;
-    PartialSerializer partial_serializer(isolate, &startup_serializer,
-                                         &partial_sink);
+    PartialSerializer partial_serializer(isolate, &startup_serializer);
     partial_serializer.Serialize(&raw_foo);
 
     startup_serializer.SerializeWeakReferencesAndDeferred();
 
-    SnapshotData startup_snapshot(startup_serializer);
-    SnapshotData partial_snapshot(partial_serializer);
+    SnapshotData startup_snapshot(&startup_serializer);
+    SnapshotData partial_snapshot(&partial_serializer);
 
     *partial_blob_out = WritePayload(partial_snapshot.RawData());
     *startup_blob_out = WritePayload(startup_snapshot.RawData());
@@ -380,17 +379,17 @@
     env.Reset();
 
     SnapshotByteSink startup_sink;
-    StartupSerializer startup_serializer(isolate, &startup_sink);
+    StartupSerializer startup_serializer(
+        isolate, v8::SnapshotCreator::FunctionCodeHandling::kClear);
     startup_serializer.SerializeStrongReferences();
 
     SnapshotByteSink partial_sink;
-    PartialSerializer partial_serializer(isolate, &startup_serializer,
-                                         &partial_sink);
+    PartialSerializer partial_serializer(isolate, &startup_serializer);
     partial_serializer.Serialize(&raw_context);
     startup_serializer.SerializeWeakReferencesAndDeferred();
 
-    SnapshotData startup_snapshot(startup_serializer);
-    SnapshotData partial_snapshot(partial_serializer);
+    SnapshotData startup_snapshot(&startup_serializer);
+    SnapshotData partial_snapshot(&partial_serializer);
 
     *partial_blob_out = WritePayload(partial_snapshot.RawData());
     *startup_blob_out = WritePayload(startup_snapshot.RawData());
@@ -498,17 +497,17 @@
     env.Reset();
 
     SnapshotByteSink startup_sink;
-    StartupSerializer startup_serializer(isolate, &startup_sink);
+    StartupSerializer startup_serializer(
+        isolate, v8::SnapshotCreator::FunctionCodeHandling::kClear);
     startup_serializer.SerializeStrongReferences();
 
     SnapshotByteSink partial_sink;
-    PartialSerializer partial_serializer(isolate, &startup_serializer,
-                                         &partial_sink);
+    PartialSerializer partial_serializer(isolate, &startup_serializer);
     partial_serializer.Serialize(&raw_context);
     startup_serializer.SerializeWeakReferencesAndDeferred();
 
-    SnapshotData startup_snapshot(startup_serializer);
-    SnapshotData partial_snapshot(partial_serializer);
+    SnapshotData startup_snapshot(&startup_serializer);
+    SnapshotData partial_snapshot(&partial_serializer);
 
     *partial_blob_out = WritePayload(partial_snapshot.RawData());
     *startup_blob_out = WritePayload(startup_snapshot.RawData());
@@ -792,7 +791,7 @@
 
 TEST(SnapshotDataBlobWithWarmup) {
   DisableTurbofan();
-  const char* warmup = "Math.tan(1); Math.sin = 1;";
+  const char* warmup = "Math.tanh(1); Math.sinh = 1;";
 
   v8::StartupData cold = v8::V8::CreateSnapshotDataBlob();
   v8::StartupData warm = v8::V8::WarmUpSnapshotDataBlob(cold, warmup);
@@ -811,9 +810,9 @@
     v8::Context::Scope c_scope(context);
     // Running the warmup script has effect on whether functions are
     // pre-compiled, but does not pollute the context.
-    CHECK(IsCompiled("Math.tan"));
-    CHECK(!IsCompiled("Math.cos"));
-    CHECK(CompileRun("Math.sin")->IsFunction());
+    CHECK(IsCompiled("Math.tanh"));
+    CHECK(!IsCompiled("Math.cosh"));
+    CHECK(CompileRun("Math.sinh")->IsFunction());
   }
   isolate->Dispose();
 }
@@ -821,9 +820,9 @@
 TEST(CustomSnapshotDataBlobWithWarmup) {
   DisableTurbofan();
   const char* source =
-      "function f() { return Math.sin(1); }\n"
-      "function g() { return Math.cos(1); }\n"
-      "Math.tan(1);"
+      "function f() { return Math.sinh(1); }\n"
+      "function g() { return Math.cosh(1); }\n"
+      "Math.tanh(1);"
       "var a = 5";
   const char* warmup = "a = f()";
 
@@ -845,10 +844,10 @@
     // Running the warmup script has effect on whether functions are
     // pre-compiled, but does not pollute the context.
     CHECK(IsCompiled("f"));
-    CHECK(IsCompiled("Math.sin"));
+    CHECK(IsCompiled("Math.sinh"));
     CHECK(!IsCompiled("g"));
-    CHECK(!IsCompiled("Math.cos"));
-    CHECK(!IsCompiled("Math.tan"));
+    CHECK(!IsCompiled("Math.cosh"));
+    CHECK(!IsCompiled("Math.tanh"));
     CHECK_EQ(5, CompileRun("a")->Int32Value(context).FromJust());
   }
   isolate->Dispose();
@@ -1827,12 +1826,302 @@
       false);
   delete script_data;
 
-  SimulateIncrementalMarking(isolate->heap());
+  heap::SimulateIncrementalMarking(isolate->heap());
 
   script_data = CodeSerializer::Serialize(isolate, shared, source);
   delete script_data;
 }
 
+#if V8_TARGET_ARCH_X64
+TEST(CodeSerializerCell) {
+  FLAG_serialize_toplevel = true;
+  LocalContext context;
+  Isolate* isolate = CcTest::i_isolate();
+  isolate->compilation_cache()->Disable();  // Disable same-isolate code cache.
+
+  v8::HandleScope scope(CcTest::isolate());
+
+  size_t actual_size;
+  byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
+      Assembler::kMinimalBufferSize, &actual_size, true));
+  CHECK(buffer);
+  HandleScope handles(isolate);
+
+  MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size),
+                           v8::internal::CodeObjectRequired::kYes);
+  assembler.enable_serializer();
+  Handle<HeapNumber> number = isolate->factory()->NewHeapNumber(0.3);
+  CHECK(isolate->heap()->InNewSpace(*number));
+  MacroAssembler* masm = &assembler;
+  masm->MoveHeapObject(rax, number);
+  masm->ret(0);
+  CodeDesc desc;
+  masm->GetCode(&desc);
+  Handle<Code> code = isolate->factory()->NewCode(
+      desc, Code::ComputeFlags(Code::FUNCTION), masm->CodeObject());
+  code->set_has_reloc_info_for_serialization(true);
+
+  RelocIterator rit1(*code, 1 << RelocInfo::CELL);
+  CHECK_EQ(*number, rit1.rinfo()->target_cell()->value());
+
+  Handle<String> source = isolate->factory()->empty_string();
+  Handle<SharedFunctionInfo> sfi =
+      isolate->factory()->NewSharedFunctionInfo(source, code, false);
+  ScriptData* script_data = CodeSerializer::Serialize(isolate, sfi, source);
+
+  Handle<SharedFunctionInfo> copy =
+      CodeSerializer::Deserialize(isolate, script_data, source)
+          .ToHandleChecked();
+  RelocIterator rit2(copy->code(), 1 << RelocInfo::CELL);
+  CHECK(rit2.rinfo()->target_cell()->IsCell());
+  Handle<Cell> cell(rit2.rinfo()->target_cell());
+  CHECK(cell->value()->IsHeapNumber());
+  CHECK_EQ(0.3, HeapNumber::cast(cell->value())->value());
+
+  delete script_data;
+}
+#endif  // V8_TARGET_ARCH_X64
+
+TEST(SnapshotCreatorMultipleContexts) {
+  DisableTurbofan();
+  v8::StartupData blob;
+  {
+    v8::SnapshotCreator creator;
+    v8::Isolate* isolate = creator.GetIsolate();
+    {
+      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 1; }");
+      CHECK_EQ(0, creator.AddContext(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(1, creator.AddContext(context));
+    }
+    {
+      v8::HandleScope handle_scope(isolate);
+      v8::Local<v8::Context> context = v8::Context::New(isolate);
+      CHECK_EQ(2, creator.AddContext(context));
+    }
+    blob =
+        creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
+  }
+
+  v8::Isolate::CreateParams params;
+  params.snapshot_blob = &blob;
+  params.array_buffer_allocator = CcTest::array_buffer_allocator();
+  v8::Isolate* isolate = v8::Isolate::New(params);
+  {
+    v8::Isolate::Scope isolate_scope(isolate);
+    v8::ExtensionConfiguration* no_extension = nullptr;
+    v8::Local<v8::ObjectTemplate> no_template = v8::Local<v8::ObjectTemplate>();
+    v8::Local<v8::Value> no_object = v8::Local<v8::Value>();
+    {
+      v8::HandleScope handle_scope(isolate);
+      v8::Local<v8::Context> context =
+          v8::Context::New(isolate, no_extension, no_template, no_object, 0);
+      v8::Context::Scope context_scope(context);
+      ExpectInt32("f()", 1);
+    }
+    {
+      v8::HandleScope handle_scope(isolate);
+      v8::Local<v8::Context> context =
+          v8::Context::New(isolate, no_extension, no_template, no_object, 1);
+      v8::Context::Scope context_scope(context);
+      ExpectInt32("f()", 2);
+    }
+    {
+      v8::HandleScope handle_scope(isolate);
+      v8::Local<v8::Context> context =
+          v8::Context::New(isolate, no_extension, no_template, no_object, 2);
+      v8::Context::Scope context_scope(context);
+      ExpectUndefined("this.f");
+    }
+  }
+
+  isolate->Dispose();
+  delete[] blob.data;
+}
+
+static void SerializedCallback(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  args.GetReturnValue().Set(v8_num(42));
+}
+
+static void SerializedCallbackReplacement(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  args.GetReturnValue().Set(v8_num(1337));
+}
+
+intptr_t original_external_references[] = {
+    reinterpret_cast<intptr_t>(SerializedCallback), 0};
+
+intptr_t replaced_external_references[] = {
+    reinterpret_cast<intptr_t>(SerializedCallbackReplacement), 0};
+
+TEST(SnapshotCreatorExternalReferences) {
+  DisableTurbofan();
+  v8::StartupData blob;
+  {
+    v8::SnapshotCreator creator(original_external_references);
+    v8::Isolate* isolate = creator.GetIsolate();
+    {
+      v8::HandleScope handle_scope(isolate);
+      v8::Local<v8::Context> context = v8::Context::New(isolate);
+      v8::Context::Scope context_scope(context);
+      v8::Local<v8::FunctionTemplate> callback =
+          v8::FunctionTemplate::New(isolate, SerializedCallback);
+      v8::Local<v8::Value> function =
+          callback->GetFunction(context).ToLocalChecked();
+      CHECK(context->Global()->Set(context, v8_str("f"), function).FromJust());
+      ExpectInt32("f()", 42);
+      CHECK_EQ(0, creator.AddContext(context));
+    }
+    blob =
+        creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
+  }
+
+  // Deserialize with the original external reference.
+  {
+    v8::Isolate::CreateParams params;
+    params.snapshot_blob = &blob;
+    params.array_buffer_allocator = CcTest::array_buffer_allocator();
+    params.external_references = original_external_references;
+    v8::Isolate* isolate = v8::Isolate::New(params);
+    {
+      v8::Isolate::Scope isolate_scope(isolate);
+      v8::HandleScope handle_scope(isolate);
+      v8::ExtensionConfiguration* no_extension = nullptr;
+      v8::Local<v8::ObjectTemplate> no_template =
+          v8::Local<v8::ObjectTemplate>();
+      v8::Local<v8::Value> no_object = v8::Local<v8::Value>();
+      v8::Local<v8::Context> context =
+          v8::Context::New(isolate, no_extension, no_template, no_object, 0);
+      v8::Context::Scope context_scope(context);
+      ExpectInt32("f()", 42);
+    }
+    isolate->Dispose();
+  }
+
+  // Deserialize with the some other external reference.
+  {
+    v8::Isolate::CreateParams params;
+    params.snapshot_blob = &blob;
+    params.array_buffer_allocator = CcTest::array_buffer_allocator();
+    params.external_references = replaced_external_references;
+    v8::Isolate* isolate = v8::Isolate::New(params);
+    {
+      v8::Isolate::Scope isolate_scope(isolate);
+      v8::HandleScope handle_scope(isolate);
+      v8::ExtensionConfiguration* no_extension = nullptr;
+      v8::Local<v8::ObjectTemplate> no_template =
+          v8::Local<v8::ObjectTemplate>();
+      v8::Local<v8::Value> no_object = v8::Local<v8::Value>();
+      v8::Local<v8::Context> context =
+          v8::Context::New(isolate, no_extension, no_template, no_object, 0);
+      v8::Context::Scope context_scope(context);
+      ExpectInt32("f()", 1337);
+    }
+    isolate->Dispose();
+  }
+  delete[] blob.data;
+}
+
+TEST(SnapshotCreatorTemplates) {
+  DisableTurbofan();
+  v8::StartupData blob;
+  {
+    v8::SnapshotCreator creator(original_external_references);
+    v8::Isolate* isolate = creator.GetIsolate();
+    {
+      v8::HandleScope handle_scope(isolate);
+      v8::ExtensionConfiguration* no_extension = nullptr;
+      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);
+      v8::Local<v8::Context> context =
+          v8::Context::New(isolate, no_extension, global_template);
+      v8::Context::Scope context_scope(context);
+      ExpectInt32("f()", 42);
+      CHECK_EQ(0, creator.AddContext(context));
+      CHECK_EQ(0, creator.AddTemplate(callback));
+      CHECK_EQ(1, creator.AddTemplate(global_template));
+    }
+    blob =
+        creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
+  }
+
+  {
+    v8::Isolate::CreateParams params;
+    params.snapshot_blob = &blob;
+    params.array_buffer_allocator = CcTest::array_buffer_allocator();
+    params.external_references = original_external_references;
+    v8::Isolate* isolate = v8::Isolate::New(params);
+    {
+      v8::Isolate::Scope isolate_scope(isolate);
+      {
+        // Create a new context without a new object template.
+        v8::HandleScope handle_scope(isolate);
+        v8::ExtensionConfiguration* no_extension = nullptr;
+        v8::Local<v8::ObjectTemplate> no_template =
+            v8::Local<v8::ObjectTemplate>();
+        v8::Local<v8::Value> no_object = v8::Local<v8::Value>();
+        v8::Local<v8::Context> context =
+            v8::Context::New(isolate, no_extension, no_template, no_object, 0);
+        v8::Context::Scope context_scope(context);
+        ExpectInt32("f()", 42);
+
+        // Retrieve the snapshotted object template.
+        v8::Local<v8::ObjectTemplate> obj_template =
+            v8::ObjectTemplate::FromSnapshot(isolate, 1);
+        CHECK(!obj_template.IsEmpty());
+        v8::Local<v8::Object> object =
+            obj_template->NewInstance(context).ToLocalChecked();
+        CHECK(context->Global()->Set(context, v8_str("o"), object).FromJust());
+        ExpectInt32("o.f()", 42);
+        // Check that it instantiates to the same prototype.
+        ExpectTrue("o.f.prototype === f.prototype");
+
+        // Retrieve the snapshotted function template.
+        v8::Local<v8::FunctionTemplate> fun_template =
+            v8::FunctionTemplate::FromSnapshot(isolate, 0);
+        CHECK(!fun_template.IsEmpty());
+        v8::Local<v8::Function> fun =
+            fun_template->GetFunction(context).ToLocalChecked();
+        CHECK(context->Global()->Set(context, v8_str("g"), fun).FromJust());
+        ExpectInt32("g()", 42);
+        // Check that it instantiates to the same prototype.
+        ExpectTrue("g.prototype === f.prototype");
+      }
+
+      {
+        // Create a context with a new object template. It is merged into the
+        // deserialized global object.
+        v8::HandleScope handle_scope(isolate);
+        v8::ExtensionConfiguration* no_extension = nullptr;
+        v8::Local<v8::ObjectTemplate> global_template =
+            v8::ObjectTemplate::New(isolate);
+        global_template->Set(
+            v8_str("g"),
+            v8::FunctionTemplate::New(isolate, SerializedCallbackReplacement));
+        v8::Local<v8::Value> no_object = v8::Local<v8::Value>();
+        v8::Local<v8::Context> context = v8::Context::New(
+            isolate, no_extension, global_template, no_object, 0);
+        v8::Context::Scope context_scope(context);
+        ExpectInt32("g()", 1337);
+        ExpectInt32("f()", 42);
+      }
+    }
+    isolate->Dispose();
+  }
+  delete[] blob.data;
+}
 
 TEST(SerializationMemoryStats) {
   FLAG_profile_deserialization = true;