LCOV - code coverage report
Current view: top level - test/cctest - test-serialize.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1651 1707 96.7 %
Date: 2019-04-17 Functions: 117 127 92.1 %

          Line data    Source code
       1             : // Copyright 2007-2010 the V8 project authors. All rights reserved.
       2             : // Redistribution and use in source and binary forms, with or without
       3             : // modification, are permitted provided that the following conditions are
       4             : // met:
       5             : //
       6             : //     * Redistributions of source code must retain the above copyright
       7             : //       notice, this list of conditions and the following disclaimer.
       8             : //     * Redistributions in binary form must reproduce the above
       9             : //       copyright notice, this list of conditions and the following
      10             : //       disclaimer in the documentation and/or other materials provided
      11             : //       with the distribution.
      12             : //     * Neither the name of Google Inc. nor the names of its
      13             : //       contributors may be used to endorse or promote products derived
      14             : //       from this software without specific prior written permission.
      15             : //
      16             : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      17             : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      18             : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      19             : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      20             : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      21             : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      22             : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      23             : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      24             : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      25             : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      26             : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      27             : 
      28             : #include <signal.h>
      29             : 
      30             : #include <sys/stat.h>
      31             : 
      32             : #include "src/v8.h"
      33             : 
      34             : #include "src/api-inl.h"
      35             : #include "src/assembler-inl.h"
      36             : #include "src/bootstrapper.h"
      37             : #include "src/compilation-cache.h"
      38             : #include "src/compiler.h"
      39             : #include "src/debug/debug.h"
      40             : #include "src/hash-seed-inl.h"
      41             : #include "src/heap/heap-inl.h"
      42             : #include "src/heap/read-only-heap.h"
      43             : #include "src/heap/spaces.h"
      44             : #include "src/interpreter/interpreter.h"
      45             : #include "src/macro-assembler-inl.h"
      46             : #include "src/objects-inl.h"
      47             : #include "src/objects/js-array-buffer-inl.h"
      48             : #include "src/objects/js-array-inl.h"
      49             : #include "src/objects/js-regexp-inl.h"
      50             : #include "src/runtime/runtime.h"
      51             : #include "src/snapshot/code-serializer.h"
      52             : #include "src/snapshot/natives.h"
      53             : #include "src/snapshot/partial-deserializer.h"
      54             : #include "src/snapshot/partial-serializer.h"
      55             : #include "src/snapshot/read-only-deserializer.h"
      56             : #include "src/snapshot/read-only-serializer.h"
      57             : #include "src/snapshot/snapshot.h"
      58             : #include "src/snapshot/startup-deserializer.h"
      59             : #include "src/snapshot/startup-serializer.h"
      60             : #include "test/cctest/cctest.h"
      61             : #include "test/cctest/heap/heap-utils.h"
      62             : #include "test/cctest/setup-isolate-for-tests.h"
      63             : 
      64             : namespace v8 {
      65             : namespace internal {
      66             : 
      67             : enum CodeCacheType { kLazy, kEager, kAfterExecute };
      68             : 
      69           0 : void DisableAlwaysOpt() {
      70             :   // Isolates prepared for serialization do not optimize. The only exception is
      71             :   // with the flag --always-opt.
      72         230 :   FLAG_always_opt = false;
      73           0 : }
      74             : 
      75             : // A convenience struct to simplify management of the blobs required to
      76             : // deserialize an isolate.
      77             : struct StartupBlobs {
      78             :   Vector<const byte> startup;
      79             :   Vector<const byte> read_only;
      80             : 
      81          65 :   void Dispose() {
      82             :     startup.Dispose();
      83             :     read_only.Dispose();
      84          65 :   }
      85             : };
      86             : 
      87             : // TestSerializer is used for testing isolate serialization.
      88             : class TestSerializer {
      89             :  public:
      90          55 :   static v8::Isolate* NewIsolateInitialized() {
      91             :     const bool kEnableSerializer = true;
      92             :     const bool kGenerateHeap = true;
      93          55 :     DisableEmbeddedBlobRefcounting();
      94          55 :     v8::Isolate* v8_isolate = NewIsolate(kEnableSerializer, kGenerateHeap);
      95             :     v8::Isolate::Scope isolate_scope(v8_isolate);
      96             :     i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
      97          55 :     isolate->Init(nullptr, nullptr);
      98          55 :     isolate->heap()->read_only_space()->ClearStringPaddingIfNeeded();
      99          55 :     return v8_isolate;
     100             :   }
     101             : 
     102          55 :   static v8::Isolate* NewIsolateFromBlob(StartupBlobs& blobs) {
     103             :     SnapshotData startup_snapshot(blobs.startup);
     104             :     SnapshotData read_only_snapshot(blobs.read_only);
     105             :     ReadOnlyDeserializer read_only_deserializer(&read_only_snapshot);
     106             :     StartupDeserializer startup_deserializer(&startup_snapshot);
     107             :     const bool kEnableSerializer = false;
     108             :     const bool kGenerateHeap = false;
     109          55 :     v8::Isolate* v8_isolate = NewIsolate(kEnableSerializer, kGenerateHeap);
     110             :     v8::Isolate::Scope isolate_scope(v8_isolate);
     111             :     i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
     112          55 :     isolate->Init(&read_only_deserializer, &startup_deserializer);
     113          55 :     return v8_isolate;
     114             :   }
     115             : 
     116             :   // Wraps v8::Isolate::New, but with a test isolate under the hood.
     117             :   // Allows flexibility to bootstrap with or without snapshot even when
     118             :   // the production Isolate class has one or the other behavior baked in.
     119         155 :   static v8::Isolate* NewIsolate(const v8::Isolate::CreateParams& params) {
     120             :     const bool kEnableSerializer = false;
     121         155 :     const bool kGenerateHeap = params.snapshot_blob == nullptr;
     122         155 :     v8::Isolate* v8_isolate = NewIsolate(kEnableSerializer, kGenerateHeap);
     123         155 :     v8::Isolate::Initialize(v8_isolate, params);
     124         155 :     return v8_isolate;
     125             :   }
     126             : 
     127             :  private:
     128             :   // Creates an Isolate instance configured for testing.
     129         265 :   static v8::Isolate* NewIsolate(bool with_serializer, bool generate_heap) {
     130         265 :     i::Isolate* isolate = i::Isolate::New();
     131             :     v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
     132             : 
     133         265 :     if (with_serializer) isolate->enable_serializer();
     134             :     isolate->set_array_buffer_allocator(CcTest::array_buffer_allocator());
     135         530 :     isolate->setup_delegate_ = new SetupIsolateDelegateForTests(generate_heap);
     136             : 
     137         265 :     return v8_isolate;
     138             :   }
     139             : };
     140             : 
     141         140 : static Vector<const byte> WritePayload(const Vector<const byte>& payload) {
     142             :   int length = payload.length();
     143         140 :   byte* blob = NewArray<byte>(length);
     144             :   memcpy(blob, payload.begin(), length);
     145         140 :   return Vector<const byte>(const_cast<const byte*>(blob), length);
     146             : }
     147             : 
     148             : namespace {
     149             : 
     150          70 : bool RunExtraCode(v8::Isolate* isolate, v8::Local<v8::Context> context,
     151             :                   const char* utf8_source, const char* name) {
     152             :   v8::Context::Scope context_scope(context);
     153         140 :   v8::TryCatch try_catch(isolate);
     154             :   v8::Local<v8::String> source_string;
     155         140 :   if (!v8::String::NewFromUtf8(isolate, utf8_source, v8::NewStringType::kNormal)
     156             :            .ToLocal(&source_string)) {
     157             :     return false;
     158             :   }
     159             :   v8::Local<v8::String> resource_name =
     160          70 :       v8::String::NewFromUtf8(isolate, name, v8::NewStringType::kNormal)
     161             :           .ToLocalChecked();
     162             :   v8::ScriptOrigin origin(resource_name);
     163             :   v8::ScriptCompiler::Source source(source_string, origin);
     164             :   v8::Local<v8::Script> script;
     165         140 :   if (!v8::ScriptCompiler::Compile(context, &source).ToLocal(&script))
     166             :     return false;
     167         140 :   if (script->Run(context).IsEmpty()) return false;
     168          70 :   CHECK(!try_catch.HasCaught());
     169             :   return true;
     170             : }
     171             : 
     172          70 : v8::StartupData CreateSnapshotDataBlob(
     173             :     v8::SnapshotCreator::FunctionCodeHandling function_code_handling,
     174             :     const char* embedded_source) {
     175             :   // Create a new isolate and a new context from scratch, optionally run
     176             :   // a script to embed, and serialize to create a snapshot blob.
     177          70 :   DisableEmbeddedBlobRefcounting();
     178             :   v8::StartupData result = {nullptr, 0};
     179             :   {
     180         140 :     v8::SnapshotCreator snapshot_creator;
     181          70 :     v8::Isolate* isolate = snapshot_creator.GetIsolate();
     182             :     {
     183         140 :       v8::HandleScope scope(isolate);
     184          70 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
     185         130 :       if (embedded_source != nullptr &&
     186          60 :           !RunExtraCode(isolate, context, embedded_source, "<embedded>")) {
     187           0 :         return result;
     188             :       }
     189          70 :       snapshot_creator.SetDefaultContext(context);
     190             :     }
     191          70 :     result = snapshot_creator.CreateBlob(function_code_handling);
     192             :   }
     193          70 :   return result;
     194             : }
     195             : 
     196             : v8::StartupData CreateSnapshotDataBlob(const char* embedded_source = nullptr) {
     197             :   return CreateSnapshotDataBlob(
     198          60 :       v8::SnapshotCreator::FunctionCodeHandling::kClear, embedded_source);
     199             : }
     200             : 
     201          10 : v8::StartupData WarmUpSnapshotDataBlob(v8::StartupData cold_snapshot_blob,
     202             :                                        const char* warmup_source) {
     203          10 :   CHECK(cold_snapshot_blob.raw_size > 0 && cold_snapshot_blob.data != nullptr);
     204          10 :   CHECK_NOT_NULL(warmup_source);
     205             :   // Use following steps to create a warmed up snapshot blob from a cold one:
     206             :   //  - Create a new isolate from the cold snapshot.
     207             :   //  - Create a new context to run the warmup script. This will trigger
     208             :   //    compilation of executed functions.
     209             :   //  - Create a new context. This context will be unpolluted.
     210             :   //  - Serialize the isolate and the second context into a new snapshot blob.
     211             :   v8::StartupData result = {nullptr, 0};
     212             :   {
     213          20 :     v8::SnapshotCreator snapshot_creator(nullptr, &cold_snapshot_blob);
     214          10 :     v8::Isolate* isolate = snapshot_creator.GetIsolate();
     215             :     {
     216          20 :       v8::HandleScope scope(isolate);
     217          10 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
     218          10 :       if (!RunExtraCode(isolate, context, warmup_source, "<warm-up>")) {
     219           0 :         return result;
     220             :       }
     221             :     }
     222             :     {
     223          20 :       v8::HandleScope handle_scope(isolate);
     224          10 :       isolate->ContextDisposedNotification(false);
     225          10 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
     226          10 :       snapshot_creator.SetDefaultContext(context);
     227             :     }
     228             :     result = snapshot_creator.CreateBlob(
     229          10 :         v8::SnapshotCreator::FunctionCodeHandling::kKeep);
     230             :   }
     231          10 :   return result;
     232             : }
     233             : 
     234             : }  // namespace
     235             : 
     236          55 : static StartupBlobs Serialize(v8::Isolate* isolate) {
     237             :   // We have to create one context.  One reason for this is so that the builtins
     238             :   // can be loaded from self hosted JS builtins and their addresses can be
     239             :   // processed.  This will clear the pending fixups array, which would otherwise
     240             :   // contain GC roots that would confuse the serialization/deserialization
     241             :   // process.
     242             :   v8::Isolate::Scope isolate_scope(isolate);
     243             :   {
     244         110 :     v8::HandleScope scope(isolate);
     245          55 :     v8::Context::New(isolate);
     246             :   }
     247             : 
     248             :   Isolate* internal_isolate = reinterpret_cast<Isolate*>(isolate);
     249             :   internal_isolate->heap()->CollectAllAvailableGarbage(
     250          55 :       i::GarbageCollectionReason::kTesting);
     251             : 
     252         110 :   ReadOnlySerializer read_only_serializer(internal_isolate);
     253          55 :   read_only_serializer.SerializeReadOnlyRoots();
     254             : 
     255         110 :   StartupSerializer ser(internal_isolate, &read_only_serializer);
     256          55 :   ser.SerializeStrongReferences();
     257             : 
     258          55 :   ser.SerializeWeakReferencesAndDeferred();
     259          55 :   read_only_serializer.FinalizeSerialization();
     260          55 :   SnapshotData startup_snapshot(&ser);
     261          55 :   SnapshotData read_only_snapshot(&read_only_serializer);
     262         110 :   return {WritePayload(startup_snapshot.RawData()),
     263         165 :           WritePayload(read_only_snapshot.RawData())};
     264             : }
     265             : 
     266             : 
     267          50 : Vector<const uint8_t> ConstructSource(Vector<const uint8_t> head,
     268             :                                       Vector<const uint8_t> body,
     269             :                                       Vector<const uint8_t> tail, int repeats) {
     270         100 :   int source_length = head.length() + body.length() * repeats + tail.length();
     271          50 :   uint8_t* source = NewArray<uint8_t>(static_cast<size_t>(source_length));
     272          50 :   CopyChars(source, head.start(), head.length());
     273    35252190 :   for (int i = 0; i < repeats; i++) {
     274    17626070 :     CopyChars(source + head.length() + i * body.length(), body.start(),
     275             :               body.length());
     276             :   }
     277          50 :   CopyChars(source + head.length() + repeats * body.length(), tail.start(),
     278             :             tail.length());
     279             :   return Vector<const uint8_t>(const_cast<const uint8_t*>(source),
     280          50 :                                source_length);
     281             : }
     282             : 
     283             : 
     284          45 : static v8::Isolate* Deserialize(StartupBlobs& blobs) {
     285          45 :   v8::Isolate* isolate = TestSerializer::NewIsolateFromBlob(blobs);
     286          45 :   CHECK(isolate);
     287          45 :   return isolate;
     288             : }
     289             : 
     290             : 
     291          40 : static void SanityCheck(v8::Isolate* v8_isolate) {
     292             :   Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
     293          80 :   v8::HandleScope scope(v8_isolate);
     294             : #ifdef VERIFY_HEAP
     295             :   isolate->heap()->Verify();
     296             : #endif
     297          40 :   CHECK(isolate->global_object()->IsJSObject());
     298          80 :   CHECK(isolate->native_context()->IsContext());
     299          40 :   isolate->factory()->InternalizeOneByteString(StaticCharVector("Empty"));
     300          40 : }
     301             : 
     302          30 : void TestStartupSerializerOnceImpl() {
     303          30 :   v8::Isolate* isolate = TestSerializer::NewIsolateInitialized();
     304          30 :   StartupBlobs blobs = Serialize(isolate);
     305          30 :   isolate->Dispose();
     306          30 :   isolate = Deserialize(blobs);
     307             :   {
     308          60 :     v8::HandleScope handle_scope(isolate);
     309             :     v8::Isolate::Scope isolate_scope(isolate);
     310             : 
     311          30 :     v8::Local<v8::Context> env = v8::Context::New(isolate);
     312          30 :     env->Enter();
     313             : 
     314          30 :     SanityCheck(isolate);
     315             :   }
     316          30 :   isolate->Dispose();
     317          30 :   blobs.Dispose();
     318          30 :   FreeCurrentEmbeddedBlob();
     319          30 : }
     320             : 
     321       26644 : UNINITIALIZED_TEST(StartupSerializerOnce) {
     322             :   DisableAlwaysOpt();
     323           5 :   TestStartupSerializerOnceImpl();
     324           5 : }
     325             : 
     326       26644 : UNINITIALIZED_TEST(StartupSerializerOnce1) {
     327             :   DisableAlwaysOpt();
     328           5 :   FLAG_serialization_chunk_size = 1;
     329           5 :   TestStartupSerializerOnceImpl();
     330           5 : }
     331             : 
     332       26644 : UNINITIALIZED_TEST(StartupSerializerOnce32) {
     333             :   DisableAlwaysOpt();
     334           5 :   FLAG_serialization_chunk_size = 32;
     335           5 :   TestStartupSerializerOnceImpl();
     336           5 : }
     337             : 
     338       26644 : UNINITIALIZED_TEST(StartupSerializerOnce1K) {
     339             :   DisableAlwaysOpt();
     340           5 :   FLAG_serialization_chunk_size = 1 * KB;
     341           5 :   TestStartupSerializerOnceImpl();
     342           5 : }
     343             : 
     344       26644 : UNINITIALIZED_TEST(StartupSerializerOnce4K) {
     345             :   DisableAlwaysOpt();
     346           5 :   FLAG_serialization_chunk_size = 4 * KB;
     347           5 :   TestStartupSerializerOnceImpl();
     348           5 : }
     349             : 
     350       26644 : UNINITIALIZED_TEST(StartupSerializerOnce32K) {
     351             :   DisableAlwaysOpt();
     352           5 :   FLAG_serialization_chunk_size = 32 * KB;
     353           5 :   TestStartupSerializerOnceImpl();
     354           5 : }
     355             : 
     356       26644 : UNINITIALIZED_TEST(StartupSerializerRootMapDependencies) {
     357             :   DisableAlwaysOpt();
     358          10 :   v8::SnapshotCreator snapshot_creator;
     359           5 :   v8::Isolate* isolate = snapshot_creator.GetIsolate();
     360             :   {
     361             :     v8::Isolate::Scope isolate_scope(isolate);
     362          10 :     v8::HandleScope handle_scope(isolate);
     363             :     Isolate* internal_isolate = reinterpret_cast<Isolate*>(isolate);
     364             :     // Here is interesting retaining path:
     365             :     // - FreeSpaceMap
     366             :     // - Map for Map types itself
     367             :     // - NullValue
     368             :     // - Internalized one byte string
     369             :     // - Map for Internalized one byte string
     370             :     // - TheHoleValue
     371             :     // - HeapNumber
     372             :     // HeapNumber objects require kDoubleUnaligned on 32-bit
     373             :     // platforms. So, without special measures we're risking to serialize
     374             :     // object, requiring alignment before FreeSpaceMap is fully serialized.
     375             :     v8::internal::Handle<Map> map(
     376             :         ReadOnlyRoots(internal_isolate).one_byte_internalized_string_map(),
     377             :         internal_isolate);
     378             :     // Need to avoid DCHECKs inside SnapshotCreator.
     379           5 :     snapshot_creator.SetDefaultContext(v8::Context::New(isolate));
     380             :   }
     381             : 
     382             :   v8::StartupData startup_data = snapshot_creator.CreateBlob(
     383           5 :       v8::SnapshotCreator::FunctionCodeHandling::kKeep);
     384             : 
     385             :   v8::Isolate::CreateParams params;
     386           5 :   params.snapshot_blob = &startup_data;
     387           5 :   params.array_buffer_allocator = CcTest::array_buffer_allocator();
     388           5 :   isolate = v8::Isolate::New(params);
     389             : 
     390             :   {
     391          10 :     v8::HandleScope handle_scope(isolate);
     392             :     v8::Isolate::Scope isolate_scope(isolate);
     393             : 
     394           5 :     v8::Local<v8::Context> env = v8::Context::New(isolate);
     395           5 :     env->Enter();
     396             : 
     397           5 :     SanityCheck(isolate);
     398             :   }
     399           5 :   isolate->Dispose();
     400           5 :   delete[] startup_data.data;
     401           5 : }
     402             : 
     403       26644 : UNINITIALIZED_TEST(StartupSerializerTwice) {
     404             :   DisableAlwaysOpt();
     405           5 :   v8::Isolate* isolate = TestSerializer::NewIsolateInitialized();
     406           5 :   StartupBlobs blobs1 = Serialize(isolate);
     407           5 :   StartupBlobs blobs2 = Serialize(isolate);
     408           5 :   isolate->Dispose();
     409           5 :   blobs1.Dispose();
     410           5 :   isolate = Deserialize(blobs2);
     411             :   {
     412             :     v8::Isolate::Scope isolate_scope(isolate);
     413          10 :     v8::HandleScope handle_scope(isolate);
     414             : 
     415           5 :     v8::Local<v8::Context> env = v8::Context::New(isolate);
     416           5 :     env->Enter();
     417             : 
     418           5 :     SanityCheck(isolate);
     419             :   }
     420           5 :   isolate->Dispose();
     421           5 :   blobs2.Dispose();
     422           5 :   FreeCurrentEmbeddedBlob();
     423           5 : }
     424             : 
     425       26644 : UNINITIALIZED_TEST(StartupSerializerOnceRunScript) {
     426             :   DisableAlwaysOpt();
     427           5 :   v8::Isolate* isolate = TestSerializer::NewIsolateInitialized();
     428           5 :   StartupBlobs blobs = Serialize(isolate);
     429           5 :   isolate->Dispose();
     430           5 :   isolate = Deserialize(blobs);
     431             :   {
     432             :     v8::Isolate::Scope isolate_scope(isolate);
     433          10 :     v8::HandleScope handle_scope(isolate);
     434             : 
     435             : 
     436           5 :     v8::Local<v8::Context> env = v8::Context::New(isolate);
     437           5 :     env->Enter();
     438             : 
     439             :     const char* c_source = "\"1234\".length";
     440             :     v8::Local<v8::Script> script = v8_compile(c_source);
     441           5 :     v8::Maybe<int32_t> result = script->Run(isolate->GetCurrentContext())
     442             :                                     .ToLocalChecked()
     443          10 :                                     ->Int32Value(isolate->GetCurrentContext());
     444           5 :     CHECK_EQ(4, result.FromJust());
     445             :   }
     446           5 :   isolate->Dispose();
     447           5 :   blobs.Dispose();
     448           5 :   FreeCurrentEmbeddedBlob();
     449           5 : }
     450             : 
     451       26644 : UNINITIALIZED_TEST(StartupSerializerTwiceRunScript) {
     452             :   DisableAlwaysOpt();
     453           5 :   v8::Isolate* isolate = TestSerializer::NewIsolateInitialized();
     454           5 :   StartupBlobs blobs1 = Serialize(isolate);
     455           5 :   StartupBlobs blobs2 = Serialize(isolate);
     456           5 :   isolate->Dispose();
     457           5 :   blobs1.Dispose();
     458           5 :   isolate = Deserialize(blobs2);
     459             :   {
     460             :     v8::Isolate::Scope isolate_scope(isolate);
     461          10 :     v8::HandleScope handle_scope(isolate);
     462             : 
     463           5 :     v8::Local<v8::Context> env = v8::Context::New(isolate);
     464           5 :     env->Enter();
     465             : 
     466             :     const char* c_source = "\"1234\".length";
     467             :     v8::Local<v8::Script> script = v8_compile(c_source);
     468           5 :     v8::Maybe<int32_t> result = script->Run(isolate->GetCurrentContext())
     469             :                                     .ToLocalChecked()
     470          10 :                                     ->Int32Value(isolate->GetCurrentContext());
     471           5 :     CHECK_EQ(4, result.FromJust());
     472             :   }
     473           5 :   isolate->Dispose();
     474           5 :   blobs2.Dispose();
     475           5 :   FreeCurrentEmbeddedBlob();
     476           5 : }
     477             : 
     478           5 : static void PartiallySerializeContext(Vector<const byte>* startup_blob_out,
     479             :                                       Vector<const byte>* read_only_blob_out,
     480             :                                       Vector<const byte>* partial_blob_out) {
     481           5 :   v8::Isolate* v8_isolate = TestSerializer::NewIsolateInitialized();
     482             :   Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
     483             :   Heap* heap = isolate->heap();
     484             :   {
     485             :     v8::Isolate::Scope isolate_scope(v8_isolate);
     486             : 
     487             :     v8::Persistent<v8::Context> env;
     488             :     {
     489             :       HandleScope scope(isolate);
     490          10 :       env.Reset(v8_isolate, v8::Context::New(v8_isolate));
     491             :     }
     492           5 :     CHECK(!env.IsEmpty());
     493             :     {
     494          10 :       v8::HandleScope handle_scope(v8_isolate);
     495           5 :       v8::Local<v8::Context>::New(v8_isolate, env)->Enter();
     496             :     }
     497             : 
     498             :     // If we don't do this then we end up with a stray root pointing at the
     499             :     // context even after we have disposed of env.
     500           5 :     heap->CollectAllAvailableGarbage(i::GarbageCollectionReason::kTesting);
     501             : 
     502             :     {
     503          10 :       v8::HandleScope handle_scope(v8_isolate);
     504           5 :       v8::Local<v8::Context>::New(v8_isolate, env)->Exit();
     505             :     }
     506             : 
     507           5 :     i::Context raw_context = i::Context::cast(*v8::Utils::OpenPersistent(env));
     508             : 
     509             :     env.Reset();
     510             : 
     511             :     SnapshotByteSink read_only_sink;
     512          10 :     ReadOnlySerializer read_only_serializer(isolate);
     513           5 :     read_only_serializer.SerializeReadOnlyRoots();
     514             : 
     515             :     SnapshotByteSink startup_sink;
     516          10 :     StartupSerializer startup_serializer(isolate, &read_only_serializer);
     517           5 :     startup_serializer.SerializeStrongReferences();
     518             : 
     519             :     SnapshotByteSink partial_sink;
     520             :     PartialSerializer partial_serializer(isolate, &startup_serializer,
     521          10 :                                          v8::SerializeInternalFieldsCallback());
     522           5 :     partial_serializer.Serialize(&raw_context, false);
     523             : 
     524           5 :     startup_serializer.SerializeWeakReferencesAndDeferred();
     525             : 
     526           5 :     read_only_serializer.FinalizeSerialization();
     527             : 
     528           5 :     SnapshotData read_only_snapshot(&read_only_serializer);
     529           5 :     SnapshotData startup_snapshot(&startup_serializer);
     530           5 :     SnapshotData partial_snapshot(&partial_serializer);
     531             : 
     532           5 :     *partial_blob_out = WritePayload(partial_snapshot.RawData());
     533           5 :     *startup_blob_out = WritePayload(startup_snapshot.RawData());
     534           5 :     *read_only_blob_out = WritePayload(read_only_snapshot.RawData());
     535             :   }
     536           5 :   v8_isolate->Dispose();
     537           5 : }
     538             : 
     539       26644 : UNINITIALIZED_TEST(PartialSerializerContext) {
     540             :   DisableAlwaysOpt();
     541           5 :   Vector<const byte> startup_blob;
     542           5 :   Vector<const byte> read_only_blob;
     543           5 :   Vector<const byte> partial_blob;
     544           5 :   PartiallySerializeContext(&startup_blob, &read_only_blob, &partial_blob);
     545             : 
     546           5 :   StartupBlobs blobs = {startup_blob, read_only_blob};
     547           5 :   v8::Isolate* v8_isolate = TestSerializer::NewIsolateFromBlob(blobs);
     548           5 :   CHECK(v8_isolate);
     549             :   {
     550             :     v8::Isolate::Scope isolate_scope(v8_isolate);
     551             : 
     552             :     Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
     553             :     HandleScope handle_scope(isolate);
     554             :     Handle<Object> root;
     555             :     Handle<JSGlobalProxy> global_proxy =
     556             :         isolate->factory()->NewUninitializedJSGlobalProxy(
     557           5 :             JSGlobalProxy::SizeWithEmbedderFields(0));
     558             :     {
     559             :       SnapshotData snapshot_data(partial_blob);
     560          10 :       root = PartialDeserializer::DeserializeContext(
     561             :                  isolate, &snapshot_data, false, global_proxy,
     562           5 :                  v8::DeserializeInternalFieldsCallback())
     563             :                  .ToHandleChecked();
     564           5 :       CHECK(root->IsContext());
     565          10 :       CHECK(Handle<Context>::cast(root)->global_proxy() == *global_proxy);
     566             :     }
     567             : 
     568             :     Handle<Object> root2;
     569             :     {
     570             :       SnapshotData snapshot_data(partial_blob);
     571          10 :       root2 = PartialDeserializer::DeserializeContext(
     572             :                   isolate, &snapshot_data, false, global_proxy,
     573           5 :                   v8::DeserializeInternalFieldsCallback())
     574             :                   .ToHandleChecked();
     575           5 :       CHECK(root2->IsContext());
     576           5 :       CHECK(!root.is_identical_to(root2));
     577             :     }
     578             :     partial_blob.Dispose();
     579             :   }
     580           5 :   v8_isolate->Dispose();
     581           5 :   blobs.Dispose();
     582           5 :   FreeCurrentEmbeddedBlob();
     583           5 : }
     584             : 
     585           5 : static void PartiallySerializeCustomContext(
     586             :     Vector<const byte>* startup_blob_out,
     587             :     Vector<const byte>* read_only_blob_out,
     588             :     Vector<const byte>* partial_blob_out) {
     589           5 :   v8::Isolate* v8_isolate = TestSerializer::NewIsolateInitialized();
     590             :   Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
     591             :   {
     592             :     v8::Isolate::Scope isolate_scope(v8_isolate);
     593             : 
     594             :     v8::Persistent<v8::Context> env;
     595             :     {
     596             :       HandleScope scope(isolate);
     597          10 :       env.Reset(v8_isolate, v8::Context::New(v8_isolate));
     598             :     }
     599           5 :     CHECK(!env.IsEmpty());
     600             :     {
     601          10 :       v8::HandleScope handle_scope(v8_isolate);
     602           5 :       v8::Local<v8::Context>::New(v8_isolate, env)->Enter();
     603             :       // After execution, e's function context refers to the global object.
     604             :       CompileRun(
     605             :           "var e;"
     606             :           "(function() {"
     607             :           "  e = function(s) { return eval (s); }"
     608             :           "})();"
     609             :           "var o = this;"
     610             :           "var r = Math.random();"
     611             :           "var c = Math.sin(0) + Math.cos(0);"
     612             :           "var f = (function(a, b) { return a + b; }).bind(1, 2, 3);"
     613             :           "var s = parseInt('12345');"
     614             :           "var p = 0;"
     615             :           "(async ()=>{ p = await 42; })();");
     616             : 
     617             :       Vector<const uint8_t> source = ConstructSource(
     618             :           StaticCharVector("function g() { return [,"), StaticCharVector("1,"),
     619           5 :           StaticCharVector("];} a = g(); b = g(); b.push(1);"), 100000);
     620             :       v8::MaybeLocal<v8::String> source_str = v8::String::NewFromOneByte(
     621             :           v8_isolate, source.start(), v8::NewStringType::kNormal,
     622           5 :           source.length());
     623           5 :       CompileRun(source_str.ToLocalChecked());
     624             :       source.Dispose();
     625             :     }
     626             :     // If we don't do this then we end up with a stray root pointing at the
     627             :     // context even after we have disposed of env.
     628             :     isolate->heap()->CollectAllAvailableGarbage(
     629           5 :         i::GarbageCollectionReason::kTesting);
     630             : 
     631             :     {
     632          10 :       v8::HandleScope handle_scope(v8_isolate);
     633           5 :       v8::Local<v8::Context>::New(v8_isolate, env)->Exit();
     634             :     }
     635             : 
     636           5 :     i::Context raw_context = i::Context::cast(*v8::Utils::OpenPersistent(env));
     637             : 
     638             :     env.Reset();
     639             : 
     640             :     SnapshotByteSink read_only_sink;
     641          10 :     ReadOnlySerializer read_only_serializer(isolate);
     642           5 :     read_only_serializer.SerializeReadOnlyRoots();
     643             : 
     644             :     SnapshotByteSink startup_sink;
     645          10 :     StartupSerializer startup_serializer(isolate, &read_only_serializer);
     646           5 :     startup_serializer.SerializeStrongReferences();
     647             : 
     648             :     SnapshotByteSink partial_sink;
     649             :     PartialSerializer partial_serializer(isolate, &startup_serializer,
     650          10 :                                          v8::SerializeInternalFieldsCallback());
     651           5 :     partial_serializer.Serialize(&raw_context, false);
     652             : 
     653           5 :     startup_serializer.SerializeWeakReferencesAndDeferred();
     654             : 
     655           5 :     read_only_serializer.FinalizeSerialization();
     656             : 
     657           5 :     SnapshotData read_only_snapshot(&read_only_serializer);
     658           5 :     SnapshotData startup_snapshot(&startup_serializer);
     659           5 :     SnapshotData partial_snapshot(&partial_serializer);
     660             : 
     661           5 :     *partial_blob_out = WritePayload(partial_snapshot.RawData());
     662           5 :     *startup_blob_out = WritePayload(startup_snapshot.RawData());
     663           5 :     *read_only_blob_out = WritePayload(read_only_snapshot.RawData());
     664             :   }
     665           5 :   v8_isolate->Dispose();
     666           5 : }
     667             : 
     668       26644 : UNINITIALIZED_TEST(PartialSerializerCustomContext) {
     669             :   DisableAlwaysOpt();
     670           5 :   Vector<const byte> startup_blob;
     671           5 :   Vector<const byte> read_only_blob;
     672           5 :   Vector<const byte> partial_blob;
     673             :   PartiallySerializeCustomContext(&startup_blob, &read_only_blob,
     674           5 :                                   &partial_blob);
     675             : 
     676           5 :   StartupBlobs blobs = {startup_blob, read_only_blob};
     677           5 :   v8::Isolate* v8_isolate = TestSerializer::NewIsolateFromBlob(blobs);
     678           5 :   CHECK(v8_isolate);
     679             :   {
     680             :     v8::Isolate::Scope isolate_scope(v8_isolate);
     681             : 
     682             :     Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
     683             :     HandleScope handle_scope(isolate);
     684             :     Handle<Object> root;
     685             :     Handle<JSGlobalProxy> global_proxy =
     686             :         isolate->factory()->NewUninitializedJSGlobalProxy(
     687           5 :             JSGlobalProxy::SizeWithEmbedderFields(0));
     688             :     {
     689             :       SnapshotData snapshot_data(partial_blob);
     690          10 :       root = PartialDeserializer::DeserializeContext(
     691             :                  isolate, &snapshot_data, false, global_proxy,
     692           5 :                  v8::DeserializeInternalFieldsCallback())
     693             :                  .ToHandleChecked();
     694           5 :       CHECK(root->IsContext());
     695             :       Handle<Context> context = Handle<Context>::cast(root);
     696             : 
     697             :       // Add context to the weak native context list
     698             :       context->set(Context::NEXT_CONTEXT_LINK,
     699             :                    isolate->heap()->native_contexts_list(),
     700             :                    UPDATE_WEAK_WRITE_BARRIER);
     701             :       isolate->heap()->set_native_contexts_list(*context);
     702             : 
     703          10 :       CHECK(context->global_proxy() == *global_proxy);
     704           5 :       Handle<String> o = isolate->factory()->NewStringFromAsciiChecked("o");
     705          10 :       Handle<JSObject> global_object(context->global_object(), isolate);
     706           5 :       Handle<Object> property = JSReceiver::GetDataProperty(global_object, o);
     707           5 :       CHECK(property.is_identical_to(global_proxy));
     708             : 
     709             :       v8::Local<v8::Context> v8_context = v8::Utils::ToLocal(context);
     710             :       v8::Context::Scope context_scope(v8_context);
     711             :       double r = CompileRun("r")
     712          10 :                      ->ToNumber(v8_isolate->GetCurrentContext())
     713             :                      .ToLocalChecked()
     714           5 :                      ->Value();
     715           5 :       CHECK(0.0 <= r && r < 1.0);
     716             :       // Math.random still works.
     717             :       double random = CompileRun("Math.random()")
     718          10 :                           ->ToNumber(v8_isolate->GetCurrentContext())
     719             :                           .ToLocalChecked()
     720           5 :                           ->Value();
     721           5 :       CHECK(0.0 <= random && random < 1.0);
     722             :       double c = CompileRun("c")
     723          10 :                      ->ToNumber(v8_isolate->GetCurrentContext())
     724             :                      .ToLocalChecked()
     725           5 :                      ->Value();
     726           5 :       CHECK_EQ(1, c);
     727             :       int f = CompileRun("f()")
     728          10 :                   ->ToNumber(v8_isolate->GetCurrentContext())
     729             :                   .ToLocalChecked()
     730          15 :                   ->Int32Value(v8_isolate->GetCurrentContext())
     731             :                   .FromJust();
     732           5 :       CHECK_EQ(5, f);
     733             :       f = CompileRun("e('f()')")
     734          10 :               ->ToNumber(v8_isolate->GetCurrentContext())
     735             :               .ToLocalChecked()
     736          15 :               ->Int32Value(v8_isolate->GetCurrentContext())
     737             :               .FromJust();
     738           5 :       CHECK_EQ(5, f);
     739             :       v8::Local<v8::String> s = CompileRun("s")
     740          10 :                                     ->ToString(v8_isolate->GetCurrentContext())
     741             :                                     .ToLocalChecked();
     742          15 :       CHECK(s->Equals(v8_isolate->GetCurrentContext(), v8_str("12345"))
     743             :                 .FromJust());
     744             :       v8::Local<v8::String> p = CompileRun("p")
     745          10 :                                     ->ToString(v8_isolate->GetCurrentContext())
     746             :                                     .ToLocalChecked();
     747          15 :       CHECK(
     748             :           p->Equals(v8_isolate->GetCurrentContext(), v8_str("42")).FromJust());
     749             :       int a = CompileRun("a.length")
     750          10 :                   ->ToNumber(v8_isolate->GetCurrentContext())
     751             :                   .ToLocalChecked()
     752          15 :                   ->Int32Value(v8_isolate->GetCurrentContext())
     753             :                   .FromJust();
     754           5 :       CHECK_EQ(100001, a);
     755             :       int b = CompileRun("b.length")
     756          10 :                   ->ToNumber(v8_isolate->GetCurrentContext())
     757             :                   .ToLocalChecked()
     758          15 :                   ->Int32Value(v8_isolate->GetCurrentContext())
     759             :                   .FromJust();
     760           5 :       CHECK_EQ(100002, b);
     761             :     }
     762             :     partial_blob.Dispose();
     763             :   }
     764           5 :   v8_isolate->Dispose();
     765           5 :   blobs.Dispose();
     766           5 :   FreeCurrentEmbeddedBlob();
     767           5 : }
     768             : 
     769       26644 : UNINITIALIZED_TEST(CustomSnapshotDataBlob1) {
     770             :   DisableAlwaysOpt();
     771             :   const char* source1 = "function f() { return 42; }";
     772             : 
     773           5 :   v8::StartupData data1 = CreateSnapshotDataBlob(source1);
     774             : 
     775             :   v8::Isolate::CreateParams params1;
     776           5 :   params1.snapshot_blob = &data1;
     777           5 :   params1.array_buffer_allocator = CcTest::array_buffer_allocator();
     778             : 
     779             :   // Test-appropriate equivalent of v8::Isolate::New.
     780           5 :   v8::Isolate* isolate1 = TestSerializer::NewIsolate(params1);
     781             :   {
     782             :     v8::Isolate::Scope i_scope(isolate1);
     783          10 :     v8::HandleScope h_scope(isolate1);
     784           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate1);
     785             :     v8::Context::Scope c_scope(context);
     786             :     v8::Maybe<int32_t> result =
     787          10 :         CompileRun("f()")->Int32Value(isolate1->GetCurrentContext());
     788           5 :     CHECK_EQ(42, result.FromJust());
     789           5 :     CHECK(CompileRun("this.g")->IsUndefined());
     790             :   }
     791           5 :   isolate1->Dispose();
     792           5 :   delete[] data1.data;  // We can dispose of the snapshot blob now.
     793           5 :   FreeCurrentEmbeddedBlob();
     794           5 : }
     795             : 
     796           0 : static void UnreachableCallback(const FunctionCallbackInfo<Value>& args) {
     797           0 :   UNREACHABLE();
     798             : }
     799             : 
     800       26644 : UNINITIALIZED_TEST(CustomSnapshotDataBlobOverwriteGlobal) {
     801             :   DisableAlwaysOpt();
     802             :   const char* source1 = "function f() { return 42; }";
     803             : 
     804           5 :   v8::StartupData data1 = CreateSnapshotDataBlob(source1);
     805             : 
     806             :   v8::Isolate::CreateParams params1;
     807           5 :   params1.snapshot_blob = &data1;
     808           5 :   params1.array_buffer_allocator = CcTest::array_buffer_allocator();
     809             : 
     810             :   // Test that the snapshot overwrites the object template when there are
     811             :   // duplicate global properties.
     812           5 :   v8::Isolate* isolate1 = TestSerializer::NewIsolate(params1);
     813             :   {
     814             :     v8::Isolate::Scope i_scope(isolate1);
     815          10 :     v8::HandleScope h_scope(isolate1);
     816             :     v8::Local<v8::ObjectTemplate> global_template =
     817           5 :         v8::ObjectTemplate::New(isolate1);
     818          15 :     global_template->Set(
     819           5 :         v8_str("f"), v8::FunctionTemplate::New(isolate1, UnreachableCallback));
     820             :     v8::Local<v8::Context> context =
     821           5 :         v8::Context::New(isolate1, nullptr, global_template);
     822             :     v8::Context::Scope c_scope(context);
     823             :     v8::Maybe<int32_t> result =
     824          10 :         CompileRun("f()")->Int32Value(isolate1->GetCurrentContext());
     825           5 :     CHECK_EQ(42, result.FromJust());
     826             :   }
     827           5 :   isolate1->Dispose();
     828           5 :   delete[] data1.data;  // We can dispose of the snapshot blob now.
     829           5 :   FreeCurrentEmbeddedBlob();
     830           5 : }
     831             : 
     832       26644 : UNINITIALIZED_TEST(CustomSnapshotDataBlobStringNotInternalized) {
     833             :   DisableAlwaysOpt();
     834             :   const char* source1 =
     835             :       R"javascript(
     836             :       // String would be internalized if it came from a literal so create "A"
     837             :       // via a function call.
     838             :       var global = String.fromCharCode(65);
     839             :       function f() { return global; }
     840             :       )javascript";
     841             : 
     842           5 :   v8::StartupData data1 = CreateSnapshotDataBlob(source1);
     843             : 
     844             :   v8::Isolate::CreateParams params1;
     845           5 :   params1.snapshot_blob = &data1;
     846           5 :   params1.array_buffer_allocator = CcTest::array_buffer_allocator();
     847             : 
     848             :   // Test-appropriate equivalent of v8::Isolate::New.
     849           5 :   v8::Isolate* isolate1 = TestSerializer::NewIsolate(params1);
     850             :   {
     851             :     v8::Isolate::Scope i_scope(isolate1);
     852          10 :     v8::HandleScope h_scope(isolate1);
     853           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate1);
     854             :     v8::Context::Scope c_scope(context);
     855             :     v8::Local<v8::Value> result = CompileRun("f()").As<v8::Value>();
     856           5 :     CHECK(result->IsString());
     857           5 :     i::String str = *v8::Utils::OpenHandle(*result.As<v8::String>());
     858          20 :     CHECK_EQ(std::string(str->ToCString().get()), "A");
     859           5 :     CHECK(!str.IsInternalizedString());
     860           5 :     CHECK(!i::ReadOnlyHeap::Contains(str));
     861             :   }
     862           5 :   isolate1->Dispose();
     863           5 :   delete[] data1.data;  // We can dispose of the snapshot blob now.
     864           5 :   FreeCurrentEmbeddedBlob();
     865           5 : }
     866             : 
     867             : namespace {
     868             : 
     869          10 : void TestCustomSnapshotDataBlobWithIrregexpCode(
     870             :     v8::SnapshotCreator::FunctionCodeHandling function_code_handling) {
     871             :   DisableAlwaysOpt();
     872             :   const char* source =
     873             :       "var re1 = /\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\//;\n"
     874             :       "function f() { return '/* a comment */'.search(re1); }\n"
     875             :       "function g() { return 'not a comment'.search(re1); }\n"
     876             :       "function h() { return '// this is a comment'.search(re1); }\n"
     877             :       "var re2 = /a/;\n"
     878             :       "function i() { return '/* a comment */'.search(re2); }\n"
     879             :       "f(); f(); g(); g(); h(); h(); i(); i();\n";
     880             : 
     881             :   v8::StartupData data1 =
     882          10 :       CreateSnapshotDataBlob(function_code_handling, source);
     883             : 
     884             :   v8::Isolate::CreateParams params1;
     885          10 :   params1.snapshot_blob = &data1;
     886          10 :   params1.array_buffer_allocator = CcTest::array_buffer_allocator();
     887             : 
     888             :   // Test-appropriate equivalent of v8::Isolate::New.
     889          10 :   v8::Isolate* isolate1 = TestSerializer::NewIsolate(params1);
     890             :   {
     891             :     v8::Isolate::Scope i_scope(isolate1);
     892          20 :     v8::HandleScope h_scope(isolate1);
     893          10 :     v8::Local<v8::Context> context = v8::Context::New(isolate1);
     894             :     v8::Context::Scope c_scope(context);
     895             :     {
     896             :       // Check that compiled irregexp code has not been flushed prior to
     897             :       // serialization.
     898             :       i::Handle<i::JSRegExp> re =
     899             :           Utils::OpenHandle(*CompileRun("re1").As<v8::RegExp>());
     900          20 :       CHECK_EQ(re->HasCompiledCode(),
     901             :                function_code_handling ==
     902             :                    v8::SnapshotCreator::FunctionCodeHandling::kKeep);
     903             :     }
     904             :     {
     905             :       v8::Maybe<int32_t> result =
     906          20 :           CompileRun("f()")->Int32Value(isolate1->GetCurrentContext());
     907          10 :       CHECK_EQ(0, result.FromJust());
     908             :     }
     909             :     {
     910             :       v8::Maybe<int32_t> result =
     911          20 :           CompileRun("g()")->Int32Value(isolate1->GetCurrentContext());
     912          10 :       CHECK_EQ(-1, result.FromJust());
     913             :     }
     914             :     {
     915             :       v8::Maybe<int32_t> result =
     916          20 :           CompileRun("h()")->Int32Value(isolate1->GetCurrentContext());
     917          10 :       CHECK_EQ(-1, result.FromJust());
     918             :     }
     919             :     {
     920             :       // Check that ATOM regexp remains valid.
     921             :       i::Handle<i::JSRegExp> re =
     922             :           Utils::OpenHandle(*CompileRun("re2").As<v8::RegExp>());
     923          10 :       CHECK_EQ(re->TypeTag(), JSRegExp::ATOM);
     924          10 :       CHECK(!re->HasCompiledCode());
     925             :     }
     926             :   }
     927          10 :   isolate1->Dispose();
     928          10 :   delete[] data1.data;  // We can dispose of the snapshot blob now.
     929          10 :   FreeCurrentEmbeddedBlob();
     930          10 : }
     931             : 
     932             : }  // namespace
     933             : 
     934       26644 : UNINITIALIZED_TEST(CustomSnapshotDataBlobWithIrregexpCodeKeepCode) {
     935             :   TestCustomSnapshotDataBlobWithIrregexpCode(
     936           5 :       v8::SnapshotCreator::FunctionCodeHandling::kKeep);
     937           5 : }
     938             : 
     939       26644 : UNINITIALIZED_TEST(CustomSnapshotDataBlobWithIrregexpCodeClearCode) {
     940             :   TestCustomSnapshotDataBlobWithIrregexpCode(
     941           5 :       v8::SnapshotCreator::FunctionCodeHandling::kClear);
     942           5 : }
     943             : 
     944       26644 : UNINITIALIZED_TEST(SnapshotChecksum) {
     945             :   DisableAlwaysOpt();
     946             :   const char* source1 = "function f() { return 42; }";
     947             : 
     948           5 :   v8::StartupData data1 = CreateSnapshotDataBlob(source1);
     949           5 :   CHECK(i::Snapshot::VerifyChecksum(&data1));
     950           5 :   const_cast<char*>(data1.data)[142] = data1.data[142] ^ 4;  // Flip a bit.
     951           5 :   CHECK(!i::Snapshot::VerifyChecksum(&data1));
     952           5 :   delete[] data1.data;  // We can dispose of the snapshot blob now.
     953           5 :   FreeCurrentEmbeddedBlob();
     954           5 : }
     955             : 
     956             : struct InternalFieldData {
     957             :   uint32_t data;
     958             : };
     959             : 
     960         250 : v8::StartupData SerializeInternalFields(v8::Local<v8::Object> holder, int index,
     961             :                                         void* data) {
     962         250 :   if (data == reinterpret_cast<void*>(2000)) {
     963             :     // Used for SnapshotCreatorTemplates test. We check that none of the fields
     964             :     // have been cleared yet.
     965          20 :     CHECK_NOT_NULL(holder->GetAlignedPointerFromInternalField(1));
     966             :   } else {
     967         230 :     CHECK_EQ(reinterpret_cast<void*>(2016), data);
     968             :   }
     969         250 :   if (index != 1) return {nullptr, 0};
     970             :   InternalFieldData* embedder_field = static_cast<InternalFieldData*>(
     971             :       holder->GetAlignedPointerFromInternalField(index));
     972         130 :   if (embedder_field == nullptr) return {nullptr, 0};
     973             :   int size = sizeof(*embedder_field);
     974          15 :   char* payload = new char[size];
     975             :   // We simply use memcpy to serialize the content.
     976             :   memcpy(payload, embedder_field, size);
     977          15 :   return {payload, size};
     978             : }
     979             : 
     980       26639 : std::vector<InternalFieldData*> deserialized_data;
     981             : 
     982          15 : void DeserializeInternalFields(v8::Local<v8::Object> holder, int index,
     983             :                                v8::StartupData payload, void* data) {
     984          15 :   if (payload.raw_size == 0) {
     985           0 :     holder->SetAlignedPointerInInternalField(index, nullptr);
     986           0 :     return;
     987             :   }
     988          15 :   CHECK_EQ(reinterpret_cast<void*>(2017), data);
     989          15 :   InternalFieldData* embedder_field = new InternalFieldData{0};
     990          15 :   memcpy(embedder_field, payload.data, payload.raw_size);
     991          15 :   holder->SetAlignedPointerInInternalField(index, embedder_field);
     992          15 :   deserialized_data.push_back(embedder_field);
     993             : }
     994             : 
     995             : typedef std::vector<std::tuple<const char*, int32_t>> Int32Expectations;
     996             : 
     997           0 : void TestInt32Expectations(const Int32Expectations& expectations) {
     998         330 :   for (const auto& e : expectations) {
     999         250 :     ExpectInt32(std::get<0>(e), std::get<1>(e));
    1000             :   }
    1001           0 : }
    1002             : 
    1003          20 : void TypedArrayTestHelper(
    1004             :     const char* code, const Int32Expectations& expectations,
    1005             :     const char* code_to_run_after_restore = nullptr,
    1006             :     const Int32Expectations& after_restore_expectations = Int32Expectations()) {
    1007             :   DisableAlwaysOpt();
    1008          20 :   i::FLAG_allow_natives_syntax = true;
    1009          20 :   DisableEmbeddedBlobRefcounting();
    1010             :   v8::StartupData blob;
    1011             :   {
    1012          40 :     v8::SnapshotCreator creator;
    1013          20 :     v8::Isolate* isolate = creator.GetIsolate();
    1014             :     {
    1015          40 :       v8::HandleScope handle_scope(isolate);
    1016          20 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    1017             :       v8::Context::Scope context_scope(context);
    1018             : 
    1019             :       CompileRun(code);
    1020             :       TestInt32Expectations(expectations);
    1021          20 :       creator.SetDefaultContext(
    1022             :           context, v8::SerializeInternalFieldsCallback(
    1023          20 :                        SerializeInternalFields, reinterpret_cast<void*>(2016)));
    1024             :     }
    1025             :     blob =
    1026          20 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    1027             :   }
    1028             : 
    1029             :   v8::Isolate::CreateParams create_params;
    1030          20 :   create_params.snapshot_blob = &blob;
    1031          20 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    1032          20 :   v8::Isolate* isolate = TestSerializer::NewIsolate(create_params);
    1033             :   {
    1034             :     v8::Isolate::Scope i_scope(isolate);
    1035          40 :     v8::HandleScope h_scope(isolate);
    1036             :     v8::Local<v8::Context> context = v8::Context::New(
    1037             :         isolate, nullptr, v8::MaybeLocal<v8::ObjectTemplate>(),
    1038             :         v8::MaybeLocal<v8::Value>(),
    1039             :         v8::DeserializeInternalFieldsCallback(DeserializeInternalFields,
    1040          20 :                                               reinterpret_cast<void*>(2017)));
    1041          20 :     CHECK(deserialized_data.empty());  // We do not expect any embedder data.
    1042             :     v8::Context::Scope c_scope(context);
    1043             :     TestInt32Expectations(expectations);
    1044          20 :     if (code_to_run_after_restore) {
    1045             :       CompileRun(code_to_run_after_restore);
    1046             :     }
    1047             :     TestInt32Expectations(after_restore_expectations);
    1048             :   }
    1049          20 :   isolate->Dispose();
    1050          20 :   delete[] blob.data;  // We can dispose of the snapshot blob now.
    1051          20 :   FreeCurrentEmbeddedBlob();
    1052          20 : }
    1053             : 
    1054       26644 : UNINITIALIZED_TEST(CustomSnapshotDataBlobWithOffHeapTypedArray) {
    1055             :   const char* code =
    1056             :       "var x = new Uint8Array(128);"
    1057             :       "x[0] = 12;"
    1058             :       "var arr = new Array(17);"
    1059             :       "arr[1] = 24;"
    1060             :       "var y = new Uint32Array(arr);"
    1061             :       "var buffer = new ArrayBuffer(128);"
    1062             :       "var z = new Int16Array(buffer);"
    1063             :       "z[0] = 48;";
    1064             :   Int32Expectations expectations = {std::make_tuple("x[0]", 12),
    1065             :                                     std::make_tuple("y[1]", 24),
    1066             :                                     std::make_tuple("z[0]", 48)};
    1067             : 
    1068          10 :   TypedArrayTestHelper(code, expectations);
    1069           5 : }
    1070             : 
    1071       26644 : UNINITIALIZED_TEST(CustomSnapshotDataBlobSharedArrayBuffer) {
    1072             :   const char* code =
    1073             :       "var x = new Int32Array([12, 24, 48, 96]);"
    1074             :       "var y = new Uint8Array(x.buffer)";
    1075             :   Int32Expectations expectations = {
    1076             :     std::make_tuple("x[0]", 12),
    1077             :     std::make_tuple("x[1]", 24),
    1078             : #if !V8_TARGET_BIG_ENDIAN
    1079             :     std::make_tuple("y[0]", 12),
    1080             :     std::make_tuple("y[1]", 0),
    1081             :     std::make_tuple("y[2]", 0),
    1082             :     std::make_tuple("y[3]", 0),
    1083             :     std::make_tuple("y[4]", 24)
    1084             : #else
    1085             :     std::make_tuple("y[3]", 12),
    1086             :     std::make_tuple("y[2]", 0),
    1087             :     std::make_tuple("y[1]", 0),
    1088             :     std::make_tuple("y[0]", 0),
    1089             :     std::make_tuple("y[7]", 24)
    1090             : #endif
    1091             :   };
    1092             : 
    1093          10 :   TypedArrayTestHelper(code, expectations);
    1094           5 : }
    1095             : 
    1096       26644 : UNINITIALIZED_TEST(CustomSnapshotDataBlobArrayBufferWithOffset) {
    1097             :   const char* code =
    1098             :       "var x = new Int32Array([12, 24, 48, 96]);"
    1099             :       "var y = new Int32Array(x.buffer, 4, 2)";
    1100             :   Int32Expectations expectations = {
    1101             :       std::make_tuple("x[1]", 24), std::make_tuple("x[2]", 48),
    1102             :       std::make_tuple("y[0]", 24), std::make_tuple("y[1]", 48),
    1103             :   };
    1104             : 
    1105             :   // Verify that the typed arrays use the same buffer (not independent copies).
    1106             :   const char* code_to_run_after_restore = "x[2] = 57; y[0] = 42;";
    1107             :   Int32Expectations after_restore_expectations = {
    1108             :       std::make_tuple("x[1]", 42), std::make_tuple("y[1]", 57),
    1109             :   };
    1110             : 
    1111             :   TypedArrayTestHelper(code, expectations, code_to_run_after_restore,
    1112           5 :                        after_restore_expectations);
    1113           5 : }
    1114             : 
    1115       26644 : UNINITIALIZED_TEST(CustomSnapshotDataBlobDataView) {
    1116             :   const char* code =
    1117             :       "var x = new Int8Array([1, 2, 3, 4]);"
    1118             :       "var v = new DataView(x.buffer)";
    1119             :   Int32Expectations expectations = {std::make_tuple("v.getInt8(0)", 1),
    1120             :                                     std::make_tuple("v.getInt8(1)", 2),
    1121             :                                     std::make_tuple("v.getInt16(0)", 258),
    1122             :                                     std::make_tuple("v.getInt16(1)", 515)};
    1123             : 
    1124          10 :   TypedArrayTestHelper(code, expectations);
    1125           5 : }
    1126             : 
    1127       26644 : UNINITIALIZED_TEST(CustomSnapshotDataBlobDetachedArrayBuffer) {
    1128             :   const char* code =
    1129             :       "var x = new Int16Array([12, 24, 48]);"
    1130             :       "%ArrayBufferDetach(x.buffer);";
    1131             :   Int32Expectations expectations = {std::make_tuple("x.buffer.byteLength", 0),
    1132             :                                     std::make_tuple("x.length", 0)};
    1133             : 
    1134             :   DisableAlwaysOpt();
    1135           5 :   i::FLAG_allow_natives_syntax = true;
    1136           5 :   DisableEmbeddedBlobRefcounting();
    1137             :   v8::StartupData blob;
    1138             :   {
    1139          10 :     v8::SnapshotCreator creator;
    1140           5 :     v8::Isolate* isolate = creator.GetIsolate();
    1141             :     {
    1142          10 :       v8::HandleScope handle_scope(isolate);
    1143           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    1144             :       v8::Context::Scope context_scope(context);
    1145             : 
    1146             :       CompileRun(code);
    1147             :       TestInt32Expectations(expectations);
    1148           5 :       creator.SetDefaultContext(
    1149             :           context, v8::SerializeInternalFieldsCallback(
    1150           5 :                        SerializeInternalFields, reinterpret_cast<void*>(2016)));
    1151             :     }
    1152             :     blob =
    1153           5 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    1154             :   }
    1155             : 
    1156             :   v8::Isolate::CreateParams create_params;
    1157           5 :   create_params.snapshot_blob = &blob;
    1158           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    1159           5 :   v8::Isolate* isolate = TestSerializer::NewIsolate(create_params);
    1160             :   {
    1161             :     v8::Isolate::Scope i_scope(isolate);
    1162          10 :     v8::HandleScope h_scope(isolate);
    1163             :     v8::Local<v8::Context> context = v8::Context::New(
    1164             :         isolate, nullptr, v8::MaybeLocal<v8::ObjectTemplate>(),
    1165             :         v8::MaybeLocal<v8::Value>(),
    1166             :         v8::DeserializeInternalFieldsCallback(DeserializeInternalFields,
    1167           5 :                                               reinterpret_cast<void*>(2017)));
    1168             :     v8::Context::Scope c_scope(context);
    1169             :     TestInt32Expectations(expectations);
    1170             : 
    1171             :     v8::Local<v8::Value> x = CompileRun("x");
    1172           5 :     CHECK(x->IsTypedArray());
    1173             :     i::Handle<i::JSTypedArray> array =
    1174             :         i::Handle<i::JSTypedArray>::cast(v8::Utils::OpenHandle(*x));
    1175           5 :     CHECK(array->WasDetached());
    1176           5 :     CHECK_NULL(
    1177             :         FixedTypedArrayBase::cast(array->elements())->external_pointer());
    1178             :   }
    1179           5 :   isolate->Dispose();
    1180           5 :   delete[] blob.data;  // We can dispose of the snapshot blob now.
    1181           5 :   FreeCurrentEmbeddedBlob();
    1182           5 : }
    1183             : 
    1184          15 : i::Handle<i::JSArrayBuffer> GetBufferFromTypedArray(
    1185             :     v8::Local<v8::Value> typed_array) {
    1186          15 :   CHECK(typed_array->IsTypedArray());
    1187             : 
    1188             :   i::Handle<i::JSArrayBufferView> view = i::Handle<i::JSArrayBufferView>::cast(
    1189             :       v8::Utils::OpenHandle(*typed_array));
    1190             : 
    1191          15 :   return i::handle(i::JSArrayBuffer::cast(view->buffer()), view->GetIsolate());
    1192             : }
    1193             : 
    1194       26644 : UNINITIALIZED_TEST(CustomSnapshotDataBlobOnOrOffHeapTypedArray) {
    1195             :   const char* code =
    1196             :       "var x = new Uint8Array(8);"
    1197             :       "x[0] = 12;"
    1198             :       "x[7] = 24;"
    1199             :       "var y = new Int16Array([12, 24, 48]);"
    1200             :       "var z = new Int32Array(64);"
    1201             :       "z[0] = 96;";
    1202             :   Int32Expectations expectations = {
    1203             :       std::make_tuple("x[0]", 12), std::make_tuple("x[7]", 24),
    1204             :       std::make_tuple("y[2]", 48), std::make_tuple("z[0]", 96)};
    1205             : 
    1206             :   DisableAlwaysOpt();
    1207           5 :   i::FLAG_allow_natives_syntax = true;
    1208           5 :   DisableEmbeddedBlobRefcounting();
    1209             :   v8::StartupData blob;
    1210             :   {
    1211          10 :     v8::SnapshotCreator creator;
    1212           5 :     v8::Isolate* isolate = creator.GetIsolate();
    1213             :     {
    1214          10 :       v8::HandleScope handle_scope(isolate);
    1215           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    1216             :       v8::Context::Scope context_scope(context);
    1217             : 
    1218             :       CompileRun(code);
    1219             :       TestInt32Expectations(expectations);
    1220           5 :       creator.SetDefaultContext(
    1221             :           context, v8::SerializeInternalFieldsCallback(
    1222           5 :                        SerializeInternalFields, reinterpret_cast<void*>(2016)));
    1223             :     }
    1224             :     blob =
    1225           5 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    1226             :   }
    1227             : 
    1228             :   v8::Isolate::CreateParams create_params;
    1229           5 :   create_params.snapshot_blob = &blob;
    1230           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    1231           5 :   v8::Isolate* isolate = TestSerializer::NewIsolate(create_params);
    1232             :   {
    1233             :     v8::Isolate::Scope i_scope(isolate);
    1234          10 :     v8::HandleScope h_scope(isolate);
    1235             :     v8::Local<v8::Context> context = v8::Context::New(
    1236             :         isolate, nullptr, v8::MaybeLocal<v8::ObjectTemplate>(),
    1237             :         v8::MaybeLocal<v8::Value>(),
    1238             :         v8::DeserializeInternalFieldsCallback(DeserializeInternalFields,
    1239           5 :                                               reinterpret_cast<void*>(2017)));
    1240             :     v8::Context::Scope c_scope(context);
    1241             :     TestInt32Expectations(expectations);
    1242             : 
    1243             :     i::Handle<i::JSArrayBuffer> buffer =
    1244           5 :         GetBufferFromTypedArray(CompileRun("x"));
    1245             :     // The resulting buffer should be on-heap.
    1246           5 :     CHECK_NULL(buffer->backing_store());
    1247             : 
    1248           5 :     buffer = GetBufferFromTypedArray(CompileRun("y"));
    1249           5 :     CHECK_NULL(buffer->backing_store());
    1250             : 
    1251           5 :     buffer = GetBufferFromTypedArray(CompileRun("z"));
    1252             :     // The resulting buffer should be off-heap.
    1253           5 :     CHECK_NOT_NULL(buffer->backing_store());
    1254             :   }
    1255           5 :   isolate->Dispose();
    1256           5 :   delete[] blob.data;  // We can dispose of the snapshot blob now.
    1257           5 :   FreeCurrentEmbeddedBlob();
    1258           5 : }
    1259             : 
    1260       26644 : UNINITIALIZED_TEST(CustomSnapshotDataBlobTypedArrayNoEmbedderFieldCallback) {
    1261             :   const char* code = "var x = new Uint8Array(8);";
    1262             :   DisableAlwaysOpt();
    1263           5 :   i::FLAG_allow_natives_syntax = true;
    1264           5 :   DisableEmbeddedBlobRefcounting();
    1265             :   v8::StartupData blob;
    1266             :   {
    1267          10 :     v8::SnapshotCreator creator;
    1268           5 :     v8::Isolate* isolate = creator.GetIsolate();
    1269             :     {
    1270          10 :       v8::HandleScope handle_scope(isolate);
    1271           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    1272             :       v8::Context::Scope context_scope(context);
    1273             : 
    1274             :       CompileRun(code);
    1275           5 :       creator.SetDefaultContext(context, v8::SerializeInternalFieldsCallback());
    1276             :     }
    1277             :     blob =
    1278           5 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    1279             :   }
    1280             : 
    1281             :   v8::Isolate::CreateParams create_params;
    1282           5 :   create_params.snapshot_blob = &blob;
    1283           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    1284           5 :   v8::Isolate* isolate = TestSerializer::NewIsolate(create_params);
    1285             :   {
    1286             :     v8::Isolate::Scope i_scope(isolate);
    1287          10 :     v8::HandleScope h_scope(isolate);
    1288             :     v8::Local<v8::Context> context = v8::Context::New(
    1289             :         isolate, nullptr, v8::MaybeLocal<v8::ObjectTemplate>(),
    1290           5 :         v8::MaybeLocal<v8::Value>(), v8::DeserializeInternalFieldsCallback());
    1291             :     v8::Context::Scope c_scope(context);
    1292             :   }
    1293           5 :   isolate->Dispose();
    1294           5 :   delete[] blob.data;  // We can dispose of the snapshot blob now.
    1295           5 :   FreeCurrentEmbeddedBlob();
    1296           5 : }
    1297             : 
    1298       26644 : UNINITIALIZED_TEST(CustomSnapshotDataBlob2) {
    1299             :   DisableAlwaysOpt();
    1300             :   const char* source2 =
    1301             :       "function f() { return g() * 2; }"
    1302             :       "function g() { return 43; }"
    1303             :       "/./.test('a')";
    1304             : 
    1305           5 :   v8::StartupData data2 = CreateSnapshotDataBlob(source2);
    1306             : 
    1307             :   v8::Isolate::CreateParams params2;
    1308           5 :   params2.snapshot_blob = &data2;
    1309           5 :   params2.array_buffer_allocator = CcTest::array_buffer_allocator();
    1310             :   // Test-appropriate equivalent of v8::Isolate::New.
    1311           5 :   v8::Isolate* isolate2 = TestSerializer::NewIsolate(params2);
    1312             :   {
    1313             :     v8::Isolate::Scope i_scope(isolate2);
    1314          10 :     v8::HandleScope h_scope(isolate2);
    1315           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate2);
    1316             :     v8::Context::Scope c_scope(context);
    1317             :     v8::Maybe<int32_t> result =
    1318          10 :         CompileRun("f()")->Int32Value(isolate2->GetCurrentContext());
    1319           5 :     CHECK_EQ(86, result.FromJust());
    1320          10 :     result = CompileRun("g()")->Int32Value(isolate2->GetCurrentContext());
    1321           5 :     CHECK_EQ(43, result.FromJust());
    1322             :   }
    1323           5 :   isolate2->Dispose();
    1324           5 :   delete[] data2.data;  // We can dispose of the snapshot blob now.
    1325           5 :   FreeCurrentEmbeddedBlob();
    1326           5 : }
    1327             : 
    1328           5 : static void SerializationFunctionTemplate(
    1329             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    1330             :   args.GetReturnValue().Set(args[0]);
    1331           5 : }
    1332             : 
    1333       26644 : UNINITIALIZED_TEST(CustomSnapshotDataBlobOutdatedContextWithOverflow) {
    1334             :   DisableAlwaysOpt();
    1335             :   const char* source1 =
    1336             :       "var o = {};"
    1337             :       "(function() {"
    1338             :       "  function f1(x) { return f2(x) instanceof Array; }"
    1339             :       "  function f2(x) { return foo.bar(x); }"
    1340             :       "  o.a = f2.bind(null);"
    1341             :       "  o.b = 1;"
    1342             :       "  o.c = 2;"
    1343             :       "  o.d = 3;"
    1344             :       "  o.e = 4;"
    1345             :       "})();\n";
    1346             : 
    1347             :   const char* source2 = "o.a(42)";
    1348             : 
    1349           5 :   v8::StartupData data = CreateSnapshotDataBlob(source1);
    1350             : 
    1351             :   v8::Isolate::CreateParams params;
    1352           5 :   params.snapshot_blob = &data;
    1353           5 :   params.array_buffer_allocator = CcTest::array_buffer_allocator();
    1354             : 
    1355             :   // Test-appropriate equivalent of v8::Isolate::New.
    1356           5 :   v8::Isolate* isolate = TestSerializer::NewIsolate(params);
    1357             :   {
    1358             :     v8::Isolate::Scope i_scope(isolate);
    1359          10 :     v8::HandleScope h_scope(isolate);
    1360             : 
    1361           5 :     v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);
    1362           5 :     v8::Local<v8::ObjectTemplate> property = v8::ObjectTemplate::New(isolate);
    1363             :     v8::Local<v8::FunctionTemplate> function =
    1364           5 :         v8::FunctionTemplate::New(isolate, SerializationFunctionTemplate);
    1365             :     property->Set(isolate, "bar", function);
    1366             :     global->Set(isolate, "foo", property);
    1367             : 
    1368           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate, nullptr, global);
    1369             :     v8::Context::Scope c_scope(context);
    1370           5 :     v8::Local<v8::Value> result = CompileRun(source2);
    1371          10 :     v8::Maybe<bool> compare = v8_str("42")->Equals(
    1372          10 :         v8::Isolate::GetCurrent()->GetCurrentContext(), result);
    1373           5 :     CHECK(compare.FromJust());
    1374             :   }
    1375           5 :   isolate->Dispose();
    1376           5 :   delete[] data.data;  // We can dispose of the snapshot blob now.
    1377           5 :   FreeCurrentEmbeddedBlob();
    1378           5 : }
    1379             : 
    1380       26644 : UNINITIALIZED_TEST(CustomSnapshotDataBlobWithLocker) {
    1381             :   DisableAlwaysOpt();
    1382           5 :   DisableEmbeddedBlobRefcounting();
    1383             :   v8::Isolate::CreateParams create_params;
    1384           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    1385           5 :   v8::Isolate* isolate0 = v8::Isolate::New(create_params);
    1386             :   {
    1387           5 :     v8::Locker locker(isolate0);
    1388             :     v8::Isolate::Scope i_scope(isolate0);
    1389          10 :     v8::HandleScope h_scope(isolate0);
    1390           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate0);
    1391             :     v8::Context::Scope c_scope(context);
    1392             :     v8::Maybe<int32_t> result =
    1393          10 :         CompileRun("Math.cos(0)")->Int32Value(isolate0->GetCurrentContext());
    1394           5 :     CHECK_EQ(1, result.FromJust());
    1395             :   }
    1396           5 :   isolate0->Dispose();
    1397             : 
    1398             :   const char* source1 = "function f() { return 42; }";
    1399             : 
    1400           5 :   v8::StartupData data1 = CreateSnapshotDataBlob(source1);
    1401             : 
    1402             :   v8::Isolate::CreateParams params1;
    1403           5 :   params1.snapshot_blob = &data1;
    1404           5 :   params1.array_buffer_allocator = CcTest::array_buffer_allocator();
    1405             :   // Test-appropriate equivalent of v8::Isolate::New.
    1406           5 :   v8::Isolate* isolate1 = TestSerializer::NewIsolate(params1);
    1407             :   {
    1408           5 :     v8::Locker locker(isolate1);
    1409             :     v8::Isolate::Scope i_scope(isolate1);
    1410          10 :     v8::HandleScope h_scope(isolate1);
    1411           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate1);
    1412             :     v8::Context::Scope c_scope(context);
    1413           5 :     v8::Maybe<int32_t> result = CompileRun("f()")->Int32Value(context);
    1414           5 :     CHECK_EQ(42, result.FromJust());
    1415             :   }
    1416           5 :   isolate1->Dispose();
    1417           5 :   delete[] data1.data;  // We can dispose of the snapshot blob now.
    1418           5 :   FreeCurrentEmbeddedBlob();
    1419           5 : }
    1420             : 
    1421       26644 : UNINITIALIZED_TEST(CustomSnapshotDataBlobStackOverflow) {
    1422             :   DisableAlwaysOpt();
    1423             :   const char* source =
    1424             :       "var a = [0];"
    1425             :       "var b = a;"
    1426             :       "for (var i = 0; i < 10000; i++) {"
    1427             :       "  var c = [i];"
    1428             :       "  b.push(c);"
    1429             :       "  b.push(c);"
    1430             :       "  b = c;"
    1431             :       "}";
    1432             : 
    1433           5 :   v8::StartupData data = CreateSnapshotDataBlob(source);
    1434             : 
    1435             :   v8::Isolate::CreateParams params;
    1436           5 :   params.snapshot_blob = &data;
    1437           5 :   params.array_buffer_allocator = CcTest::array_buffer_allocator();
    1438             : 
    1439             :   // Test-appropriate equivalent of v8::Isolate::New.
    1440           5 :   v8::Isolate* isolate = TestSerializer::NewIsolate(params);
    1441             :   {
    1442             :     v8::Isolate::Scope i_scope(isolate);
    1443          10 :     v8::HandleScope h_scope(isolate);
    1444           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate);
    1445             :     v8::Context::Scope c_scope(context);
    1446             :     const char* test =
    1447             :         "var sum = 0;"
    1448             :         "while (a) {"
    1449             :         "  sum += a[0];"
    1450             :         "  a = a[1];"
    1451             :         "}"
    1452             :         "sum";
    1453             :     v8::Maybe<int32_t> result =
    1454          10 :         CompileRun(test)->Int32Value(isolate->GetCurrentContext());
    1455           5 :     CHECK_EQ(9999 * 5000, result.FromJust());
    1456             :   }
    1457           5 :   isolate->Dispose();
    1458           5 :   delete[] data.data;  // We can dispose of the snapshot blob now.
    1459           5 :   FreeCurrentEmbeddedBlob();
    1460           5 : }
    1461             : 
    1462          35 : bool IsCompiled(const char* name) {
    1463             :   return i::Handle<i::JSFunction>::cast(
    1464             :              v8::Utils::OpenHandle(*CompileRun(name)))
    1465          70 :       ->shared()
    1466          70 :       ->is_compiled();
    1467             : }
    1468             : 
    1469       26644 : UNINITIALIZED_TEST(SnapshotDataBlobWithWarmup) {
    1470             :   DisableAlwaysOpt();
    1471             :   const char* warmup = "Math.abs(1); Math.random = 1;";
    1472             : 
    1473           5 :   v8::StartupData cold = CreateSnapshotDataBlob();
    1474           5 :   v8::StartupData warm = WarmUpSnapshotDataBlob(cold, warmup);
    1475           5 :   delete[] cold.data;
    1476             : 
    1477             :   v8::Isolate::CreateParams params;
    1478           5 :   params.snapshot_blob = &warm;
    1479           5 :   params.array_buffer_allocator = CcTest::array_buffer_allocator();
    1480             : 
    1481             :   // Test-appropriate equivalent of v8::Isolate::New.
    1482           5 :   v8::Isolate* isolate = TestSerializer::NewIsolate(params);
    1483             :   {
    1484             :     v8::Isolate::Scope i_scope(isolate);
    1485          10 :     v8::HandleScope h_scope(isolate);
    1486           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate);
    1487             :     v8::Context::Scope c_scope(context);
    1488             :     // Running the warmup script has effect on whether functions are
    1489             :     // pre-compiled, but does not pollute the context.
    1490           5 :     CHECK(IsCompiled("Math.abs"));
    1491           5 :     CHECK(IsCompiled("String.raw"));
    1492           5 :     CHECK(CompileRun("Math.random")->IsFunction());
    1493             :   }
    1494           5 :   isolate->Dispose();
    1495           5 :   delete[] warm.data;
    1496           5 :   FreeCurrentEmbeddedBlob();
    1497           5 : }
    1498             : 
    1499       26644 : UNINITIALIZED_TEST(CustomSnapshotDataBlobWithWarmup) {
    1500             :   DisableAlwaysOpt();
    1501             :   const char* source =
    1502             :       "function f() { return Math.abs(1); }\n"
    1503             :       "function g() { return String.raw(1); }\n"
    1504             :       "Object.valueOf(1);"
    1505             :       "var a = 5";
    1506             :   const char* warmup = "a = f()";
    1507             : 
    1508           5 :   v8::StartupData cold = CreateSnapshotDataBlob(source);
    1509           5 :   v8::StartupData warm = WarmUpSnapshotDataBlob(cold, warmup);
    1510           5 :   delete[] cold.data;
    1511             : 
    1512             :   v8::Isolate::CreateParams params;
    1513           5 :   params.snapshot_blob = &warm;
    1514           5 :   params.array_buffer_allocator = CcTest::array_buffer_allocator();
    1515             : 
    1516             :   // Test-appropriate equivalent of v8::Isolate::New.
    1517           5 :   v8::Isolate* isolate = TestSerializer::NewIsolate(params);
    1518             :   {
    1519             :     v8::Isolate::Scope i_scope(isolate);
    1520          10 :     v8::HandleScope h_scope(isolate);
    1521           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate);
    1522             :     v8::Context::Scope c_scope(context);
    1523             :     // Running the warmup script has effect on whether functions are
    1524             :     // pre-compiled, but does not pollute the context.
    1525           5 :     CHECK(IsCompiled("f"));
    1526           5 :     CHECK(IsCompiled("Math.abs"));
    1527           5 :     CHECK(!IsCompiled("g"));
    1528           5 :     CHECK(IsCompiled("String.raw"));
    1529           5 :     CHECK(IsCompiled("Array.prototype.lastIndexOf"));
    1530          10 :     CHECK_EQ(5, CompileRun("a")->Int32Value(context).FromJust());
    1531             :   }
    1532           5 :   isolate->Dispose();
    1533           5 :   delete[] warm.data;
    1534           5 :   FreeCurrentEmbeddedBlob();
    1535           5 : }
    1536             : 
    1537       26644 : UNINITIALIZED_TEST(CustomSnapshotDataBlobImmortalImmovableRoots) {
    1538             :   DisableAlwaysOpt();
    1539             :   // Flood the startup snapshot with shared function infos. If they are
    1540             :   // serialized before the immortal immovable root, the root will no longer end
    1541             :   // up on the first page.
    1542             :   Vector<const uint8_t> source =
    1543             :       ConstructSource(StaticCharVector("var a = [];"),
    1544             :                       StaticCharVector("a.push(function() {return 7});"),
    1545           5 :                       StaticCharVector("\0"), 10000);
    1546             : 
    1547             :   v8::StartupData data =
    1548           5 :       CreateSnapshotDataBlob(reinterpret_cast<const char*>(source.start()));
    1549             : 
    1550             :   v8::Isolate::CreateParams params;
    1551           5 :   params.snapshot_blob = &data;
    1552           5 :   params.array_buffer_allocator = CcTest::array_buffer_allocator();
    1553             : 
    1554             :   // Test-appropriate equivalent of v8::Isolate::New.
    1555           5 :   v8::Isolate* isolate = TestSerializer::NewIsolate(params);
    1556             :   {
    1557             :     v8::Isolate::Scope i_scope(isolate);
    1558          10 :     v8::HandleScope h_scope(isolate);
    1559           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate);
    1560             :     v8::Context::Scope c_scope(context);
    1561          10 :     CHECK_EQ(7, CompileRun("a[0]()")->Int32Value(context).FromJust());
    1562             :   }
    1563           5 :   isolate->Dispose();
    1564             :   source.Dispose();
    1565           5 :   delete[] data.data;  // We can dispose of the snapshot blob now.
    1566           5 :   FreeCurrentEmbeddedBlob();
    1567           5 : }
    1568             : 
    1569       26644 : TEST(TestThatAlwaysSucceeds) {
    1570           5 : }
    1571             : 
    1572             : 
    1573       26639 : TEST(TestThatAlwaysFails) {
    1574             :   bool ArtificialFailure = false;
    1575           0 :   CHECK(ArtificialFailure);
    1576             : }
    1577             : 
    1578             : 
    1579          60 : int CountBuiltins() {
    1580             :   // Check that we have not deserialized any additional builtin.
    1581         120 :   HeapIterator iterator(CcTest::heap());
    1582             :   DisallowHeapAllocation no_allocation;
    1583             :   int counter = 0;
    1584      847286 :   for (HeapObject obj = iterator.next(); !obj.is_null();
    1585             :        obj = iterator.next()) {
    1586      515052 :     if (obj->IsCode() && Code::cast(obj)->kind() == Code::BUILTIN) counter++;
    1587             :   }
    1588          60 :   return counter;
    1589             : }
    1590             : 
    1591          75 : static Handle<SharedFunctionInfo> CompileScript(
    1592             :     Isolate* isolate, Handle<String> source, Handle<String> name,
    1593             :     ScriptData* cached_data, v8::ScriptCompiler::CompileOptions options) {
    1594         150 :   return Compiler::GetSharedFunctionInfoForScript(
    1595             :              isolate, source, Compiler::ScriptDetails(name),
    1596             :              v8::ScriptOriginOptions(), nullptr, cached_data, options,
    1597          75 :              ScriptCompiler::kNoCacheNoReason, NOT_NATIVES_CODE)
    1598          75 :       .ToHandleChecked();
    1599             : }
    1600             : 
    1601          80 : static Handle<SharedFunctionInfo> CompileScriptAndProduceCache(
    1602             :     Isolate* isolate, Handle<String> source, Handle<String> name,
    1603             :     ScriptData** script_data, v8::ScriptCompiler::CompileOptions options) {
    1604             :   Handle<SharedFunctionInfo> sfi =
    1605         160 :       Compiler::GetSharedFunctionInfoForScript(
    1606             :           isolate, source, Compiler::ScriptDetails(name),
    1607             :           v8::ScriptOriginOptions(), nullptr, nullptr, options,
    1608          80 :           ScriptCompiler::kNoCacheNoReason, NOT_NATIVES_CODE)
    1609             :           .ToHandleChecked();
    1610             :   std::unique_ptr<ScriptCompiler::CachedData> cached_data(
    1611         160 :       ScriptCompiler::CreateCodeCache(ToApiHandle<UnboundScript>(sfi)));
    1612          80 :   uint8_t* buffer = NewArray<uint8_t>(cached_data->length);
    1613          80 :   MemCopy(buffer, cached_data->data, cached_data->length);
    1614          80 :   *script_data = new i::ScriptData(buffer, cached_data->length);
    1615             :   (*script_data)->AcquireDataOwnership();
    1616         160 :   return sfi;
    1617             : }
    1618             : 
    1619          25 : void TestCodeSerializerOnePlusOneImpl() {
    1620          25 :   LocalContext context;
    1621             :   Isolate* isolate = CcTest::i_isolate();
    1622          25 :   isolate->compilation_cache()->Disable();  // Disable same-isolate code cache.
    1623             : 
    1624          50 :   v8::HandleScope scope(CcTest::isolate());
    1625             : 
    1626             :   const char* source = "1 + 1";
    1627             : 
    1628             :   Handle<String> orig_source = isolate->factory()
    1629          50 :                                    ->NewStringFromUtf8(CStrVector(source))
    1630             :                                    .ToHandleChecked();
    1631             :   Handle<String> copy_source = isolate->factory()
    1632          50 :                                    ->NewStringFromUtf8(CStrVector(source))
    1633             :                                    .ToHandleChecked();
    1634          25 :   CHECK(!orig_source.is_identical_to(copy_source));
    1635          25 :   CHECK(orig_source->Equals(*copy_source));
    1636             : 
    1637          25 :   ScriptData* cache = nullptr;
    1638             : 
    1639             :   Handle<SharedFunctionInfo> orig = CompileScriptAndProduceCache(
    1640             :       isolate, orig_source, Handle<String>(), &cache,
    1641          25 :       v8::ScriptCompiler::kNoCompileOptions);
    1642             : 
    1643          25 :   int builtins_count = CountBuiltins();
    1644             : 
    1645             :   Handle<SharedFunctionInfo> copy;
    1646             :   {
    1647             :     DisallowCompilation no_compile_expected(isolate);
    1648             :     copy = CompileScript(isolate, copy_source, Handle<String>(), cache,
    1649          50 :                          v8::ScriptCompiler::kConsumeCodeCache);
    1650             :   }
    1651             : 
    1652          25 :   CHECK_NE(*orig, *copy);
    1653          50 :   CHECK(Script::cast(copy->script())->source() == *copy_source);
    1654             : 
    1655             :   Handle<JSFunction> copy_fun =
    1656             :       isolate->factory()->NewFunctionFromSharedFunctionInfo(
    1657          50 :           copy, isolate->native_context());
    1658          50 :   Handle<JSObject> global(isolate->context()->global_object(), isolate);
    1659             :   Handle<Object> copy_result =
    1660          50 :       Execution::Call(isolate, copy_fun, global, 0, nullptr).ToHandleChecked();
    1661          25 :   CHECK_EQ(2, Handle<Smi>::cast(copy_result)->value());
    1662             : 
    1663          25 :   CHECK_EQ(builtins_count, CountBuiltins());
    1664             : 
    1665          50 :   delete cache;
    1666          25 : }
    1667             : 
    1668       26644 : TEST(CodeSerializerOnePlusOne) { TestCodeSerializerOnePlusOneImpl(); }
    1669             : 
    1670       26644 : TEST(CodeSerializerOnePlusOneWithDebugger) {
    1671          10 :   v8::HandleScope scope(CcTest::isolate());
    1672           5 :   static v8::debug::DebugDelegate dummy_delegate;
    1673           5 :   v8::debug::SetDebugDelegate(CcTest::isolate(), &dummy_delegate);
    1674           5 :   TestCodeSerializerOnePlusOneImpl();
    1675           5 : }
    1676             : 
    1677       26644 : TEST(CodeSerializerOnePlusOne1) {
    1678           5 :   FLAG_serialization_chunk_size = 1;
    1679           5 :   TestCodeSerializerOnePlusOneImpl();
    1680           5 : }
    1681             : 
    1682       26644 : TEST(CodeSerializerOnePlusOne32) {
    1683           5 :   FLAG_serialization_chunk_size = 32;
    1684           5 :   TestCodeSerializerOnePlusOneImpl();
    1685           5 : }
    1686             : 
    1687       26644 : TEST(CodeSerializerOnePlusOne4K) {
    1688           5 :   FLAG_serialization_chunk_size = 4 * KB;
    1689           5 :   TestCodeSerializerOnePlusOneImpl();
    1690           5 : }
    1691             : 
    1692       26644 : TEST(CodeSerializerPromotedToCompilationCache) {
    1693           5 :   LocalContext context;
    1694             :   Isolate* isolate = CcTest::i_isolate();
    1695             : 
    1696          10 :   v8::HandleScope scope(CcTest::isolate());
    1697             : 
    1698             :   const char* source = "1 + 1";
    1699             : 
    1700             :   Handle<String> src = isolate->factory()
    1701          10 :                            ->NewStringFromUtf8(CStrVector(source))
    1702             :                            .ToHandleChecked();
    1703           5 :   ScriptData* cache = nullptr;
    1704             : 
    1705             :   CompileScriptAndProduceCache(isolate, src, src, &cache,
    1706           5 :                                v8::ScriptCompiler::kNoCompileOptions);
    1707             : 
    1708             :   DisallowCompilation no_compile_expected(isolate);
    1709             :   Handle<SharedFunctionInfo> copy = CompileScript(
    1710           5 :       isolate, src, src, cache, v8::ScriptCompiler::kConsumeCodeCache);
    1711             : 
    1712             :   MaybeHandle<SharedFunctionInfo> shared =
    1713             :       isolate->compilation_cache()->LookupScript(
    1714             :           src, src, 0, 0, v8::ScriptOriginOptions(), isolate->native_context(),
    1715          10 :           LanguageMode::kSloppy);
    1716             : 
    1717           5 :   CHECK(*shared.ToHandleChecked() == *copy);
    1718             : 
    1719          10 :   delete cache;
    1720           5 : }
    1721             : 
    1722       26644 : TEST(CodeSerializerInternalizedString) {
    1723           5 :   LocalContext context;
    1724             :   Isolate* isolate = CcTest::i_isolate();
    1725           5 :   isolate->compilation_cache()->Disable();  // Disable same-isolate code cache.
    1726             : 
    1727          10 :   v8::HandleScope scope(CcTest::isolate());
    1728             : 
    1729             :   const char* source = "'string1'";
    1730             : 
    1731             :   Handle<String> orig_source = isolate->factory()
    1732          10 :                                    ->NewStringFromUtf8(CStrVector(source))
    1733             :                                    .ToHandleChecked();
    1734             :   Handle<String> copy_source = isolate->factory()
    1735          10 :                                    ->NewStringFromUtf8(CStrVector(source))
    1736             :                                    .ToHandleChecked();
    1737           5 :   CHECK(!orig_source.is_identical_to(copy_source));
    1738           5 :   CHECK(orig_source->Equals(*copy_source));
    1739             : 
    1740          10 :   Handle<JSObject> global(isolate->context()->global_object(), isolate);
    1741             : 
    1742           5 :   i::ScriptData* script_data = nullptr;
    1743             :   Handle<SharedFunctionInfo> orig = CompileScriptAndProduceCache(
    1744             :       isolate, orig_source, Handle<String>(), &script_data,
    1745           5 :       v8::ScriptCompiler::kNoCompileOptions);
    1746             :   Handle<JSFunction> orig_fun =
    1747             :       isolate->factory()->NewFunctionFromSharedFunctionInfo(
    1748          10 :           orig, isolate->native_context());
    1749             :   Handle<Object> orig_result =
    1750          10 :       Execution::Call(isolate, orig_fun, global, 0, nullptr).ToHandleChecked();
    1751           5 :   CHECK(orig_result->IsInternalizedString());
    1752             : 
    1753           5 :   int builtins_count = CountBuiltins();
    1754             : 
    1755             :   Handle<SharedFunctionInfo> copy;
    1756             :   {
    1757             :     DisallowCompilation no_compile_expected(isolate);
    1758             :     copy = CompileScript(isolate, copy_source, Handle<String>(), script_data,
    1759          10 :                          v8::ScriptCompiler::kConsumeCodeCache);
    1760             :   }
    1761           5 :   CHECK_NE(*orig, *copy);
    1762          10 :   CHECK(Script::cast(copy->script())->source() == *copy_source);
    1763             : 
    1764             :   Handle<JSFunction> copy_fun =
    1765             :       isolate->factory()->NewFunctionFromSharedFunctionInfo(
    1766          10 :           copy, isolate->native_context());
    1767           5 :   CHECK_NE(*orig_fun, *copy_fun);
    1768             :   Handle<Object> copy_result =
    1769          10 :       Execution::Call(isolate, copy_fun, global, 0, nullptr).ToHandleChecked();
    1770           5 :   CHECK(orig_result.is_identical_to(copy_result));
    1771             :   Handle<String> expected =
    1772           5 :       isolate->factory()->NewStringFromAsciiChecked("string1");
    1773             : 
    1774           5 :   CHECK(Handle<String>::cast(copy_result)->Equals(*expected));
    1775           5 :   CHECK_EQ(builtins_count, CountBuiltins());
    1776             : 
    1777          10 :   delete script_data;
    1778           5 : }
    1779             : 
    1780       26644 : TEST(CodeSerializerLargeCodeObject) {
    1781           5 :   LocalContext context;
    1782             :   Isolate* isolate = CcTest::i_isolate();
    1783           5 :   isolate->compilation_cache()->Disable();  // Disable same-isolate code cache.
    1784             : 
    1785          10 :   v8::HandleScope scope(CcTest::isolate());
    1786             : 
    1787             :   // The serializer only tests the shared code, which is always the unoptimized
    1788             :   // code. Don't even bother generating optimized code to avoid timeouts.
    1789           5 :   FLAG_always_opt = false;
    1790             : 
    1791             :   Vector<const uint8_t> source = ConstructSource(
    1792             :       StaticCharVector("var j=1; if (j == 0) {"),
    1793             :       StaticCharVector(
    1794             :           "for (let i of Object.prototype) for (let k = 0; k < 0; ++k);"),
    1795           5 :       StaticCharVector("} j=7; j"), 2000);
    1796             :   Handle<String> source_str =
    1797          10 :       isolate->factory()->NewStringFromOneByte(source).ToHandleChecked();
    1798             : 
    1799          10 :   Handle<JSObject> global(isolate->context()->global_object(), isolate);
    1800           5 :   ScriptData* cache = nullptr;
    1801             : 
    1802             :   Handle<SharedFunctionInfo> orig = CompileScriptAndProduceCache(
    1803             :       isolate, source_str, Handle<String>(), &cache,
    1804           5 :       v8::ScriptCompiler::kNoCompileOptions);
    1805             : 
    1806          10 :   CHECK(isolate->heap()->InSpace(orig->abstract_code(), LO_SPACE));
    1807             : 
    1808             :   Handle<SharedFunctionInfo> copy;
    1809             :   {
    1810             :     DisallowCompilation no_compile_expected(isolate);
    1811             :     copy = CompileScript(isolate, source_str, Handle<String>(), cache,
    1812          10 :                          v8::ScriptCompiler::kConsumeCodeCache);
    1813             :   }
    1814           5 :   CHECK_NE(*orig, *copy);
    1815             : 
    1816             :   Handle<JSFunction> copy_fun =
    1817             :       isolate->factory()->NewFunctionFromSharedFunctionInfo(
    1818          10 :           copy, isolate->native_context());
    1819             : 
    1820             :   Handle<Object> copy_result =
    1821          10 :       Execution::Call(isolate, copy_fun, global, 0, nullptr).ToHandleChecked();
    1822             : 
    1823             :   int result_int;
    1824           5 :   CHECK(copy_result->ToInt32(&result_int));
    1825           5 :   CHECK_EQ(7, result_int);
    1826             : 
    1827          10 :   delete cache;
    1828             :   source.Dispose();
    1829           5 : }
    1830             : 
    1831       26644 : TEST(CodeSerializerLargeCodeObjectWithIncrementalMarking) {
    1832           5 :   if (FLAG_never_compact) return;
    1833             :   ManualGCScope manual_gc_scope;
    1834           5 :   FLAG_always_opt = false;
    1835             :   const char* filter_flag = "--turbo-filter=NOTHING";
    1836           5 :   FlagList::SetFlagsFromString(filter_flag, StrLength(filter_flag));
    1837           5 :   FLAG_manual_evacuation_candidates_selection = true;
    1838             : 
    1839           5 :   LocalContext context;
    1840             :   Isolate* isolate = CcTest::i_isolate();
    1841             :   Heap* heap = isolate->heap();
    1842           5 :   isolate->compilation_cache()->Disable();  // Disable same-isolate code cache.
    1843             : 
    1844          10 :   v8::HandleScope scope(CcTest::isolate());
    1845             : 
    1846             :   Vector<const uint8_t> source = ConstructSource(
    1847             :       StaticCharVector("var j=1; if (j == 0) {"),
    1848             :       StaticCharVector("for (var i = 0; i < Object.prototype; i++);"),
    1849           5 :       StaticCharVector("} j=7; var s = 'happy_hippo'; j"), 20000);
    1850             :   Handle<String> source_str =
    1851          10 :       isolate->factory()->NewStringFromOneByte(source).ToHandleChecked();
    1852             : 
    1853             :   // Create a string on an evacuation candidate in old space.
    1854             :   Handle<String> moving_object;
    1855             :   Page* ec_page;
    1856             :   {
    1857             :     AlwaysAllocateScope always_allocate(isolate);
    1858           5 :     heap::SimulateFullSpace(heap->old_space());
    1859             :     moving_object = isolate->factory()->InternalizeString(
    1860           5 :         isolate->factory()->NewStringFromAsciiChecked("happy_hippo"));
    1861             :     ec_page = Page::FromHeapObject(*moving_object);
    1862             :   }
    1863             : 
    1864          10 :   Handle<JSObject> global(isolate->context()->global_object(), isolate);
    1865           5 :   ScriptData* cache = nullptr;
    1866             : 
    1867             :   Handle<SharedFunctionInfo> orig = CompileScriptAndProduceCache(
    1868             :       isolate, source_str, Handle<String>(), &cache,
    1869           5 :       v8::ScriptCompiler::kNoCompileOptions);
    1870             : 
    1871           5 :   CHECK(heap->InSpace(orig->abstract_code(), LO_SPACE));
    1872             : 
    1873             :   // Pretend that incremental marking is on when deserialization begins.
    1874           5 :   heap::ForceEvacuationCandidate(ec_page);
    1875           5 :   heap::SimulateIncrementalMarking(heap, false);
    1876             :   IncrementalMarking* marking = heap->incremental_marking();
    1877             :   marking->StartBlackAllocationForTesting();
    1878           5 :   CHECK(marking->IsCompacting());
    1879           5 :   CHECK(MarkCompactCollector::IsOnEvacuationCandidate(*moving_object));
    1880             : 
    1881             :   Handle<SharedFunctionInfo> copy;
    1882             :   {
    1883             :     DisallowCompilation no_compile_expected(isolate);
    1884             :     copy = CompileScript(isolate, source_str, Handle<String>(), cache,
    1885          10 :                          v8::ScriptCompiler::kConsumeCodeCache);
    1886             :   }
    1887           5 :   CHECK_NE(*orig, *copy);
    1888             : 
    1889             :   // We should have missed a write barrier. Complete incremental marking
    1890             :   // to flush out the bug.
    1891           5 :   heap::SimulateIncrementalMarking(heap, true);
    1892           5 :   CcTest::CollectAllGarbage();
    1893             : 
    1894             :   Handle<JSFunction> copy_fun =
    1895             :       isolate->factory()->NewFunctionFromSharedFunctionInfo(
    1896          10 :           copy, isolate->native_context());
    1897             : 
    1898             :   Handle<Object> copy_result =
    1899          10 :       Execution::Call(isolate, copy_fun, global, 0, nullptr).ToHandleChecked();
    1900             : 
    1901             :   int result_int;
    1902           5 :   CHECK(copy_result->ToInt32(&result_int));
    1903           5 :   CHECK_EQ(7, result_int);
    1904             : 
    1905          10 :   delete cache;
    1906             :   source.Dispose();
    1907             : }
    1908       26644 : TEST(CodeSerializerLargeStrings) {
    1909           5 :   LocalContext context;
    1910             :   Isolate* isolate = CcTest::i_isolate();
    1911             :   Factory* f = isolate->factory();
    1912           5 :   isolate->compilation_cache()->Disable();  // Disable same-isolate code cache.
    1913             : 
    1914          10 :   v8::HandleScope scope(CcTest::isolate());
    1915             : 
    1916             :   Vector<const uint8_t> source_s = ConstructSource(
    1917             :       StaticCharVector("var s = \""), StaticCharVector("abcdef"),
    1918           5 :       StaticCharVector("\";"), 1000000);
    1919             :   Vector<const uint8_t> source_t = ConstructSource(
    1920             :       StaticCharVector("var t = \""), StaticCharVector("uvwxyz"),
    1921           5 :       StaticCharVector("\"; s + t"), 999999);
    1922             :   Handle<String> source_str =
    1923          15 :       f->NewConsString(f->NewStringFromOneByte(source_s).ToHandleChecked(),
    1924          10 :                        f->NewStringFromOneByte(source_t).ToHandleChecked())
    1925           5 :           .ToHandleChecked();
    1926             : 
    1927          10 :   Handle<JSObject> global(isolate->context()->global_object(), isolate);
    1928           5 :   ScriptData* cache = nullptr;
    1929             : 
    1930             :   Handle<SharedFunctionInfo> orig = CompileScriptAndProduceCache(
    1931             :       isolate, source_str, Handle<String>(), &cache,
    1932           5 :       v8::ScriptCompiler::kNoCompileOptions);
    1933             : 
    1934             :   Handle<SharedFunctionInfo> copy;
    1935             :   {
    1936             :     DisallowCompilation no_compile_expected(isolate);
    1937             :     copy = CompileScript(isolate, source_str, Handle<String>(), cache,
    1938          10 :                          v8::ScriptCompiler::kConsumeCodeCache);
    1939             :   }
    1940           5 :   CHECK_NE(*orig, *copy);
    1941             : 
    1942             :   Handle<JSFunction> copy_fun =
    1943             :       isolate->factory()->NewFunctionFromSharedFunctionInfo(
    1944          10 :           copy, isolate->native_context());
    1945             : 
    1946             :   Handle<Object> copy_result =
    1947          10 :       Execution::Call(isolate, copy_fun, global, 0, nullptr).ToHandleChecked();
    1948             : 
    1949           5 :   CHECK_EQ(6 * 1999999, Handle<String>::cast(copy_result)->length());
    1950             :   Handle<Object> property = JSReceiver::GetDataProperty(
    1951          15 :       isolate->global_object(), f->NewStringFromAsciiChecked("s"));
    1952           5 :   CHECK(isolate->heap()->InSpace(HeapObject::cast(*property), LO_SPACE));
    1953             :   property = JSReceiver::GetDataProperty(isolate->global_object(),
    1954          15 :                                          f->NewStringFromAsciiChecked("t"));
    1955           5 :   CHECK(isolate->heap()->InSpace(HeapObject::cast(*property), LO_SPACE));
    1956             :   // Make sure we do not serialize too much, e.g. include the source string.
    1957           5 :   CHECK_LT(cache->length(), 13000000);
    1958             : 
    1959          10 :   delete cache;
    1960             :   source_s.Dispose();
    1961             :   source_t.Dispose();
    1962           5 : }
    1963             : 
    1964       26644 : TEST(CodeSerializerThreeBigStrings) {
    1965           5 :   LocalContext context;
    1966             :   Isolate* isolate = CcTest::i_isolate();
    1967             :   Factory* f = isolate->factory();
    1968           5 :   isolate->compilation_cache()->Disable();  // Disable same-isolate code cache.
    1969             : 
    1970          10 :   v8::HandleScope scope(CcTest::isolate());
    1971             : 
    1972             :   const int32_t length_of_a = kMaxRegularHeapObjectSize * 2;
    1973             :   const int32_t length_of_b = kMaxRegularHeapObjectSize / 2;
    1974             :   const int32_t length_of_c = kMaxRegularHeapObjectSize / 2;
    1975             : 
    1976             :   Vector<const uint8_t> source_a =
    1977             :       ConstructSource(StaticCharVector("var a = \""), StaticCharVector("a"),
    1978           5 :                       StaticCharVector("\";"), length_of_a);
    1979             :   Handle<String> source_a_str =
    1980          10 :       f->NewStringFromOneByte(source_a).ToHandleChecked();
    1981             : 
    1982             :   Vector<const uint8_t> source_b =
    1983             :       ConstructSource(StaticCharVector("var b = \""), StaticCharVector("b"),
    1984           5 :                       StaticCharVector("\";"), length_of_b);
    1985             :   Handle<String> source_b_str =
    1986          10 :       f->NewStringFromOneByte(source_b).ToHandleChecked();
    1987             : 
    1988             :   Vector<const uint8_t> source_c =
    1989             :       ConstructSource(StaticCharVector("var c = \""), StaticCharVector("c"),
    1990           5 :                       StaticCharVector("\";"), length_of_c);
    1991             :   Handle<String> source_c_str =
    1992          10 :       f->NewStringFromOneByte(source_c).ToHandleChecked();
    1993             : 
    1994             :   Handle<String> source_str =
    1995          10 :       f->NewConsString(
    1996          10 :              f->NewConsString(source_a_str, source_b_str).ToHandleChecked(),
    1997           5 :              source_c_str).ToHandleChecked();
    1998             : 
    1999          10 :   Handle<JSObject> global(isolate->context()->global_object(), isolate);
    2000           5 :   ScriptData* cache = nullptr;
    2001             : 
    2002             :   Handle<SharedFunctionInfo> orig = CompileScriptAndProduceCache(
    2003             :       isolate, source_str, Handle<String>(), &cache,
    2004           5 :       v8::ScriptCompiler::kNoCompileOptions);
    2005             : 
    2006             :   Handle<SharedFunctionInfo> copy;
    2007             :   {
    2008             :     DisallowCompilation no_compile_expected(isolate);
    2009             :     copy = CompileScript(isolate, source_str, Handle<String>(), cache,
    2010          10 :                          v8::ScriptCompiler::kConsumeCodeCache);
    2011             :   }
    2012           5 :   CHECK_NE(*orig, *copy);
    2013             : 
    2014             :   Handle<JSFunction> copy_fun =
    2015             :       isolate->factory()->NewFunctionFromSharedFunctionInfo(
    2016          10 :           copy, isolate->native_context());
    2017             : 
    2018           5 :   USE(Execution::Call(isolate, copy_fun, global, 0, nullptr));
    2019             : 
    2020             :   v8::Maybe<int32_t> result =
    2021             :       CompileRun("(a + b).length")
    2022          10 :           ->Int32Value(v8::Isolate::GetCurrent()->GetCurrentContext());
    2023           5 :   CHECK_EQ(length_of_a + length_of_b, result.FromJust());
    2024             :   result = CompileRun("(b + c).length")
    2025          10 :                ->Int32Value(v8::Isolate::GetCurrent()->GetCurrentContext());
    2026           5 :   CHECK_EQ(length_of_b + length_of_c, result.FromJust());
    2027             :   Heap* heap = isolate->heap();
    2028             :   v8::Local<v8::String> result_str =
    2029             :       CompileRun("a")
    2030          10 :           ->ToString(CcTest::isolate()->GetCurrentContext())
    2031             :           .ToLocalChecked();
    2032           5 :   CHECK(heap->InSpace(*v8::Utils::OpenHandle(*result_str), LO_SPACE));
    2033             :   result_str = CompileRun("b")
    2034          10 :                    ->ToString(CcTest::isolate()->GetCurrentContext())
    2035             :                    .ToLocalChecked();
    2036           5 :   CHECK(heap->InSpace(*v8::Utils::OpenHandle(*result_str), OLD_SPACE));
    2037             : 
    2038             :   result_str = CompileRun("c")
    2039          10 :                    ->ToString(CcTest::isolate()->GetCurrentContext())
    2040             :                    .ToLocalChecked();
    2041           5 :   CHECK(heap->InSpace(*v8::Utils::OpenHandle(*result_str), OLD_SPACE));
    2042             : 
    2043          10 :   delete cache;
    2044             :   source_a.Dispose();
    2045             :   source_b.Dispose();
    2046             :   source_c.Dispose();
    2047           5 : }
    2048             : 
    2049             : 
    2050       53308 : class SerializerOneByteResource
    2051             :     : public v8::String::ExternalOneByteStringResource {
    2052             :  public:
    2053             :   SerializerOneByteResource(const char* data, size_t length)
    2054       26654 :       : data_(data), length_(length), dispose_count_(0) {}
    2055         112 :   const char* data() const override { return data_; }
    2056          40 :   size_t length() const override { return length_; }
    2057          15 :   void Dispose() override { dispose_count_++; }
    2058             :   int dispose_count() { return dispose_count_; }
    2059             : 
    2060             :  private:
    2061             :   const char* data_;
    2062             :   size_t length_;
    2063             :   int dispose_count_;
    2064             : };
    2065             : 
    2066             : 
    2067             : class SerializerTwoByteResource : public v8::String::ExternalStringResource {
    2068             :  public:
    2069             :   SerializerTwoByteResource(const char* data, size_t length)
    2070       26644 :       : data_(AsciiToTwoByteString(data)), length_(length), dispose_count_(0) {}
    2071       53288 :   ~SerializerTwoByteResource() override { DeleteArray<const uint16_t>(data_); }
    2072             : 
    2073          67 :   const uint16_t* data() const override { return data_; }
    2074          25 :   size_t length() const override { return length_; }
    2075          15 :   void Dispose() override { dispose_count_++; }
    2076             :   int dispose_count() { return dispose_count_; }
    2077             : 
    2078             :  private:
    2079             :   const uint16_t* data_;
    2080             :   size_t length_;
    2081             :   int dispose_count_;
    2082             : };
    2083             : 
    2084       26644 : TEST(CodeSerializerExternalString) {
    2085           5 :   LocalContext context;
    2086             :   Isolate* isolate = CcTest::i_isolate();
    2087           5 :   isolate->compilation_cache()->Disable();  // Disable same-isolate code cache.
    2088             : 
    2089          10 :   v8::HandleScope scope(CcTest::isolate());
    2090             : 
    2091             :   // Obtain external internalized one-byte string.
    2092             :   SerializerOneByteResource one_byte_resource("one_byte", 8);
    2093             :   Handle<String> one_byte_string =
    2094           5 :       isolate->factory()->NewStringFromAsciiChecked("one_byte");
    2095           5 :   one_byte_string = isolate->factory()->InternalizeString(one_byte_string);
    2096           5 :   one_byte_string->MakeExternal(&one_byte_resource);
    2097           5 :   CHECK(one_byte_string->IsExternalOneByteString());
    2098           5 :   CHECK(one_byte_string->IsInternalizedString());
    2099             : 
    2100             :   // Obtain external internalized two-byte string.
    2101             :   SerializerTwoByteResource two_byte_resource("two_byte", 8);
    2102             :   Handle<String> two_byte_string =
    2103           5 :       isolate->factory()->NewStringFromAsciiChecked("two_byte");
    2104           5 :   two_byte_string = isolate->factory()->InternalizeString(two_byte_string);
    2105           5 :   two_byte_string->MakeExternal(&two_byte_resource);
    2106           5 :   CHECK(two_byte_string->IsExternalTwoByteString());
    2107           5 :   CHECK(two_byte_string->IsInternalizedString());
    2108             : 
    2109             :   const char* source =
    2110             :       "var o = {}               \n"
    2111             :       "o.one_byte = 7;          \n"
    2112             :       "o.two_byte = 8;          \n"
    2113             :       "o.one_byte + o.two_byte; \n";
    2114             :   Handle<String> source_string = isolate->factory()
    2115          10 :                                      ->NewStringFromUtf8(CStrVector(source))
    2116           5 :                                      .ToHandleChecked();
    2117             : 
    2118          10 :   Handle<JSObject> global(isolate->context()->global_object(), isolate);
    2119           5 :   ScriptData* cache = nullptr;
    2120             : 
    2121             :   Handle<SharedFunctionInfo> orig = CompileScriptAndProduceCache(
    2122             :       isolate, source_string, Handle<String>(), &cache,
    2123           5 :       v8::ScriptCompiler::kNoCompileOptions);
    2124             : 
    2125             :   Handle<SharedFunctionInfo> copy;
    2126             :   {
    2127             :     DisallowCompilation no_compile_expected(isolate);
    2128             :     copy = CompileScript(isolate, source_string, Handle<String>(), cache,
    2129          10 :                          v8::ScriptCompiler::kConsumeCodeCache);
    2130             :   }
    2131           5 :   CHECK_NE(*orig, *copy);
    2132             : 
    2133             :   Handle<JSFunction> copy_fun =
    2134             :       isolate->factory()->NewFunctionFromSharedFunctionInfo(
    2135          10 :           copy, isolate->native_context());
    2136             : 
    2137             :   Handle<Object> copy_result =
    2138          10 :       Execution::Call(isolate, copy_fun, global, 0, nullptr).ToHandleChecked();
    2139             : 
    2140           5 :   CHECK_EQ(15.0, copy_result->Number());
    2141             : 
    2142             :   // This avoids the GC from trying to free stack allocated resources.
    2143             :   i::Handle<i::ExternalOneByteString>::cast(one_byte_string)
    2144           5 :       ->SetResource(isolate, nullptr);
    2145             :   i::Handle<i::ExternalTwoByteString>::cast(two_byte_string)
    2146           5 :       ->SetResource(isolate, nullptr);
    2147          10 :   delete cache;
    2148           5 : }
    2149             : 
    2150       26644 : TEST(CodeSerializerLargeExternalString) {
    2151           5 :   LocalContext context;
    2152             :   Isolate* isolate = CcTest::i_isolate();
    2153           5 :   isolate->compilation_cache()->Disable();  // Disable same-isolate code cache.
    2154             : 
    2155             :   Factory* f = isolate->factory();
    2156             : 
    2157          10 :   v8::HandleScope scope(CcTest::isolate());
    2158             : 
    2159             :   // Create a huge external internalized string to use as variable name.
    2160             :   Vector<const uint8_t> string =
    2161             :       ConstructSource(StaticCharVector(""), StaticCharVector("abcdef"),
    2162           5 :                       StaticCharVector(""), 999999);
    2163          10 :   Handle<String> name = f->NewStringFromOneByte(string).ToHandleChecked();
    2164             :   SerializerOneByteResource one_byte_resource(
    2165           5 :       reinterpret_cast<const char*>(string.start()), string.length());
    2166           5 :   name = f->InternalizeString(name);
    2167           5 :   name->MakeExternal(&one_byte_resource);
    2168           5 :   CHECK(name->IsExternalOneByteString());
    2169           5 :   CHECK(name->IsInternalizedString());
    2170          10 :   CHECK(isolate->heap()->InSpace(*name, LO_SPACE));
    2171             : 
    2172             :   // Create the source, which is "var <literal> = 42; <literal>".
    2173             :   Handle<String> source_str =
    2174          10 :       f->NewConsString(
    2175          10 :              f->NewConsString(f->NewStringFromAsciiChecked("var "), name)
    2176             :                  .ToHandleChecked(),
    2177          10 :              f->NewConsString(f->NewStringFromAsciiChecked(" = 42; "), name)
    2178           5 :                  .ToHandleChecked()).ToHandleChecked();
    2179             : 
    2180          10 :   Handle<JSObject> global(isolate->context()->global_object(), isolate);
    2181           5 :   ScriptData* cache = nullptr;
    2182             : 
    2183             :   Handle<SharedFunctionInfo> orig = CompileScriptAndProduceCache(
    2184             :       isolate, source_str, Handle<String>(), &cache,
    2185           5 :       v8::ScriptCompiler::kNoCompileOptions);
    2186             : 
    2187             :   Handle<SharedFunctionInfo> copy;
    2188             :   {
    2189             :     DisallowCompilation no_compile_expected(isolate);
    2190             :     copy = CompileScript(isolate, source_str, Handle<String>(), cache,
    2191          10 :                          v8::ScriptCompiler::kConsumeCodeCache);
    2192             :   }
    2193           5 :   CHECK_NE(*orig, *copy);
    2194             : 
    2195             :   Handle<JSFunction> copy_fun =
    2196          10 :       f->NewFunctionFromSharedFunctionInfo(copy, isolate->native_context());
    2197             : 
    2198             :   Handle<Object> copy_result =
    2199          10 :       Execution::Call(isolate, copy_fun, global, 0, nullptr).ToHandleChecked();
    2200             : 
    2201           5 :   CHECK_EQ(42.0, copy_result->Number());
    2202             : 
    2203             :   // This avoids the GC from trying to free stack allocated resources.
    2204          10 :   i::Handle<i::ExternalOneByteString>::cast(name)->SetResource(isolate,
    2205           5 :                                                                nullptr);
    2206          10 :   delete cache;
    2207             :   string.Dispose();
    2208           5 : }
    2209             : 
    2210       26644 : TEST(CodeSerializerExternalScriptName) {
    2211           5 :   LocalContext context;
    2212             :   Isolate* isolate = CcTest::i_isolate();
    2213           5 :   isolate->compilation_cache()->Disable();  // Disable same-isolate code cache.
    2214             : 
    2215             :   Factory* f = isolate->factory();
    2216             : 
    2217          10 :   v8::HandleScope scope(CcTest::isolate());
    2218             : 
    2219             :   const char* source =
    2220             :       "var a = [1, 2, 3, 4];"
    2221             :       "a.reduce(function(x, y) { return x + y }, 0)";
    2222             : 
    2223             :   Handle<String> source_string =
    2224          10 :       f->NewStringFromUtf8(CStrVector(source)).ToHandleChecked();
    2225             : 
    2226             :   const SerializerOneByteResource one_byte_resource("one_byte", 8);
    2227             :   Handle<String> name =
    2228          10 :       f->NewExternalStringFromOneByte(&one_byte_resource).ToHandleChecked();
    2229           5 :   CHECK(name->IsExternalOneByteString());
    2230           5 :   CHECK(!name->IsInternalizedString());
    2231             : 
    2232          10 :   Handle<JSObject> global(isolate->context()->global_object(), isolate);
    2233           5 :   ScriptData* cache = nullptr;
    2234             : 
    2235             :   Handle<SharedFunctionInfo> orig =
    2236             :       CompileScriptAndProduceCache(isolate, source_string, name, &cache,
    2237           5 :                                    v8::ScriptCompiler::kNoCompileOptions);
    2238             : 
    2239             :   Handle<SharedFunctionInfo> copy;
    2240             :   {
    2241             :     DisallowCompilation no_compile_expected(isolate);
    2242             :     copy = CompileScript(isolate, source_string, name, cache,
    2243           5 :                          v8::ScriptCompiler::kConsumeCodeCache);
    2244             :   }
    2245           5 :   CHECK_NE(*orig, *copy);
    2246             : 
    2247             :   Handle<JSFunction> copy_fun =
    2248          10 :       f->NewFunctionFromSharedFunctionInfo(copy, isolate->native_context());
    2249             : 
    2250             :   Handle<Object> copy_result =
    2251          10 :       Execution::Call(isolate, copy_fun, global, 0, nullptr).ToHandleChecked();
    2252             : 
    2253           5 :   CHECK_EQ(10.0, copy_result->Number());
    2254             : 
    2255             :   // This avoids the GC from trying to free stack allocated resources.
    2256          10 :   i::Handle<i::ExternalOneByteString>::cast(name)->SetResource(isolate,
    2257           5 :                                                                nullptr);
    2258          10 :   delete cache;
    2259           5 : }
    2260             : 
    2261             : 
    2262             : static bool toplevel_test_code_event_found = false;
    2263             : 
    2264             : 
    2265          88 : static void SerializerCodeEventListener(const v8::JitCodeEvent* event) {
    2266         118 :   if (event->type == v8::JitCodeEvent::CODE_ADDED &&
    2267          50 :       (memcmp(event->name.str, "Script:~ test", 13) == 0 ||
    2268          20 :        memcmp(event->name.str, "Script: test", 12) == 0)) {
    2269          10 :     toplevel_test_code_event_found = true;
    2270             :   }
    2271          88 : }
    2272             : 
    2273          25 : v8::ScriptCompiler::CachedData* CompileRunAndProduceCache(
    2274             :     const char* source, CodeCacheType cacheType = CodeCacheType::kLazy) {
    2275             :   v8::ScriptCompiler::CachedData* cache;
    2276             :   v8::Isolate::CreateParams create_params;
    2277          25 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    2278          25 :   v8::Isolate* isolate1 = v8::Isolate::New(create_params);
    2279             :   {
    2280             :     v8::Isolate::Scope iscope(isolate1);
    2281          50 :     v8::HandleScope scope(isolate1);
    2282          25 :     v8::Local<v8::Context> context = v8::Context::New(isolate1);
    2283             :     v8::Context::Scope context_scope(context);
    2284             : 
    2285          25 :     v8::Local<v8::String> source_str = v8_str(source);
    2286          25 :     v8::ScriptOrigin origin(v8_str("test"));
    2287             :     v8::ScriptCompiler::Source source(source_str, origin);
    2288             :     v8::ScriptCompiler::CompileOptions options;
    2289          25 :     switch (cacheType) {
    2290             :       case CodeCacheType::kEager:
    2291             :         options = v8::ScriptCompiler::kEagerCompile;
    2292             :         break;
    2293             :       case CodeCacheType::kLazy:
    2294             :       case CodeCacheType::kAfterExecute:
    2295             :         options = v8::ScriptCompiler::kNoCompileOptions;
    2296          20 :         break;
    2297             :       default:
    2298           0 :         UNREACHABLE();
    2299             :     }
    2300             :     v8::Local<v8::UnboundScript> script =
    2301          25 :         v8::ScriptCompiler::CompileUnboundScript(isolate1, &source, options)
    2302             :             .ToLocalChecked();
    2303             : 
    2304          25 :     if (cacheType != CodeCacheType::kAfterExecute) {
    2305          20 :       cache = ScriptCompiler::CreateCodeCache(script);
    2306             :     }
    2307             : 
    2308          50 :     v8::Local<v8::Value> result = script->BindToCurrentContext()
    2309          50 :                                       ->Run(isolate1->GetCurrentContext())
    2310             :                                       .ToLocalChecked();
    2311             :     v8::Local<v8::String> result_string =
    2312          25 :         result->ToString(isolate1->GetCurrentContext()).ToLocalChecked();
    2313          75 :     CHECK(result_string->Equals(isolate1->GetCurrentContext(), v8_str("abcdef"))
    2314             :               .FromJust());
    2315             : 
    2316          25 :     if (cacheType == CodeCacheType::kAfterExecute) {
    2317           5 :       cache = ScriptCompiler::CreateCodeCache(script);
    2318             :     }
    2319          25 :     CHECK(cache);
    2320             :   }
    2321          25 :   isolate1->Dispose();
    2322          25 :   return cache;
    2323             : }
    2324             : 
    2325       26644 : TEST(CodeSerializerIsolates) {
    2326             :   const char* source = "function f() { return 'abc'; }; f() + 'def'";
    2327           5 :   v8::ScriptCompiler::CachedData* cache = CompileRunAndProduceCache(source);
    2328             : 
    2329             :   v8::Isolate::CreateParams create_params;
    2330           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    2331           5 :   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
    2332             :   isolate2->SetJitCodeEventHandler(v8::kJitCodeEventDefault,
    2333           5 :                                    SerializerCodeEventListener);
    2334           5 :   toplevel_test_code_event_found = false;
    2335             :   {
    2336             :     v8::Isolate::Scope iscope(isolate2);
    2337          10 :     v8::HandleScope scope(isolate2);
    2338           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate2);
    2339             :     v8::Context::Scope context_scope(context);
    2340             : 
    2341           5 :     v8::Local<v8::String> source_str = v8_str(source);
    2342           5 :     v8::ScriptOrigin origin(v8_str("test"));
    2343             :     v8::ScriptCompiler::Source source(source_str, origin, cache);
    2344             :     v8::Local<v8::UnboundScript> script;
    2345             :     {
    2346             :       DisallowCompilation no_compile(reinterpret_cast<Isolate*>(isolate2));
    2347           5 :       script = v8::ScriptCompiler::CompileUnboundScript(
    2348             :                    isolate2, &source, v8::ScriptCompiler::kConsumeCodeCache)
    2349             :                    .ToLocalChecked();
    2350             :     }
    2351           5 :     CHECK(!cache->rejected);
    2352          10 :     v8::Local<v8::Value> result = script->BindToCurrentContext()
    2353          10 :                                       ->Run(isolate2->GetCurrentContext())
    2354             :                                       .ToLocalChecked();
    2355          20 :     CHECK(result->ToString(isolate2->GetCurrentContext())
    2356             :               .ToLocalChecked()
    2357             :               ->Equals(isolate2->GetCurrentContext(), v8_str("abcdef"))
    2358             :               .FromJust());
    2359             :   }
    2360           5 :   CHECK(toplevel_test_code_event_found);
    2361           5 :   isolate2->Dispose();
    2362           5 : }
    2363             : 
    2364       26644 : TEST(CodeSerializerIsolatesEager) {
    2365             :   const char* source =
    2366             :       "function f() {"
    2367             :       "  return function g() {"
    2368             :       "    return 'abc';"
    2369             :       "  }"
    2370             :       "}"
    2371             :       "f()() + 'def'";
    2372             :   v8::ScriptCompiler::CachedData* cache =
    2373           5 :       CompileRunAndProduceCache(source, CodeCacheType::kEager);
    2374             : 
    2375             :   v8::Isolate::CreateParams create_params;
    2376           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    2377           5 :   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
    2378             :   isolate2->SetJitCodeEventHandler(v8::kJitCodeEventDefault,
    2379           5 :                                    SerializerCodeEventListener);
    2380           5 :   toplevel_test_code_event_found = false;
    2381             :   {
    2382             :     v8::Isolate::Scope iscope(isolate2);
    2383          10 :     v8::HandleScope scope(isolate2);
    2384           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate2);
    2385             :     v8::Context::Scope context_scope(context);
    2386             : 
    2387           5 :     v8::Local<v8::String> source_str = v8_str(source);
    2388           5 :     v8::ScriptOrigin origin(v8_str("test"));
    2389             :     v8::ScriptCompiler::Source source(source_str, origin, cache);
    2390             :     v8::Local<v8::UnboundScript> script;
    2391             :     {
    2392             :       DisallowCompilation no_compile(reinterpret_cast<Isolate*>(isolate2));
    2393           5 :       script = v8::ScriptCompiler::CompileUnboundScript(
    2394             :                    isolate2, &source, v8::ScriptCompiler::kConsumeCodeCache)
    2395             :                    .ToLocalChecked();
    2396             :     }
    2397           5 :     CHECK(!cache->rejected);
    2398          10 :     v8::Local<v8::Value> result = script->BindToCurrentContext()
    2399          10 :                                       ->Run(isolate2->GetCurrentContext())
    2400             :                                       .ToLocalChecked();
    2401          20 :     CHECK(result->ToString(isolate2->GetCurrentContext())
    2402             :               .ToLocalChecked()
    2403             :               ->Equals(isolate2->GetCurrentContext(), v8_str("abcdef"))
    2404             :               .FromJust());
    2405             :   }
    2406           5 :   CHECK(toplevel_test_code_event_found);
    2407           5 :   isolate2->Dispose();
    2408           5 : }
    2409             : 
    2410       26644 : TEST(CodeSerializerAfterExecute) {
    2411             :   // We test that no compilations happen when running this code. Forcing
    2412             :   // to always optimize breaks this test.
    2413           5 :   bool prev_always_opt_value = FLAG_always_opt;
    2414           5 :   FLAG_always_opt = false;
    2415             :   const char* source = "function f() { return 'abc'; }; f() + 'def'";
    2416             :   v8::ScriptCompiler::CachedData* cache =
    2417           5 :       CompileRunAndProduceCache(source, CodeCacheType::kAfterExecute);
    2418             : 
    2419             :   v8::Isolate::CreateParams create_params;
    2420           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    2421           5 :   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
    2422             : 
    2423             :   {
    2424             :     v8::Isolate::Scope iscope(isolate2);
    2425          10 :     v8::HandleScope scope(isolate2);
    2426           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate2);
    2427             :     v8::Context::Scope context_scope(context);
    2428             : 
    2429           5 :     v8::Local<v8::String> source_str = v8_str(source);
    2430           5 :     v8::ScriptOrigin origin(v8_str("test"));
    2431             :     v8::ScriptCompiler::Source source(source_str, origin, cache);
    2432             :     v8::Local<v8::UnboundScript> script;
    2433             :     {
    2434             :       DisallowCompilation no_compile_expected(
    2435             :           reinterpret_cast<Isolate*>(isolate2));
    2436           5 :       script = v8::ScriptCompiler::CompileUnboundScript(
    2437             :                    isolate2, &source, v8::ScriptCompiler::kConsumeCodeCache)
    2438             :                    .ToLocalChecked();
    2439             :     }
    2440           5 :     CHECK(!cache->rejected);
    2441             : 
    2442             :     Handle<SharedFunctionInfo> sfi = v8::Utils::OpenHandle(*script);
    2443           5 :     CHECK(sfi->HasBytecodeArray());
    2444           5 :     BytecodeArray bytecode = sfi->GetBytecodeArray();
    2445           5 :     CHECK_EQ(bytecode->osr_loop_nesting_level(), 0);
    2446             : 
    2447             :     {
    2448             :       DisallowCompilation no_compile_expected(
    2449             :           reinterpret_cast<Isolate*>(isolate2));
    2450          10 :       v8::Local<v8::Value> result = script->BindToCurrentContext()
    2451          10 :                                         ->Run(isolate2->GetCurrentContext())
    2452             :                                         .ToLocalChecked();
    2453             :       v8::Local<v8::String> result_string =
    2454           5 :           result->ToString(isolate2->GetCurrentContext()).ToLocalChecked();
    2455          15 :       CHECK(
    2456             :           result_string->Equals(isolate2->GetCurrentContext(), v8_str("abcdef"))
    2457             :               .FromJust());
    2458             :     }
    2459             :   }
    2460           5 :   isolate2->Dispose();
    2461             : 
    2462             :   // Restore the flags.
    2463           5 :   FLAG_always_opt = prev_always_opt_value;
    2464           5 : }
    2465             : 
    2466       26644 : TEST(CodeSerializerFlagChange) {
    2467             :   const char* source = "function f() { return 'abc'; }; f() + 'def'";
    2468           5 :   v8::ScriptCompiler::CachedData* cache = CompileRunAndProduceCache(source);
    2469             : 
    2470             :   v8::Isolate::CreateParams create_params;
    2471           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    2472           5 :   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
    2473             : 
    2474           5 :   FLAG_allow_natives_syntax = true;  // Flag change should trigger cache reject.
    2475           5 :   FlagList::EnforceFlagImplications();
    2476             :   {
    2477             :     v8::Isolate::Scope iscope(isolate2);
    2478          10 :     v8::HandleScope scope(isolate2);
    2479           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate2);
    2480             :     v8::Context::Scope context_scope(context);
    2481             : 
    2482           5 :     v8::Local<v8::String> source_str = v8_str(source);
    2483           5 :     v8::ScriptOrigin origin(v8_str("test"));
    2484             :     v8::ScriptCompiler::Source source(source_str, origin, cache);
    2485           5 :     v8::ScriptCompiler::CompileUnboundScript(
    2486             :         isolate2, &source, v8::ScriptCompiler::kConsumeCodeCache)
    2487             :         .ToLocalChecked();
    2488           5 :     CHECK(cache->rejected);
    2489             :   }
    2490           5 :   isolate2->Dispose();
    2491           5 : }
    2492             : 
    2493       26644 : TEST(CodeSerializerBitFlip) {
    2494             :   const char* source = "function f() { return 'abc'; }; f() + 'def'";
    2495           5 :   v8::ScriptCompiler::CachedData* cache = CompileRunAndProduceCache(source);
    2496             : 
    2497             :   // Random bit flip.
    2498           5 :   const_cast<uint8_t*>(cache->data)[337] ^= 0x40;
    2499             : 
    2500             :   v8::Isolate::CreateParams create_params;
    2501           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    2502           5 :   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
    2503             :   {
    2504             :     v8::Isolate::Scope iscope(isolate2);
    2505          10 :     v8::HandleScope scope(isolate2);
    2506           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate2);
    2507             :     v8::Context::Scope context_scope(context);
    2508             : 
    2509           5 :     v8::Local<v8::String> source_str = v8_str(source);
    2510           5 :     v8::ScriptOrigin origin(v8_str("test"));
    2511             :     v8::ScriptCompiler::Source source(source_str, origin, cache);
    2512           5 :     v8::ScriptCompiler::CompileUnboundScript(
    2513             :         isolate2, &source, v8::ScriptCompiler::kConsumeCodeCache)
    2514             :         .ToLocalChecked();
    2515           5 :     CHECK(cache->rejected);
    2516             :   }
    2517           5 :   isolate2->Dispose();
    2518           5 : }
    2519             : 
    2520       26644 : TEST(CodeSerializerWithHarmonyScoping) {
    2521             :   const char* source1 = "'use strict'; let x = 'X'";
    2522             :   const char* source2 = "'use strict'; let y = 'Y'";
    2523             :   const char* source3 = "'use strict'; x + y";
    2524             : 
    2525             :   v8::ScriptCompiler::CachedData* cache;
    2526             : 
    2527             :   v8::Isolate::CreateParams create_params;
    2528           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    2529           5 :   v8::Isolate* isolate1 = v8::Isolate::New(create_params);
    2530             :   {
    2531             :     v8::Isolate::Scope iscope(isolate1);
    2532          10 :     v8::HandleScope scope(isolate1);
    2533           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate1);
    2534             :     v8::Context::Scope context_scope(context);
    2535             : 
    2536             :     CompileRun(source1);
    2537             :     CompileRun(source2);
    2538             : 
    2539           5 :     v8::Local<v8::String> source_str = v8_str(source3);
    2540           5 :     v8::ScriptOrigin origin(v8_str("test"));
    2541             :     v8::ScriptCompiler::Source source(source_str, origin);
    2542             :     v8::Local<v8::UnboundScript> script =
    2543           5 :         v8::ScriptCompiler::CompileUnboundScript(
    2544             :             isolate1, &source, v8::ScriptCompiler::kNoCompileOptions)
    2545             :             .ToLocalChecked();
    2546           5 :     cache = v8::ScriptCompiler::CreateCodeCache(script);
    2547           5 :     CHECK(cache);
    2548             : 
    2549          10 :     v8::Local<v8::Value> result = script->BindToCurrentContext()
    2550          10 :                                       ->Run(isolate1->GetCurrentContext())
    2551             :                                       .ToLocalChecked();
    2552             :     v8::Local<v8::String> result_str =
    2553           5 :         result->ToString(isolate1->GetCurrentContext()).ToLocalChecked();
    2554          15 :     CHECK(result_str->Equals(isolate1->GetCurrentContext(), v8_str("XY"))
    2555             :               .FromJust());
    2556             :   }
    2557           5 :   isolate1->Dispose();
    2558             : 
    2559           5 :   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
    2560             :   {
    2561             :     v8::Isolate::Scope iscope(isolate2);
    2562          10 :     v8::HandleScope scope(isolate2);
    2563           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate2);
    2564             :     v8::Context::Scope context_scope(context);
    2565             : 
    2566             :     // Reverse order of prior running scripts.
    2567             :     CompileRun(source2);
    2568             :     CompileRun(source1);
    2569             : 
    2570           5 :     v8::Local<v8::String> source_str = v8_str(source3);
    2571           5 :     v8::ScriptOrigin origin(v8_str("test"));
    2572             :     v8::ScriptCompiler::Source source(source_str, origin, cache);
    2573             :     v8::Local<v8::UnboundScript> script;
    2574             :     {
    2575             :       DisallowCompilation no_compile(reinterpret_cast<Isolate*>(isolate2));
    2576           5 :       script = v8::ScriptCompiler::CompileUnboundScript(
    2577             :                    isolate2, &source, v8::ScriptCompiler::kConsumeCodeCache)
    2578             :                    .ToLocalChecked();
    2579             :     }
    2580          10 :     v8::Local<v8::Value> result = script->BindToCurrentContext()
    2581          10 :                                       ->Run(isolate2->GetCurrentContext())
    2582             :                                       .ToLocalChecked();
    2583             :     v8::Local<v8::String> result_str =
    2584           5 :         result->ToString(isolate2->GetCurrentContext()).ToLocalChecked();
    2585          15 :     CHECK(result_str->Equals(isolate2->GetCurrentContext(), v8_str("XY"))
    2586             :               .FromJust());
    2587             :   }
    2588           5 :   isolate2->Dispose();
    2589           5 : }
    2590             : 
    2591       26644 : TEST(Regress503552) {
    2592           5 :   if (!FLAG_incremental_marking) return;
    2593             :   // Test that the code serializer can deal with weak cells that form a linked
    2594             :   // list during incremental marking.
    2595           5 :   CcTest::InitializeVM();
    2596             :   Isolate* isolate = CcTest::i_isolate();
    2597             : 
    2598             :   HandleScope scope(isolate);
    2599             :   Handle<String> source = isolate->factory()->NewStringFromAsciiChecked(
    2600           5 :       "function f() {} function g() {}");
    2601           5 :   ScriptData* script_data = nullptr;
    2602             :   Handle<SharedFunctionInfo> shared = CompileScriptAndProduceCache(
    2603             :       isolate, source, Handle<String>(), &script_data,
    2604           5 :       v8::ScriptCompiler::kNoCompileOptions);
    2605          10 :   delete script_data;
    2606             : 
    2607           5 :   heap::SimulateIncrementalMarking(isolate->heap());
    2608             : 
    2609             :   v8::ScriptCompiler::CachedData* cache_data =
    2610           5 :       CodeSerializer::Serialize(shared);
    2611           5 :   delete cache_data;
    2612             : }
    2613             : 
    2614       26644 : UNINITIALIZED_TEST(SnapshotCreatorMultipleContexts) {
    2615             :   DisableAlwaysOpt();
    2616           5 :   DisableEmbeddedBlobRefcounting();
    2617             :   v8::StartupData blob;
    2618             :   {
    2619          10 :     v8::SnapshotCreator creator;
    2620           5 :     v8::Isolate* isolate = creator.GetIsolate();
    2621             :     {
    2622          10 :       v8::HandleScope handle_scope(isolate);
    2623           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2624             :       v8::Context::Scope context_scope(context);
    2625             :       CompileRun("var f = function() { return 1; }");
    2626           5 :       creator.SetDefaultContext(context);
    2627             :     }
    2628             :     {
    2629          10 :       v8::HandleScope handle_scope(isolate);
    2630           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2631             :       v8::Context::Scope context_scope(context);
    2632             :       CompileRun("var f = function() { return 2; }");
    2633           5 :       CHECK_EQ(0u, creator.AddContext(context));
    2634             :     }
    2635             :     {
    2636          10 :       v8::HandleScope handle_scope(isolate);
    2637           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2638           5 :       CHECK_EQ(1u, creator.AddContext(context));
    2639             :     }
    2640             :     blob =
    2641           5 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    2642             :   }
    2643             : 
    2644             :   v8::Isolate::CreateParams params;
    2645           5 :   params.snapshot_blob = &blob;
    2646           5 :   params.array_buffer_allocator = CcTest::array_buffer_allocator();
    2647             :   // Test-appropriate equivalent of v8::Isolate::New.
    2648           5 :   v8::Isolate* isolate = TestSerializer::NewIsolate(params);
    2649             :   {
    2650             :     v8::Isolate::Scope isolate_scope(isolate);
    2651             :     {
    2652          10 :       v8::HandleScope handle_scope(isolate);
    2653           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2654             :       v8::Context::Scope context_scope(context);
    2655           5 :       ExpectInt32("f()", 1);
    2656             :     }
    2657             :     {
    2658          10 :       v8::HandleScope handle_scope(isolate);
    2659             :       v8::Local<v8::Context> context =
    2660          10 :           v8::Context::FromSnapshot(isolate, 0).ToLocalChecked();
    2661             :       v8::Context::Scope context_scope(context);
    2662           5 :       ExpectInt32("f()", 2);
    2663             :     }
    2664             :     {
    2665          10 :       v8::HandleScope handle_scope(isolate);
    2666             :       v8::Local<v8::Context> context =
    2667          10 :           v8::Context::FromSnapshot(isolate, 1).ToLocalChecked();
    2668             :       v8::Context::Scope context_scope(context);
    2669           5 :       ExpectUndefined("this.f");
    2670             :     }
    2671             :   }
    2672             : 
    2673           5 :   isolate->Dispose();
    2674           5 :   delete[] blob.data;
    2675           5 :   FreeCurrentEmbeddedBlob();
    2676           5 : }
    2677             : 
    2678             : static int serialized_static_field = 314;
    2679             : 
    2680          65 : static void SerializedCallback(
    2681             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    2682          65 :   if (args.Data()->IsExternal()) {
    2683          20 :     CHECK_EQ(args.Data().As<v8::External>()->Value(),
    2684             :              static_cast<void*>(&serialized_static_field));
    2685             :     int* value =
    2686          20 :         reinterpret_cast<int*>(args.Data().As<v8::External>()->Value());
    2687          20 :     (*value)++;
    2688             :   }
    2689          65 :   args.GetReturnValue().Set(v8_num(42));
    2690          65 : }
    2691             : 
    2692          10 : static void SerializedCallbackReplacement(
    2693             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    2694          10 :   args.GetReturnValue().Set(v8_num(1337));
    2695          10 : }
    2696             : 
    2697         135 : static void NamedPropertyGetterForSerialization(
    2698             :     v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
    2699         540 :   if (name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("x"))
    2700             :           .FromJust()) {
    2701          20 :     info.GetReturnValue().Set(v8_num(2016));
    2702             :   }
    2703         135 : }
    2704             : 
    2705          10 : static void AccessorForSerialization(
    2706             :     v8::Local<v8::String> property,
    2707             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
    2708          10 :   info.GetReturnValue().Set(v8_num(2017));
    2709          10 : }
    2710             : 
    2711             : 
    2712       26639 : static SerializerOneByteResource serializable_one_byte_resource("one_byte", 8);
    2713       26639 : static SerializerTwoByteResource serializable_two_byte_resource("two_byte", 8);
    2714             : 
    2715             : intptr_t original_external_references[] = {
    2716             :     reinterpret_cast<intptr_t>(SerializedCallback),
    2717             :     reinterpret_cast<intptr_t>(&serialized_static_field),
    2718             :     reinterpret_cast<intptr_t>(&NamedPropertyGetterForSerialization),
    2719             :     reinterpret_cast<intptr_t>(&AccessorForSerialization),
    2720             :     reinterpret_cast<intptr_t>(&serialized_static_field),  // duplicate entry
    2721             :     reinterpret_cast<intptr_t>(&serializable_one_byte_resource),
    2722             :     reinterpret_cast<intptr_t>(&serializable_two_byte_resource),
    2723             :     0};
    2724             : 
    2725             : intptr_t replaced_external_references[] = {
    2726             :     reinterpret_cast<intptr_t>(SerializedCallbackReplacement),
    2727             :     reinterpret_cast<intptr_t>(&serialized_static_field),
    2728             :     reinterpret_cast<intptr_t>(&NamedPropertyGetterForSerialization),
    2729             :     reinterpret_cast<intptr_t>(&AccessorForSerialization),
    2730             :     reinterpret_cast<intptr_t>(&serialized_static_field),
    2731             :     reinterpret_cast<intptr_t>(&serializable_one_byte_resource),
    2732             :     reinterpret_cast<intptr_t>(&serializable_two_byte_resource),
    2733             :     0};
    2734             : 
    2735             : intptr_t short_external_references[] = {
    2736             :     reinterpret_cast<intptr_t>(SerializedCallbackReplacement), 0};
    2737             : 
    2738       26644 : UNINITIALIZED_TEST(SnapshotCreatorExternalReferences) {
    2739             :   DisableAlwaysOpt();
    2740           5 :   DisableEmbeddedBlobRefcounting();
    2741             :   v8::StartupData blob;
    2742             :   {
    2743          10 :     v8::SnapshotCreator creator(original_external_references);
    2744           5 :     v8::Isolate* isolate = creator.GetIsolate();
    2745             :     {
    2746          10 :       v8::HandleScope handle_scope(isolate);
    2747           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2748             :       v8::Context::Scope context_scope(context);
    2749             :       v8::Local<v8::FunctionTemplate> callback =
    2750           5 :           v8::FunctionTemplate::New(isolate, SerializedCallback);
    2751             :       v8::Local<v8::Value> function =
    2752           5 :           callback->GetFunction(context).ToLocalChecked();
    2753          20 :       CHECK(context->Global()->Set(context, v8_str("f"), function).FromJust());
    2754             : 
    2755          25 :       CHECK(context->Global()
    2756             :                 ->Set(context, v8_str("one_byte"),
    2757             :                       v8::String::NewExternalOneByte(
    2758             :                           isolate, &serializable_one_byte_resource)
    2759             :                           .ToLocalChecked())
    2760             :                 .FromJust());
    2761          25 :       CHECK(context->Global()
    2762             :                 ->Set(context, v8_str("two_byte"),
    2763             :                       v8::String::NewExternalTwoByte(
    2764             :                           isolate, &serializable_two_byte_resource)
    2765             :                           .ToLocalChecked())
    2766             :                 .FromJust());
    2767             : 
    2768           5 :       ExpectInt32("f()", 42);
    2769           5 :       ExpectString("one_byte", "one_byte");
    2770           5 :       ExpectString("two_byte", "two_byte");
    2771           5 :       creator.SetDefaultContext(context);
    2772             :     }
    2773             :     blob =
    2774           5 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    2775             :   }
    2776             : 
    2777           5 :   CHECK_EQ(1, serializable_one_byte_resource.dispose_count());
    2778           5 :   CHECK_EQ(1, serializable_two_byte_resource.dispose_count());
    2779             : 
    2780             :   // Deserialize with the original external reference.
    2781             :   {
    2782             :     v8::Isolate::CreateParams params;
    2783           5 :     params.snapshot_blob = &blob;
    2784           5 :     params.array_buffer_allocator = CcTest::array_buffer_allocator();
    2785           5 :     params.external_references = original_external_references;
    2786             :     // Test-appropriate equivalent of v8::Isolate::New.
    2787           5 :     v8::Isolate* isolate = TestSerializer::NewIsolate(params);
    2788             :     {
    2789             :       v8::Isolate::Scope isolate_scope(isolate);
    2790          10 :       v8::HandleScope handle_scope(isolate);
    2791           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2792             :       v8::Context::Scope context_scope(context);
    2793           5 :       ExpectInt32("f()", 42);
    2794           5 :       ExpectString("one_byte", "one_byte");
    2795           5 :       ExpectString("two_byte", "two_byte");
    2796           5 :       CHECK(CompileRun("one_byte").As<v8::String>()->IsExternalOneByte());
    2797           5 :       CHECK(CompileRun("two_byte").As<v8::String>()->IsExternal());
    2798             :     }
    2799           5 :     isolate->Dispose();
    2800             :   }
    2801             : 
    2802           5 :   CHECK_EQ(2, serializable_one_byte_resource.dispose_count());
    2803           5 :   CHECK_EQ(2, serializable_two_byte_resource.dispose_count());
    2804             : 
    2805             :   // Deserialize with some other external reference.
    2806             :   {
    2807             :     v8::Isolate::CreateParams params;
    2808           5 :     params.snapshot_blob = &blob;
    2809           5 :     params.array_buffer_allocator = CcTest::array_buffer_allocator();
    2810           5 :     params.external_references = replaced_external_references;
    2811             :     // Test-appropriate equivalent of v8::Isolate::New.
    2812           5 :     v8::Isolate* isolate = TestSerializer::NewIsolate(params);
    2813             :     {
    2814             :       v8::Isolate::Scope isolate_scope(isolate);
    2815          10 :       v8::HandleScope handle_scope(isolate);
    2816           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2817             :       v8::Context::Scope context_scope(context);
    2818           5 :       ExpectInt32("f()", 1337);
    2819             :     }
    2820           5 :     isolate->Dispose();
    2821             :   }
    2822             : 
    2823           5 :   CHECK_EQ(3, serializable_one_byte_resource.dispose_count());
    2824           5 :   CHECK_EQ(3, serializable_two_byte_resource.dispose_count());
    2825             : 
    2826           5 :   delete[] blob.data;
    2827           5 :   FreeCurrentEmbeddedBlob();
    2828           5 : }
    2829             : 
    2830       26644 : UNINITIALIZED_TEST(SnapshotCreatorShortExternalReferences) {
    2831             :   DisableAlwaysOpt();
    2832           5 :   DisableEmbeddedBlobRefcounting();
    2833             :   v8::StartupData blob;
    2834             :   {
    2835          10 :     v8::SnapshotCreator creator(original_external_references);
    2836           5 :     v8::Isolate* isolate = creator.GetIsolate();
    2837             :     {
    2838          10 :       v8::HandleScope handle_scope(isolate);
    2839           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2840             :       v8::Context::Scope context_scope(context);
    2841             :       v8::Local<v8::FunctionTemplate> callback =
    2842           5 :           v8::FunctionTemplate::New(isolate, SerializedCallback);
    2843             :       v8::Local<v8::Value> function =
    2844           5 :           callback->GetFunction(context).ToLocalChecked();
    2845          20 :       CHECK(context->Global()->Set(context, v8_str("f"), function).FromJust());
    2846           5 :       ExpectInt32("f()", 42);
    2847           5 :       creator.SetDefaultContext(context);
    2848             :     }
    2849             :     blob =
    2850           5 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    2851             :   }
    2852             : 
    2853             :   // Deserialize with an incomplete list of external references.
    2854             :   {
    2855             :     v8::Isolate::CreateParams params;
    2856           5 :     params.snapshot_blob = &blob;
    2857           5 :     params.array_buffer_allocator = CcTest::array_buffer_allocator();
    2858           5 :     params.external_references = short_external_references;
    2859             :     // Test-appropriate equivalent of v8::Isolate::New.
    2860           5 :     v8::Isolate* isolate = TestSerializer::NewIsolate(params);
    2861             :     {
    2862             :       v8::Isolate::Scope isolate_scope(isolate);
    2863          10 :       v8::HandleScope handle_scope(isolate);
    2864           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2865             :       v8::Context::Scope context_scope(context);
    2866           5 :       ExpectInt32("f()", 1337);
    2867             :     }
    2868           5 :     isolate->Dispose();
    2869             :   }
    2870           5 :   delete[] blob.data;
    2871           5 :   FreeCurrentEmbeddedBlob();
    2872           5 : }
    2873             : 
    2874           5 : v8::StartupData CreateSnapshotWithDefaultAndCustom() {
    2875          10 :   v8::SnapshotCreator creator(original_external_references);
    2876           5 :   v8::Isolate* isolate = creator.GetIsolate();
    2877             :   {
    2878          10 :     v8::HandleScope handle_scope(isolate);
    2879             :     {
    2880           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2881             :       v8::Context::Scope context_scope(context);
    2882             :       CompileRun("function f() { return 41; }");
    2883           5 :       creator.SetDefaultContext(context);
    2884           5 :       ExpectInt32("f()", 41);
    2885             :     }
    2886             :     {
    2887           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2888             :       v8::Context::Scope context_scope(context);
    2889             :       v8::Local<v8::FunctionTemplate> function_template =
    2890           5 :           v8::FunctionTemplate::New(isolate, SerializedCallback);
    2891             :       v8::Local<v8::Value> function =
    2892           5 :           function_template->GetFunction(context).ToLocalChecked();
    2893          20 :       CHECK(context->Global()->Set(context, v8_str("f"), function).FromJust());
    2894             :       v8::Local<v8::ObjectTemplate> object_template =
    2895           5 :           v8::ObjectTemplate::New(isolate);
    2896           5 :       object_template->SetAccessor(v8_str("x"), AccessorForSerialization);
    2897             :       v8::Local<v8::Object> object =
    2898           5 :           object_template->NewInstance(context).ToLocalChecked();
    2899          20 :       CHECK(context->Global()->Set(context, v8_str("o"), object).FromJust());
    2900           5 :       ExpectInt32("f()", 42);
    2901           5 :       ExpectInt32("o.x", 2017);
    2902           5 :       creator.AddContext(context);
    2903             :     }
    2904             :   }
    2905          10 :   return creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    2906             : }
    2907             : 
    2908       26644 : UNINITIALIZED_TEST(SnapshotCreatorNoExternalReferencesDefault) {
    2909             :   DisableAlwaysOpt();
    2910           5 :   DisableEmbeddedBlobRefcounting();
    2911           5 :   v8::StartupData blob = CreateSnapshotWithDefaultAndCustom();
    2912             : 
    2913             :   // Deserialize with an incomplete list of external references.
    2914             :   {
    2915             :     v8::Isolate::CreateParams params;
    2916           5 :     params.snapshot_blob = &blob;
    2917           5 :     params.array_buffer_allocator = CcTest::array_buffer_allocator();
    2918             :     params.external_references = nullptr;
    2919             :     // Test-appropriate equivalent of v8::Isolate::New.
    2920           5 :     v8::Isolate* isolate = TestSerializer::NewIsolate(params);
    2921             :     {
    2922             :       v8::Isolate::Scope isolate_scope(isolate);
    2923          10 :       v8::HandleScope handle_scope(isolate);
    2924           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2925             :       v8::Context::Scope context_scope(context);
    2926           5 :       ExpectInt32("f()", 41);
    2927             :     }
    2928           5 :     isolate->Dispose();
    2929             :   }
    2930           5 :   delete[] blob.data;
    2931           5 :   FreeCurrentEmbeddedBlob();
    2932           5 : }
    2933             : 
    2934           5 : v8::StartupData CreateCustomSnapshotWithPreparseDataAndNoOuterScope() {
    2935          10 :   v8::SnapshotCreator creator;
    2936           5 :   v8::Isolate* isolate = creator.GetIsolate();
    2937             :   {
    2938          10 :     v8::HandleScope handle_scope(isolate);
    2939             :     {
    2940           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2941             :       v8::Context::Scope context_scope(context);
    2942             :       CompileRun(
    2943             :           "var foo = {\n"
    2944             :           "  // This function is not top-level, but also has no outer scope.\n"
    2945             :           "  bar: function(){\n"
    2946             :           "    // Add an inner function so that the outer one has preparse\n"
    2947             :           "    // scope data.\n"
    2948             :           "    return function(){}\n"
    2949             :           "  }\n"
    2950             :           "};\n");
    2951           5 :       creator.SetDefaultContext(context);
    2952             :     }
    2953             :   }
    2954          10 :   return creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    2955             : }
    2956             : 
    2957       26644 : UNINITIALIZED_TEST(SnapshotCreatorPreparseDataAndNoOuterScope) {
    2958             :   DisableAlwaysOpt();
    2959           5 :   DisableEmbeddedBlobRefcounting();
    2960           5 :   v8::StartupData blob = CreateCustomSnapshotWithPreparseDataAndNoOuterScope();
    2961             : 
    2962             :   // Deserialize with an incomplete list of external references.
    2963             :   {
    2964             :     v8::Isolate::CreateParams params;
    2965           5 :     params.snapshot_blob = &blob;
    2966           5 :     params.array_buffer_allocator = CcTest::array_buffer_allocator();
    2967             :     // Test-appropriate equivalent of v8::Isolate::New.
    2968           5 :     v8::Isolate* isolate = TestSerializer::NewIsolate(params);
    2969             :     {
    2970             :       v8::Isolate::Scope isolate_scope(isolate);
    2971          10 :       v8::HandleScope handle_scope(isolate);
    2972           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2973             :       v8::Context::Scope context_scope(context);
    2974             :     }
    2975           5 :     isolate->Dispose();
    2976             :   }
    2977           5 :   delete[] blob.data;
    2978           5 :   FreeCurrentEmbeddedBlob();
    2979           5 : }
    2980             : 
    2981           5 : v8::StartupData CreateCustomSnapshotArrayJoinWithKeep() {
    2982          10 :   v8::SnapshotCreator creator;
    2983           5 :   v8::Isolate* isolate = creator.GetIsolate();
    2984             :   {
    2985          10 :     v8::HandleScope handle_scope(isolate);
    2986             :     {
    2987           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2988             :       v8::Context::Scope context_scope(context);
    2989             :       CompileRun(
    2990             :           "[].join('');\n"
    2991             :           "function g() { return String([1,2,3]); }\n");
    2992           5 :       ExpectString("g()", "1,2,3");
    2993           5 :       creator.SetDefaultContext(context);
    2994             :     }
    2995             :   }
    2996          10 :   return creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kKeep);
    2997             : }
    2998             : 
    2999       26644 : UNINITIALIZED_TEST(SnapshotCreatorArrayJoinWithKeep) {
    3000             :   DisableAlwaysOpt();
    3001           5 :   DisableEmbeddedBlobRefcounting();
    3002           5 :   v8::StartupData blob = CreateCustomSnapshotArrayJoinWithKeep();
    3003             : 
    3004             :   // Deserialize with an incomplete list of external references.
    3005             :   {
    3006             :     v8::Isolate::CreateParams params;
    3007           5 :     params.snapshot_blob = &blob;
    3008           5 :     params.array_buffer_allocator = CcTest::array_buffer_allocator();
    3009             :     // Test-appropriate equivalent of v8::Isolate::New.
    3010           5 :     v8::Isolate* isolate = TestSerializer::NewIsolate(params);
    3011             :     {
    3012             :       v8::Isolate::Scope isolate_scope(isolate);
    3013          10 :       v8::HandleScope handle_scope(isolate);
    3014           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    3015             :       v8::Context::Scope context_scope(context);
    3016           5 :       ExpectString("g()", "1,2,3");
    3017             :     }
    3018           5 :     isolate->Dispose();
    3019             :   }
    3020           5 :   delete[] blob.data;
    3021           5 :   FreeCurrentEmbeddedBlob();
    3022           5 : }
    3023             : 
    3024       26639 : TEST(SnapshotCreatorNoExternalReferencesCustomFail1) {
    3025             :   DisableAlwaysOpt();
    3026           0 :   v8::StartupData blob = CreateSnapshotWithDefaultAndCustom();
    3027             : 
    3028             :   // Deserialize with an incomplete list of external references.
    3029             :   {
    3030             :     v8::Isolate::CreateParams params;
    3031           0 :     params.snapshot_blob = &blob;
    3032           0 :     params.array_buffer_allocator = CcTest::array_buffer_allocator();
    3033             :     params.external_references = nullptr;
    3034             :     // Test-appropriate equivalent of v8::Isolate::New.
    3035           0 :     v8::Isolate* isolate = TestSerializer::NewIsolate(params);
    3036             :     {
    3037             :       v8::Isolate::Scope isolate_scope(isolate);
    3038           0 :       v8::HandleScope handle_scope(isolate);
    3039             :       v8::Local<v8::Context> context =
    3040           0 :           v8::Context::FromSnapshot(isolate, 0).ToLocalChecked();
    3041             :       v8::Context::Scope context_scope(context);
    3042           0 :       ExpectInt32("f()", 42);
    3043             :     }
    3044           0 :     isolate->Dispose();
    3045             :   }
    3046           0 :   delete[] blob.data;
    3047           0 : }
    3048             : 
    3049       26639 : TEST(SnapshotCreatorNoExternalReferencesCustomFail2) {
    3050             :   DisableAlwaysOpt();
    3051           0 :   v8::StartupData blob = CreateSnapshotWithDefaultAndCustom();
    3052             : 
    3053             :   // Deserialize with an incomplete list of external references.
    3054             :   {
    3055             :     v8::Isolate::CreateParams params;
    3056           0 :     params.snapshot_blob = &blob;
    3057           0 :     params.array_buffer_allocator = CcTest::array_buffer_allocator();
    3058             :     params.external_references = nullptr;
    3059             :     // Test-appropriate equivalent of v8::Isolate::New.
    3060           0 :     v8::Isolate* isolate = TestSerializer::NewIsolate(params);
    3061             :     {
    3062             :       v8::Isolate::Scope isolate_scope(isolate);
    3063           0 :       v8::HandleScope handle_scope(isolate);
    3064             :       v8::Local<v8::Context> context =
    3065           0 :           v8::Context::FromSnapshot(isolate, 0).ToLocalChecked();
    3066             :       v8::Context::Scope context_scope(context);
    3067           0 :       ExpectInt32("o.x", 2017);
    3068             :     }
    3069           0 :     isolate->Dispose();
    3070             :   }
    3071           0 :   delete[] blob.data;
    3072           0 : }
    3073             : 
    3074       26639 : UNINITIALIZED_TEST(SnapshotCreatorUnknownExternalReferences) {
    3075             :   DisableAlwaysOpt();
    3076           0 :   DisableEmbeddedBlobRefcounting();
    3077           0 :   v8::SnapshotCreator creator;
    3078           0 :   v8::Isolate* isolate = creator.GetIsolate();
    3079             :   {
    3080           0 :     v8::HandleScope handle_scope(isolate);
    3081           0 :     v8::Local<v8::Context> context = v8::Context::New(isolate);
    3082             :     v8::Context::Scope context_scope(context);
    3083             : 
    3084             :     v8::Local<v8::FunctionTemplate> callback =
    3085           0 :         v8::FunctionTemplate::New(isolate, SerializedCallback);
    3086             :     v8::Local<v8::Value> function =
    3087           0 :         callback->GetFunction(context).ToLocalChecked();
    3088           0 :     CHECK(context->Global()->Set(context, v8_str("f"), function).FromJust());
    3089           0 :     ExpectInt32("f()", 42);
    3090             : 
    3091           0 :     creator.SetDefaultContext(context);
    3092             :   }
    3093             :   v8::StartupData blob =
    3094           0 :       creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    3095             : 
    3096           0 :   delete[] blob.data;
    3097           0 :   FreeCurrentEmbeddedBlob();
    3098           0 : }
    3099             : 
    3100       26644 : UNINITIALIZED_TEST(SnapshotCreatorTemplates) {
    3101             :   DisableAlwaysOpt();
    3102           5 :   DisableEmbeddedBlobRefcounting();
    3103             :   v8::StartupData blob;
    3104             : 
    3105             :   {
    3106           5 :     InternalFieldData* a1 = new InternalFieldData{11};
    3107           5 :     InternalFieldData* b1 = new InternalFieldData{20};
    3108           5 :     InternalFieldData* c1 = new InternalFieldData{30};
    3109             : 
    3110          10 :     v8::SnapshotCreator creator(original_external_references);
    3111           5 :     v8::Isolate* isolate = creator.GetIsolate();
    3112             :     {
    3113          10 :       v8::HandleScope handle_scope(isolate);
    3114             :       v8::ExtensionConfiguration* no_extension = nullptr;
    3115             :       v8::Local<v8::ObjectTemplate> global_template =
    3116           5 :           v8::ObjectTemplate::New(isolate);
    3117             :       v8::Local<v8::External> external =
    3118           5 :           v8::External::New(isolate, &serialized_static_field);
    3119             :       v8::Local<v8::FunctionTemplate> callback =
    3120           5 :           v8::FunctionTemplate::New(isolate, SerializedCallback, external);
    3121          10 :       global_template->Set(v8_str("f"), callback);
    3122             :       v8::Local<v8::Context> context =
    3123           5 :           v8::Context::New(isolate, no_extension, global_template);
    3124           5 :       creator.SetDefaultContext(context);
    3125           5 :       context = v8::Context::New(isolate, no_extension, global_template);
    3126             :       v8::Local<v8::ObjectTemplate> object_template =
    3127           5 :           v8::ObjectTemplate::New(isolate);
    3128           5 :       object_template->SetInternalFieldCount(3);
    3129             : 
    3130             :       v8::Context::Scope context_scope(context);
    3131           5 :       ExpectInt32("f()", 42);
    3132           5 :       CHECK_EQ(315, serialized_static_field);
    3133             : 
    3134             :       v8::Local<v8::Object> a =
    3135           5 :           object_template->NewInstance(context).ToLocalChecked();
    3136             :       v8::Local<v8::Object> b =
    3137           5 :           object_template->NewInstance(context).ToLocalChecked();
    3138             :       v8::Local<v8::Object> c =
    3139           5 :           object_template->NewInstance(context).ToLocalChecked();
    3140             :       v8::Local<v8::External> null_external =
    3141           5 :           v8::External::New(isolate, nullptr);
    3142             :       v8::Local<v8::External> field_external =
    3143           5 :           v8::External::New(isolate, &serialized_static_field);
    3144             : 
    3145           5 :       a->SetInternalField(0, b);
    3146           5 :       b->SetInternalField(0, c);
    3147             : 
    3148           5 :       a->SetAlignedPointerInInternalField(1, a1);
    3149           5 :       b->SetAlignedPointerInInternalField(1, b1);
    3150           5 :       c->SetAlignedPointerInInternalField(1, c1);
    3151             : 
    3152           5 :       a->SetInternalField(2, null_external);
    3153           5 :       b->SetInternalField(2, field_external);
    3154           5 :       c->SetInternalField(2, v8_num(35));
    3155          20 :       CHECK(context->Global()->Set(context, v8_str("a"), a).FromJust());
    3156             : 
    3157           5 :       CHECK_EQ(0u,
    3158             :                creator.AddContext(context, v8::SerializeInternalFieldsCallback(
    3159             :                                                SerializeInternalFields,
    3160             :                                                reinterpret_cast<void*>(2000))));
    3161           5 :       CHECK_EQ(0u, creator.AddTemplate(callback));
    3162           5 :       CHECK_EQ(1u, creator.AddTemplate(global_template));
    3163             :     }
    3164             :     blob =
    3165           5 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    3166             : 
    3167           5 :     delete a1;
    3168           5 :     delete b1;
    3169           5 :     delete c1;
    3170             :   }
    3171             : 
    3172             :   {
    3173             :     v8::Isolate::CreateParams params;
    3174           5 :     params.snapshot_blob = &blob;
    3175           5 :     params.array_buffer_allocator = CcTest::array_buffer_allocator();
    3176           5 :     params.external_references = original_external_references;
    3177             :     // Test-appropriate equivalent of v8::Isolate::New.
    3178           5 :     v8::Isolate* isolate = TestSerializer::NewIsolate(params);
    3179             :     {
    3180             :       v8::Isolate::Scope isolate_scope(isolate);
    3181             :       {
    3182             :         // Create a new context without a new object template.
    3183          10 :         v8::HandleScope handle_scope(isolate);
    3184             :         v8::Local<v8::Context> context =
    3185           5 :             v8::Context::FromSnapshot(
    3186             :                 isolate, 0,
    3187             :                 v8::DeserializeInternalFieldsCallback(
    3188           5 :                     DeserializeInternalFields, reinterpret_cast<void*>(2017)))
    3189             :                 .ToLocalChecked();
    3190             :         v8::Context::Scope context_scope(context);
    3191           5 :         ExpectInt32("f()", 42);
    3192           5 :         CHECK_EQ(316, serialized_static_field);
    3193             : 
    3194             :         // Retrieve the snapshotted object template.
    3195             :         v8::Local<v8::ObjectTemplate> obj_template =
    3196           5 :             v8::ObjectTemplate::FromSnapshot(isolate, 1).ToLocalChecked();
    3197           5 :         CHECK(!obj_template.IsEmpty());
    3198             :         v8::Local<v8::Object> object =
    3199           5 :             obj_template->NewInstance(context).ToLocalChecked();
    3200          20 :         CHECK(context->Global()->Set(context, v8_str("o"), object).FromJust());
    3201           5 :         ExpectInt32("o.f()", 42);
    3202           5 :         CHECK_EQ(317, serialized_static_field);
    3203             :         // Check that it instantiates to the same prototype.
    3204             :         ExpectTrue("o.f.prototype === f.prototype");
    3205             : 
    3206             :         // Retrieve the snapshotted function template.
    3207             :         v8::Local<v8::FunctionTemplate> fun_template =
    3208           5 :             v8::FunctionTemplate::FromSnapshot(isolate, 0).ToLocalChecked();
    3209           5 :         CHECK(!fun_template.IsEmpty());
    3210             :         v8::Local<v8::Function> fun =
    3211           5 :             fun_template->GetFunction(context).ToLocalChecked();
    3212          20 :         CHECK(context->Global()->Set(context, v8_str("g"), fun).FromJust());
    3213           5 :         ExpectInt32("g()", 42);
    3214             :         // Check that it instantiates to the same prototype.
    3215             :         ExpectTrue("g.prototype === f.prototype");
    3216             : 
    3217             :         // Retrieve embedder fields.
    3218          10 :         v8::Local<v8::Object> a = context->Global()
    3219          15 :                                       ->Get(context, v8_str("a"))
    3220             :                                       .ToLocalChecked()
    3221           5 :                                       ->ToObject(context)
    3222             :                                       .ToLocalChecked();
    3223             :         v8::Local<v8::Object> b =
    3224           5 :             a->GetInternalField(0)->ToObject(context).ToLocalChecked();
    3225             :         v8::Local<v8::Object> c =
    3226           5 :             b->GetInternalField(0)->ToObject(context).ToLocalChecked();
    3227             : 
    3228             :         InternalFieldData* a1 = reinterpret_cast<InternalFieldData*>(
    3229             :             a->GetAlignedPointerFromInternalField(1));
    3230             :         v8::Local<v8::Value> a2 = a->GetInternalField(2);
    3231             : 
    3232             :         InternalFieldData* b1 = reinterpret_cast<InternalFieldData*>(
    3233             :             b->GetAlignedPointerFromInternalField(1));
    3234             :         v8::Local<v8::Value> b2 = b->GetInternalField(2);
    3235             : 
    3236             :         v8::Local<v8::Value> c0 = c->GetInternalField(0);
    3237             :         InternalFieldData* c1 = reinterpret_cast<InternalFieldData*>(
    3238             :             c->GetAlignedPointerFromInternalField(1));
    3239             :         v8::Local<v8::Value> c2 = c->GetInternalField(2);
    3240             : 
    3241           5 :         CHECK(c0->IsUndefined());
    3242             : 
    3243           5 :         CHECK_EQ(11u, a1->data);
    3244           5 :         CHECK_EQ(20u, b1->data);
    3245           5 :         CHECK_EQ(30u, c1->data);
    3246             : 
    3247           5 :         CHECK(a2->IsExternal());
    3248           5 :         CHECK_NULL(v8::Local<v8::External>::Cast(a2)->Value());
    3249           5 :         CHECK(b2->IsExternal());
    3250           5 :         CHECK_EQ(static_cast<void*>(&serialized_static_field),
    3251             :                  v8::Local<v8::External>::Cast(b2)->Value());
    3252          10 :         CHECK(c2->IsInt32() && c2->Int32Value(context).FromJust() == 35);
    3253             : 
    3254             :         // Accessing out of bound returns empty MaybeHandle.
    3255          10 :         CHECK(v8::ObjectTemplate::FromSnapshot(isolate, 2).IsEmpty());
    3256          10 :         CHECK(v8::FunctionTemplate::FromSnapshot(isolate, 2).IsEmpty());
    3257          10 :         CHECK(v8::Context::FromSnapshot(isolate, 1).IsEmpty());
    3258             : 
    3259          20 :         for (auto data : deserialized_data) delete data;
    3260             :         deserialized_data.clear();
    3261             :       }
    3262             :     }
    3263           5 :     isolate->Dispose();
    3264             :   }
    3265           5 :   delete[] blob.data;
    3266           5 :   FreeCurrentEmbeddedBlob();
    3267           5 : }
    3268             : 
    3269       26644 : UNINITIALIZED_TEST(SnapshotCreatorAddData) {
    3270             :   DisableAlwaysOpt();
    3271           5 :   DisableEmbeddedBlobRefcounting();
    3272             :   v8::StartupData blob;
    3273             : 
    3274             :   {
    3275          10 :     v8::SnapshotCreator creator;
    3276           5 :     v8::Isolate* isolate = creator.GetIsolate();
    3277             :     v8::Eternal<v8::Value> eternal_number;
    3278             :     v8::Persistent<v8::Value> persistent_number_1;
    3279             :     v8::Persistent<v8::Value> persistent_number_2;
    3280             :     v8::Persistent<v8::Context> persistent_context;
    3281             :     {
    3282          10 :       v8::HandleScope handle_scope(isolate);
    3283             : 
    3284           5 :       eternal_number.Set(isolate, v8_num(2017));
    3285          10 :       persistent_number_1.Reset(isolate, v8_num(2018));
    3286          10 :       persistent_number_2.Reset(isolate, v8_num(2019));
    3287             : 
    3288           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    3289           5 :       CHECK_EQ(0u, creator.AddData(context, persistent_number_2.Get(isolate)));
    3290           5 :       creator.SetDefaultContext(context);
    3291           5 :       context = v8::Context::New(isolate);
    3292             :       persistent_context.Reset(isolate, context);
    3293             : 
    3294             :       v8::Context::Scope context_scope(context);
    3295             : 
    3296             :       v8::Local<v8::Object> object = CompileRun("({ p: 12 })").As<v8::Object>();
    3297             : 
    3298             :       v8::Local<v8::ObjectTemplate> object_template =
    3299           5 :           v8::ObjectTemplate::New(isolate);
    3300           5 :       object_template->SetInternalFieldCount(3);
    3301             : 
    3302             :       v8::Local<v8::Private> private_symbol =
    3303           5 :           v8::Private::ForApi(isolate, v8_str("private_symbol"));
    3304             : 
    3305             :       v8::Local<v8::Signature> signature =
    3306           5 :         v8::Signature::New(isolate, v8::FunctionTemplate::New(isolate));
    3307             : 
    3308             :       v8::Local<v8::AccessorSignature> accessor_signature =
    3309             :            v8::AccessorSignature::New(isolate,
    3310           5 :                                       v8::FunctionTemplate::New(isolate));
    3311             : 
    3312           5 :       CHECK_EQ(0u, creator.AddData(context, object));
    3313          10 :       CHECK_EQ(1u, creator.AddData(context, v8_str("context-dependent")));
    3314           5 :       CHECK_EQ(2u, creator.AddData(context, persistent_number_1.Get(isolate)));
    3315           5 :       CHECK_EQ(3u, creator.AddData(context, object_template));
    3316           5 :       CHECK_EQ(4u, creator.AddData(context, persistent_context.Get(isolate)));
    3317           5 :       creator.AddContext(context);
    3318             : 
    3319          10 :       CHECK_EQ(0u, creator.AddData(v8_str("context-independent")));
    3320           5 :       CHECK_EQ(1u, creator.AddData(eternal_number.Get(isolate)));
    3321           5 :       CHECK_EQ(2u, creator.AddData(object_template));
    3322          10 :       CHECK_EQ(3u, creator.AddData(v8::FunctionTemplate::New(isolate)));
    3323           5 :       CHECK_EQ(4u, creator.AddData(private_symbol));
    3324           5 :       CHECK_EQ(5u, creator.AddData(signature));
    3325           5 :       CHECK_EQ(6u, creator.AddData(accessor_signature));
    3326             :     }
    3327             : 
    3328             :     blob =
    3329           5 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    3330             :   }
    3331             : 
    3332             :   {
    3333             :     v8::Isolate::CreateParams params;
    3334           5 :     params.snapshot_blob = &blob;
    3335           5 :     params.array_buffer_allocator = CcTest::array_buffer_allocator();
    3336             :     // Test-appropriate equivalent of v8::Isolate::New.
    3337           5 :     v8::Isolate* isolate = TestSerializer::NewIsolate(params);
    3338             :     {
    3339             :       v8::Isolate::Scope isolate_scope(isolate);
    3340          10 :       v8::HandleScope handle_scope(isolate);
    3341             :       v8::Local<v8::Context> context =
    3342          10 :           v8::Context::FromSnapshot(isolate, 0).ToLocalChecked();
    3343             : 
    3344             :       // Check serialized data on the context.
    3345             :       v8::Local<v8::Object> object =
    3346             :           context->GetDataFromSnapshotOnce<v8::Object>(0).ToLocalChecked();
    3347           5 :       CHECK(context->GetDataFromSnapshotOnce<v8::Object>(0).IsEmpty());
    3348          20 :       CHECK_EQ(12, object->Get(context, v8_str("p"))
    3349             :                        .ToLocalChecked()
    3350             :                        ->Int32Value(context)
    3351             :                        .FromJust());
    3352             : 
    3353             :       v8::Local<v8::String> string =
    3354             :           context->GetDataFromSnapshotOnce<v8::String>(1).ToLocalChecked();
    3355           5 :       CHECK(context->GetDataFromSnapshotOnce<v8::String>(1).IsEmpty());
    3356          15 :       CHECK(string->Equals(context, v8_str("context-dependent")).FromJust());
    3357             : 
    3358             :       v8::Local<v8::Number> number =
    3359             :           context->GetDataFromSnapshotOnce<v8::Number>(2).ToLocalChecked();
    3360           5 :       CHECK(context->GetDataFromSnapshotOnce<v8::Number>(2).IsEmpty());
    3361          10 :       CHECK_EQ(2018, number->Int32Value(context).FromJust());
    3362             : 
    3363             :       v8::Local<v8::ObjectTemplate> templ =
    3364             :           context->GetDataFromSnapshotOnce<v8::ObjectTemplate>(3)
    3365             :               .ToLocalChecked();
    3366           5 :       CHECK(context->GetDataFromSnapshotOnce<v8::ObjectTemplate>(3).IsEmpty());
    3367           5 :       CHECK_EQ(3, templ->InternalFieldCount());
    3368             : 
    3369             :       v8::Local<v8::Context> serialized_context =
    3370             :           context->GetDataFromSnapshotOnce<v8::Context>(4).ToLocalChecked();
    3371           5 :       CHECK(context->GetDataFromSnapshotOnce<v8::Context>(4).IsEmpty());
    3372           5 :       CHECK_EQ(*v8::Utils::OpenHandle(*serialized_context),
    3373             :                *v8::Utils::OpenHandle(*context));
    3374             : 
    3375           5 :       CHECK(context->GetDataFromSnapshotOnce<v8::Value>(5).IsEmpty());
    3376             : 
    3377             :       // Check serialized data on the isolate.
    3378             :       string = isolate->GetDataFromSnapshotOnce<v8::String>(0).ToLocalChecked();
    3379           5 :       CHECK(context->GetDataFromSnapshotOnce<v8::String>(0).IsEmpty());
    3380          15 :       CHECK(string->Equals(context, v8_str("context-independent")).FromJust());
    3381             : 
    3382             :       number = isolate->GetDataFromSnapshotOnce<v8::Number>(1).ToLocalChecked();
    3383           5 :       CHECK(isolate->GetDataFromSnapshotOnce<v8::Number>(1).IsEmpty());
    3384          10 :       CHECK_EQ(2017, number->Int32Value(context).FromJust());
    3385             : 
    3386             :       templ = isolate->GetDataFromSnapshotOnce<v8::ObjectTemplate>(2)
    3387             :                   .ToLocalChecked();
    3388           5 :       CHECK(isolate->GetDataFromSnapshotOnce<v8::ObjectTemplate>(2).IsEmpty());
    3389           5 :       CHECK_EQ(3, templ->InternalFieldCount());
    3390             : 
    3391             :       isolate->GetDataFromSnapshotOnce<v8::FunctionTemplate>(3)
    3392             :           .ToLocalChecked();
    3393           5 :       CHECK(
    3394             :           isolate->GetDataFromSnapshotOnce<v8::FunctionTemplate>(3).IsEmpty());
    3395             : 
    3396             :       isolate->GetDataFromSnapshotOnce<v8::Private>(4).ToLocalChecked();
    3397           5 :       CHECK(
    3398             :           isolate->GetDataFromSnapshotOnce<v8::Private>(4).IsEmpty());
    3399             : 
    3400             :       isolate->GetDataFromSnapshotOnce<v8::Signature>(5).ToLocalChecked();
    3401           5 :       CHECK(isolate->GetDataFromSnapshotOnce<v8::Signature>(5).IsEmpty());
    3402             : 
    3403             :       isolate->GetDataFromSnapshotOnce<v8::AccessorSignature>(6)
    3404             :           .ToLocalChecked();
    3405           5 :       CHECK(
    3406             :           isolate->GetDataFromSnapshotOnce<v8::AccessorSignature>(6).IsEmpty());
    3407             : 
    3408           5 :       CHECK(isolate->GetDataFromSnapshotOnce<v8::Value>(7).IsEmpty());
    3409             :     }
    3410           5 :     isolate->Dispose();
    3411             :   }
    3412             :   {
    3413          10 :     SnapshotCreator creator(nullptr, &blob);
    3414           5 :     v8::Isolate* isolate = creator.GetIsolate();
    3415             :     {
    3416             :       // Adding data to a snapshot replaces the list of existing data.
    3417          10 :       v8::HandleScope hscope(isolate);
    3418           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    3419           5 :       creator.SetDefaultContext(context);
    3420          10 :       context = v8::Context::FromSnapshot(isolate, 0).ToLocalChecked();
    3421             :       v8::Local<v8::String> string =
    3422             :           context->GetDataFromSnapshotOnce<v8::String>(1).ToLocalChecked();
    3423           5 :       CHECK(context->GetDataFromSnapshotOnce<v8::String>(1).IsEmpty());
    3424          15 :       CHECK(string->Equals(context, v8_str("context-dependent")).FromJust());
    3425             :       v8::Local<v8::Number> number =
    3426             :           isolate->GetDataFromSnapshotOnce<v8::Number>(1).ToLocalChecked();
    3427           5 :       CHECK(isolate->GetDataFromSnapshotOnce<v8::Number>(1).IsEmpty());
    3428          10 :       CHECK_EQ(2017, number->Int32Value(context).FromJust());
    3429             : 
    3430          10 :       CHECK_EQ(0u, creator.AddData(context, v8_num(2016)));
    3431           5 :       CHECK_EQ(0u, creator.AddContext(context));
    3432          10 :       CHECK_EQ(0u, creator.AddData(v8_str("stuff")));
    3433             :     }
    3434           5 :     delete[] blob.data;
    3435             :     blob =
    3436           5 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    3437             :   }
    3438             :   {
    3439             :     v8::Isolate::CreateParams params;
    3440           5 :     params.snapshot_blob = &blob;
    3441           5 :     params.array_buffer_allocator = CcTest::array_buffer_allocator();
    3442             :     // Test-appropriate equivalent of v8::Isolate::New.
    3443           5 :     v8::Isolate* isolate = TestSerializer::NewIsolate(params);
    3444             :     {
    3445             :       v8::Isolate::Scope isolate_scope(isolate);
    3446          10 :       v8::HandleScope handle_scope(isolate);
    3447             : 
    3448             :       // Context where we did not re-add data no longer has data.
    3449           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    3450           5 :       CHECK(context->GetDataFromSnapshotOnce<v8::Object>(0).IsEmpty());
    3451             : 
    3452             :       // Context where we re-added data has completely new ones.
    3453          10 :       context = v8::Context::FromSnapshot(isolate, 0).ToLocalChecked();
    3454             :       v8::Local<v8::Value> value =
    3455             :           context->GetDataFromSnapshotOnce<v8::Value>(0).ToLocalChecked();
    3456          10 :       CHECK_EQ(2016, value->Int32Value(context).FromJust());
    3457           5 :       CHECK(context->GetDataFromSnapshotOnce<v8::Value>(1).IsEmpty());
    3458             : 
    3459             :       // Ditto for the isolate.
    3460             :       v8::Local<v8::String> string =
    3461             :           isolate->GetDataFromSnapshotOnce<v8::String>(0).ToLocalChecked();
    3462          15 :       CHECK(string->Equals(context, v8_str("stuff")).FromJust());
    3463           5 :       CHECK(context->GetDataFromSnapshotOnce<v8::String>(1).IsEmpty());
    3464             :     }
    3465           5 :     isolate->Dispose();
    3466             :   }
    3467           5 :   delete[] blob.data;
    3468           5 :   FreeCurrentEmbeddedBlob();
    3469           5 : }
    3470             : 
    3471       26639 : TEST(SnapshotCreatorUnknownHandles) {
    3472             :   DisableAlwaysOpt();
    3473             :   v8::StartupData blob;
    3474             : 
    3475             :   {
    3476           0 :     v8::SnapshotCreator creator;
    3477           0 :     v8::Isolate* isolate = creator.GetIsolate();
    3478             :     v8::Eternal<v8::Value> eternal_number;
    3479             :     v8::Persistent<v8::Value> persistent_number;
    3480             :     {
    3481           0 :       v8::HandleScope handle_scope(isolate);
    3482             : 
    3483           0 :       eternal_number.Set(isolate, v8_num(2017));
    3484           0 :       persistent_number.Reset(isolate, v8_num(2018));
    3485             : 
    3486           0 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    3487           0 :       creator.SetDefaultContext(context);
    3488             :     }
    3489             : 
    3490             :     blob =
    3491           0 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    3492             :   }
    3493           0 :   delete[] blob.data;
    3494           0 : }
    3495             : 
    3496       26644 : UNINITIALIZED_TEST(SnapshotCreatorIncludeGlobalProxy) {
    3497             :   DisableAlwaysOpt();
    3498           5 :   DisableEmbeddedBlobRefcounting();
    3499             :   v8::StartupData blob;
    3500             : 
    3501             :   {
    3502          10 :     v8::SnapshotCreator creator(original_external_references);
    3503           5 :     v8::Isolate* isolate = creator.GetIsolate();
    3504             :     {
    3505             :       // Set default context. This context implicitly does *not* serialize
    3506             :       // the global proxy, and upon deserialization one has to be created
    3507             :       // in the bootstrapper from the global object template.
    3508             :       // Side effects from extensions are persisted though.
    3509          10 :       v8::HandleScope handle_scope(isolate);
    3510             :       v8::Local<v8::ObjectTemplate> global_template =
    3511           5 :           v8::ObjectTemplate::New(isolate);
    3512             :       v8::Local<v8::FunctionTemplate> callback =
    3513           5 :           v8::FunctionTemplate::New(isolate, SerializedCallback);
    3514          10 :       global_template->Set(v8_str("f"), callback);
    3515           5 :       global_template->SetHandler(v8::NamedPropertyHandlerConfiguration(
    3516           5 :           NamedPropertyGetterForSerialization));
    3517             :       v8::Local<v8::Context> context =
    3518           5 :           v8::Context::New(isolate, nullptr, global_template);
    3519             :       v8::Context::Scope context_scope(context);
    3520             :       CompileRun(
    3521             :           "function h() { return 13; };"
    3522             :           "function i() { return 14; };"
    3523             :           "var o = { p: 7 };");
    3524           5 :       ExpectInt32("f()", 42);
    3525           5 :       ExpectInt32("h()", 13);
    3526           5 :       ExpectInt32("o.p", 7);
    3527           5 :       ExpectInt32("x", 2016);
    3528           5 :       creator.SetDefaultContext(context);
    3529             :     }
    3530             :     {
    3531             :       // Add additional context. This context implicitly *does* serialize
    3532             :       // the global proxy, and upon deserialization one has to be created
    3533             :       // in the bootstrapper from the global object template.
    3534             :       // Side effects from extensions are persisted.
    3535          10 :       v8::HandleScope handle_scope(isolate);
    3536             :       v8::Local<v8::ObjectTemplate> global_template =
    3537           5 :           v8::ObjectTemplate::New(isolate);
    3538             :       v8::Local<v8::FunctionTemplate> callback =
    3539           5 :           v8::FunctionTemplate::New(isolate, SerializedCallback);
    3540           5 :       global_template->SetInternalFieldCount(3);
    3541          10 :       global_template->Set(v8_str("f"), callback);
    3542           5 :       global_template->SetHandler(v8::NamedPropertyHandlerConfiguration(
    3543           5 :           NamedPropertyGetterForSerialization));
    3544           5 :       global_template->SetAccessor(v8_str("y"), AccessorForSerialization);
    3545             :       v8::Local<v8::Private> priv =
    3546           5 :           v8::Private::ForApi(isolate, v8_str("cached"));
    3547          10 :       global_template->SetAccessorProperty(
    3548             :           v8_str("cached"),
    3549             :           v8::FunctionTemplate::NewWithCache(isolate, SerializedCallback, priv,
    3550           5 :                                              v8::Local<v8::Value>()));
    3551             :       v8::Local<v8::Context> context =
    3552           5 :           v8::Context::New(isolate, nullptr, global_template);
    3553             :       v8::Context::Scope context_scope(context);
    3554             : 
    3555          20 :       CHECK(context->Global()
    3556             :                 ->SetPrivate(context, priv, v8_str("cached string"))
    3557             :                 .FromJust());
    3558             :       v8::Local<v8::Private> hidden =
    3559           5 :           v8::Private::ForApi(isolate, v8_str("hidden"));
    3560          20 :       CHECK(context->Global()
    3561             :                 ->SetPrivate(context, hidden, v8_str("hidden string"))
    3562             :                 .FromJust());
    3563             : 
    3564           5 :       ExpectInt32("f()", 42);
    3565           5 :       ExpectInt32("x", 2016);
    3566           5 :       ExpectInt32("y", 2017);
    3567          25 :       CHECK(v8_str("hidden string")
    3568             :                 ->Equals(context, context->Global()
    3569             :                                       ->GetPrivate(context, hidden)
    3570             :                                       .ToLocalChecked())
    3571             :                 .FromJust());
    3572             : 
    3573           5 :       CHECK_EQ(0u,
    3574             :                creator.AddContext(context, v8::SerializeInternalFieldsCallback(
    3575             :                                                SerializeInternalFields,
    3576             :                                                reinterpret_cast<void*>(2016))));
    3577             :     }
    3578             :     blob =
    3579           5 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    3580             :   }
    3581             : 
    3582             :   {
    3583             :     v8::Isolate::CreateParams params;
    3584           5 :     params.snapshot_blob = &blob;
    3585           5 :     params.array_buffer_allocator = CcTest::array_buffer_allocator();
    3586           5 :     params.external_references = original_external_references;
    3587             :     // Test-appropriate equivalent of v8::Isolate::New.
    3588           5 :     v8::Isolate* isolate = TestSerializer::NewIsolate(params);
    3589             :     {
    3590             :       v8::Isolate::Scope isolate_scope(isolate);
    3591             :       // We can introduce new extensions, which could override functions already
    3592             :       // in the snapshot.
    3593             :       auto extension =
    3594             :           base::make_unique<v8::Extension>("new extension",
    3595             :                                            "function i() { return 24; }"
    3596             :                                            "function j() { return 25; }"
    3597             :                                            "try {"
    3598             :                                            "  if (o.p == 7) o.p++;"
    3599           5 :                                            "} catch {}");
    3600             :       extension->set_auto_enable(true);
    3601          10 :       v8::RegisterExtension(std::move(extension));
    3602             :       {
    3603             :         // Create a new context from default context snapshot. This will
    3604             :         // create a new global object from a new global object template
    3605             :         // without the interceptor.
    3606          10 :         v8::HandleScope handle_scope(isolate);
    3607           5 :         v8::Local<v8::Context> context = v8::Context::New(isolate);
    3608             :         v8::Context::Scope context_scope(context);
    3609           5 :         ExpectInt32("f()", 42);
    3610           5 :         ExpectInt32("h()", 13);
    3611           5 :         ExpectInt32("i()", 24);
    3612           5 :         ExpectInt32("j()", 25);
    3613           5 :         ExpectInt32("o.p", 8);
    3614          10 :         v8::TryCatch try_catch(isolate);
    3615           5 :         CHECK(CompileRun("x").IsEmpty());
    3616           5 :         CHECK(try_catch.HasCaught());
    3617             :       }
    3618             :       {
    3619             :         // Create a new context from first additional context snapshot. This
    3620             :         // will use the global object from the snapshot, including interceptor.
    3621          10 :         v8::HandleScope handle_scope(isolate);
    3622             :         v8::Local<v8::Context> context =
    3623           5 :             v8::Context::FromSnapshot(
    3624             :                 isolate, 0,
    3625             :                 v8::DeserializeInternalFieldsCallback(
    3626           5 :                     DeserializeInternalFields, reinterpret_cast<void*>(2017)))
    3627             :                 .ToLocalChecked();
    3628             : 
    3629             :         {
    3630             :           v8::Context::Scope context_scope(context);
    3631           5 :           ExpectInt32("f()", 42);
    3632           5 :           ExpectInt32("i()", 24);
    3633           5 :           ExpectInt32("j()", 25);
    3634           5 :           ExpectInt32("x", 2016);
    3635             :           v8::Local<v8::Private> hidden =
    3636           5 :               v8::Private::ForApi(isolate, v8_str("hidden"));
    3637          25 :           CHECK(v8_str("hidden string")
    3638             :                     ->Equals(context, context->Global()
    3639             :                                           ->GetPrivate(context, hidden)
    3640             :                                           .ToLocalChecked())
    3641             :                     .FromJust());
    3642           5 :           ExpectString("cached", "cached string");
    3643             :         }
    3644             : 
    3645           5 :         v8::Local<v8::Object> global = context->Global();
    3646           5 :         CHECK_EQ(3, global->InternalFieldCount());
    3647           5 :         context->DetachGlobal();
    3648             : 
    3649             :         // New context, but reuse global proxy.
    3650             :         v8::ExtensionConfiguration* no_extensions = nullptr;
    3651             :         v8::Local<v8::Context> context2 =
    3652           5 :             v8::Context::FromSnapshot(
    3653             :                 isolate, 0,
    3654             :                 v8::DeserializeInternalFieldsCallback(
    3655             :                     DeserializeInternalFields, reinterpret_cast<void*>(2017)),
    3656           5 :                 no_extensions, global)
    3657             :                 .ToLocalChecked();
    3658             :         {
    3659             :           v8::Context::Scope context_scope(context2);
    3660           5 :           ExpectInt32("f()", 42);
    3661           5 :           ExpectInt32("i()", 24);
    3662           5 :           ExpectInt32("j()", 25);
    3663           5 :           ExpectInt32("x", 2016);
    3664             :           v8::Local<v8::Private> hidden =
    3665           5 :               v8::Private::ForApi(isolate, v8_str("hidden"));
    3666          25 :           CHECK(v8_str("hidden string")
    3667             :                     ->Equals(context2, context2->Global()
    3668             :                                            ->GetPrivate(context2, hidden)
    3669             :                                            .ToLocalChecked())
    3670             :                     .FromJust());
    3671             : 
    3672             :           // Set cached accessor property again.
    3673             :           v8::Local<v8::Private> priv =
    3674           5 :               v8::Private::ForApi(isolate, v8_str("cached"));
    3675          20 :           CHECK(context2->Global()
    3676             :                     ->SetPrivate(context2, priv, v8_str("cached string 1"))
    3677             :                     .FromJust());
    3678           5 :           ExpectString("cached", "cached string 1");
    3679             :         }
    3680             : 
    3681          15 :         CHECK(context2->Global()->Equals(context2, global).FromJust());
    3682             :       }
    3683             :     }
    3684           5 :     isolate->Dispose();
    3685             :   }
    3686           5 :   delete[] blob.data;
    3687           5 :   FreeCurrentEmbeddedBlob();
    3688           5 : }
    3689             : 
    3690       26644 : UNINITIALIZED_TEST(ReinitializeHashSeedNotRehashable) {
    3691             :   DisableAlwaysOpt();
    3692           5 :   i::FLAG_rehash_snapshot = true;
    3693           5 :   i::FLAG_hash_seed = 42;
    3694           5 :   i::FLAG_allow_natives_syntax = true;
    3695           5 :   DisableEmbeddedBlobRefcounting();
    3696             :   v8::StartupData blob;
    3697             :   {
    3698          10 :     v8::SnapshotCreator creator;
    3699           5 :     v8::Isolate* isolate = creator.GetIsolate();
    3700             :     {
    3701          10 :       v8::HandleScope handle_scope(isolate);
    3702           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    3703             :       v8::Context::Scope context_scope(context);
    3704             :       // Create an object with an ordered hash table.
    3705             :       CompileRun(
    3706             :           "var m = new Map();"
    3707             :           "m.set('a', 1);"
    3708             :           "m.set('b', 2);");
    3709           5 :       ExpectInt32("m.get('b')", 2);
    3710           5 :       creator.SetDefaultContext(context);
    3711             :     }
    3712             :     blob =
    3713           5 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    3714             :   }
    3715             : 
    3716           5 :   i::FLAG_hash_seed = 1337;
    3717             :   v8::Isolate::CreateParams create_params;
    3718           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    3719           5 :   create_params.snapshot_blob = &blob;
    3720           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
    3721             :   {
    3722             :     // Check that no rehashing has been performed.
    3723           5 :     CHECK_EQ(static_cast<uint64_t>(42),
    3724             :              HashSeed(reinterpret_cast<i::Isolate*>(isolate)));
    3725             :     v8::Isolate::Scope isolate_scope(isolate);
    3726          10 :     v8::HandleScope handle_scope(isolate);
    3727           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate);
    3728           5 :     CHECK(!context.IsEmpty());
    3729             :     v8::Context::Scope context_scope(context);
    3730           5 :     ExpectInt32("m.get('b')", 2);
    3731             :   }
    3732           5 :   isolate->Dispose();
    3733           5 :   delete[] blob.data;
    3734           5 :   FreeCurrentEmbeddedBlob();
    3735           5 : }
    3736             : 
    3737       26644 : UNINITIALIZED_TEST(ReinitializeHashSeedRehashable) {
    3738             :   DisableAlwaysOpt();
    3739           5 :   i::FLAG_rehash_snapshot = true;
    3740           5 :   i::FLAG_hash_seed = 42;
    3741           5 :   i::FLAG_allow_natives_syntax = true;
    3742           5 :   DisableEmbeddedBlobRefcounting();
    3743             :   v8::StartupData blob;
    3744             :   {
    3745          10 :     v8::SnapshotCreator creator;
    3746           5 :     v8::Isolate* isolate = creator.GetIsolate();
    3747             :     {
    3748          10 :       v8::HandleScope handle_scope(isolate);
    3749           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    3750             :       v8::Context::Scope context_scope(context);
    3751             :       // Create dictionary mode object.
    3752             :       CompileRun(
    3753             :           "var a = new Array(10000);"
    3754             :           "%NormalizeElements(a);"
    3755             :           "a[133] = 1;"
    3756             :           "a[177] = 2;"
    3757             :           "a[971] = 3;"
    3758             :           "a[7997] = 4;"
    3759             :           "a[2111] = 5;"
    3760             :           "var o = {};"
    3761             :           "%OptimizeObjectForAddingMultipleProperties(o, 3);"
    3762             :           "o.a = 1;"
    3763             :           "o.b = 2;"
    3764             :           "o.c = 3;"
    3765             :           "var p = { foo: 1 };"  // Test rehashing of transition arrays.
    3766             :           "p = JSON.parse('{\"foo\": {\"x\": 1}}');");
    3767             :       i::Handle<i::Object> i_a = v8::Utils::OpenHandle(*CompileRun("a"));
    3768             :       i::Handle<i::Object> i_o = v8::Utils::OpenHandle(*CompileRun("o"));
    3769           5 :       CHECK(i_a->IsJSArray());
    3770           5 :       CHECK(i_a->IsJSObject());
    3771           5 :       CHECK(!i::Handle<i::JSArray>::cast(i_a)->HasFastElements());
    3772           5 :       CHECK(!i::Handle<i::JSObject>::cast(i_o)->HasFastProperties());
    3773           5 :       ExpectInt32("a[2111]", 5);
    3774           5 :       ExpectInt32("o.c", 3);
    3775           5 :       creator.SetDefaultContext(context);
    3776             :     }
    3777             :     blob =
    3778           5 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    3779             :   }
    3780             : 
    3781           5 :   i::FLAG_hash_seed = 1337;
    3782             :   v8::Isolate::CreateParams create_params;
    3783           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    3784           5 :   create_params.snapshot_blob = &blob;
    3785           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
    3786             :   {
    3787             :     // Check that rehashing has been performed.
    3788           5 :     CHECK_EQ(static_cast<uint64_t>(1337),
    3789             :              HashSeed(reinterpret_cast<i::Isolate*>(isolate)));
    3790             :     v8::Isolate::Scope isolate_scope(isolate);
    3791          10 :     v8::HandleScope handle_scope(isolate);
    3792           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate);
    3793           5 :     CHECK(!context.IsEmpty());
    3794             :     v8::Context::Scope context_scope(context);
    3795             :     i::Handle<i::Object> i_a = v8::Utils::OpenHandle(*CompileRun("a"));
    3796             :     i::Handle<i::Object> i_o = v8::Utils::OpenHandle(*CompileRun("o"));
    3797           5 :     CHECK(i_a->IsJSArray());
    3798           5 :     CHECK(i_a->IsJSObject());
    3799           5 :     CHECK(!i::Handle<i::JSArray>::cast(i_a)->HasFastElements());
    3800           5 :     CHECK(!i::Handle<i::JSObject>::cast(i_o)->HasFastProperties());
    3801           5 :     ExpectInt32("a[2111]", 5);
    3802           5 :     ExpectInt32("o.c", 3);
    3803             :   }
    3804           5 :   isolate->Dispose();
    3805           5 :   delete[] blob.data;
    3806           5 :   FreeCurrentEmbeddedBlob();
    3807           5 : }
    3808             : 
    3809       26644 : UNINITIALIZED_TEST(SerializationStats) {
    3810           5 :   FLAG_profile_deserialization = true;
    3811           5 :   FLAG_always_opt = false;
    3812             :   v8::StartupData blob = CreateSnapshotDataBlob();
    3813           5 :   delete[] blob.data;
    3814             : 
    3815             :   // Track the embedded blob size as well.
    3816             :   {
    3817             :     int embedded_blob_size = 0;
    3818             :     if (FLAG_embedded_builtins) {
    3819             :       i::EmbeddedData d = i::EmbeddedData::FromBlob();
    3820           5 :       embedded_blob_size = static_cast<int>(d.size());
    3821             :     }
    3822           5 :     PrintF("Embedded blob is %d bytes\n", embedded_blob_size);
    3823             :   }
    3824             : 
    3825           5 :   FreeCurrentEmbeddedBlob();
    3826           5 : }
    3827             : 
    3828          10 : void CheckSFIsAreWeak(WeakFixedArray sfis, Isolate* isolate) {
    3829          10 :   CHECK_GT(sfis->length(), 0);
    3830             :   int no_of_weak = 0;
    3831          50 :   for (int i = 0; i < sfis->length(); ++i) {
    3832             :     MaybeObject maybe_object = sfis->Get(i);
    3833             :     HeapObject heap_object;
    3834          20 :     CHECK(maybe_object->IsWeakOrCleared() ||
    3835             :           (maybe_object->GetHeapObjectIfStrong(&heap_object) &&
    3836             :            heap_object->IsUndefined(isolate)));
    3837          20 :     if (maybe_object->IsWeak()) {
    3838          15 :       ++no_of_weak;
    3839             :     }
    3840             :   }
    3841          10 :   CHECK_GT(no_of_weak, 0);
    3842          10 : }
    3843             : 
    3844       26644 : UNINITIALIZED_TEST(WeakArraySerializationInSnapshot) {
    3845             :   const char* code = "var my_func = function() { }";
    3846             : 
    3847             :   DisableAlwaysOpt();
    3848           5 :   DisableEmbeddedBlobRefcounting();
    3849           5 :   i::FLAG_allow_natives_syntax = true;
    3850             :   v8::StartupData blob;
    3851             :   {
    3852          10 :     v8::SnapshotCreator creator;
    3853           5 :     v8::Isolate* isolate = creator.GetIsolate();
    3854             :     {
    3855          10 :       v8::HandleScope handle_scope(isolate);
    3856           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    3857             :       v8::Context::Scope context_scope(context);
    3858             : 
    3859             :       CompileRun(code);
    3860           5 :       creator.SetDefaultContext(
    3861             :           context, v8::SerializeInternalFieldsCallback(
    3862           5 :                        SerializeInternalFields, reinterpret_cast<void*>(2016)));
    3863             :     }
    3864             :     blob =
    3865           5 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    3866             :   }
    3867             : 
    3868             :   v8::Isolate::CreateParams create_params;
    3869           5 :   create_params.snapshot_blob = &blob;
    3870           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    3871           5 :   v8::Isolate* isolate = TestSerializer::NewIsolate(create_params);
    3872             :   {
    3873             :     v8::Isolate::Scope i_scope(isolate);
    3874          10 :     v8::HandleScope h_scope(isolate);
    3875             :     v8::Local<v8::Context> context = v8::Context::New(
    3876             :         isolate, nullptr, v8::MaybeLocal<v8::ObjectTemplate>(),
    3877             :         v8::MaybeLocal<v8::Value>(),
    3878             :         v8::DeserializeInternalFieldsCallback(DeserializeInternalFields,
    3879           5 :                                               reinterpret_cast<void*>(2017)));
    3880             :     v8::Context::Scope c_scope(context);
    3881             : 
    3882             :     v8::Local<v8::Value> x = CompileRun("my_func");
    3883           5 :     CHECK(x->IsFunction());
    3884             :     Handle<JSFunction> function =
    3885             :         Handle<JSFunction>::cast(v8::Utils::OpenHandle(*x));
    3886             : 
    3887             :     // Verify that the pointers in shared_function_infos are weak.
    3888             :     WeakFixedArray sfis =
    3889          10 :         Script::cast(function->shared()->script())->shared_function_infos();
    3890           5 :     CheckSFIsAreWeak(sfis, reinterpret_cast<i::Isolate*>(isolate));
    3891             :   }
    3892           5 :   isolate->Dispose();
    3893           5 :   delete[] blob.data;
    3894           5 :   FreeCurrentEmbeddedBlob();
    3895           5 : }
    3896             : 
    3897       26644 : TEST(WeakArraySerializationInCodeCache) {
    3898           5 :   LocalContext context;
    3899             :   Isolate* isolate = CcTest::i_isolate();
    3900           5 :   isolate->compilation_cache()->Disable();
    3901             : 
    3902          10 :   v8::HandleScope scope(CcTest::isolate());
    3903             : 
    3904             :   const char* source = "function foo() { }";
    3905             : 
    3906             :   Handle<String> src = isolate->factory()
    3907          10 :                            ->NewStringFromUtf8(CStrVector(source))
    3908           5 :                            .ToHandleChecked();
    3909           5 :   ScriptData* cache = nullptr;
    3910             : 
    3911             :   CompileScriptAndProduceCache(isolate, src, src, &cache,
    3912           5 :                                v8::ScriptCompiler::kNoCompileOptions);
    3913             : 
    3914             :   DisallowCompilation no_compile_expected(isolate);
    3915             :   Handle<SharedFunctionInfo> copy = CompileScript(
    3916           5 :       isolate, src, src, cache, v8::ScriptCompiler::kConsumeCodeCache);
    3917             : 
    3918             :   // Verify that the pointers in shared_function_infos are weak.
    3919          10 :   WeakFixedArray sfis = Script::cast(copy->script())->shared_function_infos();
    3920           5 :   CheckSFIsAreWeak(sfis, isolate);
    3921             : 
    3922          10 :   delete cache;
    3923           5 : }
    3924             : 
    3925       26644 : TEST(CachedCompileFunctionInContext) {
    3926             :   DisableAlwaysOpt();
    3927           5 :   LocalContext env;
    3928             :   Isolate* isolate = CcTest::i_isolate();
    3929           5 :   isolate->compilation_cache()->Disable();  // Disable same-isolate code cache.
    3930             : 
    3931          10 :   v8::HandleScope scope(CcTest::isolate());
    3932             : 
    3933           5 :   v8::Local<v8::String> source = v8_str("return x*x;");
    3934           5 :   v8::Local<v8::String> arg_str = v8_str("x");
    3935             :   ScriptCompiler::CachedData* cache;
    3936             :   {
    3937             :     v8::ScriptCompiler::Source script_source(source);
    3938             :     v8::Local<v8::Function> fun =
    3939           5 :         v8::ScriptCompiler::CompileFunctionInContext(
    3940             :             env.local(), &script_source, 1, &arg_str, 0, nullptr,
    3941             :             v8::ScriptCompiler::kEagerCompile)
    3942           5 :             .ToLocalChecked();
    3943           5 :     cache = v8::ScriptCompiler::CreateCodeCacheForFunction(fun);
    3944             :   }
    3945             : 
    3946             :   {
    3947             :     DisallowCompilation no_compile_expected(isolate);
    3948             :     v8::ScriptCompiler::Source script_source(source, cache);
    3949             :     v8::Local<v8::Function> fun =
    3950           5 :         v8::ScriptCompiler::CompileFunctionInContext(
    3951             :             env.local(), &script_source, 1, &arg_str, 0, nullptr,
    3952             :             v8::ScriptCompiler::kConsumeCodeCache)
    3953             :             .ToLocalChecked();
    3954           5 :     v8::Local<v8::Value> arg = v8_num(3);
    3955             :     v8::Local<v8::Value> result =
    3956          15 :         fun->Call(env.local(), v8::Undefined(CcTest::isolate()), 1, &arg)
    3957             :             .ToLocalChecked();
    3958          10 :     CHECK_EQ(9, result->Int32Value(env.local()).FromJust());
    3959             :   }
    3960           5 : }
    3961             : 
    3962       26644 : UNINITIALIZED_TEST(SnapshotCreatorAnonClassWithKeep) {
    3963             :   DisableAlwaysOpt();
    3964          10 :   v8::SnapshotCreator creator;
    3965           5 :   v8::Isolate* isolate = creator.GetIsolate();
    3966             :   {
    3967          10 :     v8::HandleScope handle_scope(isolate);
    3968             :     {
    3969           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    3970             :       v8::Context::Scope context_scope(context);
    3971             :       CompileRun(
    3972             :           "function Foo() { return class {}; } \n"
    3973             :           "class Bar extends Foo() {}\n"
    3974             :           "Foo()\n");
    3975           5 :       creator.SetDefaultContext(context);
    3976             :     }
    3977             :   }
    3978             :   v8::StartupData blob =
    3979           5 :       creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kKeep);
    3980             : 
    3981           5 :   delete[] blob.data;
    3982           5 : }
    3983             : 
    3984             : }  // namespace internal
    3985       79917 : }  // namespace v8

Generated by: LCOV version 1.10