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