OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/api.h" | 8 #include "src/api.h" |
9 #include "src/base/platform/platform.h" | 9 #include "src/base/platform/platform.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
553 Initialize(isolate); | 553 Initialize(isolate); |
554 if (!ReserveSpace()) V8::FatalProcessOutOfMemory("deserializing context"); | 554 if (!ReserveSpace()) V8::FatalProcessOutOfMemory("deserializing context"); |
555 // No active threads. | 555 // No active threads. |
556 DCHECK_NULL(isolate_->thread_manager()->FirstThreadStateInUse()); | 556 DCHECK_NULL(isolate_->thread_manager()->FirstThreadStateInUse()); |
557 // No active handles. | 557 // No active handles. |
558 DCHECK(isolate_->handle_scope_implementer()->blocks()->is_empty()); | 558 DCHECK(isolate_->handle_scope_implementer()->blocks()->is_empty()); |
559 isolate_->heap()->IterateSmiRoots(this); | 559 isolate_->heap()->IterateSmiRoots(this); |
560 isolate_->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG); | 560 isolate_->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG); |
561 isolate_->heap()->RepairFreeListsAfterDeserialization(); | 561 isolate_->heap()->RepairFreeListsAfterDeserialization(); |
562 isolate_->heap()->IterateWeakRoots(this, VISIT_ALL); | 562 isolate_->heap()->IterateWeakRoots(this, VISIT_ALL); |
| 563 DeserializeDeferredObjects(); |
563 | 564 |
564 isolate_->heap()->set_native_contexts_list( | 565 isolate_->heap()->set_native_contexts_list( |
565 isolate_->heap()->undefined_value()); | 566 isolate_->heap()->undefined_value()); |
566 | 567 |
567 // The allocation site list is build during root iteration, but if no sites | 568 // The allocation site list is build during root iteration, but if no sites |
568 // were encountered then it needs to be initialized to undefined. | 569 // were encountered then it needs to be initialized to undefined. |
569 if (isolate_->heap()->allocation_sites_list() == Smi::FromInt(0)) { | 570 if (isolate_->heap()->allocation_sites_list() == Smi::FromInt(0)) { |
570 isolate_->heap()->set_allocation_sites_list( | 571 isolate_->heap()->set_allocation_sites_list( |
571 isolate_->heap()->undefined_value()); | 572 isolate_->heap()->undefined_value()); |
572 } | 573 } |
(...skipping 29 matching lines...) Expand all Loading... |
602 | 603 |
603 DisallowHeapAllocation no_gc; | 604 DisallowHeapAllocation no_gc; |
604 // Keep track of the code space start and end pointers in case new | 605 // Keep track of the code space start and end pointers in case new |
605 // code objects were unserialized | 606 // code objects were unserialized |
606 OldSpace* code_space = isolate_->heap()->code_space(); | 607 OldSpace* code_space = isolate_->heap()->code_space(); |
607 Address start_address = code_space->top(); | 608 Address start_address = code_space->top(); |
608 Object* root; | 609 Object* root; |
609 Object* outdated_contexts; | 610 Object* outdated_contexts; |
610 VisitPointer(&root); | 611 VisitPointer(&root); |
611 VisitPointer(&outdated_contexts); | 612 VisitPointer(&outdated_contexts); |
| 613 DeserializeDeferredObjects(); |
612 | 614 |
613 // There's no code deserialized here. If this assert fires | 615 // There's no code deserialized here. If this assert fires |
614 // then that's changed and logging should be added to notify | 616 // then that's changed and logging should be added to notify |
615 // the profiler et al of the new code. | 617 // the profiler et al of the new code. |
616 CHECK_EQ(start_address, code_space->top()); | 618 CHECK_EQ(start_address, code_space->top()); |
617 CHECK(outdated_contexts->IsFixedArray()); | 619 CHECK(outdated_contexts->IsFixedArray()); |
618 *outdated_contexts_out = | 620 *outdated_contexts_out = |
619 Handle<FixedArray>(FixedArray::cast(outdated_contexts), isolate); | 621 Handle<FixedArray>(FixedArray::cast(outdated_contexts), isolate); |
620 return Handle<Object>(root, isolate); | 622 return Handle<Object>(root, isolate); |
621 } | 623 } |
622 | 624 |
623 | 625 |
624 MaybeHandle<SharedFunctionInfo> Deserializer::DeserializeCode( | 626 MaybeHandle<SharedFunctionInfo> Deserializer::DeserializeCode( |
625 Isolate* isolate) { | 627 Isolate* isolate) { |
626 Initialize(isolate); | 628 Initialize(isolate); |
627 if (!ReserveSpace()) { | 629 if (!ReserveSpace()) { |
628 return Handle<SharedFunctionInfo>(); | 630 return Handle<SharedFunctionInfo>(); |
629 } else { | 631 } else { |
630 deserializing_user_code_ = true; | 632 deserializing_user_code_ = true; |
631 DisallowHeapAllocation no_gc; | 633 DisallowHeapAllocation no_gc; |
632 Object* root; | 634 Object* root; |
633 VisitPointer(&root); | 635 VisitPointer(&root); |
| 636 DeserializeDeferredObjects(); |
634 return Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(root)); | 637 return Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(root)); |
635 } | 638 } |
636 } | 639 } |
637 | 640 |
638 | 641 |
639 Deserializer::~Deserializer() { | 642 Deserializer::~Deserializer() { |
640 // TODO(svenpanne) Re-enable this assertion when v8 initialization is fixed. | 643 // TODO(svenpanne) Re-enable this assertion when v8 initialization is fixed. |
641 // DCHECK(source_.AtEOF()); | 644 // DCHECK(source_.AtEOF()); |
642 attached_objects_.Dispose(); | 645 attached_objects_.Dispose(); |
643 } | 646 } |
644 | 647 |
645 | 648 |
646 // This is called on the roots. It is the driver of the deserialization | 649 // This is called on the roots. It is the driver of the deserialization |
647 // process. It is also called on the body of each function. | 650 // process. It is also called on the body of each function. |
648 void Deserializer::VisitPointers(Object** start, Object** end) { | 651 void Deserializer::VisitPointers(Object** start, Object** end) { |
649 // The space must be new space. Any other space would cause ReadChunk to try | 652 // The space must be new space. Any other space would cause ReadChunk to try |
650 // to update the remembered using NULL as the address. | 653 // to update the remembered using NULL as the address. |
651 ReadData(start, end, NEW_SPACE, NULL); | 654 ReadData(start, end, NEW_SPACE, NULL); |
652 } | 655 } |
653 | 656 |
654 | 657 |
655 void Deserializer::RelinkAllocationSite(AllocationSite* site) { | 658 void Deserializer::DeserializeDeferredObjects() { |
656 if (isolate_->heap()->allocation_sites_list() == Smi::FromInt(0)) { | 659 for (int code = source_.Get(); code != kSynchronize; code = source_.Get()) { |
657 site->set_weak_next(isolate_->heap()->undefined_value()); | 660 int space = code & kSpaceMask; |
658 } else { | 661 DCHECK(space <= kNumberOfSpaces); |
659 site->set_weak_next(isolate_->heap()->allocation_sites_list()); | 662 DCHECK(code - space == kNewObject); |
| 663 HeapObject* object = GetBackReferencedObject(space); |
| 664 int size = source_.GetInt() << kPointerSizeLog2; |
| 665 Address obj_address = object->address(); |
| 666 Object** start = reinterpret_cast<Object**>(obj_address + kPointerSize); |
| 667 Object** end = reinterpret_cast<Object**>(obj_address + size); |
| 668 bool filled = ReadData(start, end, space, obj_address); |
| 669 CHECK(filled); |
| 670 if (object->IsAllocationSite()) { |
| 671 RelinkAllocationSite(AllocationSite::cast(object)); |
| 672 } |
660 } | 673 } |
661 isolate_->heap()->set_allocation_sites_list(site); | |
662 } | 674 } |
663 | 675 |
664 | 676 |
665 // Used to insert a deserialized internalized string into the string table. | 677 // Used to insert a deserialized internalized string into the string table. |
666 class StringTableInsertionKey : public HashTableKey { | 678 class StringTableInsertionKey : public HashTableKey { |
667 public: | 679 public: |
668 explicit StringTableInsertionKey(String* string) | 680 explicit StringTableInsertionKey(String* string) |
669 : string_(string), hash_(HashForObject(string)) { | 681 : string_(string), hash_(HashForObject(string)) { |
670 DCHECK(string->IsInternalizedString()); | 682 DCHECK(string->IsInternalizedString()); |
671 } | 683 } |
(...skipping 14 matching lines...) Expand all Loading... |
686 | 698 |
687 MUST_USE_RESULT virtual Handle<Object> AsHandle(Isolate* isolate) override { | 699 MUST_USE_RESULT virtual Handle<Object> AsHandle(Isolate* isolate) override { |
688 return handle(string_, isolate); | 700 return handle(string_, isolate); |
689 } | 701 } |
690 | 702 |
691 String* string_; | 703 String* string_; |
692 uint32_t hash_; | 704 uint32_t hash_; |
693 }; | 705 }; |
694 | 706 |
695 | 707 |
696 HeapObject* Deserializer::ProcessNewObjectFromSerializedCode(HeapObject* obj) { | 708 HeapObject* Deserializer::PostProcessNewObject(HeapObject* obj) { |
| 709 DCHECK(deserializing_user_code()); |
697 if (obj->IsString()) { | 710 if (obj->IsString()) { |
698 String* string = String::cast(obj); | 711 String* string = String::cast(obj); |
699 // Uninitialize hash field as the hash seed may have changed. | 712 // Uninitialize hash field as the hash seed may have changed. |
700 string->set_hash_field(String::kEmptyHashField); | 713 string->set_hash_field(String::kEmptyHashField); |
701 if (string->IsInternalizedString()) { | 714 if (string->IsInternalizedString()) { |
702 DisallowHeapAllocation no_gc; | 715 DisallowHeapAllocation no_gc; |
703 HandleScope scope(isolate_); | 716 HandleScope scope(isolate_); |
704 StringTableInsertionKey key(string); | 717 StringTableInsertionKey key(string); |
705 String* canonical = *StringTable::LookupKey(isolate_, &key); | 718 String* canonical = *StringTable::LookupKey(isolate_, &key); |
706 string->SetForwardedInternalizedString(canonical); | 719 string->SetForwardedInternalizedString(canonical); |
707 return canonical; | 720 return canonical; |
708 } | 721 } |
709 } else if (obj->IsScript()) { | 722 } else if (obj->IsScript()) { |
710 Script::cast(obj)->set_id(isolate_->heap()->NextScriptId()); | 723 Script::cast(obj)->set_id(isolate_->heap()->NextScriptId()); |
| 724 } else { |
| 725 DCHECK(CanBeDeferred(obj)); |
711 } | 726 } |
712 return obj; | 727 return obj; |
713 } | 728 } |
714 | 729 |
715 | 730 |
| 731 void Deserializer::RelinkAllocationSite(AllocationSite* obj) { |
| 732 DCHECK(obj->IsAllocationSite()); |
| 733 // Allocation sites are present in the snapshot, and must be linked into |
| 734 // a list at deserialization time. |
| 735 AllocationSite* site = AllocationSite::cast(obj); |
| 736 // TODO(mvstanton): consider treating the heap()->allocation_sites_list() |
| 737 // as a (weak) root. If this root is relocated correctly, |
| 738 // RelinkAllocationSite() isn't necessary. |
| 739 if (isolate_->heap()->allocation_sites_list() == Smi::FromInt(0)) { |
| 740 site->set_weak_next(isolate_->heap()->undefined_value()); |
| 741 } else { |
| 742 site->set_weak_next(isolate_->heap()->allocation_sites_list()); |
| 743 } |
| 744 isolate_->heap()->set_allocation_sites_list(site); |
| 745 } |
| 746 |
| 747 |
716 HeapObject* Deserializer::GetBackReferencedObject(int space) { | 748 HeapObject* Deserializer::GetBackReferencedObject(int space) { |
717 HeapObject* obj; | 749 HeapObject* obj; |
718 BackReference back_reference(source_.GetInt()); | 750 BackReference back_reference(source_.GetInt()); |
719 if (space == LO_SPACE) { | 751 if (space == LO_SPACE) { |
720 CHECK(back_reference.chunk_index() == 0); | 752 CHECK(back_reference.chunk_index() == 0); |
721 uint32_t index = back_reference.large_object_index(); | 753 uint32_t index = back_reference.large_object_index(); |
722 obj = deserialized_large_objects_[index]; | 754 obj = deserialized_large_objects_[index]; |
723 } else { | 755 } else { |
724 DCHECK(space < kNumberOfPreallocatedSpaces); | 756 DCHECK(space < kNumberOfPreallocatedSpaces); |
725 uint32_t chunk_index = back_reference.chunk_index(); | 757 uint32_t chunk_index = back_reference.chunk_index(); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
761 obj = isolate_->heap()->DoubleAlignForDeserialization(obj, reserved_size); | 793 obj = isolate_->heap()->DoubleAlignForDeserialization(obj, reserved_size); |
762 address = obj->address(); | 794 address = obj->address(); |
763 } | 795 } |
764 | 796 |
765 isolate_->heap()->OnAllocationEvent(obj, size); | 797 isolate_->heap()->OnAllocationEvent(obj, size); |
766 Object** current = reinterpret_cast<Object**>(address); | 798 Object** current = reinterpret_cast<Object**>(address); |
767 Object** limit = current + (size >> kPointerSizeLog2); | 799 Object** limit = current + (size >> kPointerSizeLog2); |
768 if (FLAG_log_snapshot_positions) { | 800 if (FLAG_log_snapshot_positions) { |
769 LOG(isolate_, SnapshotPositionEvent(address, source_.position())); | 801 LOG(isolate_, SnapshotPositionEvent(address, source_.position())); |
770 } | 802 } |
771 ReadData(current, limit, space_number, address); | |
772 | 803 |
773 // TODO(mvstanton): consider treating the heap()->allocation_sites_list() | 804 if (ReadData(current, limit, space_number, address)) { |
774 // as a (weak) root. If this root is relocated correctly, | 805 // Only post process if object content has not been deferred. |
775 // RelinkAllocationSite() isn't necessary. | 806 if (obj->IsAllocationSite()) { |
776 if (obj->IsAllocationSite()) RelinkAllocationSite(AllocationSite::cast(obj)); | 807 RelinkAllocationSite(AllocationSite::cast(obj)); |
| 808 } |
777 | 809 |
778 // Fix up strings from serialized user code. | 810 if (deserializing_user_code()) obj = PostProcessNewObject(obj); |
779 if (deserializing_user_code()) obj = ProcessNewObjectFromSerializedCode(obj); | 811 } |
780 | 812 |
781 Object* write_back_obj = obj; | 813 Object* write_back_obj = obj; |
782 UnalignedCopy(write_back, &write_back_obj); | 814 UnalignedCopy(write_back, &write_back_obj); |
783 #ifdef DEBUG | 815 #ifdef DEBUG |
784 if (obj->IsCode()) { | 816 if (obj->IsCode()) { |
785 DCHECK(space_number == CODE_SPACE || space_number == LO_SPACE); | 817 DCHECK(space_number == CODE_SPACE || space_number == LO_SPACE); |
786 #ifdef VERIFY_HEAP | |
787 obj->ObjectVerify(); | |
788 #endif // VERIFY_HEAP | |
789 } else { | 818 } else { |
790 DCHECK(space_number != CODE_SPACE); | 819 DCHECK(space_number != CODE_SPACE); |
791 } | 820 } |
792 #endif // DEBUG | 821 #endif // DEBUG |
793 } | 822 } |
794 | 823 |
795 | 824 |
796 // We know the space requirements before deserialization and can | 825 // We know the space requirements before deserialization and can |
797 // pre-allocate that reserved space. During deserialization, all we need | 826 // pre-allocate that reserved space. During deserialization, all we need |
798 // to do is to bump up the pointer for each space in the reserved | 827 // to do is to bump up the pointer for each space in the reserved |
(...skipping 23 matching lines...) Expand all Loading... |
822 // Assert that the current reserved chunk is still big enough. | 851 // Assert that the current reserved chunk is still big enough. |
823 const Heap::Reservation& reservation = reservations_[space_index]; | 852 const Heap::Reservation& reservation = reservations_[space_index]; |
824 int chunk_index = current_chunk_[space_index]; | 853 int chunk_index = current_chunk_[space_index]; |
825 CHECK_LE(high_water_[space_index], reservation[chunk_index].end); | 854 CHECK_LE(high_water_[space_index], reservation[chunk_index].end); |
826 #endif | 855 #endif |
827 return address; | 856 return address; |
828 } | 857 } |
829 } | 858 } |
830 | 859 |
831 | 860 |
832 void Deserializer::ReadData(Object** current, Object** limit, int source_space, | 861 bool Deserializer::ReadData(Object** current, Object** limit, int source_space, |
833 Address current_object_address) { | 862 Address current_object_address) { |
834 Isolate* const isolate = isolate_; | 863 Isolate* const isolate = isolate_; |
835 // Write barrier support costs around 1% in startup time. In fact there | 864 // Write barrier support costs around 1% in startup time. In fact there |
836 // are no new space objects in current boot snapshots, so it's not needed, | 865 // are no new space objects in current boot snapshots, so it's not needed, |
837 // but that may change. | 866 // but that may change. |
838 bool write_barrier_needed = | 867 bool write_barrier_needed = |
839 (current_object_address != NULL && source_space != NEW_SPACE && | 868 (current_object_address != NULL && source_space != NEW_SPACE && |
840 source_space != CODE_SPACE); | 869 source_space != CODE_SPACE); |
841 while (current < limit) { | 870 while (current < limit) { |
842 byte data = source_.Get(); | 871 byte data = source_.Get(); |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1079 const Heap::Reservation& reservation = reservations_[space]; | 1108 const Heap::Reservation& reservation = reservations_[space]; |
1080 // Make sure the current chunk is indeed exhausted. | 1109 // Make sure the current chunk is indeed exhausted. |
1081 CHECK_EQ(reservation[chunk_index].end, high_water_[space]); | 1110 CHECK_EQ(reservation[chunk_index].end, high_water_[space]); |
1082 // Move to next reserved chunk. | 1111 // Move to next reserved chunk. |
1083 chunk_index = ++current_chunk_[space]; | 1112 chunk_index = ++current_chunk_[space]; |
1084 CHECK_LT(chunk_index, reservation.length()); | 1113 CHECK_LT(chunk_index, reservation.length()); |
1085 high_water_[space] = reservation[chunk_index].start; | 1114 high_water_[space] = reservation[chunk_index].start; |
1086 break; | 1115 break; |
1087 } | 1116 } |
1088 | 1117 |
| 1118 case kDeferred: { |
| 1119 // Deferred can only occur right after the heap object header. |
| 1120 DCHECK(current == reinterpret_cast<Object**>(current_object_address + |
| 1121 kPointerSize)); |
| 1122 HeapObject* obj = HeapObject::FromAddress(current_object_address); |
| 1123 // If the deferred object is a map, its instance type may be used |
| 1124 // during deserialization. Initialize it with a temporary value. |
| 1125 if (obj->IsMap()) Map::cast(obj)->set_instance_type(FILLER_TYPE); |
| 1126 current = limit; |
| 1127 return false; |
| 1128 } |
| 1129 |
1089 case kSynchronize: | 1130 case kSynchronize: |
1090 // If we get here then that indicates that you have a mismatch between | 1131 // If we get here then that indicates that you have a mismatch between |
1091 // the number of GC roots when serializing and deserializing. | 1132 // the number of GC roots when serializing and deserializing. |
1092 CHECK(false); | 1133 CHECK(false); |
1093 break; | 1134 break; |
1094 | 1135 |
1095 case kNativesStringResource: { | 1136 case kNativesStringResource: { |
1096 DCHECK(!isolate_->heap()->deserialization_complete()); | 1137 DCHECK(!isolate_->heap()->deserialization_complete()); |
1097 int index = source_.Get(); | 1138 int index = source_.Get(); |
1098 Vector<const char> source_vector = Natives::GetScriptSource(index); | 1139 Vector<const char> source_vector = Natives::GetScriptSource(index); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1185 } | 1226 } |
1186 | 1227 |
1187 #undef SIXTEEN_CASES | 1228 #undef SIXTEEN_CASES |
1188 #undef FOUR_CASES | 1229 #undef FOUR_CASES |
1189 | 1230 |
1190 default: | 1231 default: |
1191 CHECK(false); | 1232 CHECK(false); |
1192 } | 1233 } |
1193 } | 1234 } |
1194 CHECK_EQ(limit, current); | 1235 CHECK_EQ(limit, current); |
| 1236 return true; |
1195 } | 1237 } |
1196 | 1238 |
1197 | 1239 |
1198 Serializer::Serializer(Isolate* isolate, SnapshotByteSink* sink) | 1240 Serializer::Serializer(Isolate* isolate, SnapshotByteSink* sink) |
1199 : isolate_(isolate), | 1241 : isolate_(isolate), |
1200 sink_(sink), | 1242 sink_(sink), |
1201 external_reference_encoder_(isolate), | 1243 external_reference_encoder_(isolate), |
1202 root_index_map_(isolate), | 1244 root_index_map_(isolate), |
| 1245 recursion_depth_(0), |
1203 code_address_map_(NULL), | 1246 code_address_map_(NULL), |
1204 large_objects_total_size_(0), | 1247 large_objects_total_size_(0), |
1205 seen_large_objects_index_(0) { | 1248 seen_large_objects_index_(0) { |
1206 // The serializer is meant to be used only to generate initial heap images | 1249 // The serializer is meant to be used only to generate initial heap images |
1207 // from a context in which there is only one isolate. | 1250 // from a context in which there is only one isolate. |
1208 for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) { | 1251 for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) { |
1209 pending_chunk_[i] = 0; | 1252 pending_chunk_[i] = 0; |
1210 max_chunk_size_[i] = static_cast<uint32_t>( | 1253 max_chunk_size_[i] = static_cast<uint32_t>( |
1211 MemoryAllocator::PageAreaSize(static_cast<AllocationSpace>(i))); | 1254 MemoryAllocator::PageAreaSize(static_cast<AllocationSpace>(i))); |
1212 } | 1255 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1268 PrintF("%10d %10" V8_PTR_PREFIX "d %s\n", instance_type_count_[Name], \ | 1311 PrintF("%10d %10" V8_PTR_PREFIX "d %s\n", instance_type_count_[Name], \ |
1269 instance_type_size_[Name], #Name); \ | 1312 instance_type_size_[Name], #Name); \ |
1270 } | 1313 } |
1271 INSTANCE_TYPE_LIST(PRINT_INSTANCE_TYPE) | 1314 INSTANCE_TYPE_LIST(PRINT_INSTANCE_TYPE) |
1272 #undef PRINT_INSTANCE_TYPE | 1315 #undef PRINT_INSTANCE_TYPE |
1273 PrintF("\n"); | 1316 PrintF("\n"); |
1274 #endif // OBJECT_PRINT | 1317 #endif // OBJECT_PRINT |
1275 } | 1318 } |
1276 | 1319 |
1277 | 1320 |
| 1321 void Serializer::SerializeDeferredObjects() { |
| 1322 while (deferred_objects_.length() > 0) { |
| 1323 HeapObject* obj = deferred_objects_.RemoveLast(); |
| 1324 ObjectSerializer obj_serializer(this, obj, sink_, kPlain, kStartOfObject); |
| 1325 obj_serializer.SerializeDeferred(); |
| 1326 } |
| 1327 sink_->Put(kSynchronize, "Finished with deferred objects"); |
| 1328 } |
| 1329 |
| 1330 |
1278 void StartupSerializer::SerializeStrongReferences() { | 1331 void StartupSerializer::SerializeStrongReferences() { |
1279 Isolate* isolate = this->isolate(); | 1332 Isolate* isolate = this->isolate(); |
1280 // No active threads. | 1333 // No active threads. |
1281 CHECK_NULL(isolate->thread_manager()->FirstThreadStateInUse()); | 1334 CHECK_NULL(isolate->thread_manager()->FirstThreadStateInUse()); |
1282 // No active or weak handles. | 1335 // No active or weak handles. |
1283 CHECK(isolate->handle_scope_implementer()->blocks()->is_empty()); | 1336 CHECK(isolate->handle_scope_implementer()->blocks()->is_empty()); |
1284 CHECK_EQ(0, isolate->global_handles()->NumberOfWeakHandles()); | 1337 CHECK_EQ(0, isolate->global_handles()->NumberOfWeakHandles()); |
1285 CHECK_EQ(0, isolate->eternal_handles()->NumberOfHandles()); | 1338 CHECK_EQ(0, isolate->eternal_handles()->NumberOfHandles()); |
1286 // We don't support serializing installed extensions. | 1339 // We don't support serializing installed extensions. |
1287 CHECK(!isolate->has_installed_extensions()); | 1340 CHECK(!isolate->has_installed_extensions()); |
(...skipping 24 matching lines...) Expand all Loading... |
1312 | 1365 |
1313 | 1366 |
1314 void PartialSerializer::Serialize(Object** o) { | 1367 void PartialSerializer::Serialize(Object** o) { |
1315 if ((*o)->IsContext()) { | 1368 if ((*o)->IsContext()) { |
1316 Context* context = Context::cast(*o); | 1369 Context* context = Context::cast(*o); |
1317 global_object_ = context->global_object(); | 1370 global_object_ = context->global_object(); |
1318 back_reference_map()->AddGlobalProxy(context->global_proxy()); | 1371 back_reference_map()->AddGlobalProxy(context->global_proxy()); |
1319 } | 1372 } |
1320 VisitPointer(o); | 1373 VisitPointer(o); |
1321 SerializeOutdatedContextsAsFixedArray(); | 1374 SerializeOutdatedContextsAsFixedArray(); |
| 1375 SerializeDeferredObjects(); |
1322 Pad(); | 1376 Pad(); |
1323 } | 1377 } |
1324 | 1378 |
1325 | 1379 |
1326 void PartialSerializer::SerializeOutdatedContextsAsFixedArray() { | 1380 void PartialSerializer::SerializeOutdatedContextsAsFixedArray() { |
1327 int length = outdated_contexts_.length(); | 1381 int length = outdated_contexts_.length(); |
1328 if (length == 0) { | 1382 if (length == 0) { |
1329 FixedArray* empty = isolate_->heap()->empty_fixed_array(); | 1383 FixedArray* empty = isolate_->heap()->empty_fixed_array(); |
1330 SerializeObject(empty, kPlain, kStartOfObject, 0); | 1384 SerializeObject(empty, kPlain, kStartOfObject, 0); |
1331 } else { | 1385 } else { |
1332 // Serialize an imaginary fixed array containing outdated contexts. | 1386 // Serialize an imaginary fixed array containing outdated contexts. |
1333 int size = FixedArray::SizeFor(length); | 1387 int size = FixedArray::SizeFor(length); |
1334 Allocate(NEW_SPACE, size); | 1388 Allocate(NEW_SPACE, size); |
1335 sink_->Put(kNewObject + NEW_SPACE, "emulated FixedArray"); | 1389 sink_->Put(kNewObject + NEW_SPACE, "emulated FixedArray"); |
1336 sink_->PutInt(size >> kObjectAlignmentBits, "FixedArray size in words"); | 1390 sink_->PutInt(size >> kObjectAlignmentBits, "FixedArray size in words"); |
1337 Map* map = isolate_->heap()->fixed_array_map(); | 1391 Map* map = isolate_->heap()->fixed_array_map(); |
1338 SerializeObject(map, kPlain, kStartOfObject, 0); | 1392 SerializeObject(map, kPlain, kStartOfObject, 0); |
1339 Smi* length_smi = Smi::FromInt(length); | 1393 Smi* length_smi = Smi::FromInt(length); |
1340 sink_->Put(kOnePointerRawData, "Smi"); | 1394 sink_->Put(kOnePointerRawData, "Smi"); |
1341 for (int i = 0; i < kPointerSize; i++) { | 1395 for (int i = 0; i < kPointerSize; i++) { |
1342 sink_->Put(reinterpret_cast<byte*>(&length_smi)[i], "Byte"); | 1396 sink_->Put(reinterpret_cast<byte*>(&length_smi)[i], "Byte"); |
1343 } | 1397 } |
1344 for (int i = 0; i < length; i++) { | 1398 for (int i = 0; i < length; i++) { |
1345 BackReference back_ref = outdated_contexts_[i]; | 1399 Context* context = outdated_contexts_[i]; |
1346 DCHECK(BackReferenceIsAlreadyAllocated(back_ref)); | 1400 BackReference back_reference = back_reference_map_.Lookup(context); |
1347 sink_->Put(kBackref + back_ref.space(), "BackRef"); | 1401 sink_->Put(kBackref + back_reference.space(), "BackRef"); |
1348 sink_->PutInt(back_ref.reference(), "BackRefValue"); | 1402 PutBackReference(context, back_reference); |
1349 } | 1403 } |
1350 } | 1404 } |
1351 } | 1405 } |
1352 | 1406 |
1353 | 1407 |
1354 bool Serializer::ShouldBeSkipped(Object** current) { | 1408 bool Serializer::ShouldBeSkipped(Object** current) { |
1355 Object** roots = isolate()->heap()->roots_array_start(); | 1409 Object** roots = isolate()->heap()->roots_array_start(); |
1356 return current == &roots[Heap::kStoreBufferTopRootIndex] | 1410 return current == &roots[Heap::kStoreBufferTopRootIndex] |
1357 || current == &roots[Heap::kStackLimitRootIndex] | 1411 || current == &roots[Heap::kStackLimitRootIndex] |
1358 || current == &roots[Heap::kRealStackLimitRootIndex]; | 1412 || current == &roots[Heap::kRealStackLimitRootIndex]; |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1501 } | 1555 } |
1502 | 1556 |
1503 AllocationSpace space = back_reference.space(); | 1557 AllocationSpace space = back_reference.space(); |
1504 if (skip == 0) { | 1558 if (skip == 0) { |
1505 sink_->Put(kBackref + how_to_code + where_to_point + space, "BackRef"); | 1559 sink_->Put(kBackref + how_to_code + where_to_point + space, "BackRef"); |
1506 } else { | 1560 } else { |
1507 sink_->Put(kBackrefWithSkip + how_to_code + where_to_point + space, | 1561 sink_->Put(kBackrefWithSkip + how_to_code + where_to_point + space, |
1508 "BackRefWithSkip"); | 1562 "BackRefWithSkip"); |
1509 sink_->PutInt(skip, "BackRefSkipDistance"); | 1563 sink_->PutInt(skip, "BackRefSkipDistance"); |
1510 } | 1564 } |
1511 DCHECK(BackReferenceIsAlreadyAllocated(back_reference)); | 1565 PutBackReference(obj, back_reference); |
1512 sink_->PutInt(back_reference.reference(), "BackRefValue"); | |
1513 | |
1514 hot_objects_.Add(obj); | |
1515 } | 1566 } |
1516 return true; | 1567 return true; |
1517 } | 1568 } |
1518 return false; | 1569 return false; |
1519 } | 1570 } |
1520 | 1571 |
1521 | 1572 |
1522 void StartupSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, | 1573 void StartupSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, |
1523 WhereToPoint where_to_point, int skip) { | 1574 WhereToPoint where_to_point, int skip) { |
1524 DCHECK(!obj->IsJSFunction()); | 1575 DCHECK(!obj->IsJSFunction()); |
(...skipping 15 matching lines...) Expand all Loading... |
1540 | 1591 |
1541 FlushSkip(skip); | 1592 FlushSkip(skip); |
1542 | 1593 |
1543 // Object has not yet been serialized. Serialize it here. | 1594 // Object has not yet been serialized. Serialize it here. |
1544 ObjectSerializer object_serializer(this, obj, sink_, how_to_code, | 1595 ObjectSerializer object_serializer(this, obj, sink_, how_to_code, |
1545 where_to_point); | 1596 where_to_point); |
1546 object_serializer.Serialize(); | 1597 object_serializer.Serialize(); |
1547 } | 1598 } |
1548 | 1599 |
1549 | 1600 |
1550 void StartupSerializer::SerializeWeakReferences() { | 1601 void StartupSerializer::SerializeWeakReferencesAndDeferred() { |
1551 // This phase comes right after the serialization (of the snapshot). | 1602 // This phase comes right after the serialization (of the snapshot). |
1552 // After we have done the partial serialization the partial snapshot cache | 1603 // After we have done the partial serialization the partial snapshot cache |
1553 // will contain some references needed to decode the partial snapshot. We | 1604 // will contain some references needed to decode the partial snapshot. We |
1554 // add one entry with 'undefined' which is the sentinel that the deserializer | 1605 // add one entry with 'undefined' which is the sentinel that the deserializer |
1555 // uses to know it is done deserializing the array. | 1606 // uses to know it is done deserializing the array. |
1556 Object* undefined = isolate()->heap()->undefined_value(); | 1607 Object* undefined = isolate()->heap()->undefined_value(); |
1557 VisitPointer(&undefined); | 1608 VisitPointer(&undefined); |
1558 isolate()->heap()->IterateWeakRoots(this, VISIT_ALL); | 1609 isolate()->heap()->IterateWeakRoots(this, VISIT_ALL); |
| 1610 SerializeDeferredObjects(); |
1559 Pad(); | 1611 Pad(); |
1560 } | 1612 } |
1561 | 1613 |
1562 | 1614 |
1563 void Serializer::PutRoot(int root_index, | 1615 void Serializer::PutRoot(int root_index, |
1564 HeapObject* object, | 1616 HeapObject* object, |
1565 SerializerDeserializer::HowToCode how_to_code, | 1617 SerializerDeserializer::HowToCode how_to_code, |
1566 SerializerDeserializer::WhereToPoint where_to_point, | 1618 SerializerDeserializer::WhereToPoint where_to_point, |
1567 int skip) { | 1619 int skip) { |
1568 if (FLAG_trace_serializer) { | 1620 if (FLAG_trace_serializer) { |
(...skipping 12 matching lines...) Expand all Loading... |
1581 sink_->PutInt(skip, "SkipInPutRoot"); | 1633 sink_->PutInt(skip, "SkipInPutRoot"); |
1582 } | 1634 } |
1583 } else { | 1635 } else { |
1584 FlushSkip(skip); | 1636 FlushSkip(skip); |
1585 sink_->Put(kRootArray + how_to_code + where_to_point, "RootSerialization"); | 1637 sink_->Put(kRootArray + how_to_code + where_to_point, "RootSerialization"); |
1586 sink_->PutInt(root_index, "root_index"); | 1638 sink_->PutInt(root_index, "root_index"); |
1587 } | 1639 } |
1588 } | 1640 } |
1589 | 1641 |
1590 | 1642 |
| 1643 void Serializer::PutBackReference(HeapObject* object, BackReference reference) { |
| 1644 DCHECK(BackReferenceIsAlreadyAllocated(reference)); |
| 1645 sink_->PutInt(reference.reference(), "BackRefValue"); |
| 1646 hot_objects_.Add(object); |
| 1647 } |
| 1648 |
| 1649 |
1591 void PartialSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, | 1650 void PartialSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, |
1592 WhereToPoint where_to_point, int skip) { | 1651 WhereToPoint where_to_point, int skip) { |
1593 if (obj->IsMap()) { | 1652 if (obj->IsMap()) { |
1594 // The code-caches link to context-specific code objects, which | 1653 // The code-caches link to context-specific code objects, which |
1595 // the startup and context serializes cannot currently handle. | 1654 // the startup and context serializes cannot currently handle. |
1596 DCHECK(Map::cast(obj)->code_cache() == obj->GetHeap()->empty_fixed_array()); | 1655 DCHECK(Map::cast(obj)->code_cache() == obj->GetHeap()->empty_fixed_array()); |
1597 } | 1656 } |
1598 | 1657 |
1599 // Replace typed arrays by undefined. | 1658 // Replace typed arrays by undefined. |
1600 if (obj->IsJSTypedArray()) obj = isolate_->heap()->undefined_value(); | 1659 if (obj->IsJSTypedArray()) obj = isolate_->heap()->undefined_value(); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1634 } | 1693 } |
1635 | 1694 |
1636 // Object has not yet been serialized. Serialize it here. | 1695 // Object has not yet been serialized. Serialize it here. |
1637 ObjectSerializer serializer(this, obj, sink_, how_to_code, where_to_point); | 1696 ObjectSerializer serializer(this, obj, sink_, how_to_code, where_to_point); |
1638 serializer.Serialize(); | 1697 serializer.Serialize(); |
1639 | 1698 |
1640 if (obj->IsContext() && | 1699 if (obj->IsContext() && |
1641 Context::cast(obj)->global_object() == global_object_) { | 1700 Context::cast(obj)->global_object() == global_object_) { |
1642 // Context refers to the current global object. This reference will | 1701 // Context refers to the current global object. This reference will |
1643 // become outdated after deserialization. | 1702 // become outdated after deserialization. |
1644 BackReference back_reference = back_reference_map_.Lookup(obj); | 1703 outdated_contexts_.Add(Context::cast(obj)); |
1645 DCHECK(back_reference.is_valid()); | |
1646 outdated_contexts_.Add(back_reference); | |
1647 } | 1704 } |
1648 } | 1705 } |
1649 | 1706 |
1650 | 1707 |
1651 void Serializer::ObjectSerializer::SerializePrologue(AllocationSpace space, | 1708 void Serializer::ObjectSerializer::SerializePrologue(AllocationSpace space, |
1652 int size, Map* map) { | 1709 int size, Map* map) { |
1653 if (serializer_->code_address_map_) { | 1710 if (serializer_->code_address_map_) { |
1654 const char* code_name = | 1711 const char* code_name = |
1655 serializer_->code_address_map_->Lookup(object_->address()); | 1712 serializer_->code_address_map_->Lookup(object_->address()); |
1656 LOG(serializer_->isolate_, | 1713 LOG(serializer_->isolate_, |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1766 void Serializer::ObjectSerializer::Serialize() { | 1823 void Serializer::ObjectSerializer::Serialize() { |
1767 if (FLAG_trace_serializer) { | 1824 if (FLAG_trace_serializer) { |
1768 PrintF(" Encoding heap object: "); | 1825 PrintF(" Encoding heap object: "); |
1769 object_->ShortPrint(); | 1826 object_->ShortPrint(); |
1770 PrintF("\n"); | 1827 PrintF("\n"); |
1771 } | 1828 } |
1772 | 1829 |
1773 // We cannot serialize typed array objects correctly. | 1830 // We cannot serialize typed array objects correctly. |
1774 DCHECK(!object_->IsJSTypedArray()); | 1831 DCHECK(!object_->IsJSTypedArray()); |
1775 | 1832 |
| 1833 // We don't expect fillers. |
| 1834 DCHECK(!object_->IsFiller()); |
| 1835 |
1776 if (object_->IsPrototypeInfo()) { | 1836 if (object_->IsPrototypeInfo()) { |
1777 Object* prototype_users = PrototypeInfo::cast(object_)->prototype_users(); | 1837 Object* prototype_users = PrototypeInfo::cast(object_)->prototype_users(); |
1778 if (prototype_users->IsWeakFixedArray()) { | 1838 if (prototype_users->IsWeakFixedArray()) { |
1779 WeakFixedArray::cast(prototype_users)->Compact(); | 1839 WeakFixedArray::cast(prototype_users)->Compact(); |
1780 } | 1840 } |
1781 } | 1841 } |
1782 | 1842 |
1783 if (object_->IsScript()) { | 1843 if (object_->IsScript()) { |
1784 // Clear cached line ends. | 1844 // Clear cached line ends. |
1785 Object* undefined = serializer_->isolate()->heap()->undefined_value(); | 1845 Object* undefined = serializer_->isolate()->heap()->undefined_value(); |
(...skipping 17 matching lines...) Expand all Loading... |
1803 int size = object_->Size(); | 1863 int size = object_->Size(); |
1804 Map* map = object_->map(); | 1864 Map* map = object_->map(); |
1805 AllocationSpace space = | 1865 AllocationSpace space = |
1806 MemoryChunk::FromAddress(object_->address())->owner()->identity(); | 1866 MemoryChunk::FromAddress(object_->address())->owner()->identity(); |
1807 SerializePrologue(space, size, map); | 1867 SerializePrologue(space, size, map); |
1808 | 1868 |
1809 // Serialize the rest of the object. | 1869 // Serialize the rest of the object. |
1810 CHECK_EQ(0, bytes_processed_so_far_); | 1870 CHECK_EQ(0, bytes_processed_so_far_); |
1811 bytes_processed_so_far_ = kPointerSize; | 1871 bytes_processed_so_far_ = kPointerSize; |
1812 | 1872 |
| 1873 RecursionScope recursion(serializer_); |
| 1874 // Objects that are immediately post processed during deserialization |
| 1875 // cannot be deferred, since post processing requires the object content. |
| 1876 if (recursion.ExceedsMaximum() && CanBeDeferred(object_)) { |
| 1877 serializer_->QueueDeferredObject(object_); |
| 1878 sink_->Put(kDeferred, "Deferring object content"); |
| 1879 return; |
| 1880 } |
| 1881 |
1813 object_->IterateBody(map->instance_type(), size, this); | 1882 object_->IterateBody(map->instance_type(), size, this); |
1814 OutputRawData(object_->address() + size); | 1883 OutputRawData(object_->address() + size); |
1815 } | 1884 } |
| 1885 |
| 1886 |
| 1887 void Serializer::ObjectSerializer::SerializeDeferred() { |
| 1888 if (FLAG_trace_serializer) { |
| 1889 PrintF(" Encoding deferred heap object: "); |
| 1890 object_->ShortPrint(); |
| 1891 PrintF("\n"); |
| 1892 } |
| 1893 |
| 1894 int size = object_->Size(); |
| 1895 Map* map = object_->map(); |
| 1896 BackReference reference = serializer_->back_reference_map()->Lookup(object_); |
| 1897 |
| 1898 // Serialize the rest of the object. |
| 1899 CHECK_EQ(0, bytes_processed_so_far_); |
| 1900 bytes_processed_so_far_ = kPointerSize; |
| 1901 |
| 1902 sink_->Put(kNewObject + reference.space(), "deferred object"); |
| 1903 serializer_->PutBackReference(object_, reference); |
| 1904 sink_->PutInt(size >> kPointerSizeLog2, "deferred object size"); |
| 1905 |
| 1906 object_->IterateBody(map->instance_type(), size, this); |
| 1907 OutputRawData(object_->address() + size); |
| 1908 } |
1816 | 1909 |
1817 | 1910 |
1818 void Serializer::ObjectSerializer::VisitPointers(Object** start, | 1911 void Serializer::ObjectSerializer::VisitPointers(Object** start, |
1819 Object** end) { | 1912 Object** end) { |
1820 Object** current = start; | 1913 Object** current = start; |
1821 while (current < end) { | 1914 while (current < end) { |
1822 while (current < end && (*current)->IsSmi()) current++; | 1915 while (current < end && (*current)->IsSmi()) current++; |
1823 if (current < end) OutputRawData(reinterpret_cast<Address>(current)); | 1916 if (current < end) OutputRawData(reinterpret_cast<Address>(current)); |
1824 | 1917 |
1825 while (current < end && !(*current)->IsSmi()) { | 1918 while (current < end && !(*current)->IsSmi()) { |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2127 if (script->IsScript()) Script::cast(script)->name()->ShortPrint(); | 2220 if (script->IsScript()) Script::cast(script)->name()->ShortPrint(); |
2128 PrintF("]\n"); | 2221 PrintF("]\n"); |
2129 } | 2222 } |
2130 | 2223 |
2131 // Serialize code object. | 2224 // Serialize code object. |
2132 SnapshotByteSink sink(info->code()->CodeSize() * 2); | 2225 SnapshotByteSink sink(info->code()->CodeSize() * 2); |
2133 CodeSerializer cs(isolate, &sink, *source, info->code()); | 2226 CodeSerializer cs(isolate, &sink, *source, info->code()); |
2134 DisallowHeapAllocation no_gc; | 2227 DisallowHeapAllocation no_gc; |
2135 Object** location = Handle<Object>::cast(info).location(); | 2228 Object** location = Handle<Object>::cast(info).location(); |
2136 cs.VisitPointer(location); | 2229 cs.VisitPointer(location); |
| 2230 cs.SerializeDeferredObjects(); |
2137 cs.Pad(); | 2231 cs.Pad(); |
2138 | 2232 |
2139 SerializedCodeData data(sink.data(), cs); | 2233 SerializedCodeData data(sink.data(), cs); |
2140 ScriptData* script_data = data.GetScriptData(); | 2234 ScriptData* script_data = data.GetScriptData(); |
2141 | 2235 |
2142 if (FLAG_profile_deserialization) { | 2236 if (FLAG_profile_deserialization) { |
2143 double ms = timer.Elapsed().InMillisecondsF(); | 2237 double ms = timer.Elapsed().InMillisecondsF(); |
2144 int length = script_data->length(); | 2238 int length = script_data->length(); |
2145 PrintF("[Serializing to %d bytes took %0.3f ms]\n", length, ms); | 2239 PrintF("[Serializing to %d bytes took %0.3f ms]\n", length, ms); |
2146 } | 2240 } |
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2592 DisallowHeapAllocation no_gc; | 2686 DisallowHeapAllocation no_gc; |
2593 SerializedCodeData* scd = new SerializedCodeData(cached_data); | 2687 SerializedCodeData* scd = new SerializedCodeData(cached_data); |
2594 SanityCheckResult r = scd->SanityCheck(isolate, source); | 2688 SanityCheckResult r = scd->SanityCheck(isolate, source); |
2595 if (r == CHECK_SUCCESS) return scd; | 2689 if (r == CHECK_SUCCESS) return scd; |
2596 cached_data->Reject(); | 2690 cached_data->Reject(); |
2597 source->GetIsolate()->counters()->code_cache_reject_reason()->AddSample(r); | 2691 source->GetIsolate()->counters()->code_cache_reject_reason()->AddSample(r); |
2598 delete scd; | 2692 delete scd; |
2599 return NULL; | 2693 return NULL; |
2600 } | 2694 } |
2601 } } // namespace v8::internal | 2695 } } // namespace v8::internal |
OLD | NEW |