Chromium Code Reviews| 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 Deserializer::Deserializer(SerializedData* sd) |
| 615 : isolate_(NULL), | 615 : isolate_(NULL), |
| 616 attached_objects_(NULL), | 616 attached_objects_(NULL), |
| 617 source_(source), | 617 source_(sd->Payload()), |
| 618 external_reference_decoder_(NULL), | 618 external_reference_decoder_(NULL), |
| 619 deserialized_large_objects_(0) { | 619 deserialized_large_objects_(0) { |
| 620 // Set reservations. | |
| 621 STATIC_ASSERT(NEW_SPACE == 0); | |
| 622 int current_space = NEW_SPACE; | |
| 623 Vector<const SerializedData::Reservation> res = sd->Reservations(); | |
| 624 for (const auto& r : res) { | |
| 625 reservations_[current_space].Add({r.chunk_size(), NULL, NULL}); | |
| 626 if (r.is_last()) current_space++; | |
| 627 } | |
| 628 DCHECK_EQ(kNumberOfSpaces, current_space); | |
| 620 for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) current_chunk_[i] = 0; | 629 for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) current_chunk_[i] = 0; |
| 621 } | 630 } |
| 622 | 631 |
| 623 | 632 |
| 624 void Deserializer::FlushICacheForNewCodeObjects() { | 633 void Deserializer::FlushICacheForNewCodeObjects() { |
| 625 PageIterator it(isolate_->heap()->code_space()); | 634 PageIterator it(isolate_->heap()->code_space()); |
| 626 while (it.has_next()) { | 635 while (it.has_next()) { |
| 627 Page* p = it.next(); | 636 Page* p = it.next(); |
| 628 CpuFeatures::FlushICache(p->area_start(), p->area_end() - p->area_start()); | 637 CpuFeatures::FlushICache(p->area_start(), p->area_end() - p->area_start()); |
| 629 } | 638 } |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 709 | 718 |
| 710 // There's no code deserialized here. If this assert fires | 719 // There's no code deserialized here. If this assert fires |
| 711 // then that's changed and logging should be added to notify | 720 // then that's changed and logging should be added to notify |
| 712 // the profiler et al of the new code. | 721 // the profiler et al of the new code. |
| 713 CHECK_EQ(start_address, code_space->top()); | 722 CHECK_EQ(start_address, code_space->top()); |
| 714 } | 723 } |
| 715 | 724 |
| 716 | 725 |
| 717 Deserializer::~Deserializer() { | 726 Deserializer::~Deserializer() { |
| 718 // TODO(svenpanne) Re-enable this assertion when v8 initialization is fixed. | 727 // TODO(svenpanne) Re-enable this assertion when v8 initialization is fixed. |
| 719 // DCHECK(source_->AtEOF()); | 728 // DCHECK(source_.AtEOF()); |
| 720 if (external_reference_decoder_) { | 729 if (external_reference_decoder_) { |
| 721 delete external_reference_decoder_; | 730 delete external_reference_decoder_; |
| 722 external_reference_decoder_ = NULL; | 731 external_reference_decoder_ = NULL; |
| 723 } | 732 } |
| 724 if (attached_objects_) attached_objects_->Dispose(); | 733 if (attached_objects_) attached_objects_->Dispose(); |
| 725 } | 734 } |
| 726 | 735 |
| 727 | 736 |
| 728 // This is called on the roots. It is the driver of the deserialization | 737 // 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. | 738 // process. It is also called on the body of each function. |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 803 | 812 |
| 804 | 813 |
| 805 // This routine writes the new object into the pointer provided and then | 814 // This routine writes the new object into the pointer provided and then |
| 806 // returns true if the new object was in young space and false otherwise. | 815 // returns true if the new object was in young space and false otherwise. |
| 807 // The reason for this strange interface is that otherwise the object is | 816 // The reason for this strange interface is that otherwise the object is |
| 808 // written very late, which means the FreeSpace map is not set up by the | 817 // written very late, which means the FreeSpace map is not set up by the |
| 809 // time we need to use it to mark the space at the end of a page free. | 818 // time we need to use it to mark the space at the end of a page free. |
| 810 void Deserializer::ReadObject(int space_number, Object** write_back) { | 819 void Deserializer::ReadObject(int space_number, Object** write_back) { |
| 811 Address address; | 820 Address address; |
| 812 HeapObject* obj; | 821 HeapObject* obj; |
| 813 int next_int = source_->GetInt(); | 822 int next_int = source_.GetInt(); |
| 814 | 823 |
| 815 bool double_align = false; | 824 bool double_align = false; |
| 816 #ifndef V8_HOST_ARCH_64_BIT | 825 #ifndef V8_HOST_ARCH_64_BIT |
| 817 double_align = next_int == kDoubleAlignmentSentinel; | 826 double_align = next_int == kDoubleAlignmentSentinel; |
| 818 if (double_align) next_int = source_->GetInt(); | 827 if (double_align) next_int = source_.GetInt(); |
| 819 #endif | 828 #endif |
| 820 | 829 |
| 821 DCHECK_NE(kDoubleAlignmentSentinel, next_int); | 830 DCHECK_NE(kDoubleAlignmentSentinel, next_int); |
| 822 int size = next_int << kObjectAlignmentBits; | 831 int size = next_int << kObjectAlignmentBits; |
| 823 int reserved_size = size + (double_align ? kPointerSize : 0); | 832 int reserved_size = size + (double_align ? kPointerSize : 0); |
| 824 address = Allocate(space_number, reserved_size); | 833 address = Allocate(space_number, reserved_size); |
| 825 obj = HeapObject::FromAddress(address); | 834 obj = HeapObject::FromAddress(address); |
| 826 if (double_align) { | 835 if (double_align) { |
| 827 obj = isolate_->heap()->DoubleAlignForDeserialization(obj, reserved_size); | 836 obj = isolate_->heap()->DoubleAlignForDeserialization(obj, reserved_size); |
| 828 address = obj->address(); | 837 address = obj->address(); |
| 829 } | 838 } |
| 830 | 839 |
| 831 isolate_->heap()->OnAllocationEvent(obj, size); | 840 isolate_->heap()->OnAllocationEvent(obj, size); |
| 832 Object** current = reinterpret_cast<Object**>(address); | 841 Object** current = reinterpret_cast<Object**>(address); |
| 833 Object** limit = current + (size >> kPointerSizeLog2); | 842 Object** limit = current + (size >> kPointerSizeLog2); |
| 834 if (FLAG_log_snapshot_positions) { | 843 if (FLAG_log_snapshot_positions) { |
| 835 LOG(isolate_, SnapshotPositionEvent(address, source_->position())); | 844 LOG(isolate_, SnapshotPositionEvent(address, source_.position())); |
| 836 } | 845 } |
| 837 ReadData(current, limit, space_number, address); | 846 ReadData(current, limit, space_number, address); |
| 838 | 847 |
| 839 // TODO(mvstanton): consider treating the heap()->allocation_sites_list() | 848 // TODO(mvstanton): consider treating the heap()->allocation_sites_list() |
| 840 // as a (weak) root. If this root is relocated correctly, | 849 // as a (weak) root. If this root is relocated correctly, |
| 841 // RelinkAllocationSite() isn't necessary. | 850 // RelinkAllocationSite() isn't necessary. |
| 842 if (obj->IsAllocationSite()) RelinkAllocationSite(AllocationSite::cast(obj)); | 851 if (obj->IsAllocationSite()) RelinkAllocationSite(AllocationSite::cast(obj)); |
| 843 | 852 |
| 844 // Fix up strings from serialized user code. | 853 // Fix up strings from serialized user code. |
| 845 if (deserializing_user_code()) obj = ProcessNewObjectFromSerializedCode(obj); | 854 if (deserializing_user_code()) obj = ProcessNewObjectFromSerializedCode(obj); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 863 // because it would not fit onto a single page. We do not have to keep | 872 // because it would not fit onto a single page. We do not have to keep |
| 864 // track of when to move to the next chunk. An opcode will signal this. | 873 // track of when to move to the next chunk. An opcode will signal this. |
| 865 // Since multiple large objects cannot be folded into one large object | 874 // Since multiple large objects cannot be folded into one large object |
| 866 // space allocation, we have to do an actual allocation when deserializing | 875 // space allocation, we have to do an actual allocation when deserializing |
| 867 // each large object. Instead of tracking offset for back references, we | 876 // each large object. Instead of tracking offset for back references, we |
| 868 // reference large objects by index. | 877 // reference large objects by index. |
| 869 Address Deserializer::Allocate(int space_index, int size) { | 878 Address Deserializer::Allocate(int space_index, int size) { |
| 870 if (space_index == LO_SPACE) { | 879 if (space_index == LO_SPACE) { |
| 871 AlwaysAllocateScope scope(isolate_); | 880 AlwaysAllocateScope scope(isolate_); |
| 872 LargeObjectSpace* lo_space = isolate_->heap()->lo_space(); | 881 LargeObjectSpace* lo_space = isolate_->heap()->lo_space(); |
| 873 Executability exec = static_cast<Executability>(source_->Get()); | 882 Executability exec = static_cast<Executability>(source_.Get()); |
| 874 AllocationResult result = lo_space->AllocateRaw(size, exec); | 883 AllocationResult result = lo_space->AllocateRaw(size, exec); |
| 875 HeapObject* obj = HeapObject::cast(result.ToObjectChecked()); | 884 HeapObject* obj = HeapObject::cast(result.ToObjectChecked()); |
| 876 deserialized_large_objects_.Add(obj); | 885 deserialized_large_objects_.Add(obj); |
| 877 return obj->address(); | 886 return obj->address(); |
| 878 } else { | 887 } else { |
| 879 DCHECK(space_index < kNumberOfPreallocatedSpaces); | 888 DCHECK(space_index < kNumberOfPreallocatedSpaces); |
| 880 Address address = high_water_[space_index]; | 889 Address address = high_water_[space_index]; |
| 881 DCHECK_NE(NULL, address); | 890 DCHECK_NE(NULL, address); |
| 882 high_water_[space_index] += size; | 891 high_water_[space_index] += size; |
| 883 #ifdef DEBUG | 892 #ifdef DEBUG |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 897 // Write barrier support costs around 1% in startup time. In fact there | 906 // Write barrier support costs around 1% in startup time. In fact there |
| 898 // are no new space objects in current boot snapshots, so it's not needed, | 907 // are no new space objects in current boot snapshots, so it's not needed, |
| 899 // but that may change. | 908 // but that may change. |
| 900 bool write_barrier_needed = (current_object_address != NULL && | 909 bool write_barrier_needed = (current_object_address != NULL && |
| 901 source_space != NEW_SPACE && | 910 source_space != NEW_SPACE && |
| 902 source_space != CELL_SPACE && | 911 source_space != CELL_SPACE && |
| 903 source_space != PROPERTY_CELL_SPACE && | 912 source_space != PROPERTY_CELL_SPACE && |
| 904 source_space != CODE_SPACE && | 913 source_space != CODE_SPACE && |
| 905 source_space != OLD_DATA_SPACE); | 914 source_space != OLD_DATA_SPACE); |
| 906 while (current < limit) { | 915 while (current < limit) { |
| 907 int data = source_->Get(); | 916 int data = source_.Get(); |
| 908 switch (data) { | 917 switch (data) { |
| 909 #define CASE_STATEMENT(where, how, within, space_number) \ | 918 #define CASE_STATEMENT(where, how, within, space_number) \ |
| 910 case where + how + within + space_number: \ | 919 case where + how + within + space_number: \ |
| 911 STATIC_ASSERT((where & ~kPointedToMask) == 0); \ | 920 STATIC_ASSERT((where & ~kPointedToMask) == 0); \ |
| 912 STATIC_ASSERT((how & ~kHowToCodeMask) == 0); \ | 921 STATIC_ASSERT((how & ~kHowToCodeMask) == 0); \ |
| 913 STATIC_ASSERT((within & ~kWhereToPointMask) == 0); \ | 922 STATIC_ASSERT((within & ~kWhereToPointMask) == 0); \ |
| 914 STATIC_ASSERT((space_number & ~kSpaceMask) == 0); | 923 STATIC_ASSERT((space_number & ~kSpaceMask) == 0); |
| 915 | 924 |
| 916 #define CASE_BODY(where, how, within, space_number_if_any) \ | 925 #define CASE_BODY(where, how, within, space_number_if_any) \ |
| 917 { \ | 926 { \ |
| 918 bool emit_write_barrier = false; \ | 927 bool emit_write_barrier = false; \ |
| 919 bool current_was_incremented = false; \ | 928 bool current_was_incremented = false; \ |
| 920 int space_number = space_number_if_any == kAnyOldSpace \ | 929 int space_number = space_number_if_any == kAnyOldSpace \ |
| 921 ? (data & kSpaceMask) \ | 930 ? (data & kSpaceMask) \ |
| 922 : space_number_if_any; \ | 931 : space_number_if_any; \ |
| 923 if (where == kNewObject && how == kPlain && within == kStartOfObject) { \ | 932 if (where == kNewObject && how == kPlain && within == kStartOfObject) { \ |
| 924 ReadObject(space_number, current); \ | 933 ReadObject(space_number, current); \ |
| 925 emit_write_barrier = (space_number == NEW_SPACE); \ | 934 emit_write_barrier = (space_number == NEW_SPACE); \ |
| 926 } else { \ | 935 } else { \ |
| 927 Object* new_object = NULL; /* May not be a real Object pointer. */ \ | 936 Object* new_object = NULL; /* May not be a real Object pointer. */ \ |
| 928 if (where == kNewObject) { \ | 937 if (where == kNewObject) { \ |
| 929 ReadObject(space_number, &new_object); \ | 938 ReadObject(space_number, &new_object); \ |
| 930 } else if (where == kRootArray) { \ | 939 } else if (where == kRootArray) { \ |
| 931 int root_id = source_->GetInt(); \ | 940 int root_id = source_.GetInt(); \ |
| 932 new_object = isolate->heap()->roots_array_start()[root_id]; \ | 941 new_object = isolate->heap()->roots_array_start()[root_id]; \ |
| 933 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ | 942 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ |
| 934 } else if (where == kPartialSnapshotCache) { \ | 943 } else if (where == kPartialSnapshotCache) { \ |
| 935 int cache_index = source_->GetInt(); \ | 944 int cache_index = source_.GetInt(); \ |
| 936 new_object = isolate->serialize_partial_snapshot_cache()[cache_index]; \ | 945 new_object = isolate->serialize_partial_snapshot_cache()[cache_index]; \ |
| 937 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ | 946 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ |
| 938 } else if (where == kExternalReference) { \ | 947 } else if (where == kExternalReference) { \ |
| 939 int skip = source_->GetInt(); \ | 948 int skip = source_.GetInt(); \ |
| 940 current = reinterpret_cast<Object**>( \ | 949 current = reinterpret_cast<Object**>( \ |
| 941 reinterpret_cast<Address>(current) + skip); \ | 950 reinterpret_cast<Address>(current) + skip); \ |
| 942 int reference_id = source_->GetInt(); \ | 951 int reference_id = source_.GetInt(); \ |
| 943 Address address = external_reference_decoder_->Decode(reference_id); \ | 952 Address address = external_reference_decoder_->Decode(reference_id); \ |
| 944 new_object = reinterpret_cast<Object*>(address); \ | 953 new_object = reinterpret_cast<Object*>(address); \ |
| 945 } else if (where == kBackref) { \ | 954 } else if (where == kBackref) { \ |
| 946 emit_write_barrier = (space_number == NEW_SPACE); \ | 955 emit_write_barrier = (space_number == NEW_SPACE); \ |
| 947 new_object = GetBackReferencedObject(data & kSpaceMask); \ | 956 new_object = GetBackReferencedObject(data & kSpaceMask); \ |
| 948 if (deserializing_user_code()) { \ | 957 if (deserializing_user_code()) { \ |
| 949 new_object = ProcessBackRefInSerializedCode(new_object); \ | 958 new_object = ProcessBackRefInSerializedCode(new_object); \ |
| 950 } \ | 959 } \ |
| 951 } else if (where == kBuiltin) { \ | 960 } else if (where == kBuiltin) { \ |
| 952 DCHECK(deserializing_user_code()); \ | 961 DCHECK(deserializing_user_code()); \ |
| 953 int builtin_id = source_->GetInt(); \ | 962 int builtin_id = source_.GetInt(); \ |
| 954 DCHECK_LE(0, builtin_id); \ | 963 DCHECK_LE(0, builtin_id); \ |
| 955 DCHECK_LT(builtin_id, Builtins::builtin_count); \ | 964 DCHECK_LT(builtin_id, Builtins::builtin_count); \ |
| 956 Builtins::Name name = static_cast<Builtins::Name>(builtin_id); \ | 965 Builtins::Name name = static_cast<Builtins::Name>(builtin_id); \ |
| 957 new_object = isolate->builtins()->builtin(name); \ | 966 new_object = isolate->builtins()->builtin(name); \ |
| 958 emit_write_barrier = false; \ | 967 emit_write_barrier = false; \ |
| 959 } else if (where == kAttachedReference) { \ | 968 } else if (where == kAttachedReference) { \ |
| 960 DCHECK(deserializing_user_code()); \ | 969 DCHECK(deserializing_user_code()); \ |
| 961 int index = source_->GetInt(); \ | 970 int index = source_.GetInt(); \ |
| 962 new_object = *attached_objects_->at(index); \ | 971 new_object = *attached_objects_->at(index); \ |
| 963 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ | 972 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ |
| 964 } else { \ | 973 } else { \ |
| 965 DCHECK(where == kBackrefWithSkip); \ | 974 DCHECK(where == kBackrefWithSkip); \ |
| 966 int skip = source_->GetInt(); \ | 975 int skip = source_.GetInt(); \ |
| 967 current = reinterpret_cast<Object**>( \ | 976 current = reinterpret_cast<Object**>( \ |
| 968 reinterpret_cast<Address>(current) + skip); \ | 977 reinterpret_cast<Address>(current) + skip); \ |
| 969 emit_write_barrier = (space_number == NEW_SPACE); \ | 978 emit_write_barrier = (space_number == NEW_SPACE); \ |
| 970 new_object = GetBackReferencedObject(data & kSpaceMask); \ | 979 new_object = GetBackReferencedObject(data & kSpaceMask); \ |
| 971 if (deserializing_user_code()) { \ | 980 if (deserializing_user_code()) { \ |
| 972 new_object = ProcessBackRefInSerializedCode(new_object); \ | 981 new_object = ProcessBackRefInSerializedCode(new_object); \ |
| 973 } \ | 982 } \ |
| 974 } \ | 983 } \ |
| 975 if (within == kInnerPointer) { \ | 984 if (within == kInnerPointer) { \ |
| 976 if (space_number != CODE_SPACE || new_object->IsCode()) { \ | 985 if (space_number != CODE_SPACE || new_object->IsCode()) { \ |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1063 f(25) \ | 1072 f(25) \ |
| 1064 f(26) \ | 1073 f(26) \ |
| 1065 f(27) \ | 1074 f(27) \ |
| 1066 f(28) \ | 1075 f(28) \ |
| 1067 f(29) \ | 1076 f(29) \ |
| 1068 f(30) \ | 1077 f(30) \ |
| 1069 f(31) | 1078 f(31) |
| 1070 | 1079 |
| 1071 // We generate 15 cases and bodies that process special tags that combine | 1080 // We generate 15 cases and bodies that process special tags that combine |
| 1072 // the raw data tag and the length into one byte. | 1081 // the raw data tag and the length into one byte. |
| 1073 #define RAW_CASE(index) \ | 1082 #define RAW_CASE(index) \ |
| 1074 case kRawData + index: { \ | 1083 case kRawData + index: { \ |
| 1075 byte* raw_data_out = reinterpret_cast<byte*>(current); \ | 1084 byte* raw_data_out = reinterpret_cast<byte*>(current); \ |
| 1076 source_->CopyRaw(raw_data_out, index * kPointerSize); \ | 1085 source_.CopyRaw(raw_data_out, index* kPointerSize); \ |
| 1077 current = \ | 1086 current = reinterpret_cast<Object**>(raw_data_out + index * kPointerSize); \ |
| 1078 reinterpret_cast<Object**>(raw_data_out + index * kPointerSize); \ | 1087 break; \ |
| 1079 break; \ | 1088 } |
| 1080 } | |
| 1081 COMMON_RAW_LENGTHS(RAW_CASE) | 1089 COMMON_RAW_LENGTHS(RAW_CASE) |
| 1082 #undef RAW_CASE | 1090 #undef RAW_CASE |
| 1083 | 1091 |
| 1084 // 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 |
| 1085 // lengths. | 1093 // lengths. |
| 1086 case kRawData: { | 1094 case kRawData: { |
| 1087 int size = source_->GetInt(); | 1095 int size = source_.GetInt(); |
| 1088 byte* raw_data_out = reinterpret_cast<byte*>(current); | 1096 byte* raw_data_out = reinterpret_cast<byte*>(current); |
| 1089 source_->CopyRaw(raw_data_out, size); | 1097 source_.CopyRaw(raw_data_out, size); |
| 1090 break; | 1098 break; |
| 1091 } | 1099 } |
| 1092 | 1100 |
| 1093 SIXTEEN_CASES(kRootArrayConstants + kNoSkipDistance) | 1101 SIXTEEN_CASES(kRootArrayConstants + kNoSkipDistance) |
| 1094 SIXTEEN_CASES(kRootArrayConstants + kNoSkipDistance + 16) { | 1102 SIXTEEN_CASES(kRootArrayConstants + kNoSkipDistance + 16) { |
| 1095 int root_id = RootArrayConstantFromByteCode(data); | 1103 int root_id = RootArrayConstantFromByteCode(data); |
| 1096 Object* object = isolate->heap()->roots_array_start()[root_id]; | 1104 Object* object = isolate->heap()->roots_array_start()[root_id]; |
| 1097 DCHECK(!isolate->heap()->InNewSpace(object)); | 1105 DCHECK(!isolate->heap()->InNewSpace(object)); |
| 1098 *current++ = object; | 1106 *current++ = object; |
| 1099 break; | 1107 break; |
| 1100 } | 1108 } |
| 1101 | 1109 |
| 1102 SIXTEEN_CASES(kRootArrayConstants + kHasSkipDistance) | 1110 SIXTEEN_CASES(kRootArrayConstants + kHasSkipDistance) |
| 1103 SIXTEEN_CASES(kRootArrayConstants + kHasSkipDistance + 16) { | 1111 SIXTEEN_CASES(kRootArrayConstants + kHasSkipDistance + 16) { |
| 1104 int root_id = RootArrayConstantFromByteCode(data); | 1112 int root_id = RootArrayConstantFromByteCode(data); |
| 1105 int skip = source_->GetInt(); | 1113 int skip = source_.GetInt(); |
| 1106 current = reinterpret_cast<Object**>( | 1114 current = reinterpret_cast<Object**>( |
| 1107 reinterpret_cast<intptr_t>(current) + skip); | 1115 reinterpret_cast<intptr_t>(current) + skip); |
| 1108 Object* object = isolate->heap()->roots_array_start()[root_id]; | 1116 Object* object = isolate->heap()->roots_array_start()[root_id]; |
| 1109 DCHECK(!isolate->heap()->InNewSpace(object)); | 1117 DCHECK(!isolate->heap()->InNewSpace(object)); |
| 1110 *current++ = object; | 1118 *current++ = object; |
| 1111 break; | 1119 break; |
| 1112 } | 1120 } |
| 1113 | 1121 |
| 1114 case kRepeat: { | 1122 case kRepeat: { |
| 1115 int repeats = source_->GetInt(); | 1123 int repeats = source_.GetInt(); |
| 1116 Object* object = current[-1]; | 1124 Object* object = current[-1]; |
| 1117 DCHECK(!isolate->heap()->InNewSpace(object)); | 1125 DCHECK(!isolate->heap()->InNewSpace(object)); |
| 1118 for (int i = 0; i < repeats; i++) current[i] = object; | 1126 for (int i = 0; i < repeats; i++) current[i] = object; |
| 1119 current += repeats; | 1127 current += repeats; |
| 1120 break; | 1128 break; |
| 1121 } | 1129 } |
| 1122 | 1130 |
| 1123 STATIC_ASSERT(kRootArrayNumberOfConstantEncodings == | 1131 STATIC_ASSERT(kRootArrayNumberOfConstantEncodings == |
| 1124 Heap::kOldSpaceRoots); | 1132 Heap::kOldSpaceRoots); |
| 1125 STATIC_ASSERT(kMaxRepeats == 13); | 1133 STATIC_ASSERT(kMaxRepeats == 13); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1223 CASE_STATEMENT(kAttachedReference, kPlain, kInnerPointer, 0) | 1231 CASE_STATEMENT(kAttachedReference, kPlain, kInnerPointer, 0) |
| 1224 CASE_BODY(kAttachedReference, kPlain, kInnerPointer, 0) | 1232 CASE_BODY(kAttachedReference, kPlain, kInnerPointer, 0) |
| 1225 CASE_STATEMENT(kAttachedReference, kFromCode, kInnerPointer, 0) | 1233 CASE_STATEMENT(kAttachedReference, kFromCode, kInnerPointer, 0) |
| 1226 CASE_BODY(kAttachedReference, kFromCode, kInnerPointer, 0) | 1234 CASE_BODY(kAttachedReference, kFromCode, kInnerPointer, 0) |
| 1227 | 1235 |
| 1228 #undef CASE_STATEMENT | 1236 #undef CASE_STATEMENT |
| 1229 #undef CASE_BODY | 1237 #undef CASE_BODY |
| 1230 #undef ALL_SPACES | 1238 #undef ALL_SPACES |
| 1231 | 1239 |
| 1232 case kSkip: { | 1240 case kSkip: { |
| 1233 int size = source_->GetInt(); | 1241 int size = source_.GetInt(); |
| 1234 current = reinterpret_cast<Object**>( | 1242 current = reinterpret_cast<Object**>( |
| 1235 reinterpret_cast<intptr_t>(current) + size); | 1243 reinterpret_cast<intptr_t>(current) + size); |
| 1236 break; | 1244 break; |
| 1237 } | 1245 } |
| 1238 | 1246 |
| 1239 case kNativesStringResource: { | 1247 case kNativesStringResource: { |
| 1240 int index = source_->Get(); | 1248 int index = source_.Get(); |
| 1241 Vector<const char> source_vector = Natives::GetRawScriptSource(index); | 1249 Vector<const char> source_vector = Natives::GetRawScriptSource(index); |
| 1242 NativesExternalStringResource* resource = | 1250 NativesExternalStringResource* resource = |
| 1243 new NativesExternalStringResource(isolate->bootstrapper(), | 1251 new NativesExternalStringResource(isolate->bootstrapper(), |
| 1244 source_vector.start(), | 1252 source_vector.start(), |
| 1245 source_vector.length()); | 1253 source_vector.length()); |
| 1246 *current++ = reinterpret_cast<Object*>(resource); | 1254 *current++ = reinterpret_cast<Object*>(resource); |
| 1247 break; | 1255 break; |
| 1248 } | 1256 } |
| 1249 | 1257 |
| 1250 case kNextChunk: { | 1258 case kNextChunk: { |
| 1251 int space = source_->Get(); | 1259 int space = source_.Get(); |
| 1252 DCHECK(space < kNumberOfPreallocatedSpaces); | 1260 DCHECK(space < kNumberOfPreallocatedSpaces); |
| 1253 int chunk_index = current_chunk_[space]; | 1261 int chunk_index = current_chunk_[space]; |
| 1254 const Heap::Reservation& reservation = reservations_[space]; | 1262 const Heap::Reservation& reservation = reservations_[space]; |
| 1255 // Make sure the current chunk is indeed exhausted. | 1263 // Make sure the current chunk is indeed exhausted. |
| 1256 CHECK_EQ(reservation[chunk_index].end, high_water_[space]); | 1264 CHECK_EQ(reservation[chunk_index].end, high_water_[space]); |
| 1257 // Move to next reserved chunk. | 1265 // Move to next reserved chunk. |
| 1258 chunk_index = ++current_chunk_[space]; | 1266 chunk_index = ++current_chunk_[space]; |
| 1259 DCHECK_LT(chunk_index, reservation.length()); | 1267 DCHECK_LT(chunk_index, reservation.length()); |
| 1260 high_water_[space] = reservation[chunk_index].start; | 1268 high_water_[space] = reservation[chunk_index].start; |
| 1261 break; | 1269 break; |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1356 for (int i = 0; i < kPointerSize; i++) { | 1364 for (int i = 0; i < kPointerSize; i++) { |
| 1357 sink_->Put(reinterpret_cast<byte*>(current)[i], "Byte"); | 1365 sink_->Put(reinterpret_cast<byte*>(current)[i], "Byte"); |
| 1358 } | 1366 } |
| 1359 } else { | 1367 } else { |
| 1360 SerializeObject(HeapObject::cast(*current), kPlain, kStartOfObject, 0); | 1368 SerializeObject(HeapObject::cast(*current), kPlain, kStartOfObject, 0); |
| 1361 } | 1369 } |
| 1362 } | 1370 } |
| 1363 } | 1371 } |
| 1364 | 1372 |
| 1365 | 1373 |
| 1366 void Serializer::FinalizeAllocation() { | 1374 void Serializer::EncodeReservations( |
| 1375 List<SerializedData::Reservation>* out) const { | |
| 1367 for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) { | 1376 for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) { |
| 1368 // Complete the last pending chunk and if there are no completed chunks, | 1377 for (int j = 0; j < completed_chunks_[i].length(); j++) { |
| 1369 // make sure there is at least one empty chunk. | 1378 out->Add(SerializedData::Reservation(completed_chunks_[i][j])); |
| 1379 } | |
| 1380 | |
| 1370 if (pending_chunk_[i] > 0 || completed_chunks_[i].length() == 0) { | 1381 if (pending_chunk_[i] > 0 || completed_chunks_[i].length() == 0) { |
| 1371 completed_chunks_[i].Add(pending_chunk_[i]); | 1382 out->Add(SerializedData::Reservation(pending_chunk_[i])); |
| 1372 pending_chunk_[i] = 0; | |
| 1373 } | 1383 } |
| 1384 out->last().mark_as_last(); | |
| 1374 } | 1385 } |
| 1386 | |
| 1387 out->Add(SerializedData::Reservation(large_objects_total_size_)); | |
| 1388 out->last().mark_as_last(); | |
| 1375 } | 1389 } |
| 1376 | 1390 |
| 1377 | 1391 |
| 1378 // This ensures that the partial snapshot cache keeps things alive during GC and | 1392 // This ensures that the partial snapshot cache keeps things alive during GC and |
| 1379 // tracks their movement. When it is called during serialization of the startup | 1393 // tracks their movement. When it is called during serialization of the startup |
| 1380 // snapshot nothing happens. When the partial (context) snapshot is created, | 1394 // snapshot nothing happens. When the partial (context) snapshot is created, |
| 1381 // this array is populated with the pointers that the partial snapshot will | 1395 // this array is populated with the pointers that the partial snapshot will |
| 1382 // need. As that happens we emit serialized objects to the startup snapshot | 1396 // need. As that happens we emit serialized objects to the startup snapshot |
| 1383 // that correspond to the elements of this cache array. On deserialization we | 1397 // that correspond to the elements of this cache array. On deserialization we |
| 1384 // therefore need to visit the cache array. This fills it up with pointers to | 1398 // therefore need to visit the cache array. This fills it up with pointers to |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1656 sink_->Put(kRawData, "RawDataForString"); | 1670 sink_->Put(kRawData, "RawDataForString"); |
| 1657 sink_->PutInt(bytes_to_output, "length"); | 1671 sink_->PutInt(bytes_to_output, "length"); |
| 1658 | 1672 |
| 1659 // Serialize string header (except for map). | 1673 // Serialize string header (except for map). |
| 1660 Address string_start = string->address(); | 1674 Address string_start = string->address(); |
| 1661 for (int i = HeapObject::kHeaderSize; i < SeqString::kHeaderSize; i++) { | 1675 for (int i = HeapObject::kHeaderSize; i < SeqString::kHeaderSize; i++) { |
| 1662 sink_->PutSection(string_start[i], "StringHeader"); | 1676 sink_->PutSection(string_start[i], "StringHeader"); |
| 1663 } | 1677 } |
| 1664 | 1678 |
| 1665 // Serialize string content. | 1679 // Serialize string content. |
| 1666 sink_->PutRaw(const_cast<byte*>(resource), content_size, "StringContent"); | 1680 sink_->PutRaw(resource, content_size, "StringContent"); |
| 1667 | 1681 |
| 1668 // Since the allocation size is rounded up to object alignment, there | 1682 // Since the allocation size is rounded up to object alignment, there |
| 1669 // maybe left-over bytes that need to be padded. | 1683 // maybe left-over bytes that need to be padded. |
| 1670 int padding_size = allocation_size - SeqString::kHeaderSize - content_size; | 1684 int padding_size = allocation_size - SeqString::kHeaderSize - content_size; |
| 1671 DCHECK(0 <= padding_size && padding_size < kObjectAlignment); | 1685 DCHECK(0 <= padding_size && padding_size < kObjectAlignment); |
| 1672 for (int i = 0; i < padding_size; i++) sink_->PutSection(0, "StringPadding"); | 1686 for (int i = 0; i < padding_size; i++) sink_->PutSection(0, "StringPadding"); |
| 1673 | 1687 |
| 1674 sink_->Put(kSkip, "SkipAfterString"); | 1688 sink_->Put(kSkip, "SkipAfterString"); |
| 1675 sink_->PutInt(bytes_to_output, "SkipDistance"); | 1689 sink_->PutInt(bytes_to_output, "SkipDistance"); |
| 1676 } | 1690 } |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1953 BackReference Serializer::Allocate(AllocationSpace space, int size) { | 1967 BackReference Serializer::Allocate(AllocationSpace space, int size) { |
| 1954 DCHECK(space >= 0 && space < kNumberOfPreallocatedSpaces); | 1968 DCHECK(space >= 0 && space < kNumberOfPreallocatedSpaces); |
| 1955 DCHECK(size > 0 && size <= static_cast<int>(max_chunk_size(space))); | 1969 DCHECK(size > 0 && size <= static_cast<int>(max_chunk_size(space))); |
| 1956 uint32_t new_chunk_size = pending_chunk_[space] + size; | 1970 uint32_t new_chunk_size = pending_chunk_[space] + size; |
| 1957 if (new_chunk_size > max_chunk_size(space)) { | 1971 if (new_chunk_size > max_chunk_size(space)) { |
| 1958 // The new chunk size would not fit onto a single page. Complete the | 1972 // The new chunk size would not fit onto a single page. Complete the |
| 1959 // current chunk and start a new one. | 1973 // current chunk and start a new one. |
| 1960 sink_->Put(kNextChunk, "move to next chunk"); | 1974 sink_->Put(kNextChunk, "move to next chunk"); |
| 1961 sink_->Put(space, "space of next chunk"); | 1975 sink_->Put(space, "space of next chunk"); |
| 1962 completed_chunks_[space].Add(pending_chunk_[space]); | 1976 completed_chunks_[space].Add(pending_chunk_[space]); |
| 1977 DCHECK_LE(completed_chunks_[space].length(), BackReference::kMaxChunkIndex); | |
| 1963 pending_chunk_[space] = 0; | 1978 pending_chunk_[space] = 0; |
| 1964 new_chunk_size = size; | 1979 new_chunk_size = size; |
| 1965 } | 1980 } |
| 1966 uint32_t offset = pending_chunk_[space]; | 1981 uint32_t offset = pending_chunk_[space]; |
| 1967 pending_chunk_[space] = new_chunk_size; | 1982 pending_chunk_[space] = new_chunk_size; |
| 1968 return BackReference::Reference(space, completed_chunks_[space].length(), | 1983 return BackReference::Reference(space, completed_chunks_[space].length(), |
| 1969 offset); | 1984 offset); |
| 1970 } | 1985 } |
| 1971 | 1986 |
| 1972 | 1987 |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 1997 PrintF("]\n"); | 2012 PrintF("]\n"); |
| 1998 } | 2013 } |
| 1999 | 2014 |
| 2000 // Serialize code object. | 2015 // Serialize code object. |
| 2001 SnapshotByteSink sink(info->code()->CodeSize() * 2); | 2016 SnapshotByteSink sink(info->code()->CodeSize() * 2); |
| 2002 CodeSerializer cs(isolate, &sink, *source, info->code()); | 2017 CodeSerializer cs(isolate, &sink, *source, info->code()); |
| 2003 DisallowHeapAllocation no_gc; | 2018 DisallowHeapAllocation no_gc; |
| 2004 Object** location = Handle<Object>::cast(info).location(); | 2019 Object** location = Handle<Object>::cast(info).location(); |
| 2005 cs.VisitPointer(location); | 2020 cs.VisitPointer(location); |
| 2006 cs.Pad(); | 2021 cs.Pad(); |
| 2007 cs.FinalizeAllocation(); | |
| 2008 | 2022 |
| 2009 for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) { | 2023 SerializedCodeData data(sink.data(), cs); |
| 2010 // Fail if any chunk index exceeds the limit. | |
| 2011 if (cs.FinalAllocationChunks(i).length() > BackReference::kMaxChunkIndex) { | |
| 2012 return NULL; | |
| 2013 } | |
| 2014 } | |
| 2015 | |
| 2016 SerializedCodeData data(sink.data(), &cs); | |
| 2017 ScriptData* script_data = data.GetScriptData(); | 2024 ScriptData* script_data = data.GetScriptData(); |
| 2018 | 2025 |
| 2019 if (FLAG_profile_deserialization) { | 2026 if (FLAG_profile_deserialization) { |
| 2020 double ms = timer.Elapsed().InMillisecondsF(); | 2027 double ms = timer.Elapsed().InMillisecondsF(); |
| 2021 int length = script_data->length(); | 2028 int length = script_data->length(); |
| 2022 PrintF("[Serializing to %d bytes took %0.3f ms]\n", length, ms); | 2029 PrintF("[Serializing to %d bytes took %0.3f ms]\n", length, ms); |
| 2023 } | 2030 } |
| 2024 | 2031 |
| 2025 return script_data; | 2032 return script_data; |
| 2026 } | 2033 } |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2233 { | 2240 { |
| 2234 HandleScope scope(isolate); | 2241 HandleScope scope(isolate); |
| 2235 | 2242 |
| 2236 SmartPointer<SerializedCodeData> scd( | 2243 SmartPointer<SerializedCodeData> scd( |
| 2237 SerializedCodeData::FromCachedData(cached_data, *source)); | 2244 SerializedCodeData::FromCachedData(cached_data, *source)); |
| 2238 if (scd.is_empty()) { | 2245 if (scd.is_empty()) { |
| 2239 if (FLAG_profile_deserialization) PrintF("[Cached code failed check]\n"); | 2246 if (FLAG_profile_deserialization) PrintF("[Cached code failed check]\n"); |
| 2240 DCHECK(cached_data->rejected()); | 2247 DCHECK(cached_data->rejected()); |
| 2241 return MaybeHandle<SharedFunctionInfo>(); | 2248 return MaybeHandle<SharedFunctionInfo>(); |
| 2242 } | 2249 } |
| 2243 SnapshotByteSource payload(scd->Payload(), scd->PayloadLength()); | |
| 2244 Deserializer deserializer(&payload); | |
| 2245 | 2250 |
| 2246 // Eagerly expand string table to avoid allocations during deserialization. | 2251 // Eagerly expand string table to avoid allocations during deserialization. |
| 2247 StringTable::EnsureCapacityForDeserialization( | 2252 StringTable::EnsureCapacityForDeserialization( |
| 2248 isolate, scd->NumInternalizedStrings()); | 2253 isolate, scd->NumInternalizedStrings()); |
| 2249 | 2254 |
| 2250 // Set reservations. | |
| 2251 STATIC_ASSERT(NEW_SPACE == 0); | |
| 2252 int current_space = NEW_SPACE; | |
| 2253 Vector<const SerializedCodeData::Reservation> res = scd->Reservations(); | |
| 2254 for (const auto& r : res) { | |
| 2255 deserializer.AddReservation(current_space, r.chunk_size()); | |
| 2256 if (r.is_last_chunk()) current_space++; | |
| 2257 } | |
| 2258 DCHECK_EQ(kNumberOfSpaces, current_space); | |
| 2259 | |
| 2260 // Prepare and register list of attached objects. | 2255 // Prepare and register list of attached objects. |
| 2261 Vector<const uint32_t> code_stub_keys = scd->CodeStubKeys(); | 2256 Vector<const uint32_t> code_stub_keys = scd->CodeStubKeys(); |
| 2262 Vector<Handle<Object> > attached_objects = Vector<Handle<Object> >::New( | 2257 Vector<Handle<Object> > attached_objects = Vector<Handle<Object> >::New( |
| 2263 code_stub_keys.length() + kCodeStubsBaseIndex); | 2258 code_stub_keys.length() + kCodeStubsBaseIndex); |
| 2264 attached_objects[kSourceObjectIndex] = source; | 2259 attached_objects[kSourceObjectIndex] = source; |
| 2265 for (int i = 0; i < code_stub_keys.length(); i++) { | 2260 for (int i = 0; i < code_stub_keys.length(); i++) { |
| 2266 attached_objects[i + kCodeStubsBaseIndex] = | 2261 attached_objects[i + kCodeStubsBaseIndex] = |
| 2267 CodeStub::GetCode(isolate, code_stub_keys[i]).ToHandleChecked(); | 2262 CodeStub::GetCode(isolate, code_stub_keys[i]).ToHandleChecked(); |
| 2268 } | 2263 } |
| 2264 | |
| 2265 Deserializer deserializer(scd.get()); | |
| 2269 deserializer.SetAttachedObjects(&attached_objects); | 2266 deserializer.SetAttachedObjects(&attached_objects); |
| 2270 | 2267 |
| 2271 // Deserialize. | 2268 // Deserialize. |
| 2272 deserializer.DeserializePartial(isolate, &root, Deserializer::NULL_ON_OOM); | 2269 deserializer.DeserializePartial(isolate, &root, Deserializer::NULL_ON_OOM); |
| 2273 if (root == NULL) { | 2270 if (root == NULL) { |
| 2274 // Deserializing may fail if the reservations cannot be fulfilled. | 2271 // Deserializing may fail if the reservations cannot be fulfilled. |
| 2275 if (FLAG_profile_deserialization) PrintF("[Deserializing failed]\n"); | 2272 if (FLAG_profile_deserialization) PrintF("[Deserializing failed]\n"); |
| 2276 return MaybeHandle<SharedFunctionInfo>(); | 2273 return MaybeHandle<SharedFunctionInfo>(); |
| 2277 } | 2274 } |
| 2278 deserializer.FlushICacheForNewCodeObjects(); | 2275 deserializer.FlushICacheForNewCodeObjects(); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 2294 if (script->name()->IsString()) name = String::cast(script->name()); | 2291 if (script->name()->IsString()) name = String::cast(script->name()); |
| 2295 } | 2292 } |
| 2296 isolate->logger()->CodeCreateEvent(Logger::SCRIPT_TAG, result->code(), | 2293 isolate->logger()->CodeCreateEvent(Logger::SCRIPT_TAG, result->code(), |
| 2297 *result, NULL, name); | 2294 *result, NULL, name); |
| 2298 } | 2295 } |
| 2299 | 2296 |
| 2300 return result; | 2297 return result; |
| 2301 } | 2298 } |
| 2302 | 2299 |
| 2303 | 2300 |
| 2301 SnapshotData::SnapshotData(const SnapshotByteSink& sink, | |
| 2302 const Serializer& ser) { | |
| 2303 DisallowHeapAllocation no_gc; | |
| 2304 List<Reservation> reservations; | |
| 2305 ser.EncodeReservations(&reservations); | |
| 2306 const List<byte>& payload = sink.data(); | |
| 2307 | |
| 2308 // Calculate sizes. | |
| 2309 int reservation_size = reservations.length() * kInt32Size; | |
| 2310 size_ = kHeaderSize + reservation_size + payload.length(); | |
| 2311 | |
| 2312 // Allocate backing store and create result data. | |
| 2313 data_ = NewArray<byte>(size_); | |
|
vogelheim
2014/12/03 18:49:25
Related to the comment in serialize.h:
I was tryi
Yang
2014/12/04 08:51:43
I moved allocation into a helper method in the par
| |
| 2314 DCHECK(IsAligned(reinterpret_cast<intptr_t>(data_), kPointerAlignment)); | |
| 2315 | |
| 2316 // Set header values. | |
| 2317 SetHeaderValue(kCheckSumOffset, Version::Hash()); | |
| 2318 SetHeaderValue(kReservationsOffset, reservations.length()); | |
| 2319 SetHeaderValue(kPayloadLengthOffset, payload.length()); | |
| 2320 | |
| 2321 // Copy reservation chunk sizes. | |
| 2322 CopyBytes(data_ + kHeaderSize, reinterpret_cast<byte*>(reservations.begin()), | |
| 2323 reservation_size); | |
| 2324 | |
| 2325 // Copy serialized data. | |
| 2326 CopyBytes(data_ + kHeaderSize + reservation_size, payload.begin(), | |
| 2327 static_cast<size_t>(payload.length())); | |
| 2328 } | |
| 2329 | |
| 2330 | |
| 2331 bool SnapshotData::IsSane() { | |
| 2332 return GetHeaderValue(kCheckSumOffset) == Version::Hash(); | |
| 2333 } | |
| 2334 | |
| 2335 | |
| 2336 Vector<const SerializedData::Reservation> SnapshotData::Reservations() const { | |
| 2337 return Vector<const Reservation>( | |
| 2338 reinterpret_cast<const Reservation*>(data_ + kHeaderSize), | |
| 2339 GetHeaderValue(kReservationsOffset)); | |
| 2340 } | |
| 2341 | |
| 2342 | |
| 2343 Vector<const byte> SnapshotData::Payload() const { | |
| 2344 int reservations_size = GetHeaderValue(kReservationsOffset) * kInt32Size; | |
| 2345 const byte* payload = data_ + kHeaderSize + reservations_size; | |
| 2346 int length = GetHeaderValue(kPayloadLengthOffset); | |
| 2347 DCHECK_EQ(data_ + size_, payload + length); | |
| 2348 return Vector<const byte>(payload, length); | |
| 2349 } | |
| 2350 | |
| 2351 | |
| 2304 SerializedCodeData::SerializedCodeData(const List<byte>& payload, | 2352 SerializedCodeData::SerializedCodeData(const List<byte>& payload, |
| 2305 CodeSerializer* cs) | 2353 const CodeSerializer& cs) { |
| 2306 : data_(NULL), size_(0), owns_script_data_(true) { | |
| 2307 DisallowHeapAllocation no_gc; | 2354 DisallowHeapAllocation no_gc; |
| 2308 List<uint32_t>* stub_keys = cs->stub_keys(); | 2355 const List<uint32_t>* stub_keys = cs.stub_keys(); |
| 2309 | 2356 |
| 2310 // Gather reservation chunk sizes. | 2357 List<Reservation> reservations; |
| 2311 List<uint32_t> reservations(SerializerDeserializer::kNumberOfSpaces); | 2358 cs.EncodeReservations(&reservations); |
| 2312 STATIC_ASSERT(NEW_SPACE == 0); | |
| 2313 for (int i = 0; i < SerializerDeserializer::kNumberOfSpaces; i++) { | |
| 2314 Vector<const uint32_t> chunks = cs->FinalAllocationChunks(i); | |
| 2315 for (int j = 0; j < chunks.length(); j++) { | |
| 2316 uint32_t chunk = ChunkSizeBits::encode(chunks[j]) | | |
| 2317 IsLastChunkBits::encode(j == chunks.length() - 1); | |
| 2318 reservations.Add(chunk); | |
| 2319 } | |
| 2320 } | |
| 2321 | 2359 |
| 2322 // Calculate sizes. | 2360 // Calculate sizes. |
| 2323 int reservation_size = reservations.length() * kInt32Size; | 2361 int reservation_size = reservations.length() * kInt32Size; |
| 2324 int num_stub_keys = stub_keys->length(); | 2362 int num_stub_keys = stub_keys->length(); |
| 2325 int stub_keys_size = stub_keys->length() * kInt32Size; | 2363 int stub_keys_size = stub_keys->length() * kInt32Size; |
| 2326 size_ = kHeaderSize + reservation_size + stub_keys_size + payload.length(); | 2364 size_ = kHeaderSize + reservation_size + stub_keys_size + payload.length(); |
| 2327 | 2365 |
| 2328 // Allocate backing store and create result data. | 2366 // Allocate backing store and create result data. |
| 2329 data_ = NewArray<byte>(size_); | 2367 data_ = NewArray<byte>(size_); |
| 2330 DCHECK(IsAligned(reinterpret_cast<intptr_t>(data_), kPointerAlignment)); | 2368 DCHECK(IsAligned(reinterpret_cast<intptr_t>(data_), kPointerAlignment)); |
| 2331 | 2369 |
| 2332 // Set header values. | 2370 // Set header values. |
| 2333 SetHeaderValue(kCheckSumOffset, CheckSum(cs->source())); | 2371 SetHeaderValue(kCheckSumOffset, CheckSum(cs.source())); |
| 2334 SetHeaderValue(kNumInternalizedStringsOffset, cs->num_internalized_strings()); | 2372 SetHeaderValue(kNumInternalizedStringsOffset, cs.num_internalized_strings()); |
| 2335 SetHeaderValue(kReservationsOffset, reservations.length()); | 2373 SetHeaderValue(kReservationsOffset, reservations.length()); |
| 2336 SetHeaderValue(kNumCodeStubKeysOffset, num_stub_keys); | 2374 SetHeaderValue(kNumCodeStubKeysOffset, num_stub_keys); |
| 2337 SetHeaderValue(kPayloadLengthOffset, payload.length()); | 2375 SetHeaderValue(kPayloadLengthOffset, payload.length()); |
| 2338 | 2376 |
| 2339 // Copy reservation chunk sizes. | 2377 // Copy reservation chunk sizes. |
| 2340 CopyBytes(data_ + kHeaderSize, reinterpret_cast<byte*>(reservations.begin()), | 2378 CopyBytes(data_ + kHeaderSize, reinterpret_cast<byte*>(reservations.begin()), |
| 2341 reservation_size); | 2379 reservation_size); |
| 2342 | 2380 |
| 2343 // Copy code stub keys. | 2381 // Copy code stub keys. |
| 2344 CopyBytes(data_ + kHeaderSize + reservation_size, | 2382 CopyBytes(data_ + kHeaderSize + reservation_size, |
| 2345 reinterpret_cast<byte*>(stub_keys->begin()), stub_keys_size); | 2383 reinterpret_cast<byte*>(stub_keys->begin()), stub_keys_size); |
| 2346 | 2384 |
| 2347 // Copy serialized data. | 2385 // Copy serialized data. |
| 2348 CopyBytes(data_ + kHeaderSize + reservation_size + stub_keys_size, | 2386 CopyBytes(data_ + kHeaderSize + reservation_size + stub_keys_size, |
| 2349 payload.begin(), static_cast<size_t>(payload.length())); | 2387 payload.begin(), static_cast<size_t>(payload.length())); |
| 2350 } | 2388 } |
| 2351 | 2389 |
| 2352 | 2390 |
| 2353 bool SerializedCodeData::IsSane(String* source) { | 2391 bool SerializedCodeData::IsSane(String* source) { |
| 2354 return GetHeaderValue(kCheckSumOffset) == CheckSum(source) && | 2392 return GetHeaderValue(kCheckSumOffset) == CheckSum(source) && |
| 2355 PayloadLength() >= SharedFunctionInfo::kSize; | 2393 Payload().length() >= SharedFunctionInfo::kSize; |
| 2356 } | 2394 } |
| 2357 | 2395 |
| 2358 | 2396 |
| 2359 int SerializedCodeData::CheckSum(String* string) { | 2397 int SerializedCodeData::CheckSum(String* string) { |
| 2360 return Version::Hash() ^ string->length(); | 2398 return Version::Hash() ^ string->length(); |
| 2361 } | 2399 } |
| 2400 | |
| 2401 | |
| 2402 // Return ScriptData object and relinquish ownership over it to the caller. | |
| 2403 ScriptData* SerializedCodeData::GetScriptData() { | |
| 2404 DCHECK(owns_data_); | |
| 2405 ScriptData* result = new ScriptData(data_, size_); | |
| 2406 result->AcquireDataOwnership(); | |
| 2407 owns_data_ = false; | |
| 2408 return result; | |
|
vogelheim
2014/12/03 18:49:25
Is this expected to the last method call on a part
Yang
2014/12/04 08:51:43
Done.
| |
| 2409 } | |
| 2410 | |
| 2411 | |
| 2412 Vector<const SerializedData::Reservation> SerializedCodeData::Reservations() | |
| 2413 const { | |
| 2414 return Vector<const Reservation>( | |
| 2415 reinterpret_cast<const Reservation*>(data_ + kHeaderSize), | |
| 2416 GetHeaderValue(kReservationsOffset)); | |
| 2417 } | |
| 2418 | |
| 2419 | |
| 2420 Vector<const byte> SerializedCodeData::Payload() const { | |
| 2421 int reservations_size = GetHeaderValue(kReservationsOffset) * kInt32Size; | |
| 2422 int code_stubs_size = GetHeaderValue(kNumCodeStubKeysOffset) * kInt32Size; | |
| 2423 const byte* payload = | |
| 2424 data_ + kHeaderSize + reservations_size + code_stubs_size; | |
| 2425 int length = GetHeaderValue(kPayloadLengthOffset); | |
| 2426 DCHECK_EQ(data_ + size_, payload + length); | |
| 2427 return Vector<const byte>(payload, length); | |
| 2428 } | |
| 2429 | |
| 2430 | |
| 2431 int SerializedCodeData::NumInternalizedStrings() const { | |
| 2432 return GetHeaderValue(kNumInternalizedStringsOffset); | |
| 2433 } | |
| 2434 | |
| 2435 Vector<const uint32_t> SerializedCodeData::CodeStubKeys() const { | |
| 2436 int reservations_size = GetHeaderValue(kReservationsOffset) * kInt32Size; | |
| 2437 const byte* start = data_ + kHeaderSize + reservations_size; | |
| 2438 return Vector<const uint32_t>(reinterpret_cast<const uint32_t*>(start), | |
| 2439 GetHeaderValue(kNumCodeStubKeysOffset)); | |
| 2440 } | |
| 2362 } } // namespace v8::internal | 2441 } } // namespace v8::internal |
| OLD | NEW |