Home | History | Annotate | Download | only in cctest
      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/ast/scopeinfo.h"
     35 #include "src/bootstrapper.h"
     36 #include "src/compilation-cache.h"
     37 #include "src/debug/debug.h"
     38 #include "src/heap/spaces.h"
     39 #include "src/macro-assembler.h"
     40 #include "src/objects.h"
     41 #include "src/parsing/parser.h"
     42 #include "src/runtime/runtime.h"
     43 #include "src/snapshot/code-serializer.h"
     44 #include "src/snapshot/deserializer.h"
     45 #include "src/snapshot/natives.h"
     46 #include "src/snapshot/partial-serializer.h"
     47 #include "src/snapshot/snapshot.h"
     48 #include "src/snapshot/startup-serializer.h"
     49 #include "test/cctest/cctest.h"
     50 #include "test/cctest/heap/heap-utils.h"
     51 
     52 using namespace v8::internal;
     53 
     54 void DisableTurbofan() {
     55   const char* flag = "--turbo-filter=\"\"";
     56   FlagList::SetFlagsFromString(flag, StrLength(flag));
     57 }
     58 
     59 
     60 // TestIsolate is used for testing isolate serialization.
     61 class TestIsolate : public Isolate {
     62  public:
     63   static v8::Isolate* NewInitialized(bool enable_serializer) {
     64     i::Isolate* isolate = new TestIsolate(enable_serializer);
     65     v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
     66     v8::Isolate::Scope isolate_scope(v8_isolate);
     67     isolate->Init(NULL);
     68     return v8_isolate;
     69   }
     70   explicit TestIsolate(bool enable_serializer) : Isolate(enable_serializer) {
     71     set_array_buffer_allocator(CcTest::array_buffer_allocator());
     72   }
     73 };
     74 
     75 static Vector<const byte> WritePayload(const Vector<const byte>& payload) {
     76   int length = payload.length();
     77   byte* blob = NewArray<byte>(length);
     78   memcpy(blob, payload.begin(), length);
     79   return Vector<const byte>(const_cast<const byte*>(blob), length);
     80 }
     81 
     82 static Vector<const byte> Serialize(v8::Isolate* isolate) {
     83   // We have to create one context.  One reason for this is so that the builtins
     84   // can be loaded from v8natives.js and their addresses can be processed.  This
     85   // will clear the pending fixups array, which would otherwise contain GC roots
     86   // that would confuse the serialization/deserialization process.
     87   v8::Isolate::Scope isolate_scope(isolate);
     88   {
     89     v8::HandleScope scope(isolate);
     90     v8::Context::New(isolate);
     91   }
     92 
     93   Isolate* internal_isolate = reinterpret_cast<Isolate*>(isolate);
     94   internal_isolate->heap()->CollectAllAvailableGarbage("serialize");
     95   StartupSerializer ser(internal_isolate,
     96                         v8::SnapshotCreator::FunctionCodeHandling::kClear);
     97   ser.SerializeStrongReferences();
     98   ser.SerializeWeakReferencesAndDeferred();
     99   SnapshotData snapshot_data(&ser);
    100   return WritePayload(snapshot_data.RawData());
    101 }
    102 
    103 
    104 Vector<const uint8_t> ConstructSource(Vector<const uint8_t> head,
    105                                       Vector<const uint8_t> body,
    106                                       Vector<const uint8_t> tail, int repeats) {
    107   int source_length = head.length() + body.length() * repeats + tail.length();
    108   uint8_t* source = NewArray<uint8_t>(static_cast<size_t>(source_length));
    109   CopyChars(source, head.start(), head.length());
    110   for (int i = 0; i < repeats; i++) {
    111     CopyChars(source + head.length() + i * body.length(), body.start(),
    112               body.length());
    113   }
    114   CopyChars(source + head.length() + repeats * body.length(), tail.start(),
    115             tail.length());
    116   return Vector<const uint8_t>(const_cast<const uint8_t*>(source),
    117                                source_length);
    118 }
    119 
    120 v8::Isolate* InitializeFromBlob(Vector<const byte> blob) {
    121   v8::Isolate* v8_isolate = NULL;
    122   {
    123     SnapshotData snapshot_data(blob);
    124     Deserializer deserializer(&snapshot_data);
    125     Isolate* isolate = new TestIsolate(false);
    126     v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
    127     v8::Isolate::Scope isolate_scope(v8_isolate);
    128     isolate->Init(&deserializer);
    129   }
    130   return v8_isolate;
    131 }
    132 
    133 static v8::Isolate* Deserialize(Vector<const byte> blob) {
    134   v8::Isolate* isolate = InitializeFromBlob(blob);
    135   CHECK(isolate);
    136   return isolate;
    137 }
    138 
    139 
    140 static void SanityCheck(v8::Isolate* v8_isolate) {
    141   Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
    142   v8::HandleScope scope(v8_isolate);
    143 #ifdef VERIFY_HEAP
    144   isolate->heap()->Verify();
    145 #endif
    146   CHECK(isolate->global_object()->IsJSObject());
    147   CHECK(isolate->native_context()->IsContext());
    148   CHECK(isolate->heap()->string_table()->IsStringTable());
    149   isolate->factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("Empty"));
    150 }
    151 
    152 UNINITIALIZED_TEST(StartupSerializerOnce) {
    153   // The serialize-deserialize tests only work if the VM is built without
    154   // serialization.  That doesn't matter.  We don't need to be able to
    155   // serialize a snapshot in a VM that is booted from a snapshot.
    156   DisableTurbofan();
    157   v8::Isolate* isolate = TestIsolate::NewInitialized(true);
    158   Vector<const byte> blob = Serialize(isolate);
    159   isolate = Deserialize(blob);
    160   blob.Dispose();
    161   {
    162     v8::HandleScope handle_scope(isolate);
    163     v8::Isolate::Scope isolate_scope(isolate);
    164 
    165     v8::Local<v8::Context> env = v8::Context::New(isolate);
    166     env->Enter();
    167 
    168     SanityCheck(isolate);
    169   }
    170   isolate->Dispose();
    171 }
    172 
    173 UNINITIALIZED_TEST(StartupSerializerTwice) {
    174   DisableTurbofan();
    175   v8::Isolate* isolate = TestIsolate::NewInitialized(true);
    176   Vector<const byte> blob1 = Serialize(isolate);
    177   Vector<const byte> blob2 = Serialize(isolate);
    178   blob1.Dispose();
    179   isolate = Deserialize(blob2);
    180   blob2.Dispose();
    181   {
    182     v8::Isolate::Scope isolate_scope(isolate);
    183     v8::HandleScope handle_scope(isolate);
    184 
    185     v8::Local<v8::Context> env = v8::Context::New(isolate);
    186     env->Enter();
    187 
    188     SanityCheck(isolate);
    189   }
    190   isolate->Dispose();
    191 }
    192 
    193 UNINITIALIZED_TEST(StartupSerializerOnceRunScript) {
    194   DisableTurbofan();
    195   v8::Isolate* isolate = TestIsolate::NewInitialized(true);
    196   Vector<const byte> blob = Serialize(isolate);
    197   isolate = Deserialize(blob);
    198   blob.Dispose();
    199   {
    200     v8::Isolate::Scope isolate_scope(isolate);
    201     v8::HandleScope handle_scope(isolate);
    202 
    203 
    204     v8::Local<v8::Context> env = v8::Context::New(isolate);
    205     env->Enter();
    206 
    207     const char* c_source = "\"1234\".length";
    208     v8::Local<v8::Script> script = v8_compile(c_source);
    209     v8::Maybe<int32_t> result = script->Run(isolate->GetCurrentContext())
    210                                     .ToLocalChecked()
    211                                     ->Int32Value(isolate->GetCurrentContext());
    212     CHECK_EQ(4, result.FromJust());
    213   }
    214   isolate->Dispose();
    215 }
    216 
    217 UNINITIALIZED_TEST(StartupSerializerTwiceRunScript) {
    218   DisableTurbofan();
    219   v8::Isolate* isolate = TestIsolate::NewInitialized(true);
    220   Vector<const byte> blob1 = Serialize(isolate);
    221   Vector<const byte> blob2 = Serialize(isolate);
    222   blob1.Dispose();
    223   isolate = Deserialize(blob2);
    224   blob2.Dispose();
    225   {
    226     v8::Isolate::Scope isolate_scope(isolate);
    227     v8::HandleScope handle_scope(isolate);
    228 
    229     v8::Local<v8::Context> env = v8::Context::New(isolate);
    230     env->Enter();
    231 
    232     const char* c_source = "\"1234\".length";
    233     v8::Local<v8::Script> script = v8_compile(c_source);
    234     v8::Maybe<int32_t> result = script->Run(isolate->GetCurrentContext())
    235                                     .ToLocalChecked()
    236                                     ->Int32Value(isolate->GetCurrentContext());
    237     CHECK_EQ(4, result.FromJust());
    238   }
    239   isolate->Dispose();
    240 }
    241 
    242 static void PartiallySerializeObject(Vector<const byte>* startup_blob_out,
    243                                      Vector<const byte>* partial_blob_out) {
    244   v8::Isolate* v8_isolate = TestIsolate::NewInitialized(true);
    245   Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
    246   v8_isolate->Enter();
    247   {
    248     Heap* heap = isolate->heap();
    249 
    250     v8::Persistent<v8::Context> env;
    251     {
    252       HandleScope scope(isolate);
    253       env.Reset(v8_isolate, v8::Context::New(v8_isolate));
    254     }
    255     CHECK(!env.IsEmpty());
    256     {
    257       v8::HandleScope handle_scope(v8_isolate);
    258       v8::Local<v8::Context>::New(v8_isolate, env)->Enter();
    259     }
    260     // Make sure all builtin scripts are cached.
    261     {
    262       HandleScope scope(isolate);
    263       for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
    264         isolate->bootstrapper()->SourceLookup<Natives>(i);
    265       }
    266     }
    267     heap->CollectAllGarbage();
    268     heap->CollectAllGarbage();
    269 
    270     Object* raw_foo;
    271     {
    272       v8::HandleScope handle_scope(v8_isolate);
    273       v8::Local<v8::String> foo = v8_str("foo");
    274       CHECK(!foo.IsEmpty());
    275       raw_foo = *(v8::Utils::OpenHandle(*foo));
    276     }
    277 
    278     {
    279       v8::HandleScope handle_scope(v8_isolate);
    280       v8::Local<v8::Context>::New(v8_isolate, env)->Exit();
    281     }
    282     env.Reset();
    283 
    284     StartupSerializer startup_serializer(
    285         isolate, v8::SnapshotCreator::FunctionCodeHandling::kClear);
    286     startup_serializer.SerializeStrongReferences();
    287 
    288     PartialSerializer partial_serializer(isolate, &startup_serializer);
    289     partial_serializer.Serialize(&raw_foo);
    290 
    291     startup_serializer.SerializeWeakReferencesAndDeferred();
    292 
    293     SnapshotData startup_snapshot(&startup_serializer);
    294     SnapshotData partial_snapshot(&partial_serializer);
    295 
    296     *partial_blob_out = WritePayload(partial_snapshot.RawData());
    297     *startup_blob_out = WritePayload(startup_snapshot.RawData());
    298   }
    299   v8_isolate->Exit();
    300   v8_isolate->Dispose();
    301 }
    302 
    303 UNINITIALIZED_TEST(PartialSerializerObject) {
    304   DisableTurbofan();
    305   Vector<const byte> startup_blob;
    306   Vector<const byte> partial_blob;
    307   PartiallySerializeObject(&startup_blob, &partial_blob);
    308 
    309   v8::Isolate* v8_isolate = InitializeFromBlob(startup_blob);
    310   startup_blob.Dispose();
    311   CHECK(v8_isolate);
    312   {
    313     v8::Isolate::Scope isolate_scope(v8_isolate);
    314 
    315     Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
    316     HandleScope handle_scope(isolate);
    317     Handle<Object> root;
    318     // Intentionally empty handle. The deserializer should not come across
    319     // any references to the global proxy in this test.
    320     Handle<JSGlobalProxy> global_proxy = Handle<JSGlobalProxy>::null();
    321     {
    322       SnapshotData snapshot_data(partial_blob);
    323       Deserializer deserializer(&snapshot_data);
    324       root = deserializer.DeserializePartial(isolate, global_proxy)
    325                  .ToHandleChecked();
    326       CHECK(root->IsString());
    327     }
    328 
    329     Handle<Object> root2;
    330     {
    331       SnapshotData snapshot_data(partial_blob);
    332       Deserializer deserializer(&snapshot_data);
    333       root2 = deserializer.DeserializePartial(isolate, global_proxy)
    334                   .ToHandleChecked();
    335       CHECK(root2->IsString());
    336       CHECK(root.is_identical_to(root2));
    337     }
    338     partial_blob.Dispose();
    339   }
    340   v8_isolate->Dispose();
    341 }
    342 
    343 static void PartiallySerializeContext(Vector<const byte>* startup_blob_out,
    344                                       Vector<const byte>* partial_blob_out) {
    345   v8::Isolate* v8_isolate = TestIsolate::NewInitialized(true);
    346   Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
    347   Heap* heap = isolate->heap();
    348   {
    349     v8::Isolate::Scope isolate_scope(v8_isolate);
    350 
    351     v8::Persistent<v8::Context> env;
    352     {
    353       HandleScope scope(isolate);
    354       env.Reset(v8_isolate, v8::Context::New(v8_isolate));
    355     }
    356     CHECK(!env.IsEmpty());
    357     {
    358       v8::HandleScope handle_scope(v8_isolate);
    359       v8::Local<v8::Context>::New(v8_isolate, env)->Enter();
    360     }
    361     // Make sure all builtin scripts are cached.
    362     {
    363       HandleScope scope(isolate);
    364       for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
    365         isolate->bootstrapper()->SourceLookup<Natives>(i);
    366       }
    367     }
    368     // If we don't do this then we end up with a stray root pointing at the
    369     // context even after we have disposed of env.
    370     heap->CollectAllGarbage();
    371 
    372     {
    373       v8::HandleScope handle_scope(v8_isolate);
    374       v8::Local<v8::Context>::New(v8_isolate, env)->Exit();
    375     }
    376 
    377     i::Object* raw_context = *v8::Utils::OpenPersistent(env);
    378 
    379     env.Reset();
    380 
    381     SnapshotByteSink startup_sink;
    382     StartupSerializer startup_serializer(
    383         isolate, v8::SnapshotCreator::FunctionCodeHandling::kClear);
    384     startup_serializer.SerializeStrongReferences();
    385 
    386     SnapshotByteSink partial_sink;
    387     PartialSerializer partial_serializer(isolate, &startup_serializer);
    388     partial_serializer.Serialize(&raw_context);
    389     startup_serializer.SerializeWeakReferencesAndDeferred();
    390 
    391     SnapshotData startup_snapshot(&startup_serializer);
    392     SnapshotData partial_snapshot(&partial_serializer);
    393 
    394     *partial_blob_out = WritePayload(partial_snapshot.RawData());
    395     *startup_blob_out = WritePayload(startup_snapshot.RawData());
    396   }
    397   v8_isolate->Dispose();
    398 }
    399 
    400 UNINITIALIZED_TEST(PartialSerializerContext) {
    401   DisableTurbofan();
    402   Vector<const byte> startup_blob;
    403   Vector<const byte> partial_blob;
    404   PartiallySerializeContext(&startup_blob, &partial_blob);
    405 
    406   v8::Isolate* v8_isolate = InitializeFromBlob(startup_blob);
    407   CHECK(v8_isolate);
    408   startup_blob.Dispose();
    409   {
    410     v8::Isolate::Scope isolate_scope(v8_isolate);
    411 
    412     Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
    413     HandleScope handle_scope(isolate);
    414     Handle<Object> root;
    415     Handle<JSGlobalProxy> global_proxy =
    416         isolate->factory()->NewUninitializedJSGlobalProxy();
    417     {
    418       SnapshotData snapshot_data(partial_blob);
    419       Deserializer deserializer(&snapshot_data);
    420       root = deserializer.DeserializePartial(isolate, global_proxy)
    421                  .ToHandleChecked();
    422       CHECK(root->IsContext());
    423       CHECK(Handle<Context>::cast(root)->global_proxy() == *global_proxy);
    424     }
    425 
    426     Handle<Object> root2;
    427     {
    428       SnapshotData snapshot_data(partial_blob);
    429       Deserializer deserializer(&snapshot_data);
    430       root2 = deserializer.DeserializePartial(isolate, global_proxy)
    431                   .ToHandleChecked();
    432       CHECK(root2->IsContext());
    433       CHECK(!root.is_identical_to(root2));
    434     }
    435     partial_blob.Dispose();
    436   }
    437   v8_isolate->Dispose();
    438 }
    439 
    440 static void PartiallySerializeCustomContext(
    441     Vector<const byte>* startup_blob_out,
    442     Vector<const byte>* partial_blob_out) {
    443   v8::Isolate* v8_isolate = TestIsolate::NewInitialized(true);
    444   Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
    445   {
    446     v8::Isolate::Scope isolate_scope(v8_isolate);
    447 
    448     v8::Persistent<v8::Context> env;
    449     {
    450       HandleScope scope(isolate);
    451       env.Reset(v8_isolate, v8::Context::New(v8_isolate));
    452     }
    453     CHECK(!env.IsEmpty());
    454     {
    455       v8::HandleScope handle_scope(v8_isolate);
    456       v8::Local<v8::Context>::New(v8_isolate, env)->Enter();
    457       // After execution, e's function context refers to the global object.
    458       CompileRun(
    459           "var e;"
    460           "(function() {"
    461           "  e = function(s) { return eval (s); }"
    462           "})();"
    463           "var o = this;"
    464           "var r = Math.random();"
    465           "var c = Math.sin(0) + Math.cos(0);"
    466           "var f = (function(a, b) { return a + b; }).bind(1, 2, 3);"
    467           "var s = parseInt('12345');");
    468 
    469       Vector<const uint8_t> source = ConstructSource(
    470           STATIC_CHAR_VECTOR("function g() { return [,"),
    471           STATIC_CHAR_VECTOR("1,"),
    472           STATIC_CHAR_VECTOR("];} a = g(); b = g(); b.push(1);"), 100000);
    473       v8::MaybeLocal<v8::String> source_str = v8::String::NewFromOneByte(
    474           v8_isolate, source.start(), v8::NewStringType::kNormal,
    475           source.length());
    476       CompileRun(source_str.ToLocalChecked());
    477       source.Dispose();
    478     }
    479     // Make sure all builtin scripts are cached.
    480     {
    481       HandleScope scope(isolate);
    482       for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
    483         isolate->bootstrapper()->SourceLookup<Natives>(i);
    484       }
    485     }
    486     // If we don't do this then we end up with a stray root pointing at the
    487     // context even after we have disposed of env.
    488     isolate->heap()->CollectAllAvailableGarbage("snapshotting");
    489 
    490     {
    491       v8::HandleScope handle_scope(v8_isolate);
    492       v8::Local<v8::Context>::New(v8_isolate, env)->Exit();
    493     }
    494 
    495     i::Object* raw_context = *v8::Utils::OpenPersistent(env);
    496 
    497     env.Reset();
    498 
    499     SnapshotByteSink startup_sink;
    500     StartupSerializer startup_serializer(
    501         isolate, v8::SnapshotCreator::FunctionCodeHandling::kClear);
    502     startup_serializer.SerializeStrongReferences();
    503 
    504     SnapshotByteSink partial_sink;
    505     PartialSerializer partial_serializer(isolate, &startup_serializer);
    506     partial_serializer.Serialize(&raw_context);
    507     startup_serializer.SerializeWeakReferencesAndDeferred();
    508 
    509     SnapshotData startup_snapshot(&startup_serializer);
    510     SnapshotData partial_snapshot(&partial_serializer);
    511 
    512     *partial_blob_out = WritePayload(partial_snapshot.RawData());
    513     *startup_blob_out = WritePayload(startup_snapshot.RawData());
    514   }
    515   v8_isolate->Dispose();
    516 }
    517 
    518 UNINITIALIZED_TEST(PartialSerializerCustomContext) {
    519   DisableTurbofan();
    520   Vector<const byte> startup_blob;
    521   Vector<const byte> partial_blob;
    522   PartiallySerializeCustomContext(&startup_blob, &partial_blob);
    523 
    524   v8::Isolate* v8_isolate = InitializeFromBlob(startup_blob);
    525   CHECK(v8_isolate);
    526   startup_blob.Dispose();
    527   {
    528     v8::Isolate::Scope isolate_scope(v8_isolate);
    529 
    530     Isolate* isolate = reinterpret_cast<Isolate*>(v8_isolate);
    531     HandleScope handle_scope(isolate);
    532     Handle<Object> root;
    533     Handle<JSGlobalProxy> global_proxy =
    534         isolate->factory()->NewUninitializedJSGlobalProxy();
    535     {
    536       SnapshotData snapshot_data(partial_blob);
    537       Deserializer deserializer(&snapshot_data);
    538       root = deserializer.DeserializePartial(isolate, global_proxy)
    539                  .ToHandleChecked();
    540       CHECK(root->IsContext());
    541       Handle<Context> context = Handle<Context>::cast(root);
    542 
    543       // Add context to the weak native context list
    544       context->set(Context::NEXT_CONTEXT_LINK,
    545                    isolate->heap()->native_contexts_list(),
    546                    UPDATE_WEAK_WRITE_BARRIER);
    547       isolate->heap()->set_native_contexts_list(*context);
    548 
    549       CHECK(context->global_proxy() == *global_proxy);
    550       Handle<String> o = isolate->factory()->NewStringFromAsciiChecked("o");
    551       Handle<JSObject> global_object(context->global_object(), isolate);
    552       Handle<Object> property = JSReceiver::GetDataProperty(global_object, o);
    553       CHECK(property.is_identical_to(global_proxy));
    554 
    555       v8::Local<v8::Context> v8_context = v8::Utils::ToLocal(context);
    556       v8::Context::Scope context_scope(v8_context);
    557       double r = CompileRun("r")
    558                      ->ToNumber(v8_isolate->GetCurrentContext())
    559                      .ToLocalChecked()
    560                      ->Value();
    561       CHECK(0.0 <= r && r < 1.0);
    562       // Math.random still works.
    563       double random = CompileRun("Math.random()")
    564                           ->ToNumber(v8_isolate->GetCurrentContext())
    565                           .ToLocalChecked()
    566                           ->Value();
    567       CHECK(0.0 <= random && random < 1.0);
    568       double c = CompileRun("c")
    569                      ->ToNumber(v8_isolate->GetCurrentContext())
    570                      .ToLocalChecked()
    571                      ->Value();
    572       CHECK_EQ(1, c);
    573       int f = CompileRun("f()")
    574                   ->ToNumber(v8_isolate->GetCurrentContext())
    575                   .ToLocalChecked()
    576                   ->Int32Value(v8_isolate->GetCurrentContext())
    577                   .FromJust();
    578       CHECK_EQ(5, f);
    579       f = CompileRun("e('f()')")
    580               ->ToNumber(v8_isolate->GetCurrentContext())
    581               .ToLocalChecked()
    582               ->Int32Value(v8_isolate->GetCurrentContext())
    583               .FromJust();
    584       CHECK_EQ(5, f);
    585       v8::Local<v8::String> s = CompileRun("s")
    586                                     ->ToString(v8_isolate->GetCurrentContext())
    587                                     .ToLocalChecked();
    588       CHECK(s->Equals(v8_isolate->GetCurrentContext(), v8_str("12345"))
    589                 .FromJust());
    590       int a = CompileRun("a.length")
    591                   ->ToNumber(v8_isolate->GetCurrentContext())
    592                   .ToLocalChecked()
    593                   ->Int32Value(v8_isolate->GetCurrentContext())
    594                   .FromJust();
    595       CHECK_EQ(100001, a);
    596       int b = CompileRun("b.length")
    597                   ->ToNumber(v8_isolate->GetCurrentContext())
    598                   .ToLocalChecked()
    599                   ->Int32Value(v8_isolate->GetCurrentContext())
    600                   .FromJust();
    601       CHECK_EQ(100002, b);
    602     }
    603     partial_blob.Dispose();
    604   }
    605   v8_isolate->Dispose();
    606 }
    607 
    608 TEST(CustomSnapshotDataBlob) {
    609   DisableTurbofan();
    610   const char* source1 = "function f() { return 42; }";
    611   const char* source2 =
    612       "function f() { return g() * 2; }"
    613       "function g() { return 43; }"
    614       "/./.test('a')";
    615 
    616   v8::StartupData data1 = v8::V8::CreateSnapshotDataBlob(source1);
    617   v8::StartupData data2 = v8::V8::CreateSnapshotDataBlob(source2);
    618 
    619   v8::Isolate::CreateParams params1;
    620   params1.snapshot_blob = &data1;
    621   params1.array_buffer_allocator = CcTest::array_buffer_allocator();
    622 
    623   v8::Isolate* isolate1 = v8::Isolate::New(params1);
    624   {
    625     v8::Isolate::Scope i_scope(isolate1);
    626     v8::HandleScope h_scope(isolate1);
    627     v8::Local<v8::Context> context = v8::Context::New(isolate1);
    628     delete[] data1.data;  // We can dispose of the snapshot blob now.
    629     v8::Context::Scope c_scope(context);
    630     v8::Maybe<int32_t> result =
    631         CompileRun("f()")->Int32Value(isolate1->GetCurrentContext());
    632     CHECK_EQ(42, result.FromJust());
    633     CHECK(CompileRun("this.g")->IsUndefined());
    634   }
    635   isolate1->Dispose();
    636 
    637   v8::Isolate::CreateParams params2;
    638   params2.snapshot_blob = &data2;
    639   params2.array_buffer_allocator = CcTest::array_buffer_allocator();
    640   v8::Isolate* isolate2 = v8::Isolate::New(params2);
    641   {
    642     v8::Isolate::Scope i_scope(isolate2);
    643     v8::HandleScope h_scope(isolate2);
    644     v8::Local<v8::Context> context = v8::Context::New(isolate2);
    645     delete[] data2.data;  // We can dispose of the snapshot blob now.
    646     v8::Context::Scope c_scope(context);
    647     v8::Maybe<int32_t> result =
    648         CompileRun("f()")->Int32Value(isolate2->GetCurrentContext());
    649     CHECK_EQ(86, result.FromJust());
    650     result = CompileRun("g()")->Int32Value(isolate2->GetCurrentContext());
    651     CHECK_EQ(43, result.FromJust());
    652   }
    653   isolate2->Dispose();
    654 }
    655 
    656 
    657 static void SerializationFunctionTemplate(
    658     const v8::FunctionCallbackInfo<v8::Value>& args) {
    659   args.GetReturnValue().Set(args[0]);
    660 }
    661 
    662 TEST(CustomSnapshotDataBlobOutdatedContextWithOverflow) {
    663   DisableTurbofan();
    664 
    665   const char* source1 =
    666       "var o = {};"
    667       "(function() {"
    668       "  function f1(x) { return f2(x) instanceof Array; }"
    669       "  function f2(x) { return foo.bar(x); }"
    670       "  o.a = f2.bind(null);"
    671       "  o.b = 1;"
    672       "  o.c = 2;"
    673       "  o.d = 3;"
    674       "  o.e = 4;"
    675       "})();\n";
    676 
    677   const char* source2 = "o.a(42)";
    678 
    679   v8::StartupData data = v8::V8::CreateSnapshotDataBlob(source1);
    680 
    681   v8::Isolate::CreateParams params;
    682   params.snapshot_blob = &data;
    683   params.array_buffer_allocator = CcTest::array_buffer_allocator();
    684 
    685   v8::Isolate* isolate = v8::Isolate::New(params);
    686   {
    687     v8::Isolate::Scope i_scope(isolate);
    688     v8::HandleScope h_scope(isolate);
    689 
    690     v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);
    691     v8::Local<v8::ObjectTemplate> property = v8::ObjectTemplate::New(isolate);
    692     v8::Local<v8::FunctionTemplate> function =
    693         v8::FunctionTemplate::New(isolate, SerializationFunctionTemplate);
    694     property->Set(isolate, "bar", function);
    695     global->Set(isolate, "foo", property);
    696 
    697     v8::Local<v8::Context> context = v8::Context::New(isolate, NULL, global);
    698     delete[] data.data;  // We can dispose of the snapshot blob now.
    699     v8::Context::Scope c_scope(context);
    700     v8::Local<v8::Value> result = CompileRun(source2);
    701     v8::Maybe<bool> compare = v8_str("42")->Equals(
    702         v8::Isolate::GetCurrent()->GetCurrentContext(), result);
    703     CHECK(compare.FromJust());
    704   }
    705   isolate->Dispose();
    706 }
    707 
    708 TEST(CustomSnapshotDataBlobWithLocker) {
    709   DisableTurbofan();
    710   v8::Isolate::CreateParams create_params;
    711   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
    712   v8::Isolate* isolate0 = v8::Isolate::New(create_params);
    713   {
    714     v8::Locker locker(isolate0);
    715     v8::Isolate::Scope i_scope(isolate0);
    716     v8::HandleScope h_scope(isolate0);
    717     v8::Local<v8::Context> context = v8::Context::New(isolate0);
    718     v8::Context::Scope c_scope(context);
    719     v8::Maybe<int32_t> result =
    720         CompileRun("Math.cos(0)")->Int32Value(isolate0->GetCurrentContext());
    721     CHECK_EQ(1, result.FromJust());
    722   }
    723   isolate0->Dispose();
    724 
    725   const char* source1 = "function f() { return 42; }";
    726 
    727   v8::StartupData data1 = v8::V8::CreateSnapshotDataBlob(source1);
    728 
    729   v8::Isolate::CreateParams params1;
    730   params1.snapshot_blob = &data1;
    731   params1.array_buffer_allocator = CcTest::array_buffer_allocator();
    732   v8::Isolate* isolate1 = v8::Isolate::New(params1);
    733   {
    734     v8::Locker locker(isolate1);
    735     v8::Isolate::Scope i_scope(isolate1);
    736     v8::HandleScope h_scope(isolate1);
    737     v8::Local<v8::Context> context = v8::Context::New(isolate1);
    738     delete[] data1.data;  // We can dispose of the snapshot blob now.
    739     v8::Context::Scope c_scope(context);
    740     v8::Maybe<int32_t> result = CompileRun("f()")->Int32Value(context);
    741     CHECK_EQ(42, result.FromJust());
    742   }
    743   isolate1->Dispose();
    744 }
    745 
    746 TEST(CustomSnapshotDataBlobStackOverflow) {
    747   DisableTurbofan();
    748   const char* source =
    749       "var a = [0];"
    750       "var b = a;"
    751       "for (var i = 0; i < 10000; i++) {"
    752       "  var c = [i];"
    753       "  b.push(c);"
    754       "  b.push(c);"
    755       "  b = c;"
    756       "}";
    757 
    758   v8::StartupData data = v8::V8::CreateSnapshotDataBlob(source);
    759 
    760   v8::Isolate::CreateParams params;
    761   params.snapshot_blob = &data;
    762   params.array_buffer_allocator = CcTest::array_buffer_allocator();
    763 
    764   v8::Isolate* isolate = v8::Isolate::New(params);
    765   {
    766     v8::Isolate::Scope i_scope(isolate);
    767     v8::HandleScope h_scope(isolate);
    768     v8::Local<v8::Context> context = v8::Context::New(isolate);
    769     delete[] data.data;  // We can dispose of the snapshot blob now.
    770     v8::Context::Scope c_scope(context);
    771     const char* test =
    772         "var sum = 0;"
    773         "while (a) {"
    774         "  sum += a[0];"
    775         "  a = a[1];"
    776         "}"
    777         "sum";
    778     v8::Maybe<int32_t> result =
    779         CompileRun(test)->Int32Value(isolate->GetCurrentContext());
    780     CHECK_EQ(9999 * 5000, result.FromJust());
    781   }
    782   isolate->Dispose();
    783 }
    784 
    785 bool IsCompiled(const char* name) {
    786   return i::Handle<i::JSFunction>::cast(
    787              v8::Utils::OpenHandle(*CompileRun(name)))
    788       ->shared()
    789       ->is_compiled();
    790 }
    791 
    792 TEST(SnapshotDataBlobWithWarmup) {
    793   DisableTurbofan();
    794   const char* warmup = "Math.tanh(1); Math.sinh = 1;";
    795 
    796   v8::StartupData cold = v8::V8::CreateSnapshotDataBlob();
    797   v8::StartupData warm = v8::V8::WarmUpSnapshotDataBlob(cold, warmup);
    798   delete[] cold.data;
    799 
    800   v8::Isolate::CreateParams params;
    801   params.snapshot_blob = &warm;
    802   params.array_buffer_allocator = CcTest::array_buffer_allocator();
    803 
    804   v8::Isolate* isolate = v8::Isolate::New(params);
    805   {
    806     v8::Isolate::Scope i_scope(isolate);
    807     v8::HandleScope h_scope(isolate);
    808     v8::Local<v8::Context> context = v8::Context::New(isolate);
    809     delete[] warm.data;
    810     v8::Context::Scope c_scope(context);
    811     // Running the warmup script has effect on whether functions are
    812     // pre-compiled, but does not pollute the context.
    813     CHECK(IsCompiled("Math.tanh"));
    814     CHECK(!IsCompiled("Math.cosh"));
    815     CHECK(CompileRun("Math.sinh")->IsFunction());
    816   }
    817   isolate->Dispose();
    818 }
    819 
    820 TEST(CustomSnapshotDataBlobWithWarmup) {
    821   DisableTurbofan();
    822   const char* source =
    823       "function f() { return Math.sinh(1); }\n"
    824       "function g() { return Math.cosh(1); }\n"
    825       "Math.tanh(1);"
    826       "var a = 5";
    827   const char* warmup = "a = f()";
    828 
    829   v8::StartupData cold = v8::V8::CreateSnapshotDataBlob(source);
    830   v8::StartupData warm = v8::V8::WarmUpSnapshotDataBlob(cold, warmup);
    831   delete[] cold.data;
    832 
    833   v8::Isolate::CreateParams params;
    834   params.snapshot_blob = &warm;
    835   params.array_buffer_allocator = CcTest::array_buffer_allocator();
    836 
    837   v8::Isolate* isolate = v8::Isolate::New(params);
    838   {
    839     v8::Isolate::Scope i_scope(isolate);
    840     v8::HandleScope h_scope(isolate);
    841     v8::Local<v8::Context> context = v8::Context::New(isolate);
    842     delete[] warm.data;
    843     v8::Context::Scope c_scope(context);
    844     // Running the warmup script has effect on whether functions are
    845     // pre-compiled, but does not pollute the context.
    846     CHECK(IsCompiled("f"));
    847     CHECK(IsCompiled("Math.sinh"));
    848     CHECK(!IsCompiled("g"));
    849     CHECK(!IsCompiled("Math.cosh"));
    850     CHECK(!IsCompiled("Math.tanh"));
    851     CHECK_EQ(5, CompileRun("a")->Int32Value(context).FromJust());
    852   }
    853   isolate->Dispose();
    854 }
    855 
    856 TEST(CustomSnapshotDataBlobImmortalImmovableRoots) {
    857   DisableTurbofan();
    858   // Flood the startup snapshot with shared function infos. If they are
    859   // serialized before the immortal immovable root, the root will no longer end
    860   // up on the first page.
    861   Vector<const uint8_t> source =
    862       ConstructSource(STATIC_CHAR_VECTOR("var a = [];"),
    863                       STATIC_CHAR_VECTOR("a.push(function() {return 7});"),
    864                       STATIC_CHAR_VECTOR("\0"), 10000);
    865 
    866   v8::StartupData data = v8::V8::CreateSnapshotDataBlob(
    867       reinterpret_cast<const char*>(source.start()));
    868 
    869   v8::Isolate::CreateParams params;
    870   params.snapshot_blob = &data;
    871   params.array_buffer_allocator = CcTest::array_buffer_allocator();
    872 
    873   v8::Isolate* isolate = v8::Isolate::New(params);
    874   {
    875     v8::Isolate::Scope i_scope(isolate);
    876     v8::HandleScope h_scope(isolate);
    877     v8::Local<v8::Context> context = v8::Context::New(isolate);
    878     delete[] data.data;  // We can dispose of the snapshot blob now.
    879     v8::Context::Scope c_scope(context);
    880     CHECK_EQ(7, CompileRun("a[0]()")->Int32Value(context).FromJust());
    881   }
    882   isolate->Dispose();
    883   source.Dispose();
    884 }
    885 
    886 TEST(TestThatAlwaysSucceeds) {
    887 }
    888 
    889 
    890 TEST(TestThatAlwaysFails) {
    891   bool ArtificialFailure = false;
    892   CHECK(ArtificialFailure);
    893 }
    894 
    895 
    896 int CountBuiltins() {
    897   // Check that we have not deserialized any additional builtin.
    898   HeapIterator iterator(CcTest::heap());
    899   DisallowHeapAllocation no_allocation;
    900   int counter = 0;
    901   for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
    902     if (obj->IsCode() && Code::cast(obj)->kind() == Code::BUILTIN) counter++;
    903   }
    904   return counter;
    905 }
    906 
    907 
    908 static Handle<SharedFunctionInfo> CompileScript(
    909     Isolate* isolate, Handle<String> source, Handle<String> name,
    910     ScriptData** cached_data, v8::ScriptCompiler::CompileOptions options) {
    911   return Compiler::GetSharedFunctionInfoForScript(
    912       source, name, 0, 0, v8::ScriptOriginOptions(), Handle<Object>(),
    913       Handle<Context>(isolate->native_context()), NULL, cached_data, options,
    914       NOT_NATIVES_CODE, false);
    915 }
    916 
    917 TEST(CodeSerializerOnePlusOne) {
    918   FLAG_serialize_toplevel = true;
    919   LocalContext context;
    920   Isolate* isolate = CcTest::i_isolate();
    921   isolate->compilation_cache()->Disable();  // Disable same-isolate code cache.
    922 
    923   v8::HandleScope scope(CcTest::isolate());
    924 
    925   const char* source = "1 + 1";
    926 
    927   Handle<String> orig_source = isolate->factory()
    928                                    ->NewStringFromUtf8(CStrVector(source))
    929                                    .ToHandleChecked();
    930   Handle<String> copy_source = isolate->factory()
    931                                    ->NewStringFromUtf8(CStrVector(source))
    932                                    .ToHandleChecked();
    933   CHECK(!orig_source.is_identical_to(copy_source));
    934   CHECK(orig_source->Equals(*copy_source));
    935 
    936   ScriptData* cache = NULL;
    937 
    938   Handle<SharedFunctionInfo> orig =
    939       CompileScript(isolate, orig_source, Handle<String>(), &cache,
    940                     v8::ScriptCompiler::kProduceCodeCache);
    941 
    942   int builtins_count = CountBuiltins();
    943 
    944   Handle<SharedFunctionInfo> copy;
    945   {
    946     DisallowCompilation no_compile_expected(isolate);
    947     copy = CompileScript(isolate, copy_source, Handle<String>(), &cache,
    948                          v8::ScriptCompiler::kConsumeCodeCache);
    949   }
    950 
    951   CHECK_NE(*orig, *copy);
    952   CHECK(Script::cast(copy->script())->source() == *copy_source);
    953 
    954   Handle<JSFunction> copy_fun =
    955       isolate->factory()->NewFunctionFromSharedFunctionInfo(
    956           copy, isolate->native_context());
    957   Handle<JSObject> global(isolate->context()->global_object());
    958   Handle<Object> copy_result =
    959       Execution::Call(isolate, copy_fun, global, 0, NULL).ToHandleChecked();
    960   CHECK_EQ(2, Handle<Smi>::cast(copy_result)->value());
    961 
    962   CHECK_EQ(builtins_count, CountBuiltins());
    963 
    964   delete cache;
    965 }
    966 
    967 TEST(CodeSerializerPromotedToCompilationCache) {
    968   FLAG_serialize_toplevel = true;
    969   LocalContext context;
    970   Isolate* isolate = CcTest::i_isolate();
    971 
    972   v8::HandleScope scope(CcTest::isolate());
    973 
    974   const char* source = "1 + 1";
    975 
    976   Handle<String> src = isolate->factory()
    977                            ->NewStringFromUtf8(CStrVector(source))
    978                            .ToHandleChecked();
    979   ScriptData* cache = NULL;
    980 
    981   CompileScript(isolate, src, src, &cache,
    982                 v8::ScriptCompiler::kProduceCodeCache);
    983 
    984   DisallowCompilation no_compile_expected(isolate);
    985   Handle<SharedFunctionInfo> copy = CompileScript(
    986       isolate, src, src, &cache, v8::ScriptCompiler::kConsumeCodeCache);
    987 
    988   CHECK(isolate->compilation_cache()
    989             ->LookupScript(src, src, 0, 0, v8::ScriptOriginOptions(),
    990                            isolate->native_context(), SLOPPY)
    991             .ToHandleChecked()
    992             .is_identical_to(copy));
    993 
    994   delete cache;
    995 }
    996 
    997 TEST(CodeSerializerInternalizedString) {
    998   FLAG_serialize_toplevel = true;
    999   LocalContext context;
   1000   Isolate* isolate = CcTest::i_isolate();
   1001   isolate->compilation_cache()->Disable();  // Disable same-isolate code cache.
   1002 
   1003   v8::HandleScope scope(CcTest::isolate());
   1004 
   1005   const char* source = "'string1'";
   1006 
   1007   Handle<String> orig_source = isolate->factory()
   1008                                    ->NewStringFromUtf8(CStrVector(source))
   1009                                    .ToHandleChecked();
   1010   Handle<String> copy_source = isolate->factory()
   1011                                    ->NewStringFromUtf8(CStrVector(source))
   1012                                    .ToHandleChecked();
   1013   CHECK(!orig_source.is_identical_to(copy_source));
   1014   CHECK(orig_source->Equals(*copy_source));
   1015 
   1016   Handle<JSObject> global(isolate->context()->global_object());
   1017   ScriptData* cache = NULL;
   1018 
   1019   Handle<SharedFunctionInfo> orig =
   1020       CompileScript(isolate, orig_source, Handle<String>(), &cache,
   1021                     v8::ScriptCompiler::kProduceCodeCache);
   1022   Handle<JSFunction> orig_fun =
   1023       isolate->factory()->NewFunctionFromSharedFunctionInfo(
   1024           orig, isolate->native_context());
   1025   Handle<Object> orig_result =
   1026       Execution::Call(isolate, orig_fun, global, 0, NULL).ToHandleChecked();
   1027   CHECK(orig_result->IsInternalizedString());
   1028 
   1029   int builtins_count = CountBuiltins();
   1030 
   1031   Handle<SharedFunctionInfo> copy;
   1032   {
   1033     DisallowCompilation no_compile_expected(isolate);
   1034     copy = CompileScript(isolate, copy_source, Handle<String>(), &cache,
   1035                          v8::ScriptCompiler::kConsumeCodeCache);
   1036   }
   1037   CHECK_NE(*orig, *copy);
   1038   CHECK(Script::cast(copy->script())->source() == *copy_source);
   1039 
   1040   Handle<JSFunction> copy_fun =
   1041       isolate->factory()->NewFunctionFromSharedFunctionInfo(
   1042           copy, isolate->native_context());
   1043   CHECK_NE(*orig_fun, *copy_fun);
   1044   Handle<Object> copy_result =
   1045       Execution::Call(isolate, copy_fun, global, 0, NULL).ToHandleChecked();
   1046   CHECK(orig_result.is_identical_to(copy_result));
   1047   Handle<String> expected =
   1048       isolate->factory()->NewStringFromAsciiChecked("string1");
   1049 
   1050   CHECK(Handle<String>::cast(copy_result)->Equals(*expected));
   1051   CHECK_EQ(builtins_count, CountBuiltins());
   1052 
   1053   delete cache;
   1054 }
   1055 
   1056 TEST(CodeSerializerLargeCodeObject) {
   1057   FLAG_serialize_toplevel = true;
   1058   LocalContext context;
   1059   Isolate* isolate = CcTest::i_isolate();
   1060   isolate->compilation_cache()->Disable();  // Disable same-isolate code cache.
   1061 
   1062   v8::HandleScope scope(CcTest::isolate());
   1063 
   1064   Vector<const uint8_t> source =
   1065       ConstructSource(STATIC_CHAR_VECTOR("var j=1; try { if (j) throw 1;"),
   1066                       STATIC_CHAR_VECTOR("for(var i=0;i<1;i++)j++;"),
   1067                       STATIC_CHAR_VECTOR("} catch (e) { j=7; } j"), 10000);
   1068   Handle<String> source_str =
   1069       isolate->factory()->NewStringFromOneByte(source).ToHandleChecked();
   1070 
   1071   Handle<JSObject> global(isolate->context()->global_object());
   1072   ScriptData* cache = NULL;
   1073 
   1074   Handle<SharedFunctionInfo> orig =
   1075       CompileScript(isolate, source_str, Handle<String>(), &cache,
   1076                     v8::ScriptCompiler::kProduceCodeCache);
   1077 
   1078   CHECK(isolate->heap()->InSpace(orig->code(), LO_SPACE));
   1079 
   1080   Handle<SharedFunctionInfo> copy;
   1081   {
   1082     DisallowCompilation no_compile_expected(isolate);
   1083     copy = CompileScript(isolate, source_str, Handle<String>(), &cache,
   1084                          v8::ScriptCompiler::kConsumeCodeCache);
   1085   }
   1086   CHECK_NE(*orig, *copy);
   1087 
   1088   Handle<JSFunction> copy_fun =
   1089       isolate->factory()->NewFunctionFromSharedFunctionInfo(
   1090           copy, isolate->native_context());
   1091 
   1092   Handle<Object> copy_result =
   1093       Execution::Call(isolate, copy_fun, global, 0, NULL).ToHandleChecked();
   1094 
   1095   int result_int;
   1096   CHECK(copy_result->ToInt32(&result_int));
   1097   CHECK_EQ(7, result_int);
   1098 
   1099   delete cache;
   1100   source.Dispose();
   1101 }
   1102 
   1103 TEST(CodeSerializerLargeStrings) {
   1104   FLAG_serialize_toplevel = true;
   1105   LocalContext context;
   1106   Isolate* isolate = CcTest::i_isolate();
   1107   Factory* f = isolate->factory();
   1108   isolate->compilation_cache()->Disable();  // Disable same-isolate code cache.
   1109 
   1110   v8::HandleScope scope(CcTest::isolate());
   1111 
   1112   Vector<const uint8_t> source_s = ConstructSource(
   1113       STATIC_CHAR_VECTOR("var s = \""), STATIC_CHAR_VECTOR("abcdef"),
   1114       STATIC_CHAR_VECTOR("\";"), 1000000);
   1115   Vector<const uint8_t> source_t = ConstructSource(
   1116       STATIC_CHAR_VECTOR("var t = \""), STATIC_CHAR_VECTOR("uvwxyz"),
   1117       STATIC_CHAR_VECTOR("\"; s + t"), 999999);
   1118   Handle<String> source_str =
   1119       f->NewConsString(f->NewStringFromOneByte(source_s).ToHandleChecked(),
   1120                        f->NewStringFromOneByte(source_t).ToHandleChecked())
   1121           .ToHandleChecked();
   1122 
   1123   Handle<JSObject> global(isolate->context()->global_object());
   1124   ScriptData* cache = NULL;
   1125 
   1126   Handle<SharedFunctionInfo> orig =
   1127       CompileScript(isolate, source_str, Handle<String>(), &cache,
   1128                     v8::ScriptCompiler::kProduceCodeCache);
   1129 
   1130   Handle<SharedFunctionInfo> copy;
   1131   {
   1132     DisallowCompilation no_compile_expected(isolate);
   1133     copy = CompileScript(isolate, source_str, Handle<String>(), &cache,
   1134                          v8::ScriptCompiler::kConsumeCodeCache);
   1135   }
   1136   CHECK_NE(*orig, *copy);
   1137 
   1138   Handle<JSFunction> copy_fun =
   1139       isolate->factory()->NewFunctionFromSharedFunctionInfo(
   1140           copy, isolate->native_context());
   1141 
   1142   Handle<Object> copy_result =
   1143       Execution::Call(isolate, copy_fun, global, 0, NULL).ToHandleChecked();
   1144 
   1145   CHECK_EQ(6 * 1999999, Handle<String>::cast(copy_result)->length());
   1146   Handle<Object> property = JSReceiver::GetDataProperty(
   1147       isolate->global_object(), f->NewStringFromAsciiChecked("s"));
   1148   CHECK(isolate->heap()->InSpace(HeapObject::cast(*property), LO_SPACE));
   1149   property = JSReceiver::GetDataProperty(isolate->global_object(),
   1150                                          f->NewStringFromAsciiChecked("t"));
   1151   CHECK(isolate->heap()->InSpace(HeapObject::cast(*property), LO_SPACE));
   1152   // Make sure we do not serialize too much, e.g. include the source string.
   1153   CHECK_LT(cache->length(), 13000000);
   1154 
   1155   delete cache;
   1156   source_s.Dispose();
   1157   source_t.Dispose();
   1158 }
   1159 
   1160 TEST(CodeSerializerThreeBigStrings) {
   1161   FLAG_serialize_toplevel = true;
   1162   LocalContext context;
   1163   Isolate* isolate = CcTest::i_isolate();
   1164   Factory* f = isolate->factory();
   1165   isolate->compilation_cache()->Disable();  // Disable same-isolate code cache.
   1166 
   1167   v8::HandleScope scope(CcTest::isolate());
   1168 
   1169   Vector<const uint8_t> source_a =
   1170       ConstructSource(STATIC_CHAR_VECTOR("var a = \""), STATIC_CHAR_VECTOR("a"),
   1171                       STATIC_CHAR_VECTOR("\";"), 700000);
   1172   Handle<String> source_a_str =
   1173       f->NewStringFromOneByte(source_a).ToHandleChecked();
   1174 
   1175   Vector<const uint8_t> source_b =
   1176       ConstructSource(STATIC_CHAR_VECTOR("var b = \""), STATIC_CHAR_VECTOR("b"),
   1177                       STATIC_CHAR_VECTOR("\";"), 600000);
   1178   Handle<String> source_b_str =
   1179       f->NewStringFromOneByte(source_b).ToHandleChecked();
   1180 
   1181   Vector<const uint8_t> source_c =
   1182       ConstructSource(STATIC_CHAR_VECTOR("var c = \""), STATIC_CHAR_VECTOR("c"),
   1183                       STATIC_CHAR_VECTOR("\";"), 500000);
   1184   Handle<String> source_c_str =
   1185       f->NewStringFromOneByte(source_c).ToHandleChecked();
   1186 
   1187   Handle<String> source_str =
   1188       f->NewConsString(
   1189              f->NewConsString(source_a_str, source_b_str).ToHandleChecked(),
   1190              source_c_str).ToHandleChecked();
   1191 
   1192   Handle<JSObject> global(isolate->context()->global_object());
   1193   ScriptData* cache = NULL;
   1194 
   1195   Handle<SharedFunctionInfo> orig =
   1196       CompileScript(isolate, source_str, Handle<String>(), &cache,
   1197                     v8::ScriptCompiler::kProduceCodeCache);
   1198 
   1199   Handle<SharedFunctionInfo> copy;
   1200   {
   1201     DisallowCompilation no_compile_expected(isolate);
   1202     copy = CompileScript(isolate, source_str, Handle<String>(), &cache,
   1203                          v8::ScriptCompiler::kConsumeCodeCache);
   1204   }
   1205   CHECK_NE(*orig, *copy);
   1206 
   1207   Handle<JSFunction> copy_fun =
   1208       isolate->factory()->NewFunctionFromSharedFunctionInfo(
   1209           copy, isolate->native_context());
   1210 
   1211   USE(Execution::Call(isolate, copy_fun, global, 0, NULL));
   1212 
   1213   v8::Maybe<int32_t> result =
   1214       CompileRun("(a + b).length")
   1215           ->Int32Value(v8::Isolate::GetCurrent()->GetCurrentContext());
   1216   CHECK_EQ(600000 + 700000, result.FromJust());
   1217   result = CompileRun("(b + c).length")
   1218                ->Int32Value(v8::Isolate::GetCurrent()->GetCurrentContext());
   1219   CHECK_EQ(500000 + 600000, result.FromJust());
   1220   Heap* heap = isolate->heap();
   1221   v8::Local<v8::String> result_str =
   1222       CompileRun("a")
   1223           ->ToString(CcTest::isolate()->GetCurrentContext())
   1224           .ToLocalChecked();
   1225   CHECK(heap->InSpace(*v8::Utils::OpenHandle(*result_str), LO_SPACE));
   1226   result_str = CompileRun("b")
   1227                    ->ToString(CcTest::isolate()->GetCurrentContext())
   1228                    .ToLocalChecked();
   1229   CHECK(heap->InSpace(*v8::Utils::OpenHandle(*result_str), OLD_SPACE));
   1230   result_str = CompileRun("c")
   1231                    ->ToString(CcTest::isolate()->GetCurrentContext())
   1232                    .ToLocalChecked();
   1233   CHECK(heap->InSpace(*v8::Utils::OpenHandle(*result_str), OLD_SPACE));
   1234 
   1235   delete cache;
   1236   source_a.Dispose();
   1237   source_b.Dispose();
   1238   source_c.Dispose();
   1239 }
   1240 
   1241 
   1242 class SerializerOneByteResource
   1243     : public v8::String::ExternalOneByteStringResource {
   1244  public:
   1245   SerializerOneByteResource(const char* data, size_t length)
   1246       : data_(data), length_(length) {}
   1247   virtual const char* data() const { return data_; }
   1248   virtual size_t length() const { return length_; }
   1249 
   1250  private:
   1251   const char* data_;
   1252   size_t length_;
   1253 };
   1254 
   1255 
   1256 class SerializerTwoByteResource : public v8::String::ExternalStringResource {
   1257  public:
   1258   SerializerTwoByteResource(const char* data, size_t length)
   1259       : data_(AsciiToTwoByteString(data)), length_(length) {}
   1260   ~SerializerTwoByteResource() { DeleteArray<const uint16_t>(data_); }
   1261 
   1262   virtual const uint16_t* data() const { return data_; }
   1263   virtual size_t length() const { return length_; }
   1264 
   1265  private:
   1266   const uint16_t* data_;
   1267   size_t length_;
   1268 };
   1269 
   1270 TEST(CodeSerializerExternalString) {
   1271   FLAG_serialize_toplevel = true;
   1272   LocalContext context;
   1273   Isolate* isolate = CcTest::i_isolate();
   1274   isolate->compilation_cache()->Disable();  // Disable same-isolate code cache.
   1275 
   1276   v8::HandleScope scope(CcTest::isolate());
   1277 
   1278   // Obtain external internalized one-byte string.
   1279   SerializerOneByteResource one_byte_resource("one_byte", 8);
   1280   Handle<String> one_byte_string =
   1281       isolate->factory()->NewStringFromAsciiChecked("one_byte");
   1282   one_byte_string = isolate->factory()->InternalizeString(one_byte_string);
   1283   one_byte_string->MakeExternal(&one_byte_resource);
   1284   CHECK(one_byte_string->IsExternalOneByteString());
   1285   CHECK(one_byte_string->IsInternalizedString());
   1286 
   1287   // Obtain external internalized two-byte string.
   1288   SerializerTwoByteResource two_byte_resource("two_byte", 8);
   1289   Handle<String> two_byte_string =
   1290       isolate->factory()->NewStringFromAsciiChecked("two_byte");
   1291   two_byte_string = isolate->factory()->InternalizeString(two_byte_string);
   1292   two_byte_string->MakeExternal(&two_byte_resource);
   1293   CHECK(two_byte_string->IsExternalTwoByteString());
   1294   CHECK(two_byte_string->IsInternalizedString());
   1295 
   1296   const char* source =
   1297       "var o = {}               \n"
   1298       "o.one_byte = 7;          \n"
   1299       "o.two_byte = 8;          \n"
   1300       "o.one_byte + o.two_byte; \n";
   1301   Handle<String> source_string = isolate->factory()
   1302                                      ->NewStringFromUtf8(CStrVector(source))
   1303                                      .ToHandleChecked();
   1304 
   1305   Handle<JSObject> global(isolate->context()->global_object());
   1306   ScriptData* cache = NULL;
   1307 
   1308   Handle<SharedFunctionInfo> orig =
   1309       CompileScript(isolate, source_string, Handle<String>(), &cache,
   1310                     v8::ScriptCompiler::kProduceCodeCache);
   1311 
   1312   Handle<SharedFunctionInfo> copy;
   1313   {
   1314     DisallowCompilation no_compile_expected(isolate);
   1315     copy = CompileScript(isolate, source_string, Handle<String>(), &cache,
   1316                          v8::ScriptCompiler::kConsumeCodeCache);
   1317   }
   1318   CHECK_NE(*orig, *copy);
   1319 
   1320   Handle<JSFunction> copy_fun =
   1321       isolate->factory()->NewFunctionFromSharedFunctionInfo(
   1322           copy, isolate->native_context());
   1323 
   1324   Handle<Object> copy_result =
   1325       Execution::Call(isolate, copy_fun, global, 0, NULL).ToHandleChecked();
   1326 
   1327   CHECK_EQ(15.0, copy_result->Number());
   1328 
   1329   delete cache;
   1330 }
   1331 
   1332 TEST(CodeSerializerLargeExternalString) {
   1333   FLAG_serialize_toplevel = true;
   1334   LocalContext context;
   1335   Isolate* isolate = CcTest::i_isolate();
   1336   isolate->compilation_cache()->Disable();  // Disable same-isolate code cache.
   1337 
   1338   Factory* f = isolate->factory();
   1339 
   1340   v8::HandleScope scope(CcTest::isolate());
   1341 
   1342   // Create a huge external internalized string to use as variable name.
   1343   Vector<const uint8_t> string =
   1344       ConstructSource(STATIC_CHAR_VECTOR(""), STATIC_CHAR_VECTOR("abcdef"),
   1345                       STATIC_CHAR_VECTOR(""), 999999);
   1346   Handle<String> name = f->NewStringFromOneByte(string).ToHandleChecked();
   1347   SerializerOneByteResource one_byte_resource(
   1348       reinterpret_cast<const char*>(string.start()), string.length());
   1349   name = f->InternalizeString(name);
   1350   name->MakeExternal(&one_byte_resource);
   1351   CHECK(name->IsExternalOneByteString());
   1352   CHECK(name->IsInternalizedString());
   1353   CHECK(isolate->heap()->InSpace(*name, LO_SPACE));
   1354 
   1355   // Create the source, which is "var <literal> = 42; <literal>".
   1356   Handle<String> source_str =
   1357       f->NewConsString(
   1358              f->NewConsString(f->NewStringFromAsciiChecked("var "), name)
   1359                  .ToHandleChecked(),
   1360              f->NewConsString(f->NewStringFromAsciiChecked(" = 42; "), name)
   1361                  .ToHandleChecked()).ToHandleChecked();
   1362 
   1363   Handle<JSObject> global(isolate->context()->global_object());
   1364   ScriptData* cache = NULL;
   1365 
   1366   Handle<SharedFunctionInfo> orig =
   1367       CompileScript(isolate, source_str, Handle<String>(), &cache,
   1368                     v8::ScriptCompiler::kProduceCodeCache);
   1369 
   1370   Handle<SharedFunctionInfo> copy;
   1371   {
   1372     DisallowCompilation no_compile_expected(isolate);
   1373     copy = CompileScript(isolate, source_str, Handle<String>(), &cache,
   1374                          v8::ScriptCompiler::kConsumeCodeCache);
   1375   }
   1376   CHECK_NE(*orig, *copy);
   1377 
   1378   Handle<JSFunction> copy_fun =
   1379       f->NewFunctionFromSharedFunctionInfo(copy, isolate->native_context());
   1380 
   1381   Handle<Object> copy_result =
   1382       Execution::Call(isolate, copy_fun, global, 0, NULL).ToHandleChecked();
   1383 
   1384   CHECK_EQ(42.0, copy_result->Number());
   1385 
   1386   delete cache;
   1387   string.Dispose();
   1388 }
   1389 
   1390 TEST(CodeSerializerExternalScriptName) {
   1391   FLAG_serialize_toplevel = true;
   1392   LocalContext context;
   1393   Isolate* isolate = CcTest::i_isolate();
   1394   isolate->compilation_cache()->Disable();  // Disable same-isolate code cache.
   1395 
   1396   Factory* f = isolate->factory();
   1397 
   1398   v8::HandleScope scope(CcTest::isolate());
   1399 
   1400   const char* source =
   1401       "var a = [1, 2, 3, 4];"
   1402       "a.reduce(function(x, y) { return x + y }, 0)";
   1403 
   1404   Handle<String> source_string =
   1405       f->NewStringFromUtf8(CStrVector(source)).ToHandleChecked();
   1406 
   1407   const SerializerOneByteResource one_byte_resource("one_byte", 8);
   1408   Handle<String> name =
   1409       f->NewExternalStringFromOneByte(&one_byte_resource).ToHandleChecked();
   1410   CHECK(name->IsExternalOneByteString());
   1411   CHECK(!name->IsInternalizedString());
   1412 
   1413   Handle<JSObject> global(isolate->context()->global_object());
   1414   ScriptData* cache = NULL;
   1415 
   1416   Handle<SharedFunctionInfo> orig =
   1417       CompileScript(isolate, source_string, name, &cache,
   1418                     v8::ScriptCompiler::kProduceCodeCache);
   1419 
   1420   Handle<SharedFunctionInfo> copy;
   1421   {
   1422     DisallowCompilation no_compile_expected(isolate);
   1423     copy = CompileScript(isolate, source_string, name, &cache,
   1424                          v8::ScriptCompiler::kConsumeCodeCache);
   1425   }
   1426   CHECK_NE(*orig, *copy);
   1427 
   1428   Handle<JSFunction> copy_fun =
   1429       f->NewFunctionFromSharedFunctionInfo(copy, isolate->native_context());
   1430 
   1431   Handle<Object> copy_result =
   1432       Execution::Call(isolate, copy_fun, global, 0, NULL).ToHandleChecked();
   1433 
   1434   CHECK_EQ(10.0, copy_result->Number());
   1435 
   1436   delete cache;
   1437 }
   1438 
   1439 
   1440 static bool toplevel_test_code_event_found = false;
   1441 
   1442 
   1443 static void SerializerCodeEventListener(const v8::JitCodeEvent* event) {
   1444   if (event->type == v8::JitCodeEvent::CODE_ADDED &&
   1445       memcmp(event->name.str, "Script:~test", 12) == 0) {
   1446     toplevel_test_code_event_found = true;
   1447   }
   1448 }
   1449 
   1450 
   1451 v8::ScriptCompiler::CachedData* ProduceCache(const char* source) {
   1452   v8::ScriptCompiler::CachedData* cache;
   1453   v8::Isolate::CreateParams create_params;
   1454   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   1455   v8::Isolate* isolate1 = v8::Isolate::New(create_params);
   1456   {
   1457     v8::Isolate::Scope iscope(isolate1);
   1458     v8::HandleScope scope(isolate1);
   1459     v8::Local<v8::Context> context = v8::Context::New(isolate1);
   1460     v8::Context::Scope context_scope(context);
   1461 
   1462     v8::Local<v8::String> source_str = v8_str(source);
   1463     v8::ScriptOrigin origin(v8_str("test"));
   1464     v8::ScriptCompiler::Source source(source_str, origin);
   1465     v8::Local<v8::UnboundScript> script =
   1466         v8::ScriptCompiler::CompileUnboundScript(
   1467             isolate1, &source, v8::ScriptCompiler::kProduceCodeCache)
   1468             .ToLocalChecked();
   1469     const v8::ScriptCompiler::CachedData* data = source.GetCachedData();
   1470     CHECK(data);
   1471     // Persist cached data.
   1472     uint8_t* buffer = NewArray<uint8_t>(data->length);
   1473     MemCopy(buffer, data->data, data->length);
   1474     cache = new v8::ScriptCompiler::CachedData(
   1475         buffer, data->length, v8::ScriptCompiler::CachedData::BufferOwned);
   1476 
   1477     v8::Local<v8::Value> result = script->BindToCurrentContext()
   1478                                       ->Run(isolate1->GetCurrentContext())
   1479                                       .ToLocalChecked();
   1480     v8::Local<v8::String> result_string =
   1481         result->ToString(isolate1->GetCurrentContext()).ToLocalChecked();
   1482     CHECK(result_string->Equals(isolate1->GetCurrentContext(), v8_str("abcdef"))
   1483               .FromJust());
   1484   }
   1485   isolate1->Dispose();
   1486   return cache;
   1487 }
   1488 
   1489 TEST(CodeSerializerIsolates) {
   1490   FLAG_serialize_toplevel = true;
   1491 
   1492   const char* source = "function f() { return 'abc'; }; f() + 'def'";
   1493   v8::ScriptCompiler::CachedData* cache = ProduceCache(source);
   1494 
   1495   v8::Isolate::CreateParams create_params;
   1496   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   1497   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
   1498   isolate2->SetJitCodeEventHandler(v8::kJitCodeEventDefault,
   1499                                    SerializerCodeEventListener);
   1500   toplevel_test_code_event_found = false;
   1501   {
   1502     v8::Isolate::Scope iscope(isolate2);
   1503     v8::HandleScope scope(isolate2);
   1504     v8::Local<v8::Context> context = v8::Context::New(isolate2);
   1505     v8::Context::Scope context_scope(context);
   1506 
   1507     v8::Local<v8::String> source_str = v8_str(source);
   1508     v8::ScriptOrigin origin(v8_str("test"));
   1509     v8::ScriptCompiler::Source source(source_str, origin, cache);
   1510     v8::Local<v8::UnboundScript> script;
   1511     {
   1512       DisallowCompilation no_compile(reinterpret_cast<Isolate*>(isolate2));
   1513       script = v8::ScriptCompiler::CompileUnboundScript(
   1514                    isolate2, &source, v8::ScriptCompiler::kConsumeCodeCache)
   1515                    .ToLocalChecked();
   1516     }
   1517     CHECK(!cache->rejected);
   1518     v8::Local<v8::Value> result = script->BindToCurrentContext()
   1519                                       ->Run(isolate2->GetCurrentContext())
   1520                                       .ToLocalChecked();
   1521     CHECK(result->ToString(isolate2->GetCurrentContext())
   1522               .ToLocalChecked()
   1523               ->Equals(isolate2->GetCurrentContext(), v8_str("abcdef"))
   1524               .FromJust());
   1525   }
   1526   CHECK(toplevel_test_code_event_found);
   1527   isolate2->Dispose();
   1528 }
   1529 
   1530 TEST(CodeSerializerFlagChange) {
   1531   FLAG_serialize_toplevel = true;
   1532 
   1533   const char* source = "function f() { return 'abc'; }; f() + 'def'";
   1534   v8::ScriptCompiler::CachedData* cache = ProduceCache(source);
   1535 
   1536   v8::Isolate::CreateParams create_params;
   1537   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   1538   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
   1539 
   1540   FLAG_allow_natives_syntax = true;  // Flag change should trigger cache reject.
   1541   FlagList::EnforceFlagImplications();
   1542   {
   1543     v8::Isolate::Scope iscope(isolate2);
   1544     v8::HandleScope scope(isolate2);
   1545     v8::Local<v8::Context> context = v8::Context::New(isolate2);
   1546     v8::Context::Scope context_scope(context);
   1547 
   1548     v8::Local<v8::String> source_str = v8_str(source);
   1549     v8::ScriptOrigin origin(v8_str("test"));
   1550     v8::ScriptCompiler::Source source(source_str, origin, cache);
   1551     v8::ScriptCompiler::CompileUnboundScript(
   1552         isolate2, &source, v8::ScriptCompiler::kConsumeCodeCache)
   1553         .ToLocalChecked();
   1554     CHECK(cache->rejected);
   1555   }
   1556   isolate2->Dispose();
   1557 }
   1558 
   1559 TEST(CodeSerializerBitFlip) {
   1560   FLAG_serialize_toplevel = true;
   1561 
   1562   const char* source = "function f() { return 'abc'; }; f() + 'def'";
   1563   v8::ScriptCompiler::CachedData* cache = ProduceCache(source);
   1564 
   1565   // Random bit flip.
   1566   const_cast<uint8_t*>(cache->data)[337] ^= 0x40;
   1567 
   1568   v8::Isolate::CreateParams create_params;
   1569   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   1570   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
   1571   {
   1572     v8::Isolate::Scope iscope(isolate2);
   1573     v8::HandleScope scope(isolate2);
   1574     v8::Local<v8::Context> context = v8::Context::New(isolate2);
   1575     v8::Context::Scope context_scope(context);
   1576 
   1577     v8::Local<v8::String> source_str = v8_str(source);
   1578     v8::ScriptOrigin origin(v8_str("test"));
   1579     v8::ScriptCompiler::Source source(source_str, origin, cache);
   1580     v8::ScriptCompiler::CompileUnboundScript(
   1581         isolate2, &source, v8::ScriptCompiler::kConsumeCodeCache)
   1582         .ToLocalChecked();
   1583     CHECK(cache->rejected);
   1584   }
   1585   isolate2->Dispose();
   1586 }
   1587 
   1588 TEST(CodeSerializerWithHarmonyScoping) {
   1589   FLAG_serialize_toplevel = true;
   1590 
   1591   const char* source1 = "'use strict'; let x = 'X'";
   1592   const char* source2 = "'use strict'; let y = 'Y'";
   1593   const char* source3 = "'use strict'; x + y";
   1594 
   1595   v8::ScriptCompiler::CachedData* cache;
   1596 
   1597   v8::Isolate::CreateParams create_params;
   1598   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   1599   v8::Isolate* isolate1 = v8::Isolate::New(create_params);
   1600   {
   1601     v8::Isolate::Scope iscope(isolate1);
   1602     v8::HandleScope scope(isolate1);
   1603     v8::Local<v8::Context> context = v8::Context::New(isolate1);
   1604     v8::Context::Scope context_scope(context);
   1605 
   1606     CompileRun(source1);
   1607     CompileRun(source2);
   1608 
   1609     v8::Local<v8::String> source_str = v8_str(source3);
   1610     v8::ScriptOrigin origin(v8_str("test"));
   1611     v8::ScriptCompiler::Source source(source_str, origin);
   1612     v8::Local<v8::UnboundScript> script =
   1613         v8::ScriptCompiler::CompileUnboundScript(
   1614             isolate1, &source, v8::ScriptCompiler::kProduceCodeCache)
   1615             .ToLocalChecked();
   1616     const v8::ScriptCompiler::CachedData* data = source.GetCachedData();
   1617     CHECK(data);
   1618     // Persist cached data.
   1619     uint8_t* buffer = NewArray<uint8_t>(data->length);
   1620     MemCopy(buffer, data->data, data->length);
   1621     cache = new v8::ScriptCompiler::CachedData(
   1622         buffer, data->length, v8::ScriptCompiler::CachedData::BufferOwned);
   1623 
   1624     v8::Local<v8::Value> result = script->BindToCurrentContext()
   1625                                       ->Run(isolate1->GetCurrentContext())
   1626                                       .ToLocalChecked();
   1627     v8::Local<v8::String> result_str =
   1628         result->ToString(isolate1->GetCurrentContext()).ToLocalChecked();
   1629     CHECK(result_str->Equals(isolate1->GetCurrentContext(), v8_str("XY"))
   1630               .FromJust());
   1631   }
   1632   isolate1->Dispose();
   1633 
   1634   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
   1635   {
   1636     v8::Isolate::Scope iscope(isolate2);
   1637     v8::HandleScope scope(isolate2);
   1638     v8::Local<v8::Context> context = v8::Context::New(isolate2);
   1639     v8::Context::Scope context_scope(context);
   1640 
   1641     // Reverse order of prior running scripts.
   1642     CompileRun(source2);
   1643     CompileRun(source1);
   1644 
   1645     v8::Local<v8::String> source_str = v8_str(source3);
   1646     v8::ScriptOrigin origin(v8_str("test"));
   1647     v8::ScriptCompiler::Source source(source_str, origin, cache);
   1648     v8::Local<v8::UnboundScript> script;
   1649     {
   1650       DisallowCompilation no_compile(reinterpret_cast<Isolate*>(isolate2));
   1651       script = v8::ScriptCompiler::CompileUnboundScript(
   1652                    isolate2, &source, v8::ScriptCompiler::kConsumeCodeCache)
   1653                    .ToLocalChecked();
   1654     }
   1655     v8::Local<v8::Value> result = script->BindToCurrentContext()
   1656                                       ->Run(isolate2->GetCurrentContext())
   1657                                       .ToLocalChecked();
   1658     v8::Local<v8::String> result_str =
   1659         result->ToString(isolate2->GetCurrentContext()).ToLocalChecked();
   1660     CHECK(result_str->Equals(isolate2->GetCurrentContext(), v8_str("XY"))
   1661               .FromJust());
   1662   }
   1663   isolate2->Dispose();
   1664 }
   1665 
   1666 TEST(CodeSerializerInternalReference) {
   1667 #if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_ARM64
   1668   return;
   1669 #endif
   1670   // In ignition there are only relative jumps, so the following code
   1671   // would not have any internal references. This test is not relevant
   1672   // for ignition.
   1673   if (FLAG_ignition) {
   1674     return;
   1675   }
   1676   // Disable experimental natives that are loaded after deserialization.
   1677   FLAG_function_context_specialization = false;
   1678   FLAG_always_opt = true;
   1679   const char* flag = "--turbo-filter=foo";
   1680   FlagList::SetFlagsFromString(flag, StrLength(flag));
   1681 
   1682   const char* source =
   1683       "var foo = (function(stdlib, foreign, heap) {"
   1684       "  function foo(i) {"
   1685       "    i = i|0;"
   1686       "    var j = 0;"
   1687       "    switch (i) {"
   1688       "      case 0:"
   1689       "      case 1: j = 1; break;"
   1690       "      case 2:"
   1691       "      case 3: j = 2; break;"
   1692       "      case 4:"
   1693       "      case 5: j = foo(3) + 1; break;"
   1694       "      default: j = 0; break;"
   1695       "    }"
   1696       "    return j + 10;"
   1697       "  }"
   1698       "  return { foo: foo };"
   1699       "})(this, {}, undefined).foo;"
   1700       "foo(1);";
   1701 
   1702   v8::StartupData data = v8::V8::CreateSnapshotDataBlob(source);
   1703   CHECK(data.data);
   1704 
   1705   v8::Isolate::CreateParams params;
   1706   params.snapshot_blob = &data;
   1707   params.array_buffer_allocator = CcTest::array_buffer_allocator();
   1708   v8::Isolate* isolate = v8::Isolate::New(params);
   1709   {
   1710     v8::Isolate::Scope i_scope(isolate);
   1711     v8::HandleScope h_scope(isolate);
   1712     v8::Local<v8::Context> context = v8::Context::New(isolate);
   1713     delete[] data.data;  // We can dispose of the snapshot blob now.
   1714     v8::Context::Scope c_scope(context);
   1715     v8::Local<v8::Function> foo =
   1716         v8::Local<v8::Function>::Cast(CompileRun("foo"));
   1717 
   1718     // There are at least 6 internal references.
   1719     int mask = RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
   1720                RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED);
   1721     RelocIterator it(
   1722         Handle<JSFunction>::cast(v8::Utils::OpenHandle(*foo))->code(), mask);
   1723     for (int i = 0; i < 6; ++i) {
   1724       CHECK(!it.done());
   1725       it.next();
   1726     }
   1727 
   1728     CHECK(Handle<JSFunction>::cast(v8::Utils::OpenHandle(*foo))
   1729               ->code()
   1730               ->is_turbofanned());
   1731     CHECK_EQ(11, CompileRun("foo(0)")
   1732                      ->Int32Value(isolate->GetCurrentContext())
   1733                      .FromJust());
   1734     CHECK_EQ(11, CompileRun("foo(1)")
   1735                      ->Int32Value(isolate->GetCurrentContext())
   1736                      .FromJust());
   1737     CHECK_EQ(12, CompileRun("foo(2)")
   1738                      ->Int32Value(isolate->GetCurrentContext())
   1739                      .FromJust());
   1740     CHECK_EQ(12, CompileRun("foo(3)")
   1741                      ->Int32Value(isolate->GetCurrentContext())
   1742                      .FromJust());
   1743     CHECK_EQ(23, CompileRun("foo(4)")
   1744                      ->Int32Value(isolate->GetCurrentContext())
   1745                      .FromJust());
   1746     CHECK_EQ(23, CompileRun("foo(5)")
   1747                      ->Int32Value(isolate->GetCurrentContext())
   1748                      .FromJust());
   1749     CHECK_EQ(10, CompileRun("foo(6)")
   1750                      ->Int32Value(isolate->GetCurrentContext())
   1751                      .FromJust());
   1752   }
   1753   isolate->Dispose();
   1754 }
   1755 
   1756 TEST(CodeSerializerEagerCompilationAndPreAge) {
   1757   if (FLAG_ignition) return;
   1758 
   1759   FLAG_lazy = true;
   1760   FLAG_serialize_toplevel = true;
   1761   FLAG_serialize_age_code = true;
   1762   FLAG_serialize_eager = true;
   1763   FLAG_min_preparse_length = 1;
   1764 
   1765   static const char* source =
   1766       "function f() {"
   1767       "  function g() {"
   1768       "    return 1;"
   1769       "  }"
   1770       "  return g();"
   1771       "}"
   1772       "'abcdef';";
   1773 
   1774   v8::ScriptCompiler::CachedData* cache = ProduceCache(source);
   1775 
   1776   v8::Isolate::CreateParams create_params;
   1777   create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
   1778   v8::Isolate* isolate2 = v8::Isolate::New(create_params);
   1779   {
   1780     v8::Isolate::Scope iscope(isolate2);
   1781     v8::HandleScope scope(isolate2);
   1782     v8::Local<v8::Context> context = v8::Context::New(isolate2);
   1783     v8::Context::Scope context_scope(context);
   1784 
   1785     v8::Local<v8::String> source_str = v8_str(source);
   1786     v8::ScriptOrigin origin(v8_str("test"));
   1787     v8::ScriptCompiler::Source source(source_str, origin, cache);
   1788     v8::Local<v8::UnboundScript> unbound =
   1789         v8::ScriptCompiler::CompileUnboundScript(
   1790             isolate2, &source, v8::ScriptCompiler::kConsumeCodeCache)
   1791             .ToLocalChecked();
   1792 
   1793     CHECK(!cache->rejected);
   1794 
   1795     Isolate* i_isolate = reinterpret_cast<Isolate*>(isolate2);
   1796     HandleScope i_scope(i_isolate);
   1797     Handle<SharedFunctionInfo> toplevel = v8::Utils::OpenHandle(*unbound);
   1798     Handle<Script> script(Script::cast(toplevel->script()));
   1799     WeakFixedArray::Iterator iterator(script->shared_function_infos());
   1800     // Every function has been pre-compiled from the code cache.
   1801     int count = 0;
   1802     while (SharedFunctionInfo* shared = iterator.Next<SharedFunctionInfo>()) {
   1803       CHECK(shared->is_compiled());
   1804       CHECK_EQ(Code::kPreAgedCodeAge, shared->code()->GetAge());
   1805       count++;
   1806     }
   1807     CHECK_EQ(3, count);
   1808   }
   1809   isolate2->Dispose();
   1810 }
   1811 
   1812 TEST(Regress503552) {
   1813   // Test that the code serializer can deal with weak cells that form a linked
   1814   // list during incremental marking.
   1815   CcTest::InitializeVM();
   1816   Isolate* isolate = CcTest::i_isolate();
   1817 
   1818   HandleScope scope(isolate);
   1819   Handle<String> source = isolate->factory()->NewStringFromAsciiChecked(
   1820       "function f() {} function g() {}");
   1821   ScriptData* script_data = NULL;
   1822   Handle<SharedFunctionInfo> shared = Compiler::GetSharedFunctionInfoForScript(
   1823       source, Handle<String>(), 0, 0, v8::ScriptOriginOptions(),
   1824       Handle<Object>(), Handle<Context>(isolate->native_context()), NULL,
   1825       &script_data, v8::ScriptCompiler::kProduceCodeCache, NOT_NATIVES_CODE,
   1826       false);
   1827   delete script_data;
   1828 
   1829   heap::SimulateIncrementalMarking(isolate->heap());
   1830 
   1831   script_data = CodeSerializer::Serialize(isolate, shared, source);
   1832   delete script_data;
   1833 }
   1834 
   1835 #if V8_TARGET_ARCH_X64
   1836 TEST(CodeSerializerCell) {
   1837   FLAG_serialize_toplevel = true;
   1838   LocalContext context;
   1839   Isolate* isolate = CcTest::i_isolate();
   1840   isolate->compilation_cache()->Disable();  // Disable same-isolate code cache.
   1841 
   1842   v8::HandleScope scope(CcTest::isolate());
   1843 
   1844   size_t actual_size;
   1845   byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
   1846       Assembler::kMinimalBufferSize, &actual_size, true));
   1847   CHECK(buffer);
   1848   HandleScope handles(isolate);
   1849 
   1850   MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size),
   1851                            v8::internal::CodeObjectRequired::kYes);
   1852   assembler.enable_serializer();
   1853   Handle<HeapNumber> number = isolate->factory()->NewHeapNumber(0.3);
   1854   CHECK(isolate->heap()->InNewSpace(*number));
   1855   MacroAssembler* masm = &assembler;
   1856   masm->MoveHeapObject(rax, number);
   1857   masm->ret(0);
   1858   CodeDesc desc;
   1859   masm->GetCode(&desc);
   1860   Handle<Code> code = isolate->factory()->NewCode(
   1861       desc, Code::ComputeFlags(Code::FUNCTION), masm->CodeObject());
   1862   code->set_has_reloc_info_for_serialization(true);
   1863 
   1864   RelocIterator rit1(*code, 1 << RelocInfo::CELL);
   1865   CHECK_EQ(*number, rit1.rinfo()->target_cell()->value());
   1866 
   1867   Handle<String> source = isolate->factory()->empty_string();
   1868   Handle<SharedFunctionInfo> sfi =
   1869       isolate->factory()->NewSharedFunctionInfo(source, code, false);
   1870   ScriptData* script_data = CodeSerializer::Serialize(isolate, sfi, source);
   1871 
   1872   Handle<SharedFunctionInfo> copy =
   1873       CodeSerializer::Deserialize(isolate, script_data, source)
   1874           .ToHandleChecked();
   1875   RelocIterator rit2(copy->code(), 1 << RelocInfo::CELL);
   1876   CHECK(rit2.rinfo()->target_cell()->IsCell());
   1877   Handle<Cell> cell(rit2.rinfo()->target_cell());
   1878   CHECK(cell->value()->IsHeapNumber());
   1879   CHECK_EQ(0.3, HeapNumber::cast(cell->value())->value());
   1880 
   1881   delete script_data;
   1882 }
   1883 #endif  // V8_TARGET_ARCH_X64
   1884 
   1885 TEST(SnapshotCreatorMultipleContexts) {
   1886   DisableTurbofan();
   1887   v8::StartupData blob;
   1888   {
   1889     v8::SnapshotCreator creator;
   1890     v8::Isolate* isolate = creator.GetIsolate();
   1891     {
   1892       v8::HandleScope handle_scope(isolate);
   1893       v8::Local<v8::Context> context = v8::Context::New(isolate);
   1894       v8::Context::Scope context_scope(context);
   1895       CompileRun("var f = function() { return 1; }");
   1896       CHECK_EQ(0, creator.AddContext(context));
   1897     }
   1898     {
   1899       v8::HandleScope handle_scope(isolate);
   1900       v8::Local<v8::Context> context = v8::Context::New(isolate);
   1901       v8::Context::Scope context_scope(context);
   1902       CompileRun("var f = function() { return 2; }");
   1903       CHECK_EQ(1, creator.AddContext(context));
   1904     }
   1905     {
   1906       v8::HandleScope handle_scope(isolate);
   1907       v8::Local<v8::Context> context = v8::Context::New(isolate);
   1908       CHECK_EQ(2, creator.AddContext(context));
   1909     }
   1910     blob =
   1911         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
   1912   }
   1913 
   1914   v8::Isolate::CreateParams params;
   1915   params.snapshot_blob = &blob;
   1916   params.array_buffer_allocator = CcTest::array_buffer_allocator();
   1917   v8::Isolate* isolate = v8::Isolate::New(params);
   1918   {
   1919     v8::Isolate::Scope isolate_scope(isolate);
   1920     v8::ExtensionConfiguration* no_extension = nullptr;
   1921     v8::Local<v8::ObjectTemplate> no_template = v8::Local<v8::ObjectTemplate>();
   1922     v8::Local<v8::Value> no_object = v8::Local<v8::Value>();
   1923     {
   1924       v8::HandleScope handle_scope(isolate);
   1925       v8::Local<v8::Context> context =
   1926           v8::Context::New(isolate, no_extension, no_template, no_object, 0);
   1927       v8::Context::Scope context_scope(context);
   1928       ExpectInt32("f()", 1);
   1929     }
   1930     {
   1931       v8::HandleScope handle_scope(isolate);
   1932       v8::Local<v8::Context> context =
   1933           v8::Context::New(isolate, no_extension, no_template, no_object, 1);
   1934       v8::Context::Scope context_scope(context);
   1935       ExpectInt32("f()", 2);
   1936     }
   1937     {
   1938       v8::HandleScope handle_scope(isolate);
   1939       v8::Local<v8::Context> context =
   1940           v8::Context::New(isolate, no_extension, no_template, no_object, 2);
   1941       v8::Context::Scope context_scope(context);
   1942       ExpectUndefined("this.f");
   1943     }
   1944   }
   1945 
   1946   isolate->Dispose();
   1947   delete[] blob.data;
   1948 }
   1949 
   1950 static void SerializedCallback(
   1951     const v8::FunctionCallbackInfo<v8::Value>& args) {
   1952   args.GetReturnValue().Set(v8_num(42));
   1953 }
   1954 
   1955 static void SerializedCallbackReplacement(
   1956     const v8::FunctionCallbackInfo<v8::Value>& args) {
   1957   args.GetReturnValue().Set(v8_num(1337));
   1958 }
   1959 
   1960 intptr_t original_external_references[] = {
   1961     reinterpret_cast<intptr_t>(SerializedCallback), 0};
   1962 
   1963 intptr_t replaced_external_references[] = {
   1964     reinterpret_cast<intptr_t>(SerializedCallbackReplacement), 0};
   1965 
   1966 TEST(SnapshotCreatorExternalReferences) {
   1967   DisableTurbofan();
   1968   v8::StartupData blob;
   1969   {
   1970     v8::SnapshotCreator creator(original_external_references);
   1971     v8::Isolate* isolate = creator.GetIsolate();
   1972     {
   1973       v8::HandleScope handle_scope(isolate);
   1974       v8::Local<v8::Context> context = v8::Context::New(isolate);
   1975       v8::Context::Scope context_scope(context);
   1976       v8::Local<v8::FunctionTemplate> callback =
   1977           v8::FunctionTemplate::New(isolate, SerializedCallback);
   1978       v8::Local<v8::Value> function =
   1979           callback->GetFunction(context).ToLocalChecked();
   1980       CHECK(context->Global()->Set(context, v8_str("f"), function).FromJust());
   1981       ExpectInt32("f()", 42);
   1982       CHECK_EQ(0, creator.AddContext(context));
   1983     }
   1984     blob =
   1985         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
   1986   }
   1987 
   1988   // Deserialize with the original external reference.
   1989   {
   1990     v8::Isolate::CreateParams params;
   1991     params.snapshot_blob = &blob;
   1992     params.array_buffer_allocator = CcTest::array_buffer_allocator();
   1993     params.external_references = original_external_references;
   1994     v8::Isolate* isolate = v8::Isolate::New(params);
   1995     {
   1996       v8::Isolate::Scope isolate_scope(isolate);
   1997       v8::HandleScope handle_scope(isolate);
   1998       v8::ExtensionConfiguration* no_extension = nullptr;
   1999       v8::Local<v8::ObjectTemplate> no_template =
   2000           v8::Local<v8::ObjectTemplate>();
   2001       v8::Local<v8::Value> no_object = v8::Local<v8::Value>();
   2002       v8::Local<v8::Context> context =
   2003           v8::Context::New(isolate, no_extension, no_template, no_object, 0);
   2004       v8::Context::Scope context_scope(context);
   2005       ExpectInt32("f()", 42);
   2006     }
   2007     isolate->Dispose();
   2008   }
   2009 
   2010   // Deserialize with the some other external reference.
   2011   {
   2012     v8::Isolate::CreateParams params;
   2013     params.snapshot_blob = &blob;
   2014     params.array_buffer_allocator = CcTest::array_buffer_allocator();
   2015     params.external_references = replaced_external_references;
   2016     v8::Isolate* isolate = v8::Isolate::New(params);
   2017     {
   2018       v8::Isolate::Scope isolate_scope(isolate);
   2019       v8::HandleScope handle_scope(isolate);
   2020       v8::ExtensionConfiguration* no_extension = nullptr;
   2021       v8::Local<v8::ObjectTemplate> no_template =
   2022           v8::Local<v8::ObjectTemplate>();
   2023       v8::Local<v8::Value> no_object = v8::Local<v8::Value>();
   2024       v8::Local<v8::Context> context =
   2025           v8::Context::New(isolate, no_extension, no_template, no_object, 0);
   2026       v8::Context::Scope context_scope(context);
   2027       ExpectInt32("f()", 1337);
   2028     }
   2029     isolate->Dispose();
   2030   }
   2031   delete[] blob.data;
   2032 }
   2033 
   2034 TEST(SnapshotCreatorTemplates) {
   2035   DisableTurbofan();
   2036   v8::StartupData blob;
   2037   {
   2038     v8::SnapshotCreator creator(original_external_references);
   2039     v8::Isolate* isolate = creator.GetIsolate();
   2040     {
   2041       v8::HandleScope handle_scope(isolate);
   2042       v8::ExtensionConfiguration* no_extension = nullptr;
   2043       v8::Local<v8::ObjectTemplate> global_template =
   2044           v8::ObjectTemplate::New(isolate);
   2045       v8::Local<v8::FunctionTemplate> callback =
   2046           v8::FunctionTemplate::New(isolate, SerializedCallback);
   2047       global_template->Set(v8_str("f"), callback);
   2048       v8::Local<v8::Context> context =
   2049           v8::Context::New(isolate, no_extension, global_template);
   2050       v8::Context::Scope context_scope(context);
   2051       ExpectInt32("f()", 42);
   2052       CHECK_EQ(0, creator.AddContext(context));
   2053       CHECK_EQ(0, creator.AddTemplate(callback));
   2054       CHECK_EQ(1, creator.AddTemplate(global_template));
   2055     }
   2056     blob =
   2057         creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
   2058   }
   2059 
   2060   {
   2061     v8::Isolate::CreateParams params;
   2062     params.snapshot_blob = &blob;
   2063     params.array_buffer_allocator = CcTest::array_buffer_allocator();
   2064     params.external_references = original_external_references;
   2065     v8::Isolate* isolate = v8::Isolate::New(params);
   2066     {
   2067       v8::Isolate::Scope isolate_scope(isolate);
   2068       {
   2069         // Create a new context without a new object template.
   2070         v8::HandleScope handle_scope(isolate);
   2071         v8::ExtensionConfiguration* no_extension = nullptr;
   2072         v8::Local<v8::ObjectTemplate> no_template =
   2073             v8::Local<v8::ObjectTemplate>();
   2074         v8::Local<v8::Value> no_object = v8::Local<v8::Value>();
   2075         v8::Local<v8::Context> context =
   2076             v8::Context::New(isolate, no_extension, no_template, no_object, 0);
   2077         v8::Context::Scope context_scope(context);
   2078         ExpectInt32("f()", 42);
   2079 
   2080         // Retrieve the snapshotted object template.
   2081         v8::Local<v8::ObjectTemplate> obj_template =
   2082             v8::ObjectTemplate::FromSnapshot(isolate, 1);
   2083         CHECK(!obj_template.IsEmpty());
   2084         v8::Local<v8::Object> object =
   2085             obj_template->NewInstance(context).ToLocalChecked();
   2086         CHECK(context->Global()->Set(context, v8_str("o"), object).FromJust());
   2087         ExpectInt32("o.f()", 42);
   2088         // Check that it instantiates to the same prototype.
   2089         ExpectTrue("o.f.prototype === f.prototype");
   2090 
   2091         // Retrieve the snapshotted function template.
   2092         v8::Local<v8::FunctionTemplate> fun_template =
   2093             v8::FunctionTemplate::FromSnapshot(isolate, 0);
   2094         CHECK(!fun_template.IsEmpty());
   2095         v8::Local<v8::Function> fun =
   2096             fun_template->GetFunction(context).ToLocalChecked();
   2097         CHECK(context->Global()->Set(context, v8_str("g"), fun).FromJust());
   2098         ExpectInt32("g()", 42);
   2099         // Check that it instantiates to the same prototype.
   2100         ExpectTrue("g.prototype === f.prototype");
   2101       }
   2102 
   2103       {
   2104         // Create a context with a new object template. It is merged into the
   2105         // deserialized global object.
   2106         v8::HandleScope handle_scope(isolate);
   2107         v8::ExtensionConfiguration* no_extension = nullptr;
   2108         v8::Local<v8::ObjectTemplate> global_template =
   2109             v8::ObjectTemplate::New(isolate);
   2110         global_template->Set(
   2111             v8_str("g"),
   2112             v8::FunctionTemplate::New(isolate, SerializedCallbackReplacement));
   2113         v8::Local<v8::Value> no_object = v8::Local<v8::Value>();
   2114         v8::Local<v8::Context> context = v8::Context::New(
   2115             isolate, no_extension, global_template, no_object, 0);
   2116         v8::Context::Scope context_scope(context);
   2117         ExpectInt32("g()", 1337);
   2118         ExpectInt32("f()", 42);
   2119       }
   2120     }
   2121     isolate->Dispose();
   2122   }
   2123   delete[] blob.data;
   2124 }
   2125 
   2126 TEST(SerializationMemoryStats) {
   2127   FLAG_profile_deserialization = true;
   2128   FLAG_always_opt = false;
   2129   v8::StartupData blob = v8::V8::CreateSnapshotDataBlob();
   2130   delete[] blob.data;
   2131 }
   2132