The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / test / cctest / test-serialize.cc @ f230a1cf

History | View | Annotate | Download (21.4 KB)

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::New(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::New(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::New("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.Dispose();
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.Dispose();
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
}