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