test-serialize.cc 21.4 KB
Newer Older
1
// Copyright 2007-2010 the V8 project authors. All rights reserved.
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <signal.h>

#include "sys/stat.h"
31

32 33 34 35 36 37 38 39 40
#include "v8.h"

#include "debug.h"
#include "ic-inl.h"
#include "runtime.h"
#include "serialize.h"
#include "scopeinfo.h"
#include "snapshot.h"
#include "cctest.h"
41 42
#include "spaces.h"
#include "objects.h"
43 44
#include "natives.h"
#include "bootstrapper.h"
45 46 47

using namespace v8::internal;

48 49 50 51 52 53 54 55 56 57 58 59 60
static const unsigned kCounters = 256;
static int local_counters[kCounters];
static const char* local_counter_names[kCounters];


static unsigned CounterHash(const char* s) {
  unsigned hash = 0;
  while (*++s) {
    hash |= hash << 5;
    hash += *s;
  }
  return hash;
}
61 62 63


// Callback receiver to track counters in test.
64
static int* counter_function(const char* name) {
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
  unsigned hash = CounterHash(name) % kCounters;
  unsigned original_hash = hash;
  USE(original_hash);
  while (true) {
    if (local_counter_names[hash] == name) {
      return &local_counters[hash];
    }
    if (local_counter_names[hash] == 0) {
      local_counter_names[hash] = name;
      return &local_counters[hash];
    }
    if (strcmp(local_counter_names[hash], name) == 0) {
      return &local_counters[hash];
    }
    hash = (hash + 1) % kCounters;
    ASSERT(hash != original_hash);  // Hash table has been filled up.
81 82 83 84 85 86
  }
}


template <class T>
static Address AddressOf(T id) {
87
  return ExternalReference(id, CcTest::i_isolate()).address();
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
}


template <class T>
static uint32_t Encode(const ExternalReferenceEncoder& encoder, T id) {
  return encoder.Encode(AddressOf(id));
}


static int make_code(TypeCode type, int id) {
  return static_cast<uint32_t>(type) << kReferenceTypeShift | id;
}


TEST(ExternalReferenceEncoder) {
103
  Isolate* isolate = CcTest::i_isolate();
104
  isolate->stats_table()->SetCounterFunction(counter_function);
105 106
  v8::V8::Initialize();

107
  ExternalReferenceEncoder encoder(isolate);
108 109
  CHECK_EQ(make_code(BUILTIN, Builtins::kArrayCode),
           Encode(encoder, Builtins::kArrayCode));
110
  CHECK_EQ(make_code(v8::internal::RUNTIME_FUNCTION, Runtime::kAbort),
111
           Encode(encoder, Runtime::kAbort));
112 113 114 115
  ExternalReference total_compile_size =
      ExternalReference(isolate->counters()->total_compile_size());
  CHECK_EQ(make_code(STATS_COUNTER, Counters::k_total_compile_size),
           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 120
           encoder.Encode(stack_limit_address.address()));
  ExternalReference real_stack_limit_address =
121
      ExternalReference::address_of_real_stack_limit(isolate);
122 123
  CHECK_EQ(make_code(UNCLASSIFIED, 5),
           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 130
           encoder.Encode(
               ExternalReference::new_space_start(isolate).address()));
131
  CHECK_EQ(make_code(UNCLASSIFIED, 3),
132 133
           encoder.Encode(
               ExternalReference::roots_array_start(isolate).address()));
134 135
  CHECK_EQ(make_code(UNCLASSIFIED, 52),
           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 143
  v8::V8::Initialize();

144
  ExternalReferenceDecoder decoder(isolate);
145 146
  CHECK_EQ(AddressOf(Builtins::kArrayCode),
           decoder.Decode(make_code(BUILTIN, Builtins::kArrayCode)));
147
  CHECK_EQ(AddressOf(Runtime::kAbort),
148 149
           decoder.Decode(make_code(v8::internal::RUNTIME_FUNCTION,
                                    Runtime::kAbort)));
150 151 152
  ExternalReference total_compile_size =
      ExternalReference(isolate->counters()->total_compile_size());
  CHECK_EQ(total_compile_size.address(),
153 154
           decoder.Decode(
               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 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
class FileByteSink : public SnapshotByteSink {
 public:
  explicit FileByteSink(const char* snapshot_file) {
    fp_ = OS::FOpen(snapshot_file, "wb");
    file_name_ = snapshot_file;
    if (fp_ == NULL) {
      PrintF("Unable to write to snapshot file \"%s\"\n", snapshot_file);
      exit(1);
    }
  }
  virtual ~FileByteSink() {
    if (fp_ != NULL) {
      fclose(fp_);
    }
  }
  virtual void Put(int byte, const char* description) {
    if (fp_ != NULL) {
      fputc(byte, fp_);
    }
  }
  virtual int Position() {
    return ftell(fp_);
  }
  void WriteSpaceUsed(
      int new_space_used,
      int pointer_space_used,
      int data_space_used,
      int code_space_used,
      int map_space_used,
198 199
      int cell_space_used,
      int property_cell_space_used);
200 201 202 203 204 205 206 207 208 209 210 211 212

 private:
  FILE* fp_;
  const char* file_name_;
};


void FileByteSink::WriteSpaceUsed(
      int new_space_used,
      int pointer_space_used,
      int data_space_used,
      int code_space_used,
      int map_space_used,
213 214
      int cell_space_used,
      int property_cell_space_used) {
215
  int file_name_length = StrLength(file_name_) + 10;
216 217 218
  Vector<char> name = Vector<char>::New(file_name_length + 1);
  OS::SNPrintF(name, "%s.size", file_name_);
  FILE* fp = OS::FOpen(name.start(), "w");
219
  name.Dispose();
220 221 222 223 224 225
  fprintf(fp, "new %d\n", new_space_used);
  fprintf(fp, "pointer %d\n", pointer_space_used);
  fprintf(fp, "data %d\n", data_space_used);
  fprintf(fp, "code %d\n", code_space_used);
  fprintf(fp, "map %d\n", map_space_used);
  fprintf(fp, "cell %d\n", cell_space_used);
226
  fprintf(fp, "property cell %d\n", property_cell_space_used);
227 228 229 230
  fclose(fp);
}


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 237 238 239 240 241

  file.WriteSpaceUsed(
      ser.CurrentAllocationAddress(NEW_SPACE),
      ser.CurrentAllocationAddress(OLD_POINTER_SPACE),
      ser.CurrentAllocationAddress(OLD_DATA_SPACE),
      ser.CurrentAllocationAddress(CODE_SPACE),
      ser.CurrentAllocationAddress(MAP_SPACE),
242 243
      ser.CurrentAllocationAddress(CELL_SPACE),
      ser.CurrentAllocationAddress(PROPERTY_CELL_SPACE));
244

245 246 247 248
  return true;
}


249
static void Serialize() {
250 251 252 253
  // We have to create one context.  One reason for this is so that the builtins
  // can be loaded from v8natives.js and their addresses can be processed.  This
  // will clear the pending fixups array, which would otherwise contain GC roots
  // that would confuse the serialization/deserialization process.
254
  v8::Isolate* isolate = CcTest::isolate();
255 256 257 258
  {
    v8::HandleScope scope(isolate);
    v8::Context::New(isolate);
  }
259 260 261 262

  Isolate* internal_isolate = CcTest::i_isolate();
  internal_isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "serialize");
  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 271 272
    v8::V8::Initialize();
    Serialize();
  }
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 281 282 283
    v8::V8::Initialize();
    Serialize();
    Serialize();
  }
284 285 286
}


287 288 289 290
//----------------------------------------------------------------------------
// Tests that the heap can be deserialized.

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 302
  CHECK(isolate->global_object()->IsJSObject());
  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 311 312
  // The serialize-deserialize tests only work if the VM is built without
  // serialization.  That doesn't matter.  We don't need to be able to
  // 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 322
    SanityCheck();
  }
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 336
    SanityCheck();
  }
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 350 351 352 353
    const char* c_source = "\"1234\".length";
    v8::Local<v8::String> source = v8::String::New(c_source);
    v8::Local<v8::Script> script = v8::Script::Compile(source);
    CHECK_EQ(4, script->Run()->Int32Value());
  }
354 355 356
}


357 358
DEPENDENT_TEST(DeserializeFromSecondSerializationAndRunScript2,
               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 368 369 370 371
    const char* c_source = "\"1234\".length";
    v8::Local<v8::String> source = v8::String::New(c_source);
    v8::Local<v8::Script> script = v8::Script::Compile(source);
    CHECK_EQ(4, script->Run()->Int32Value());
  }
372 373 374
}


375
TEST(PartialSerialization) {
376
  if (!Snapshot::HaveASnapshotToStartFrom()) {
377
    Isolate* isolate = CcTest::i_isolate();
378 379
    Serializer::Enable(isolate);
    v8::V8::Initialize();
380
    v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
381
    Heap* heap = isolate->heap();
382

383 384 385
    v8::Persistent<v8::Context> env;
    {
      HandleScope scope(isolate);
386
      env.Reset(v8_isolate, v8::Context::New(v8_isolate));
387
    }
388
    ASSERT(!env.IsEmpty());
389 390 391 392
    {
      v8::HandleScope handle_scope(v8_isolate);
      v8::Local<v8::Context>::New(v8_isolate, env)->Enter();
    }
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 400
    heap->CollectAllGarbage(Heap::kNoGCFlags);
    heap->CollectAllGarbage(Heap::kNoGCFlags);
401

402 403
    Object* raw_foo;
    {
404
      v8::HandleScope handle_scope(v8_isolate);
405 406 407 408
      v8::Local<v8::String> foo = v8::String::New("foo");
      ASSERT(!foo.IsEmpty());
      raw_foo = *(v8::Utils::OpenHandle(*foo));
    }
409

410 411 412
    int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
    Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
    OS::SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
413

414 415 416 417
    {
      v8::HandleScope handle_scope(v8_isolate);
      v8::Local<v8::Context>::New(v8_isolate, env)->Exit();
    }
418
    env.Dispose();
419

420
    FileByteSink startup_sink(startup_name.start());
421
    StartupSerializer startup_serializer(isolate, &startup_sink);
422 423 424
    startup_serializer.SerializeStrongReferences();

    FileByteSink partial_sink(FLAG_testing_serialization_file);
425
    PartialSerializer p_ser(isolate, &startup_serializer, &partial_sink);
426 427
    p_ser.Serialize(&raw_foo);
    startup_serializer.SerializeWeakReferences();
428

429 430 431 432 433 434
    partial_sink.WriteSpaceUsed(
        p_ser.CurrentAllocationAddress(NEW_SPACE),
        p_ser.CurrentAllocationAddress(OLD_POINTER_SPACE),
        p_ser.CurrentAllocationAddress(OLD_DATA_SPACE),
        p_ser.CurrentAllocationAddress(CODE_SPACE),
        p_ser.CurrentAllocationAddress(MAP_SPACE),
435 436
        p_ser.CurrentAllocationAddress(CELL_SPACE),
        p_ser.CurrentAllocationAddress(PROPERTY_CELL_SPACE));
437 438 439 440 441 442 443

    startup_sink.WriteSpaceUsed(
        startup_serializer.CurrentAllocationAddress(NEW_SPACE),
        startup_serializer.CurrentAllocationAddress(OLD_POINTER_SPACE),
        startup_serializer.CurrentAllocationAddress(OLD_DATA_SPACE),
        startup_serializer.CurrentAllocationAddress(CODE_SPACE),
        startup_serializer.CurrentAllocationAddress(MAP_SPACE),
444 445
        startup_serializer.CurrentAllocationAddress(CELL_SPACE),
        startup_serializer.CurrentAllocationAddress(PROPERTY_CELL_SPACE));
446
    startup_name.Dispose();
447
  }
448 449 450
}


451 452
static void ReserveSpaceForSnapshot(Deserializer* deserializer,
                                    const char* file_name) {
453
  int file_name_length = StrLength(file_name) + 10;
454 455
  Vector<char> name = Vector<char>::New(file_name_length + 1);
  OS::SNPrintF(name, "%s.size", file_name);
456
  FILE* fp = OS::FOpen(name.start(), "r");
457
  name.Dispose();
458 459
  int new_size, pointer_size, data_size, code_size, map_size, cell_size,
      property_cell_size;
460 461 462 463 464
#ifdef _MSC_VER
  // Avoid warning about unsafe fscanf from MSVC.
  // Please note that this is only fine if %c and %s are not being used.
#define fscanf fscanf_s
#endif
465 466 467 468 469 470
  CHECK_EQ(1, fscanf(fp, "new %d\n", &new_size));
  CHECK_EQ(1, fscanf(fp, "pointer %d\n", &pointer_size));
  CHECK_EQ(1, fscanf(fp, "data %d\n", &data_size));
  CHECK_EQ(1, fscanf(fp, "code %d\n", &code_size));
  CHECK_EQ(1, fscanf(fp, "map %d\n", &map_size));
  CHECK_EQ(1, fscanf(fp, "cell %d\n", &cell_size));
471
  CHECK_EQ(1, fscanf(fp, "property cell %d\n", &property_cell_size));
472 473 474
#ifdef _MSC_VER
#undef fscanf
#endif
475
  fclose(fp);
476 477 478 479 480 481
  deserializer->set_reservation(NEW_SPACE, new_size);
  deserializer->set_reservation(OLD_POINTER_SPACE, pointer_size);
  deserializer->set_reservation(OLD_DATA_SPACE, data_size);
  deserializer->set_reservation(CODE_SPACE, code_size);
  deserializer->set_reservation(MAP_SPACE, map_size);
  deserializer->set_reservation(CELL_SPACE, cell_size);
482
  deserializer->set_reservation(PROPERTY_CELL_SPACE, property_cell_size);
483
}
484

485 486 487 488 489 490 491 492

DEPENDENT_TEST(PartialDeserialization, PartialSerialization) {
  if (!Snapshot::IsEnabled()) {
    int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
    Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
    OS::SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);

    CHECK(Snapshot::Initialize(startup_name.start()));
493
    startup_name.Dispose();
494 495 496 497 498 499

    const char* file_name = FLAG_testing_serialization_file;

    int snapshot_size = 0;
    byte* snapshot = ReadBytes(file_name, &snapshot_size);

500
    Isolate* isolate = CcTest::i_isolate();
501 502 503 504
    Object* root;
    {
      SnapshotByteSource source(snapshot, snapshot_size);
      Deserializer deserializer(&source);
505
      ReserveSpaceForSnapshot(&deserializer, file_name);
506
      deserializer.DeserializePartial(isolate, &root);
507 508
      CHECK(root->IsString());
    }
509 510
    HandleScope handle_scope(isolate);
    Handle<Object> root_handle(root, isolate);
511

512 513 514 515 516

    Object* root2;
    {
      SnapshotByteSource source(snapshot, snapshot_size);
      Deserializer deserializer(&source);
517
      ReserveSpaceForSnapshot(&deserializer, file_name);
518
      deserializer.DeserializePartial(isolate, &root2);
519 520 521
      CHECK(root2->IsString());
      CHECK(*root_handle == root2);
    }
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 535 536
    v8::Persistent<v8::Context> env;
    {
      HandleScope scope(isolate);
537
      env.Reset(v8_isolate, v8::Context::New(v8_isolate));
538
    }
539
    ASSERT(!env.IsEmpty());
540 541 542 543
    {
      v8::HandleScope handle_scope(v8_isolate);
      v8::Local<v8::Context>::New(v8_isolate, env)->Enter();
    }
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 551
    // If we don't do this then we end up with a stray root pointing at the
    // context even after we have disposed of env.
552
    heap->CollectAllGarbage(Heap::kNoGCFlags);
553

554 555 556
    int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
    Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
    OS::SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);
557

558 559 560 561
    {
      v8::HandleScope handle_scope(v8_isolate);
      v8::Local<v8::Context>::New(v8_isolate, env)->Exit();
    }
562

563
    i::Object* raw_context = *v8::Utils::OpenPersistent(env);
564

565
    env.Dispose();
566

567
    FileByteSink startup_sink(startup_name.start());
568
    StartupSerializer startup_serializer(isolate, &startup_sink);
569 570 571
    startup_serializer.SerializeStrongReferences();

    FileByteSink partial_sink(FLAG_testing_serialization_file);
572
    PartialSerializer p_ser(isolate, &startup_serializer, &partial_sink);
573 574
    p_ser.Serialize(&raw_context);
    startup_serializer.SerializeWeakReferences();
575

576 577 578 579 580 581
    partial_sink.WriteSpaceUsed(
        p_ser.CurrentAllocationAddress(NEW_SPACE),
        p_ser.CurrentAllocationAddress(OLD_POINTER_SPACE),
        p_ser.CurrentAllocationAddress(OLD_DATA_SPACE),
        p_ser.CurrentAllocationAddress(CODE_SPACE),
        p_ser.CurrentAllocationAddress(MAP_SPACE),
582 583
        p_ser.CurrentAllocationAddress(CELL_SPACE),
        p_ser.CurrentAllocationAddress(PROPERTY_CELL_SPACE));
584 585 586 587 588 589 590

    startup_sink.WriteSpaceUsed(
        startup_serializer.CurrentAllocationAddress(NEW_SPACE),
        startup_serializer.CurrentAllocationAddress(OLD_POINTER_SPACE),
        startup_serializer.CurrentAllocationAddress(OLD_DATA_SPACE),
        startup_serializer.CurrentAllocationAddress(CODE_SPACE),
        startup_serializer.CurrentAllocationAddress(MAP_SPACE),
591 592
        startup_serializer.CurrentAllocationAddress(CELL_SPACE),
        startup_serializer.CurrentAllocationAddress(PROPERTY_CELL_SPACE));
593
    startup_name.Dispose();
594
  }
595 596 597 598
}


DEPENDENT_TEST(ContextDeserialization, ContextSerialization) {
599
  if (!Snapshot::HaveASnapshotToStartFrom()) {
600 601 602 603 604
    int file_name_length = StrLength(FLAG_testing_serialization_file) + 10;
    Vector<char> startup_name = Vector<char>::New(file_name_length + 1);
    OS::SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file);

    CHECK(Snapshot::Initialize(startup_name.start()));
605
    startup_name.Dispose();
606 607 608 609 610 611

    const char* file_name = FLAG_testing_serialization_file;

    int snapshot_size = 0;
    byte* snapshot = ReadBytes(file_name, &snapshot_size);

612
    Isolate* isolate = CcTest::i_isolate();
613 614 615 616
    Object* root;
    {
      SnapshotByteSource source(snapshot, snapshot_size);
      Deserializer deserializer(&source);
617
      ReserveSpaceForSnapshot(&deserializer, file_name);
618
      deserializer.DeserializePartial(isolate, &root);
619 620
      CHECK(root->IsContext());
    }
621 622
    HandleScope handle_scope(isolate);
    Handle<Object> root_handle(root, isolate);
623

624 625 626 627 628

    Object* root2;
    {
      SnapshotByteSource source(snapshot, snapshot_size);
      Deserializer deserializer(&source);
629
      ReserveSpaceForSnapshot(&deserializer, file_name);
630
      deserializer.DeserializePartial(isolate, &root2);
631 632 633
      CHECK(root2->IsContext());
      CHECK(*root_handle != root2);
    }
634
  }
635 636 637
}


638 639 640 641 642 643 644 645 646 647 648 649 650 651
TEST(TestThatAlwaysSucceeds) {
}


TEST(TestThatAlwaysFails) {
  bool ArtificialFailure = false;
  CHECK(ArtificialFailure);
}


DEPENDENT_TEST(DependentTestThatAlwaysFails, TestThatAlwaysSucceeds) {
  bool ArtificialFailure2 = false;
  CHECK(ArtificialFailure2);
}