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, i::Isolate::Current()).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 = i::Isolate::Current(); 104 isolate->stats_table()->SetCounterFunction(counter_function); 105 v8::V8::Initialize(); 106 107 ExternalReferenceEncoder encoder; 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 = i::Isolate::Current(); 141 isolate->stats_table()->SetCounterFunction(counter_function); 142 v8::V8::Initialize(); 143 144 ExternalReferenceDecoder decoder; 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(const char* snapshot_file) { 232 FileByteSink file(snapshot_file); 233 StartupSerializer ser(&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 { 255 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 256 v8::HandleScope scope(isolate); 257 v8::Context::New(isolate); 258 } 259 WriteToFile(FLAG_testing_serialization_file); 260 } 261 262 263 // Test that the whole heap can be serialized. 264 TEST(Serialize) { 265 if (!Snapshot::HaveASnapshotToStartFrom()) { 266 Serializer::Enable(); 267 v8::V8::Initialize(); 268 Serialize(); 269 } 270 } 271 272 273 // Test that heap serialization is non-destructive. 274 TEST(SerializeTwice) { 275 if (!Snapshot::HaveASnapshotToStartFrom()) { 276 Serializer::Enable(); 277 v8::V8::Initialize(); 278 Serialize(); 279 Serialize(); 280 } 281 } 282 283 284 //---------------------------------------------------------------------------- 285 // Tests that the heap can be deserialized. 286 287 static void Deserialize() { 288 CHECK(Snapshot::Initialize(FLAG_testing_serialization_file)); 289 } 290 291 292 static void SanityCheck() { 293 Isolate* isolate = Isolate::Current(); 294 v8::HandleScope scope(v8::Isolate::GetCurrent()); 295 #ifdef VERIFY_HEAP 296 HEAP->Verify(); 297 #endif 298 CHECK(isolate->global_object()->IsJSObject()); 299 CHECK(isolate->native_context()->IsContext()); 300 CHECK(HEAP->string_table()->IsStringTable()); 301 CHECK(!isolate->factory()->InternalizeOneByteString( 302 STATIC_ASCII_VECTOR("Empty"))->IsFailure()); 303 } 304 305 306 DEPENDENT_TEST(Deserialize, Serialize) { 307 // The serialize-deserialize tests only work if the VM is built without 308 // serialization. That doesn't matter. We don't need to be able to 309 // serialize a snapshot in a VM that is booted from a snapshot. 310 if (!Snapshot::HaveASnapshotToStartFrom()) { 311 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 312 v8::HandleScope scope(isolate); 313 Deserialize(); 314 315 v8::Local<v8::Context> env = v8::Context::New(isolate); 316 env->Enter(); 317 318 SanityCheck(); 319 } 320 } 321 322 323 DEPENDENT_TEST(DeserializeFromSecondSerialization, SerializeTwice) { 324 if (!Snapshot::HaveASnapshotToStartFrom()) { 325 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 326 v8::HandleScope scope(isolate); 327 Deserialize(); 328 329 v8::Local<v8::Context> env = v8::Context::New(isolate); 330 env->Enter(); 331 332 SanityCheck(); 333 } 334 } 335 336 337 DEPENDENT_TEST(DeserializeAndRunScript2, Serialize) { 338 if (!Snapshot::HaveASnapshotToStartFrom()) { 339 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 340 v8::HandleScope scope(isolate); 341 Deserialize(); 342 343 v8::Local<v8::Context> env = v8::Context::New(isolate); 344 env->Enter(); 345 346 const char* c_source = "\"1234\".length"; 347 v8::Local<v8::String> source = v8::String::New(c_source); 348 v8::Local<v8::Script> script = v8::Script::Compile(source); 349 CHECK_EQ(4, script->Run()->Int32Value()); 350 } 351 } 352 353 354 DEPENDENT_TEST(DeserializeFromSecondSerializationAndRunScript2, 355 SerializeTwice) { 356 if (!Snapshot::HaveASnapshotToStartFrom()) { 357 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 358 v8::HandleScope scope(isolate); 359 Deserialize(); 360 361 v8::Local<v8::Context> env = v8::Context::New(isolate); 362 env->Enter(); 363 364 const char* c_source = "\"1234\".length"; 365 v8::Local<v8::String> source = v8::String::New(c_source); 366 v8::Local<v8::Script> script = v8::Script::Compile(source); 367 CHECK_EQ(4, script->Run()->Int32Value()); 368 } 369 } 370 371 372 TEST(PartialSerialization) { 373 if (!Snapshot::HaveASnapshotToStartFrom()) { 374 Serializer::Enable(); 375 v8::V8::Initialize(); 376 Isolate* isolate = Isolate::Current(); 377 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate); 378 Heap* heap = isolate->heap(); 379 380 v8::Persistent<v8::Context> env; 381 { 382 HandleScope scope(isolate); 383 env.Reset(v8_isolate, v8::Context::New(v8_isolate)); 384 } 385 ASSERT(!env.IsEmpty()); 386 { 387 v8::HandleScope handle_scope(v8_isolate); 388 v8::Local<v8::Context>::New(v8_isolate, env)->Enter(); 389 } 390 // Make sure all builtin scripts are cached. 391 { HandleScope scope(isolate); 392 for (int i = 0; i < Natives::GetBuiltinsCount(); i++) { 393 isolate->bootstrapper()->NativesSourceLookup(i); 394 } 395 } 396 heap->CollectAllGarbage(Heap::kNoGCFlags); 397 heap->CollectAllGarbage(Heap::kNoGCFlags); 398 399 Object* raw_foo; 400 { 401 v8::HandleScope handle_scope(v8_isolate); 402 v8::Local<v8::String> foo = v8::String::New("foo"); 403 ASSERT(!foo.IsEmpty()); 404 raw_foo = *(v8::Utils::OpenHandle(*foo)); 405 } 406 407 int file_name_length = StrLength(FLAG_testing_serialization_file) + 10; 408 Vector<char> startup_name = Vector<char>::New(file_name_length + 1); 409 OS::SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file); 410 411 { 412 v8::HandleScope handle_scope(v8_isolate); 413 v8::Local<v8::Context>::New(v8_isolate, env)->Exit(); 414 } 415 env.Dispose(v8_isolate); 416 417 FileByteSink startup_sink(startup_name.start()); 418 StartupSerializer startup_serializer(&startup_sink); 419 startup_serializer.SerializeStrongReferences(); 420 421 FileByteSink partial_sink(FLAG_testing_serialization_file); 422 PartialSerializer p_ser(&startup_serializer, &partial_sink); 423 p_ser.Serialize(&raw_foo); 424 startup_serializer.SerializeWeakReferences(); 425 426 partial_sink.WriteSpaceUsed( 427 p_ser.CurrentAllocationAddress(NEW_SPACE), 428 p_ser.CurrentAllocationAddress(OLD_POINTER_SPACE), 429 p_ser.CurrentAllocationAddress(OLD_DATA_SPACE), 430 p_ser.CurrentAllocationAddress(CODE_SPACE), 431 p_ser.CurrentAllocationAddress(MAP_SPACE), 432 p_ser.CurrentAllocationAddress(CELL_SPACE), 433 p_ser.CurrentAllocationAddress(PROPERTY_CELL_SPACE)); 434 435 startup_sink.WriteSpaceUsed( 436 startup_serializer.CurrentAllocationAddress(NEW_SPACE), 437 startup_serializer.CurrentAllocationAddress(OLD_POINTER_SPACE), 438 startup_serializer.CurrentAllocationAddress(OLD_DATA_SPACE), 439 startup_serializer.CurrentAllocationAddress(CODE_SPACE), 440 startup_serializer.CurrentAllocationAddress(MAP_SPACE), 441 startup_serializer.CurrentAllocationAddress(CELL_SPACE), 442 startup_serializer.CurrentAllocationAddress(PROPERTY_CELL_SPACE)); 443 startup_name.Dispose(); 444 } 445 } 446 447 448 static void ReserveSpaceForSnapshot(Deserializer* deserializer, 449 const char* file_name) { 450 int file_name_length = StrLength(file_name) + 10; 451 Vector<char> name = Vector<char>::New(file_name_length + 1); 452 OS::SNPrintF(name, "%s.size", file_name); 453 FILE* fp = OS::FOpen(name.start(), "r"); 454 name.Dispose(); 455 int new_size, pointer_size, data_size, code_size, map_size, cell_size, 456 property_cell_size; 457 #ifdef _MSC_VER 458 // Avoid warning about unsafe fscanf from MSVC. 459 // Please note that this is only fine if %c and %s are not being used. 460 #define fscanf fscanf_s 461 #endif 462 CHECK_EQ(1, fscanf(fp, "new %d\n", &new_size)); 463 CHECK_EQ(1, fscanf(fp, "pointer %d\n", &pointer_size)); 464 CHECK_EQ(1, fscanf(fp, "data %d\n", &data_size)); 465 CHECK_EQ(1, fscanf(fp, "code %d\n", &code_size)); 466 CHECK_EQ(1, fscanf(fp, "map %d\n", &map_size)); 467 CHECK_EQ(1, fscanf(fp, "cell %d\n", &cell_size)); 468 CHECK_EQ(1, fscanf(fp, "property cell %d\n", &property_cell_size)); 469 #ifdef _MSC_VER 470 #undef fscanf 471 #endif 472 fclose(fp); 473 deserializer->set_reservation(NEW_SPACE, new_size); 474 deserializer->set_reservation(OLD_POINTER_SPACE, pointer_size); 475 deserializer->set_reservation(OLD_DATA_SPACE, data_size); 476 deserializer->set_reservation(CODE_SPACE, code_size); 477 deserializer->set_reservation(MAP_SPACE, map_size); 478 deserializer->set_reservation(CELL_SPACE, cell_size); 479 deserializer->set_reservation(PROPERTY_CELL_SPACE, property_cell_size); 480 } 481 482 483 DEPENDENT_TEST(PartialDeserialization, PartialSerialization) { 484 if (!Snapshot::IsEnabled()) { 485 int file_name_length = StrLength(FLAG_testing_serialization_file) + 10; 486 Vector<char> startup_name = Vector<char>::New(file_name_length + 1); 487 OS::SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file); 488 489 CHECK(Snapshot::Initialize(startup_name.start())); 490 startup_name.Dispose(); 491 492 const char* file_name = FLAG_testing_serialization_file; 493 494 int snapshot_size = 0; 495 byte* snapshot = ReadBytes(file_name, &snapshot_size); 496 497 Object* root; 498 { 499 SnapshotByteSource source(snapshot, snapshot_size); 500 Deserializer deserializer(&source); 501 ReserveSpaceForSnapshot(&deserializer, file_name); 502 deserializer.DeserializePartial(&root); 503 CHECK(root->IsString()); 504 } 505 v8::HandleScope handle_scope(v8::Isolate::GetCurrent()); 506 Handle<Object> root_handle(root, Isolate::Current()); 507 508 509 Object* root2; 510 { 511 SnapshotByteSource source(snapshot, snapshot_size); 512 Deserializer deserializer(&source); 513 ReserveSpaceForSnapshot(&deserializer, file_name); 514 deserializer.DeserializePartial(&root2); 515 CHECK(root2->IsString()); 516 CHECK(*root_handle == root2); 517 } 518 } 519 } 520 521 522 TEST(ContextSerialization) { 523 if (!Snapshot::HaveASnapshotToStartFrom()) { 524 Serializer::Enable(); 525 v8::V8::Initialize(); 526 Isolate* isolate = Isolate::Current(); 527 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate); 528 Heap* heap = isolate->heap(); 529 530 v8::Persistent<v8::Context> env; 531 { 532 HandleScope scope(isolate); 533 env.Reset(v8_isolate, v8::Context::New(v8_isolate)); 534 } 535 ASSERT(!env.IsEmpty()); 536 { 537 v8::HandleScope handle_scope(v8_isolate); 538 v8::Local<v8::Context>::New(v8_isolate, env)->Enter(); 539 } 540 // Make sure all builtin scripts are cached. 541 { HandleScope scope(isolate); 542 for (int i = 0; i < Natives::GetBuiltinsCount(); i++) { 543 isolate->bootstrapper()->NativesSourceLookup(i); 544 } 545 } 546 // If we don't do this then we end up with a stray root pointing at the 547 // context even after we have disposed of env. 548 heap->CollectAllGarbage(Heap::kNoGCFlags); 549 550 int file_name_length = StrLength(FLAG_testing_serialization_file) + 10; 551 Vector<char> startup_name = Vector<char>::New(file_name_length + 1); 552 OS::SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file); 553 554 { 555 v8::HandleScope handle_scope(v8_isolate); 556 v8::Local<v8::Context>::New(v8_isolate, env)->Exit(); 557 } 558 559 i::Object* raw_context = *v8::Utils::OpenPersistent(env); 560 561 env.Dispose(v8_isolate); 562 563 FileByteSink startup_sink(startup_name.start()); 564 StartupSerializer startup_serializer(&startup_sink); 565 startup_serializer.SerializeStrongReferences(); 566 567 FileByteSink partial_sink(FLAG_testing_serialization_file); 568 PartialSerializer p_ser(&startup_serializer, &partial_sink); 569 p_ser.Serialize(&raw_context); 570 startup_serializer.SerializeWeakReferences(); 571 572 partial_sink.WriteSpaceUsed( 573 p_ser.CurrentAllocationAddress(NEW_SPACE), 574 p_ser.CurrentAllocationAddress(OLD_POINTER_SPACE), 575 p_ser.CurrentAllocationAddress(OLD_DATA_SPACE), 576 p_ser.CurrentAllocationAddress(CODE_SPACE), 577 p_ser.CurrentAllocationAddress(MAP_SPACE), 578 p_ser.CurrentAllocationAddress(CELL_SPACE), 579 p_ser.CurrentAllocationAddress(PROPERTY_CELL_SPACE)); 580 581 startup_sink.WriteSpaceUsed( 582 startup_serializer.CurrentAllocationAddress(NEW_SPACE), 583 startup_serializer.CurrentAllocationAddress(OLD_POINTER_SPACE), 584 startup_serializer.CurrentAllocationAddress(OLD_DATA_SPACE), 585 startup_serializer.CurrentAllocationAddress(CODE_SPACE), 586 startup_serializer.CurrentAllocationAddress(MAP_SPACE), 587 startup_serializer.CurrentAllocationAddress(CELL_SPACE), 588 startup_serializer.CurrentAllocationAddress(PROPERTY_CELL_SPACE)); 589 startup_name.Dispose(); 590 } 591 } 592 593 594 DEPENDENT_TEST(ContextDeserialization, ContextSerialization) { 595 if (!Snapshot::HaveASnapshotToStartFrom()) { 596 int file_name_length = StrLength(FLAG_testing_serialization_file) + 10; 597 Vector<char> startup_name = Vector<char>::New(file_name_length + 1); 598 OS::SNPrintF(startup_name, "%s.startup", FLAG_testing_serialization_file); 599 600 CHECK(Snapshot::Initialize(startup_name.start())); 601 startup_name.Dispose(); 602 603 const char* file_name = FLAG_testing_serialization_file; 604 605 int snapshot_size = 0; 606 byte* snapshot = ReadBytes(file_name, &snapshot_size); 607 608 Object* root; 609 { 610 SnapshotByteSource source(snapshot, snapshot_size); 611 Deserializer deserializer(&source); 612 ReserveSpaceForSnapshot(&deserializer, file_name); 613 deserializer.DeserializePartial(&root); 614 CHECK(root->IsContext()); 615 } 616 v8::HandleScope handle_scope(v8::Isolate::GetCurrent()); 617 Handle<Object> root_handle(root, Isolate::Current()); 618 619 620 Object* root2; 621 { 622 SnapshotByteSource source(snapshot, snapshot_size); 623 Deserializer deserializer(&source); 624 ReserveSpaceForSnapshot(&deserializer, file_name); 625 deserializer.DeserializePartial(&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