LCOV - code coverage report
Current view: top level - test/cctest - test-serialize.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1202 1221 98.4 %
Date: 2017-10-20 Functions: 80 91 87.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.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/heap/spaces.h"
      41             : #include "src/macro-assembler-inl.h"
      42             : #include "src/objects-inl.h"
      43             : #include "src/runtime/runtime.h"
      44             : #include "src/snapshot/builtin-deserializer.h"
      45             : #include "src/snapshot/builtin-serializer.h"
      46             : #include "src/snapshot/code-serializer.h"
      47             : #include "src/snapshot/natives.h"
      48             : #include "src/snapshot/partial-deserializer.h"
      49             : #include "src/snapshot/partial-serializer.h"
      50             : #include "src/snapshot/snapshot.h"
      51             : #include "src/snapshot/startup-deserializer.h"
      52             : #include "src/snapshot/startup-serializer.h"
      53             : #include "test/cctest/cctest.h"
      54             : #include "test/cctest/heap/heap-utils.h"
      55             : #include "test/cctest/setup-isolate-for-tests.h"
      56             : 
      57             : namespace v8 {
      58             : namespace internal {
      59             : 
      60           0 : void DisableLazyDeserialization() {
      61             :   // UNINITIALIZED tests do not set up the isolate sufficiently for lazy
      62             :   // deserialization to work.
      63             :   // TODO(jgruber): Fix this. It may just be enough to set the snapshot_blob.
      64          45 :   FLAG_lazy_deserialization = false;
      65           0 : }
      66             : 
      67           0 : void DisableAlwaysOpt() {
      68             :   // Isolates prepared for serialization do not optimize. The only exception is
      69             :   // with the flag --always-opt.
      70         130 :   FLAG_always_opt = false;
      71           0 : }
      72             : 
      73             : 
      74             : // TestIsolate is used for testing isolate serialization.
      75             : class TestIsolate : public Isolate {
      76             :  public:
      77          30 :   static v8::Isolate* NewInitialized(bool enable_serializer) {
      78          30 :     i::Isolate* isolate = new TestIsolate(enable_serializer);
      79          60 :     isolate->setup_delegate_ = new SetupIsolateDelegateForTests(true);
      80             :     v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
      81             :     v8::Isolate::Scope isolate_scope(v8_isolate);
      82          30 :     isolate->Init(nullptr);
      83          30 :     return v8_isolate;
      84             :   }
      85             :   // Wraps v8::Isolate::New, but with a TestIsolate under the hood.
      86             :   // Allows flexibility to bootstrap with or without snapshot even when
      87             :   // the production Isolate class has one or the other behavior baked in.
      88          95 :   static v8::Isolate* New(const v8::Isolate::CreateParams& params) {
      89          95 :     i::Isolate* isolate = new TestIsolate(false);
      90          95 :     bool create_heap_objects = params.snapshot_blob == nullptr;
      91             :     isolate->setup_delegate_ =
      92         190 :         new SetupIsolateDelegateForTests(create_heap_objects);
      93          95 :     return v8::IsolateNewImpl(isolate, params);
      94             :   }
      95         155 :   explicit TestIsolate(bool enable_serializer) : Isolate(enable_serializer) {
      96             :     set_array_buffer_allocator(CcTest::array_buffer_allocator());
      97             :   }
      98             :   void SetDeserializeFromSnapshot() {
      99          60 :     setup_delegate_ = new SetupIsolateDelegateForTests(false);
     100             :   }
     101             : };
     102             : 
     103         180 : static Vector<const byte> WritePayload(const Vector<const byte>& payload) {
     104             :   int length = payload.length();
     105          90 :   byte* blob = NewArray<byte>(length);
     106             :   memcpy(blob, payload.begin(), length);
     107          90 :   return Vector<const byte>(const_cast<const byte*>(blob), length);
     108             : }
     109             : 
     110             : // A convenience struct to simplify management of the two blobs required to
     111             : // deserialize an isolate.
     112             : struct StartupBlobs {
     113             :   Vector<const byte> startup;
     114             :   Vector<const byte> builtin;
     115             : 
     116          40 :   void Dispose() {
     117             :     startup.Dispose();
     118             :     builtin.Dispose();
     119          40 :   }
     120             : };
     121             : 
     122          30 : static StartupBlobs Serialize(v8::Isolate* isolate) {
     123             :   // We have to create one context.  One reason for this is so that the builtins
     124             :   // can be loaded from v8natives.js and their addresses can be processed.  This
     125             :   // will clear the pending fixups array, which would otherwise contain GC roots
     126             :   // that would confuse the serialization/deserialization process.
     127             :   v8::Isolate::Scope isolate_scope(isolate);
     128             :   {
     129          30 :     v8::HandleScope scope(isolate);
     130          30 :     v8::Context::New(isolate);
     131             :   }
     132             : 
     133             :   Isolate* internal_isolate = reinterpret_cast<Isolate*>(isolate);
     134             :   internal_isolate->heap()->CollectAllAvailableGarbage(
     135          30 :       i::GarbageCollectionReason::kTesting);
     136             :   StartupSerializer ser(internal_isolate,
     137          60 :                         v8::SnapshotCreator::FunctionCodeHandling::kClear);
     138          30 :   ser.SerializeStrongReferences();
     139             : 
     140          60 :   i::BuiltinSerializer builtin_serializer(internal_isolate, &ser);
     141          30 :   builtin_serializer.SerializeBuiltins();
     142             : 
     143          30 :   ser.SerializeWeakReferencesAndDeferred();
     144          30 :   SnapshotData startup_snapshot(&ser);
     145          30 :   BuiltinSnapshotData builtin_snapshot(&builtin_serializer);
     146          90 :   return {WritePayload(startup_snapshot.RawData()),
     147          90 :           WritePayload(builtin_snapshot.RawData())};
     148             : }
     149             : 
     150             : 
     151          50 : Vector<const uint8_t> ConstructSource(Vector<const uint8_t> head,
     152             :                                       Vector<const uint8_t> body,
     153             :                                       Vector<const uint8_t> tail, int repeats) {
     154         100 :   int source_length = head.length() + body.length() * repeats + tail.length();
     155          50 :   uint8_t* source = NewArray<uint8_t>(static_cast<size_t>(source_length));
     156          50 :   CopyChars(source, head.start(), head.length());
     157    23105490 :   for (int i = 0; i < repeats; i++) {
     158    23105490 :     CopyChars(source + head.length() + i * body.length(), body.start(),
     159    46210980 :               body.length());
     160             :   }
     161          50 :   CopyChars(source + head.length() + repeats * body.length(), tail.start(),
     162         100 :             tail.length());
     163             :   return Vector<const uint8_t>(const_cast<const uint8_t*>(source),
     164          50 :                                source_length);
     165             : }
     166             : 
     167          30 : v8::Isolate* InitializeFromBlob(StartupBlobs& blobs) {
     168             :   v8::Isolate* v8_isolate = nullptr;
     169             :   {
     170             :     SnapshotData startup_snapshot(blobs.startup);
     171             :     BuiltinSnapshotData builtin_snapshot(blobs.builtin);
     172             :     StartupDeserializer deserializer(&startup_snapshot, &builtin_snapshot);
     173          30 :     TestIsolate* isolate = new TestIsolate(false);
     174             :     v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
     175             :     v8::Isolate::Scope isolate_scope(v8_isolate);
     176             :     isolate->SetDeserializeFromSnapshot();
     177          30 :     isolate->Init(&deserializer);
     178             :   }
     179          30 :   return v8_isolate;
     180             : }
     181             : 
     182          20 : static v8::Isolate* Deserialize(StartupBlobs& blobs) {
     183          20 :   v8::Isolate* isolate = InitializeFromBlob(blobs);
     184          20 :   CHECK(isolate);
     185          20 :   return isolate;
     186             : }
     187             : 
     188             : 
     189          15 : static void SanityCheck(v8::Isolate* v8_isolate) {
     190             :   Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
     191          15 :   v8::HandleScope scope(v8_isolate);
     192             : #ifdef VERIFY_HEAP
     193             :   isolate->heap()->Verify();
     194             : #endif
     195          30 :   CHECK(isolate->global_object()->IsJSObject());
     196          30 :   CHECK(isolate->native_context()->IsContext());
     197          30 :   CHECK(isolate->heap()->string_table()->IsStringTable());
     198          15 :   isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("Empty"));
     199          15 : }
     200             : 
     201       23723 : UNINITIALIZED_TEST(StartupSerializerOnce) {
     202             :   DisableLazyDeserialization();
     203             :   DisableAlwaysOpt();
     204           5 :   v8::Isolate* isolate = TestIsolate::NewInitialized(true);
     205           5 :   StartupBlobs blobs = Serialize(isolate);
     206           5 :   isolate->Dispose();
     207           5 :   isolate = Deserialize(blobs);
     208           5 :   blobs.Dispose();
     209             :   {
     210           5 :     v8::HandleScope handle_scope(isolate);
     211             :     v8::Isolate::Scope isolate_scope(isolate);
     212             : 
     213           5 :     v8::Local<v8::Context> env = v8::Context::New(isolate);
     214           5 :     env->Enter();
     215             : 
     216          10 :     SanityCheck(isolate);
     217             :   }
     218           5 :   isolate->Dispose();
     219           5 : }
     220             : 
     221       23723 : UNINITIALIZED_TEST(StartupSerializerRootMapDependencies) {
     222             :   DisableAlwaysOpt();
     223           5 :   v8::SnapshotCreator snapshot_creator;
     224           5 :   v8::Isolate* isolate = snapshot_creator.GetIsolate();
     225             :   {
     226             :     v8::Isolate::Scope isolate_scope(isolate);
     227          10 :     v8::HandleScope handle_scope(isolate);
     228             :     Isolate* internal_isolate = reinterpret_cast<Isolate*>(isolate);
     229             :     // Here is interesting retaining path:
     230             :     // - FreeSpaceMap
     231             :     // - Map for Map types itself
     232             :     // - NullValue
     233             :     // - Internalized one byte string
     234             :     // - Map for Internalized one byte string
     235             :     // - WeakCell
     236             :     // - TheHoleValue
     237             :     // - HeapNumber
     238             :     // HeapNumber objects require kDoubleUnaligned on 32-bit
     239             :     // platforms. So, without special measures we're risking to serialize
     240             :     // object, requiring alignment before FreeSpaceMap is fully serialized.
     241             :     v8::internal::Handle<Map> map(
     242           5 :         internal_isolate->heap()->one_byte_internalized_string_map());
     243           5 :     Map::WeakCellForMap(map);
     244             :     // Need to avoid DCHECKs inside SnapshotCreator.
     245           5 :     snapshot_creator.SetDefaultContext(v8::Context::New(isolate));
     246             :   }
     247             : 
     248             :   v8::StartupData startup_data = snapshot_creator.CreateBlob(
     249           5 :       v8::SnapshotCreator::FunctionCodeHandling::kKeep);
     250             : 
     251             :   v8::Isolate::CreateParams params;
     252           5 :   params.snapshot_blob = &startup_data;
     253           5 :   params.array_buffer_allocator = CcTest::array_buffer_allocator();
     254           5 :   isolate = v8::Isolate::New(params);
     255             : 
     256             :   {
     257           5 :     v8::HandleScope handle_scope(isolate);
     258             :     v8::Isolate::Scope isolate_scope(isolate);
     259             : 
     260           5 :     v8::Local<v8::Context> env = v8::Context::New(isolate);
     261           5 :     env->Enter();
     262             : 
     263          10 :     SanityCheck(isolate);
     264             :   }
     265           5 :   isolate->Dispose();
     266           5 :   delete[] startup_data.data;
     267           5 : }
     268             : 
     269       23723 : UNINITIALIZED_TEST(StartupSerializerTwice) {
     270             :   DisableLazyDeserialization();
     271             :   DisableAlwaysOpt();
     272           5 :   v8::Isolate* isolate = TestIsolate::NewInitialized(true);
     273           5 :   StartupBlobs blobs1 = Serialize(isolate);
     274           5 :   StartupBlobs blobs2 = Serialize(isolate);
     275           5 :   isolate->Dispose();
     276           5 :   blobs1.Dispose();
     277           5 :   isolate = Deserialize(blobs2);
     278           5 :   blobs2.Dispose();
     279             :   {
     280             :     v8::Isolate::Scope isolate_scope(isolate);
     281          10 :     v8::HandleScope handle_scope(isolate);
     282             : 
     283           5 :     v8::Local<v8::Context> env = v8::Context::New(isolate);
     284           5 :     env->Enter();
     285             : 
     286           5 :     SanityCheck(isolate);
     287             :   }
     288           5 :   isolate->Dispose();
     289           5 : }
     290             : 
     291       23723 : UNINITIALIZED_TEST(StartupSerializerOnceRunScript) {
     292             :   DisableLazyDeserialization();
     293             :   DisableAlwaysOpt();
     294           5 :   v8::Isolate* isolate = TestIsolate::NewInitialized(true);
     295           5 :   StartupBlobs blobs = Serialize(isolate);
     296           5 :   isolate->Dispose();
     297           5 :   isolate = Deserialize(blobs);
     298           5 :   blobs.Dispose();
     299             :   {
     300             :     v8::Isolate::Scope isolate_scope(isolate);
     301          10 :     v8::HandleScope handle_scope(isolate);
     302             : 
     303             : 
     304           5 :     v8::Local<v8::Context> env = v8::Context::New(isolate);
     305           5 :     env->Enter();
     306             : 
     307             :     const char* c_source = "\"1234\".length";
     308             :     v8::Local<v8::Script> script = v8_compile(c_source);
     309           5 :     v8::Maybe<int32_t> result = script->Run(isolate->GetCurrentContext())
     310           5 :                                     .ToLocalChecked()
     311          10 :                                     ->Int32Value(isolate->GetCurrentContext());
     312           5 :     CHECK_EQ(4, result.FromJust());
     313             :   }
     314           5 :   isolate->Dispose();
     315           5 : }
     316             : 
     317       23723 : UNINITIALIZED_TEST(StartupSerializerTwiceRunScript) {
     318             :   DisableLazyDeserialization();
     319             :   DisableAlwaysOpt();
     320           5 :   v8::Isolate* isolate = TestIsolate::NewInitialized(true);
     321           5 :   StartupBlobs blobs1 = Serialize(isolate);
     322           5 :   StartupBlobs blobs2 = Serialize(isolate);
     323           5 :   isolate->Dispose();
     324           5 :   blobs1.Dispose();
     325           5 :   isolate = Deserialize(blobs2);
     326           5 :   blobs2.Dispose();
     327             :   {
     328             :     v8::Isolate::Scope isolate_scope(isolate);
     329          10 :     v8::HandleScope handle_scope(isolate);
     330             : 
     331           5 :     v8::Local<v8::Context> env = v8::Context::New(isolate);
     332           5 :     env->Enter();
     333             : 
     334             :     const char* c_source = "\"1234\".length";
     335             :     v8::Local<v8::Script> script = v8_compile(c_source);
     336           5 :     v8::Maybe<int32_t> result = script->Run(isolate->GetCurrentContext())
     337           5 :                                     .ToLocalChecked()
     338          10 :                                     ->Int32Value(isolate->GetCurrentContext());
     339           5 :     CHECK_EQ(4, result.FromJust());
     340             :   }
     341           5 :   isolate->Dispose();
     342           5 : }
     343             : 
     344           5 : static void PartiallySerializeContext(Vector<const byte>* startup_blob_out,
     345             :                                       Vector<const byte>* builtin_blob_out,
     346             :                                       Vector<const byte>* partial_blob_out) {
     347           5 :   v8::Isolate* v8_isolate = TestIsolate::NewInitialized(true);
     348             :   Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
     349           5 :   Heap* heap = isolate->heap();
     350             :   {
     351             :     v8::Isolate::Scope isolate_scope(v8_isolate);
     352             : 
     353             :     v8::Persistent<v8::Context> env;
     354             :     {
     355             :       HandleScope scope(isolate);
     356           5 :       env.Reset(v8_isolate, v8::Context::New(v8_isolate));
     357             :     }
     358           5 :     CHECK(!env.IsEmpty());
     359             :     {
     360           5 :       v8::HandleScope handle_scope(v8_isolate);
     361           5 :       v8::Local<v8::Context>::New(v8_isolate, env)->Enter();
     362             :     }
     363             : 
     364             :     // If we don't do this then we end up with a stray root pointing at the
     365             :     // context even after we have disposed of env.
     366           5 :     heap->CollectAllAvailableGarbage(i::GarbageCollectionReason::kTesting);
     367             : 
     368             :     {
     369           5 :       v8::HandleScope handle_scope(v8_isolate);
     370           5 :       v8::Local<v8::Context>::New(v8_isolate, env)->Exit();
     371             :     }
     372             : 
     373           5 :     i::Object* raw_context = *v8::Utils::OpenPersistent(env);
     374             : 
     375             :     env.Reset();
     376             : 
     377             :     SnapshotByteSink startup_sink;
     378             :     StartupSerializer startup_serializer(
     379          10 :         isolate, v8::SnapshotCreator::FunctionCodeHandling::kClear);
     380           5 :     startup_serializer.SerializeStrongReferences();
     381             : 
     382             :     SnapshotByteSink partial_sink;
     383             :     PartialSerializer partial_serializer(isolate, &startup_serializer,
     384          10 :                                          v8::SerializeInternalFieldsCallback());
     385           5 :     partial_serializer.Serialize(&raw_context, false);
     386             : 
     387          10 :     i::BuiltinSerializer builtin_serializer(isolate, &startup_serializer);
     388           5 :     builtin_serializer.SerializeBuiltins();
     389             : 
     390           5 :     startup_serializer.SerializeWeakReferencesAndDeferred();
     391             : 
     392           5 :     SnapshotData startup_snapshot(&startup_serializer);
     393           5 :     BuiltinSnapshotData builtin_snapshot(&builtin_serializer);
     394           5 :     SnapshotData partial_snapshot(&partial_serializer);
     395             : 
     396          10 :     *partial_blob_out = WritePayload(partial_snapshot.RawData());
     397          10 :     *builtin_blob_out = WritePayload(builtin_snapshot.RawData());
     398          10 :     *startup_blob_out = WritePayload(startup_snapshot.RawData());
     399             :   }
     400           5 :   v8_isolate->Dispose();
     401           5 : }
     402             : 
     403       23723 : UNINITIALIZED_TEST(PartialSerializerContext) {
     404             :   DisableLazyDeserialization();
     405             :   DisableAlwaysOpt();
     406           5 :   Vector<const byte> startup_blob;
     407           5 :   Vector<const byte> builtin_blob;
     408           5 :   Vector<const byte> partial_blob;
     409           5 :   PartiallySerializeContext(&startup_blob, &builtin_blob, &partial_blob);
     410             : 
     411           5 :   StartupBlobs blobs = {startup_blob, builtin_blob};
     412           5 :   v8::Isolate* v8_isolate = InitializeFromBlob(blobs);
     413           5 :   CHECK(v8_isolate);
     414           5 :   blobs.Dispose();
     415             :   {
     416             :     v8::Isolate::Scope isolate_scope(v8_isolate);
     417             : 
     418             :     Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
     419             :     HandleScope handle_scope(isolate);
     420             :     Handle<Object> root;
     421             :     Handle<JSGlobalProxy> global_proxy =
     422             :         isolate->factory()->NewUninitializedJSGlobalProxy(
     423           5 :             JSGlobalProxy::SizeWithEmbedderFields(0));
     424             :     {
     425             :       SnapshotData snapshot_data(partial_blob);
     426             :       root = PartialDeserializer::DeserializeContext(
     427             :                  isolate, &snapshot_data, false, global_proxy,
     428           5 :                  v8::DeserializeInternalFieldsCallback())
     429          10 :                  .ToHandleChecked();
     430           5 :       CHECK(root->IsContext());
     431          10 :       CHECK(Handle<Context>::cast(root)->global_proxy() == *global_proxy);
     432             :     }
     433             : 
     434             :     Handle<Object> root2;
     435             :     {
     436             :       SnapshotData snapshot_data(partial_blob);
     437             :       root2 = PartialDeserializer::DeserializeContext(
     438             :                   isolate, &snapshot_data, false, global_proxy,
     439           5 :                   v8::DeserializeInternalFieldsCallback())
     440          10 :                   .ToHandleChecked();
     441           5 :       CHECK(root2->IsContext());
     442           5 :       CHECK(!root.is_identical_to(root2));
     443             :     }
     444             :     partial_blob.Dispose();
     445             :   }
     446           5 :   v8_isolate->Dispose();
     447           5 : }
     448             : 
     449           5 : static void PartiallySerializeCustomContext(
     450             :     Vector<const byte>* startup_blob_out, Vector<const byte>* builtin_blob_out,
     451             :     Vector<const byte>* partial_blob_out) {
     452           5 :   v8::Isolate* v8_isolate = TestIsolate::NewInitialized(true);
     453             :   Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
     454             :   {
     455             :     v8::Isolate::Scope isolate_scope(v8_isolate);
     456             : 
     457             :     v8::Persistent<v8::Context> env;
     458             :     {
     459             :       HandleScope scope(isolate);
     460          10 :       env.Reset(v8_isolate, v8::Context::New(v8_isolate));
     461             :     }
     462           5 :     CHECK(!env.IsEmpty());
     463             :     {
     464           5 :       v8::HandleScope handle_scope(v8_isolate);
     465           5 :       v8::Local<v8::Context>::New(v8_isolate, env)->Enter();
     466             :       // After execution, e's function context refers to the global object.
     467             :       CompileRun(
     468             :           "var e;"
     469             :           "(function() {"
     470             :           "  e = function(s) { return eval (s); }"
     471             :           "})();"
     472             :           "var o = this;"
     473             :           "var r = Math.random();"
     474             :           "var c = Math.sin(0) + Math.cos(0);"
     475             :           "var f = (function(a, b) { return a + b; }).bind(1, 2, 3);"
     476             :           "var s = parseInt('12345');");
     477             : 
     478             :       Vector<const uint8_t> source = ConstructSource(
     479             :           STATIC_CHAR_VECTOR("function g() { return [,"),
     480             :           STATIC_CHAR_VECTOR("1,"),
     481           5 :           STATIC_CHAR_VECTOR("];} a = g(); b = g(); b.push(1);"), 100000);
     482             :       v8::MaybeLocal<v8::String> source_str = v8::String::NewFromOneByte(
     483             :           v8_isolate, source.start(), v8::NewStringType::kNormal,
     484           5 :           source.length());
     485           5 :       CompileRun(source_str.ToLocalChecked());
     486           5 :       source.Dispose();
     487             :     }
     488             :     // If we don't do this then we end up with a stray root pointing at the
     489             :     // context even after we have disposed of env.
     490             :     isolate->heap()->CollectAllAvailableGarbage(
     491           5 :         i::GarbageCollectionReason::kTesting);
     492             : 
     493             :     {
     494           5 :       v8::HandleScope handle_scope(v8_isolate);
     495           5 :       v8::Local<v8::Context>::New(v8_isolate, env)->Exit();
     496             :     }
     497             : 
     498           5 :     i::Object* raw_context = *v8::Utils::OpenPersistent(env);
     499             : 
     500             :     env.Reset();
     501             : 
     502             :     SnapshotByteSink startup_sink;
     503             :     StartupSerializer startup_serializer(
     504          10 :         isolate, v8::SnapshotCreator::FunctionCodeHandling::kClear);
     505           5 :     startup_serializer.SerializeStrongReferences();
     506             : 
     507             :     SnapshotByteSink partial_sink;
     508             :     PartialSerializer partial_serializer(isolate, &startup_serializer,
     509          10 :                                          v8::SerializeInternalFieldsCallback());
     510           5 :     partial_serializer.Serialize(&raw_context, false);
     511             : 
     512          10 :     i::BuiltinSerializer builtin_serializer(isolate, &startup_serializer);
     513           5 :     builtin_serializer.SerializeBuiltins();
     514             : 
     515           5 :     startup_serializer.SerializeWeakReferencesAndDeferred();
     516             : 
     517           5 :     SnapshotData startup_snapshot(&startup_serializer);
     518           5 :     BuiltinSnapshotData builtin_snapshot(&builtin_serializer);
     519           5 :     SnapshotData partial_snapshot(&partial_serializer);
     520             : 
     521          10 :     *partial_blob_out = WritePayload(partial_snapshot.RawData());
     522          10 :     *builtin_blob_out = WritePayload(builtin_snapshot.RawData());
     523          10 :     *startup_blob_out = WritePayload(startup_snapshot.RawData());
     524             :   }
     525           5 :   v8_isolate->Dispose();
     526           5 : }
     527             : 
     528       23723 : UNINITIALIZED_TEST(PartialSerializerCustomContext) {
     529             :   DisableLazyDeserialization();
     530             :   DisableAlwaysOpt();
     531           5 :   Vector<const byte> startup_blob;
     532           5 :   Vector<const byte> builtin_blob;
     533           5 :   Vector<const byte> partial_blob;
     534           5 :   PartiallySerializeCustomContext(&startup_blob, &builtin_blob, &partial_blob);
     535             : 
     536           5 :   StartupBlobs blobs = {startup_blob, builtin_blob};
     537           5 :   v8::Isolate* v8_isolate = InitializeFromBlob(blobs);
     538           5 :   CHECK(v8_isolate);
     539           5 :   blobs.Dispose();
     540             :   {
     541             :     v8::Isolate::Scope isolate_scope(v8_isolate);
     542             : 
     543             :     Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
     544             :     HandleScope handle_scope(isolate);
     545             :     Handle<Object> root;
     546             :     Handle<JSGlobalProxy> global_proxy =
     547             :         isolate->factory()->NewUninitializedJSGlobalProxy(
     548           5 :             JSGlobalProxy::SizeWithEmbedderFields(0));
     549             :     {
     550             :       SnapshotData snapshot_data(partial_blob);
     551             :       root = PartialDeserializer::DeserializeContext(
     552             :                  isolate, &snapshot_data, false, global_proxy,
     553           5 :                  v8::DeserializeInternalFieldsCallback())
     554          10 :                  .ToHandleChecked();
     555           5 :       CHECK(root->IsContext());
     556             :       Handle<Context> context = Handle<Context>::cast(root);
     557             : 
     558             :       // Add context to the weak native context list
     559             :       context->set(Context::NEXT_CONTEXT_LINK,
     560             :                    isolate->heap()->native_contexts_list(),
     561          10 :                    UPDATE_WEAK_WRITE_BARRIER);
     562             :       isolate->heap()->set_native_contexts_list(*context);
     563             : 
     564          10 :       CHECK(context->global_proxy() == *global_proxy);
     565           5 :       Handle<String> o = isolate->factory()->NewStringFromAsciiChecked("o");
     566           5 :       Handle<JSObject> global_object(context->global_object(), isolate);
     567           5 :       Handle<Object> property = JSReceiver::GetDataProperty(global_object, o);
     568           5 :       CHECK(property.is_identical_to(global_proxy));
     569             : 
     570             :       v8::Local<v8::Context> v8_context = v8::Utils::ToLocal(context);
     571             :       v8::Context::Scope context_scope(v8_context);
     572             :       double r = CompileRun("r")
     573           5 :                      ->ToNumber(v8_isolate->GetCurrentContext())
     574           5 :                      .ToLocalChecked()
     575           5 :                      ->Value();
     576           5 :       CHECK(0.0 <= r && r < 1.0);
     577             :       // Math.random still works.
     578             :       double random = CompileRun("Math.random()")
     579           5 :                           ->ToNumber(v8_isolate->GetCurrentContext())
     580           5 :                           .ToLocalChecked()
     581           5 :                           ->Value();
     582           5 :       CHECK(0.0 <= random && random < 1.0);
     583             :       double c = CompileRun("c")
     584           5 :                      ->ToNumber(v8_isolate->GetCurrentContext())
     585           5 :                      .ToLocalChecked()
     586           5 :                      ->Value();
     587           5 :       CHECK_EQ(1, c);
     588             :       int f = CompileRun("f()")
     589           5 :                   ->ToNumber(v8_isolate->GetCurrentContext())
     590           5 :                   .ToLocalChecked()
     591           5 :                   ->Int32Value(v8_isolate->GetCurrentContext())
     592          10 :                   .FromJust();
     593           5 :       CHECK_EQ(5, f);
     594             :       f = CompileRun("e('f()')")
     595           5 :               ->ToNumber(v8_isolate->GetCurrentContext())
     596           5 :               .ToLocalChecked()
     597           5 :               ->Int32Value(v8_isolate->GetCurrentContext())
     598          10 :               .FromJust();
     599           5 :       CHECK_EQ(5, f);
     600             :       v8::Local<v8::String> s = CompileRun("s")
     601           5 :                                     ->ToString(v8_isolate->GetCurrentContext())
     602           5 :                                     .ToLocalChecked();
     603          15 :       CHECK(s->Equals(v8_isolate->GetCurrentContext(), v8_str("12345"))
     604             :                 .FromJust());
     605             :       int a = CompileRun("a.length")
     606           5 :                   ->ToNumber(v8_isolate->GetCurrentContext())
     607           5 :                   .ToLocalChecked()
     608           5 :                   ->Int32Value(v8_isolate->GetCurrentContext())
     609          10 :                   .FromJust();
     610           5 :       CHECK_EQ(100001, a);
     611             :       int b = CompileRun("b.length")
     612           5 :                   ->ToNumber(v8_isolate->GetCurrentContext())
     613           5 :                   .ToLocalChecked()
     614           5 :                   ->Int32Value(v8_isolate->GetCurrentContext())
     615          10 :                   .FromJust();
     616           5 :       CHECK_EQ(100002, b);
     617             :     }
     618             :     partial_blob.Dispose();
     619             :   }
     620           5 :   v8_isolate->Dispose();
     621           5 : }
     622             : 
     623       23723 : TEST(CustomSnapshotDataBlob1) {
     624             :   DisableAlwaysOpt();
     625             :   const char* source1 = "function f() { return 42; }";
     626             : 
     627           5 :   v8::StartupData data1 = v8::V8::CreateSnapshotDataBlob(source1);
     628             : 
     629             :   v8::Isolate::CreateParams params1;
     630           5 :   params1.snapshot_blob = &data1;
     631           5 :   params1.array_buffer_allocator = CcTest::array_buffer_allocator();
     632             : 
     633             :   // Test-appropriate equivalent of v8::Isolate::New.
     634           5 :   v8::Isolate* isolate1 = TestIsolate::New(params1);
     635             :   {
     636             :     v8::Isolate::Scope i_scope(isolate1);
     637          10 :     v8::HandleScope h_scope(isolate1);
     638           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate1);
     639           5 :     delete[] data1.data;  // We can dispose of the snapshot blob now.
     640             :     v8::Context::Scope c_scope(context);
     641             :     v8::Maybe<int32_t> result =
     642          10 :         CompileRun("f()")->Int32Value(isolate1->GetCurrentContext());
     643           5 :     CHECK_EQ(42, result.FromJust());
     644           5 :     CHECK(CompileRun("this.g")->IsUndefined());
     645             :   }
     646           5 :   isolate1->Dispose();
     647           5 : }
     648             : 
     649             : struct InternalFieldData {
     650             :   uint32_t data;
     651             : };
     652             : 
     653         215 : v8::StartupData SerializeInternalFields(v8::Local<v8::Object> holder, int index,
     654             :                                         void* data) {
     655         215 :   CHECK_EQ(reinterpret_cast<void*>(2016), data);
     656             :   InternalFieldData* embedder_field = static_cast<InternalFieldData*>(
     657             :       holder->GetAlignedPointerFromInternalField(index));
     658         215 :   if (embedder_field == nullptr) return {nullptr, 0};
     659             :   int size = sizeof(*embedder_field);
     660          15 :   char* payload = new char[size];
     661             :   // We simply use memcpy to serialize the content.
     662             :   memcpy(payload, embedder_field, size);
     663          15 :   return {payload, size};
     664             : }
     665             : 
     666       23718 : std::vector<InternalFieldData*> deserialized_data;
     667             : 
     668         215 : void DeserializeInternalFields(v8::Local<v8::Object> holder, int index,
     669             :                                v8::StartupData payload, void* data) {
     670         215 :   if (payload.raw_size == 0) {
     671         200 :     holder->SetAlignedPointerInInternalField(index, nullptr);
     672         415 :     return;
     673             :   }
     674          15 :   CHECK_EQ(reinterpret_cast<void*>(2017), data);
     675          15 :   InternalFieldData* embedder_field = new InternalFieldData{0};
     676          15 :   memcpy(embedder_field, payload.data, payload.raw_size);
     677          15 :   holder->SetAlignedPointerInInternalField(index, embedder_field);
     678          15 :   deserialized_data.push_back(embedder_field);
     679             : }
     680             : 
     681             : typedef std::vector<std::tuple<const char*, int32_t>> Int32Expectations;
     682             : 
     683          50 : void TestInt32Expectations(const Int32Expectations& expectations) {
     684         300 :   for (const auto& e : expectations) {
     685         200 :     ExpectInt32(std::get<0>(e), std::get<1>(e));
     686             :   }
     687          50 : }
     688             : 
     689          15 : void TypedArrayTestHelper(const char* code,
     690             :                           const Int32Expectations& expectations) {
     691             :   DisableAlwaysOpt();
     692          15 :   i::FLAG_allow_natives_syntax = true;
     693             :   v8::StartupData blob;
     694             :   {
     695          15 :     v8::SnapshotCreator creator;
     696          15 :     v8::Isolate* isolate = creator.GetIsolate();
     697             :     {
     698          15 :       v8::HandleScope handle_scope(isolate);
     699          15 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
     700             :       v8::Context::Scope context_scope(context);
     701             : 
     702             :       CompileRun(code);
     703          15 :       TestInt32Expectations(expectations);
     704             :       creator.SetDefaultContext(
     705             :           context, v8::SerializeInternalFieldsCallback(
     706          30 :                        SerializeInternalFields, reinterpret_cast<void*>(2016)));
     707             :     }
     708             :     blob =
     709          15 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
     710             :   }
     711             : 
     712             :   v8::Isolate::CreateParams create_params;
     713          15 :   create_params.snapshot_blob = &blob;
     714          15 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
     715          15 :   v8::Isolate* isolate = TestIsolate::New(create_params);
     716             :   {
     717             :     v8::Isolate::Scope i_scope(isolate);
     718          30 :     v8::HandleScope h_scope(isolate);
     719             :     v8::Local<v8::Context> context = v8::Context::New(
     720             :         isolate, nullptr, v8::MaybeLocal<v8::ObjectTemplate>(),
     721             :         v8::MaybeLocal<v8::Value>(),
     722             :         v8::DeserializeInternalFieldsCallback(DeserializeInternalFields,
     723          15 :                                               reinterpret_cast<void*>(2017)));
     724          15 :     delete[] blob.data;  // We can dispose of the snapshot blob now.
     725          15 :     CHECK(deserialized_data.empty());  // We do not expect any embedder data.
     726             :     v8::Context::Scope c_scope(context);
     727          15 :     TestInt32Expectations(expectations);
     728             :   }
     729          15 :   isolate->Dispose();
     730          15 : }
     731             : 
     732       23723 : TEST(CustomSnapshotDataBlobWithOffHeapTypedArray) {
     733             :   const char* code =
     734             :       "var x = new Uint8Array(128);"
     735             :       "x[0] = 12;"
     736             :       "var arr = new Array(17);"
     737             :       "arr[1] = 24;"
     738             :       "var y = new Uint32Array(arr);"
     739             :       "var buffer = new ArrayBuffer(128);"
     740             :       "var z = new Int16Array(buffer);"
     741             :       "z[0] = 48;";
     742             :   Int32Expectations expectations = {std::make_tuple("x[0]", 12),
     743             :                                     std::make_tuple("y[1]", 24),
     744           5 :                                     std::make_tuple("z[0]", 48)};
     745             : 
     746           5 :   TypedArrayTestHelper(code, expectations);
     747           5 : }
     748             : 
     749       23723 : TEST(CustomSnapshotDataBlobSharedArrayBuffer) {
     750             :   const char* code =
     751             :       "var x = new Int32Array([12, 24, 48, 96]);"
     752             :       "var y = new Uint8Array(x.buffer)";
     753             :   Int32Expectations expectations = {
     754             :     std::make_tuple("x[0]", 12),
     755             :     std::make_tuple("x[1]", 24),
     756             : #if !V8_TARGET_BIG_ENDIAN
     757             :     std::make_tuple("y[0]", 12),
     758             :     std::make_tuple("y[1]", 0),
     759             :     std::make_tuple("y[2]", 0),
     760             :     std::make_tuple("y[3]", 0),
     761             :     std::make_tuple("y[4]", 24)
     762             : #else
     763             :     std::make_tuple("y[3]", 12),
     764             :     std::make_tuple("y[2]", 0),
     765             :     std::make_tuple("y[1]", 0),
     766             :     std::make_tuple("y[0]", 0),
     767             :     std::make_tuple("y[7]", 24)
     768             : #endif
     769           5 :   };
     770             : 
     771           5 :   TypedArrayTestHelper(code, expectations);
     772           5 : }
     773             : 
     774       23723 : TEST(CustomSnapshotDataBlobDataView) {
     775             :   const char* code =
     776             :       "var x = new Int8Array([1, 2, 3, 4]);"
     777             :       "var v = new DataView(x.buffer)";
     778             :   Int32Expectations expectations = {std::make_tuple("v.getInt8(0)", 1),
     779             :                                     std::make_tuple("v.getInt8(1)", 2),
     780             :                                     std::make_tuple("v.getInt16(0)", 258),
     781           5 :                                     std::make_tuple("v.getInt16(1)", 515)};
     782             : 
     783           5 :   TypedArrayTestHelper(code, expectations);
     784           5 : }
     785             : 
     786       23723 : TEST(CustomSnapshotDataBlobNeuteredArrayBuffer) {
     787             :   const char* code =
     788             :       "var x = new Int16Array([12, 24, 48]);"
     789             :       "%ArrayBufferNeuter(x.buffer);";
     790             :   Int32Expectations expectations = {std::make_tuple("x.buffer.byteLength", 0),
     791           5 :                                     std::make_tuple("x.length", 0)};
     792             : 
     793             :   DisableLazyDeserialization();
     794             :   DisableAlwaysOpt();
     795           5 :   i::FLAG_allow_natives_syntax = true;
     796             :   v8::StartupData blob;
     797             :   {
     798           5 :     v8::SnapshotCreator creator;
     799           5 :     v8::Isolate* isolate = creator.GetIsolate();
     800             :     {
     801           5 :       v8::HandleScope handle_scope(isolate);
     802           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
     803             :       v8::Context::Scope context_scope(context);
     804             : 
     805             :       CompileRun(code);
     806           5 :       TestInt32Expectations(expectations);
     807             :       creator.SetDefaultContext(
     808             :           context, v8::SerializeInternalFieldsCallback(
     809          10 :                        SerializeInternalFields, reinterpret_cast<void*>(2016)));
     810             :     }
     811             :     blob =
     812           5 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
     813             :   }
     814             : 
     815             :   v8::Isolate::CreateParams create_params;
     816           5 :   create_params.snapshot_blob = &blob;
     817           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
     818           5 :   v8::Isolate* isolate = TestIsolate::New(create_params);
     819             :   {
     820             :     v8::Isolate::Scope i_scope(isolate);
     821          10 :     v8::HandleScope h_scope(isolate);
     822             :     v8::Local<v8::Context> context = v8::Context::New(
     823             :         isolate, nullptr, v8::MaybeLocal<v8::ObjectTemplate>(),
     824             :         v8::MaybeLocal<v8::Value>(),
     825             :         v8::DeserializeInternalFieldsCallback(DeserializeInternalFields,
     826           5 :                                               reinterpret_cast<void*>(2017)));
     827           5 :     delete[] blob.data;  // We can dispose of the snapshot blob now.
     828             :     v8::Context::Scope c_scope(context);
     829           5 :     TestInt32Expectations(expectations);
     830             : 
     831             :     v8::Local<v8::Value> x = CompileRun("x");
     832           5 :     CHECK(x->IsTypedArray());
     833             :     i::Handle<i::JSTypedArray> array =
     834             :         i::Handle<i::JSTypedArray>::cast(v8::Utils::OpenHandle(*x));
     835           5 :     CHECK(array->WasNeutered());
     836           5 :     CHECK_NULL(
     837             :         FixedTypedArrayBase::cast(array->elements())->external_pointer());
     838             :   }
     839           5 :   isolate->Dispose();
     840           5 : }
     841             : 
     842          15 : i::Handle<i::JSArrayBuffer> GetBufferFromTypedArray(
     843             :     v8::Local<v8::Value> typed_array) {
     844          15 :   CHECK(typed_array->IsTypedArray());
     845             : 
     846             :   i::Handle<i::JSArrayBufferView> view = i::Handle<i::JSArrayBufferView>::cast(
     847             :       v8::Utils::OpenHandle(*typed_array));
     848             : 
     849          15 :   return i::handle(i::JSArrayBuffer::cast(view->buffer()));
     850             : }
     851             : 
     852       23723 : TEST(CustomSnapshotDataBlobOnOrOffHeapTypedArray) {
     853             :   const char* code =
     854             :       "var x = new Uint8Array(8);"
     855             :       "x[0] = 12;"
     856             :       "x[7] = 24;"
     857             :       "var y = new Int16Array([12, 24, 48]);"
     858             :       "var z = new Int32Array(64);"
     859             :       "z[0] = 96;";
     860             :   Int32Expectations expectations = {
     861             :       std::make_tuple("x[0]", 12), std::make_tuple("x[7]", 24),
     862           5 :       std::make_tuple("y[2]", 48), std::make_tuple("z[0]", 96)};
     863             : 
     864             :   DisableAlwaysOpt();
     865           5 :   i::FLAG_allow_natives_syntax = true;
     866             :   v8::StartupData blob;
     867             :   {
     868           5 :     v8::SnapshotCreator creator;
     869           5 :     v8::Isolate* isolate = creator.GetIsolate();
     870             :     {
     871           5 :       v8::HandleScope handle_scope(isolate);
     872           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
     873             :       v8::Context::Scope context_scope(context);
     874             : 
     875             :       CompileRun(code);
     876           5 :       TestInt32Expectations(expectations);
     877             :       creator.SetDefaultContext(
     878             :           context, v8::SerializeInternalFieldsCallback(
     879          10 :                        SerializeInternalFields, reinterpret_cast<void*>(2016)));
     880             :     }
     881             :     blob =
     882           5 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
     883             :   }
     884             : 
     885             :   v8::Isolate::CreateParams create_params;
     886           5 :   create_params.snapshot_blob = &blob;
     887           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
     888           5 :   v8::Isolate* isolate = TestIsolate::New(create_params);
     889             :   {
     890             :     v8::Isolate::Scope i_scope(isolate);
     891          10 :     v8::HandleScope h_scope(isolate);
     892             :     v8::Local<v8::Context> context = v8::Context::New(
     893             :         isolate, nullptr, v8::MaybeLocal<v8::ObjectTemplate>(),
     894             :         v8::MaybeLocal<v8::Value>(),
     895             :         v8::DeserializeInternalFieldsCallback(DeserializeInternalFields,
     896           5 :                                               reinterpret_cast<void*>(2017)));
     897           5 :     delete[] blob.data;  // We can dispose of the snapshot blob now.
     898             :     v8::Context::Scope c_scope(context);
     899           5 :     TestInt32Expectations(expectations);
     900             : 
     901             :     i::Handle<i::JSArrayBuffer> buffer =
     902           5 :         GetBufferFromTypedArray(CompileRun("x"));
     903             :     // The resulting buffer should be on-heap.
     904           5 :     CHECK_NULL(buffer->backing_store());
     905             : 
     906           5 :     buffer = GetBufferFromTypedArray(CompileRun("y"));
     907           5 :     CHECK_NULL(buffer->backing_store());
     908             : 
     909           5 :     buffer = GetBufferFromTypedArray(CompileRun("z"));
     910             :     // The resulting buffer should be off-heap.
     911           5 :     CHECK_NOT_NULL(buffer->backing_store());
     912             :   }
     913           5 :   isolate->Dispose();
     914           5 : }
     915             : 
     916       23723 : TEST(CustomSnapshotDataBlob2) {
     917             :   DisableAlwaysOpt();
     918             :   const char* source2 =
     919             :       "function f() { return g() * 2; }"
     920             :       "function g() { return 43; }"
     921             :       "/./.test('a')";
     922             : 
     923           5 :   v8::StartupData data2 = v8::V8::CreateSnapshotDataBlob(source2);
     924             : 
     925             :   v8::Isolate::CreateParams params2;
     926           5 :   params2.snapshot_blob = &data2;
     927           5 :   params2.array_buffer_allocator = CcTest::array_buffer_allocator();
     928             :   // Test-appropriate equivalent of v8::Isolate::New.
     929           5 :   v8::Isolate* isolate2 = TestIsolate::New(params2);
     930             :   {
     931             :     v8::Isolate::Scope i_scope(isolate2);
     932          10 :     v8::HandleScope h_scope(isolate2);
     933           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate2);
     934           5 :     delete[] data2.data;  // We can dispose of the snapshot blob now.
     935             :     v8::Context::Scope c_scope(context);
     936             :     v8::Maybe<int32_t> result =
     937          10 :         CompileRun("f()")->Int32Value(isolate2->GetCurrentContext());
     938           5 :     CHECK_EQ(86, result.FromJust());
     939          10 :     result = CompileRun("g()")->Int32Value(isolate2->GetCurrentContext());
     940           5 :     CHECK_EQ(43, result.FromJust());
     941             :   }
     942           5 :   isolate2->Dispose();
     943           5 : }
     944             : 
     945           5 : static void SerializationFunctionTemplate(
     946           5 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
     947             :   args.GetReturnValue().Set(args[0]);
     948           5 : }
     949             : 
     950       23723 : TEST(CustomSnapshotDataBlobOutdatedContextWithOverflow) {
     951             :   DisableAlwaysOpt();
     952             :   const char* source1 =
     953             :       "var o = {};"
     954             :       "(function() {"
     955             :       "  function f1(x) { return f2(x) instanceof Array; }"
     956             :       "  function f2(x) { return foo.bar(x); }"
     957             :       "  o.a = f2.bind(null);"
     958             :       "  o.b = 1;"
     959             :       "  o.c = 2;"
     960             :       "  o.d = 3;"
     961             :       "  o.e = 4;"
     962             :       "})();\n";
     963             : 
     964             :   const char* source2 = "o.a(42)";
     965             : 
     966           5 :   v8::StartupData data = v8::V8::CreateSnapshotDataBlob(source1);
     967             : 
     968             :   v8::Isolate::CreateParams params;
     969           5 :   params.snapshot_blob = &data;
     970           5 :   params.array_buffer_allocator = CcTest::array_buffer_allocator();
     971             : 
     972             :   // Test-appropriate equivalent of v8::Isolate::New.
     973           5 :   v8::Isolate* isolate = TestIsolate::New(params);
     974             :   {
     975             :     v8::Isolate::Scope i_scope(isolate);
     976          10 :     v8::HandleScope h_scope(isolate);
     977             : 
     978           5 :     v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);
     979           5 :     v8::Local<v8::ObjectTemplate> property = v8::ObjectTemplate::New(isolate);
     980             :     v8::Local<v8::FunctionTemplate> function =
     981           5 :         v8::FunctionTemplate::New(isolate, SerializationFunctionTemplate);
     982             :     property->Set(isolate, "bar", function);
     983             :     global->Set(isolate, "foo", property);
     984             : 
     985           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate, nullptr, global);
     986           5 :     delete[] data.data;  // We can dispose of the snapshot blob now.
     987             :     v8::Context::Scope c_scope(context);
     988           5 :     v8::Local<v8::Value> result = CompileRun(source2);
     989          10 :     v8::Maybe<bool> compare = v8_str("42")->Equals(
     990          10 :         v8::Isolate::GetCurrent()->GetCurrentContext(), result);
     991           5 :     CHECK(compare.FromJust());
     992             :   }
     993           5 :   isolate->Dispose();
     994           5 : }
     995             : 
     996       23723 : TEST(CustomSnapshotDataBlobWithLocker) {
     997             :   DisableAlwaysOpt();
     998             :   v8::Isolate::CreateParams create_params;
     999           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    1000           5 :   v8::Isolate* isolate0 = v8::Isolate::New(create_params);
    1001             :   {
    1002             :     v8::Locker locker(isolate0);
    1003             :     v8::Isolate::Scope i_scope(isolate0);
    1004          10 :     v8::HandleScope h_scope(isolate0);
    1005           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate0);
    1006             :     v8::Context::Scope c_scope(context);
    1007             :     v8::Maybe<int32_t> result =
    1008          10 :         CompileRun("Math.cos(0)")->Int32Value(isolate0->GetCurrentContext());
    1009          10 :     CHECK_EQ(1, result.FromJust());
    1010             :   }
    1011           5 :   isolate0->Dispose();
    1012             : 
    1013             :   const char* source1 = "function f() { return 42; }";
    1014             : 
    1015           5 :   v8::StartupData data1 = v8::V8::CreateSnapshotDataBlob(source1);
    1016             : 
    1017             :   v8::Isolate::CreateParams params1;
    1018           5 :   params1.snapshot_blob = &data1;
    1019           5 :   params1.array_buffer_allocator = CcTest::array_buffer_allocator();
    1020             :   // Test-appropriate equivalent of v8::Isolate::New.
    1021           5 :   v8::Isolate* isolate1 = TestIsolate::New(params1);
    1022             :   {
    1023             :     v8::Locker locker(isolate1);
    1024             :     v8::Isolate::Scope i_scope(isolate1);
    1025          10 :     v8::HandleScope h_scope(isolate1);
    1026           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate1);
    1027           5 :     delete[] data1.data;  // We can dispose of the snapshot blob now.
    1028             :     v8::Context::Scope c_scope(context);
    1029           5 :     v8::Maybe<int32_t> result = CompileRun("f()")->Int32Value(context);
    1030          10 :     CHECK_EQ(42, result.FromJust());
    1031             :   }
    1032           5 :   isolate1->Dispose();
    1033           5 : }
    1034             : 
    1035       23723 : TEST(CustomSnapshotDataBlobStackOverflow) {
    1036             :   DisableAlwaysOpt();
    1037             :   const char* source =
    1038             :       "var a = [0];"
    1039             :       "var b = a;"
    1040             :       "for (var i = 0; i < 10000; i++) {"
    1041             :       "  var c = [i];"
    1042             :       "  b.push(c);"
    1043             :       "  b.push(c);"
    1044             :       "  b = c;"
    1045             :       "}";
    1046             : 
    1047           5 :   v8::StartupData data = v8::V8::CreateSnapshotDataBlob(source);
    1048             : 
    1049             :   v8::Isolate::CreateParams params;
    1050           5 :   params.snapshot_blob = &data;
    1051           5 :   params.array_buffer_allocator = CcTest::array_buffer_allocator();
    1052             : 
    1053             :   // Test-appropriate equivalent of v8::Isolate::New.
    1054           5 :   v8::Isolate* isolate = TestIsolate::New(params);
    1055             :   {
    1056             :     v8::Isolate::Scope i_scope(isolate);
    1057          10 :     v8::HandleScope h_scope(isolate);
    1058           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate);
    1059           5 :     delete[] data.data;  // We can dispose of the snapshot blob now.
    1060             :     v8::Context::Scope c_scope(context);
    1061             :     const char* test =
    1062             :         "var sum = 0;"
    1063             :         "while (a) {"
    1064             :         "  sum += a[0];"
    1065             :         "  a = a[1];"
    1066             :         "}"
    1067             :         "sum";
    1068             :     v8::Maybe<int32_t> result =
    1069          10 :         CompileRun(test)->Int32Value(isolate->GetCurrentContext());
    1070           5 :     CHECK_EQ(9999 * 5000, result.FromJust());
    1071             :   }
    1072           5 :   isolate->Dispose();
    1073           5 : }
    1074             : 
    1075          35 : bool IsCompiled(const char* name) {
    1076             :   return i::Handle<i::JSFunction>::cast(
    1077             :              v8::Utils::OpenHandle(*CompileRun(name)))
    1078             :       ->shared()
    1079          35 :       ->is_compiled();
    1080             : }
    1081             : 
    1082       23723 : TEST(SnapshotDataBlobWithWarmup) {
    1083             :   DisableLazyDeserialization();
    1084             :   DisableAlwaysOpt();
    1085             :   const char* warmup = "Math.abs(1); Math.random = 1;";
    1086             : 
    1087           5 :   v8::StartupData cold = v8::V8::CreateSnapshotDataBlob();
    1088           5 :   v8::StartupData warm = v8::V8::WarmUpSnapshotDataBlob(cold, warmup);
    1089           5 :   delete[] cold.data;
    1090             : 
    1091             :   v8::Isolate::CreateParams params;
    1092           5 :   params.snapshot_blob = &warm;
    1093           5 :   params.array_buffer_allocator = CcTest::array_buffer_allocator();
    1094             : 
    1095             :   // Test-appropriate equivalent of v8::Isolate::New.
    1096           5 :   v8::Isolate* isolate = TestIsolate::New(params);
    1097             :   {
    1098             :     v8::Isolate::Scope i_scope(isolate);
    1099          10 :     v8::HandleScope h_scope(isolate);
    1100           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate);
    1101           5 :     delete[] warm.data;
    1102             :     v8::Context::Scope c_scope(context);
    1103             :     // Running the warmup script has effect on whether functions are
    1104             :     // pre-compiled, but does not pollute the context.
    1105           5 :     CHECK(IsCompiled("Math.abs"));
    1106           5 :     CHECK(IsCompiled("String.raw"));
    1107           5 :     CHECK(CompileRun("Math.random")->IsFunction());
    1108             :   }
    1109           5 :   isolate->Dispose();
    1110           5 : }
    1111             : 
    1112       23723 : TEST(CustomSnapshotDataBlobWithWarmup) {
    1113             :   DisableLazyDeserialization();
    1114             :   DisableAlwaysOpt();
    1115             :   const char* source =
    1116             :       "function f() { return Math.abs(1); }\n"
    1117             :       "function g() { return String.raw(1); }\n"
    1118             :       "Object.valueOf(1);"
    1119             :       "var a = 5";
    1120             :   const char* warmup = "a = f()";
    1121             : 
    1122           5 :   v8::StartupData cold = v8::V8::CreateSnapshotDataBlob(source);
    1123           5 :   v8::StartupData warm = v8::V8::WarmUpSnapshotDataBlob(cold, warmup);
    1124           5 :   delete[] cold.data;
    1125             : 
    1126             :   v8::Isolate::CreateParams params;
    1127           5 :   params.snapshot_blob = &warm;
    1128           5 :   params.array_buffer_allocator = CcTest::array_buffer_allocator();
    1129             : 
    1130             :   // Test-appropriate equivalent of v8::Isolate::New.
    1131           5 :   v8::Isolate* isolate = TestIsolate::New(params);
    1132             :   {
    1133             :     v8::Isolate::Scope i_scope(isolate);
    1134          10 :     v8::HandleScope h_scope(isolate);
    1135           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate);
    1136           5 :     delete[] warm.data;
    1137             :     v8::Context::Scope c_scope(context);
    1138             :     // Running the warmup script has effect on whether functions are
    1139             :     // pre-compiled, but does not pollute the context.
    1140           5 :     CHECK(IsCompiled("f"));
    1141           5 :     CHECK(IsCompiled("Math.abs"));
    1142           5 :     CHECK(!IsCompiled("g"));
    1143           5 :     CHECK(IsCompiled("String.raw"));
    1144           5 :     CHECK(!IsCompiled("Array.prototype.sort"));
    1145          10 :     CHECK_EQ(5, CompileRun("a")->Int32Value(context).FromJust());
    1146             :   }
    1147           5 :   isolate->Dispose();
    1148           5 : }
    1149             : 
    1150       23723 : TEST(CustomSnapshotDataBlobImmortalImmovableRoots) {
    1151             :   DisableAlwaysOpt();
    1152             :   // Flood the startup snapshot with shared function infos. If they are
    1153             :   // serialized before the immortal immovable root, the root will no longer end
    1154             :   // up on the first page.
    1155             :   Vector<const uint8_t> source =
    1156             :       ConstructSource(STATIC_CHAR_VECTOR("var a = [];"),
    1157             :                       STATIC_CHAR_VECTOR("a.push(function() {return 7});"),
    1158           5 :                       STATIC_CHAR_VECTOR("\0"), 10000);
    1159             : 
    1160             :   v8::StartupData data = v8::V8::CreateSnapshotDataBlob(
    1161           5 :       reinterpret_cast<const char*>(source.start()));
    1162             : 
    1163             :   v8::Isolate::CreateParams params;
    1164           5 :   params.snapshot_blob = &data;
    1165           5 :   params.array_buffer_allocator = CcTest::array_buffer_allocator();
    1166             : 
    1167             :   // Test-appropriate equivalent of v8::Isolate::New.
    1168           5 :   v8::Isolate* isolate = TestIsolate::New(params);
    1169             :   {
    1170             :     v8::Isolate::Scope i_scope(isolate);
    1171          10 :     v8::HandleScope h_scope(isolate);
    1172           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate);
    1173           5 :     delete[] data.data;  // We can dispose of the snapshot blob now.
    1174             :     v8::Context::Scope c_scope(context);
    1175          10 :     CHECK_EQ(7, CompileRun("a[0]()")->Int32Value(context).FromJust());
    1176             :   }
    1177           5 :   isolate->Dispose();
    1178             :   source.Dispose();
    1179           5 : }
    1180             : 
    1181       23723 : TEST(TestThatAlwaysSucceeds) {
    1182           5 : }
    1183             : 
    1184             : 
    1185       23718 : TEST(TestThatAlwaysFails) {
    1186             :   bool ArtificialFailure = false;
    1187           0 :   CHECK(ArtificialFailure);
    1188             : }
    1189             : 
    1190             : 
    1191          20 : int CountBuiltins() {
    1192             :   // Check that we have not deserialized any additional builtin.
    1193          20 :   HeapIterator iterator(CcTest::heap());
    1194             :   DisallowHeapAllocation no_allocation;
    1195             :   int counter = 0;
    1196      160405 :   for (HeapObject* obj = iterator.next(); obj != nullptr;
    1197             :        obj = iterator.next()) {
    1198      179552 :     if (obj->IsCode() && Code::cast(obj)->kind() == Code::BUILTIN) counter++;
    1199             :   }
    1200          20 :   return counter;
    1201             : }
    1202             : 
    1203             : 
    1204         100 : static Handle<SharedFunctionInfo> CompileScript(
    1205             :     Isolate* isolate, Handle<String> source, Handle<String> name,
    1206             :     ScriptData** cached_data, v8::ScriptCompiler::CompileOptions options) {
    1207             :   return Compiler::GetSharedFunctionInfoForScript(
    1208             :              source, name, 0, 0, v8::ScriptOriginOptions(), Handle<Object>(),
    1209             :              Handle<Context>(isolate->native_context()), nullptr, cached_data,
    1210         200 :              options, NOT_NATIVES_CODE, Handle<FixedArray>())
    1211         300 :       .ToHandleChecked();
    1212             : }
    1213             : 
    1214       23723 : TEST(CodeSerializerOnePlusOne) {
    1215           5 :   LocalContext context;
    1216          10 :   Isolate* isolate = CcTest::i_isolate();
    1217           5 :   isolate->compilation_cache()->Disable();  // Disable same-isolate code cache.
    1218             : 
    1219          10 :   v8::HandleScope scope(CcTest::isolate());
    1220             : 
    1221             :   const char* source = "1 + 1";
    1222             : 
    1223             :   Handle<String> orig_source = isolate->factory()
    1224             :                                    ->NewStringFromUtf8(CStrVector(source))
    1225          10 :                                    .ToHandleChecked();
    1226             :   Handle<String> copy_source = isolate->factory()
    1227             :                                    ->NewStringFromUtf8(CStrVector(source))
    1228          10 :                                    .ToHandleChecked();
    1229           5 :   CHECK(!orig_source.is_identical_to(copy_source));
    1230           5 :   CHECK(orig_source->Equals(*copy_source));
    1231             : 
    1232           5 :   ScriptData* cache = nullptr;
    1233             : 
    1234             :   Handle<SharedFunctionInfo> orig =
    1235             :       CompileScript(isolate, orig_source, Handle<String>(), &cache,
    1236           5 :                     v8::ScriptCompiler::kProduceCodeCache);
    1237             : 
    1238           5 :   int builtins_count = CountBuiltins();
    1239             : 
    1240             :   Handle<SharedFunctionInfo> copy;
    1241             :   {
    1242             :     DisallowCompilation no_compile_expected(isolate);
    1243             :     copy = CompileScript(isolate, copy_source, Handle<String>(), &cache,
    1244           5 :                          v8::ScriptCompiler::kConsumeCodeCache);
    1245             :   }
    1246             : 
    1247           5 :   CHECK_NE(*orig, *copy);
    1248           5 :   CHECK(Script::cast(copy->script())->source() == *copy_source);
    1249             : 
    1250             :   Handle<JSFunction> copy_fun =
    1251             :       isolate->factory()->NewFunctionFromSharedFunctionInfo(
    1252           5 :           copy, isolate->native_context());
    1253           5 :   Handle<JSObject> global(isolate->context()->global_object());
    1254             :   Handle<Object> copy_result =
    1255          10 :       Execution::Call(isolate, copy_fun, global, 0, nullptr).ToHandleChecked();
    1256           5 :   CHECK_EQ(2, Handle<Smi>::cast(copy_result)->value());
    1257             : 
    1258           5 :   CHECK_EQ(builtins_count, CountBuiltins());
    1259             : 
    1260          15 :   delete cache;
    1261           5 : }
    1262             : 
    1263       23723 : TEST(CodeSerializerPromotedToCompilationCache) {
    1264           5 :   LocalContext context;
    1265           5 :   Isolate* isolate = CcTest::i_isolate();
    1266             : 
    1267          10 :   v8::HandleScope scope(CcTest::isolate());
    1268             : 
    1269             :   const char* source = "1 + 1";
    1270             : 
    1271             :   Handle<String> src = isolate->factory()
    1272             :                            ->NewStringFromUtf8(CStrVector(source))
    1273          10 :                            .ToHandleChecked();
    1274           5 :   ScriptData* cache = nullptr;
    1275             : 
    1276             :   CompileScript(isolate, src, src, &cache,
    1277           5 :                 v8::ScriptCompiler::kProduceCodeCache);
    1278             : 
    1279             :   DisallowCompilation no_compile_expected(isolate);
    1280             :   Handle<SharedFunctionInfo> copy = CompileScript(
    1281           5 :       isolate, src, src, &cache, v8::ScriptCompiler::kConsumeCodeCache);
    1282             : 
    1283             :   InfoVectorPair pair = isolate->compilation_cache()->LookupScript(
    1284             :       src, src, 0, 0, v8::ScriptOriginOptions(), isolate->native_context(),
    1285          10 :       LanguageMode::kSloppy);
    1286             : 
    1287          10 :   CHECK(pair.shared() == *copy);
    1288             : 
    1289          15 :   delete cache;
    1290           5 : }
    1291             : 
    1292       23723 : TEST(CodeSerializerInternalizedString) {
    1293           5 :   LocalContext context;
    1294          10 :   Isolate* isolate = CcTest::i_isolate();
    1295           5 :   isolate->compilation_cache()->Disable();  // Disable same-isolate code cache.
    1296             : 
    1297          10 :   v8::HandleScope scope(CcTest::isolate());
    1298             : 
    1299             :   const char* source = "'string1'";
    1300             : 
    1301             :   Handle<String> orig_source = isolate->factory()
    1302             :                                    ->NewStringFromUtf8(CStrVector(source))
    1303          10 :                                    .ToHandleChecked();
    1304             :   Handle<String> copy_source = isolate->factory()
    1305             :                                    ->NewStringFromUtf8(CStrVector(source))
    1306          10 :                                    .ToHandleChecked();
    1307           5 :   CHECK(!orig_source.is_identical_to(copy_source));
    1308           5 :   CHECK(orig_source->Equals(*copy_source));
    1309             : 
    1310           5 :   Handle<JSObject> global(isolate->context()->global_object());
    1311           5 :   ScriptData* cache = nullptr;
    1312             : 
    1313             :   Handle<SharedFunctionInfo> orig =
    1314             :       CompileScript(isolate, orig_source, Handle<String>(), &cache,
    1315           5 :                     v8::ScriptCompiler::kProduceCodeCache);
    1316             :   Handle<JSFunction> orig_fun =
    1317             :       isolate->factory()->NewFunctionFromSharedFunctionInfo(
    1318           5 :           orig, isolate->native_context());
    1319             :   Handle<Object> orig_result =
    1320          10 :       Execution::Call(isolate, orig_fun, global, 0, nullptr).ToHandleChecked();
    1321           5 :   CHECK(orig_result->IsInternalizedString());
    1322             : 
    1323           5 :   int builtins_count = CountBuiltins();
    1324             : 
    1325             :   Handle<SharedFunctionInfo> copy;
    1326             :   {
    1327             :     DisallowCompilation no_compile_expected(isolate);
    1328             :     copy = CompileScript(isolate, copy_source, Handle<String>(), &cache,
    1329           5 :                          v8::ScriptCompiler::kConsumeCodeCache);
    1330             :   }
    1331           5 :   CHECK_NE(*orig, *copy);
    1332           5 :   CHECK(Script::cast(copy->script())->source() == *copy_source);
    1333             : 
    1334             :   Handle<JSFunction> copy_fun =
    1335             :       isolate->factory()->NewFunctionFromSharedFunctionInfo(
    1336           5 :           copy, isolate->native_context());
    1337           5 :   CHECK_NE(*orig_fun, *copy_fun);
    1338             :   Handle<Object> copy_result =
    1339          10 :       Execution::Call(isolate, copy_fun, global, 0, nullptr).ToHandleChecked();
    1340           5 :   CHECK(orig_result.is_identical_to(copy_result));
    1341             :   Handle<String> expected =
    1342           5 :       isolate->factory()->NewStringFromAsciiChecked("string1");
    1343             : 
    1344           5 :   CHECK(Handle<String>::cast(copy_result)->Equals(*expected));
    1345           5 :   CHECK_EQ(builtins_count, CountBuiltins());
    1346             : 
    1347          15 :   delete cache;
    1348           5 : }
    1349             : 
    1350       23723 : TEST(CodeSerializerLargeCodeObject) {
    1351           5 :   LocalContext context;
    1352          10 :   Isolate* isolate = CcTest::i_isolate();
    1353           5 :   isolate->compilation_cache()->Disable();  // Disable same-isolate code cache.
    1354             : 
    1355          10 :   v8::HandleScope scope(CcTest::isolate());
    1356             : 
    1357             :   // The serializer only tests the shared code, which is always the unoptimized
    1358             :   // code. Don't even bother generating optimized code to avoid timeouts.
    1359           5 :   FLAG_always_opt = false;
    1360             : 
    1361             :   Vector<const uint8_t> source =
    1362             :       ConstructSource(STATIC_CHAR_VECTOR("var j=1; if (j == 0) {"),
    1363             :                       STATIC_CHAR_VECTOR("for (let i of Object.prototype);"),
    1364           5 :                       STATIC_CHAR_VECTOR("} j=7; j"), 1100);
    1365             :   Handle<String> source_str =
    1366          10 :       isolate->factory()->NewStringFromOneByte(source).ToHandleChecked();
    1367             : 
    1368           5 :   Handle<JSObject> global(isolate->context()->global_object());
    1369           5 :   ScriptData* cache = nullptr;
    1370             : 
    1371             :   Handle<SharedFunctionInfo> orig =
    1372             :       CompileScript(isolate, source_str, Handle<String>(), &cache,
    1373           5 :                     v8::ScriptCompiler::kProduceCodeCache);
    1374             : 
    1375           5 :   CHECK(isolate->heap()->InSpace(orig->abstract_code(), LO_SPACE));
    1376             : 
    1377             :   Handle<SharedFunctionInfo> copy;
    1378             :   {
    1379             :     DisallowCompilation no_compile_expected(isolate);
    1380             :     copy = CompileScript(isolate, source_str, Handle<String>(), &cache,
    1381           5 :                          v8::ScriptCompiler::kConsumeCodeCache);
    1382             :   }
    1383           5 :   CHECK_NE(*orig, *copy);
    1384             : 
    1385             :   Handle<JSFunction> copy_fun =
    1386             :       isolate->factory()->NewFunctionFromSharedFunctionInfo(
    1387           5 :           copy, isolate->native_context());
    1388             : 
    1389             :   Handle<Object> copy_result =
    1390          10 :       Execution::Call(isolate, copy_fun, global, 0, nullptr).ToHandleChecked();
    1391             : 
    1392             :   int result_int;
    1393           5 :   CHECK(copy_result->ToInt32(&result_int));
    1394           5 :   CHECK_EQ(7, result_int);
    1395             : 
    1396          10 :   delete cache;
    1397           5 :   source.Dispose();
    1398           5 : }
    1399             : 
    1400       23723 : TEST(CodeSerializerLargeCodeObjectWithIncrementalMarking) {
    1401           5 :   if (FLAG_never_compact) return;
    1402             :   ManualGCScope manual_gc_scope;
    1403           5 :   FLAG_always_opt = false;
    1404             :   const char* filter_flag = "--turbo-filter=NOTHING";
    1405           5 :   FlagList::SetFlagsFromString(filter_flag, StrLength(filter_flag));
    1406           5 :   FLAG_black_allocation = true;
    1407           5 :   FLAG_manual_evacuation_candidates_selection = true;
    1408             : 
    1409          10 :   LocalContext context;
    1410          10 :   Isolate* isolate = CcTest::i_isolate();
    1411          15 :   Heap* heap = isolate->heap();
    1412           5 :   isolate->compilation_cache()->Disable();  // Disable same-isolate code cache.
    1413             : 
    1414          10 :   v8::HandleScope scope(CcTest::isolate());
    1415             : 
    1416             :   Vector<const uint8_t> source = ConstructSource(
    1417             :       STATIC_CHAR_VECTOR("var j=1; if (j == 0) {"),
    1418             :       STATIC_CHAR_VECTOR("for (var i = 0; i < Object.prototype; i++);"),
    1419           5 :       STATIC_CHAR_VECTOR("} j=7; var s = 'happy_hippo'; j"), 10000);
    1420             :   Handle<String> source_str =
    1421          10 :       isolate->factory()->NewStringFromOneByte(source).ToHandleChecked();
    1422             : 
    1423             :   // Create a string on an evacuation candidate in old space.
    1424             :   Handle<String> moving_object;
    1425             :   Page* ec_page;
    1426             :   {
    1427             :     AlwaysAllocateScope always_allocate(isolate);
    1428           5 :     heap::SimulateFullSpace(heap->old_space());
    1429             :     moving_object = isolate->factory()->InternalizeString(
    1430           5 :         isolate->factory()->NewStringFromAsciiChecked("happy_hippo"));
    1431           5 :     ec_page = Page::FromAddress(moving_object->address());
    1432             :   }
    1433             : 
    1434           5 :   Handle<JSObject> global(isolate->context()->global_object());
    1435           5 :   ScriptData* cache = nullptr;
    1436             : 
    1437             :   Handle<SharedFunctionInfo> orig =
    1438             :       CompileScript(isolate, source_str, Handle<String>(), &cache,
    1439           5 :                     v8::ScriptCompiler::kProduceCodeCache);
    1440             : 
    1441           5 :   CHECK(heap->InSpace(orig->abstract_code(), LO_SPACE));
    1442             : 
    1443             :   // Pretend that incremental marking is on when deserialization begins.
    1444           5 :   heap::ForceEvacuationCandidate(ec_page);
    1445           5 :   heap::SimulateIncrementalMarking(heap, false);
    1446             :   IncrementalMarking* marking = heap->incremental_marking();
    1447             :   marking->StartBlackAllocationForTesting();
    1448           5 :   CHECK(marking->IsCompacting());
    1449           5 :   CHECK(MarkCompactCollector::IsOnEvacuationCandidate(*moving_object));
    1450             : 
    1451             :   Handle<SharedFunctionInfo> copy;
    1452             :   {
    1453             :     DisallowCompilation no_compile_expected(isolate);
    1454             :     copy = CompileScript(isolate, source_str, Handle<String>(), &cache,
    1455           5 :                          v8::ScriptCompiler::kConsumeCodeCache);
    1456             :   }
    1457           5 :   CHECK_NE(*orig, *copy);
    1458             : 
    1459             :   // We should have missed a write barrier. Complete incremental marking
    1460             :   // to flush out the bug.
    1461           5 :   heap::SimulateIncrementalMarking(heap, true);
    1462           5 :   CcTest::CollectAllGarbage();
    1463             : 
    1464             :   Handle<JSFunction> copy_fun =
    1465             :       isolate->factory()->NewFunctionFromSharedFunctionInfo(
    1466           5 :           copy, isolate->native_context());
    1467             : 
    1468             :   Handle<Object> copy_result =
    1469          10 :       Execution::Call(isolate, copy_fun, global, 0, nullptr).ToHandleChecked();
    1470             : 
    1471             :   int result_int;
    1472           5 :   CHECK(copy_result->ToInt32(&result_int));
    1473           5 :   CHECK_EQ(7, result_int);
    1474             : 
    1475          10 :   delete cache;
    1476             :   source.Dispose();
    1477             : }
    1478       23723 : TEST(CodeSerializerLargeStrings) {
    1479           5 :   LocalContext context;
    1480          10 :   Isolate* isolate = CcTest::i_isolate();
    1481             :   Factory* f = isolate->factory();
    1482           5 :   isolate->compilation_cache()->Disable();  // Disable same-isolate code cache.
    1483             : 
    1484          10 :   v8::HandleScope scope(CcTest::isolate());
    1485             : 
    1486             :   Vector<const uint8_t> source_s = ConstructSource(
    1487             :       STATIC_CHAR_VECTOR("var s = \""), STATIC_CHAR_VECTOR("abcdef"),
    1488           5 :       STATIC_CHAR_VECTOR("\";"), 1000000);
    1489             :   Vector<const uint8_t> source_t = ConstructSource(
    1490             :       STATIC_CHAR_VECTOR("var t = \""), STATIC_CHAR_VECTOR("uvwxyz"),
    1491           5 :       STATIC_CHAR_VECTOR("\"; s + t"), 999999);
    1492             :   Handle<String> source_str =
    1493             :       f->NewConsString(f->NewStringFromOneByte(source_s).ToHandleChecked(),
    1494          15 :                        f->NewStringFromOneByte(source_t).ToHandleChecked())
    1495          10 :           .ToHandleChecked();
    1496             : 
    1497           5 :   Handle<JSObject> global(isolate->context()->global_object());
    1498           5 :   ScriptData* cache = nullptr;
    1499             : 
    1500             :   Handle<SharedFunctionInfo> orig =
    1501             :       CompileScript(isolate, source_str, Handle<String>(), &cache,
    1502           5 :                     v8::ScriptCompiler::kProduceCodeCache);
    1503             : 
    1504             :   Handle<SharedFunctionInfo> copy;
    1505             :   {
    1506             :     DisallowCompilation no_compile_expected(isolate);
    1507             :     copy = CompileScript(isolate, source_str, Handle<String>(), &cache,
    1508           5 :                          v8::ScriptCompiler::kConsumeCodeCache);
    1509             :   }
    1510           5 :   CHECK_NE(*orig, *copy);
    1511             : 
    1512             :   Handle<JSFunction> copy_fun =
    1513             :       isolate->factory()->NewFunctionFromSharedFunctionInfo(
    1514           5 :           copy, isolate->native_context());
    1515             : 
    1516             :   Handle<Object> copy_result =
    1517          10 :       Execution::Call(isolate, copy_fun, global, 0, nullptr).ToHandleChecked();
    1518             : 
    1519           5 :   CHECK_EQ(6 * 1999999, Handle<String>::cast(copy_result)->length());
    1520             :   Handle<Object> property = JSReceiver::GetDataProperty(
    1521          15 :       isolate->global_object(), f->NewStringFromAsciiChecked("s"));
    1522           5 :   CHECK(isolate->heap()->InSpace(HeapObject::cast(*property), LO_SPACE));
    1523             :   property = JSReceiver::GetDataProperty(isolate->global_object(),
    1524          15 :                                          f->NewStringFromAsciiChecked("t"));
    1525           5 :   CHECK(isolate->heap()->InSpace(HeapObject::cast(*property), LO_SPACE));
    1526             :   // Make sure we do not serialize too much, e.g. include the source string.
    1527           5 :   CHECK_LT(cache->length(), 13000000);
    1528             : 
    1529          10 :   delete cache;
    1530             :   source_s.Dispose();
    1531           5 :   source_t.Dispose();
    1532           5 : }
    1533             : 
    1534       23723 : TEST(CodeSerializerThreeBigStrings) {
    1535           5 :   LocalContext context;
    1536          10 :   Isolate* isolate = CcTest::i_isolate();
    1537             :   Factory* f = isolate->factory();
    1538           5 :   isolate->compilation_cache()->Disable();  // Disable same-isolate code cache.
    1539             : 
    1540          10 :   v8::HandleScope scope(CcTest::isolate());
    1541             : 
    1542             :   Vector<const uint8_t> source_a =
    1543             :       ConstructSource(STATIC_CHAR_VECTOR("var a = \""), STATIC_CHAR_VECTOR("a"),
    1544           5 :                       STATIC_CHAR_VECTOR("\";"), 700000);
    1545             :   Handle<String> source_a_str =
    1546          10 :       f->NewStringFromOneByte(source_a).ToHandleChecked();
    1547             : 
    1548             :   Vector<const uint8_t> source_b =
    1549             :       ConstructSource(STATIC_CHAR_VECTOR("var b = \""), STATIC_CHAR_VECTOR("b"),
    1550           5 :                       STATIC_CHAR_VECTOR("\";"), 400000);
    1551             :   Handle<String> source_b_str =
    1552          10 :       f->NewStringFromOneByte(source_b).ToHandleChecked();
    1553             : 
    1554             :   Vector<const uint8_t> source_c =
    1555             :       ConstructSource(STATIC_CHAR_VECTOR("var c = \""), STATIC_CHAR_VECTOR("c"),
    1556           5 :                       STATIC_CHAR_VECTOR("\";"), 400000);
    1557             :   Handle<String> source_c_str =
    1558          10 :       f->NewStringFromOneByte(source_c).ToHandleChecked();
    1559             : 
    1560             :   Handle<String> source_str =
    1561             :       f->NewConsString(
    1562             :              f->NewConsString(source_a_str, source_b_str).ToHandleChecked(),
    1563          15 :              source_c_str).ToHandleChecked();
    1564             : 
    1565           5 :   Handle<JSObject> global(isolate->context()->global_object());
    1566           5 :   ScriptData* cache = nullptr;
    1567             : 
    1568             :   Handle<SharedFunctionInfo> orig =
    1569             :       CompileScript(isolate, source_str, Handle<String>(), &cache,
    1570           5 :                     v8::ScriptCompiler::kProduceCodeCache);
    1571             : 
    1572             :   Handle<SharedFunctionInfo> copy;
    1573             :   {
    1574             :     DisallowCompilation no_compile_expected(isolate);
    1575             :     copy = CompileScript(isolate, source_str, Handle<String>(), &cache,
    1576           5 :                          v8::ScriptCompiler::kConsumeCodeCache);
    1577             :   }
    1578           5 :   CHECK_NE(*orig, *copy);
    1579             : 
    1580             :   Handle<JSFunction> copy_fun =
    1581             :       isolate->factory()->NewFunctionFromSharedFunctionInfo(
    1582           5 :           copy, isolate->native_context());
    1583             : 
    1584           5 :   USE(Execution::Call(isolate, copy_fun, global, 0, nullptr));
    1585             : 
    1586             :   v8::Maybe<int32_t> result =
    1587             :       CompileRun("(a + b).length")
    1588          10 :           ->Int32Value(v8::Isolate::GetCurrent()->GetCurrentContext());
    1589           5 :   CHECK_EQ(400000 + 700000, result.FromJust());
    1590             :   result = CompileRun("(b + c).length")
    1591          10 :                ->Int32Value(v8::Isolate::GetCurrent()->GetCurrentContext());
    1592           5 :   CHECK_EQ(400000 + 400000, result.FromJust());
    1593           5 :   Heap* heap = isolate->heap();
    1594             :   v8::Local<v8::String> result_str =
    1595             :       CompileRun("a")
    1596           5 :           ->ToString(CcTest::isolate()->GetCurrentContext())
    1597           5 :           .ToLocalChecked();
    1598           5 :   CHECK(heap->InSpace(*v8::Utils::OpenHandle(*result_str), LO_SPACE));
    1599             :   result_str = CompileRun("b")
    1600           5 :                    ->ToString(CcTest::isolate()->GetCurrentContext())
    1601           5 :                    .ToLocalChecked();
    1602           5 :   CHECK(heap->InSpace(*v8::Utils::OpenHandle(*result_str), OLD_SPACE));
    1603             :   result_str = CompileRun("c")
    1604           5 :                    ->ToString(CcTest::isolate()->GetCurrentContext())
    1605           5 :                    .ToLocalChecked();
    1606           5 :   CHECK(heap->InSpace(*v8::Utils::OpenHandle(*result_str), OLD_SPACE));
    1607             : 
    1608          10 :   delete cache;
    1609             :   source_a.Dispose();
    1610             :   source_b.Dispose();
    1611           5 :   source_c.Dispose();
    1612           5 : }
    1613             : 
    1614             : 
    1615          15 : class SerializerOneByteResource
    1616             :     : public v8::String::ExternalOneByteStringResource {
    1617             :  public:
    1618             :   SerializerOneByteResource(const char* data, size_t length)
    1619          15 :       : data_(data), length_(length) {}
    1620          65 :   virtual const char* data() const { return data_; }
    1621           5 :   virtual size_t length() const { return length_; }
    1622             : 
    1623             :  private:
    1624             :   const char* data_;
    1625             :   size_t length_;
    1626             : };
    1627             : 
    1628             : 
    1629             : class SerializerTwoByteResource : public v8::String::ExternalStringResource {
    1630             :  public:
    1631             :   SerializerTwoByteResource(const char* data, size_t length)
    1632           5 :       : data_(AsciiToTwoByteString(data)), length_(length) {}
    1633           5 :   ~SerializerTwoByteResource() { DeleteArray<const uint16_t>(data_); }
    1634             : 
    1635          60 :   virtual const uint16_t* data() const { return data_; }
    1636           0 :   virtual size_t length() const { return length_; }
    1637             : 
    1638             :  private:
    1639             :   const uint16_t* data_;
    1640             :   size_t length_;
    1641             : };
    1642             : 
    1643       23723 : TEST(CodeSerializerExternalString) {
    1644           5 :   LocalContext context;
    1645          10 :   Isolate* isolate = CcTest::i_isolate();
    1646           5 :   isolate->compilation_cache()->Disable();  // Disable same-isolate code cache.
    1647             : 
    1648          10 :   v8::HandleScope scope(CcTest::isolate());
    1649             : 
    1650             :   // Obtain external internalized one-byte string.
    1651             :   SerializerOneByteResource one_byte_resource("one_byte", 8);
    1652             :   Handle<String> one_byte_string =
    1653           5 :       isolate->factory()->NewStringFromAsciiChecked("one_byte");
    1654           5 :   one_byte_string = isolate->factory()->InternalizeString(one_byte_string);
    1655           5 :   one_byte_string->MakeExternal(&one_byte_resource);
    1656           5 :   CHECK(one_byte_string->IsExternalOneByteString());
    1657           5 :   CHECK(one_byte_string->IsInternalizedString());
    1658             : 
    1659             :   // Obtain external internalized two-byte string.
    1660             :   SerializerTwoByteResource two_byte_resource("two_byte", 8);
    1661             :   Handle<String> two_byte_string =
    1662           5 :       isolate->factory()->NewStringFromAsciiChecked("two_byte");
    1663           5 :   two_byte_string = isolate->factory()->InternalizeString(two_byte_string);
    1664           5 :   two_byte_string->MakeExternal(&two_byte_resource);
    1665           5 :   CHECK(two_byte_string->IsExternalTwoByteString());
    1666           5 :   CHECK(two_byte_string->IsInternalizedString());
    1667             : 
    1668             :   const char* source =
    1669             :       "var o = {}               \n"
    1670             :       "o.one_byte = 7;          \n"
    1671             :       "o.two_byte = 8;          \n"
    1672             :       "o.one_byte + o.two_byte; \n";
    1673             :   Handle<String> source_string = isolate->factory()
    1674             :                                      ->NewStringFromUtf8(CStrVector(source))
    1675          10 :                                      .ToHandleChecked();
    1676             : 
    1677           5 :   Handle<JSObject> global(isolate->context()->global_object());
    1678           5 :   ScriptData* cache = nullptr;
    1679             : 
    1680             :   Handle<SharedFunctionInfo> orig =
    1681             :       CompileScript(isolate, source_string, Handle<String>(), &cache,
    1682           5 :                     v8::ScriptCompiler::kProduceCodeCache);
    1683             : 
    1684             :   Handle<SharedFunctionInfo> copy;
    1685             :   {
    1686             :     DisallowCompilation no_compile_expected(isolate);
    1687             :     copy = CompileScript(isolate, source_string, Handle<String>(), &cache,
    1688           5 :                          v8::ScriptCompiler::kConsumeCodeCache);
    1689             :   }
    1690           5 :   CHECK_NE(*orig, *copy);
    1691             : 
    1692             :   Handle<JSFunction> copy_fun =
    1693             :       isolate->factory()->NewFunctionFromSharedFunctionInfo(
    1694           5 :           copy, isolate->native_context());
    1695             : 
    1696             :   Handle<Object> copy_result =
    1697          10 :       Execution::Call(isolate, copy_fun, global, 0, nullptr).ToHandleChecked();
    1698             : 
    1699           5 :   CHECK_EQ(15.0, copy_result->Number());
    1700             : 
    1701          15 :   delete cache;
    1702           5 : }
    1703             : 
    1704       23723 : TEST(CodeSerializerLargeExternalString) {
    1705           5 :   LocalContext context;
    1706          10 :   Isolate* isolate = CcTest::i_isolate();
    1707           5 :   isolate->compilation_cache()->Disable();  // Disable same-isolate code cache.
    1708             : 
    1709             :   Factory* f = isolate->factory();
    1710             : 
    1711          10 :   v8::HandleScope scope(CcTest::isolate());
    1712             : 
    1713             :   // Create a huge external internalized string to use as variable name.
    1714             :   Vector<const uint8_t> string =
    1715             :       ConstructSource(STATIC_CHAR_VECTOR(""), STATIC_CHAR_VECTOR("abcdef"),
    1716           5 :                       STATIC_CHAR_VECTOR(""), 999999);
    1717          10 :   Handle<String> name = f->NewStringFromOneByte(string).ToHandleChecked();
    1718             :   SerializerOneByteResource one_byte_resource(
    1719           5 :       reinterpret_cast<const char*>(string.start()), string.length());
    1720           5 :   name = f->InternalizeString(name);
    1721           5 :   name->MakeExternal(&one_byte_resource);
    1722           5 :   CHECK(name->IsExternalOneByteString());
    1723           5 :   CHECK(name->IsInternalizedString());
    1724           5 :   CHECK(isolate->heap()->InSpace(*name, LO_SPACE));
    1725             : 
    1726             :   // Create the source, which is "var <literal> = 42; <literal>".
    1727             :   Handle<String> source_str =
    1728             :       f->NewConsString(
    1729           5 :              f->NewConsString(f->NewStringFromAsciiChecked("var "), name)
    1730             :                  .ToHandleChecked(),
    1731           5 :              f->NewConsString(f->NewStringFromAsciiChecked(" = 42; "), name)
    1732          20 :                  .ToHandleChecked()).ToHandleChecked();
    1733             : 
    1734           5 :   Handle<JSObject> global(isolate->context()->global_object());
    1735           5 :   ScriptData* cache = nullptr;
    1736             : 
    1737             :   Handle<SharedFunctionInfo> orig =
    1738             :       CompileScript(isolate, source_str, Handle<String>(), &cache,
    1739           5 :                     v8::ScriptCompiler::kProduceCodeCache);
    1740             : 
    1741             :   Handle<SharedFunctionInfo> copy;
    1742             :   {
    1743             :     DisallowCompilation no_compile_expected(isolate);
    1744             :     copy = CompileScript(isolate, source_str, Handle<String>(), &cache,
    1745           5 :                          v8::ScriptCompiler::kConsumeCodeCache);
    1746             :   }
    1747           5 :   CHECK_NE(*orig, *copy);
    1748             : 
    1749             :   Handle<JSFunction> copy_fun =
    1750           5 :       f->NewFunctionFromSharedFunctionInfo(copy, isolate->native_context());
    1751             : 
    1752             :   Handle<Object> copy_result =
    1753          10 :       Execution::Call(isolate, copy_fun, global, 0, nullptr).ToHandleChecked();
    1754             : 
    1755           5 :   CHECK_EQ(42.0, copy_result->Number());
    1756             : 
    1757          10 :   delete cache;
    1758           5 :   string.Dispose();
    1759           5 : }
    1760             : 
    1761       23723 : TEST(CodeSerializerExternalScriptName) {
    1762           5 :   LocalContext context;
    1763          10 :   Isolate* isolate = CcTest::i_isolate();
    1764           5 :   isolate->compilation_cache()->Disable();  // Disable same-isolate code cache.
    1765             : 
    1766             :   Factory* f = isolate->factory();
    1767             : 
    1768          10 :   v8::HandleScope scope(CcTest::isolate());
    1769             : 
    1770             :   const char* source =
    1771             :       "var a = [1, 2, 3, 4];"
    1772             :       "a.reduce(function(x, y) { return x + y }, 0)";
    1773             : 
    1774             :   Handle<String> source_string =
    1775          10 :       f->NewStringFromUtf8(CStrVector(source)).ToHandleChecked();
    1776             : 
    1777             :   const SerializerOneByteResource one_byte_resource("one_byte", 8);
    1778             :   Handle<String> name =
    1779          10 :       f->NewExternalStringFromOneByte(&one_byte_resource).ToHandleChecked();
    1780           5 :   CHECK(name->IsExternalOneByteString());
    1781           5 :   CHECK(!name->IsInternalizedString());
    1782             : 
    1783           5 :   Handle<JSObject> global(isolate->context()->global_object());
    1784           5 :   ScriptData* cache = nullptr;
    1785             : 
    1786             :   Handle<SharedFunctionInfo> orig =
    1787             :       CompileScript(isolate, source_string, name, &cache,
    1788           5 :                     v8::ScriptCompiler::kProduceCodeCache);
    1789             : 
    1790             :   Handle<SharedFunctionInfo> copy;
    1791             :   {
    1792             :     DisallowCompilation no_compile_expected(isolate);
    1793             :     copy = CompileScript(isolate, source_string, name, &cache,
    1794           5 :                          v8::ScriptCompiler::kConsumeCodeCache);
    1795             :   }
    1796           5 :   CHECK_NE(*orig, *copy);
    1797             : 
    1798             :   Handle<JSFunction> copy_fun =
    1799           5 :       f->NewFunctionFromSharedFunctionInfo(copy, isolate->native_context());
    1800             : 
    1801             :   Handle<Object> copy_result =
    1802          10 :       Execution::Call(isolate, copy_fun, global, 0, nullptr).ToHandleChecked();
    1803             : 
    1804           5 :   CHECK_EQ(10.0, copy_result->Number());
    1805             : 
    1806          15 :   delete cache;
    1807           5 : }
    1808             : 
    1809             : 
    1810             : static bool toplevel_test_code_event_found = false;
    1811             : 
    1812             : 
    1813          80 : static void SerializerCodeEventListener(const v8::JitCodeEvent* event) {
    1814         102 :   if (event->type == v8::JitCodeEvent::CODE_ADDED &&
    1815          22 :       memcmp(event->name.str, "Script:~test", 12) == 0) {
    1816          10 :     toplevel_test_code_event_found = true;
    1817             :   }
    1818          80 : }
    1819             : 
    1820          20 : v8::ScriptCompiler::CachedData* ProduceCache(const char* source,
    1821             :                                              bool eager = false) {
    1822             :   v8::ScriptCompiler::CachedData* cache;
    1823             :   v8::Isolate::CreateParams create_params;
    1824          20 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    1825          20 :   v8::Isolate* isolate1 = v8::Isolate::New(create_params);
    1826             :   {
    1827             :     v8::Isolate::Scope iscope(isolate1);
    1828          40 :     v8::HandleScope scope(isolate1);
    1829          20 :     v8::Local<v8::Context> context = v8::Context::New(isolate1);
    1830             :     v8::Context::Scope context_scope(context);
    1831             : 
    1832          20 :     v8::Local<v8::String> source_str = v8_str(source);
    1833          20 :     v8::ScriptOrigin origin(v8_str("test"));
    1834             :     v8::ScriptCompiler::Source source(source_str, origin);
    1835             :     v8::ScriptCompiler::CompileOptions options =
    1836             :         eager ? v8::ScriptCompiler::kProduceFullCodeCache
    1837          20 :               : v8::ScriptCompiler::kProduceCodeCache;
    1838             :     v8::Local<v8::UnboundScript> script =
    1839             :         v8::ScriptCompiler::CompileUnboundScript(isolate1, &source, options)
    1840          20 :             .ToLocalChecked();
    1841          20 :     const v8::ScriptCompiler::CachedData* data = source.GetCachedData();
    1842          20 :     CHECK(data);
    1843             :     // Persist cached data.
    1844          20 :     uint8_t* buffer = NewArray<uint8_t>(data->length);
    1845          20 :     MemCopy(buffer, data->data, data->length);
    1846             :     cache = new v8::ScriptCompiler::CachedData(
    1847          20 :         buffer, data->length, v8::ScriptCompiler::CachedData::BufferOwned);
    1848             : 
    1849             :     v8::Local<v8::Value> result = script->BindToCurrentContext()
    1850          40 :                                       ->Run(isolate1->GetCurrentContext())
    1851          20 :                                       .ToLocalChecked();
    1852             :     v8::Local<v8::String> result_string =
    1853          20 :         result->ToString(isolate1->GetCurrentContext()).ToLocalChecked();
    1854          60 :     CHECK(result_string->Equals(isolate1->GetCurrentContext(), v8_str("abcdef"))
    1855             :               .FromJust());
    1856             :   }
    1857          20 :   isolate1->Dispose();
    1858          20 :   return cache;
    1859             : }
    1860             : 
    1861          15 : void CheckDeserializedFlag(v8::Local<v8::UnboundScript> script) {
    1862             :   i::Handle<i::SharedFunctionInfo> sfi = v8::Utils::OpenHandle(*script);
    1863             :   i::Handle<i::Script> i_script(Script::cast(sfi->script()));
    1864          15 :   i::SharedFunctionInfo::ScriptIterator iterator(i_script);
    1865          45 :   while (SharedFunctionInfo* next = iterator.Next()) {
    1866          30 :     CHECK_EQ(next->is_compiled(), next->deserialized());
    1867             :   }
    1868          15 : }
    1869             : 
    1870       23723 : TEST(CodeSerializerIsolates) {
    1871             :   const char* source = "function f() { return 'abc'; }; f() + 'def'";
    1872           5 :   v8::ScriptCompiler::CachedData* cache = ProduceCache(source);
    1873             : 
    1874             :   v8::Isolate::CreateParams create_params;
    1875           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    1876           5 :   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
    1877             :   isolate2->SetJitCodeEventHandler(v8::kJitCodeEventDefault,
    1878           5 :                                    SerializerCodeEventListener);
    1879           5 :   toplevel_test_code_event_found = false;
    1880             :   {
    1881             :     v8::Isolate::Scope iscope(isolate2);
    1882          10 :     v8::HandleScope scope(isolate2);
    1883           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate2);
    1884             :     v8::Context::Scope context_scope(context);
    1885             : 
    1886           5 :     v8::Local<v8::String> source_str = v8_str(source);
    1887           5 :     v8::ScriptOrigin origin(v8_str("test"));
    1888             :     v8::ScriptCompiler::Source source(source_str, origin, cache);
    1889             :     v8::Local<v8::UnboundScript> script;
    1890             :     {
    1891             :       DisallowCompilation no_compile(reinterpret_cast<Isolate*>(isolate2));
    1892             :       script = v8::ScriptCompiler::CompileUnboundScript(
    1893             :                    isolate2, &source, v8::ScriptCompiler::kConsumeCodeCache)
    1894           5 :                    .ToLocalChecked();
    1895             :     }
    1896           5 :     CHECK(!cache->rejected);
    1897           5 :     CheckDeserializedFlag(script);
    1898             :     v8::Local<v8::Value> result = script->BindToCurrentContext()
    1899          10 :                                       ->Run(isolate2->GetCurrentContext())
    1900           5 :                                       .ToLocalChecked();
    1901          20 :     CHECK(result->ToString(isolate2->GetCurrentContext())
    1902             :               .ToLocalChecked()
    1903             :               ->Equals(isolate2->GetCurrentContext(), v8_str("abcdef"))
    1904             :               .FromJust());
    1905             :   }
    1906           5 :   CHECK(toplevel_test_code_event_found);
    1907           5 :   isolate2->Dispose();
    1908           5 : }
    1909             : 
    1910       23723 : TEST(CodeSerializerIsolatesEager) {
    1911             :   const char* source =
    1912             :       "function f() {"
    1913             :       "  return function g() {"
    1914             :       "    return 'abc';"
    1915             :       "  }"
    1916             :       "}"
    1917             :       "f()() + 'def'";
    1918           5 :   v8::ScriptCompiler::CachedData* cache = ProduceCache(source, true);
    1919             : 
    1920             :   v8::Isolate::CreateParams create_params;
    1921           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    1922           5 :   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
    1923             :   isolate2->SetJitCodeEventHandler(v8::kJitCodeEventDefault,
    1924           5 :                                    SerializerCodeEventListener);
    1925           5 :   toplevel_test_code_event_found = false;
    1926             :   {
    1927             :     v8::Isolate::Scope iscope(isolate2);
    1928          10 :     v8::HandleScope scope(isolate2);
    1929           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate2);
    1930             :     v8::Context::Scope context_scope(context);
    1931             : 
    1932           5 :     v8::Local<v8::String> source_str = v8_str(source);
    1933           5 :     v8::ScriptOrigin origin(v8_str("test"));
    1934             :     v8::ScriptCompiler::Source source(source_str, origin, cache);
    1935             :     v8::Local<v8::UnboundScript> script;
    1936             :     {
    1937             :       DisallowCompilation no_compile(reinterpret_cast<Isolate*>(isolate2));
    1938             :       script = v8::ScriptCompiler::CompileUnboundScript(
    1939             :                    isolate2, &source, v8::ScriptCompiler::kConsumeCodeCache)
    1940           5 :                    .ToLocalChecked();
    1941             :     }
    1942           5 :     CHECK(!cache->rejected);
    1943           5 :     CheckDeserializedFlag(script);
    1944             :     v8::Local<v8::Value> result = script->BindToCurrentContext()
    1945          10 :                                       ->Run(isolate2->GetCurrentContext())
    1946           5 :                                       .ToLocalChecked();
    1947          20 :     CHECK(result->ToString(isolate2->GetCurrentContext())
    1948             :               .ToLocalChecked()
    1949             :               ->Equals(isolate2->GetCurrentContext(), v8_str("abcdef"))
    1950             :               .FromJust());
    1951             :   }
    1952           5 :   CHECK(toplevel_test_code_event_found);
    1953           5 :   isolate2->Dispose();
    1954           5 : }
    1955             : 
    1956       23723 : TEST(CodeSerializerFlagChange) {
    1957             :   const char* source = "function f() { return 'abc'; }; f() + 'def'";
    1958           5 :   v8::ScriptCompiler::CachedData* cache = ProduceCache(source);
    1959             : 
    1960             :   v8::Isolate::CreateParams create_params;
    1961           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    1962           5 :   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
    1963             : 
    1964           5 :   FLAG_allow_natives_syntax = true;  // Flag change should trigger cache reject.
    1965           5 :   FlagList::EnforceFlagImplications();
    1966             :   {
    1967             :     v8::Isolate::Scope iscope(isolate2);
    1968          10 :     v8::HandleScope scope(isolate2);
    1969           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate2);
    1970             :     v8::Context::Scope context_scope(context);
    1971             : 
    1972           5 :     v8::Local<v8::String> source_str = v8_str(source);
    1973           5 :     v8::ScriptOrigin origin(v8_str("test"));
    1974             :     v8::ScriptCompiler::Source source(source_str, origin, cache);
    1975             :     v8::ScriptCompiler::CompileUnboundScript(
    1976             :         isolate2, &source, v8::ScriptCompiler::kConsumeCodeCache)
    1977           5 :         .ToLocalChecked();
    1978           5 :     CHECK(cache->rejected);
    1979             :   }
    1980           5 :   isolate2->Dispose();
    1981           5 : }
    1982             : 
    1983       23723 : TEST(CodeSerializerBitFlip) {
    1984             :   const char* source = "function f() { return 'abc'; }; f() + 'def'";
    1985           5 :   v8::ScriptCompiler::CachedData* cache = ProduceCache(source);
    1986             : 
    1987             :   // Random bit flip.
    1988           5 :   const_cast<uint8_t*>(cache->data)[337] ^= 0x40;
    1989             : 
    1990             :   v8::Isolate::CreateParams create_params;
    1991           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    1992           5 :   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
    1993             :   {
    1994             :     v8::Isolate::Scope iscope(isolate2);
    1995          10 :     v8::HandleScope scope(isolate2);
    1996           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate2);
    1997             :     v8::Context::Scope context_scope(context);
    1998             : 
    1999           5 :     v8::Local<v8::String> source_str = v8_str(source);
    2000           5 :     v8::ScriptOrigin origin(v8_str("test"));
    2001             :     v8::ScriptCompiler::Source source(source_str, origin, cache);
    2002             :     v8::ScriptCompiler::CompileUnboundScript(
    2003             :         isolate2, &source, v8::ScriptCompiler::kConsumeCodeCache)
    2004           5 :         .ToLocalChecked();
    2005           5 :     CHECK(cache->rejected);
    2006             :   }
    2007           5 :   isolate2->Dispose();
    2008           5 : }
    2009             : 
    2010       23723 : TEST(CodeSerializerWithHarmonyScoping) {
    2011             :   const char* source1 = "'use strict'; let x = 'X'";
    2012             :   const char* source2 = "'use strict'; let y = 'Y'";
    2013             :   const char* source3 = "'use strict'; x + y";
    2014             : 
    2015             :   v8::ScriptCompiler::CachedData* cache;
    2016             : 
    2017             :   v8::Isolate::CreateParams create_params;
    2018           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    2019           5 :   v8::Isolate* isolate1 = v8::Isolate::New(create_params);
    2020             :   {
    2021             :     v8::Isolate::Scope iscope(isolate1);
    2022          10 :     v8::HandleScope scope(isolate1);
    2023           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate1);
    2024             :     v8::Context::Scope context_scope(context);
    2025             : 
    2026             :     CompileRun(source1);
    2027             :     CompileRun(source2);
    2028             : 
    2029           5 :     v8::Local<v8::String> source_str = v8_str(source3);
    2030           5 :     v8::ScriptOrigin origin(v8_str("test"));
    2031             :     v8::ScriptCompiler::Source source(source_str, origin);
    2032             :     v8::Local<v8::UnboundScript> script =
    2033             :         v8::ScriptCompiler::CompileUnboundScript(
    2034             :             isolate1, &source, v8::ScriptCompiler::kProduceCodeCache)
    2035           5 :             .ToLocalChecked();
    2036           5 :     const v8::ScriptCompiler::CachedData* data = source.GetCachedData();
    2037           5 :     CHECK(data);
    2038             :     // Persist cached data.
    2039           5 :     uint8_t* buffer = NewArray<uint8_t>(data->length);
    2040           5 :     MemCopy(buffer, data->data, data->length);
    2041             :     cache = new v8::ScriptCompiler::CachedData(
    2042           5 :         buffer, data->length, v8::ScriptCompiler::CachedData::BufferOwned);
    2043             : 
    2044             :     v8::Local<v8::Value> result = script->BindToCurrentContext()
    2045          10 :                                       ->Run(isolate1->GetCurrentContext())
    2046           5 :                                       .ToLocalChecked();
    2047             :     v8::Local<v8::String> result_str =
    2048           5 :         result->ToString(isolate1->GetCurrentContext()).ToLocalChecked();
    2049          15 :     CHECK(result_str->Equals(isolate1->GetCurrentContext(), v8_str("XY"))
    2050             :               .FromJust());
    2051             :   }
    2052           5 :   isolate1->Dispose();
    2053             : 
    2054           5 :   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
    2055             :   {
    2056             :     v8::Isolate::Scope iscope(isolate2);
    2057          10 :     v8::HandleScope scope(isolate2);
    2058           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate2);
    2059             :     v8::Context::Scope context_scope(context);
    2060             : 
    2061             :     // Reverse order of prior running scripts.
    2062             :     CompileRun(source2);
    2063             :     CompileRun(source1);
    2064             : 
    2065           5 :     v8::Local<v8::String> source_str = v8_str(source3);
    2066           5 :     v8::ScriptOrigin origin(v8_str("test"));
    2067             :     v8::ScriptCompiler::Source source(source_str, origin, cache);
    2068             :     v8::Local<v8::UnboundScript> script;
    2069             :     {
    2070             :       DisallowCompilation no_compile(reinterpret_cast<Isolate*>(isolate2));
    2071             :       script = v8::ScriptCompiler::CompileUnboundScript(
    2072             :                    isolate2, &source, v8::ScriptCompiler::kConsumeCodeCache)
    2073           5 :                    .ToLocalChecked();
    2074             :     }
    2075           5 :     CheckDeserializedFlag(script);
    2076             :     v8::Local<v8::Value> result = script->BindToCurrentContext()
    2077          10 :                                       ->Run(isolate2->GetCurrentContext())
    2078           5 :                                       .ToLocalChecked();
    2079             :     v8::Local<v8::String> result_str =
    2080           5 :         result->ToString(isolate2->GetCurrentContext()).ToLocalChecked();
    2081          15 :     CHECK(result_str->Equals(isolate2->GetCurrentContext(), v8_str("XY"))
    2082             :               .FromJust());
    2083             :   }
    2084           5 :   isolate2->Dispose();
    2085           5 : }
    2086             : 
    2087       23723 : TEST(Regress503552) {
    2088           5 :   if (!FLAG_incremental_marking) return;
    2089             :   // Test that the code serializer can deal with weak cells that form a linked
    2090             :   // list during incremental marking.
    2091           5 :   CcTest::InitializeVM();
    2092             :   Isolate* isolate = CcTest::i_isolate();
    2093             : 
    2094             :   HandleScope scope(isolate);
    2095             :   Handle<String> source = isolate->factory()->NewStringFromAsciiChecked(
    2096           5 :       "function f() {} function g() {}");
    2097           5 :   ScriptData* script_data = nullptr;
    2098             :   Handle<SharedFunctionInfo> shared =
    2099             :       Compiler::GetSharedFunctionInfoForScript(
    2100             :           source, MaybeHandle<String>(), 0, 0, v8::ScriptOriginOptions(),
    2101             :           MaybeHandle<Object>(), Handle<Context>(isolate->native_context()),
    2102             :           nullptr, &script_data, v8::ScriptCompiler::kProduceCodeCache,
    2103          10 :           NOT_NATIVES_CODE, MaybeHandle<FixedArray>())
    2104          10 :           .ToHandleChecked();
    2105          10 :   delete script_data;
    2106             : 
    2107           5 :   heap::SimulateIncrementalMarking(isolate->heap());
    2108             : 
    2109           5 :   script_data = CodeSerializer::Serialize(isolate, shared, source);
    2110          10 :   delete script_data;
    2111             : }
    2112             : 
    2113       23723 : TEST(SnapshotCreatorMultipleContexts) {
    2114             :   DisableAlwaysOpt();
    2115             :   v8::StartupData blob;
    2116             :   {
    2117           5 :     v8::SnapshotCreator creator;
    2118           5 :     v8::Isolate* isolate = creator.GetIsolate();
    2119             :     {
    2120           5 :       v8::HandleScope handle_scope(isolate);
    2121           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2122             :       v8::Context::Scope context_scope(context);
    2123             :       CompileRun("var f = function() { return 1; }");
    2124          10 :       creator.SetDefaultContext(context);
    2125             :     }
    2126             :     {
    2127           5 :       v8::HandleScope handle_scope(isolate);
    2128           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2129             :       v8::Context::Scope context_scope(context);
    2130             :       CompileRun("var f = function() { return 2; }");
    2131          10 :       CHECK_EQ(0u, creator.AddContext(context));
    2132             :     }
    2133             :     {
    2134           5 :       v8::HandleScope handle_scope(isolate);
    2135           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2136           5 :       CHECK_EQ(1u, creator.AddContext(context));
    2137             :     }
    2138             :     blob =
    2139           5 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    2140             :   }
    2141             : 
    2142             :   v8::Isolate::CreateParams params;
    2143           5 :   params.snapshot_blob = &blob;
    2144           5 :   params.array_buffer_allocator = CcTest::array_buffer_allocator();
    2145             :   // Test-appropriate equivalent of v8::Isolate::New.
    2146           5 :   v8::Isolate* isolate = TestIsolate::New(params);
    2147             :   {
    2148             :     v8::Isolate::Scope isolate_scope(isolate);
    2149             :     {
    2150           5 :       v8::HandleScope handle_scope(isolate);
    2151           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2152             :       v8::Context::Scope context_scope(context);
    2153          10 :       ExpectInt32("f()", 1);
    2154             :     }
    2155             :     {
    2156           5 :       v8::HandleScope handle_scope(isolate);
    2157             :       v8::Local<v8::Context> context =
    2158          10 :           v8::Context::FromSnapshot(isolate, 0).ToLocalChecked();
    2159             :       v8::Context::Scope context_scope(context);
    2160          10 :       ExpectInt32("f()", 2);
    2161             :     }
    2162             :     {
    2163           5 :       v8::HandleScope handle_scope(isolate);
    2164             :       v8::Local<v8::Context> context =
    2165          10 :           v8::Context::FromSnapshot(isolate, 1).ToLocalChecked();
    2166             :       v8::Context::Scope context_scope(context);
    2167          10 :       ExpectUndefined("this.f");
    2168             :     }
    2169             :   }
    2170             : 
    2171           5 :   isolate->Dispose();
    2172           5 :   delete[] blob.data;
    2173           5 : }
    2174             : 
    2175          60 : static void SerializedCallback(
    2176          60 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    2177          60 :   args.GetReturnValue().Set(v8_num(42));
    2178          60 : }
    2179             : 
    2180          10 : static void SerializedCallbackReplacement(
    2181          10 :     const v8::FunctionCallbackInfo<v8::Value>& args) {
    2182          10 :   args.GetReturnValue().Set(v8_num(1337));
    2183          10 : }
    2184             : 
    2185         185 : static void NamedPropertyGetterForSerialization(
    2186             :     v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
    2187         555 :   if (name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("x"))
    2188         370 :           .FromJust()) {
    2189          20 :     info.GetReturnValue().Set(v8_num(2016));
    2190             :   }
    2191         185 : }
    2192             : 
    2193           5 : static void AccessorForSerialization(
    2194             :     v8::Local<v8::String> property,
    2195             :     const v8::PropertyCallbackInfo<v8::Value>& info) {
    2196           5 :   info.GetReturnValue().Set(v8_num(2017));
    2197           5 : }
    2198             : 
    2199             : static int serialized_static_field = 314;
    2200             : 
    2201           0 : class SerializedExtension : public v8::Extension {
    2202             :  public:
    2203           5 :   SerializedExtension()
    2204             :       : v8::Extension("serialized extension",
    2205             :                       "native function g();"
    2206             :                       "function h() { return 13; };"
    2207             :                       "function i() { return 14; };"
    2208           5 :                       "var o = { p: 7 };") {}
    2209             : 
    2210           5 :   virtual v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
    2211             :       v8::Isolate* isolate, v8::Local<v8::String> name) {
    2212          20 :     CHECK(name->Equals(isolate->GetCurrentContext(), v8_str("g")).FromJust());
    2213           5 :     return v8::FunctionTemplate::New(isolate, FunctionCallback);
    2214             :   }
    2215             : 
    2216          25 :   static void FunctionCallback(
    2217          25 :       const v8::FunctionCallbackInfo<v8::Value>& args) {
    2218          25 :     args.GetReturnValue().Set(v8_num(12));
    2219          25 :   }
    2220             : };
    2221             : 
    2222             : intptr_t original_external_references[] = {
    2223             :     reinterpret_cast<intptr_t>(SerializedCallback),
    2224             :     reinterpret_cast<intptr_t>(&serialized_static_field),
    2225             :     reinterpret_cast<intptr_t>(&NamedPropertyGetterForSerialization),
    2226             :     reinterpret_cast<intptr_t>(&AccessorForSerialization),
    2227             :     reinterpret_cast<intptr_t>(&SerializedExtension::FunctionCallback),
    2228             :     reinterpret_cast<intptr_t>(&serialized_static_field),  // duplicate entry
    2229             :     0};
    2230             : 
    2231             : intptr_t replaced_external_references[] = {
    2232             :     reinterpret_cast<intptr_t>(SerializedCallbackReplacement),
    2233             :     reinterpret_cast<intptr_t>(&serialized_static_field),
    2234             :     reinterpret_cast<intptr_t>(&NamedPropertyGetterForSerialization),
    2235             :     reinterpret_cast<intptr_t>(&AccessorForSerialization),
    2236             :     reinterpret_cast<intptr_t>(&SerializedExtension::FunctionCallback),
    2237             :     reinterpret_cast<intptr_t>(&serialized_static_field),
    2238             :     0};
    2239             : 
    2240             : intptr_t short_external_references[] = {
    2241             :     reinterpret_cast<intptr_t>(SerializedCallbackReplacement), 0};
    2242             : 
    2243       23723 : TEST(SnapshotCreatorExternalReferences) {
    2244             :   DisableAlwaysOpt();
    2245             :   v8::StartupData blob;
    2246             :   {
    2247           5 :     v8::SnapshotCreator creator(original_external_references);
    2248           5 :     v8::Isolate* isolate = creator.GetIsolate();
    2249             :     {
    2250           5 :       v8::HandleScope handle_scope(isolate);
    2251           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2252             :       v8::Context::Scope context_scope(context);
    2253             :       v8::Local<v8::FunctionTemplate> callback =
    2254           5 :           v8::FunctionTemplate::New(isolate, SerializedCallback);
    2255             :       v8::Local<v8::Value> function =
    2256           5 :           callback->GetFunction(context).ToLocalChecked();
    2257          20 :       CHECK(context->Global()->Set(context, v8_str("f"), function).FromJust());
    2258           5 :       ExpectInt32("f()", 42);
    2259          10 :       creator.SetDefaultContext(context);
    2260             :     }
    2261             :     blob =
    2262           5 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    2263             :   }
    2264             : 
    2265             :   // Deserialize with the original external reference.
    2266             :   {
    2267             :     v8::Isolate::CreateParams params;
    2268           5 :     params.snapshot_blob = &blob;
    2269           5 :     params.array_buffer_allocator = CcTest::array_buffer_allocator();
    2270           5 :     params.external_references = original_external_references;
    2271             :     // Test-appropriate equivalent of v8::Isolate::New.
    2272           5 :     v8::Isolate* isolate = TestIsolate::New(params);
    2273             :     {
    2274             :       v8::Isolate::Scope isolate_scope(isolate);
    2275          10 :       v8::HandleScope handle_scope(isolate);
    2276           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2277             :       v8::Context::Scope context_scope(context);
    2278           5 :       ExpectInt32("f()", 42);
    2279             :     }
    2280           5 :     isolate->Dispose();
    2281             :   }
    2282             : 
    2283             :   // Deserialize with some other external reference.
    2284             :   {
    2285             :     v8::Isolate::CreateParams params;
    2286           5 :     params.snapshot_blob = &blob;
    2287           5 :     params.array_buffer_allocator = CcTest::array_buffer_allocator();
    2288           5 :     params.external_references = replaced_external_references;
    2289             :     // Test-appropriate equivalent of v8::Isolate::New.
    2290           5 :     v8::Isolate* isolate = TestIsolate::New(params);
    2291             :     {
    2292             :       v8::Isolate::Scope isolate_scope(isolate);
    2293          10 :       v8::HandleScope handle_scope(isolate);
    2294           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2295             :       v8::Context::Scope context_scope(context);
    2296           5 :       ExpectInt32("f()", 1337);
    2297             :     }
    2298           5 :     isolate->Dispose();
    2299             :   }
    2300           5 :   delete[] blob.data;
    2301           5 : }
    2302             : 
    2303       23723 : TEST(SnapshotCreatorShortExternalReferences) {
    2304             :   DisableAlwaysOpt();
    2305             :   v8::StartupData blob;
    2306             :   {
    2307           5 :     v8::SnapshotCreator creator(original_external_references);
    2308           5 :     v8::Isolate* isolate = creator.GetIsolate();
    2309             :     {
    2310           5 :       v8::HandleScope handle_scope(isolate);
    2311           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2312             :       v8::Context::Scope context_scope(context);
    2313             :       v8::Local<v8::FunctionTemplate> callback =
    2314           5 :           v8::FunctionTemplate::New(isolate, SerializedCallback);
    2315             :       v8::Local<v8::Value> function =
    2316           5 :           callback->GetFunction(context).ToLocalChecked();
    2317          20 :       CHECK(context->Global()->Set(context, v8_str("f"), function).FromJust());
    2318           5 :       ExpectInt32("f()", 42);
    2319          10 :       creator.SetDefaultContext(context);
    2320             :     }
    2321             :     blob =
    2322           5 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    2323             :   }
    2324             : 
    2325             :   // Deserialize with an incomplete list of external references.
    2326             :   {
    2327             :     v8::Isolate::CreateParams params;
    2328           5 :     params.snapshot_blob = &blob;
    2329           5 :     params.array_buffer_allocator = CcTest::array_buffer_allocator();
    2330           5 :     params.external_references = short_external_references;
    2331             :     // Test-appropriate equivalent of v8::Isolate::New.
    2332           5 :     v8::Isolate* isolate = TestIsolate::New(params);
    2333             :     {
    2334             :       v8::Isolate::Scope isolate_scope(isolate);
    2335          10 :       v8::HandleScope handle_scope(isolate);
    2336           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2337             :       v8::Context::Scope context_scope(context);
    2338           5 :       ExpectInt32("f()", 1337);
    2339             :     }
    2340           5 :     isolate->Dispose();
    2341             :   }
    2342           5 :   delete[] blob.data;
    2343           5 : }
    2344             : 
    2345       23718 : TEST(SnapshotCreatorUnknownExternalReferences) {
    2346             :   DisableAlwaysOpt();
    2347           0 :   v8::SnapshotCreator creator;
    2348           0 :   v8::Isolate* isolate = creator.GetIsolate();
    2349             :   {
    2350           0 :     v8::HandleScope handle_scope(isolate);
    2351           0 :     v8::Local<v8::Context> context = v8::Context::New(isolate);
    2352             :     v8::Context::Scope context_scope(context);
    2353             : 
    2354             :     v8::Local<v8::FunctionTemplate> callback =
    2355           0 :         v8::FunctionTemplate::New(isolate, SerializedCallback);
    2356             :     v8::Local<v8::Value> function =
    2357           0 :         callback->GetFunction(context).ToLocalChecked();
    2358           0 :     CHECK(context->Global()->Set(context, v8_str("f"), function).FromJust());
    2359           0 :     ExpectInt32("f()", 42);
    2360             : 
    2361           0 :     creator.SetDefaultContext(context);
    2362             :   }
    2363             :   v8::StartupData blob =
    2364           0 :       creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    2365             : 
    2366           0 :   delete[] blob.data;
    2367           0 : }
    2368             : 
    2369       23723 : TEST(SnapshotCreatorTemplates) {
    2370             :   DisableAlwaysOpt();
    2371             :   v8::StartupData blob;
    2372             : 
    2373             :   {
    2374           5 :     InternalFieldData* a1 = new InternalFieldData{11};
    2375           5 :     InternalFieldData* b0 = new InternalFieldData{20};
    2376           5 :     InternalFieldData* c0 = new InternalFieldData{30};
    2377             : 
    2378           5 :     v8::SnapshotCreator creator(original_external_references);
    2379           5 :     v8::Isolate* isolate = creator.GetIsolate();
    2380             :     {
    2381           5 :       v8::HandleScope handle_scope(isolate);
    2382             :       v8::ExtensionConfiguration* no_extension = nullptr;
    2383             :       v8::Local<v8::ObjectTemplate> global_template =
    2384           5 :           v8::ObjectTemplate::New(isolate);
    2385             :       v8::Local<v8::FunctionTemplate> callback =
    2386           5 :           v8::FunctionTemplate::New(isolate, SerializedCallback);
    2387          10 :       global_template->Set(v8_str("f"), callback);
    2388             :       v8::Local<v8::Context> context =
    2389           5 :           v8::Context::New(isolate, no_extension, global_template);
    2390           5 :       creator.SetDefaultContext(context);
    2391           5 :       context = v8::Context::New(isolate, no_extension, global_template);
    2392             :       v8::Local<v8::ObjectTemplate> object_template =
    2393           5 :           v8::ObjectTemplate::New(isolate);
    2394           5 :       object_template->SetInternalFieldCount(3);
    2395             : 
    2396             :       v8::Context::Scope context_scope(context);
    2397           5 :       ExpectInt32("f()", 42);
    2398             : 
    2399             :       v8::Local<v8::Object> a =
    2400           5 :           object_template->NewInstance(context).ToLocalChecked();
    2401             :       v8::Local<v8::Object> b =
    2402           5 :           object_template->NewInstance(context).ToLocalChecked();
    2403             :       v8::Local<v8::Object> c =
    2404           5 :           object_template->NewInstance(context).ToLocalChecked();
    2405             :       v8::Local<v8::External> null_external =
    2406           5 :           v8::External::New(isolate, nullptr);
    2407             :       v8::Local<v8::External> field_external =
    2408           5 :           v8::External::New(isolate, &serialized_static_field);
    2409           5 :       a->SetInternalField(0, b);
    2410           5 :       a->SetAlignedPointerInInternalField(1, a1);
    2411           5 :       b->SetAlignedPointerInInternalField(0, b0);
    2412           5 :       b->SetInternalField(1, c);
    2413           5 :       c->SetAlignedPointerInInternalField(0, c0);
    2414           5 :       c->SetInternalField(1, null_external);
    2415           5 :       c->SetInternalField(2, field_external);
    2416          20 :       CHECK(context->Global()->Set(context, v8_str("a"), a).FromJust());
    2417             : 
    2418           5 :       CHECK_EQ(0u,
    2419             :                creator.AddContext(context, v8::SerializeInternalFieldsCallback(
    2420             :                                                SerializeInternalFields,
    2421             :                                                reinterpret_cast<void*>(2016))));
    2422           5 :       CHECK_EQ(0u, creator.AddTemplate(callback));
    2423          10 :       CHECK_EQ(1u, creator.AddTemplate(global_template));
    2424             :     }
    2425             :     blob =
    2426           5 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    2427             : 
    2428           5 :     delete a1;
    2429           5 :     delete b0;
    2430           5 :     delete c0;
    2431             :   }
    2432             : 
    2433             :   {
    2434             :     v8::Isolate::CreateParams params;
    2435           5 :     params.snapshot_blob = &blob;
    2436           5 :     params.array_buffer_allocator = CcTest::array_buffer_allocator();
    2437           5 :     params.external_references = original_external_references;
    2438             :     // Test-appropriate equivalent of v8::Isolate::New.
    2439           5 :     v8::Isolate* isolate = TestIsolate::New(params);
    2440             :     {
    2441             :       v8::Isolate::Scope isolate_scope(isolate);
    2442             :       {
    2443             :         // Create a new context without a new object template.
    2444           5 :         v8::HandleScope handle_scope(isolate);
    2445             :         v8::Local<v8::Context> context =
    2446             :             v8::Context::FromSnapshot(
    2447             :                 isolate, 0,
    2448             :                 v8::DeserializeInternalFieldsCallback(
    2449           5 :                     DeserializeInternalFields, reinterpret_cast<void*>(2017)))
    2450           5 :                 .ToLocalChecked();
    2451             :         v8::Context::Scope context_scope(context);
    2452           5 :         ExpectInt32("f()", 42);
    2453             : 
    2454             :         // Retrieve the snapshotted object template.
    2455             :         v8::Local<v8::ObjectTemplate> obj_template =
    2456           5 :             v8::ObjectTemplate::FromSnapshot(isolate, 1).ToLocalChecked();
    2457           5 :         CHECK(!obj_template.IsEmpty());
    2458             :         v8::Local<v8::Object> object =
    2459           5 :             obj_template->NewInstance(context).ToLocalChecked();
    2460          20 :         CHECK(context->Global()->Set(context, v8_str("o"), object).FromJust());
    2461           5 :         ExpectInt32("o.f()", 42);
    2462             :         // Check that it instantiates to the same prototype.
    2463             :         ExpectTrue("o.f.prototype === f.prototype");
    2464             : 
    2465             :         // Retrieve the snapshotted function template.
    2466             :         v8::Local<v8::FunctionTemplate> fun_template =
    2467           5 :             v8::FunctionTemplate::FromSnapshot(isolate, 0).ToLocalChecked();
    2468           5 :         CHECK(!fun_template.IsEmpty());
    2469             :         v8::Local<v8::Function> fun =
    2470           5 :             fun_template->GetFunction(context).ToLocalChecked();
    2471          20 :         CHECK(context->Global()->Set(context, v8_str("g"), fun).FromJust());
    2472           5 :         ExpectInt32("g()", 42);
    2473             :         // Check that it instantiates to the same prototype.
    2474             :         ExpectTrue("g.prototype === f.prototype");
    2475             : 
    2476             :         // Retrieve embedder fields.
    2477             :         v8::Local<v8::Object> a = context->Global()
    2478          15 :                                       ->Get(context, v8_str("a"))
    2479           5 :                                       .ToLocalChecked()
    2480             :                                       ->ToObject(context)
    2481           5 :                                       .ToLocalChecked();
    2482             :         v8::Local<v8::Object> b =
    2483           5 :             a->GetInternalField(0)->ToObject(context).ToLocalChecked();
    2484             :         InternalFieldData* a1 = reinterpret_cast<InternalFieldData*>(
    2485             :             a->GetAlignedPointerFromInternalField(1));
    2486             :         v8::Local<v8::Value> a2 = a->GetInternalField(2);
    2487             : 
    2488             :         InternalFieldData* b0 = reinterpret_cast<InternalFieldData*>(
    2489             :             b->GetAlignedPointerFromInternalField(0));
    2490             :         v8::Local<v8::Object> c =
    2491           5 :             b->GetInternalField(1)->ToObject(context).ToLocalChecked();
    2492             :         v8::Local<v8::Value> b2 = b->GetInternalField(2);
    2493             : 
    2494             :         InternalFieldData* c0 = reinterpret_cast<InternalFieldData*>(
    2495             :             c->GetAlignedPointerFromInternalField(0));
    2496             :         v8::Local<v8::Value> c1 = c->GetInternalField(1);
    2497             :         v8::Local<v8::Value> c2 = c->GetInternalField(2);
    2498             : 
    2499           5 :         CHECK_EQ(11u, a1->data);
    2500           5 :         CHECK(a2->IsUndefined());
    2501           5 :         CHECK_EQ(20u, b0->data);
    2502           5 :         CHECK(b2->IsUndefined());
    2503           5 :         CHECK_EQ(30u, c0->data);
    2504           5 :         CHECK(c1->IsExternal());
    2505           5 :         CHECK_NULL(v8::Local<v8::External>::Cast(c1)->Value());
    2506           5 :         CHECK_EQ(static_cast<void*>(&serialized_static_field),
    2507             :                  v8::Local<v8::External>::Cast(c2)->Value());
    2508             : 
    2509             :         // Accessing out of bound returns empty MaybeHandle.
    2510          10 :         CHECK(v8::ObjectTemplate::FromSnapshot(isolate, 2).IsEmpty());
    2511          10 :         CHECK(v8::FunctionTemplate::FromSnapshot(isolate, 2).IsEmpty());
    2512          10 :         CHECK(v8::Context::FromSnapshot(isolate, 1).IsEmpty());
    2513             : 
    2514          25 :         for (auto data : deserialized_data) delete data;
    2515           5 :         deserialized_data.clear();
    2516             :       }
    2517             :     }
    2518           5 :     isolate->Dispose();
    2519             :   }
    2520           5 :   delete[] blob.data;
    2521           5 : }
    2522             : 
    2523       23723 : TEST(SnapshotCreatorIncludeGlobalProxy) {
    2524             :   DisableAlwaysOpt();
    2525             :   v8::StartupData blob;
    2526             : 
    2527             :   {
    2528           5 :     v8::SnapshotCreator creator(original_external_references);
    2529           5 :     v8::Isolate* isolate = creator.GetIsolate();
    2530           5 :     v8::RegisterExtension(new SerializedExtension);
    2531           5 :     const char* extension_names[] = {"serialized extension"};
    2532             :     v8::ExtensionConfiguration extensions(1, extension_names);
    2533             :     {
    2534             :       // Set default context. This context implicitly does *not* serialize
    2535             :       // the global proxy, and upon deserialization one has to be created
    2536             :       // in the bootstrapper from the global object template.
    2537             :       // Side effects from extensions are persisted though.
    2538           5 :       v8::HandleScope handle_scope(isolate);
    2539             :       v8::Local<v8::ObjectTemplate> global_template =
    2540           5 :           v8::ObjectTemplate::New(isolate);
    2541             :       v8::Local<v8::FunctionTemplate> callback =
    2542           5 :           v8::FunctionTemplate::New(isolate, SerializedCallback);
    2543          10 :       global_template->Set(v8_str("f"), callback);
    2544             :       global_template->SetHandler(v8::NamedPropertyHandlerConfiguration(
    2545           5 :           NamedPropertyGetterForSerialization));
    2546             :       v8::Local<v8::Context> context =
    2547           5 :           v8::Context::New(isolate, &extensions, global_template);
    2548             :       v8::Context::Scope context_scope(context);
    2549           5 :       ExpectInt32("f()", 42);
    2550           5 :       ExpectInt32("g()", 12);
    2551           5 :       ExpectInt32("h()", 13);
    2552           5 :       ExpectInt32("o.p", 7);
    2553           5 :       ExpectInt32("x", 2016);
    2554          10 :       creator.SetDefaultContext(context);
    2555             :     }
    2556             :     {
    2557             :       // Add additional context. This context implicitly *does* serialize
    2558             :       // the global proxy, and upon deserialization one has to be created
    2559             :       // in the bootstrapper from the global object template.
    2560             :       // Side effects from extensions are persisted.
    2561           5 :       v8::HandleScope handle_scope(isolate);
    2562             :       v8::Local<v8::ObjectTemplate> global_template =
    2563           5 :           v8::ObjectTemplate::New(isolate);
    2564             :       v8::Local<v8::FunctionTemplate> callback =
    2565           5 :           v8::FunctionTemplate::New(isolate, SerializedCallback);
    2566           5 :       global_template->SetInternalFieldCount(3);
    2567          10 :       global_template->Set(v8_str("f"), callback);
    2568             :       global_template->SetHandler(v8::NamedPropertyHandlerConfiguration(
    2569           5 :           NamedPropertyGetterForSerialization));
    2570           5 :       global_template->SetAccessor(v8_str("y"), AccessorForSerialization);
    2571             :       v8::Local<v8::Private> priv =
    2572           5 :           v8::Private::ForApi(isolate, v8_str("cached"));
    2573             :       global_template->SetAccessorProperty(
    2574             :           v8_str("cached"),
    2575             :           v8::FunctionTemplate::NewWithCache(isolate, SerializedCallback, priv,
    2576          10 :                                              v8::Local<v8::Value>()));
    2577             :       v8::Local<v8::Context> context =
    2578           5 :           v8::Context::New(isolate, &extensions, global_template);
    2579             :       v8::Context::Scope context_scope(context);
    2580             : 
    2581          20 :       CHECK(context->Global()
    2582             :                 ->SetPrivate(context, priv, v8_str("cached string"))
    2583             :                 .FromJust());
    2584             :       v8::Local<v8::Private> hidden =
    2585           5 :           v8::Private::ForApi(isolate, v8_str("hidden"));
    2586          20 :       CHECK(context->Global()
    2587             :                 ->SetPrivate(context, hidden, v8_str("hidden string"))
    2588             :                 .FromJust());
    2589             : 
    2590           5 :       ExpectInt32("f()", 42);
    2591           5 :       ExpectInt32("g()", 12);
    2592           5 :       ExpectInt32("h()", 13);
    2593           5 :       ExpectInt32("o.p", 7);
    2594           5 :       ExpectInt32("x", 2016);
    2595           5 :       ExpectInt32("y", 2017);
    2596          25 :       CHECK(v8_str("hidden string")
    2597             :                 ->Equals(context, context->Global()
    2598             :                                       ->GetPrivate(context, hidden)
    2599             :                                       .ToLocalChecked())
    2600             :                 .FromJust());
    2601             : 
    2602           5 :       CHECK_EQ(0u,
    2603             :                creator.AddContext(context, v8::SerializeInternalFieldsCallback(
    2604             :                                                SerializeInternalFields,
    2605           5 :                                                reinterpret_cast<void*>(2016))));
    2606             :     }
    2607             :     blob =
    2608           5 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    2609             :   }
    2610             : 
    2611             :   {
    2612             :     v8::Isolate::CreateParams params;
    2613           5 :     params.snapshot_blob = &blob;
    2614           5 :     params.array_buffer_allocator = CcTest::array_buffer_allocator();
    2615           5 :     params.external_references = original_external_references;
    2616             :     // Test-appropriate equivalent of v8::Isolate::New.
    2617           5 :     v8::Isolate* isolate = TestIsolate::New(params);
    2618             :     {
    2619             :       v8::Isolate::Scope isolate_scope(isolate);
    2620             :       // We can introduce new extensions, which could override the already
    2621             :       // snapshotted extension.
    2622             :       v8::Extension* extension = new v8::Extension("new extension",
    2623             :                                                    "function i() { return 24; }"
    2624             :                                                    "function j() { return 25; }"
    2625           5 :                                                    "if (o.p == 7) o.p++;");
    2626             :       extension->set_auto_enable(true);
    2627           5 :       v8::RegisterExtension(extension);
    2628             :       {
    2629             :         // Create a new context from default context snapshot. This will
    2630             :         // create a new global object from a new global object template
    2631             :         // without the interceptor.
    2632           5 :         v8::HandleScope handle_scope(isolate);
    2633           5 :         v8::Local<v8::Context> context = v8::Context::New(isolate);
    2634             :         v8::Context::Scope context_scope(context);
    2635           5 :         ExpectInt32("f()", 42);
    2636           5 :         ExpectInt32("g()", 12);
    2637           5 :         ExpectInt32("h()", 13);
    2638           5 :         ExpectInt32("i()", 24);
    2639           5 :         ExpectInt32("j()", 25);
    2640           5 :         ExpectInt32("o.p", 8);
    2641          10 :         v8::TryCatch try_catch(isolate);
    2642           5 :         CHECK(CompileRun("x").IsEmpty());
    2643          10 :         CHECK(try_catch.HasCaught());
    2644             :       }
    2645             :       {
    2646             :         // Create a new context from first additional context snapshot. This
    2647             :         // will use the global object from the snapshot, including interceptor.
    2648           5 :         v8::HandleScope handle_scope(isolate);
    2649             :         v8::Local<v8::Context> context =
    2650             :             v8::Context::FromSnapshot(
    2651             :                 isolate, 0,
    2652             :                 v8::DeserializeInternalFieldsCallback(
    2653           5 :                     DeserializeInternalFields, reinterpret_cast<void*>(2017)))
    2654           5 :                 .ToLocalChecked();
    2655             : 
    2656             :         {
    2657             :           v8::Context::Scope context_scope(context);
    2658           5 :           ExpectInt32("f()", 42);
    2659           5 :           ExpectInt32("g()", 12);
    2660           5 :           ExpectInt32("h()", 13);
    2661           5 :           ExpectInt32("i()", 24);
    2662           5 :           ExpectInt32("j()", 25);
    2663           5 :           ExpectInt32("o.p", 8);
    2664           5 :           ExpectInt32("x", 2016);
    2665             :           v8::Local<v8::Private> hidden =
    2666           5 :               v8::Private::ForApi(isolate, v8_str("hidden"));
    2667          25 :           CHECK(v8_str("hidden string")
    2668             :                     ->Equals(context, context->Global()
    2669             :                                           ->GetPrivate(context, hidden)
    2670             :                                           .ToLocalChecked())
    2671             :                     .FromJust());
    2672           5 :           ExpectString("cached", "cached string");
    2673             :         }
    2674             : 
    2675           5 :         v8::Local<v8::Object> global = context->Global();
    2676           5 :         CHECK_EQ(3, global->InternalFieldCount());
    2677           5 :         context->DetachGlobal();
    2678             : 
    2679             :         // New context, but reuse global proxy.
    2680             :         v8::ExtensionConfiguration* no_extensions = nullptr;
    2681             :         v8::Local<v8::Context> context2 =
    2682             :             v8::Context::FromSnapshot(
    2683             :                 isolate, 0,
    2684             :                 v8::DeserializeInternalFieldsCallback(
    2685             :                     DeserializeInternalFields, reinterpret_cast<void*>(2017)),
    2686           5 :                 no_extensions, global)
    2687           5 :                 .ToLocalChecked();
    2688             :         {
    2689             :           v8::Context::Scope context_scope(context2);
    2690           5 :           ExpectInt32("f()", 42);
    2691           5 :           ExpectInt32("g()", 12);
    2692           5 :           ExpectInt32("h()", 13);
    2693           5 :           ExpectInt32("i()", 24);
    2694           5 :           ExpectInt32("j()", 25);
    2695           5 :           ExpectInt32("o.p", 8);
    2696           5 :           ExpectInt32("x", 2016);
    2697             :           v8::Local<v8::Private> hidden =
    2698           5 :               v8::Private::ForApi(isolate, v8_str("hidden"));
    2699          25 :           CHECK(v8_str("hidden string")
    2700             :                     ->Equals(context2, context2->Global()
    2701             :                                            ->GetPrivate(context2, hidden)
    2702             :                                            .ToLocalChecked())
    2703             :                     .FromJust());
    2704             : 
    2705             :           // Set cached accessor property again.
    2706             :           v8::Local<v8::Private> priv =
    2707           5 :               v8::Private::ForApi(isolate, v8_str("cached"));
    2708          20 :           CHECK(context2->Global()
    2709             :                     ->SetPrivate(context2, priv, v8_str("cached string 1"))
    2710             :                     .FromJust());
    2711           5 :           ExpectString("cached", "cached string 1");
    2712             :         }
    2713             : 
    2714          15 :         CHECK(context2->Global()->Equals(context2, global).FromJust());
    2715             :       }
    2716             :     }
    2717           5 :     isolate->Dispose();
    2718             :   }
    2719           5 :   delete[] blob.data;
    2720           5 : }
    2721             : 
    2722       23723 : UNINITIALIZED_TEST(ReinitializeStringHashSeedNotRehashable) {
    2723             :   DisableAlwaysOpt();
    2724           5 :   i::FLAG_rehash_snapshot = true;
    2725           5 :   i::FLAG_hash_seed = 42;
    2726           5 :   i::FLAG_allow_natives_syntax = true;
    2727             :   v8::StartupData blob;
    2728             :   {
    2729           5 :     v8::SnapshotCreator creator;
    2730           5 :     v8::Isolate* isolate = creator.GetIsolate();
    2731             :     {
    2732           5 :       v8::HandleScope handle_scope(isolate);
    2733           5 :       v8::Local<v8::Context> context = v8::Context::New(isolate);
    2734             :       v8::Context::Scope context_scope(context);
    2735             :       // Create dictionary mode object.
    2736             :       CompileRun(
    2737             :           "var a = {};"
    2738             :           "a.b = 1;"
    2739             :           "a.c = 2;"
    2740             :           "delete a.b;");
    2741           5 :       ExpectInt32("a.c", 2);
    2742          10 :       creator.SetDefaultContext(context);
    2743             :     }
    2744             :     blob =
    2745           5 :         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
    2746             :   }
    2747             : 
    2748           5 :   i::FLAG_hash_seed = 1337;
    2749             :   v8::Isolate::CreateParams create_params;
    2750           5 :   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    2751           5 :   create_params.snapshot_blob = &blob;
    2752           5 :   v8::Isolate* isolate = v8::Isolate::New(create_params);
    2753             :   {
    2754             :     // Check that no rehashing has been performed.
    2755           5 :     CHECK_EQ(42, reinterpret_cast<i::Isolate*>(isolate)->heap()->HashSeed());
    2756             :     v8::Isolate::Scope isolate_scope(isolate);
    2757          10 :     v8::HandleScope handle_scope(isolate);
    2758           5 :     v8::Local<v8::Context> context = v8::Context::New(isolate);
    2759           5 :     CHECK(!context.IsEmpty());
    2760             :     v8::Context::Scope context_scope(context);
    2761           5 :     ExpectInt32("a.c", 2);
    2762             :   }
    2763           5 :   isolate->Dispose();
    2764           5 :   delete[] blob.data;
    2765           5 : }
    2766             : 
    2767       23723 : TEST(SerializationMemoryStats) {
    2768           5 :   FLAG_profile_deserialization = true;
    2769           5 :   FLAG_always_opt = false;
    2770           5 :   v8::StartupData blob = v8::V8::CreateSnapshotDataBlob();
    2771           5 :   delete[] blob.data;
    2772           5 : }
    2773             : 
    2774       23723 : TEST(BuiltinsHaveBuiltinIdForLazyDeserialization) {
    2775           5 :   CcTest::InitializeVM();
    2776             :   Isolate* isolate = CcTest::i_isolate();
    2777             :   i::HandleScope scope(isolate);
    2778             : 
    2779           5 :   CHECK(Builtins::IsLazy(Builtins::kRegExpPrototypeExec));
    2780          10 :   CHECK_EQ(Builtins::kRegExpPrototypeExec,
    2781             :            isolate->regexp_exec_function()
    2782             :                ->shared()
    2783             :                ->lazy_deserialization_builtin_id());
    2784           5 :   CHECK(Builtins::IsLazy(Builtins::kAsyncIteratorValueUnwrap));
    2785          10 :   CHECK_EQ(Builtins::kAsyncIteratorValueUnwrap,
    2786             :            isolate->async_iterator_value_unwrap_shared_fun()
    2787             :                ->lazy_deserialization_builtin_id());
    2788             : 
    2789           5 :   CHECK(!Builtins::IsLazy(Builtins::kIllegal));
    2790          10 :   CHECK(!isolate->opaque_reference_function()
    2791             :              ->shared()
    2792             :              ->HasLazyDeserializationBuiltinId());
    2793           5 : }
    2794             : 
    2795             : }  // namespace internal
    2796       71154 : }  // namespace v8

Generated by: LCOV version 1.10