LCOV - code coverage report
Current view: top level - test/cctest - test-serialize.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1652 1708 96.7 %
Date: 2019-03-21 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       26068 : UNINITIALIZED_TEST(StartupSerializerOnce) {
     322             :   DisableAlwaysOpt();
     323           5 :   TestStartupSerializerOnceImpl();
     324           5 : }
     325             : 
     326       26068 : UNINITIALIZED_TEST(StartupSerializerOnce1) {
     327             :   DisableAlwaysOpt();
     328           5 :   FLAG_serialization_chunk_size = 1;
     329           5 :   TestStartupSerializerOnceImpl();
     330           5 : }
     331             : 
     332       26068 : UNINITIALIZED_TEST(StartupSerializerOnce32) {
     333             :   DisableAlwaysOpt();
     334           5 :   FLAG_serialization_chunk_size = 32;
     335           5 :   TestStartupSerializerOnceImpl();
     336           5 : }
     337             : 
     338       26068 : UNINITIALIZED_TEST(StartupSerializerOnce1K) {
     339             :   DisableAlwaysOpt();
     340           5 :   FLAG_serialization_chunk_size = 1 * KB;
     341           5 :   TestStartupSerializerOnceImpl();
     342           5 : }
     343             : 
     344       26068 : UNINITIALIZED_TEST(StartupSerializerOnce4K) {
     345             :   DisableAlwaysOpt();
     346           5 :   FLAG_serialization_chunk_size = 4 * KB;
     347           5 :   TestStartupSerializerOnceImpl();
     348           5 : }
     349             : 
     350       26068 : UNINITIALIZED_TEST(StartupSerializerOnce32K) {
     351             :   DisableAlwaysOpt();
     352           5 :   FLAG_serialization_chunk_size = 32 * KB;
     353           5 :   TestStartupSerializerOnceImpl();
     354           5 : }
     355             : 
     356       26068 : 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       26068 : 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       26068 : 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       26068 : 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       26068 : 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       26068 : 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       26068 : 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       26068 : 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       26068 : 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       26068 : UNINITIALIZED_TEST(CustomSnapshotDataBlobWithIrregexpCodeKeepCode) {
     935             :   TestCustomSnapshotDataBlobWithIrregexpCode(
     936           5 :       v8::SnapshotCreator::FunctionCodeHandling::kKeep);
     937           5 : }
     938             : 
     939       26068 : UNINITIALIZED_TEST(CustomSnapshotDataBlobWithIrregexpCodeClearCode) {
     940             :   TestCustomSnapshotDataBlobWithIrregexpCode(
     941           5 :       v8::SnapshotCreator::FunctionCodeHandling::kClear);
     942           5 : }
     943             : 
     944       26068 : 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       26063 : 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       26068 : 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       26068 : 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       26068 : 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       26068 : 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       26068 : 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       26068 : 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       26068 : 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       26068 : 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       26068 : 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       26068 : 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       26068 : 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       26068 : 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       26068 : 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       26068 : 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       26068 : TEST(TestThatAlwaysSucceeds) {
    1570           5 : }
    1571             : 
    1572             : 
    1573       26063 : 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      845006 :   for (HeapObject obj = iterator.next(); !obj.is_null();
    1585             :        obj = iterator.next()) {
    1586      513552 :     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       26068 : TEST(CodeSerializerOnePlusOne) { TestCodeSerializerOnePlusOneImpl(); }
    1669             : 
    1670       26068 : 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       26068 : TEST(CodeSerializerOnePlusOne1) {
    1678           5 :   FLAG_serialization_chunk_size = 1;
    1679           5 :   TestCodeSerializerOnePlusOneImpl();
    1680           5 : }
    1681             : 
    1682       26068 : TEST(CodeSerializerOnePlusOne32) {
    1683           5 :   FLAG_serialization_chunk_size = 32;
    1684           5 :   TestCodeSerializerOnePlusOneImpl();
    1685           5 : }
    1686             : 
    1687       26068 : TEST(CodeSerializerOnePlusOne4K) {
    1688           5 :   FLAG_serialization_chunk_size = 4 * KB;
    1689           5 :   TestCodeSerializerOnePlusOneImpl();
    1690           5 : }
    1691             : 
    1692       26068 : 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       26068 : 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       26068 : 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       26068 : 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       26068 : 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       26068 : 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       52156 : class SerializerOneByteResource
    2051             :     : public v8::String::ExternalOneByteStringResource {
    2052             :  public:
    2053             :   SerializerOneByteResource(const char* data, size_t length)
    2054       26078 :       : 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       26068 :       : data_(AsciiToTwoByteString(data)), length_(length), dispose_count_(0) {}
    2071       52136 :   ~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       26068 : 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       26068 : 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       26068 : 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       26068 : 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       26068 : 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       26068 : 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          10 :     CHECK_EQ(bytecode->interrupt_budget(),
    2446             :              interpreter::Interpreter::InterruptBudget());
    2447           5 :     CHECK_EQ(bytecode->osr_loop_nesting_level(), 0);
    2448             : 
    2449             :     {
    2450             :       DisallowCompilation no_compile_expected(
    2451             :           reinterpret_cast<Isolate*>(isolate2));
    2452          10 :       v8::Local<v8::Value> result = script->BindToCurrentContext()
    2453          10 :                                         ->Run(isolate2->GetCurrentContext())
    2454             :                                         .ToLocalChecked();
    2455             :       v8::Local<v8::String> result_string =
    2456           5 :           result->ToString(isolate2->GetCurrentContext()).ToLocalChecked();
    2457          15 :       CHECK(
    2458             :           result_string->Equals(isolate2->GetCurrentContext(), v8_str("abcdef"))
    2459             :               .FromJust());
    2460             :     }
    2461             :   }
    2462           5 :   isolate2->Dispose();
    2463             : 
    2464             :   // Restore the flags.
    2465           5 :   FLAG_always_opt = prev_always_opt_value;
    2466           5 : }
    2467             : 
    2468       26068 : TEST(CodeSerializerFlagChange) {
    2469             :   const char* source = "function f() { return 'abc'; }; f() + 'def'";
    2470           5 :   v8::ScriptCompiler::CachedData* cache = CompileRunAndProduceCache(source);
    2471             : 
    2472             :   v8::Isolate::CreateParams create_params;
    2473           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    2474           5 :   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
    2475             : 
    2476           5 :   FLAG_allow_natives_syntax = true;  // Flag change should trigger cache reject.
    2477           5 :   FlagList::EnforceFlagImplications();
    2478             :   {
    2479             :     v8::Isolate::Scope iscope(isolate2);
    2480          10 :     v8::HandleScope scope(isolate2);
    2481           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate2);
    2482             :     v8::Context::Scope context_scope(context);
    2483             : 
    2484           5 :     v8::Local<v8::String> source_str = v8_str(source);
    2485           5 :     v8::ScriptOrigin origin(v8_str("test"));
    2486             :     v8::ScriptCompiler::Source source(source_str, origin, cache);
    2487           5 :     v8::ScriptCompiler::CompileUnboundScript(
    2488             :         isolate2, &source, v8::ScriptCompiler::kConsumeCodeCache)
    2489             :         .ToLocalChecked();
    2490           5 :     CHECK(cache->rejected);
    2491             :   }
    2492           5 :   isolate2->Dispose();
    2493           5 : }
    2494             : 
    2495       26068 : TEST(CodeSerializerBitFlip) {
    2496             :   const char* source = "function f() { return 'abc'; }; f() + 'def'";
    2497           5 :   v8::ScriptCompiler::CachedData* cache = CompileRunAndProduceCache(source);
    2498             : 
    2499             :   // Random bit flip.
    2500           5 :   const_cast<uint8_t*>(cache->data)[337] ^= 0x40;
    2501             : 
    2502             :   v8::Isolate::CreateParams create_params;
    2503           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    2504           5 :   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
    2505             :   {
    2506             :     v8::Isolate::Scope iscope(isolate2);
    2507          10 :     v8::HandleScope scope(isolate2);
    2508           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate2);
    2509             :     v8::Context::Scope context_scope(context);
    2510             : 
    2511           5 :     v8::Local<v8::String> source_str = v8_str(source);
    2512           5 :     v8::ScriptOrigin origin(v8_str("test"));
    2513             :     v8::ScriptCompiler::Source source(source_str, origin, cache);
    2514           5 :     v8::ScriptCompiler::CompileUnboundScript(
    2515             :         isolate2, &source, v8::ScriptCompiler::kConsumeCodeCache)
    2516             :         .ToLocalChecked();
    2517           5 :     CHECK(cache->rejected);
    2518             :   }
    2519           5 :   isolate2->Dispose();
    2520           5 : }
    2521             : 
    2522       26068 : TEST(CodeSerializerWithHarmonyScoping) {
    2523             :   const char* source1 = "'use strict'; let x = 'X'";
    2524             :   const char* source2 = "'use strict'; let y = 'Y'";
    2525             :   const char* source3 = "'use strict'; x + y";
    2526             : 
    2527             :   v8::ScriptCompiler::CachedData* cache;
    2528             : 
    2529             :   v8::Isolate::CreateParams create_params;
    2530           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    2531           5 :   v8::Isolate* isolate1 = v8::Isolate::New(create_params);
    2532             :   {
    2533             :     v8::Isolate::Scope iscope(isolate1);
    2534          10 :     v8::HandleScope scope(isolate1);
    2535           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate1);
    2536             :     v8::Context::Scope context_scope(context);
    2537             : 
    2538             :     CompileRun(source1);
    2539             :     CompileRun(source2);
    2540             : 
    2541           5 :     v8::Local<v8::String> source_str = v8_str(source3);
    2542           5 :     v8::ScriptOrigin origin(v8_str("test"));
    2543             :     v8::ScriptCompiler::Source source(source_str, origin);
    2544             :     v8::Local<v8::UnboundScript> script =
    2545           5 :         v8::ScriptCompiler::CompileUnboundScript(
    2546             :             isolate1, &source, v8::ScriptCompiler::kNoCompileOptions)
    2547             :             .ToLocalChecked();
    2548           5 :     cache = v8::ScriptCompiler::CreateCodeCache(script);
    2549           5 :     CHECK(cache);
    2550             : 
    2551          10 :     v8::Local<v8::Value> result = script->BindToCurrentContext()
    2552          10 :                                       ->Run(isolate1->GetCurrentContext())
    2553             :                                       .ToLocalChecked();
    2554             :     v8::Local<v8::String> result_str =
    2555           5 :         result->ToString(isolate1->GetCurrentContext()).ToLocalChecked();
    2556          15 :     CHECK(result_str->Equals(isolate1->GetCurrentContext(), v8_str("XY"))
    2557             :               .FromJust());
    2558             :   }
    2559           5 :   isolate1->Dispose();
    2560             : 
    2561           5 :   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
    2562             :   {
    2563             :     v8::Isolate::Scope iscope(isolate2);
    2564          10 :     v8::HandleScope scope(isolate2);
    2565           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate2);
    2566             :     v8::Context::Scope context_scope(context);
    2567             : 
    2568             :     // Reverse order of prior running scripts.
    2569             :     CompileRun(source2);
    2570             :     CompileRun(source1);
    2571             : 
    2572           5 :     v8::Local<v8::String> source_str = v8_str(source3);
    2573           5 :     v8::ScriptOrigin origin(v8_str("test"));
    2574             :     v8::ScriptCompiler::Source source(source_str, origin, cache);
    2575             :     v8::Local<v8::UnboundScript> script;
    2576             :     {
    2577             :       DisallowCompilation no_compile(reinterpret_cast<Isolate*>(isolate2));
    2578           5 :       script = v8::ScriptCompiler::CompileUnboundScript(
    2579             :                    isolate2, &source, v8::ScriptCompiler::kConsumeCodeCache)
    2580             :                    .ToLocalChecked();
    2581             :     }
    2582          10 :     v8::Local<v8::Value> result = script->BindToCurrentContext()
    2583          10 :                                       ->Run(isolate2->GetCurrentContext())
    2584             :                                       .ToLocalChecked();
    2585             :     v8::Local<v8::String> result_str =
    2586           5 :         result->ToString(isolate2->GetCurrentContext()).ToLocalChecked();
    2587          15 :     CHECK(result_str->Equals(isolate2->GetCurrentContext(), v8_str("XY"))
    2588             :               .FromJust());
    2589             :   }
    2590           5 :   isolate2->Dispose();
    2591           5 : }
    2592             : 
    2593       26068 : TEST(Regress503552) {
    2594           5 :   if (!FLAG_incremental_marking) return;
    2595             :   // Test that the code serializer can deal with weak cells that form a linked
    2596             :   // list during incremental marking.
    2597           5 :   CcTest::InitializeVM();
    2598             :   Isolate* isolate = CcTest::i_isolate();
    2599             : 
    2600             :   HandleScope scope(isolate);
    2601             :   Handle<String> source = isolate->factory()->NewStringFromAsciiChecked(
    2602           5 :       "function f() {} function g() {}");
    2603           5 :   ScriptData* script_data = nullptr;
    2604             :   Handle<SharedFunctionInfo> shared = CompileScriptAndProduceCache(
    2605             :       isolate, source, Handle<String>(), &script_data,
    2606           5 :       v8::ScriptCompiler::kNoCompileOptions);
    2607          10 :   delete script_data;
    2608             : 
    2609           5 :   heap::SimulateIncrementalMarking(isolate->heap());
    2610             : 
    2611             :   v8::ScriptCompiler::CachedData* cache_data =
    2612           5 :       CodeSerializer::Serialize(shared);
    2613           5 :   delete cache_data;
    2614             : }
    2615             : 
    2616       26068 : UNINITIALIZED_TEST(SnapshotCreatorMultipleContexts) {
    2617             :   DisableAlwaysOpt();
    2618           5 :   DisableEmbeddedBlobRefcounting();
    2619             :   v8::StartupData blob;
    2620             :   {
    2621          10 :     v8::SnapshotCreator creator;
    2622           5 :     v8::Isolate* isolate = creator.GetIsolate();
    2623             :     {
    2624          10 :       v8::HandleScope handle_scope(isolate);
    2625           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2626             :       v8::Context::Scope context_scope(context);
    2627             :       CompileRun("var f = function() { return 1; }");
    2628           5 :       creator.SetDefaultContext(context);
    2629             :     }
    2630             :     {
    2631          10 :       v8::HandleScope handle_scope(isolate);
    2632           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2633             :       v8::Context::Scope context_scope(context);
    2634             :       CompileRun("var f = function() { return 2; }");
    2635           5 :       CHECK_EQ(0u, creator.AddContext(context));
    2636             :     }
    2637             :     {
    2638          10 :       v8::HandleScope handle_scope(isolate);
    2639           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2640           5 :       CHECK_EQ(1u, creator.AddContext(context));
    2641             :     }
    2642             :     blob =
    2643           5 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    2644             :   }
    2645             : 
    2646             :   v8::Isolate::CreateParams params;
    2647           5 :   params.snapshot_blob = &blob;
    2648           5 :   params.array_buffer_allocator = CcTest::array_buffer_allocator();
    2649             :   // Test-appropriate equivalent of v8::Isolate::New.
    2650           5 :   v8::Isolate* isolate = TestSerializer::NewIsolate(params);
    2651             :   {
    2652             :     v8::Isolate::Scope isolate_scope(isolate);
    2653             :     {
    2654          10 :       v8::HandleScope handle_scope(isolate);
    2655           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2656             :       v8::Context::Scope context_scope(context);
    2657           5 :       ExpectInt32("f()", 1);
    2658             :     }
    2659             :     {
    2660          10 :       v8::HandleScope handle_scope(isolate);
    2661             :       v8::Local<v8::Context> context =
    2662          10 :           v8::Context::FromSnapshot(isolate, 0).ToLocalChecked();
    2663             :       v8::Context::Scope context_scope(context);
    2664           5 :       ExpectInt32("f()", 2);
    2665             :     }
    2666             :     {
    2667          10 :       v8::HandleScope handle_scope(isolate);
    2668             :       v8::Local<v8::Context> context =
    2669          10 :           v8::Context::FromSnapshot(isolate, 1).ToLocalChecked();
    2670             :       v8::Context::Scope context_scope(context);
    2671           5 :       ExpectUndefined("this.f");
    2672             :     }
    2673             :   }
    2674             : 
    2675           5 :   isolate->Dispose();
    2676           5 :   delete[] blob.data;
    2677           5 :   FreeCurrentEmbeddedBlob();
    2678           5 : }
    2679             : 
    2680             : static int serialized_static_field = 314;
    2681             : 
    2682          65 : static void SerializedCallback(
    2683             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    2684          65 :   if (args.Data()->IsExternal()) {
    2685          20 :     CHECK_EQ(args.Data().As<v8::External>()->Value(),
    2686             :              static_cast<void*>(&serialized_static_field));
    2687             :     int* value =
    2688          20 :         reinterpret_cast<int*>(args.Data().As<v8::External>()->Value());
    2689          20 :     (*value)++;
    2690             :   }
    2691          65 :   args.GetReturnValue().Set(v8_num(42));
    2692          65 : }
    2693             : 
    2694          10 : static void SerializedCallbackReplacement(
    2695             :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    2696          10 :   args.GetReturnValue().Set(v8_num(1337));
    2697          10 : }
    2698             : 
    2699         135 : static void NamedPropertyGetterForSerialization(
    2700             :     v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
    2701         540 :   if (name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("x"))
    2702             :           .FromJust()) {
    2703          20 :     info.GetReturnValue().Set(v8_num(2016));
    2704             :   }
    2705         135 : }
    2706             : 
    2707          10 : static void AccessorForSerialization(
    2708             :     v8::Local<v8::String> property,
    2709             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
    2710          10 :   info.GetReturnValue().Set(v8_num(2017));
    2711          10 : }
    2712             : 
    2713             : 
    2714       26063 : static SerializerOneByteResource serializable_one_byte_resource("one_byte", 8);
    2715       26063 : static SerializerTwoByteResource serializable_two_byte_resource("two_byte", 8);
    2716             : 
    2717             : intptr_t original_external_references[] = {
    2718             :     reinterpret_cast<intptr_t>(SerializedCallback),
    2719             :     reinterpret_cast<intptr_t>(&serialized_static_field),
    2720             :     reinterpret_cast<intptr_t>(&NamedPropertyGetterForSerialization),
    2721             :     reinterpret_cast<intptr_t>(&AccessorForSerialization),
    2722             :     reinterpret_cast<intptr_t>(&serialized_static_field),  // duplicate entry
    2723             :     reinterpret_cast<intptr_t>(&serializable_one_byte_resource),
    2724             :     reinterpret_cast<intptr_t>(&serializable_two_byte_resource),
    2725             :     0};
    2726             : 
    2727             : intptr_t replaced_external_references[] = {
    2728             :     reinterpret_cast<intptr_t>(SerializedCallbackReplacement),
    2729             :     reinterpret_cast<intptr_t>(&serialized_static_field),
    2730             :     reinterpret_cast<intptr_t>(&NamedPropertyGetterForSerialization),
    2731             :     reinterpret_cast<intptr_t>(&AccessorForSerialization),
    2732             :     reinterpret_cast<intptr_t>(&serialized_static_field),
    2733             :     reinterpret_cast<intptr_t>(&serializable_one_byte_resource),
    2734             :     reinterpret_cast<intptr_t>(&serializable_two_byte_resource),
    2735             :     0};
    2736             : 
    2737             : intptr_t short_external_references[] = {
    2738             :     reinterpret_cast<intptr_t>(SerializedCallbackReplacement), 0};
    2739             : 
    2740       26068 : UNINITIALIZED_TEST(SnapshotCreatorExternalReferences) {
    2741             :   DisableAlwaysOpt();
    2742           5 :   DisableEmbeddedBlobRefcounting();
    2743             :   v8::StartupData blob;
    2744             :   {
    2745          10 :     v8::SnapshotCreator creator(original_external_references);
    2746           5 :     v8::Isolate* isolate = creator.GetIsolate();
    2747             :     {
    2748          10 :       v8::HandleScope handle_scope(isolate);
    2749           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2750             :       v8::Context::Scope context_scope(context);
    2751             :       v8::Local<v8::FunctionTemplate> callback =
    2752           5 :           v8::FunctionTemplate::New(isolate, SerializedCallback);
    2753             :       v8::Local<v8::Value> function =
    2754           5 :           callback->GetFunction(context).ToLocalChecked();
    2755          20 :       CHECK(context->Global()->Set(context, v8_str("f"), function).FromJust());
    2756             : 
    2757          25 :       CHECK(context->Global()
    2758             :                 ->Set(context, v8_str("one_byte"),
    2759             :                       v8::String::NewExternalOneByte(
    2760             :                           isolate, &serializable_one_byte_resource)
    2761             :                           .ToLocalChecked())
    2762             :                 .FromJust());
    2763          25 :       CHECK(context->Global()
    2764             :                 ->Set(context, v8_str("two_byte"),
    2765             :                       v8::String::NewExternalTwoByte(
    2766             :                           isolate, &serializable_two_byte_resource)
    2767             :                           .ToLocalChecked())
    2768             :                 .FromJust());
    2769             : 
    2770           5 :       ExpectInt32("f()", 42);
    2771           5 :       ExpectString("one_byte", "one_byte");
    2772           5 :       ExpectString("two_byte", "two_byte");
    2773           5 :       creator.SetDefaultContext(context);
    2774             :     }
    2775             :     blob =
    2776           5 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    2777             :   }
    2778             : 
    2779           5 :   CHECK_EQ(1, serializable_one_byte_resource.dispose_count());
    2780           5 :   CHECK_EQ(1, serializable_two_byte_resource.dispose_count());
    2781             : 
    2782             :   // Deserialize with the original external reference.
    2783             :   {
    2784             :     v8::Isolate::CreateParams params;
    2785           5 :     params.snapshot_blob = &blob;
    2786           5 :     params.array_buffer_allocator = CcTest::array_buffer_allocator();
    2787           5 :     params.external_references = original_external_references;
    2788             :     // Test-appropriate equivalent of v8::Isolate::New.
    2789           5 :     v8::Isolate* isolate = TestSerializer::NewIsolate(params);
    2790             :     {
    2791             :       v8::Isolate::Scope isolate_scope(isolate);
    2792          10 :       v8::HandleScope handle_scope(isolate);
    2793           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2794             :       v8::Context::Scope context_scope(context);
    2795           5 :       ExpectInt32("f()", 42);
    2796           5 :       ExpectString("one_byte", "one_byte");
    2797           5 :       ExpectString("two_byte", "two_byte");
    2798           5 :       CHECK(CompileRun("one_byte").As<v8::String>()->IsExternalOneByte());
    2799           5 :       CHECK(CompileRun("two_byte").As<v8::String>()->IsExternal());
    2800             :     }
    2801           5 :     isolate->Dispose();
    2802             :   }
    2803             : 
    2804           5 :   CHECK_EQ(2, serializable_one_byte_resource.dispose_count());
    2805           5 :   CHECK_EQ(2, serializable_two_byte_resource.dispose_count());
    2806             : 
    2807             :   // Deserialize with some other external reference.
    2808             :   {
    2809             :     v8::Isolate::CreateParams params;
    2810           5 :     params.snapshot_blob = &blob;
    2811           5 :     params.array_buffer_allocator = CcTest::array_buffer_allocator();
    2812           5 :     params.external_references = replaced_external_references;
    2813             :     // Test-appropriate equivalent of v8::Isolate::New.
    2814           5 :     v8::Isolate* isolate = TestSerializer::NewIsolate(params);
    2815             :     {
    2816             :       v8::Isolate::Scope isolate_scope(isolate);
    2817          10 :       v8::HandleScope handle_scope(isolate);
    2818           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2819             :       v8::Context::Scope context_scope(context);
    2820           5 :       ExpectInt32("f()", 1337);
    2821             :     }
    2822           5 :     isolate->Dispose();
    2823             :   }
    2824             : 
    2825           5 :   CHECK_EQ(3, serializable_one_byte_resource.dispose_count());
    2826           5 :   CHECK_EQ(3, serializable_two_byte_resource.dispose_count());
    2827             : 
    2828           5 :   delete[] blob.data;
    2829           5 :   FreeCurrentEmbeddedBlob();
    2830           5 : }
    2831             : 
    2832       26068 : UNINITIALIZED_TEST(SnapshotCreatorShortExternalReferences) {
    2833             :   DisableAlwaysOpt();
    2834           5 :   DisableEmbeddedBlobRefcounting();
    2835             :   v8::StartupData blob;
    2836             :   {
    2837          10 :     v8::SnapshotCreator creator(original_external_references);
    2838           5 :     v8::Isolate* isolate = creator.GetIsolate();
    2839             :     {
    2840          10 :       v8::HandleScope handle_scope(isolate);
    2841           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2842             :       v8::Context::Scope context_scope(context);
    2843             :       v8::Local<v8::FunctionTemplate> callback =
    2844           5 :           v8::FunctionTemplate::New(isolate, SerializedCallback);
    2845             :       v8::Local<v8::Value> function =
    2846           5 :           callback->GetFunction(context).ToLocalChecked();
    2847          20 :       CHECK(context->Global()->Set(context, v8_str("f"), function).FromJust());
    2848           5 :       ExpectInt32("f()", 42);
    2849           5 :       creator.SetDefaultContext(context);
    2850             :     }
    2851             :     blob =
    2852           5 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    2853             :   }
    2854             : 
    2855             :   // Deserialize with an incomplete list of external references.
    2856             :   {
    2857             :     v8::Isolate::CreateParams params;
    2858           5 :     params.snapshot_blob = &blob;
    2859           5 :     params.array_buffer_allocator = CcTest::array_buffer_allocator();
    2860           5 :     params.external_references = short_external_references;
    2861             :     // Test-appropriate equivalent of v8::Isolate::New.
    2862           5 :     v8::Isolate* isolate = TestSerializer::NewIsolate(params);
    2863             :     {
    2864             :       v8::Isolate::Scope isolate_scope(isolate);
    2865          10 :       v8::HandleScope handle_scope(isolate);
    2866           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2867             :       v8::Context::Scope context_scope(context);
    2868           5 :       ExpectInt32("f()", 1337);
    2869             :     }
    2870           5 :     isolate->Dispose();
    2871             :   }
    2872           5 :   delete[] blob.data;
    2873           5 :   FreeCurrentEmbeddedBlob();
    2874           5 : }
    2875             : 
    2876           5 : v8::StartupData CreateSnapshotWithDefaultAndCustom() {
    2877          10 :   v8::SnapshotCreator creator(original_external_references);
    2878           5 :   v8::Isolate* isolate = creator.GetIsolate();
    2879             :   {
    2880          10 :     v8::HandleScope handle_scope(isolate);
    2881             :     {
    2882           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2883             :       v8::Context::Scope context_scope(context);
    2884             :       CompileRun("function f() { return 41; }");
    2885           5 :       creator.SetDefaultContext(context);
    2886           5 :       ExpectInt32("f()", 41);
    2887             :     }
    2888             :     {
    2889           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2890             :       v8::Context::Scope context_scope(context);
    2891             :       v8::Local<v8::FunctionTemplate> function_template =
    2892           5 :           v8::FunctionTemplate::New(isolate, SerializedCallback);
    2893             :       v8::Local<v8::Value> function =
    2894           5 :           function_template->GetFunction(context).ToLocalChecked();
    2895          20 :       CHECK(context->Global()->Set(context, v8_str("f"), function).FromJust());
    2896             :       v8::Local<v8::ObjectTemplate> object_template =
    2897           5 :           v8::ObjectTemplate::New(isolate);
    2898           5 :       object_template->SetAccessor(v8_str("x"), AccessorForSerialization);
    2899             :       v8::Local<v8::Object> object =
    2900           5 :           object_template->NewInstance(context).ToLocalChecked();
    2901          20 :       CHECK(context->Global()->Set(context, v8_str("o"), object).FromJust());
    2902           5 :       ExpectInt32("f()", 42);
    2903           5 :       ExpectInt32("o.x", 2017);
    2904           5 :       creator.AddContext(context);
    2905             :     }
    2906             :   }
    2907          10 :   return creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    2908             : }
    2909             : 
    2910       26068 : UNINITIALIZED_TEST(SnapshotCreatorNoExternalReferencesDefault) {
    2911             :   DisableAlwaysOpt();
    2912           5 :   DisableEmbeddedBlobRefcounting();
    2913           5 :   v8::StartupData blob = CreateSnapshotWithDefaultAndCustom();
    2914             : 
    2915             :   // Deserialize with an incomplete list of external references.
    2916             :   {
    2917             :     v8::Isolate::CreateParams params;
    2918           5 :     params.snapshot_blob = &blob;
    2919           5 :     params.array_buffer_allocator = CcTest::array_buffer_allocator();
    2920             :     params.external_references = nullptr;
    2921             :     // Test-appropriate equivalent of v8::Isolate::New.
    2922           5 :     v8::Isolate* isolate = TestSerializer::NewIsolate(params);
    2923             :     {
    2924             :       v8::Isolate::Scope isolate_scope(isolate);
    2925          10 :       v8::HandleScope handle_scope(isolate);
    2926           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2927             :       v8::Context::Scope context_scope(context);
    2928           5 :       ExpectInt32("f()", 41);
    2929             :     }
    2930           5 :     isolate->Dispose();
    2931             :   }
    2932           5 :   delete[] blob.data;
    2933           5 :   FreeCurrentEmbeddedBlob();
    2934           5 : }
    2935             : 
    2936           5 : v8::StartupData CreateCustomSnapshotWithPreparseDataAndNoOuterScope() {
    2937          10 :   v8::SnapshotCreator creator;
    2938           5 :   v8::Isolate* isolate = creator.GetIsolate();
    2939             :   {
    2940          10 :     v8::HandleScope handle_scope(isolate);
    2941             :     {
    2942           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2943             :       v8::Context::Scope context_scope(context);
    2944             :       CompileRun(
    2945             :           "var foo = {\n"
    2946             :           "  // This function is not top-level, but also has no outer scope.\n"
    2947             :           "  bar: function(){\n"
    2948             :           "    // Add an inner function so that the outer one has preparse\n"
    2949             :           "    // scope data.\n"
    2950             :           "    return function(){}\n"
    2951             :           "  }\n"
    2952             :           "};\n");
    2953           5 :       creator.SetDefaultContext(context);
    2954             :     }
    2955             :   }
    2956          10 :   return creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    2957             : }
    2958             : 
    2959       26068 : UNINITIALIZED_TEST(SnapshotCreatorPreparseDataAndNoOuterScope) {
    2960             :   DisableAlwaysOpt();
    2961           5 :   DisableEmbeddedBlobRefcounting();
    2962           5 :   v8::StartupData blob = CreateCustomSnapshotWithPreparseDataAndNoOuterScope();
    2963             : 
    2964             :   // Deserialize with an incomplete list of external references.
    2965             :   {
    2966             :     v8::Isolate::CreateParams params;
    2967           5 :     params.snapshot_blob = &blob;
    2968           5 :     params.array_buffer_allocator = CcTest::array_buffer_allocator();
    2969             :     // Test-appropriate equivalent of v8::Isolate::New.
    2970           5 :     v8::Isolate* isolate = TestSerializer::NewIsolate(params);
    2971             :     {
    2972             :       v8::Isolate::Scope isolate_scope(isolate);
    2973          10 :       v8::HandleScope handle_scope(isolate);
    2974           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2975             :       v8::Context::Scope context_scope(context);
    2976             :     }
    2977           5 :     isolate->Dispose();
    2978             :   }
    2979           5 :   delete[] blob.data;
    2980           5 :   FreeCurrentEmbeddedBlob();
    2981           5 : }
    2982             : 
    2983           5 : v8::StartupData CreateCustomSnapshotArrayJoinWithKeep() {
    2984          10 :   v8::SnapshotCreator creator;
    2985           5 :   v8::Isolate* isolate = creator.GetIsolate();
    2986             :   {
    2987          10 :     v8::HandleScope handle_scope(isolate);
    2988             :     {
    2989           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2990             :       v8::Context::Scope context_scope(context);
    2991             :       CompileRun(
    2992             :           "[].join('');\n"
    2993             :           "function g() { return String([1,2,3]); }\n");
    2994           5 :       ExpectString("g()", "1,2,3");
    2995           5 :       creator.SetDefaultContext(context);
    2996             :     }
    2997             :   }
    2998          10 :   return creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kKeep);
    2999             : }
    3000             : 
    3001       26068 : UNINITIALIZED_TEST(SnapshotCreatorArrayJoinWithKeep) {
    3002             :   DisableAlwaysOpt();
    3003           5 :   DisableEmbeddedBlobRefcounting();
    3004           5 :   v8::StartupData blob = CreateCustomSnapshotArrayJoinWithKeep();
    3005             : 
    3006             :   // Deserialize with an incomplete list of external references.
    3007             :   {
    3008             :     v8::Isolate::CreateParams params;
    3009           5 :     params.snapshot_blob = &blob;
    3010           5 :     params.array_buffer_allocator = CcTest::array_buffer_allocator();
    3011             :     // Test-appropriate equivalent of v8::Isolate::New.
    3012           5 :     v8::Isolate* isolate = TestSerializer::NewIsolate(params);
    3013             :     {
    3014             :       v8::Isolate::Scope isolate_scope(isolate);
    3015          10 :       v8::HandleScope handle_scope(isolate);
    3016           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    3017             :       v8::Context::Scope context_scope(context);
    3018           5 :       ExpectString("g()", "1,2,3");
    3019             :     }
    3020           5 :     isolate->Dispose();
    3021             :   }
    3022           5 :   delete[] blob.data;
    3023           5 :   FreeCurrentEmbeddedBlob();
    3024           5 : }
    3025             : 
    3026       26063 : TEST(SnapshotCreatorNoExternalReferencesCustomFail1) {
    3027             :   DisableAlwaysOpt();
    3028           0 :   v8::StartupData blob = CreateSnapshotWithDefaultAndCustom();
    3029             : 
    3030             :   // Deserialize with an incomplete list of external references.
    3031             :   {
    3032             :     v8::Isolate::CreateParams params;
    3033           0 :     params.snapshot_blob = &blob;
    3034           0 :     params.array_buffer_allocator = CcTest::array_buffer_allocator();
    3035             :     params.external_references = nullptr;
    3036             :     // Test-appropriate equivalent of v8::Isolate::New.
    3037           0 :     v8::Isolate* isolate = TestSerializer::NewIsolate(params);
    3038             :     {
    3039             :       v8::Isolate::Scope isolate_scope(isolate);
    3040           0 :       v8::HandleScope handle_scope(isolate);
    3041             :       v8::Local<v8::Context> context =
    3042           0 :           v8::Context::FromSnapshot(isolate, 0).ToLocalChecked();
    3043             :       v8::Context::Scope context_scope(context);
    3044           0 :       ExpectInt32("f()", 42);
    3045             :     }
    3046           0 :     isolate->Dispose();
    3047             :   }
    3048           0 :   delete[] blob.data;
    3049           0 : }
    3050             : 
    3051       26063 : TEST(SnapshotCreatorNoExternalReferencesCustomFail2) {
    3052             :   DisableAlwaysOpt();
    3053           0 :   v8::StartupData blob = CreateSnapshotWithDefaultAndCustom();
    3054             : 
    3055             :   // Deserialize with an incomplete list of external references.
    3056             :   {
    3057             :     v8::Isolate::CreateParams params;
    3058           0 :     params.snapshot_blob = &blob;
    3059           0 :     params.array_buffer_allocator = CcTest::array_buffer_allocator();
    3060             :     params.external_references = nullptr;
    3061             :     // Test-appropriate equivalent of v8::Isolate::New.
    3062           0 :     v8::Isolate* isolate = TestSerializer::NewIsolate(params);
    3063             :     {
    3064             :       v8::Isolate::Scope isolate_scope(isolate);
    3065           0 :       v8::HandleScope handle_scope(isolate);
    3066             :       v8::Local<v8::Context> context =
    3067           0 :           v8::Context::FromSnapshot(isolate, 0).ToLocalChecked();
    3068             :       v8::Context::Scope context_scope(context);
    3069           0 :       ExpectInt32("o.x", 2017);
    3070             :     }
    3071           0 :     isolate->Dispose();
    3072             :   }
    3073           0 :   delete[] blob.data;
    3074           0 : }
    3075             : 
    3076       26063 : UNINITIALIZED_TEST(SnapshotCreatorUnknownExternalReferences) {
    3077             :   DisableAlwaysOpt();
    3078           0 :   DisableEmbeddedBlobRefcounting();
    3079           0 :   v8::SnapshotCreator creator;
    3080           0 :   v8::Isolate* isolate = creator.GetIsolate();
    3081             :   {
    3082           0 :     v8::HandleScope handle_scope(isolate);
    3083           0 :     v8::Local<v8::Context> context = v8::Context::New(isolate);
    3084             :     v8::Context::Scope context_scope(context);
    3085             : 
    3086             :     v8::Local<v8::FunctionTemplate> callback =
    3087           0 :         v8::FunctionTemplate::New(isolate, SerializedCallback);
    3088             :     v8::Local<v8::Value> function =
    3089           0 :         callback->GetFunction(context).ToLocalChecked();
    3090           0 :     CHECK(context->Global()->Set(context, v8_str("f"), function).FromJust());
    3091           0 :     ExpectInt32("f()", 42);
    3092             : 
    3093           0 :     creator.SetDefaultContext(context);
    3094             :   }
    3095             :   v8::StartupData blob =
    3096           0 :       creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    3097             : 
    3098           0 :   delete[] blob.data;
    3099           0 :   FreeCurrentEmbeddedBlob();
    3100           0 : }
    3101             : 
    3102       26068 : UNINITIALIZED_TEST(SnapshotCreatorTemplates) {
    3103             :   DisableAlwaysOpt();
    3104           5 :   DisableEmbeddedBlobRefcounting();
    3105             :   v8::StartupData blob;
    3106             : 
    3107             :   {
    3108           5 :     InternalFieldData* a1 = new InternalFieldData{11};
    3109           5 :     InternalFieldData* b1 = new InternalFieldData{20};
    3110           5 :     InternalFieldData* c1 = new InternalFieldData{30};
    3111             : 
    3112          10 :     v8::SnapshotCreator creator(original_external_references);
    3113           5 :     v8::Isolate* isolate = creator.GetIsolate();
    3114             :     {
    3115          10 :       v8::HandleScope handle_scope(isolate);
    3116             :       v8::ExtensionConfiguration* no_extension = nullptr;
    3117             :       v8::Local<v8::ObjectTemplate> global_template =
    3118           5 :           v8::ObjectTemplate::New(isolate);
    3119             :       v8::Local<v8::External> external =
    3120           5 :           v8::External::New(isolate, &serialized_static_field);
    3121             :       v8::Local<v8::FunctionTemplate> callback =
    3122           5 :           v8::FunctionTemplate::New(isolate, SerializedCallback, external);
    3123          10 :       global_template->Set(v8_str("f"), callback);
    3124             :       v8::Local<v8::Context> context =
    3125           5 :           v8::Context::New(isolate, no_extension, global_template);
    3126           5 :       creator.SetDefaultContext(context);
    3127           5 :       context = v8::Context::New(isolate, no_extension, global_template);
    3128             :       v8::Local<v8::ObjectTemplate> object_template =
    3129           5 :           v8::ObjectTemplate::New(isolate);
    3130           5 :       object_template->SetInternalFieldCount(3);
    3131             : 
    3132             :       v8::Context::Scope context_scope(context);
    3133           5 :       ExpectInt32("f()", 42);
    3134           5 :       CHECK_EQ(315, serialized_static_field);
    3135             : 
    3136             :       v8::Local<v8::Object> a =
    3137           5 :           object_template->NewInstance(context).ToLocalChecked();
    3138             :       v8::Local<v8::Object> b =
    3139           5 :           object_template->NewInstance(context).ToLocalChecked();
    3140             :       v8::Local<v8::Object> c =
    3141           5 :           object_template->NewInstance(context).ToLocalChecked();
    3142             :       v8::Local<v8::External> null_external =
    3143           5 :           v8::External::New(isolate, nullptr);
    3144             :       v8::Local<v8::External> field_external =
    3145           5 :           v8::External::New(isolate, &serialized_static_field);
    3146             : 
    3147           5 :       a->SetInternalField(0, b);
    3148           5 :       b->SetInternalField(0, c);
    3149             : 
    3150           5 :       a->SetAlignedPointerInInternalField(1, a1);
    3151           5 :       b->SetAlignedPointerInInternalField(1, b1);
    3152           5 :       c->SetAlignedPointerInInternalField(1, c1);
    3153             : 
    3154           5 :       a->SetInternalField(2, null_external);
    3155           5 :       b->SetInternalField(2, field_external);
    3156           5 :       c->SetInternalField(2, v8_num(35));
    3157          20 :       CHECK(context->Global()->Set(context, v8_str("a"), a).FromJust());
    3158             : 
    3159           5 :       CHECK_EQ(0u,
    3160             :                creator.AddContext(context, v8::SerializeInternalFieldsCallback(
    3161             :                                                SerializeInternalFields,
    3162             :                                                reinterpret_cast<void*>(2000))));
    3163           5 :       CHECK_EQ(0u, creator.AddTemplate(callback));
    3164           5 :       CHECK_EQ(1u, creator.AddTemplate(global_template));
    3165             :     }
    3166             :     blob =
    3167           5 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    3168             : 
    3169           5 :     delete a1;
    3170           5 :     delete b1;
    3171           5 :     delete c1;
    3172             :   }
    3173             : 
    3174             :   {
    3175             :     v8::Isolate::CreateParams params;
    3176           5 :     params.snapshot_blob = &blob;
    3177           5 :     params.array_buffer_allocator = CcTest::array_buffer_allocator();
    3178           5 :     params.external_references = original_external_references;
    3179             :     // Test-appropriate equivalent of v8::Isolate::New.
    3180           5 :     v8::Isolate* isolate = TestSerializer::NewIsolate(params);
    3181             :     {
    3182             :       v8::Isolate::Scope isolate_scope(isolate);
    3183             :       {
    3184             :         // Create a new context without a new object template.
    3185          10 :         v8::HandleScope handle_scope(isolate);
    3186             :         v8::Local<v8::Context> context =
    3187           5 :             v8::Context::FromSnapshot(
    3188             :                 isolate, 0,
    3189             :                 v8::DeserializeInternalFieldsCallback(
    3190           5 :                     DeserializeInternalFields, reinterpret_cast<void*>(2017)))
    3191             :                 .ToLocalChecked();
    3192             :         v8::Context::Scope context_scope(context);
    3193           5 :         ExpectInt32("f()", 42);
    3194           5 :         CHECK_EQ(316, serialized_static_field);
    3195             : 
    3196             :         // Retrieve the snapshotted object template.
    3197             :         v8::Local<v8::ObjectTemplate> obj_template =
    3198           5 :             v8::ObjectTemplate::FromSnapshot(isolate, 1).ToLocalChecked();
    3199           5 :         CHECK(!obj_template.IsEmpty());
    3200             :         v8::Local<v8::Object> object =
    3201           5 :             obj_template->NewInstance(context).ToLocalChecked();
    3202          20 :         CHECK(context->Global()->Set(context, v8_str("o"), object).FromJust());
    3203           5 :         ExpectInt32("o.f()", 42);
    3204           5 :         CHECK_EQ(317, serialized_static_field);
    3205             :         // Check that it instantiates to the same prototype.
    3206             :         ExpectTrue("o.f.prototype === f.prototype");
    3207             : 
    3208             :         // Retrieve the snapshotted function template.
    3209             :         v8::Local<v8::FunctionTemplate> fun_template =
    3210           5 :             v8::FunctionTemplate::FromSnapshot(isolate, 0).ToLocalChecked();
    3211           5 :         CHECK(!fun_template.IsEmpty());
    3212             :         v8::Local<v8::Function> fun =
    3213           5 :             fun_template->GetFunction(context).ToLocalChecked();
    3214          20 :         CHECK(context->Global()->Set(context, v8_str("g"), fun).FromJust());
    3215           5 :         ExpectInt32("g()", 42);
    3216             :         // Check that it instantiates to the same prototype.
    3217             :         ExpectTrue("g.prototype === f.prototype");
    3218             : 
    3219             :         // Retrieve embedder fields.
    3220          10 :         v8::Local<v8::Object> a = context->Global()
    3221          15 :                                       ->Get(context, v8_str("a"))
    3222             :                                       .ToLocalChecked()
    3223           5 :                                       ->ToObject(context)
    3224             :                                       .ToLocalChecked();
    3225             :         v8::Local<v8::Object> b =
    3226           5 :             a->GetInternalField(0)->ToObject(context).ToLocalChecked();
    3227             :         v8::Local<v8::Object> c =
    3228           5 :             b->GetInternalField(0)->ToObject(context).ToLocalChecked();
    3229             : 
    3230             :         InternalFieldData* a1 = reinterpret_cast<InternalFieldData*>(
    3231             :             a->GetAlignedPointerFromInternalField(1));
    3232             :         v8::Local<v8::Value> a2 = a->GetInternalField(2);
    3233             : 
    3234             :         InternalFieldData* b1 = reinterpret_cast<InternalFieldData*>(
    3235             :             b->GetAlignedPointerFromInternalField(1));
    3236             :         v8::Local<v8::Value> b2 = b->GetInternalField(2);
    3237             : 
    3238             :         v8::Local<v8::Value> c0 = c->GetInternalField(0);
    3239             :         InternalFieldData* c1 = reinterpret_cast<InternalFieldData*>(
    3240             :             c->GetAlignedPointerFromInternalField(1));
    3241             :         v8::Local<v8::Value> c2 = c->GetInternalField(2);
    3242             : 
    3243           5 :         CHECK(c0->IsUndefined());
    3244             : 
    3245           5 :         CHECK_EQ(11u, a1->data);
    3246           5 :         CHECK_EQ(20u, b1->data);
    3247           5 :         CHECK_EQ(30u, c1->data);
    3248             : 
    3249           5 :         CHECK(a2->IsExternal());
    3250           5 :         CHECK_NULL(v8::Local<v8::External>::Cast(a2)->Value());
    3251           5 :         CHECK(b2->IsExternal());
    3252           5 :         CHECK_EQ(static_cast<void*>(&serialized_static_field),
    3253             :                  v8::Local<v8::External>::Cast(b2)->Value());
    3254          10 :         CHECK(c2->IsInt32() && c2->Int32Value(context).FromJust() == 35);
    3255             : 
    3256             :         // Accessing out of bound returns empty MaybeHandle.
    3257          10 :         CHECK(v8::ObjectTemplate::FromSnapshot(isolate, 2).IsEmpty());
    3258          10 :         CHECK(v8::FunctionTemplate::FromSnapshot(isolate, 2).IsEmpty());
    3259          10 :         CHECK(v8::Context::FromSnapshot(isolate, 1).IsEmpty());
    3260             : 
    3261          20 :         for (auto data : deserialized_data) delete data;
    3262             :         deserialized_data.clear();
    3263             :       }
    3264             :     }
    3265           5 :     isolate->Dispose();
    3266             :   }
    3267           5 :   delete[] blob.data;
    3268           5 :   FreeCurrentEmbeddedBlob();
    3269           5 : }
    3270             : 
    3271       26068 : UNINITIALIZED_TEST(SnapshotCreatorAddData) {
    3272             :   DisableAlwaysOpt();
    3273           5 :   DisableEmbeddedBlobRefcounting();
    3274             :   v8::StartupData blob;
    3275             : 
    3276             :   {
    3277          10 :     v8::SnapshotCreator creator;
    3278           5 :     v8::Isolate* isolate = creator.GetIsolate();
    3279             :     v8::Eternal<v8::Value> eternal_number;
    3280             :     v8::Persistent<v8::Value> persistent_number_1;
    3281             :     v8::Persistent<v8::Value> persistent_number_2;
    3282             :     v8::Persistent<v8::Context> persistent_context;
    3283             :     {
    3284          10 :       v8::HandleScope handle_scope(isolate);
    3285             : 
    3286           5 :       eternal_number.Set(isolate, v8_num(2017));
    3287          10 :       persistent_number_1.Reset(isolate, v8_num(2018));
    3288          10 :       persistent_number_2.Reset(isolate, v8_num(2019));
    3289             : 
    3290           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    3291           5 :       CHECK_EQ(0u, creator.AddData(context, persistent_number_2.Get(isolate)));
    3292           5 :       creator.SetDefaultContext(context);
    3293           5 :       context = v8::Context::New(isolate);
    3294             :       persistent_context.Reset(isolate, context);
    3295             : 
    3296             :       v8::Context::Scope context_scope(context);
    3297             : 
    3298             :       v8::Local<v8::Object> object = CompileRun("({ p: 12 })").As<v8::Object>();
    3299             : 
    3300             :       v8::Local<v8::ObjectTemplate> object_template =
    3301           5 :           v8::ObjectTemplate::New(isolate);
    3302           5 :       object_template->SetInternalFieldCount(3);
    3303             : 
    3304             :       v8::Local<v8::Private> private_symbol =
    3305           5 :           v8::Private::ForApi(isolate, v8_str("private_symbol"));
    3306             : 
    3307             :       v8::Local<v8::Signature> signature =
    3308           5 :         v8::Signature::New(isolate, v8::FunctionTemplate::New(isolate));
    3309             : 
    3310             :       v8::Local<v8::AccessorSignature> accessor_signature =
    3311             :            v8::AccessorSignature::New(isolate,
    3312           5 :                                       v8::FunctionTemplate::New(isolate));
    3313             : 
    3314           5 :       CHECK_EQ(0u, creator.AddData(context, object));
    3315          10 :       CHECK_EQ(1u, creator.AddData(context, v8_str("context-dependent")));
    3316           5 :       CHECK_EQ(2u, creator.AddData(context, persistent_number_1.Get(isolate)));
    3317           5 :       CHECK_EQ(3u, creator.AddData(context, object_template));
    3318           5 :       CHECK_EQ(4u, creator.AddData(context, persistent_context.Get(isolate)));
    3319           5 :       creator.AddContext(context);
    3320             : 
    3321          10 :       CHECK_EQ(0u, creator.AddData(v8_str("context-independent")));
    3322           5 :       CHECK_EQ(1u, creator.AddData(eternal_number.Get(isolate)));
    3323           5 :       CHECK_EQ(2u, creator.AddData(object_template));
    3324          10 :       CHECK_EQ(3u, creator.AddData(v8::FunctionTemplate::New(isolate)));
    3325           5 :       CHECK_EQ(4u, creator.AddData(private_symbol));
    3326           5 :       CHECK_EQ(5u, creator.AddData(signature));
    3327           5 :       CHECK_EQ(6u, creator.AddData(accessor_signature));
    3328             :     }
    3329             : 
    3330             :     blob =
    3331           5 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    3332             :   }
    3333             : 
    3334             :   {
    3335             :     v8::Isolate::CreateParams params;
    3336           5 :     params.snapshot_blob = &blob;
    3337           5 :     params.array_buffer_allocator = CcTest::array_buffer_allocator();
    3338             :     // Test-appropriate equivalent of v8::Isolate::New.
    3339           5 :     v8::Isolate* isolate = TestSerializer::NewIsolate(params);
    3340             :     {
    3341             :       v8::Isolate::Scope isolate_scope(isolate);
    3342          10 :       v8::HandleScope handle_scope(isolate);
    3343             :       v8::Local<v8::Context> context =
    3344          10 :           v8::Context::FromSnapshot(isolate, 0).ToLocalChecked();
    3345             : 
    3346             :       // Check serialized data on the context.
    3347             :       v8::Local<v8::Object> object =
    3348             :           context->GetDataFromSnapshotOnce<v8::Object>(0).ToLocalChecked();
    3349           5 :       CHECK(context->GetDataFromSnapshotOnce<v8::Object>(0).IsEmpty());
    3350          20 :       CHECK_EQ(12, object->Get(context, v8_str("p"))
    3351             :                        .ToLocalChecked()
    3352             :                        ->Int32Value(context)
    3353             :                        .FromJust());
    3354             : 
    3355             :       v8::Local<v8::String> string =
    3356             :           context->GetDataFromSnapshotOnce<v8::String>(1).ToLocalChecked();
    3357           5 :       CHECK(context->GetDataFromSnapshotOnce<v8::String>(1).IsEmpty());
    3358          15 :       CHECK(string->Equals(context, v8_str("context-dependent")).FromJust());
    3359             : 
    3360             :       v8::Local<v8::Number> number =
    3361             :           context->GetDataFromSnapshotOnce<v8::Number>(2).ToLocalChecked();
    3362           5 :       CHECK(context->GetDataFromSnapshotOnce<v8::Number>(2).IsEmpty());
    3363          10 :       CHECK_EQ(2018, number->Int32Value(context).FromJust());
    3364             : 
    3365             :       v8::Local<v8::ObjectTemplate> templ =
    3366             :           context->GetDataFromSnapshotOnce<v8::ObjectTemplate>(3)
    3367             :               .ToLocalChecked();
    3368           5 :       CHECK(context->GetDataFromSnapshotOnce<v8::ObjectTemplate>(3).IsEmpty());
    3369           5 :       CHECK_EQ(3, templ->InternalFieldCount());
    3370             : 
    3371             :       v8::Local<v8::Context> serialized_context =
    3372             :           context->GetDataFromSnapshotOnce<v8::Context>(4).ToLocalChecked();
    3373           5 :       CHECK(context->GetDataFromSnapshotOnce<v8::Context>(4).IsEmpty());
    3374           5 :       CHECK_EQ(*v8::Utils::OpenHandle(*serialized_context),
    3375             :                *v8::Utils::OpenHandle(*context));
    3376             : 
    3377           5 :       CHECK(context->GetDataFromSnapshotOnce<v8::Value>(5).IsEmpty());
    3378             : 
    3379             :       // Check serialized data on the isolate.
    3380             :       string = isolate->GetDataFromSnapshotOnce<v8::String>(0).ToLocalChecked();
    3381           5 :       CHECK(context->GetDataFromSnapshotOnce<v8::String>(0).IsEmpty());
    3382          15 :       CHECK(string->Equals(context, v8_str("context-independent")).FromJust());
    3383             : 
    3384             :       number = isolate->GetDataFromSnapshotOnce<v8::Number>(1).ToLocalChecked();
    3385           5 :       CHECK(isolate->GetDataFromSnapshotOnce<v8::Number>(1).IsEmpty());
    3386          10 :       CHECK_EQ(2017, number->Int32Value(context).FromJust());
    3387             : 
    3388             :       templ = isolate->GetDataFromSnapshotOnce<v8::ObjectTemplate>(2)
    3389             :                   .ToLocalChecked();
    3390           5 :       CHECK(isolate->GetDataFromSnapshotOnce<v8::ObjectTemplate>(2).IsEmpty());
    3391           5 :       CHECK_EQ(3, templ->InternalFieldCount());
    3392             : 
    3393             :       isolate->GetDataFromSnapshotOnce<v8::FunctionTemplate>(3)
    3394             :           .ToLocalChecked();
    3395           5 :       CHECK(
    3396             :           isolate->GetDataFromSnapshotOnce<v8::FunctionTemplate>(3).IsEmpty());
    3397             : 
    3398             :       isolate->GetDataFromSnapshotOnce<v8::Private>(4).ToLocalChecked();
    3399           5 :       CHECK(
    3400             :           isolate->GetDataFromSnapshotOnce<v8::Private>(4).IsEmpty());
    3401             : 
    3402             :       isolate->GetDataFromSnapshotOnce<v8::Signature>(5).ToLocalChecked();
    3403           5 :       CHECK(isolate->GetDataFromSnapshotOnce<v8::Signature>(5).IsEmpty());
    3404             : 
    3405             :       isolate->GetDataFromSnapshotOnce<v8::AccessorSignature>(6)
    3406             :           .ToLocalChecked();
    3407           5 :       CHECK(
    3408             :           isolate->GetDataFromSnapshotOnce<v8::AccessorSignature>(6).IsEmpty());
    3409             : 
    3410           5 :       CHECK(isolate->GetDataFromSnapshotOnce<v8::Value>(7).IsEmpty());
    3411             :     }
    3412           5 :     isolate->Dispose();
    3413             :   }
    3414             :   {
    3415          10 :     SnapshotCreator creator(nullptr, &blob);
    3416           5 :     v8::Isolate* isolate = creator.GetIsolate();
    3417             :     {
    3418             :       // Adding data to a snapshot replaces the list of existing data.
    3419          10 :       v8::HandleScope hscope(isolate);
    3420           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    3421           5 :       creator.SetDefaultContext(context);
    3422          10 :       context = v8::Context::FromSnapshot(isolate, 0).ToLocalChecked();
    3423             :       v8::Local<v8::String> string =
    3424             :           context->GetDataFromSnapshotOnce<v8::String>(1).ToLocalChecked();
    3425           5 :       CHECK(context->GetDataFromSnapshotOnce<v8::String>(1).IsEmpty());
    3426          15 :       CHECK(string->Equals(context, v8_str("context-dependent")).FromJust());
    3427             :       v8::Local<v8::Number> number =
    3428             :           isolate->GetDataFromSnapshotOnce<v8::Number>(1).ToLocalChecked();
    3429           5 :       CHECK(isolate->GetDataFromSnapshotOnce<v8::Number>(1).IsEmpty());
    3430          10 :       CHECK_EQ(2017, number->Int32Value(context).FromJust());
    3431             : 
    3432          10 :       CHECK_EQ(0u, creator.AddData(context, v8_num(2016)));
    3433           5 :       CHECK_EQ(0u, creator.AddContext(context));
    3434          10 :       CHECK_EQ(0u, creator.AddData(v8_str("stuff")));
    3435             :     }
    3436           5 :     delete[] blob.data;
    3437             :     blob =
    3438           5 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    3439             :   }
    3440             :   {
    3441             :     v8::Isolate::CreateParams params;
    3442           5 :     params.snapshot_blob = &blob;
    3443           5 :     params.array_buffer_allocator = CcTest::array_buffer_allocator();
    3444             :     // Test-appropriate equivalent of v8::Isolate::New.
    3445           5 :     v8::Isolate* isolate = TestSerializer::NewIsolate(params);
    3446             :     {
    3447             :       v8::Isolate::Scope isolate_scope(isolate);
    3448          10 :       v8::HandleScope handle_scope(isolate);
    3449             : 
    3450             :       // Context where we did not re-add data no longer has data.
    3451           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    3452           5 :       CHECK(context->GetDataFromSnapshotOnce<v8::Object>(0).IsEmpty());
    3453             : 
    3454             :       // Context where we re-added data has completely new ones.
    3455          10 :       context = v8::Context::FromSnapshot(isolate, 0).ToLocalChecked();
    3456             :       v8::Local<v8::Value> value =
    3457             :           context->GetDataFromSnapshotOnce<v8::Value>(0).ToLocalChecked();
    3458          10 :       CHECK_EQ(2016, value->Int32Value(context).FromJust());
    3459           5 :       CHECK(context->GetDataFromSnapshotOnce<v8::Value>(1).IsEmpty());
    3460             : 
    3461             :       // Ditto for the isolate.
    3462             :       v8::Local<v8::String> string =
    3463             :           isolate->GetDataFromSnapshotOnce<v8::String>(0).ToLocalChecked();
    3464          15 :       CHECK(string->Equals(context, v8_str("stuff")).FromJust());
    3465           5 :       CHECK(context->GetDataFromSnapshotOnce<v8::String>(1).IsEmpty());
    3466             :     }
    3467           5 :     isolate->Dispose();
    3468             :   }
    3469           5 :   delete[] blob.data;
    3470           5 :   FreeCurrentEmbeddedBlob();
    3471           5 : }
    3472             : 
    3473       26063 : TEST(SnapshotCreatorUnknownHandles) {
    3474             :   DisableAlwaysOpt();
    3475             :   v8::StartupData blob;
    3476             : 
    3477             :   {
    3478           0 :     v8::SnapshotCreator creator;
    3479           0 :     v8::Isolate* isolate = creator.GetIsolate();
    3480             :     v8::Eternal<v8::Value> eternal_number;
    3481             :     v8::Persistent<v8::Value> persistent_number;
    3482             :     {
    3483           0 :       v8::HandleScope handle_scope(isolate);
    3484             : 
    3485           0 :       eternal_number.Set(isolate, v8_num(2017));
    3486           0 :       persistent_number.Reset(isolate, v8_num(2018));
    3487             : 
    3488           0 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    3489           0 :       creator.SetDefaultContext(context);
    3490             :     }
    3491             : 
    3492             :     blob =
    3493           0 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    3494             :   }
    3495           0 :   delete[] blob.data;
    3496           0 : }
    3497             : 
    3498       26068 : UNINITIALIZED_TEST(SnapshotCreatorIncludeGlobalProxy) {
    3499             :   DisableAlwaysOpt();
    3500           5 :   DisableEmbeddedBlobRefcounting();
    3501             :   v8::StartupData blob;
    3502             : 
    3503             :   {
    3504          10 :     v8::SnapshotCreator creator(original_external_references);
    3505           5 :     v8::Isolate* isolate = creator.GetIsolate();
    3506             :     {
    3507             :       // Set default context. This context implicitly does *not* serialize
    3508             :       // the global proxy, and upon deserialization one has to be created
    3509             :       // in the bootstrapper from the global object template.
    3510             :       // Side effects from extensions are persisted though.
    3511          10 :       v8::HandleScope handle_scope(isolate);
    3512             :       v8::Local<v8::ObjectTemplate> global_template =
    3513           5 :           v8::ObjectTemplate::New(isolate);
    3514             :       v8::Local<v8::FunctionTemplate> callback =
    3515           5 :           v8::FunctionTemplate::New(isolate, SerializedCallback);
    3516          10 :       global_template->Set(v8_str("f"), callback);
    3517           5 :       global_template->SetHandler(v8::NamedPropertyHandlerConfiguration(
    3518           5 :           NamedPropertyGetterForSerialization));
    3519             :       v8::Local<v8::Context> context =
    3520           5 :           v8::Context::New(isolate, nullptr, global_template);
    3521             :       v8::Context::Scope context_scope(context);
    3522             :       CompileRun(
    3523             :           "function h() { return 13; };"
    3524             :           "function i() { return 14; };"
    3525             :           "var o = { p: 7 };");
    3526           5 :       ExpectInt32("f()", 42);
    3527           5 :       ExpectInt32("h()", 13);
    3528           5 :       ExpectInt32("o.p", 7);
    3529           5 :       ExpectInt32("x", 2016);
    3530           5 :       creator.SetDefaultContext(context);
    3531             :     }
    3532             :     {
    3533             :       // Add additional context. This context implicitly *does* serialize
    3534             :       // the global proxy, and upon deserialization one has to be created
    3535             :       // in the bootstrapper from the global object template.
    3536             :       // Side effects from extensions are persisted.
    3537          10 :       v8::HandleScope handle_scope(isolate);
    3538             :       v8::Local<v8::ObjectTemplate> global_template =
    3539           5 :           v8::ObjectTemplate::New(isolate);
    3540             :       v8::Local<v8::FunctionTemplate> callback =
    3541           5 :           v8::FunctionTemplate::New(isolate, SerializedCallback);
    3542           5 :       global_template->SetInternalFieldCount(3);
    3543          10 :       global_template->Set(v8_str("f"), callback);
    3544           5 :       global_template->SetHandler(v8::NamedPropertyHandlerConfiguration(
    3545           5 :           NamedPropertyGetterForSerialization));
    3546           5 :       global_template->SetAccessor(v8_str("y"), AccessorForSerialization);
    3547             :       v8::Local<v8::Private> priv =
    3548           5 :           v8::Private::ForApi(isolate, v8_str("cached"));
    3549          10 :       global_template->SetAccessorProperty(
    3550             :           v8_str("cached"),
    3551             :           v8::FunctionTemplate::NewWithCache(isolate, SerializedCallback, priv,
    3552           5 :                                              v8::Local<v8::Value>()));
    3553             :       v8::Local<v8::Context> context =
    3554           5 :           v8::Context::New(isolate, nullptr, global_template);
    3555             :       v8::Context::Scope context_scope(context);
    3556             : 
    3557          20 :       CHECK(context->Global()
    3558             :                 ->SetPrivate(context, priv, v8_str("cached string"))
    3559             :                 .FromJust());
    3560             :       v8::Local<v8::Private> hidden =
    3561           5 :           v8::Private::ForApi(isolate, v8_str("hidden"));
    3562          20 :       CHECK(context->Global()
    3563             :                 ->SetPrivate(context, hidden, v8_str("hidden string"))
    3564             :                 .FromJust());
    3565             : 
    3566           5 :       ExpectInt32("f()", 42);
    3567           5 :       ExpectInt32("x", 2016);
    3568           5 :       ExpectInt32("y", 2017);
    3569          25 :       CHECK(v8_str("hidden string")
    3570             :                 ->Equals(context, context->Global()
    3571             :                                       ->GetPrivate(context, hidden)
    3572             :                                       .ToLocalChecked())
    3573             :                 .FromJust());
    3574             : 
    3575           5 :       CHECK_EQ(0u,
    3576             :                creator.AddContext(context, v8::SerializeInternalFieldsCallback(
    3577             :                                                SerializeInternalFields,
    3578             :                                                reinterpret_cast<void*>(2016))));
    3579             :     }
    3580             :     blob =
    3581           5 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    3582             :   }
    3583             : 
    3584             :   {
    3585             :     v8::Isolate::CreateParams params;
    3586           5 :     params.snapshot_blob = &blob;
    3587           5 :     params.array_buffer_allocator = CcTest::array_buffer_allocator();
    3588           5 :     params.external_references = original_external_references;
    3589             :     // Test-appropriate equivalent of v8::Isolate::New.
    3590           5 :     v8::Isolate* isolate = TestSerializer::NewIsolate(params);
    3591             :     {
    3592             :       v8::Isolate::Scope isolate_scope(isolate);
    3593             :       // We can introduce new extensions, which could override functions already
    3594             :       // in the snapshot.
    3595             :       auto extension =
    3596             :           base::make_unique<v8::Extension>("new extension",
    3597             :                                            "function i() { return 24; }"
    3598             :                                            "function j() { return 25; }"
    3599             :                                            "try {"
    3600             :                                            "  if (o.p == 7) o.p++;"
    3601           5 :                                            "} catch {}");
    3602             :       extension->set_auto_enable(true);
    3603          10 :       v8::RegisterExtension(std::move(extension));
    3604             :       {
    3605             :         // Create a new context from default context snapshot. This will
    3606             :         // create a new global object from a new global object template
    3607             :         // without the interceptor.
    3608          10 :         v8::HandleScope handle_scope(isolate);
    3609           5 :         v8::Local<v8::Context> context = v8::Context::New(isolate);
    3610             :         v8::Context::Scope context_scope(context);
    3611           5 :         ExpectInt32("f()", 42);
    3612           5 :         ExpectInt32("h()", 13);
    3613           5 :         ExpectInt32("i()", 24);
    3614           5 :         ExpectInt32("j()", 25);
    3615           5 :         ExpectInt32("o.p", 8);
    3616          10 :         v8::TryCatch try_catch(isolate);
    3617           5 :         CHECK(CompileRun("x").IsEmpty());
    3618           5 :         CHECK(try_catch.HasCaught());
    3619             :       }
    3620             :       {
    3621             :         // Create a new context from first additional context snapshot. This
    3622             :         // will use the global object from the snapshot, including interceptor.
    3623          10 :         v8::HandleScope handle_scope(isolate);
    3624             :         v8::Local<v8::Context> context =
    3625           5 :             v8::Context::FromSnapshot(
    3626             :                 isolate, 0,
    3627             :                 v8::DeserializeInternalFieldsCallback(
    3628           5 :                     DeserializeInternalFields, reinterpret_cast<void*>(2017)))
    3629             :                 .ToLocalChecked();
    3630             : 
    3631             :         {
    3632             :           v8::Context::Scope context_scope(context);
    3633           5 :           ExpectInt32("f()", 42);
    3634           5 :           ExpectInt32("i()", 24);
    3635           5 :           ExpectInt32("j()", 25);
    3636           5 :           ExpectInt32("x", 2016);
    3637             :           v8::Local<v8::Private> hidden =
    3638           5 :               v8::Private::ForApi(isolate, v8_str("hidden"));
    3639          25 :           CHECK(v8_str("hidden string")
    3640             :                     ->Equals(context, context->Global()
    3641             :                                           ->GetPrivate(context, hidden)
    3642             :                                           .ToLocalChecked())
    3643             :                     .FromJust());
    3644           5 :           ExpectString("cached", "cached string");
    3645             :         }
    3646             : 
    3647           5 :         v8::Local<v8::Object> global = context->Global();
    3648           5 :         CHECK_EQ(3, global->InternalFieldCount());
    3649           5 :         context->DetachGlobal();
    3650             : 
    3651             :         // New context, but reuse global proxy.
    3652             :         v8::ExtensionConfiguration* no_extensions = nullptr;
    3653             :         v8::Local<v8::Context> context2 =
    3654           5 :             v8::Context::FromSnapshot(
    3655             :                 isolate, 0,
    3656             :                 v8::DeserializeInternalFieldsCallback(
    3657             :                     DeserializeInternalFields, reinterpret_cast<void*>(2017)),
    3658           5 :                 no_extensions, global)
    3659             :                 .ToLocalChecked();
    3660             :         {
    3661             :           v8::Context::Scope context_scope(context2);
    3662           5 :           ExpectInt32("f()", 42);
    3663           5 :           ExpectInt32("i()", 24);
    3664           5 :           ExpectInt32("j()", 25);
    3665           5 :           ExpectInt32("x", 2016);
    3666             :           v8::Local<v8::Private> hidden =
    3667           5 :               v8::Private::ForApi(isolate, v8_str("hidden"));
    3668          25 :           CHECK(v8_str("hidden string")
    3669             :                     ->Equals(context2, context2->Global()
    3670             :                                            ->GetPrivate(context2, hidden)
    3671             :                                            .ToLocalChecked())
    3672             :                     .FromJust());
    3673             : 
    3674             :           // Set cached accessor property again.
    3675             :           v8::Local<v8::Private> priv =
    3676           5 :               v8::Private::ForApi(isolate, v8_str("cached"));
    3677          20 :           CHECK(context2->Global()
    3678             :                     ->SetPrivate(context2, priv, v8_str("cached string 1"))
    3679             :                     .FromJust());
    3680           5 :           ExpectString("cached", "cached string 1");
    3681             :         }
    3682             : 
    3683          15 :         CHECK(context2->Global()->Equals(context2, global).FromJust());
    3684             :       }
    3685             :     }
    3686           5 :     isolate->Dispose();
    3687             :   }
    3688           5 :   delete[] blob.data;
    3689           5 :   FreeCurrentEmbeddedBlob();
    3690           5 : }
    3691             : 
    3692       26068 : UNINITIALIZED_TEST(ReinitializeHashSeedNotRehashable) {
    3693             :   DisableAlwaysOpt();
    3694           5 :   i::FLAG_rehash_snapshot = true;
    3695           5 :   i::FLAG_hash_seed = 42;
    3696           5 :   i::FLAG_allow_natives_syntax = true;
    3697           5 :   DisableEmbeddedBlobRefcounting();
    3698             :   v8::StartupData blob;
    3699             :   {
    3700          10 :     v8::SnapshotCreator creator;
    3701           5 :     v8::Isolate* isolate = creator.GetIsolate();
    3702             :     {
    3703          10 :       v8::HandleScope handle_scope(isolate);
    3704           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    3705             :       v8::Context::Scope context_scope(context);
    3706             :       // Create an object with an ordered hash table.
    3707             :       CompileRun(
    3708             :           "var m = new Map();"
    3709             :           "m.set('a', 1);"
    3710             :           "m.set('b', 2);");
    3711           5 :       ExpectInt32("m.get('b')", 2);
    3712           5 :       creator.SetDefaultContext(context);
    3713             :     }
    3714             :     blob =
    3715           5 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    3716             :   }
    3717             : 
    3718           5 :   i::FLAG_hash_seed = 1337;
    3719             :   v8::Isolate::CreateParams create_params;
    3720           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    3721           5 :   create_params.snapshot_blob = &blob;
    3722           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
    3723             :   {
    3724             :     // Check that no rehashing has been performed.
    3725           5 :     CHECK_EQ(static_cast<uint64_t>(42),
    3726             :              HashSeed(reinterpret_cast<i::Isolate*>(isolate)));
    3727             :     v8::Isolate::Scope isolate_scope(isolate);
    3728          10 :     v8::HandleScope handle_scope(isolate);
    3729           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate);
    3730           5 :     CHECK(!context.IsEmpty());
    3731             :     v8::Context::Scope context_scope(context);
    3732           5 :     ExpectInt32("m.get('b')", 2);
    3733             :   }
    3734           5 :   isolate->Dispose();
    3735           5 :   delete[] blob.data;
    3736           5 :   FreeCurrentEmbeddedBlob();
    3737           5 : }
    3738             : 
    3739       26068 : UNINITIALIZED_TEST(ReinitializeHashSeedRehashable) {
    3740             :   DisableAlwaysOpt();
    3741           5 :   i::FLAG_rehash_snapshot = true;
    3742           5 :   i::FLAG_hash_seed = 42;
    3743           5 :   i::FLAG_allow_natives_syntax = true;
    3744           5 :   DisableEmbeddedBlobRefcounting();
    3745             :   v8::StartupData blob;
    3746             :   {
    3747          10 :     v8::SnapshotCreator creator;
    3748           5 :     v8::Isolate* isolate = creator.GetIsolate();
    3749             :     {
    3750          10 :       v8::HandleScope handle_scope(isolate);
    3751           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    3752             :       v8::Context::Scope context_scope(context);
    3753             :       // Create dictionary mode object.
    3754             :       CompileRun(
    3755             :           "var a = new Array(10000);"
    3756             :           "%NormalizeElements(a);"
    3757             :           "a[133] = 1;"
    3758             :           "a[177] = 2;"
    3759             :           "a[971] = 3;"
    3760             :           "a[7997] = 4;"
    3761             :           "a[2111] = 5;"
    3762             :           "var o = {};"
    3763             :           "%OptimizeObjectForAddingMultipleProperties(o, 3);"
    3764             :           "o.a = 1;"
    3765             :           "o.b = 2;"
    3766             :           "o.c = 3;"
    3767             :           "var p = { foo: 1 };"  // Test rehashing of transition arrays.
    3768             :           "p = JSON.parse('{\"foo\": {\"x\": 1}}');");
    3769             :       i::Handle<i::Object> i_a = v8::Utils::OpenHandle(*CompileRun("a"));
    3770             :       i::Handle<i::Object> i_o = v8::Utils::OpenHandle(*CompileRun("o"));
    3771           5 :       CHECK(i_a->IsJSArray());
    3772           5 :       CHECK(i_a->IsJSObject());
    3773          10 :       CHECK(!i::Handle<i::JSArray>::cast(i_a)->HasFastElements());
    3774           5 :       CHECK(!i::Handle<i::JSObject>::cast(i_o)->HasFastProperties());
    3775           5 :       ExpectInt32("a[2111]", 5);
    3776           5 :       ExpectInt32("o.c", 3);
    3777           5 :       creator.SetDefaultContext(context);
    3778             :     }
    3779             :     blob =
    3780           5 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    3781             :   }
    3782             : 
    3783           5 :   i::FLAG_hash_seed = 1337;
    3784             :   v8::Isolate::CreateParams create_params;
    3785           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    3786           5 :   create_params.snapshot_blob = &blob;
    3787           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
    3788             :   {
    3789             :     // Check that rehashing has been performed.
    3790           5 :     CHECK_EQ(static_cast<uint64_t>(1337),
    3791             :              HashSeed(reinterpret_cast<i::Isolate*>(isolate)));
    3792             :     v8::Isolate::Scope isolate_scope(isolate);
    3793          10 :     v8::HandleScope handle_scope(isolate);
    3794           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate);
    3795           5 :     CHECK(!context.IsEmpty());
    3796             :     v8::Context::Scope context_scope(context);
    3797             :     i::Handle<i::Object> i_a = v8::Utils::OpenHandle(*CompileRun("a"));
    3798             :     i::Handle<i::Object> i_o = v8::Utils::OpenHandle(*CompileRun("o"));
    3799           5 :     CHECK(i_a->IsJSArray());
    3800           5 :     CHECK(i_a->IsJSObject());
    3801          10 :     CHECK(!i::Handle<i::JSArray>::cast(i_a)->HasFastElements());
    3802           5 :     CHECK(!i::Handle<i::JSObject>::cast(i_o)->HasFastProperties());
    3803           5 :     ExpectInt32("a[2111]", 5);
    3804           5 :     ExpectInt32("o.c", 3);
    3805             :   }
    3806           5 :   isolate->Dispose();
    3807           5 :   delete[] blob.data;
    3808           5 :   FreeCurrentEmbeddedBlob();
    3809           5 : }
    3810             : 
    3811       26068 : UNINITIALIZED_TEST(SerializationStats) {
    3812           5 :   FLAG_profile_deserialization = true;
    3813           5 :   FLAG_always_opt = false;
    3814             :   v8::StartupData blob = CreateSnapshotDataBlob();
    3815           5 :   delete[] blob.data;
    3816             : 
    3817             :   // Track the embedded blob size as well.
    3818             :   {
    3819             :     int embedded_blob_size = 0;
    3820             :     if (FLAG_embedded_builtins) {
    3821             :       i::EmbeddedData d = i::EmbeddedData::FromBlob();
    3822           5 :       embedded_blob_size = static_cast<int>(d.size());
    3823             :     }
    3824           5 :     PrintF("Embedded blob is %d bytes\n", embedded_blob_size);
    3825             :   }
    3826             : 
    3827           5 :   FreeCurrentEmbeddedBlob();
    3828           5 : }
    3829             : 
    3830          10 : void CheckSFIsAreWeak(WeakFixedArray sfis, Isolate* isolate) {
    3831          10 :   CHECK_GT(sfis->length(), 0);
    3832             :   int no_of_weak = 0;
    3833          50 :   for (int i = 0; i < sfis->length(); ++i) {
    3834             :     MaybeObject maybe_object = sfis->Get(i);
    3835             :     HeapObject heap_object;
    3836          20 :     CHECK(maybe_object->IsWeakOrCleared() ||
    3837             :           (maybe_object->GetHeapObjectIfStrong(&heap_object) &&
    3838             :            heap_object->IsUndefined(isolate)));
    3839          20 :     if (maybe_object->IsWeak()) {
    3840          15 :       ++no_of_weak;
    3841             :     }
    3842             :   }
    3843          10 :   CHECK_GT(no_of_weak, 0);
    3844          10 : }
    3845             : 
    3846       26068 : UNINITIALIZED_TEST(WeakArraySerializationInSnapshot) {
    3847             :   const char* code = "var my_func = function() { }";
    3848             : 
    3849             :   DisableAlwaysOpt();
    3850           5 :   DisableEmbeddedBlobRefcounting();
    3851           5 :   i::FLAG_allow_natives_syntax = true;
    3852             :   v8::StartupData blob;
    3853             :   {
    3854          10 :     v8::SnapshotCreator creator;
    3855           5 :     v8::Isolate* isolate = creator.GetIsolate();
    3856             :     {
    3857          10 :       v8::HandleScope handle_scope(isolate);
    3858           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    3859             :       v8::Context::Scope context_scope(context);
    3860             : 
    3861             :       CompileRun(code);
    3862           5 :       creator.SetDefaultContext(
    3863             :           context, v8::SerializeInternalFieldsCallback(
    3864           5 :                        SerializeInternalFields, reinterpret_cast<void*>(2016)));
    3865             :     }
    3866             :     blob =
    3867           5 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    3868             :   }
    3869             : 
    3870             :   v8::Isolate::CreateParams create_params;
    3871           5 :   create_params.snapshot_blob = &blob;
    3872           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    3873           5 :   v8::Isolate* isolate = TestSerializer::NewIsolate(create_params);
    3874             :   {
    3875             :     v8::Isolate::Scope i_scope(isolate);
    3876          10 :     v8::HandleScope h_scope(isolate);
    3877             :     v8::Local<v8::Context> context = v8::Context::New(
    3878             :         isolate, nullptr, v8::MaybeLocal<v8::ObjectTemplate>(),
    3879             :         v8::MaybeLocal<v8::Value>(),
    3880             :         v8::DeserializeInternalFieldsCallback(DeserializeInternalFields,
    3881           5 :                                               reinterpret_cast<void*>(2017)));
    3882             :     v8::Context::Scope c_scope(context);
    3883             : 
    3884             :     v8::Local<v8::Value> x = CompileRun("my_func");
    3885           5 :     CHECK(x->IsFunction());
    3886             :     Handle<JSFunction> function =
    3887             :         Handle<JSFunction>::cast(v8::Utils::OpenHandle(*x));
    3888             : 
    3889             :     // Verify that the pointers in shared_function_infos are weak.
    3890             :     WeakFixedArray sfis =
    3891          10 :         Script::cast(function->shared()->script())->shared_function_infos();
    3892           5 :     CheckSFIsAreWeak(sfis, reinterpret_cast<i::Isolate*>(isolate));
    3893             :   }
    3894           5 :   isolate->Dispose();
    3895           5 :   delete[] blob.data;
    3896           5 :   FreeCurrentEmbeddedBlob();
    3897           5 : }
    3898             : 
    3899       26068 : TEST(WeakArraySerializationInCodeCache) {
    3900           5 :   LocalContext context;
    3901             :   Isolate* isolate = CcTest::i_isolate();
    3902           5 :   isolate->compilation_cache()->Disable();
    3903             : 
    3904          10 :   v8::HandleScope scope(CcTest::isolate());
    3905             : 
    3906             :   const char* source = "function foo() { }";
    3907             : 
    3908             :   Handle<String> src = isolate->factory()
    3909          10 :                            ->NewStringFromUtf8(CStrVector(source))
    3910           5 :                            .ToHandleChecked();
    3911           5 :   ScriptData* cache = nullptr;
    3912             : 
    3913             :   CompileScriptAndProduceCache(isolate, src, src, &cache,
    3914           5 :                                v8::ScriptCompiler::kNoCompileOptions);
    3915             : 
    3916             :   DisallowCompilation no_compile_expected(isolate);
    3917             :   Handle<SharedFunctionInfo> copy = CompileScript(
    3918           5 :       isolate, src, src, cache, v8::ScriptCompiler::kConsumeCodeCache);
    3919             : 
    3920             :   // Verify that the pointers in shared_function_infos are weak.
    3921          10 :   WeakFixedArray sfis = Script::cast(copy->script())->shared_function_infos();
    3922           5 :   CheckSFIsAreWeak(sfis, isolate);
    3923             : 
    3924          10 :   delete cache;
    3925           5 : }
    3926             : 
    3927       26068 : TEST(CachedCompileFunctionInContext) {
    3928             :   DisableAlwaysOpt();
    3929           5 :   LocalContext env;
    3930             :   Isolate* isolate = CcTest::i_isolate();
    3931           5 :   isolate->compilation_cache()->Disable();  // Disable same-isolate code cache.
    3932             : 
    3933          10 :   v8::HandleScope scope(CcTest::isolate());
    3934             : 
    3935           5 :   v8::Local<v8::String> source = v8_str("return x*x;");
    3936           5 :   v8::Local<v8::String> arg_str = v8_str("x");
    3937             :   ScriptCompiler::CachedData* cache;
    3938             :   {
    3939             :     v8::ScriptCompiler::Source script_source(source);
    3940             :     v8::Local<v8::Function> fun =
    3941           5 :         v8::ScriptCompiler::CompileFunctionInContext(
    3942             :             env.local(), &script_source, 1, &arg_str, 0, nullptr,
    3943             :             v8::ScriptCompiler::kEagerCompile)
    3944           5 :             .ToLocalChecked();
    3945           5 :     cache = v8::ScriptCompiler::CreateCodeCacheForFunction(fun);
    3946             :   }
    3947             : 
    3948             :   {
    3949             :     DisallowCompilation no_compile_expected(isolate);
    3950             :     v8::ScriptCompiler::Source script_source(source, cache);
    3951             :     v8::Local<v8::Function> fun =
    3952           5 :         v8::ScriptCompiler::CompileFunctionInContext(
    3953             :             env.local(), &script_source, 1, &arg_str, 0, nullptr,
    3954             :             v8::ScriptCompiler::kConsumeCodeCache)
    3955             :             .ToLocalChecked();
    3956           5 :     v8::Local<v8::Value> arg = v8_num(3);
    3957             :     v8::Local<v8::Value> result =
    3958          15 :         fun->Call(env.local(), v8::Undefined(CcTest::isolate()), 1, &arg)
    3959             :             .ToLocalChecked();
    3960          10 :     CHECK_EQ(9, result->Int32Value(env.local()).FromJust());
    3961             :   }
    3962           5 : }
    3963             : 
    3964       26068 : UNINITIALIZED_TEST(SnapshotCreatorAnonClassWithKeep) {
    3965             :   DisableAlwaysOpt();
    3966          10 :   v8::SnapshotCreator creator;
    3967           5 :   v8::Isolate* isolate = creator.GetIsolate();
    3968             :   {
    3969          10 :     v8::HandleScope handle_scope(isolate);
    3970             :     {
    3971           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    3972             :       v8::Context::Scope context_scope(context);
    3973             :       CompileRun(
    3974             :           "function Foo() { return class {}; } \n"
    3975             :           "class Bar extends Foo() {}\n"
    3976             :           "Foo()\n");
    3977           5 :       creator.SetDefaultContext(context);
    3978             :     }
    3979             :   }
    3980             :   v8::StartupData blob =
    3981           5 :       creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kKeep);
    3982             : 
    3983           5 :   delete[] blob.data;
    3984           5 : }
    3985             : 
    3986             : }  // namespace internal
    3987       78189 : }  // namespace v8

Generated by: LCOV version 1.10