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 593 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
604 const char* name, | 604 const char* name, |
605 int length) { | 605 int length) { |
606 address_to_name_map_.Insert(code->address(), name, length); | 606 address_to_name_map_.Insert(code->address(), name, length); |
607 } | 607 } |
608 | 608 |
609 NameMap address_to_name_map_; | 609 NameMap address_to_name_map_; |
610 Isolate* isolate_; | 610 Isolate* isolate_; |
611 }; | 611 }; |
612 | 612 |
613 | 613 |
614 void Deserializer::DecodeReservation( | 614 Deserializer::Deserializer(SnapshotByteSource* source) |
615 Vector<const SerializedData::Reservation> res) { | 615 : isolate_(NULL), |
616 DCHECK_EQ(0, reservations_[NEW_SPACE].length()); | 616 attached_objects_(NULL), |
617 STATIC_ASSERT(NEW_SPACE == 0); | 617 source_(source), |
618 int current_space = NEW_SPACE; | 618 external_reference_decoder_(NULL), |
619 for (const auto& r : res) { | 619 deserialized_large_objects_(0) { |
620 reservations_[current_space].Add({r.chunk_size(), NULL, NULL}); | |
621 if (r.is_last()) current_space++; | |
622 } | |
623 DCHECK_EQ(kNumberOfSpaces, current_space); | |
624 for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) current_chunk_[i] = 0; | 620 for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) current_chunk_[i] = 0; |
625 } | 621 } |
626 | 622 |
627 | 623 |
628 void Deserializer::FlushICacheForNewCodeObjects() { | 624 void Deserializer::FlushICacheForNewCodeObjects() { |
629 PageIterator it(isolate_->heap()->code_space()); | 625 PageIterator it(isolate_->heap()->code_space()); |
630 while (it.has_next()) { | 626 while (it.has_next()) { |
631 Page* p = it.next(); | 627 Page* p = it.next(); |
632 CpuFeatures::FlushICache(p->area_start(), p->area_end() - p->area_start()); | 628 CpuFeatures::FlushICache(p->area_start(), p->area_end() - p->area_start()); |
633 } | 629 } |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
713 | 709 |
714 // There's no code deserialized here. If this assert fires | 710 // There's no code deserialized here. If this assert fires |
715 // then that's changed and logging should be added to notify | 711 // then that's changed and logging should be added to notify |
716 // the profiler et al of the new code. | 712 // the profiler et al of the new code. |
717 CHECK_EQ(start_address, code_space->top()); | 713 CHECK_EQ(start_address, code_space->top()); |
718 } | 714 } |
719 | 715 |
720 | 716 |
721 Deserializer::~Deserializer() { | 717 Deserializer::~Deserializer() { |
722 // TODO(svenpanne) Re-enable this assertion when v8 initialization is fixed. | 718 // TODO(svenpanne) Re-enable this assertion when v8 initialization is fixed. |
723 // DCHECK(source_.AtEOF()); | 719 // DCHECK(source_->AtEOF()); |
724 if (external_reference_decoder_) { | 720 if (external_reference_decoder_) { |
725 delete external_reference_decoder_; | 721 delete external_reference_decoder_; |
726 external_reference_decoder_ = NULL; | 722 external_reference_decoder_ = NULL; |
727 } | 723 } |
728 if (attached_objects_) attached_objects_->Dispose(); | 724 if (attached_objects_) attached_objects_->Dispose(); |
729 } | 725 } |
730 | 726 |
731 | 727 |
732 // This is called on the roots. It is the driver of the deserialization | 728 // This is called on the roots. It is the driver of the deserialization |
733 // process. It is also called on the body of each function. | 729 // process. It is also called on the body of each function. |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
794 return canonical; | 790 return canonical; |
795 } | 791 } |
796 } | 792 } |
797 return obj; | 793 return obj; |
798 } | 794 } |
799 | 795 |
800 | 796 |
801 HeapObject* Deserializer::GetBackReferencedObject(int space) { | 797 HeapObject* Deserializer::GetBackReferencedObject(int space) { |
802 HeapObject* obj; | 798 HeapObject* obj; |
803 if (space == LO_SPACE) { | 799 if (space == LO_SPACE) { |
804 uint32_t index = source_.GetInt(); | 800 uint32_t index = source_->GetInt(); |
805 obj = deserialized_large_objects_[index]; | 801 obj = deserialized_large_objects_[index]; |
806 } else { | 802 } else { |
807 BackReference back_reference(source_.GetInt()); | 803 BackReference back_reference(source_->GetInt()); |
808 DCHECK(space < kNumberOfPreallocatedSpaces); | 804 DCHECK(space < kNumberOfPreallocatedSpaces); |
809 uint32_t chunk_index = back_reference.chunk_index(); | 805 uint32_t chunk_index = back_reference.chunk_index(); |
810 DCHECK_LE(chunk_index, current_chunk_[space]); | 806 DCHECK_LE(chunk_index, current_chunk_[space]); |
811 uint32_t chunk_offset = back_reference.chunk_offset(); | 807 uint32_t chunk_offset = back_reference.chunk_offset(); |
812 obj = HeapObject::FromAddress(reservations_[space][chunk_index].start + | 808 obj = HeapObject::FromAddress(reservations_[space][chunk_index].start + |
813 chunk_offset); | 809 chunk_offset); |
814 } | 810 } |
815 if (deserializing_user_code() && obj->IsInternalizedString()) { | 811 if (deserializing_user_code() && obj->IsInternalizedString()) { |
816 obj = String::cast(obj)->GetForwardedInternalizedString(); | 812 obj = String::cast(obj)->GetForwardedInternalizedString(); |
817 } | 813 } |
818 hot_objects_.Add(obj); | 814 hot_objects_.Add(obj); |
819 return obj; | 815 return obj; |
820 } | 816 } |
821 | 817 |
822 | 818 |
823 // This routine writes the new object into the pointer provided and then | 819 // This routine writes the new object into the pointer provided and then |
824 // returns true if the new object was in young space and false otherwise. | 820 // returns true if the new object was in young space and false otherwise. |
825 // The reason for this strange interface is that otherwise the object is | 821 // The reason for this strange interface is that otherwise the object is |
826 // written very late, which means the FreeSpace map is not set up by the | 822 // written very late, which means the FreeSpace map is not set up by the |
827 // time we need to use it to mark the space at the end of a page free. | 823 // time we need to use it to mark the space at the end of a page free. |
828 void Deserializer::ReadObject(int space_number, Object** write_back) { | 824 void Deserializer::ReadObject(int space_number, Object** write_back) { |
829 Address address; | 825 Address address; |
830 HeapObject* obj; | 826 HeapObject* obj; |
831 int next_int = source_.GetInt(); | 827 int next_int = source_->GetInt(); |
832 | 828 |
833 bool double_align = false; | 829 bool double_align = false; |
834 #ifndef V8_HOST_ARCH_64_BIT | 830 #ifndef V8_HOST_ARCH_64_BIT |
835 double_align = next_int == kDoubleAlignmentSentinel; | 831 double_align = next_int == kDoubleAlignmentSentinel; |
836 if (double_align) next_int = source_.GetInt(); | 832 if (double_align) next_int = source_->GetInt(); |
837 #endif | 833 #endif |
838 | 834 |
839 DCHECK_NE(kDoubleAlignmentSentinel, next_int); | 835 DCHECK_NE(kDoubleAlignmentSentinel, next_int); |
840 int size = next_int << kObjectAlignmentBits; | 836 int size = next_int << kObjectAlignmentBits; |
841 int reserved_size = size + (double_align ? kPointerSize : 0); | 837 int reserved_size = size + (double_align ? kPointerSize : 0); |
842 address = Allocate(space_number, reserved_size); | 838 address = Allocate(space_number, reserved_size); |
843 obj = HeapObject::FromAddress(address); | 839 obj = HeapObject::FromAddress(address); |
844 if (double_align) { | 840 if (double_align) { |
845 obj = isolate_->heap()->DoubleAlignForDeserialization(obj, reserved_size); | 841 obj = isolate_->heap()->DoubleAlignForDeserialization(obj, reserved_size); |
846 address = obj->address(); | 842 address = obj->address(); |
847 } | 843 } |
848 | 844 |
849 isolate_->heap()->OnAllocationEvent(obj, size); | 845 isolate_->heap()->OnAllocationEvent(obj, size); |
850 Object** current = reinterpret_cast<Object**>(address); | 846 Object** current = reinterpret_cast<Object**>(address); |
851 Object** limit = current + (size >> kPointerSizeLog2); | 847 Object** limit = current + (size >> kPointerSizeLog2); |
852 if (FLAG_log_snapshot_positions) { | 848 if (FLAG_log_snapshot_positions) { |
853 LOG(isolate_, SnapshotPositionEvent(address, source_.position())); | 849 LOG(isolate_, SnapshotPositionEvent(address, source_->position())); |
854 } | 850 } |
855 ReadData(current, limit, space_number, address); | 851 ReadData(current, limit, space_number, address); |
856 | 852 |
857 // TODO(mvstanton): consider treating the heap()->allocation_sites_list() | 853 // TODO(mvstanton): consider treating the heap()->allocation_sites_list() |
858 // as a (weak) root. If this root is relocated correctly, | 854 // as a (weak) root. If this root is relocated correctly, |
859 // RelinkAllocationSite() isn't necessary. | 855 // RelinkAllocationSite() isn't necessary. |
860 if (obj->IsAllocationSite()) RelinkAllocationSite(AllocationSite::cast(obj)); | 856 if (obj->IsAllocationSite()) RelinkAllocationSite(AllocationSite::cast(obj)); |
861 | 857 |
862 // Fix up strings from serialized user code. | 858 // Fix up strings from serialized user code. |
863 if (deserializing_user_code()) obj = ProcessNewObjectFromSerializedCode(obj); | 859 if (deserializing_user_code()) obj = ProcessNewObjectFromSerializedCode(obj); |
(...skipping 17 matching lines...) Expand all Loading... |
881 // because it would not fit onto a single page. We do not have to keep | 877 // because it would not fit onto a single page. We do not have to keep |
882 // track of when to move to the next chunk. An opcode will signal this. | 878 // track of when to move to the next chunk. An opcode will signal this. |
883 // Since multiple large objects cannot be folded into one large object | 879 // Since multiple large objects cannot be folded into one large object |
884 // space allocation, we have to do an actual allocation when deserializing | 880 // space allocation, we have to do an actual allocation when deserializing |
885 // each large object. Instead of tracking offset for back references, we | 881 // each large object. Instead of tracking offset for back references, we |
886 // reference large objects by index. | 882 // reference large objects by index. |
887 Address Deserializer::Allocate(int space_index, int size) { | 883 Address Deserializer::Allocate(int space_index, int size) { |
888 if (space_index == LO_SPACE) { | 884 if (space_index == LO_SPACE) { |
889 AlwaysAllocateScope scope(isolate_); | 885 AlwaysAllocateScope scope(isolate_); |
890 LargeObjectSpace* lo_space = isolate_->heap()->lo_space(); | 886 LargeObjectSpace* lo_space = isolate_->heap()->lo_space(); |
891 Executability exec = static_cast<Executability>(source_.Get()); | 887 Executability exec = static_cast<Executability>(source_->Get()); |
892 AllocationResult result = lo_space->AllocateRaw(size, exec); | 888 AllocationResult result = lo_space->AllocateRaw(size, exec); |
893 HeapObject* obj = HeapObject::cast(result.ToObjectChecked()); | 889 HeapObject* obj = HeapObject::cast(result.ToObjectChecked()); |
894 deserialized_large_objects_.Add(obj); | 890 deserialized_large_objects_.Add(obj); |
895 return obj->address(); | 891 return obj->address(); |
896 } else { | 892 } else { |
897 DCHECK(space_index < kNumberOfPreallocatedSpaces); | 893 DCHECK(space_index < kNumberOfPreallocatedSpaces); |
898 Address address = high_water_[space_index]; | 894 Address address = high_water_[space_index]; |
899 DCHECK_NE(NULL, address); | 895 DCHECK_NE(NULL, address); |
900 high_water_[space_index] += size; | 896 high_water_[space_index] += size; |
901 #ifdef DEBUG | 897 #ifdef DEBUG |
(...skipping 13 matching lines...) Expand all Loading... |
915 // Write barrier support costs around 1% in startup time. In fact there | 911 // Write barrier support costs around 1% in startup time. In fact there |
916 // are no new space objects in current boot snapshots, so it's not needed, | 912 // are no new space objects in current boot snapshots, so it's not needed, |
917 // but that may change. | 913 // but that may change. |
918 bool write_barrier_needed = (current_object_address != NULL && | 914 bool write_barrier_needed = (current_object_address != NULL && |
919 source_space != NEW_SPACE && | 915 source_space != NEW_SPACE && |
920 source_space != CELL_SPACE && | 916 source_space != CELL_SPACE && |
921 source_space != PROPERTY_CELL_SPACE && | 917 source_space != PROPERTY_CELL_SPACE && |
922 source_space != CODE_SPACE && | 918 source_space != CODE_SPACE && |
923 source_space != OLD_DATA_SPACE); | 919 source_space != OLD_DATA_SPACE); |
924 while (current < limit) { | 920 while (current < limit) { |
925 byte data = source_.Get(); | 921 byte data = source_->Get(); |
926 switch (data) { | 922 switch (data) { |
927 #define CASE_STATEMENT(where, how, within, space_number) \ | 923 #define CASE_STATEMENT(where, how, within, space_number) \ |
928 case where + how + within + space_number: \ | 924 case where + how + within + space_number: \ |
929 STATIC_ASSERT((where & ~kPointedToMask) == 0); \ | 925 STATIC_ASSERT((where & ~kPointedToMask) == 0); \ |
930 STATIC_ASSERT((how & ~kHowToCodeMask) == 0); \ | 926 STATIC_ASSERT((how & ~kHowToCodeMask) == 0); \ |
931 STATIC_ASSERT((within & ~kWhereToPointMask) == 0); \ | 927 STATIC_ASSERT((within & ~kWhereToPointMask) == 0); \ |
932 STATIC_ASSERT((space_number & ~kSpaceMask) == 0); | 928 STATIC_ASSERT((space_number & ~kSpaceMask) == 0); |
933 | 929 |
934 #define CASE_BODY(where, how, within, space_number_if_any) \ | 930 #define CASE_BODY(where, how, within, space_number_if_any) \ |
935 { \ | 931 { \ |
936 bool emit_write_barrier = false; \ | 932 bool emit_write_barrier = false; \ |
937 bool current_was_incremented = false; \ | 933 bool current_was_incremented = false; \ |
938 int space_number = space_number_if_any == kAnyOldSpace \ | 934 int space_number = space_number_if_any == kAnyOldSpace \ |
939 ? (data & kSpaceMask) \ | 935 ? (data & kSpaceMask) \ |
940 : space_number_if_any; \ | 936 : space_number_if_any; \ |
941 if (where == kNewObject && how == kPlain && within == kStartOfObject) { \ | 937 if (where == kNewObject && how == kPlain && within == kStartOfObject) { \ |
942 ReadObject(space_number, current); \ | 938 ReadObject(space_number, current); \ |
943 emit_write_barrier = (space_number == NEW_SPACE); \ | 939 emit_write_barrier = (space_number == NEW_SPACE); \ |
944 } else { \ | 940 } else { \ |
945 Object* new_object = NULL; /* May not be a real Object pointer. */ \ | 941 Object* new_object = NULL; /* May not be a real Object pointer. */ \ |
946 if (where == kNewObject) { \ | 942 if (where == kNewObject) { \ |
947 ReadObject(space_number, &new_object); \ | 943 ReadObject(space_number, &new_object); \ |
948 } else if (where == kRootArray) { \ | 944 } else if (where == kRootArray) { \ |
949 int root_id = source_.GetInt(); \ | 945 int root_id = source_->GetInt(); \ |
950 new_object = isolate->heap()->roots_array_start()[root_id]; \ | 946 new_object = isolate->heap()->roots_array_start()[root_id]; \ |
951 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ | 947 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ |
952 } else if (where == kPartialSnapshotCache) { \ | 948 } else if (where == kPartialSnapshotCache) { \ |
953 int cache_index = source_.GetInt(); \ | 949 int cache_index = source_->GetInt(); \ |
954 new_object = isolate->serialize_partial_snapshot_cache()[cache_index]; \ | 950 new_object = isolate->serialize_partial_snapshot_cache()[cache_index]; \ |
955 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ | 951 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ |
956 } else if (where == kExternalReference) { \ | 952 } else if (where == kExternalReference) { \ |
957 int skip = source_.GetInt(); \ | 953 int skip = source_->GetInt(); \ |
958 current = reinterpret_cast<Object**>( \ | 954 current = reinterpret_cast<Object**>( \ |
959 reinterpret_cast<Address>(current) + skip); \ | 955 reinterpret_cast<Address>(current) + skip); \ |
960 int reference_id = source_.GetInt(); \ | 956 int reference_id = source_->GetInt(); \ |
961 Address address = external_reference_decoder_->Decode(reference_id); \ | 957 Address address = external_reference_decoder_->Decode(reference_id); \ |
962 new_object = reinterpret_cast<Object*>(address); \ | 958 new_object = reinterpret_cast<Object*>(address); \ |
963 } else if (where == kBackref) { \ | 959 } else if (where == kBackref) { \ |
964 emit_write_barrier = (space_number == NEW_SPACE); \ | 960 emit_write_barrier = (space_number == NEW_SPACE); \ |
965 new_object = GetBackReferencedObject(data & kSpaceMask); \ | 961 new_object = GetBackReferencedObject(data & kSpaceMask); \ |
966 } else if (where == kBuiltin) { \ | 962 } else if (where == kBuiltin) { \ |
967 DCHECK(deserializing_user_code()); \ | 963 DCHECK(deserializing_user_code()); \ |
968 int builtin_id = source_.GetInt(); \ | 964 int builtin_id = source_->GetInt(); \ |
969 DCHECK_LE(0, builtin_id); \ | 965 DCHECK_LE(0, builtin_id); \ |
970 DCHECK_LT(builtin_id, Builtins::builtin_count); \ | 966 DCHECK_LT(builtin_id, Builtins::builtin_count); \ |
971 Builtins::Name name = static_cast<Builtins::Name>(builtin_id); \ | 967 Builtins::Name name = static_cast<Builtins::Name>(builtin_id); \ |
972 new_object = isolate->builtins()->builtin(name); \ | 968 new_object = isolate->builtins()->builtin(name); \ |
973 emit_write_barrier = false; \ | 969 emit_write_barrier = false; \ |
974 } else if (where == kAttachedReference) { \ | 970 } else if (where == kAttachedReference) { \ |
975 DCHECK(deserializing_user_code()); \ | 971 DCHECK(deserializing_user_code()); \ |
976 int index = source_.GetInt(); \ | 972 int index = source_->GetInt(); \ |
977 new_object = *attached_objects_->at(index); \ | 973 new_object = *attached_objects_->at(index); \ |
978 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ | 974 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ |
979 } else { \ | 975 } else { \ |
980 DCHECK(where == kBackrefWithSkip); \ | 976 DCHECK(where == kBackrefWithSkip); \ |
981 int skip = source_.GetInt(); \ | 977 int skip = source_->GetInt(); \ |
982 current = reinterpret_cast<Object**>( \ | 978 current = reinterpret_cast<Object**>( \ |
983 reinterpret_cast<Address>(current) + skip); \ | 979 reinterpret_cast<Address>(current) + skip); \ |
984 emit_write_barrier = (space_number == NEW_SPACE); \ | 980 emit_write_barrier = (space_number == NEW_SPACE); \ |
985 new_object = GetBackReferencedObject(data & kSpaceMask); \ | 981 new_object = GetBackReferencedObject(data & kSpaceMask); \ |
986 } \ | 982 } \ |
987 if (within == kInnerPointer) { \ | 983 if (within == kInnerPointer) { \ |
988 if (space_number != CODE_SPACE || new_object->IsCode()) { \ | 984 if (space_number != CODE_SPACE || new_object->IsCode()) { \ |
989 Code* new_code_object = reinterpret_cast<Code*>(new_object); \ | 985 Code* new_code_object = reinterpret_cast<Code*>(new_object); \ |
990 new_object = \ | 986 new_object = \ |
991 reinterpret_cast<Object*>(new_code_object->instruction_start()); \ | 987 reinterpret_cast<Object*>(new_code_object->instruction_start()); \ |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1075 f(25) \ | 1071 f(25) \ |
1076 f(26) \ | 1072 f(26) \ |
1077 f(27) \ | 1073 f(27) \ |
1078 f(28) \ | 1074 f(28) \ |
1079 f(29) \ | 1075 f(29) \ |
1080 f(30) \ | 1076 f(30) \ |
1081 f(31) | 1077 f(31) |
1082 | 1078 |
1083 // We generate 15 cases and bodies that process special tags that combine | 1079 // We generate 15 cases and bodies that process special tags that combine |
1084 // the raw data tag and the length into one byte. | 1080 // the raw data tag and the length into one byte. |
1085 #define RAW_CASE(index) \ | 1081 #define RAW_CASE(index) \ |
1086 case kRawData + index: { \ | 1082 case kRawData + index: { \ |
1087 byte* raw_data_out = reinterpret_cast<byte*>(current); \ | 1083 byte* raw_data_out = reinterpret_cast<byte*>(current); \ |
1088 source_.CopyRaw(raw_data_out, index* kPointerSize); \ | 1084 source_->CopyRaw(raw_data_out, index * kPointerSize); \ |
1089 current = reinterpret_cast<Object**>(raw_data_out + index * kPointerSize); \ | 1085 current = \ |
1090 break; \ | 1086 reinterpret_cast<Object**>(raw_data_out + index * kPointerSize); \ |
1091 } | 1087 break; \ |
| 1088 } |
1092 COMMON_RAW_LENGTHS(RAW_CASE) | 1089 COMMON_RAW_LENGTHS(RAW_CASE) |
1093 #undef RAW_CASE | 1090 #undef RAW_CASE |
1094 | 1091 |
1095 // Deserialize a chunk of raw data that doesn't have one of the popular | 1092 // Deserialize a chunk of raw data that doesn't have one of the popular |
1096 // lengths. | 1093 // lengths. |
1097 case kRawData: { | 1094 case kRawData: { |
1098 int size = source_.GetInt(); | 1095 int size = source_->GetInt(); |
1099 byte* raw_data_out = reinterpret_cast<byte*>(current); | 1096 byte* raw_data_out = reinterpret_cast<byte*>(current); |
1100 source_.CopyRaw(raw_data_out, size); | 1097 source_->CopyRaw(raw_data_out, size); |
1101 break; | 1098 break; |
1102 } | 1099 } |
1103 | 1100 |
1104 SIXTEEN_CASES(kRootArrayConstants + kNoSkipDistance) | 1101 SIXTEEN_CASES(kRootArrayConstants + kNoSkipDistance) |
1105 SIXTEEN_CASES(kRootArrayConstants + kNoSkipDistance + 16) { | 1102 SIXTEEN_CASES(kRootArrayConstants + kNoSkipDistance + 16) { |
1106 int root_id = RootArrayConstantFromByteCode(data); | 1103 int root_id = RootArrayConstantFromByteCode(data); |
1107 Object* object = isolate->heap()->roots_array_start()[root_id]; | 1104 Object* object = isolate->heap()->roots_array_start()[root_id]; |
1108 DCHECK(!isolate->heap()->InNewSpace(object)); | 1105 DCHECK(!isolate->heap()->InNewSpace(object)); |
1109 *current++ = object; | 1106 *current++ = object; |
1110 break; | 1107 break; |
1111 } | 1108 } |
1112 | 1109 |
1113 SIXTEEN_CASES(kRootArrayConstants + kHasSkipDistance) | 1110 SIXTEEN_CASES(kRootArrayConstants + kHasSkipDistance) |
1114 SIXTEEN_CASES(kRootArrayConstants + kHasSkipDistance + 16) { | 1111 SIXTEEN_CASES(kRootArrayConstants + kHasSkipDistance + 16) { |
1115 int root_id = RootArrayConstantFromByteCode(data); | 1112 int root_id = RootArrayConstantFromByteCode(data); |
1116 int skip = source_.GetInt(); | 1113 int skip = source_->GetInt(); |
1117 current = reinterpret_cast<Object**>( | 1114 current = reinterpret_cast<Object**>( |
1118 reinterpret_cast<intptr_t>(current) + skip); | 1115 reinterpret_cast<intptr_t>(current) + skip); |
1119 Object* object = isolate->heap()->roots_array_start()[root_id]; | 1116 Object* object = isolate->heap()->roots_array_start()[root_id]; |
1120 DCHECK(!isolate->heap()->InNewSpace(object)); | 1117 DCHECK(!isolate->heap()->InNewSpace(object)); |
1121 *current++ = object; | 1118 *current++ = object; |
1122 break; | 1119 break; |
1123 } | 1120 } |
1124 | 1121 |
1125 case kVariableRepeat: { | 1122 case kVariableRepeat: { |
1126 int repeats = source_.GetInt(); | 1123 int repeats = source_->GetInt(); |
1127 Object* object = current[-1]; | 1124 Object* object = current[-1]; |
1128 DCHECK(!isolate->heap()->InNewSpace(object)); | 1125 DCHECK(!isolate->heap()->InNewSpace(object)); |
1129 for (int i = 0; i < repeats; i++) current[i] = object; | 1126 for (int i = 0; i < repeats; i++) current[i] = object; |
1130 current += repeats; | 1127 current += repeats; |
1131 break; | 1128 break; |
1132 } | 1129 } |
1133 | 1130 |
1134 STATIC_ASSERT(kRootArrayNumberOfConstantEncodings == | 1131 STATIC_ASSERT(kRootArrayNumberOfConstantEncodings == |
1135 Heap::kOldSpaceRoots); | 1132 Heap::kOldSpaceRoots); |
1136 STATIC_ASSERT(kMaxFixedRepeats == 15); | 1133 STATIC_ASSERT(kMaxFixedRepeats == 15); |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1236 CASE_STATEMENT(kAttachedReference, kPlain, kInnerPointer, 0) | 1233 CASE_STATEMENT(kAttachedReference, kPlain, kInnerPointer, 0) |
1237 CASE_BODY(kAttachedReference, kPlain, kInnerPointer, 0) | 1234 CASE_BODY(kAttachedReference, kPlain, kInnerPointer, 0) |
1238 CASE_STATEMENT(kAttachedReference, kFromCode, kInnerPointer, 0) | 1235 CASE_STATEMENT(kAttachedReference, kFromCode, kInnerPointer, 0) |
1239 CASE_BODY(kAttachedReference, kFromCode, kInnerPointer, 0) | 1236 CASE_BODY(kAttachedReference, kFromCode, kInnerPointer, 0) |
1240 | 1237 |
1241 #undef CASE_STATEMENT | 1238 #undef CASE_STATEMENT |
1242 #undef CASE_BODY | 1239 #undef CASE_BODY |
1243 #undef ALL_SPACES | 1240 #undef ALL_SPACES |
1244 | 1241 |
1245 case kSkip: { | 1242 case kSkip: { |
1246 int size = source_.GetInt(); | 1243 int size = source_->GetInt(); |
1247 current = reinterpret_cast<Object**>( | 1244 current = reinterpret_cast<Object**>( |
1248 reinterpret_cast<intptr_t>(current) + size); | 1245 reinterpret_cast<intptr_t>(current) + size); |
1249 break; | 1246 break; |
1250 } | 1247 } |
1251 | 1248 |
1252 case kNativesStringResource: { | 1249 case kNativesStringResource: { |
1253 int index = source_.Get(); | 1250 int index = source_->Get(); |
1254 Vector<const char> source_vector = Natives::GetRawScriptSource(index); | 1251 Vector<const char> source_vector = Natives::GetRawScriptSource(index); |
1255 NativesExternalStringResource* resource = | 1252 NativesExternalStringResource* resource = |
1256 new NativesExternalStringResource(isolate->bootstrapper(), | 1253 new NativesExternalStringResource(isolate->bootstrapper(), |
1257 source_vector.start(), | 1254 source_vector.start(), |
1258 source_vector.length()); | 1255 source_vector.length()); |
1259 *current++ = reinterpret_cast<Object*>(resource); | 1256 *current++ = reinterpret_cast<Object*>(resource); |
1260 break; | 1257 break; |
1261 } | 1258 } |
1262 | 1259 |
1263 case kNextChunk: { | 1260 case kNextChunk: { |
1264 int space = source_.Get(); | 1261 int space = source_->Get(); |
1265 DCHECK(space < kNumberOfPreallocatedSpaces); | 1262 DCHECK(space < kNumberOfPreallocatedSpaces); |
1266 int chunk_index = current_chunk_[space]; | 1263 int chunk_index = current_chunk_[space]; |
1267 const Heap::Reservation& reservation = reservations_[space]; | 1264 const Heap::Reservation& reservation = reservations_[space]; |
1268 // Make sure the current chunk is indeed exhausted. | 1265 // Make sure the current chunk is indeed exhausted. |
1269 CHECK_EQ(reservation[chunk_index].end, high_water_[space]); | 1266 CHECK_EQ(reservation[chunk_index].end, high_water_[space]); |
1270 // Move to next reserved chunk. | 1267 // Move to next reserved chunk. |
1271 chunk_index = ++current_chunk_[space]; | 1268 chunk_index = ++current_chunk_[space]; |
1272 DCHECK_LT(chunk_index, reservation.length()); | 1269 DCHECK_LT(chunk_index, reservation.length()); |
1273 high_water_[space] = reservation[chunk_index].start; | 1270 high_water_[space] = reservation[chunk_index].start; |
1274 break; | 1271 break; |
1275 } | 1272 } |
1276 | 1273 |
1277 FOUR_CASES(kHotObjectWithSkip) | 1274 FOUR_CASES(kHotObjectWithSkip) |
1278 FOUR_CASES(kHotObjectWithSkip + 4) { | 1275 FOUR_CASES(kHotObjectWithSkip + 4) { |
1279 int skip = source_.GetInt(); | 1276 int skip = source_->GetInt(); |
1280 current = reinterpret_cast<Object**>( | 1277 current = reinterpret_cast<Object**>( |
1281 reinterpret_cast<Address>(current) + skip); | 1278 reinterpret_cast<Address>(current) + skip); |
1282 // Fall through. | 1279 // Fall through. |
1283 } | 1280 } |
1284 FOUR_CASES(kHotObject) | 1281 FOUR_CASES(kHotObject) |
1285 FOUR_CASES(kHotObject + 4) { | 1282 FOUR_CASES(kHotObject + 4) { |
1286 int index = data & kHotObjectIndexMask; | 1283 int index = data & kHotObjectIndexMask; |
1287 *current = hot_objects_.Get(index); | 1284 *current = hot_objects_.Get(index); |
1288 if (write_barrier_needed && isolate->heap()->InNewSpace(*current)) { | 1285 if (write_barrier_needed && isolate->heap()->InNewSpace(*current)) { |
1289 Address current_address = reinterpret_cast<Address>(current); | 1286 Address current_address = reinterpret_cast<Address>(current); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1390 for (int i = 0; i < kPointerSize; i++) { | 1387 for (int i = 0; i < kPointerSize; i++) { |
1391 sink_->Put(reinterpret_cast<byte*>(current)[i], "Byte"); | 1388 sink_->Put(reinterpret_cast<byte*>(current)[i], "Byte"); |
1392 } | 1389 } |
1393 } else { | 1390 } else { |
1394 SerializeObject(HeapObject::cast(*current), kPlain, kStartOfObject, 0); | 1391 SerializeObject(HeapObject::cast(*current), kPlain, kStartOfObject, 0); |
1395 } | 1392 } |
1396 } | 1393 } |
1397 } | 1394 } |
1398 | 1395 |
1399 | 1396 |
1400 void Serializer::EncodeReservations( | 1397 void Serializer::FinalizeAllocation() { |
1401 List<SerializedData::Reservation>* out) const { | |
1402 for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) { | 1398 for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) { |
1403 for (int j = 0; j < completed_chunks_[i].length(); j++) { | 1399 // Complete the last pending chunk and if there are no completed chunks, |
1404 out->Add(SerializedData::Reservation(completed_chunks_[i][j])); | 1400 // make sure there is at least one empty chunk. |
| 1401 if (pending_chunk_[i] > 0 || completed_chunks_[i].length() == 0) { |
| 1402 completed_chunks_[i].Add(pending_chunk_[i]); |
| 1403 pending_chunk_[i] = 0; |
1405 } | 1404 } |
1406 | |
1407 if (pending_chunk_[i] > 0 || completed_chunks_[i].length() == 0) { | |
1408 out->Add(SerializedData::Reservation(pending_chunk_[i])); | |
1409 } | |
1410 out->last().mark_as_last(); | |
1411 } | 1405 } |
1412 | |
1413 out->Add(SerializedData::Reservation(large_objects_total_size_)); | |
1414 out->last().mark_as_last(); | |
1415 } | 1406 } |
1416 | 1407 |
1417 | 1408 |
1418 // This ensures that the partial snapshot cache keeps things alive during GC and | 1409 // This ensures that the partial snapshot cache keeps things alive during GC and |
1419 // tracks their movement. When it is called during serialization of the startup | 1410 // tracks their movement. When it is called during serialization of the startup |
1420 // snapshot nothing happens. When the partial (context) snapshot is created, | 1411 // snapshot nothing happens. When the partial (context) snapshot is created, |
1421 // this array is populated with the pointers that the partial snapshot will | 1412 // this array is populated with the pointers that the partial snapshot will |
1422 // need. As that happens we emit serialized objects to the startup snapshot | 1413 // need. As that happens we emit serialized objects to the startup snapshot |
1423 // that correspond to the elements of this cache array. On deserialization we | 1414 // that correspond to the elements of this cache array. On deserialization we |
1424 // therefore need to visit the cache array. This fills it up with pointers to | 1415 // therefore need to visit the cache array. This fills it up with pointers to |
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1720 sink_->Put(kRawData, "RawDataForString"); | 1711 sink_->Put(kRawData, "RawDataForString"); |
1721 sink_->PutInt(bytes_to_output, "length"); | 1712 sink_->PutInt(bytes_to_output, "length"); |
1722 | 1713 |
1723 // Serialize string header (except for map). | 1714 // Serialize string header (except for map). |
1724 Address string_start = string->address(); | 1715 Address string_start = string->address(); |
1725 for (int i = HeapObject::kHeaderSize; i < SeqString::kHeaderSize; i++) { | 1716 for (int i = HeapObject::kHeaderSize; i < SeqString::kHeaderSize; i++) { |
1726 sink_->PutSection(string_start[i], "StringHeader"); | 1717 sink_->PutSection(string_start[i], "StringHeader"); |
1727 } | 1718 } |
1728 | 1719 |
1729 // Serialize string content. | 1720 // Serialize string content. |
1730 sink_->PutRaw(resource, content_size, "StringContent"); | 1721 sink_->PutRaw(const_cast<byte*>(resource), content_size, "StringContent"); |
1731 | 1722 |
1732 // Since the allocation size is rounded up to object alignment, there | 1723 // Since the allocation size is rounded up to object alignment, there |
1733 // maybe left-over bytes that need to be padded. | 1724 // maybe left-over bytes that need to be padded. |
1734 int padding_size = allocation_size - SeqString::kHeaderSize - content_size; | 1725 int padding_size = allocation_size - SeqString::kHeaderSize - content_size; |
1735 DCHECK(0 <= padding_size && padding_size < kObjectAlignment); | 1726 DCHECK(0 <= padding_size && padding_size < kObjectAlignment); |
1736 for (int i = 0; i < padding_size; i++) sink_->PutSection(0, "StringPadding"); | 1727 for (int i = 0; i < padding_size; i++) sink_->PutSection(0, "StringPadding"); |
1737 | 1728 |
1738 sink_->Put(kSkip, "SkipAfterString"); | 1729 sink_->Put(kSkip, "SkipAfterString"); |
1739 sink_->PutInt(bytes_to_output, "SkipDistance"); | 1730 sink_->PutInt(bytes_to_output, "SkipDistance"); |
1740 } | 1731 } |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2023 BackReference Serializer::Allocate(AllocationSpace space, int size) { | 2014 BackReference Serializer::Allocate(AllocationSpace space, int size) { |
2024 DCHECK(space >= 0 && space < kNumberOfPreallocatedSpaces); | 2015 DCHECK(space >= 0 && space < kNumberOfPreallocatedSpaces); |
2025 DCHECK(size > 0 && size <= static_cast<int>(max_chunk_size(space))); | 2016 DCHECK(size > 0 && size <= static_cast<int>(max_chunk_size(space))); |
2026 uint32_t new_chunk_size = pending_chunk_[space] + size; | 2017 uint32_t new_chunk_size = pending_chunk_[space] + size; |
2027 if (new_chunk_size > max_chunk_size(space)) { | 2018 if (new_chunk_size > max_chunk_size(space)) { |
2028 // The new chunk size would not fit onto a single page. Complete the | 2019 // The new chunk size would not fit onto a single page. Complete the |
2029 // current chunk and start a new one. | 2020 // current chunk and start a new one. |
2030 sink_->Put(kNextChunk, "NextChunk"); | 2021 sink_->Put(kNextChunk, "NextChunk"); |
2031 sink_->Put(space, "NextChunkSpace"); | 2022 sink_->Put(space, "NextChunkSpace"); |
2032 completed_chunks_[space].Add(pending_chunk_[space]); | 2023 completed_chunks_[space].Add(pending_chunk_[space]); |
2033 DCHECK_LE(completed_chunks_[space].length(), BackReference::kMaxChunkIndex); | |
2034 pending_chunk_[space] = 0; | 2024 pending_chunk_[space] = 0; |
2035 new_chunk_size = size; | 2025 new_chunk_size = size; |
2036 } | 2026 } |
2037 uint32_t offset = pending_chunk_[space]; | 2027 uint32_t offset = pending_chunk_[space]; |
2038 pending_chunk_[space] = new_chunk_size; | 2028 pending_chunk_[space] = new_chunk_size; |
2039 return BackReference::Reference(space, completed_chunks_[space].length(), | 2029 return BackReference::Reference(space, completed_chunks_[space].length(), |
2040 offset); | 2030 offset); |
2041 } | 2031 } |
2042 | 2032 |
2043 | 2033 |
(...skipping 24 matching lines...) Expand all Loading... |
2068 PrintF("]\n"); | 2058 PrintF("]\n"); |
2069 } | 2059 } |
2070 | 2060 |
2071 // Serialize code object. | 2061 // Serialize code object. |
2072 SnapshotByteSink sink(info->code()->CodeSize() * 2); | 2062 SnapshotByteSink sink(info->code()->CodeSize() * 2); |
2073 CodeSerializer cs(isolate, &sink, *source, info->code()); | 2063 CodeSerializer cs(isolate, &sink, *source, info->code()); |
2074 DisallowHeapAllocation no_gc; | 2064 DisallowHeapAllocation no_gc; |
2075 Object** location = Handle<Object>::cast(info).location(); | 2065 Object** location = Handle<Object>::cast(info).location(); |
2076 cs.VisitPointer(location); | 2066 cs.VisitPointer(location); |
2077 cs.Pad(); | 2067 cs.Pad(); |
| 2068 cs.FinalizeAllocation(); |
2078 | 2069 |
2079 SerializedCodeData data(sink.data(), cs); | 2070 for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) { |
| 2071 // Fail if any chunk index exceeds the limit. |
| 2072 if (cs.FinalAllocationChunks(i).length() > BackReference::kMaxChunkIndex) { |
| 2073 return NULL; |
| 2074 } |
| 2075 } |
| 2076 |
| 2077 SerializedCodeData data(sink.data(), &cs); |
2080 ScriptData* script_data = data.GetScriptData(); | 2078 ScriptData* script_data = data.GetScriptData(); |
2081 | 2079 |
2082 if (FLAG_profile_deserialization) { | 2080 if (FLAG_profile_deserialization) { |
2083 double ms = timer.Elapsed().InMillisecondsF(); | 2081 double ms = timer.Elapsed().InMillisecondsF(); |
2084 int length = script_data->length(); | 2082 int length = script_data->length(); |
2085 PrintF("[Serializing to %d bytes took %0.3f ms]\n", length, ms); | 2083 PrintF("[Serializing to %d bytes took %0.3f ms]\n", length, ms); |
2086 } | 2084 } |
2087 | 2085 |
2088 return script_data; | 2086 return script_data; |
2089 } | 2087 } |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2270 { | 2268 { |
2271 HandleScope scope(isolate); | 2269 HandleScope scope(isolate); |
2272 | 2270 |
2273 SmartPointer<SerializedCodeData> scd( | 2271 SmartPointer<SerializedCodeData> scd( |
2274 SerializedCodeData::FromCachedData(cached_data, *source)); | 2272 SerializedCodeData::FromCachedData(cached_data, *source)); |
2275 if (scd.is_empty()) { | 2273 if (scd.is_empty()) { |
2276 if (FLAG_profile_deserialization) PrintF("[Cached code failed check]\n"); | 2274 if (FLAG_profile_deserialization) PrintF("[Cached code failed check]\n"); |
2277 DCHECK(cached_data->rejected()); | 2275 DCHECK(cached_data->rejected()); |
2278 return MaybeHandle<SharedFunctionInfo>(); | 2276 return MaybeHandle<SharedFunctionInfo>(); |
2279 } | 2277 } |
| 2278 SnapshotByteSource payload(scd->Payload(), scd->PayloadLength()); |
| 2279 Deserializer deserializer(&payload); |
2280 | 2280 |
2281 // Eagerly expand string table to avoid allocations during deserialization. | 2281 // Eagerly expand string table to avoid allocations during deserialization. |
2282 StringTable::EnsureCapacityForDeserialization( | 2282 StringTable::EnsureCapacityForDeserialization( |
2283 isolate, scd->NumInternalizedStrings()); | 2283 isolate, scd->NumInternalizedStrings()); |
2284 | 2284 |
| 2285 // Set reservations. |
| 2286 STATIC_ASSERT(NEW_SPACE == 0); |
| 2287 int current_space = NEW_SPACE; |
| 2288 Vector<const SerializedCodeData::Reservation> res = scd->Reservations(); |
| 2289 for (const auto& r : res) { |
| 2290 deserializer.AddReservation(current_space, r.chunk_size()); |
| 2291 if (r.is_last_chunk()) current_space++; |
| 2292 } |
| 2293 DCHECK_EQ(kNumberOfSpaces, current_space); |
| 2294 |
2285 // Prepare and register list of attached objects. | 2295 // Prepare and register list of attached objects. |
2286 Vector<const uint32_t> code_stub_keys = scd->CodeStubKeys(); | 2296 Vector<const uint32_t> code_stub_keys = scd->CodeStubKeys(); |
2287 Vector<Handle<Object> > attached_objects = Vector<Handle<Object> >::New( | 2297 Vector<Handle<Object> > attached_objects = Vector<Handle<Object> >::New( |
2288 code_stub_keys.length() + kCodeStubsBaseIndex); | 2298 code_stub_keys.length() + kCodeStubsBaseIndex); |
2289 attached_objects[kSourceObjectIndex] = source; | 2299 attached_objects[kSourceObjectIndex] = source; |
2290 for (int i = 0; i < code_stub_keys.length(); i++) { | 2300 for (int i = 0; i < code_stub_keys.length(); i++) { |
2291 attached_objects[i + kCodeStubsBaseIndex] = | 2301 attached_objects[i + kCodeStubsBaseIndex] = |
2292 CodeStub::GetCode(isolate, code_stub_keys[i]).ToHandleChecked(); | 2302 CodeStub::GetCode(isolate, code_stub_keys[i]).ToHandleChecked(); |
2293 } | 2303 } |
2294 | |
2295 Deserializer deserializer(scd.get()); | |
2296 deserializer.SetAttachedObjects(&attached_objects); | 2304 deserializer.SetAttachedObjects(&attached_objects); |
2297 | 2305 |
2298 // Deserialize. | 2306 // Deserialize. |
2299 deserializer.DeserializePartial(isolate, &root, Deserializer::NULL_ON_OOM); | 2307 deserializer.DeserializePartial(isolate, &root, Deserializer::NULL_ON_OOM); |
2300 if (root == NULL) { | 2308 if (root == NULL) { |
2301 // Deserializing may fail if the reservations cannot be fulfilled. | 2309 // Deserializing may fail if the reservations cannot be fulfilled. |
2302 if (FLAG_profile_deserialization) PrintF("[Deserializing failed]\n"); | 2310 if (FLAG_profile_deserialization) PrintF("[Deserializing failed]\n"); |
2303 return MaybeHandle<SharedFunctionInfo>(); | 2311 return MaybeHandle<SharedFunctionInfo>(); |
2304 } | 2312 } |
2305 deserializer.FlushICacheForNewCodeObjects(); | 2313 deserializer.FlushICacheForNewCodeObjects(); |
(...skipping 15 matching lines...) Expand all Loading... |
2321 if (script->name()->IsString()) name = String::cast(script->name()); | 2329 if (script->name()->IsString()) name = String::cast(script->name()); |
2322 } | 2330 } |
2323 isolate->logger()->CodeCreateEvent(Logger::SCRIPT_TAG, result->code(), | 2331 isolate->logger()->CodeCreateEvent(Logger::SCRIPT_TAG, result->code(), |
2324 *result, NULL, name); | 2332 *result, NULL, name); |
2325 } | 2333 } |
2326 | 2334 |
2327 return result; | 2335 return result; |
2328 } | 2336 } |
2329 | 2337 |
2330 | 2338 |
2331 void SerializedData::AllocateData(int size) { | |
2332 DCHECK(!owns_data_); | |
2333 data_ = NewArray<byte>(size); | |
2334 size_ = size; | |
2335 owns_data_ = true; | |
2336 DCHECK(IsAligned(reinterpret_cast<intptr_t>(data_), kPointerAlignment)); | |
2337 } | |
2338 | |
2339 | |
2340 SnapshotData::SnapshotData(const SnapshotByteSink& sink, | |
2341 const Serializer& ser) { | |
2342 DisallowHeapAllocation no_gc; | |
2343 List<Reservation> reservations; | |
2344 ser.EncodeReservations(&reservations); | |
2345 const List<byte>& payload = sink.data(); | |
2346 | |
2347 // Calculate sizes. | |
2348 int reservation_size = reservations.length() * kInt32Size; | |
2349 int size = kHeaderSize + reservation_size + payload.length(); | |
2350 | |
2351 // Allocate backing store and create result data. | |
2352 AllocateData(size); | |
2353 | |
2354 // Set header values. | |
2355 SetHeaderValue(kCheckSumOffset, Version::Hash()); | |
2356 SetHeaderValue(kReservationsOffset, reservations.length()); | |
2357 SetHeaderValue(kPayloadLengthOffset, payload.length()); | |
2358 | |
2359 // Copy reservation chunk sizes. | |
2360 CopyBytes(data_ + kHeaderSize, reinterpret_cast<byte*>(reservations.begin()), | |
2361 reservation_size); | |
2362 | |
2363 // Copy serialized data. | |
2364 CopyBytes(data_ + kHeaderSize + reservation_size, payload.begin(), | |
2365 static_cast<size_t>(payload.length())); | |
2366 } | |
2367 | |
2368 | |
2369 bool SnapshotData::IsSane() { | |
2370 return GetHeaderValue(kCheckSumOffset) == Version::Hash(); | |
2371 } | |
2372 | |
2373 | |
2374 Vector<const SerializedData::Reservation> SnapshotData::Reservations() const { | |
2375 return Vector<const Reservation>( | |
2376 reinterpret_cast<const Reservation*>(data_ + kHeaderSize), | |
2377 GetHeaderValue(kReservationsOffset)); | |
2378 } | |
2379 | |
2380 | |
2381 Vector<const byte> SnapshotData::Payload() const { | |
2382 int reservations_size = GetHeaderValue(kReservationsOffset) * kInt32Size; | |
2383 const byte* payload = data_ + kHeaderSize + reservations_size; | |
2384 int length = GetHeaderValue(kPayloadLengthOffset); | |
2385 DCHECK_EQ(data_ + size_, payload + length); | |
2386 return Vector<const byte>(payload, length); | |
2387 } | |
2388 | |
2389 | |
2390 SerializedCodeData::SerializedCodeData(const List<byte>& payload, | 2339 SerializedCodeData::SerializedCodeData(const List<byte>& payload, |
2391 const CodeSerializer& cs) { | 2340 CodeSerializer* cs) |
| 2341 : script_data_(NULL), owns_script_data_(true) { |
2392 DisallowHeapAllocation no_gc; | 2342 DisallowHeapAllocation no_gc; |
2393 const List<uint32_t>* stub_keys = cs.stub_keys(); | 2343 List<uint32_t>* stub_keys = cs->stub_keys(); |
2394 | 2344 |
2395 List<Reservation> reservations; | 2345 // Gather reservation chunk sizes. |
2396 cs.EncodeReservations(&reservations); | 2346 List<uint32_t> reservations(SerializerDeserializer::kNumberOfSpaces); |
| 2347 STATIC_ASSERT(NEW_SPACE == 0); |
| 2348 for (int i = 0; i < SerializerDeserializer::kNumberOfSpaces; i++) { |
| 2349 Vector<const uint32_t> chunks = cs->FinalAllocationChunks(i); |
| 2350 for (int j = 0; j < chunks.length(); j++) { |
| 2351 uint32_t chunk = ChunkSizeBits::encode(chunks[j]) | |
| 2352 IsLastChunkBits::encode(j == chunks.length() - 1); |
| 2353 reservations.Add(chunk); |
| 2354 } |
| 2355 } |
2397 | 2356 |
2398 // Calculate sizes. | 2357 // Calculate sizes. |
2399 int reservation_size = reservations.length() * kInt32Size; | 2358 int reservation_size = reservations.length() * kInt32Size; |
2400 int num_stub_keys = stub_keys->length(); | 2359 int num_stub_keys = stub_keys->length(); |
2401 int stub_keys_size = stub_keys->length() * kInt32Size; | 2360 int stub_keys_size = stub_keys->length() * kInt32Size; |
2402 int size = kHeaderSize + reservation_size + stub_keys_size + payload.length(); | 2361 int data_length = |
| 2362 kHeaderSize + reservation_size + stub_keys_size + payload.length(); |
2403 | 2363 |
2404 // Allocate backing store and create result data. | 2364 // Allocate backing store and create result data. |
2405 AllocateData(size); | 2365 byte* data = NewArray<byte>(data_length); |
| 2366 DCHECK(IsAligned(reinterpret_cast<intptr_t>(data), kPointerAlignment)); |
| 2367 script_data_ = new ScriptData(data, data_length); |
| 2368 script_data_->AcquireDataOwnership(); |
2406 | 2369 |
2407 // Set header values. | 2370 // Set header values. |
2408 SetHeaderValue(kCheckSumOffset, CheckSum(cs.source())); | 2371 SetHeaderValue(kCheckSumOffset, CheckSum(cs->source())); |
2409 SetHeaderValue(kNumInternalizedStringsOffset, cs.num_internalized_strings()); | 2372 SetHeaderValue(kNumInternalizedStringsOffset, cs->num_internalized_strings()); |
2410 SetHeaderValue(kReservationsOffset, reservations.length()); | 2373 SetHeaderValue(kReservationsOffset, reservations.length()); |
2411 SetHeaderValue(kNumCodeStubKeysOffset, num_stub_keys); | 2374 SetHeaderValue(kNumCodeStubKeysOffset, num_stub_keys); |
2412 SetHeaderValue(kPayloadLengthOffset, payload.length()); | 2375 SetHeaderValue(kPayloadLengthOffset, payload.length()); |
2413 | 2376 |
2414 // Copy reservation chunk sizes. | 2377 // Copy reservation chunk sizes. |
2415 CopyBytes(data_ + kHeaderSize, reinterpret_cast<byte*>(reservations.begin()), | 2378 CopyBytes(data + kHeaderSize, reinterpret_cast<byte*>(reservations.begin()), |
2416 reservation_size); | 2379 reservation_size); |
2417 | 2380 |
2418 // Copy code stub keys. | 2381 // Copy code stub keys. |
2419 CopyBytes(data_ + kHeaderSize + reservation_size, | 2382 CopyBytes(data + kHeaderSize + reservation_size, |
2420 reinterpret_cast<byte*>(stub_keys->begin()), stub_keys_size); | 2383 reinterpret_cast<byte*>(stub_keys->begin()), stub_keys_size); |
2421 | 2384 |
2422 // Copy serialized data. | 2385 // Copy serialized data. |
2423 CopyBytes(data_ + kHeaderSize + reservation_size + stub_keys_size, | 2386 CopyBytes(data + kHeaderSize + reservation_size + stub_keys_size, |
2424 payload.begin(), static_cast<size_t>(payload.length())); | 2387 payload.begin(), static_cast<size_t>(payload.length())); |
2425 } | 2388 } |
2426 | 2389 |
2427 | 2390 |
2428 bool SerializedCodeData::IsSane(String* source) { | 2391 bool SerializedCodeData::IsSane(String* source) { |
2429 return GetHeaderValue(kCheckSumOffset) == CheckSum(source) && | 2392 return GetHeaderValue(kCheckSumOffset) == CheckSum(source) && |
2430 Payload().length() >= SharedFunctionInfo::kSize; | 2393 PayloadLength() >= SharedFunctionInfo::kSize; |
2431 } | 2394 } |
2432 | 2395 |
2433 | 2396 |
2434 int SerializedCodeData::CheckSum(String* string) { | 2397 int SerializedCodeData::CheckSum(String* string) { |
2435 return Version::Hash() ^ string->length(); | 2398 return Version::Hash() ^ string->length(); |
2436 } | 2399 } |
2437 | |
2438 | |
2439 // Return ScriptData object and relinquish ownership over it to the caller. | |
2440 ScriptData* SerializedCodeData::GetScriptData() { | |
2441 DCHECK(owns_data_); | |
2442 ScriptData* result = new ScriptData(data_, size_); | |
2443 result->AcquireDataOwnership(); | |
2444 owns_data_ = false; | |
2445 data_ = NULL; | |
2446 return result; | |
2447 } | |
2448 | |
2449 | |
2450 Vector<const SerializedData::Reservation> SerializedCodeData::Reservations() | |
2451 const { | |
2452 return Vector<const Reservation>( | |
2453 reinterpret_cast<const Reservation*>(data_ + kHeaderSize), | |
2454 GetHeaderValue(kReservationsOffset)); | |
2455 } | |
2456 | |
2457 | |
2458 Vector<const byte> SerializedCodeData::Payload() const { | |
2459 int reservations_size = GetHeaderValue(kReservationsOffset) * kInt32Size; | |
2460 int code_stubs_size = GetHeaderValue(kNumCodeStubKeysOffset) * kInt32Size; | |
2461 const byte* payload = | |
2462 data_ + kHeaderSize + reservations_size + code_stubs_size; | |
2463 int length = GetHeaderValue(kPayloadLengthOffset); | |
2464 DCHECK_EQ(data_ + size_, payload + length); | |
2465 return Vector<const byte>(payload, length); | |
2466 } | |
2467 | |
2468 | |
2469 int SerializedCodeData::NumInternalizedStrings() const { | |
2470 return GetHeaderValue(kNumInternalizedStringsOffset); | |
2471 } | |
2472 | |
2473 Vector<const uint32_t> SerializedCodeData::CodeStubKeys() const { | |
2474 int reservations_size = GetHeaderValue(kReservationsOffset) * kInt32Size; | |
2475 const byte* start = data_ + kHeaderSize + reservations_size; | |
2476 return Vector<const uint32_t>(reinterpret_cast<const uint32_t*>(start), | |
2477 GetHeaderValue(kNumCodeStubKeysOffset)); | |
2478 } | |
2479 } } // namespace v8::internal | 2400 } } // namespace v8::internal |
OLD | NEW |