Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(147)

Side by Side Diff: src/snapshot/serialize.cc

Issue 1124403006: Reland "Prevent stack overflow in the serializer/deserializer." (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fix msan issue Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/snapshot/serialize.h ('k') | test/cctest/test-serialize.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/snapshot/serialize.h ('k') | test/cctest/test-serialize.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698