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