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 "v8.h"
     33 
     34 #include "debug.h"
     35 #include "ic-inl.h"
     36 #include "runtime.h"
     37 #include "serialize.h"
     38 #include "scopeinfo.h"
     39 #include "snapshot.h"
     40 #include "cctest.h"
     41 #include "spaces.h"
     42 #include "objects.h"
     43 #include "natives.h"
     44 #include "bootstrapper.h"
     45 
     46 using namespace v8::internal;
     47 
     48 static const unsigned kCounters = 256;
     49 static int local_counters[kCounters];
     50 static const char* local_counter_names[kCounters];
     51 
     52 
     53 static unsigned CounterHash(const char* s) {
     54   unsigned hash = 0;
     55   while (*++s) {
     56     hash |= hash << 5;
     57     hash += *s;
     58   }
     59   return hash;
     60 }
     61 
     62 
     63 // Callback receiver to track counters in test.
     64 static int* counter_function(const char* name) {
     65   unsigned hash = CounterHash(name) % kCounters;
     66   unsigned original_hash = hash;
     67   USE(original_hash);
     68   while (true) {
     69     if (local_counter_names[hash] == name) {
     70       return &local_counters[hash];
     71     }
     72     if (local_counter_names[hash] == 0) {
     73       local_counter_names[hash] = name;
     74       return &local_counters[hash];
     75     }
     76     if (strcmp(local_counter_names[hash], name) == 0) {
     77       return &local_counters[hash];
     78     }
     79     hash = (hash + 1) % kCounters;
     80     ASSERT(hash != original_hash);  // Hash table has been filled up.
     81   }
     82 }
     83 
     84 
     85 template <class T>
     86 static Address AddressOf(T id) {
     87   return ExternalReference(id, i::Isolate::Current()).address();
     88 }
     89 
     90 
     91 template <class T>
     92 static uint32_t Encode(const ExternalReferenceEncoder& encoder, T id) {
     93   return encoder.Encode(AddressOf(id));
     94 }
     95 
     96 
     97 static int make_code(TypeCode type, int id) {
     98   return static_cast<uint32_t>(type) << kReferenceTypeShift | id;
     99 }
    100 
    101 
    102 TEST(ExternalReferenceEncoder) {
    103   Isolate* isolate = i::Isolate::Current();
    104   isolate->stats_table()->SetCounterFunction(counter_function);
    105   v8::V8::Initialize();
    106 
    107   ExternalReferenceEncoder encoder;
    108   CHECK_EQ(make_code(BUILTIN, Builtins::kArrayCode),
    109            Encode(encoder, Builtins::kArrayCode));
    110   CHECK_EQ(make_code(v8::internal::RUNTIME_FUNCTION, Runtime::kAbort),
    111            Encode(encoder, Runtime::kAbort));
    112   ExternalReference total_compile_size =
    113       ExternalReference(isolate->counters()->total_compile_size());
    114   CHECK_EQ(make_code(STATS_COUNTER, Counters::k_total_compile_size),
    115            encoder.Encode(total_compile_size.address()));
    116   ExternalReference stack_limit_address =
    117       ExternalReference::address_of_stack_limit(isolate);
    118   CHECK_EQ(make_code(UNCLASSIFIED, 4),
    119            encoder.Encode(stack_limit_address.address()));
    120   ExternalReference real_stack_limit_address =
    121       ExternalReference::address_of_real_stack_limit(isolate);
    122   CHECK_EQ(make_code(UNCLASSIFIED, 5),
    123            encoder.Encode(real_stack_limit_address.address()));
    124 #ifdef ENABLE_DEBUGGER_SUPPORT
    125   CHECK_EQ(make_code(UNCLASSIFIED, 16),
    126            encoder.Encode(ExternalReference::debug_break(isolate).address()));
    127 #endif  // ENABLE_DEBUGGER_SUPPORT
    128   CHECK_EQ(make_code(UNCLASSIFIED, 10),
    129            encoder.Encode(
    130                ExternalReference::new_space_start(isolate).address()));
    131   CHECK_EQ(make_code(UNCLASSIFIED, 3),
    132            encoder.Encode(
    133                ExternalReference::roots_array_start(isolate).address()));
    134   CHECK_EQ(make_code(UNCLASSIFIED, 52),
    135            encoder.Encode(ExternalReference::cpu_features().address()));
    136 }
    137 
    138 
    139 TEST(ExternalReferenceDecoder) {
    140   Isolate* isolate = i::Isolate::Current();
    141   isolate->stats_table()->SetCounterFunction(counter_function);
    142   v8::V8::Initialize();
    143 
    144   ExternalReferenceDecoder decoder;
    145   CHECK_EQ(AddressOf(Builtins::kArrayCode),
    146            decoder.Decode(make_code(BUILTIN, Builtins::kArrayCode)));
    147   CHECK_EQ(AddressOf(Runtime::kAbort),
    148            decoder.Decode(make_code(v8::internal::RUNTIME_FUNCTION,
    149                                     Runtime::kAbort)));
    150   ExternalReference total_compile_size =
    151       ExternalReference(isolate->counters()->total_compile_size());
    152   CHECK_EQ(total_compile_size.address(),
    153            decoder.Decode(
    154                make_code(STATS_COUNTER,
    155                          Counters::k_total_compile_size)));
    156   CHECK_EQ(ExternalReference::address_of_stack_limit(isolate).address(),
    157            decoder.Decode(make_code(UNCLASSIFIED, 4)));
    158   CHECK_EQ(ExternalReference::address_of_real_stack_limit(isolate).address(),
    159            decoder.Decode(make_code(UNCLASSIFIED, 5)));
    160 #ifdef ENABLE_DEBUGGER_SUPPORT
    161   CHECK_EQ(ExternalReference::debug_break(isolate).address(),
    162            decoder.Decode(make_code(UNCLASSIFIED, 16)));
    163 #endif  // ENABLE_DEBUGGER_SUPPORT
    164   CHECK_EQ(ExternalReference::new_space_start(isolate).address(),
    165            decoder.Decode(make_code(UNCLASSIFIED, 10)));
    166 }
    167 
    168 
    169 class FileByteSink : public SnapshotByteSink {
    170  public:
    171   explicit FileByteSink(const char* snapshot_file) {
    172     fp_ = OS::FOpen(snapshot_file, "wb");
    173     file_name_ = snapshot_file;
    174     if (fp_ == NULL) {
    175       PrintF("Unable to write to snapshot file \"%s\"\n", snapshot_file);
    176       exit(1);
    177     }
    178   }
    179   virtual ~FileByteSink() {
    180     if (fp_ != NULL) {
    181       fclose(fp_);
    182     }
    183   }
    184   virtual void Put(int byte, const char* description) {
    185     if (fp_ != NULL) {
    186       fputc(byte, fp_);
    187     }
    188   }
    189   virtual int Position() {
    190     return ftell(fp_);
    191   }
    192   void WriteSpaceUsed(
    193       int new_space_used,
    194       int pointer_space_used,
    195       int data_space_used,
    196       int code_space_used,
    197       int map_space_used,
    198       int cell_space_used,
    199       int property_cell_space_used);
    200 
    201  private:
    202   FILE* fp_;
    203   const char* file_name_;
    204 };
    205 
    206 
    207 void FileByteSink::WriteSpaceUsed(
    208       int new_space_used,
    209       int pointer_space_used,
    210       int data_space_used,
    211       int code_space_used,
    212       int map_space_used,
    213       int cell_space_used,
    214       int property_cell_space_used) {
    215   int file_name_length = StrLength(file_name_) + 10;
    216   Vector<char> name = Vector<char>::New(file_name_length + 1);
    217   OS::SNPrintF(name, "%s.size", file_name_);
    218   FILE* fp = OS::FOpen(name.start(), "w");
    219   name.Dispose();
    220   fprintf(fp, "new %d\n", new_space_used);
    221   fprintf(fp, "pointer %d\n", pointer_space_used);
    222   fprintf(fp, "data %d\n", data_space_used);
    223   fprintf(fp, "code %d\n", code_space_used);
    224   fprintf(fp, "map %d\n", map_space_used);
    225   fprintf(fp, "cell %d\n", cell_space_used);
    226   fprintf(fp, "property cell %d\n", property_cell_space_used);
    227   fclose(fp);
    228 }
    229 
    230 
    231 static bool WriteToFile(const char* snapshot_file) {
    232   FileByteSink file(snapshot_file);
    233   StartupSerializer ser(&file);
    234   ser.Serialize();
    235 
    236   file.WriteSpaceUsed(
    237       ser.CurrentAllocationAddress(NEW_SPACE),
    238       ser.CurrentAllocationAddress(OLD_POINTER_SPACE),
    239       ser.CurrentAllocationAddress(OLD_DATA_SPACE),
    240       ser.CurrentAllocationAddress(CODE_SPACE),
    241       ser.CurrentAllocationAddress(MAP_SPACE),
    242       ser.CurrentAllocationAddress(CELL_SPACE),
    243       ser.CurrentAllocationAddress(PROPERTY_CELL_SPACE));
    244 
    245   return true;
    246 }
    247 
    248 
    249 static void Serialize() {
    250   // We have to create one context.  One reason for this is so that the builtins
    251   // can be loaded from v8natives.js and their addresses can be processed.  This
    252   // will clear the pending fixups array, which would otherwise contain GC roots
    253   // that would confuse the serialization/deserialization process.
    254   {
    255     v8::Isolate* isolate = v8::Isolate::GetCurrent();
    256     v8::HandleScope scope(isolate);
    257     v8::Context::New(isolate);
    258   }
    259   WriteToFile(FLAG_testing_serialization_file);
    260 }
    261 
    262 
    263 // Test that the whole heap can be serialized.
    264 TEST(Serialize) {
    265   if (!Snapshot::HaveASnapshotToStartFrom()) {
    266     Serializer::Enable();
    267     v8::V8::Initialize();
    268     Serialize();
    269   }
    270 }
    271 
    272 
    273 // Test that heap serialization is non-destructive.
    274 TEST(SerializeTwice) {
    275   if (!Snapshot::HaveASnapshotToStartFrom()) {
    276     Serializer::Enable();
    277     v8::V8::Initialize();
    278     Serialize();
    279     Serialize();
    280   }
    281 }
    282 
    283 
    284 //----------------------------------------------------------------------------
    285 // Tests that the heap can be deserialized.
    286 
    287 static void Deserialize() {
    288   CHECK(Snapshot::Initialize(FLAG_testing_serialization_file));
    289 }
    290 
    291 
    292 static void SanityCheck() {
    293   Isolate* isolate = Isolate::Current();
    294   v8::HandleScope scope(v8::Isolate::GetCurrent());
    295 #ifdef VERIFY_HEAP
    296   HEAP->Verify();
    297 #endif
    298   CHECK(isolate->global_object()->IsJSObject());
    299   CHECK(isolate->native_context()->IsContext());
    300   CHECK(HEAP->string_table()->IsStringTable());
    301   CHECK(!isolate->factory()->InternalizeOneByteString(
    302       STATIC_ASCII_VECTOR("Empty"))->IsFailure());
    303 }
    304 
    305 
    306 DEPENDENT_TEST(Deserialize, Serialize) {
    307   // The serialize-deserialize tests only work if the VM is built without
    308   // serialization.  That doesn't matter.  We don't need to be able to
    309   // serialize a snapshot in a VM that is booted from a snapshot.
    310   if (!Snapshot::HaveASnapshotToStartFrom()) {
    311     v8::Isolate* isolate = v8::Isolate::GetCurrent();
    312     v8::HandleScope scope(isolate);
    313     Deserialize();
    314 
    315     v8::Local<v8::Context> env = v8::Context::New(isolate);
    316     env->Enter();
    317 
    318     SanityCheck();
    319   }
    320 }
    321 
    322 
    323 DEPENDENT_TEST(DeserializeFromSecondSerialization, SerializeTwice) {
    324   if (!Snapshot::HaveASnapshotToStartFrom()) {
    325     v8::Isolate* isolate = v8::Isolate::GetCurrent();
    326     v8::HandleScope scope(isolate);
    327     Deserialize();
    328 
    329     v8::Local<v8::Context> env = v8::Context::New(isolate);
    330     env->Enter();
    331 
    332     SanityCheck();
    333   }
    334 }
    335 
    336 
    337 DEPENDENT_TEST(DeserializeAndRunScript2, Serialize) {
    338   if (!Snapshot::HaveASnapshotToStartFrom()) {
    339     v8::Isolate* isolate = v8::Isolate::GetCurrent();
    340     v8::HandleScope scope(isolate);
    341     Deserialize();
    342 
    343     v8::Local<v8::Context> env = v8::Context::New(isolate);
    344     env->Enter();
    345 
    346     const char* c_source = "\"1234\".length";
    347     v8::Local<v8::String> source = v8::String::New(c_source);
    348     v8::Local<v8::Script> script = v8::Script::Compile(source);
    349     CHECK_EQ(4, script->Run()->Int32Value());
    350   }
    351 }
    352 
    353 
    354 DEPENDENT_TEST(DeserializeFromSecondSerializationAndRunScript2,
    355                SerializeTwice) {
    356   if (!Snapshot::HaveASnapshotToStartFrom()) {
    357     v8::Isolate* isolate = v8::Isolate::GetCurrent();
    358     v8::HandleScope scope(isolate);
    359     Deserialize();
    360 
    361     v8::Local<v8::Context> env = v8::Context::New(isolate);
    362     env->Enter();
    363 
    364     const char* c_source = "\"1234\".length";
    365     v8::Local<v8::String> source = v8::String::New(c_source);
    366     v8::Local<v8::Script> script = v8::Script::Compile(source);
    367     CHECK_EQ(4, script->Run()->Int32Value());
    368   }
    369 }
    370 
    371 
    372 TEST(PartialSerialization) {
    373   if (!Snapshot::HaveASnapshotToStartFrom()) {
    374     Serializer::Enable();
    375     v8::V8::Initialize();
    376     Isolate* isolate = Isolate::Current();
    377     v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
    378     Heap* heap = isolate->heap();
    379 
    380     v8::Persistent<v8::Context> env;
    381     {
    382       HandleScope scope(isolate);
    383       env.Reset(v8_isolate, v8::Context::New(v8_isolate));
    384     }
    385     ASSERT(!env.IsEmpty());
    386     {
    387       v8::HandleScope handle_scope(v8_isolate);
    388       v8::Local<v8::Context>::New(v8_isolate, env)->Enter();
    389     }
    390     // Make sure all builtin scripts are cached.
    391     { HandleScope scope(isolate);
    392       for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
    393         isolate->bootstrapper()->NativesSourceLookup(i);
    394       }
    395     }
    396     heap->CollectAllGarbage(Heap::kNoGCFlags);
    397     heap->CollectAllGarbage(Heap::kNoGCFlags);
    398 
    399     Object* raw_foo;
    400     {
    401       v8::HandleScope handle_scope(v8_isolate);
    402       v8::Local<v8::String> foo = v8::String::New("foo");
    403       ASSERT(!foo.IsEmpty());
    404       raw_foo = *(v8::Utils::OpenHandle(*foo));
    405     }
    406 
    407     int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
    408     Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
    409     OS::SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
    410 
    411     {
    412       v8::HandleScope handle_scope(v8_isolate);
    413       v8::Local<v8::Context>::New(v8_isolate, env)->Exit();
    414     }
    415     env.Dispose(v8_isolate);
    416 
    417     FileByteSink startup_sink(startup_name.start());
    418     StartupSerializer startup_serializer(&startup_sink);
    419     startup_serializer.SerializeStrongReferences();
    420 
    421     FileByteSink partial_sink(FLAG_testing_serialization_file);
    422     PartialSerializer p_ser(&startup_serializer, &partial_sink);
    423     p_ser.Serialize(&raw_foo);
    424     startup_serializer.SerializeWeakReferences();
    425 
    426     partial_sink.WriteSpaceUsed(
    427         p_ser.CurrentAllocationAddress(NEW_SPACE),
    428         p_ser.CurrentAllocationAddress(OLD_POINTER_SPACE),
    429         p_ser.CurrentAllocationAddress(OLD_DATA_SPACE),
    430         p_ser.CurrentAllocationAddress(CODE_SPACE),
    431         p_ser.CurrentAllocationAddress(MAP_SPACE),
    432         p_ser.CurrentAllocationAddress(CELL_SPACE),
    433         p_ser.CurrentAllocationAddress(PROPERTY_CELL_SPACE));
    434 
    435     startup_sink.WriteSpaceUsed(
    436         startup_serializer.CurrentAllocationAddress(NEW_SPACE),
    437         startup_serializer.CurrentAllocationAddress(OLD_POINTER_SPACE),
    438         startup_serializer.CurrentAllocationAddress(OLD_DATA_SPACE),
    439         startup_serializer.CurrentAllocationAddress(CODE_SPACE),
    440         startup_serializer.CurrentAllocationAddress(MAP_SPACE),
    441         startup_serializer.CurrentAllocationAddress(CELL_SPACE),
    442         startup_serializer.CurrentAllocationAddress(PROPERTY_CELL_SPACE));
    443     startup_name.Dispose();
    444   }
    445 }
    446 
    447 
    448 static void ReserveSpaceForSnapshot(Deserializer* deserializer,
    449                                     const char* file_name) {
    450   int file_name_length = StrLength(file_name) + 10;
    451   Vector<char> name = Vector<char>::New(file_name_length + 1);
    452   OS::SNPrintF(name, "%s.size", file_name);
    453   FILE* fp = OS::FOpen(name.start(), "r");
    454   name.Dispose();
    455   int new_size, pointer_size, data_size, code_size, map_size, cell_size,
    456       property_cell_size;
    457 #ifdef _MSC_VER
    458   // Avoid warning about unsafe fscanf from MSVC.
    459   // Please note that this is only fine if %c and %s are not being used.
    460 #define fscanf fscanf_s
    461 #endif
    462   CHECK_EQ(1, fscanf(fp, "new %d\n", &new_size));
    463   CHECK_EQ(1, fscanf(fp, "pointer %d\n", &pointer_size));
    464   CHECK_EQ(1, fscanf(fp, "data %d\n", &data_size));
    465   CHECK_EQ(1, fscanf(fp, "code %d\n", &code_size));
    466   CHECK_EQ(1, fscanf(fp, "map %d\n", &map_size));
    467   CHECK_EQ(1, fscanf(fp, "cell %d\n", &cell_size));
    468   CHECK_EQ(1, fscanf(fp, "property cell %d\n", &property_cell_size));
    469 #ifdef _MSC_VER
    470 #undef fscanf
    471 #endif
    472   fclose(fp);
    473   deserializer->set_reservation(NEW_SPACE, new_size);
    474   deserializer->set_reservation(OLD_POINTER_SPACE, pointer_size);
    475   deserializer->set_reservation(OLD_DATA_SPACE, data_size);
    476   deserializer->set_reservation(CODE_SPACE, code_size);
    477   deserializer->set_reservation(MAP_SPACE, map_size);
    478   deserializer->set_reservation(CELL_SPACE, cell_size);
    479   deserializer->set_reservation(PROPERTY_CELL_SPACE, property_cell_size);
    480 }
    481 
    482 
    483 DEPENDENT_TEST(PartialDeserialization, PartialSerialization) {
    484   if (!Snapshot::IsEnabled()) {
    485     int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
    486     Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
    487     OS::SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
    488 
    489     CHECK(Snapshot::Initialize(startup_name.start()));
    490     startup_name.Dispose();
    491 
    492     const char* file_name = FLAG_testing_serialization_file;
    493 
    494     int snapshot_size = 0;
    495     byte* snapshot = ReadBytes(file_name, &snapshot_size);
    496 
    497     Object* root;
    498     {
    499       SnapshotByteSource source(snapshot, snapshot_size);
    500       Deserializer deserializer(&source);
    501       ReserveSpaceForSnapshot(&deserializer, file_name);
    502       deserializer.DeserializePartial(&root);
    503       CHECK(root->IsString());
    504     }
    505     v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
    506     Handle<Object> root_handle(root, Isolate::Current());
    507 
    508 
    509     Object* root2;
    510     {
    511       SnapshotByteSource source(snapshot, snapshot_size);
    512       Deserializer deserializer(&source);
    513       ReserveSpaceForSnapshot(&deserializer, file_name);
    514       deserializer.DeserializePartial(&root2);
    515       CHECK(root2->IsString());
    516       CHECK(*root_handle == root2);
    517     }
    518   }
    519 }
    520 
    521 
    522 TEST(ContextSerialization) {
    523   if (!Snapshot::HaveASnapshotToStartFrom()) {
    524     Serializer::Enable();
    525     v8::V8::Initialize();
    526     Isolate* isolate = Isolate::Current();
    527     v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
    528     Heap* heap = isolate->heap();
    529 
    530     v8::Persistent<v8::Context> env;
    531     {
    532       HandleScope scope(isolate);
    533       env.Reset(v8_isolate, v8::Context::New(v8_isolate));
    534     }
    535     ASSERT(!env.IsEmpty());
    536     {
    537       v8::HandleScope handle_scope(v8_isolate);
    538       v8::Local<v8::Context>::New(v8_isolate, env)->Enter();
    539     }
    540     // Make sure all builtin scripts are cached.
    541     { HandleScope scope(isolate);
    542       for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
    543         isolate->bootstrapper()->NativesSourceLookup(i);
    544       }
    545     }
    546     // If we don't do this then we end up with a stray root pointing at the
    547     // context even after we have disposed of env.
    548     heap->CollectAllGarbage(Heap::kNoGCFlags);
    549 
    550     int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
    551     Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
    552     OS::SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
    553 
    554     {
    555       v8::HandleScope handle_scope(v8_isolate);
    556       v8::Local<v8::Context>::New(v8_isolate, env)->Exit();
    557     }
    558 
    559     i::Object* raw_context = *v8::Utils::OpenPersistent(env);
    560 
    561     env.Dispose(v8_isolate);
    562 
    563     FileByteSink startup_sink(startup_name.start());
    564     StartupSerializer startup_serializer(&startup_sink);
    565     startup_serializer.SerializeStrongReferences();
    566 
    567     FileByteSink partial_sink(FLAG_testing_serialization_file);
    568     PartialSerializer p_ser(&startup_serializer, &partial_sink);
    569     p_ser.Serialize(&raw_context);
    570     startup_serializer.SerializeWeakReferences();
    571 
    572     partial_sink.WriteSpaceUsed(
    573         p_ser.CurrentAllocationAddress(NEW_SPACE),
    574         p_ser.CurrentAllocationAddress(OLD_POINTER_SPACE),
    575         p_ser.CurrentAllocationAddress(OLD_DATA_SPACE),
    576         p_ser.CurrentAllocationAddress(CODE_SPACE),
    577         p_ser.CurrentAllocationAddress(MAP_SPACE),
    578         p_ser.CurrentAllocationAddress(CELL_SPACE),
    579         p_ser.CurrentAllocationAddress(PROPERTY_CELL_SPACE));
    580 
    581     startup_sink.WriteSpaceUsed(
    582         startup_serializer.CurrentAllocationAddress(NEW_SPACE),
    583         startup_serializer.CurrentAllocationAddress(OLD_POINTER_SPACE),
    584         startup_serializer.CurrentAllocationAddress(OLD_DATA_SPACE),
    585         startup_serializer.CurrentAllocationAddress(CODE_SPACE),
    586         startup_serializer.CurrentAllocationAddress(MAP_SPACE),
    587         startup_serializer.CurrentAllocationAddress(CELL_SPACE),
    588         startup_serializer.CurrentAllocationAddress(PROPERTY_CELL_SPACE));
    589     startup_name.Dispose();
    590   }
    591 }
    592 
    593 
    594 DEPENDENT_TEST(ContextDeserialization, ContextSerialization) {
    595   if (!Snapshot::HaveASnapshotToStartFrom()) {
    596     int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
    597     Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
    598     OS::SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
    599 
    600     CHECK(Snapshot::Initialize(startup_name.start()));
    601     startup_name.Dispose();
    602 
    603     const char* file_name = FLAG_testing_serialization_file;
    604 
    605     int snapshot_size = 0;
    606     byte* snapshot = ReadBytes(file_name, &snapshot_size);
    607 
    608     Object* root;
    609     {
    610       SnapshotByteSource source(snapshot, snapshot_size);
    611       Deserializer deserializer(&source);
    612       ReserveSpaceForSnapshot(&deserializer, file_name);
    613       deserializer.DeserializePartial(&root);
    614       CHECK(root->IsContext());
    615     }
    616     v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
    617     Handle<Object> root_handle(root, Isolate::Current());
    618 
    619 
    620     Object* root2;
    621     {
    622       SnapshotByteSource source(snapshot, snapshot_size);
    623       Deserializer deserializer(&source);
    624       ReserveSpaceForSnapshot(&deserializer, file_name);
    625       deserializer.DeserializePartial(&root2);
    626       CHECK(root2->IsContext());
    627       CHECK(*root_handle != root2);
    628     }
    629   }
    630 }
    631 
    632 
    633 TEST(TestThatAlwaysSucceeds) {
    634 }
    635 
    636 
    637 TEST(TestThatAlwaysFails) {
    638   bool ArtificialFailure = false;
    639   CHECK(ArtificialFailure);
    640 }
    641 
    642 
    643 DEPENDENT_TEST(DependentTestThatAlwaysFails, TestThatAlwaysSucceeds) {
    644   bool ArtificialFailure2 = false;
    645   CHECK(ArtificialFailure2);
    646 }
    647