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

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

Issue 1125073004: Prevent stack overflow in the serializer/deserializer. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fixed all 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 }
809 }
777 810
778 // Fix up strings from serialized user code. 811 if (deserializing_user_code()) obj = PostProcessNewObject(obj);
779 if (deserializing_user_code()) obj = ProcessNewObjectFromSerializedCode(obj);
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 current = limit;
1123 return false;
1124 }
1125
1089 case kSynchronize: 1126 case kSynchronize:
1090 // If we get here then that indicates that you have a mismatch between 1127 // If we get here then that indicates that you have a mismatch between
1091 // the number of GC roots when serializing and deserializing. 1128 // the number of GC roots when serializing and deserializing.
1092 CHECK(false); 1129 CHECK(false);
1093 break; 1130 break;
1094 1131
1095 case kNativesStringResource: { 1132 case kNativesStringResource: {
1096 DCHECK(!isolate_->heap()->deserialization_complete()); 1133 DCHECK(!isolate_->heap()->deserialization_complete());
1097 int index = source_.Get(); 1134 int index = source_.Get();
1098 Vector<const char> source_vector = Natives::GetScriptSource(index); 1135 Vector<const char> source_vector = Natives::GetScriptSource(index);
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1185 } 1222 }
1186 1223
1187 #undef SIXTEEN_CASES 1224 #undef SIXTEEN_CASES
1188 #undef FOUR_CASES 1225 #undef FOUR_CASES
1189 1226
1190 default: 1227 default:
1191 CHECK(false); 1228 CHECK(false);
1192 } 1229 }
1193 } 1230 }
1194 CHECK_EQ(limit, current); 1231 CHECK_EQ(limit, current);
1232 return true;
1195 } 1233 }
1196 1234
1197 1235
1198 Serializer::Serializer(Isolate* isolate, SnapshotByteSink* sink) 1236 Serializer::Serializer(Isolate* isolate, SnapshotByteSink* sink)
1199 : isolate_(isolate), 1237 : isolate_(isolate),
1200 sink_(sink), 1238 sink_(sink),
1201 external_reference_encoder_(isolate), 1239 external_reference_encoder_(isolate),
1202 root_index_map_(isolate), 1240 root_index_map_(isolate),
1241 recursion_depth_(0),
1203 code_address_map_(NULL), 1242 code_address_map_(NULL),
1204 large_objects_total_size_(0), 1243 large_objects_total_size_(0),
1205 seen_large_objects_index_(0) { 1244 seen_large_objects_index_(0) {
1206 // The serializer is meant to be used only to generate initial heap images 1245 // The serializer is meant to be used only to generate initial heap images
1207 // from a context in which there is only one isolate. 1246 // from a context in which there is only one isolate.
1208 for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) { 1247 for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) {
1209 pending_chunk_[i] = 0; 1248 pending_chunk_[i] = 0;
1210 max_chunk_size_[i] = static_cast<uint32_t>( 1249 max_chunk_size_[i] = static_cast<uint32_t>(
1211 MemoryAllocator::PageAreaSize(static_cast<AllocationSpace>(i))); 1250 MemoryAllocator::PageAreaSize(static_cast<AllocationSpace>(i)));
1212 } 1251 }
(...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], \ 1307 PrintF("%10d %10" V8_PTR_PREFIX "d %s\n", instance_type_count_[Name], \
1269 instance_type_size_[Name], #Name); \ 1308 instance_type_size_[Name], #Name); \
1270 } 1309 }
1271 INSTANCE_TYPE_LIST(PRINT_INSTANCE_TYPE) 1310 INSTANCE_TYPE_LIST(PRINT_INSTANCE_TYPE)
1272 #undef PRINT_INSTANCE_TYPE 1311 #undef PRINT_INSTANCE_TYPE
1273 PrintF("\n"); 1312 PrintF("\n");
1274 #endif // OBJECT_PRINT 1313 #endif // OBJECT_PRINT
1275 } 1314 }
1276 1315
1277 1316
1317 void Serializer::SerializeDeferredObjects() {
1318 while (deferred_objects_.length() > 0) {
1319 HeapObject* obj = deferred_objects_.RemoveLast();
1320 ObjectSerializer obj_serializer(this, obj, sink_, kPlain, kStartOfObject);
1321 obj_serializer.SerializeDeferred();
1322 }
1323 sink_->Put(kSynchronize, "Finished with deferred objects");
1324 }
1325
1326
1278 void StartupSerializer::SerializeStrongReferences() { 1327 void StartupSerializer::SerializeStrongReferences() {
1279 Isolate* isolate = this->isolate(); 1328 Isolate* isolate = this->isolate();
1280 // No active threads. 1329 // No active threads.
1281 CHECK_NULL(isolate->thread_manager()->FirstThreadStateInUse()); 1330 CHECK_NULL(isolate->thread_manager()->FirstThreadStateInUse());
1282 // No active or weak handles. 1331 // No active or weak handles.
1283 CHECK(isolate->handle_scope_implementer()->blocks()->is_empty()); 1332 CHECK(isolate->handle_scope_implementer()->blocks()->is_empty());
1284 CHECK_EQ(0, isolate->global_handles()->NumberOfWeakHandles()); 1333 CHECK_EQ(0, isolate->global_handles()->NumberOfWeakHandles());
1285 CHECK_EQ(0, isolate->eternal_handles()->NumberOfHandles()); 1334 CHECK_EQ(0, isolate->eternal_handles()->NumberOfHandles());
1286 // We don't support serializing installed extensions. 1335 // We don't support serializing installed extensions.
1287 CHECK(!isolate->has_installed_extensions()); 1336 CHECK(!isolate->has_installed_extensions());
(...skipping 24 matching lines...) Expand all
1312 1361
1313 1362
1314 void PartialSerializer::Serialize(Object** o) { 1363 void PartialSerializer::Serialize(Object** o) {
1315 if ((*o)->IsContext()) { 1364 if ((*o)->IsContext()) {
1316 Context* context = Context::cast(*o); 1365 Context* context = Context::cast(*o);
1317 global_object_ = context->global_object(); 1366 global_object_ = context->global_object();
1318 back_reference_map()->AddGlobalProxy(context->global_proxy()); 1367 back_reference_map()->AddGlobalProxy(context->global_proxy());
1319 } 1368 }
1320 VisitPointer(o); 1369 VisitPointer(o);
1321 SerializeOutdatedContextsAsFixedArray(); 1370 SerializeOutdatedContextsAsFixedArray();
1371 SerializeDeferredObjects();
1322 Pad(); 1372 Pad();
1323 } 1373 }
1324 1374
1325 1375
1326 void PartialSerializer::SerializeOutdatedContextsAsFixedArray() { 1376 void PartialSerializer::SerializeOutdatedContextsAsFixedArray() {
1327 int length = outdated_contexts_.length(); 1377 int length = outdated_contexts_.length();
1328 if (length == 0) { 1378 if (length == 0) {
1329 FixedArray* empty = isolate_->heap()->empty_fixed_array(); 1379 FixedArray* empty = isolate_->heap()->empty_fixed_array();
1330 SerializeObject(empty, kPlain, kStartOfObject, 0); 1380 SerializeObject(empty, kPlain, kStartOfObject, 0);
1331 } else { 1381 } else {
1332 // Serialize an imaginary fixed array containing outdated contexts. 1382 // Serialize an imaginary fixed array containing outdated contexts.
1333 int size = FixedArray::SizeFor(length); 1383 int size = FixedArray::SizeFor(length);
1334 Allocate(NEW_SPACE, size); 1384 Allocate(NEW_SPACE, size);
1335 sink_->Put(kNewObject + NEW_SPACE, "emulated FixedArray"); 1385 sink_->Put(kNewObject + NEW_SPACE, "emulated FixedArray");
1336 sink_->PutInt(size >> kObjectAlignmentBits, "FixedArray size in words"); 1386 sink_->PutInt(size >> kObjectAlignmentBits, "FixedArray size in words");
1337 Map* map = isolate_->heap()->fixed_array_map(); 1387 Map* map = isolate_->heap()->fixed_array_map();
1338 SerializeObject(map, kPlain, kStartOfObject, 0); 1388 SerializeObject(map, kPlain, kStartOfObject, 0);
1339 Smi* length_smi = Smi::FromInt(length); 1389 Smi* length_smi = Smi::FromInt(length);
1340 sink_->Put(kOnePointerRawData, "Smi"); 1390 sink_->Put(kOnePointerRawData, "Smi");
1341 for (int i = 0; i < kPointerSize; i++) { 1391 for (int i = 0; i < kPointerSize; i++) {
1342 sink_->Put(reinterpret_cast<byte*>(&length_smi)[i], "Byte"); 1392 sink_->Put(reinterpret_cast<byte*>(&length_smi)[i], "Byte");
1343 } 1393 }
1344 for (int i = 0; i < length; i++) { 1394 for (int i = 0; i < length; i++) {
1345 BackReference back_ref = outdated_contexts_[i]; 1395 Context* context = outdated_contexts_[i];
1346 DCHECK(BackReferenceIsAlreadyAllocated(back_ref)); 1396 BackReference back_reference = back_reference_map_.Lookup(context);
1347 sink_->Put(kBackref + back_ref.space(), "BackRef"); 1397 sink_->Put(kBackref + back_reference.space(), "BackRef");
1348 sink_->PutInt(back_ref.reference(), "BackRefValue"); 1398 PutBackReference(context, back_reference);
1349 } 1399 }
1350 } 1400 }
1351 } 1401 }
1352 1402
1353 1403
1354 bool Serializer::ShouldBeSkipped(Object** current) { 1404 bool Serializer::ShouldBeSkipped(Object** current) {
1355 Object** roots = isolate()->heap()->roots_array_start(); 1405 Object** roots = isolate()->heap()->roots_array_start();
1356 return current == &roots[Heap::kStoreBufferTopRootIndex] 1406 return current == &roots[Heap::kStoreBufferTopRootIndex]
1357 || current == &roots[Heap::kStackLimitRootIndex] 1407 || current == &roots[Heap::kStackLimitRootIndex]
1358 || current == &roots[Heap::kRealStackLimitRootIndex]; 1408 || current == &roots[Heap::kRealStackLimitRootIndex];
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
1501 } 1551 }
1502 1552
1503 AllocationSpace space = back_reference.space(); 1553 AllocationSpace space = back_reference.space();
1504 if (skip == 0) { 1554 if (skip == 0) {
1505 sink_->Put(kBackref + how_to_code + where_to_point + space, "BackRef"); 1555 sink_->Put(kBackref + how_to_code + where_to_point + space, "BackRef");
1506 } else { 1556 } else {
1507 sink_->Put(kBackrefWithSkip + how_to_code + where_to_point + space, 1557 sink_->Put(kBackrefWithSkip + how_to_code + where_to_point + space,
1508 "BackRefWithSkip"); 1558 "BackRefWithSkip");
1509 sink_->PutInt(skip, "BackRefSkipDistance"); 1559 sink_->PutInt(skip, "BackRefSkipDistance");
1510 } 1560 }
1511 DCHECK(BackReferenceIsAlreadyAllocated(back_reference)); 1561 PutBackReference(obj, back_reference);
1512 sink_->PutInt(back_reference.reference(), "BackRefValue");
1513
1514 hot_objects_.Add(obj);
1515 } 1562 }
1516 return true; 1563 return true;
1517 } 1564 }
1518 return false; 1565 return false;
1519 } 1566 }
1520 1567
1521 1568
1522 void StartupSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, 1569 void StartupSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
1523 WhereToPoint where_to_point, int skip) { 1570 WhereToPoint where_to_point, int skip) {
1524 DCHECK(!obj->IsJSFunction()); 1571 DCHECK(!obj->IsJSFunction());
(...skipping 15 matching lines...) Expand all
1540 1587
1541 FlushSkip(skip); 1588 FlushSkip(skip);
1542 1589
1543 // Object has not yet been serialized. Serialize it here. 1590 // Object has not yet been serialized. Serialize it here.
1544 ObjectSerializer object_serializer(this, obj, sink_, how_to_code, 1591 ObjectSerializer object_serializer(this, obj, sink_, how_to_code,
1545 where_to_point); 1592 where_to_point);
1546 object_serializer.Serialize(); 1593 object_serializer.Serialize();
1547 } 1594 }
1548 1595
1549 1596
1550 void StartupSerializer::SerializeWeakReferences() { 1597 void StartupSerializer::SerializeWeakReferencesAndDeferred() {
1551 // This phase comes right after the serialization (of the snapshot). 1598 // This phase comes right after the serialization (of the snapshot).
1552 // After we have done the partial serialization the partial snapshot cache 1599 // After we have done the partial serialization the partial snapshot cache
1553 // will contain some references needed to decode the partial snapshot. We 1600 // will contain some references needed to decode the partial snapshot. We
1554 // add one entry with 'undefined' which is the sentinel that the deserializer 1601 // add one entry with 'undefined' which is the sentinel that the deserializer
1555 // uses to know it is done deserializing the array. 1602 // uses to know it is done deserializing the array.
1556 Object* undefined = isolate()->heap()->undefined_value(); 1603 Object* undefined = isolate()->heap()->undefined_value();
1557 VisitPointer(&undefined); 1604 VisitPointer(&undefined);
1558 isolate()->heap()->IterateWeakRoots(this, VISIT_ALL); 1605 isolate()->heap()->IterateWeakRoots(this, VISIT_ALL);
1606 SerializeDeferredObjects();
1559 Pad(); 1607 Pad();
1560 } 1608 }
1561 1609
1562 1610
1563 void Serializer::PutRoot(int root_index, 1611 void Serializer::PutRoot(int root_index,
1564 HeapObject* object, 1612 HeapObject* object,
1565 SerializerDeserializer::HowToCode how_to_code, 1613 SerializerDeserializer::HowToCode how_to_code,
1566 SerializerDeserializer::WhereToPoint where_to_point, 1614 SerializerDeserializer::WhereToPoint where_to_point,
1567 int skip) { 1615 int skip) {
1568 if (FLAG_trace_serializer) { 1616 if (FLAG_trace_serializer) {
(...skipping 12 matching lines...) Expand all
1581 sink_->PutInt(skip, "SkipInPutRoot"); 1629 sink_->PutInt(skip, "SkipInPutRoot");
1582 } 1630 }
1583 } else { 1631 } else {
1584 FlushSkip(skip); 1632 FlushSkip(skip);
1585 sink_->Put(kRootArray + how_to_code + where_to_point, "RootSerialization"); 1633 sink_->Put(kRootArray + how_to_code + where_to_point, "RootSerialization");
1586 sink_->PutInt(root_index, "root_index"); 1634 sink_->PutInt(root_index, "root_index");
1587 } 1635 }
1588 } 1636 }
1589 1637
1590 1638
1639 void Serializer::PutBackReference(HeapObject* object, BackReference reference) {
1640 DCHECK(BackReferenceIsAlreadyAllocated(reference));
1641 sink_->PutInt(reference.reference(), "BackRefValue");
1642 hot_objects_.Add(object);
1643 }
1644
1645
1591 void PartialSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, 1646 void PartialSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
1592 WhereToPoint where_to_point, int skip) { 1647 WhereToPoint where_to_point, int skip) {
1593 if (obj->IsMap()) { 1648 if (obj->IsMap()) {
1594 // The code-caches link to context-specific code objects, which 1649 // The code-caches link to context-specific code objects, which
1595 // the startup and context serializes cannot currently handle. 1650 // the startup and context serializes cannot currently handle.
1596 DCHECK(Map::cast(obj)->code_cache() == obj->GetHeap()->empty_fixed_array()); 1651 DCHECK(Map::cast(obj)->code_cache() == obj->GetHeap()->empty_fixed_array());
1597 } 1652 }
1598 1653
1599 // Replace typed arrays by undefined. 1654 // Replace typed arrays by undefined.
1600 if (obj->IsJSTypedArray()) obj = isolate_->heap()->undefined_value(); 1655 if (obj->IsJSTypedArray()) obj = isolate_->heap()->undefined_value();
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1634 } 1689 }
1635 1690
1636 // Object has not yet been serialized. Serialize it here. 1691 // Object has not yet been serialized. Serialize it here.
1637 ObjectSerializer serializer(this, obj, sink_, how_to_code, where_to_point); 1692 ObjectSerializer serializer(this, obj, sink_, how_to_code, where_to_point);
1638 serializer.Serialize(); 1693 serializer.Serialize();
1639 1694
1640 if (obj->IsContext() && 1695 if (obj->IsContext() &&
1641 Context::cast(obj)->global_object() == global_object_) { 1696 Context::cast(obj)->global_object() == global_object_) {
1642 // Context refers to the current global object. This reference will 1697 // Context refers to the current global object. This reference will
1643 // become outdated after deserialization. 1698 // become outdated after deserialization.
1644 BackReference back_reference = back_reference_map_.Lookup(obj); 1699 outdated_contexts_.Add(Context::cast(obj));
1645 DCHECK(back_reference.is_valid());
1646 outdated_contexts_.Add(back_reference);
1647 } 1700 }
1648 } 1701 }
1649 1702
1650 1703
1651 void Serializer::ObjectSerializer::SerializePrologue(AllocationSpace space, 1704 void Serializer::ObjectSerializer::SerializePrologue(AllocationSpace space,
1652 int size, Map* map) { 1705 int size, Map* map) {
1653 if (serializer_->code_address_map_) { 1706 if (serializer_->code_address_map_) {
1654 const char* code_name = 1707 const char* code_name =
1655 serializer_->code_address_map_->Lookup(object_->address()); 1708 serializer_->code_address_map_->Lookup(object_->address());
1656 LOG(serializer_->isolate_, 1709 LOG(serializer_->isolate_,
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
1803 int size = object_->Size(); 1856 int size = object_->Size();
1804 Map* map = object_->map(); 1857 Map* map = object_->map();
1805 AllocationSpace space = 1858 AllocationSpace space =
1806 MemoryChunk::FromAddress(object_->address())->owner()->identity(); 1859 MemoryChunk::FromAddress(object_->address())->owner()->identity();
1807 SerializePrologue(space, size, map); 1860 SerializePrologue(space, size, map);
1808 1861
1809 // Serialize the rest of the object. 1862 // Serialize the rest of the object.
1810 CHECK_EQ(0, bytes_processed_so_far_); 1863 CHECK_EQ(0, bytes_processed_so_far_);
1811 bytes_processed_so_far_ = kPointerSize; 1864 bytes_processed_so_far_ = kPointerSize;
1812 1865
1866 RecursionScope recursion(serializer_);
1867 // Objects that are immediately post processed during deserialization
1868 // cannot be deferred, since post processing requires the object content.
1869 if (recursion.ExceedsMaximum() && CanBeDeferred(object_)) {
1870 serializer_->QueueDeferredObject(object_);
1871 sink_->Put(kDeferred, "Deferring object content");
1872 return;
1873 }
1874
1813 object_->IterateBody(map->instance_type(), size, this); 1875 object_->IterateBody(map->instance_type(), size, this);
1814 OutputRawData(object_->address() + size); 1876 OutputRawData(object_->address() + size);
1815 } 1877 }
1878
1879
1880 void Serializer::ObjectSerializer::SerializeDeferred() {
1881 if (FLAG_trace_serializer) {
1882 PrintF(" Encoding deferred heap object: ");
1883 object_->ShortPrint();
1884 PrintF("\n");
1885 }
1886
1887 int size = object_->Size();
1888 Map* map = object_->map();
1889 BackReference reference = serializer_->back_reference_map()->Lookup(object_);
1890
1891 // Serialize the rest of the object.
1892 CHECK_EQ(0, bytes_processed_so_far_);
1893 bytes_processed_so_far_ = kPointerSize;
1894
1895 sink_->Put(kNewObject + reference.space(), "deferred object");
1896 serializer_->PutBackReference(object_, reference);
1897 sink_->PutInt(size >> kPointerSizeLog2, "deferred object size");
1898
1899 object_->IterateBody(map->instance_type(), size, this);
1900 OutputRawData(object_->address() + size);
1901 }
1816 1902
1817 1903
1818 void Serializer::ObjectSerializer::VisitPointers(Object** start, 1904 void Serializer::ObjectSerializer::VisitPointers(Object** start,
1819 Object** end) { 1905 Object** end) {
1820 Object** current = start; 1906 Object** current = start;
1821 while (current < end) { 1907 while (current < end) {
1822 while (current < end && (*current)->IsSmi()) current++; 1908 while (current < end && (*current)->IsSmi()) current++;
1823 if (current < end) OutputRawData(reinterpret_cast<Address>(current)); 1909 if (current < end) OutputRawData(reinterpret_cast<Address>(current));
1824 1910
1825 while (current < end && !(*current)->IsSmi()) { 1911 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(); 2213 if (script->IsScript()) Script::cast(script)->name()->ShortPrint();
2128 PrintF("]\n"); 2214 PrintF("]\n");
2129 } 2215 }
2130 2216
2131 // Serialize code object. 2217 // Serialize code object.
2132 SnapshotByteSink sink(info->code()->CodeSize() * 2); 2218 SnapshotByteSink sink(info->code()->CodeSize() * 2);
2133 CodeSerializer cs(isolate, &sink, *source, info->code()); 2219 CodeSerializer cs(isolate, &sink, *source, info->code());
2134 DisallowHeapAllocation no_gc; 2220 DisallowHeapAllocation no_gc;
2135 Object** location = Handle<Object>::cast(info).location(); 2221 Object** location = Handle<Object>::cast(info).location();
2136 cs.VisitPointer(location); 2222 cs.VisitPointer(location);
2223 cs.SerializeDeferredObjects();
2137 cs.Pad(); 2224 cs.Pad();
2138 2225
2139 SerializedCodeData data(sink.data(), cs); 2226 SerializedCodeData data(sink.data(), cs);
2140 ScriptData* script_data = data.GetScriptData(); 2227 ScriptData* script_data = data.GetScriptData();
2141 2228
2142 if (FLAG_profile_deserialization) { 2229 if (FLAG_profile_deserialization) {
2143 double ms = timer.Elapsed().InMillisecondsF(); 2230 double ms = timer.Elapsed().InMillisecondsF();
2144 int length = script_data->length(); 2231 int length = script_data->length();
2145 PrintF("[Serializing to %d bytes took %0.3f ms]\n", length, ms); 2232 PrintF("[Serializing to %d bytes took %0.3f ms]\n", length, ms);
2146 } 2233 }
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after
2592 DisallowHeapAllocation no_gc; 2679 DisallowHeapAllocation no_gc;
2593 SerializedCodeData* scd = new SerializedCodeData(cached_data); 2680 SerializedCodeData* scd = new SerializedCodeData(cached_data);
2594 SanityCheckResult r = scd->SanityCheck(isolate, source); 2681 SanityCheckResult r = scd->SanityCheck(isolate, source);
2595 if (r == CHECK_SUCCESS) return scd; 2682 if (r == CHECK_SUCCESS) return scd;
2596 cached_data->Reject(); 2683 cached_data->Reject();
2597 source->GetIsolate()->counters()->code_cache_reject_reason()->AddSample(r); 2684 source->GetIsolate()->counters()->code_cache_reject_reason()->AddSample(r);
2598 delete scd; 2685 delete scd;
2599 return NULL; 2686 return NULL;
2600 } 2687 }
2601 } } // namespace v8::internal 2688 } } // 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