LCOV - code coverage report
Current view: top level - test/cctest - test-serialize.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1698 1751 97.0 %
Date: 2019-02-19 Functions: 117 126 92.9 %

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

Generated by: LCOV version 1.10