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, CcTest::i_isolate()).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 = CcTest::i_isolate();
    104   isolate->stats_table()->SetCounterFunction(counter_function);
    105   v8::V8::Initialize();
    106 
    107   ExternalReferenceEncoder encoder(isolate);
    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 = CcTest::i_isolate();
    141   isolate->stats_table()->SetCounterFunction(counter_function);
    142   v8::V8::Initialize();
    143 
    144   ExternalReferenceDecoder decoder(isolate);
    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(Isolate* isolate, const char* snapshot_file) {
    232   FileByteSink file(snapshot_file);
    233   StartupSerializer ser(isolate, &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   v8::Isolate* isolate = CcTest::isolate();
    255   {
    256     v8::HandleScope scope(isolate);
    257     v8::Context::New(isolate);
    258   }
    259 
    260   Isolate* internal_isolate = CcTest::i_isolate();
    261   internal_isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "serialize");
    262   WriteToFile(internal_isolate, FLAG_testing_serialization_file);
    263 }
    264 
    265 
    266 // Test that the whole heap can be serialized.
    267 TEST(Serialize) {
    268   if (!Snapshot::HaveASnapshotToStartFrom()) {
    269     Serializer::Enable(CcTest::i_isolate());
    270     v8::V8::Initialize();
    271     Serialize();
    272   }
    273 }
    274 
    275 
    276 // Test that heap serialization is non-destructive.
    277 TEST(SerializeTwice) {
    278   if (!Snapshot::HaveASnapshotToStartFrom()) {
    279     Serializer::Enable(CcTest::i_isolate());
    280     v8::V8::Initialize();
    281     Serialize();
    282     Serialize();
    283   }
    284 }
    285 
    286 
    287 //----------------------------------------------------------------------------
    288 // Tests that the heap can be deserialized.
    289 
    290 static void Deserialize() {
    291   CHECK(Snapshot::Initialize(FLAG_testing_serialization_file));
    292 }
    293 
    294 
    295 static void SanityCheck() {
    296   Isolate* isolate = CcTest::i_isolate();
    297   v8::HandleScope scope(CcTest::isolate());
    298 #ifdef VERIFY_HEAP
    299   CcTest::heap()->Verify();
    300 #endif
    301   CHECK(isolate->global_object()->IsJSObject());
    302   CHECK(isolate->native_context()->IsContext());
    303   CHECK(CcTest::heap()->string_table()->IsStringTable());
    304   CHECK(!isolate->factory()->InternalizeOneByteString(
    305       STATIC_ASCII_VECTOR("Empty"))->IsFailure());
    306 }
    307 
    308 
    309 DEPENDENT_TEST(Deserialize, Serialize) {
    310   // The serialize-deserialize tests only work if the VM is built without
    311   // serialization.  That doesn't matter.  We don't need to be able to
    312   // serialize a snapshot in a VM that is booted from a snapshot.
    313   if (!Snapshot::HaveASnapshotToStartFrom()) {
    314     v8::Isolate* isolate = CcTest::isolate();
    315     v8::HandleScope scope(isolate);
    316     Deserialize();
    317 
    318     v8::Local<v8::Context> env = v8::Context::New(isolate);
    319     env->Enter();
    320 
    321     SanityCheck();
    322   }
    323 }
    324 
    325 
    326 DEPENDENT_TEST(DeserializeFromSecondSerialization, SerializeTwice) {
    327   if (!Snapshot::HaveASnapshotToStartFrom()) {
    328     v8::Isolate* isolate = CcTest::isolate();
    329     v8::HandleScope scope(isolate);
    330     Deserialize();
    331 
    332     v8::Local<v8::Context> env = v8::Context::New(isolate);
    333     env->Enter();
    334 
    335     SanityCheck();
    336   }
    337 }
    338 
    339 
    340 DEPENDENT_TEST(DeserializeAndRunScript2, Serialize) {
    341   if (!Snapshot::HaveASnapshotToStartFrom()) {
    342     v8::Isolate* isolate = CcTest::isolate();
    343     v8::HandleScope scope(isolate);
    344     Deserialize();
    345 
    346     v8::Local<v8::Context> env = v8::Context::New(isolate);
    347     env->Enter();
    348 
    349     const char* c_source = "\"1234\".length";
    350     v8::Local<v8::String> source = v8::String::NewFromUtf8(isolate, c_source);
    351     v8::Local<v8::Script> script = v8::Script::Compile(source);
    352     CHECK_EQ(4, script->Run()->Int32Value());
    353   }
    354 }
    355 
    356 
    357 DEPENDENT_TEST(DeserializeFromSecondSerializationAndRunScript2,
    358                SerializeTwice) {
    359   if (!Snapshot::HaveASnapshotToStartFrom()) {
    360     v8::Isolate* isolate = CcTest::isolate();
    361     v8::HandleScope scope(isolate);
    362     Deserialize();
    363 
    364     v8::Local<v8::Context> env = v8::Context::New(isolate);
    365     env->Enter();
    366 
    367     const char* c_source = "\"1234\".length";
    368     v8::Local<v8::String> source = v8::String::NewFromUtf8(isolate, c_source);
    369     v8::Local<v8::Script> script = v8::Script::Compile(source);
    370     CHECK_EQ(4, script->Run()->Int32Value());
    371   }
    372 }
    373 
    374 
    375 TEST(PartialSerialization) {
    376   if (!Snapshot::HaveASnapshotToStartFrom()) {
    377     Isolate* isolate = CcTest::i_isolate();
    378     Serializer::Enable(isolate);
    379     v8::V8::Initialize();
    380     v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
    381     Heap* heap = isolate->heap();
    382 
    383     v8::Persistent<v8::Context> env;
    384     {
    385       HandleScope scope(isolate);
    386       env.Reset(v8_isolate, v8::Context::New(v8_isolate));
    387     }
    388     ASSERT(!env.IsEmpty());
    389     {
    390       v8::HandleScope handle_scope(v8_isolate);
    391       v8::Local<v8::Context>::New(v8_isolate, env)->Enter();
    392     }
    393     // Make sure all builtin scripts are cached.
    394     { HandleScope scope(isolate);
    395       for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
    396         isolate->bootstrapper()->NativesSourceLookup(i);
    397       }
    398     }
    399     heap->CollectAllGarbage(Heap::kNoGCFlags);
    400     heap->CollectAllGarbage(Heap::kNoGCFlags);
    401 
    402     Object* raw_foo;
    403     {
    404       v8::HandleScope handle_scope(v8_isolate);
    405       v8::Local<v8::String> foo = v8::String::NewFromUtf8(v8_isolate, "foo");
    406       ASSERT(!foo.IsEmpty());
    407       raw_foo = *(v8::Utils::OpenHandle(*foo));
    408     }
    409 
    410     int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
    411     Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
    412     OS::SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
    413 
    414     {
    415       v8::HandleScope handle_scope(v8_isolate);
    416       v8::Local<v8::Context>::New(v8_isolate, env)->Exit();
    417     }
    418     env.Reset();
    419 
    420     FileByteSink startup_sink(startup_name.start());
    421     StartupSerializer startup_serializer(isolate, &startup_sink);
    422     startup_serializer.SerializeStrongReferences();
    423 
    424     FileByteSink partial_sink(FLAG_testing_serialization_file);
    425     PartialSerializer p_ser(isolate, &startup_serializer, &partial_sink);
    426     p_ser.Serialize(&raw_foo);
    427     startup_serializer.SerializeWeakReferences();
    428 
    429     partial_sink.WriteSpaceUsed(
    430         p_ser.CurrentAllocationAddress(NEW_SPACE),
    431         p_ser.CurrentAllocationAddress(OLD_POINTER_SPACE),
    432         p_ser.CurrentAllocationAddress(OLD_DATA_SPACE),
    433         p_ser.CurrentAllocationAddress(CODE_SPACE),
    434         p_ser.CurrentAllocationAddress(MAP_SPACE),
    435         p_ser.CurrentAllocationAddress(CELL_SPACE),
    436         p_ser.CurrentAllocationAddress(PROPERTY_CELL_SPACE));
    437 
    438     startup_sink.WriteSpaceUsed(
    439         startup_serializer.CurrentAllocationAddress(NEW_SPACE),
    440         startup_serializer.CurrentAllocationAddress(OLD_POINTER_SPACE),
    441         startup_serializer.CurrentAllocationAddress(OLD_DATA_SPACE),
    442         startup_serializer.CurrentAllocationAddress(CODE_SPACE),
    443         startup_serializer.CurrentAllocationAddress(MAP_SPACE),
    444         startup_serializer.CurrentAllocationAddress(CELL_SPACE),
    445         startup_serializer.CurrentAllocationAddress(PROPERTY_CELL_SPACE));
    446     startup_name.Dispose();
    447   }
    448 }
    449 
    450 
    451 static void ReserveSpaceForSnapshot(Deserializer* deserializer,
    452                                     const char* file_name) {
    453   int file_name_length = StrLength(file_name) + 10;
    454   Vector<char> name = Vector<char>::New(file_name_length + 1);
    455   OS::SNPrintF(name, "%s.size", file_name);
    456   FILE* fp = OS::FOpen(name.start(), "r");
    457   name.Dispose();
    458   int new_size, pointer_size, data_size, code_size, map_size, cell_size,
    459       property_cell_size;
    460 #ifdef _MSC_VER
    461   // Avoid warning about unsafe fscanf from MSVC.
    462   // Please note that this is only fine if %c and %s are not being used.
    463 #define fscanf fscanf_s
    464 #endif
    465   CHECK_EQ(1, fscanf(fp, "new %d\n", &new_size));
    466   CHECK_EQ(1, fscanf(fp, "pointer %d\n", &pointer_size));
    467   CHECK_EQ(1, fscanf(fp, "data %d\n", &data_size));
    468   CHECK_EQ(1, fscanf(fp, "code %d\n", &code_size));
    469   CHECK_EQ(1, fscanf(fp, "map %d\n", &map_size));
    470   CHECK_EQ(1, fscanf(fp, "cell %d\n", &cell_size));
    471   CHECK_EQ(1, fscanf(fp, "property cell %d\n", &property_cell_size));
    472 #ifdef _MSC_VER
    473 #undef fscanf
    474 #endif
    475   fclose(fp);
    476   deserializer->set_reservation(NEW_SPACE, new_size);
    477   deserializer->set_reservation(OLD_POINTER_SPACE, pointer_size);
    478   deserializer->set_reservation(OLD_DATA_SPACE, data_size);
    479   deserializer->set_reservation(CODE_SPACE, code_size);
    480   deserializer->set_reservation(MAP_SPACE, map_size);
    481   deserializer->set_reservation(CELL_SPACE, cell_size);
    482   deserializer->set_reservation(PROPERTY_CELL_SPACE, property_cell_size);
    483 }
    484 
    485 
    486 DEPENDENT_TEST(PartialDeserialization, PartialSerialization) {
    487   if (!Snapshot::IsEnabled()) {
    488     int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
    489     Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
    490     OS::SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
    491 
    492     CHECK(Snapshot::Initialize(startup_name.start()));
    493     startup_name.Dispose();
    494 
    495     const char* file_name = FLAG_testing_serialization_file;
    496 
    497     int snapshot_size = 0;
    498     byte* snapshot = ReadBytes(file_name, &snapshot_size);
    499 
    500     Isolate* isolate = CcTest::i_isolate();
    501     Object* root;
    502     {
    503       SnapshotByteSource source(snapshot, snapshot_size);
    504       Deserializer deserializer(&source);
    505       ReserveSpaceForSnapshot(&deserializer, file_name);
    506       deserializer.DeserializePartial(isolate, &root);
    507       CHECK(root->IsString());
    508     }
    509     HandleScope handle_scope(isolate);
    510     Handle<Object> root_handle(root, isolate);
    511 
    512 
    513     Object* root2;
    514     {
    515       SnapshotByteSource source(snapshot, snapshot_size);
    516       Deserializer deserializer(&source);
    517       ReserveSpaceForSnapshot(&deserializer, file_name);
    518       deserializer.DeserializePartial(isolate, &root2);
    519       CHECK(root2->IsString());
    520       CHECK(*root_handle == root2);
    521     }
    522   }
    523 }
    524 
    525 
    526 TEST(ContextSerialization) {
    527   if (!Snapshot::HaveASnapshotToStartFrom()) {
    528     Isolate* isolate = CcTest::i_isolate();
    529     Serializer::Enable(isolate);
    530     v8::V8::Initialize();
    531     v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
    532     Heap* heap = isolate->heap();
    533 
    534     v8::Persistent<v8::Context> env;
    535     {
    536       HandleScope scope(isolate);
    537       env.Reset(v8_isolate, v8::Context::New(v8_isolate));
    538     }
    539     ASSERT(!env.IsEmpty());
    540     {
    541       v8::HandleScope handle_scope(v8_isolate);
    542       v8::Local<v8::Context>::New(v8_isolate, env)->Enter();
    543     }
    544     // Make sure all builtin scripts are cached.
    545     { HandleScope scope(isolate);
    546       for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
    547         isolate->bootstrapper()->NativesSourceLookup(i);
    548       }
    549     }
    550     // If we don't do this then we end up with a stray root pointing at the
    551     // context even after we have disposed of env.
    552     heap->CollectAllGarbage(Heap::kNoGCFlags);
    553 
    554     int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
    555     Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
    556     OS::SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
    557 
    558     {
    559       v8::HandleScope handle_scope(v8_isolate);
    560       v8::Local<v8::Context>::New(v8_isolate, env)->Exit();
    561     }
    562 
    563     i::Object* raw_context = *v8::Utils::OpenPersistent(env);
    564 
    565     env.Reset();
    566 
    567     FileByteSink startup_sink(startup_name.start());
    568     StartupSerializer startup_serializer(isolate, &startup_sink);
    569     startup_serializer.SerializeStrongReferences();
    570 
    571     FileByteSink partial_sink(FLAG_testing_serialization_file);
    572     PartialSerializer p_ser(isolate, &startup_serializer, &partial_sink);
    573     p_ser.Serialize(&raw_context);
    574     startup_serializer.SerializeWeakReferences();
    575 
    576     partial_sink.WriteSpaceUsed(
    577         p_ser.CurrentAllocationAddress(NEW_SPACE),
    578         p_ser.CurrentAllocationAddress(OLD_POINTER_SPACE),
    579         p_ser.CurrentAllocationAddress(OLD_DATA_SPACE),
    580         p_ser.CurrentAllocationAddress(CODE_SPACE),
    581         p_ser.CurrentAllocationAddress(MAP_SPACE),
    582         p_ser.CurrentAllocationAddress(CELL_SPACE),
    583         p_ser.CurrentAllocationAddress(PROPERTY_CELL_SPACE));
    584 
    585     startup_sink.WriteSpaceUsed(
    586         startup_serializer.CurrentAllocationAddress(NEW_SPACE),
    587         startup_serializer.CurrentAllocationAddress(OLD_POINTER_SPACE),
    588         startup_serializer.CurrentAllocationAddress(OLD_DATA_SPACE),
    589         startup_serializer.CurrentAllocationAddress(CODE_SPACE),
    590         startup_serializer.CurrentAllocationAddress(MAP_SPACE),
    591         startup_serializer.CurrentAllocationAddress(CELL_SPACE),
    592         startup_serializer.CurrentAllocationAddress(PROPERTY_CELL_SPACE));
    593     startup_name.Dispose();
    594   }
    595 }
    596 
    597 
    598 DEPENDENT_TEST(ContextDeserialization, ContextSerialization) {
    599   if (!Snapshot::HaveASnapshotToStartFrom()) {
    600     int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
    601     Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
    602     OS::SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
    603 
    604     CHECK(Snapshot::Initialize(startup_name.start()));
    605     startup_name.Dispose();
    606 
    607     const char* file_name = FLAG_testing_serialization_file;
    608 
    609     int snapshot_size = 0;
    610     byte* snapshot = ReadBytes(file_name, &snapshot_size);
    611 
    612     Isolate* isolate = CcTest::i_isolate();
    613     Object* root;
    614     {
    615       SnapshotByteSource source(snapshot, snapshot_size);
    616       Deserializer deserializer(&source);
    617       ReserveSpaceForSnapshot(&deserializer, file_name);
    618       deserializer.DeserializePartial(isolate, &root);
    619       CHECK(root->IsContext());
    620     }
    621     HandleScope handle_scope(isolate);
    622     Handle<Object> root_handle(root, isolate);
    623 
    624 
    625     Object* root2;
    626     {
    627       SnapshotByteSource source(snapshot, snapshot_size);
    628       Deserializer deserializer(&source);
    629       ReserveSpaceForSnapshot(&deserializer, file_name);
    630       deserializer.DeserializePartial(isolate, &root2);
    631       CHECK(root2->IsContext());
    632       CHECK(*root_handle != root2);
    633     }
    634   }
    635 }
    636 
    637 
    638 TEST(TestThatAlwaysSucceeds) {
    639 }
    640 
    641 
    642 TEST(TestThatAlwaysFails) {
    643   bool ArtificialFailure = false;
    644   CHECK(ArtificialFailure);
    645 }
    646 
    647 
    648 DEPENDENT_TEST(DependentTestThatAlwaysFails, TestThatAlwaysSucceeds) {
    649   bool ArtificialFailure2 = false;
    650   CHECK(ArtificialFailure2);
    651 }
    652