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