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