| 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 580 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 591 Isolate* isolate_; | 591 Isolate* isolate_; |
| 592 }; | 592 }; |
| 593 | 593 |
| 594 | 594 |
| 595 Deserializer::Deserializer(SnapshotByteSource* source) | 595 Deserializer::Deserializer(SnapshotByteSource* source) |
| 596 : isolate_(NULL), | 596 : isolate_(NULL), |
| 597 attached_objects_(NULL), | 597 attached_objects_(NULL), |
| 598 source_(source), | 598 source_(source), |
| 599 external_reference_decoder_(NULL), | 599 external_reference_decoder_(NULL), |
| 600 deserialized_large_objects_(0) { | 600 deserialized_large_objects_(0) { |
| 601 for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) current_chunk_[i] = 0; | 601 for (int i = 0; i < kNumberOfSpaces; i++) { |
| 602 reservations_[i] = kUninitializedReservation; |
| 603 } |
| 602 } | 604 } |
| 603 | 605 |
| 604 | 606 |
| 605 void Deserializer::FlushICacheForNewCodeObjects() { | 607 void Deserializer::FlushICacheForNewCodeObjects() { |
| 606 PageIterator it(isolate_->heap()->code_space()); | 608 PageIterator it(isolate_->heap()->code_space()); |
| 607 while (it.has_next()) { | 609 while (it.has_next()) { |
| 608 Page* p = it.next(); | 610 Page* p = it.next(); |
| 609 CpuFeatures::FlushICache(p->area_start(), p->area_end() - p->area_start()); | 611 CpuFeatures::FlushICache(p->area_start(), p->area_end() - p->area_start()); |
| 610 } | 612 } |
| 611 } | 613 } |
| 612 | 614 |
| 613 | 615 |
| 614 bool Deserializer::ReserveSpace() { | |
| 615 if (!isolate_->heap()->ReserveSpace(reservations_)) return false; | |
| 616 for (int i = 0; i < kNumberOfPreallocatedSpaces; i++) { | |
| 617 high_water_[i] = reservations_[i][0].start; | |
| 618 } | |
| 619 return true; | |
| 620 } | |
| 621 | |
| 622 | |
| 623 void Deserializer::Deserialize(Isolate* isolate) { | 616 void Deserializer::Deserialize(Isolate* isolate) { |
| 624 isolate_ = isolate; | 617 isolate_ = isolate; |
| 625 DCHECK(isolate_ != NULL); | 618 DCHECK(isolate_ != NULL); |
| 626 if (!ReserveSpace()) FatalProcessOutOfMemory("deserializing context"); | 619 isolate_->heap()->ReserveSpace(reservations_, high_water_); |
| 627 // No active threads. | 620 // No active threads. |
| 628 DCHECK_EQ(NULL, isolate_->thread_manager()->FirstThreadStateInUse()); | 621 DCHECK_EQ(NULL, isolate_->thread_manager()->FirstThreadStateInUse()); |
| 629 // No active handles. | 622 // No active handles. |
| 630 DCHECK(isolate_->handle_scope_implementer()->blocks()->is_empty()); | 623 DCHECK(isolate_->handle_scope_implementer()->blocks()->is_empty()); |
| 631 DCHECK_EQ(NULL, external_reference_decoder_); | 624 DCHECK_EQ(NULL, external_reference_decoder_); |
| 632 external_reference_decoder_ = new ExternalReferenceDecoder(isolate); | 625 external_reference_decoder_ = new ExternalReferenceDecoder(isolate); |
| 633 isolate_->heap()->IterateSmiRoots(this); | 626 isolate_->heap()->IterateSmiRoots(this); |
| 634 isolate_->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG); | 627 isolate_->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG); |
| 635 isolate_->heap()->RepairFreeListsAfterBoot(); | 628 isolate_->heap()->RepairFreeListsAfterBoot(); |
| 636 isolate_->heap()->IterateWeakRoots(this, VISIT_ALL); | 629 isolate_->heap()->IterateWeakRoots(this, VISIT_ALL); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 658 } | 651 } |
| 659 | 652 |
| 660 FlushICacheForNewCodeObjects(); | 653 FlushICacheForNewCodeObjects(); |
| 661 | 654 |
| 662 // Issue code events for newly deserialized code objects. | 655 // Issue code events for newly deserialized code objects. |
| 663 LOG_CODE_EVENT(isolate_, LogCodeObjects()); | 656 LOG_CODE_EVENT(isolate_, LogCodeObjects()); |
| 664 LOG_CODE_EVENT(isolate_, LogCompiledFunctions()); | 657 LOG_CODE_EVENT(isolate_, LogCompiledFunctions()); |
| 665 } | 658 } |
| 666 | 659 |
| 667 | 660 |
| 668 void Deserializer::DeserializePartial(Isolate* isolate, Object** root, | 661 void Deserializer::DeserializePartial(Isolate* isolate, Object** root) { |
| 669 OnOOM on_oom) { | |
| 670 isolate_ = isolate; | 662 isolate_ = isolate; |
| 671 for (int i = NEW_SPACE; i < kNumberOfSpaces; i++) { | 663 for (int i = NEW_SPACE; i < kNumberOfSpaces; i++) { |
| 672 DCHECK(reservations_[i].length() > 0); | 664 DCHECK(reservations_[i] != kUninitializedReservation); |
| 673 } | 665 } |
| 674 if (!ReserveSpace()) { | 666 Heap* heap = isolate->heap(); |
| 675 if (on_oom == FATAL_ON_OOM) FatalProcessOutOfMemory("deserialize context"); | 667 heap->ReserveSpace(reservations_, high_water_); |
| 676 *root = NULL; | |
| 677 return; | |
| 678 } | |
| 679 if (external_reference_decoder_ == NULL) { | 668 if (external_reference_decoder_ == NULL) { |
| 680 external_reference_decoder_ = new ExternalReferenceDecoder(isolate); | 669 external_reference_decoder_ = new ExternalReferenceDecoder(isolate); |
| 681 } | 670 } |
| 682 | 671 |
| 683 DisallowHeapAllocation no_gc; | 672 DisallowHeapAllocation no_gc; |
| 684 | 673 |
| 685 // Keep track of the code space start and end pointers in case new | 674 // Keep track of the code space start and end pointers in case new |
| 686 // code objects were unserialized | 675 // code objects were unserialized |
| 687 OldSpace* code_space = isolate_->heap()->code_space(); | 676 OldSpace* code_space = isolate_->heap()->code_space(); |
| 688 Address start_address = code_space->top(); | 677 Address start_address = code_space->top(); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 704 } | 693 } |
| 705 if (attached_objects_) attached_objects_->Dispose(); | 694 if (attached_objects_) attached_objects_->Dispose(); |
| 706 } | 695 } |
| 707 | 696 |
| 708 | 697 |
| 709 // This is called on the roots. It is the driver of the deserialization | 698 // This is called on the roots. It is the driver of the deserialization |
| 710 // process. It is also called on the body of each function. | 699 // process. It is also called on the body of each function. |
| 711 void Deserializer::VisitPointers(Object** start, Object** end) { | 700 void Deserializer::VisitPointers(Object** start, Object** end) { |
| 712 // The space must be new space. Any other space would cause ReadChunk to try | 701 // The space must be new space. Any other space would cause ReadChunk to try |
| 713 // to update the remembered using NULL as the address. | 702 // to update the remembered using NULL as the address. |
| 714 ReadData(start, end, NEW_SPACE, NULL); | 703 ReadChunk(start, end, NEW_SPACE, NULL); |
| 715 } | 704 } |
| 716 | 705 |
| 717 | 706 |
| 718 void Deserializer::RelinkAllocationSite(AllocationSite* site) { | 707 void Deserializer::RelinkAllocationSite(AllocationSite* site) { |
| 719 if (isolate_->heap()->allocation_sites_list() == Smi::FromInt(0)) { | 708 if (isolate_->heap()->allocation_sites_list() == Smi::FromInt(0)) { |
| 720 site->set_weak_next(isolate_->heap()->undefined_value()); | 709 site->set_weak_next(isolate_->heap()->undefined_value()); |
| 721 } else { | 710 } else { |
| 722 site->set_weak_next(isolate_->heap()->allocation_sites_list()); | 711 site->set_weak_next(isolate_->heap()->allocation_sites_list()); |
| 723 } | 712 } |
| 724 isolate_->heap()->set_allocation_sites_list(site); | 713 isolate_->heap()->set_allocation_sites_list(site); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 792 Object** write_back) { | 781 Object** write_back) { |
| 793 int size = source_->GetInt() << kObjectAlignmentBits; | 782 int size = source_->GetInt() << kObjectAlignmentBits; |
| 794 Address address = Allocate(space_number, size); | 783 Address address = Allocate(space_number, size); |
| 795 HeapObject* obj = HeapObject::FromAddress(address); | 784 HeapObject* obj = HeapObject::FromAddress(address); |
| 796 isolate_->heap()->OnAllocationEvent(obj, size); | 785 isolate_->heap()->OnAllocationEvent(obj, size); |
| 797 Object** current = reinterpret_cast<Object**>(address); | 786 Object** current = reinterpret_cast<Object**>(address); |
| 798 Object** limit = current + (size >> kPointerSizeLog2); | 787 Object** limit = current + (size >> kPointerSizeLog2); |
| 799 if (FLAG_log_snapshot_positions) { | 788 if (FLAG_log_snapshot_positions) { |
| 800 LOG(isolate_, SnapshotPositionEvent(address, source_->position())); | 789 LOG(isolate_, SnapshotPositionEvent(address, source_->position())); |
| 801 } | 790 } |
| 802 ReadData(current, limit, space_number, address); | 791 ReadChunk(current, limit, space_number, address); |
| 803 | 792 |
| 804 // TODO(mvstanton): consider treating the heap()->allocation_sites_list() | 793 // TODO(mvstanton): consider treating the heap()->allocation_sites_list() |
| 805 // as a (weak) root. If this root is relocated correctly, | 794 // as a (weak) root. If this root is relocated correctly, |
| 806 // RelinkAllocationSite() isn't necessary. | 795 // RelinkAllocationSite() isn't necessary. |
| 807 if (obj->IsAllocationSite()) RelinkAllocationSite(AllocationSite::cast(obj)); | 796 if (obj->IsAllocationSite()) RelinkAllocationSite(AllocationSite::cast(obj)); |
| 808 | 797 |
| 809 // Fix up strings from serialized user code. | 798 // Fix up strings from serialized user code. |
| 810 if (deserializing_user_code()) obj = ProcessNewObjectFromSerializedCode(obj); | 799 if (deserializing_user_code()) obj = ProcessNewObjectFromSerializedCode(obj); |
| 811 | 800 |
| 812 *write_back = obj; | 801 *write_back = obj; |
| 813 #ifdef DEBUG | 802 #ifdef DEBUG |
| 814 if (obj->IsCode()) { | 803 if (obj->IsCode()) { |
| 815 DCHECK(space_number == CODE_SPACE || space_number == LO_SPACE); | 804 DCHECK(space_number == CODE_SPACE || space_number == LO_SPACE); |
| 816 } else { | 805 } else { |
| 817 DCHECK(space_number != CODE_SPACE); | 806 DCHECK(space_number != CODE_SPACE); |
| 818 } | 807 } |
| 819 #endif | 808 #endif |
| 820 } | 809 } |
| 821 | 810 |
| 822 | 811 |
| 823 // We know the space requirements before deserialization and can | 812 // We know the space requirements before deserialization and can |
| 824 // pre-allocate that reserved space. During deserialization, all we need | 813 // pre-allocate that reserved space. During deserialization, all we need |
| 825 // to do is to bump up the pointer for each space in the reserved | 814 // to do is to bump up the pointer for each space in the reserved |
| 826 // space. This is also used for fixing back references. | 815 // space. This is also used for fixing back references. |
| 827 // We may have to split up the pre-allocation into several chunks | |
| 828 // because it would not fit onto a single page, we have to keep track | |
| 829 // of when to move to the next chunk. | |
| 830 // Since multiple large objects cannot be folded into one large object | 816 // Since multiple large objects cannot be folded into one large object |
| 831 // space allocation, we have to do an actual allocation when deserializing | 817 // space allocation, we have to do an actual allocation when deserializing |
| 832 // each large object. Instead of tracking offset for back references, we | 818 // each large object. Instead of tracking offset for back references, we |
| 833 // reference large objects by index. | 819 // reference large objects by index. |
| 834 Address Deserializer::Allocate(int space_index, int size) { | 820 Address Deserializer::Allocate(int space_index, int size) { |
| 835 if (space_index == LO_SPACE) { | 821 if (space_index == LO_SPACE) { |
| 836 AlwaysAllocateScope scope(isolate_); | 822 AlwaysAllocateScope scope(isolate_); |
| 837 LargeObjectSpace* lo_space = isolate_->heap()->lo_space(); | 823 LargeObjectSpace* lo_space = isolate_->heap()->lo_space(); |
| 838 Executability exec = static_cast<Executability>(source_->Get()); | 824 Executability exec = static_cast<Executability>(source_->GetInt()); |
| 839 AllocationResult result = lo_space->AllocateRaw(size, exec); | 825 AllocationResult result = lo_space->AllocateRaw(size, exec); |
| 840 HeapObject* obj = HeapObject::cast(result.ToObjectChecked()); | 826 HeapObject* obj = HeapObject::cast(result.ToObjectChecked()); |
| 841 deserialized_large_objects_.Add(obj); | 827 deserialized_large_objects_.Add(obj); |
| 842 return obj->address(); | 828 return obj->address(); |
| 843 } else { | 829 } else { |
| 844 DCHECK(space_index < kNumberOfPreallocatedSpaces); | 830 DCHECK(space_index < kNumberOfPreallocatedSpaces); |
| 845 Address address = high_water_[space_index]; | 831 Address address = high_water_[space_index]; |
| 846 DCHECK_NE(NULL, address); | |
| 847 const Heap::Reservation& reservation = reservations_[space_index]; | |
| 848 int chunk_index = current_chunk_[space_index]; | |
| 849 if (address + size > reservation[chunk_index].end) { | |
| 850 // The last chunk size matches exactly the already deserialized data. | |
| 851 DCHECK_EQ(address, reservation[chunk_index].end); | |
| 852 // Move to next reserved chunk. | |
| 853 chunk_index = ++current_chunk_[space_index]; | |
| 854 DCHECK_LT(chunk_index, reservation.length()); | |
| 855 // Prepare for next allocation in the next chunk. | |
| 856 address = reservation[chunk_index].start; | |
| 857 } else { | |
| 858 high_water_[space_index] = address + size; | |
| 859 } | |
| 860 high_water_[space_index] = address + size; | 832 high_water_[space_index] = address + size; |
| 861 return address; | 833 return address; |
| 862 } | 834 } |
| 863 } | 835 } |
| 864 | 836 |
| 865 | 837 |
| 866 void Deserializer::ReadData(Object** current, Object** limit, int source_space, | 838 void Deserializer::ReadChunk(Object** current, |
| 867 Address current_object_address) { | 839 Object** limit, |
| 840 int source_space, |
| 841 Address current_object_address) { |
| 868 Isolate* const isolate = isolate_; | 842 Isolate* const isolate = isolate_; |
| 869 // Write barrier support costs around 1% in startup time. In fact there | 843 // Write barrier support costs around 1% in startup time. In fact there |
| 870 // are no new space objects in current boot snapshots, so it's not needed, | 844 // are no new space objects in current boot snapshots, so it's not needed, |
| 871 // but that may change. | 845 // but that may change. |
| 872 bool write_barrier_needed = (current_object_address != NULL && | 846 bool write_barrier_needed = (current_object_address != NULL && |
| 873 source_space != NEW_SPACE && | 847 source_space != NEW_SPACE && |
| 874 source_space != CELL_SPACE && | 848 source_space != CELL_SPACE && |
| 875 source_space != PROPERTY_CELL_SPACE && | 849 source_space != PROPERTY_CELL_SPACE && |
| 876 source_space != CODE_SPACE && | 850 source_space != CODE_SPACE && |
| 877 source_space != OLD_DATA_SPACE); | 851 source_space != OLD_DATA_SPACE); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 909 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ | 883 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ |
| 910 } else if (where == kExternalReference) { \ | 884 } else if (where == kExternalReference) { \ |
| 911 int skip = source_->GetInt(); \ | 885 int skip = source_->GetInt(); \ |
| 912 current = reinterpret_cast<Object**>( \ | 886 current = reinterpret_cast<Object**>( \ |
| 913 reinterpret_cast<Address>(current) + skip); \ | 887 reinterpret_cast<Address>(current) + skip); \ |
| 914 int reference_id = source_->GetInt(); \ | 888 int reference_id = source_->GetInt(); \ |
| 915 Address address = external_reference_decoder_->Decode(reference_id); \ | 889 Address address = external_reference_decoder_->Decode(reference_id); \ |
| 916 new_object = reinterpret_cast<Object*>(address); \ | 890 new_object = reinterpret_cast<Object*>(address); \ |
| 917 } else if (where == kBackref) { \ | 891 } else if (where == kBackref) { \ |
| 918 emit_write_barrier = (space_number == NEW_SPACE); \ | 892 emit_write_barrier = (space_number == NEW_SPACE); \ |
| 919 new_object = GetBackReferencedObject(data & kSpaceMask); \ | 893 new_object = GetAddressFromEnd(data & kSpaceMask); \ |
| 920 if (deserializing_user_code()) { \ | 894 if (deserializing_user_code()) { \ |
| 921 new_object = ProcessBackRefInSerializedCode(new_object); \ | 895 new_object = ProcessBackRefInSerializedCode(new_object); \ |
| 922 } \ | 896 } \ |
| 923 } else if (where == kBuiltin) { \ | 897 } else if (where == kBuiltin) { \ |
| 924 DCHECK(deserializing_user_code()); \ | 898 DCHECK(deserializing_user_code()); \ |
| 925 int builtin_id = source_->GetInt(); \ | 899 int builtin_id = source_->GetInt(); \ |
| 926 DCHECK_LE(0, builtin_id); \ | 900 DCHECK_LE(0, builtin_id); \ |
| 927 DCHECK_LT(builtin_id, Builtins::builtin_count); \ | 901 DCHECK_LT(builtin_id, Builtins::builtin_count); \ |
| 928 Builtins::Name name = static_cast<Builtins::Name>(builtin_id); \ | 902 Builtins::Name name = static_cast<Builtins::Name>(builtin_id); \ |
| 929 new_object = isolate->builtins()->builtin(name); \ | 903 new_object = isolate->builtins()->builtin(name); \ |
| 930 emit_write_barrier = false; \ | 904 emit_write_barrier = false; \ |
| 931 } else if (where == kAttachedReference) { \ | 905 } else if (where == kAttachedReference) { \ |
| 932 DCHECK(deserializing_user_code()); \ | 906 DCHECK(deserializing_user_code()); \ |
| 933 int index = source_->GetInt(); \ | 907 int index = source_->GetInt(); \ |
| 934 new_object = *attached_objects_->at(index); \ | 908 new_object = *attached_objects_->at(index); \ |
| 935 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ | 909 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ |
| 936 } else { \ | 910 } else { \ |
| 937 DCHECK(where == kBackrefWithSkip); \ | 911 DCHECK(where == kBackrefWithSkip); \ |
| 938 int skip = source_->GetInt(); \ | 912 int skip = source_->GetInt(); \ |
| 939 current = reinterpret_cast<Object**>( \ | 913 current = reinterpret_cast<Object**>( \ |
| 940 reinterpret_cast<Address>(current) + skip); \ | 914 reinterpret_cast<Address>(current) + skip); \ |
| 941 emit_write_barrier = (space_number == NEW_SPACE); \ | 915 emit_write_barrier = (space_number == NEW_SPACE); \ |
| 942 new_object = GetBackReferencedObject(data & kSpaceMask); \ | 916 new_object = GetAddressFromEnd(data & kSpaceMask); \ |
| 943 if (deserializing_user_code()) { \ | 917 if (deserializing_user_code()) { \ |
| 944 new_object = ProcessBackRefInSerializedCode(new_object); \ | 918 new_object = ProcessBackRefInSerializedCode(new_object); \ |
| 945 } \ | 919 } \ |
| 946 } \ | 920 } \ |
| 947 if (within == kInnerPointer) { \ | 921 if (within == kInnerPointer) { \ |
| 948 if (space_number != CODE_SPACE || new_object->IsCode()) { \ | 922 if (space_number != CODE_SPACE || new_object->IsCode()) { \ |
| 949 Code* new_code_object = reinterpret_cast<Code*>(new_object); \ | 923 Code* new_code_object = reinterpret_cast<Code*>(new_object); \ |
| 950 new_object = \ | 924 new_object = \ |
| 951 reinterpret_cast<Object*>(new_code_object->instruction_start()); \ | 925 reinterpret_cast<Object*>(new_code_object->instruction_start()); \ |
| 952 } else { \ | 926 } else { \ |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1240 | 1214 |
| 1241 Serializer::Serializer(Isolate* isolate, SnapshotByteSink* sink) | 1215 Serializer::Serializer(Isolate* isolate, SnapshotByteSink* sink) |
| 1242 : isolate_(isolate), | 1216 : isolate_(isolate), |
| 1243 sink_(sink), | 1217 sink_(sink), |
| 1244 external_reference_encoder_(new ExternalReferenceEncoder(isolate)), | 1218 external_reference_encoder_(new ExternalReferenceEncoder(isolate)), |
| 1245 root_index_wave_front_(0), | 1219 root_index_wave_front_(0), |
| 1246 code_address_map_(NULL), | 1220 code_address_map_(NULL), |
| 1247 seen_large_objects_index_(0) { | 1221 seen_large_objects_index_(0) { |
| 1248 // The serializer is meant to be used only to generate initial heap images | 1222 // The serializer is meant to be used only to generate initial heap images |
| 1249 // from a context in which there is only one isolate. | 1223 // from a context in which there is only one isolate. |
| 1250 for (int i = 0; i < kNumberOfSpaces; i++) pending_chunk_[i] = 0; | 1224 for (int i = 0; i < kNumberOfSpaces; i++) fullness_[i] = 0; |
| 1251 } | 1225 } |
| 1252 | 1226 |
| 1253 | 1227 |
| 1254 Serializer::~Serializer() { | 1228 Serializer::~Serializer() { |
| 1255 delete external_reference_encoder_; | 1229 delete external_reference_encoder_; |
| 1256 if (code_address_map_ != NULL) delete code_address_map_; | 1230 if (code_address_map_ != NULL) delete code_address_map_; |
| 1257 } | 1231 } |
| 1258 | 1232 |
| 1259 | 1233 |
| 1260 void StartupSerializer::SerializeStrongReferences() { | 1234 void StartupSerializer::SerializeStrongReferences() { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1302 for (int i = 0; i < kPointerSize; i++) { | 1276 for (int i = 0; i < kPointerSize; i++) { |
| 1303 sink_->Put(reinterpret_cast<byte*>(current)[i], "Byte"); | 1277 sink_->Put(reinterpret_cast<byte*>(current)[i], "Byte"); |
| 1304 } | 1278 } |
| 1305 } else { | 1279 } else { |
| 1306 SerializeObject(*current, kPlain, kStartOfObject, 0); | 1280 SerializeObject(*current, kPlain, kStartOfObject, 0); |
| 1307 } | 1281 } |
| 1308 } | 1282 } |
| 1309 } | 1283 } |
| 1310 | 1284 |
| 1311 | 1285 |
| 1312 void Serializer::FinalizeAllocation() { | |
| 1313 DCHECK_EQ(0, completed_chunks_[LO_SPACE].length()); // Not yet finalized. | |
| 1314 for (int i = 0; i < kNumberOfSpaces; i++) { | |
| 1315 // Complete the last pending chunk and if there are no completed chunks, | |
| 1316 // make sure there is at least one empty chunk. | |
| 1317 if (pending_chunk_[i] > 0 || completed_chunks_[i].length() == 0) { | |
| 1318 completed_chunks_[i].Add(pending_chunk_[i]); | |
| 1319 pending_chunk_[i] = 0; | |
| 1320 } | |
| 1321 } | |
| 1322 } | |
| 1323 | |
| 1324 | |
| 1325 // This ensures that the partial snapshot cache keeps things alive during GC and | 1286 // This ensures that the partial snapshot cache keeps things alive during GC and |
| 1326 // tracks their movement. When it is called during serialization of the startup | 1287 // tracks their movement. When it is called during serialization of the startup |
| 1327 // snapshot nothing happens. When the partial (context) snapshot is created, | 1288 // snapshot nothing happens. When the partial (context) snapshot is created, |
| 1328 // this array is populated with the pointers that the partial snapshot will | 1289 // this array is populated with the pointers that the partial snapshot will |
| 1329 // need. As that happens we emit serialized objects to the startup snapshot | 1290 // need. As that happens we emit serialized objects to the startup snapshot |
| 1330 // that correspond to the elements of this cache array. On deserialization we | 1291 // that correspond to the elements of this cache array. On deserialization we |
| 1331 // therefore need to visit the cache array. This fills it up with pointers to | 1292 // therefore need to visit the cache array. This fills it up with pointers to |
| 1332 // deserialized objects. | 1293 // deserialized objects. |
| 1333 void SerializerDeserializer::Iterate(Isolate* isolate, | 1294 void SerializerDeserializer::Iterate(Isolate* isolate, |
| 1334 ObjectVisitor* visitor) { | 1295 ObjectVisitor* visitor) { |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1401 } else { | 1362 } else { |
| 1402 sink_->Put(kBackrefWithSkip + how_to_code + where_to_point + space, | 1363 sink_->Put(kBackrefWithSkip + how_to_code + where_to_point + space, |
| 1403 "BackRefSerWithSkip"); | 1364 "BackRefSerWithSkip"); |
| 1404 sink_->PutInt(skip, "BackRefSkipDistance"); | 1365 sink_->PutInt(skip, "BackRefSkipDistance"); |
| 1405 } | 1366 } |
| 1406 | 1367 |
| 1407 if (space == LO_SPACE) { | 1368 if (space == LO_SPACE) { |
| 1408 int index = address_mapper_.MappedTo(heap_object); | 1369 int index = address_mapper_.MappedTo(heap_object); |
| 1409 sink_->PutInt(index, "large object index"); | 1370 sink_->PutInt(index, "large object index"); |
| 1410 } else { | 1371 } else { |
| 1411 uint32_t existing_allocation = address_mapper_.MappedTo(heap_object); | 1372 int address = address_mapper_.MappedTo(heap_object); |
| 1373 int offset = CurrentAllocationAddress(space) - address; |
| 1412 // Shift out the bits that are always 0. | 1374 // Shift out the bits that are always 0. |
| 1413 existing_allocation >>= kObjectAlignmentBits; | 1375 offset >>= kObjectAlignmentBits; |
| 1414 sink_->PutInt(existing_allocation, "allocation"); | 1376 sink_->PutInt(offset, "offset"); |
| 1415 } | 1377 } |
| 1416 } | 1378 } |
| 1417 | 1379 |
| 1418 | 1380 |
| 1419 void StartupSerializer::SerializeObject( | 1381 void StartupSerializer::SerializeObject( |
| 1420 Object* o, | 1382 Object* o, |
| 1421 HowToCode how_to_code, | 1383 HowToCode how_to_code, |
| 1422 WhereToPoint where_to_point, | 1384 WhereToPoint where_to_point, |
| 1423 int skip) { | 1385 int skip) { |
| 1424 CHECK(o->IsHeapObject()); | 1386 CHECK(o->IsHeapObject()); |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1564 serializer_->code_address_map_->Lookup(object_->address()); | 1526 serializer_->code_address_map_->Lookup(object_->address()); |
| 1565 LOG(serializer_->isolate_, | 1527 LOG(serializer_->isolate_, |
| 1566 CodeNameEvent(object_->address(), sink_->Position(), code_name)); | 1528 CodeNameEvent(object_->address(), sink_->Position(), code_name)); |
| 1567 LOG(serializer_->isolate_, | 1529 LOG(serializer_->isolate_, |
| 1568 SnapshotPositionEvent(object_->address(), sink_->Position())); | 1530 SnapshotPositionEvent(object_->address(), sink_->Position())); |
| 1569 } | 1531 } |
| 1570 | 1532 |
| 1571 // Mark this object as already serialized. | 1533 // Mark this object as already serialized. |
| 1572 if (space == LO_SPACE) { | 1534 if (space == LO_SPACE) { |
| 1573 if (object_->IsCode()) { | 1535 if (object_->IsCode()) { |
| 1574 sink_->Put(EXECUTABLE, "executable large object"); | 1536 sink_->PutInt(EXECUTABLE, "executable large object"); |
| 1575 } else { | 1537 } else { |
| 1576 sink_->Put(NOT_EXECUTABLE, "not executable large object"); | 1538 sink_->PutInt(NOT_EXECUTABLE, "not executable large object"); |
| 1577 } | 1539 } |
| 1578 int index = serializer_->AllocateLargeObject(size); | 1540 int index = serializer_->AllocateLargeObject(size); |
| 1579 serializer_->address_mapper()->AddMapping(object_, index); | 1541 serializer_->address_mapper()->AddMapping(object_, index); |
| 1580 } else { | 1542 } else { |
| 1581 int allocation = serializer_->Allocate(space, size); | 1543 int offset = serializer_->Allocate(space, size); |
| 1582 serializer_->address_mapper()->AddMapping(object_, allocation); | 1544 serializer_->address_mapper()->AddMapping(object_, offset); |
| 1583 } | 1545 } |
| 1584 | 1546 |
| 1585 // Serialize the map (first word of the object). | 1547 // Serialize the map (first word of the object). |
| 1586 serializer_->SerializeObject(map, kPlain, kStartOfObject, 0); | 1548 serializer_->SerializeObject(map, kPlain, kStartOfObject, 0); |
| 1587 } | 1549 } |
| 1588 | 1550 |
| 1589 | 1551 |
| 1590 void Serializer::ObjectSerializer::SerializeExternalString() { | 1552 void Serializer::ObjectSerializer::SerializeExternalString() { |
| 1591 // Instead of serializing this as an external string, we serialize | 1553 // Instead of serializing this as an external string, we serialize |
| 1592 // an imaginary sequential string with the same content. | 1554 // an imaginary sequential string with the same content. |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1898 if (object->GetHeap()->InSpace(object, s)) { | 1860 if (object->GetHeap()->InSpace(object, s)) { |
| 1899 DCHECK(i < kNumberOfSpaces); | 1861 DCHECK(i < kNumberOfSpaces); |
| 1900 return i; | 1862 return i; |
| 1901 } | 1863 } |
| 1902 } | 1864 } |
| 1903 UNREACHABLE(); | 1865 UNREACHABLE(); |
| 1904 return 0; | 1866 return 0; |
| 1905 } | 1867 } |
| 1906 | 1868 |
| 1907 | 1869 |
| 1908 uint32_t Serializer::AllocateLargeObject(int size) { | 1870 int Serializer::AllocateLargeObject(int size) { |
| 1909 // Large objects are allocated one-by-one when deserializing. We do not | 1871 fullness_[LO_SPACE] += size; |
| 1910 // have to keep track of multiple chunks. | |
| 1911 pending_chunk_[LO_SPACE] += size; | |
| 1912 return seen_large_objects_index_++; | 1872 return seen_large_objects_index_++; |
| 1913 } | 1873 } |
| 1914 | 1874 |
| 1915 | 1875 |
| 1916 uint32_t Serializer::Allocate(int space, int size) { | 1876 int Serializer::Allocate(int space, int size) { |
| 1917 CHECK(space >= 0 && space < kNumberOfPreallocatedSpaces); | 1877 CHECK(space >= 0 && space < kNumberOfPreallocatedSpaces); |
| 1918 DCHECK(size > 0 && size < Page::kMaxRegularHeapObjectSize); | 1878 int allocation_address = fullness_[space]; |
| 1919 uint32_t new_chunk_size = pending_chunk_[space] + size; | 1879 fullness_[space] = allocation_address + size; |
| 1920 uint32_t allocation; | 1880 return allocation_address; |
| 1921 if (new_chunk_size > Page::kMaxRegularHeapObjectSize) { | |
| 1922 // The new chunk size would not fit onto a single page. Complete the | |
| 1923 // current chunk and start a new one. | |
| 1924 completed_chunks_[space].Add(pending_chunk_[space]); | |
| 1925 pending_chunk_[space] = 0; | |
| 1926 new_chunk_size = size; | |
| 1927 } | |
| 1928 // For back-referencing, each allocation is encoded as a combination | |
| 1929 // of chunk index and offset inside the chunk. | |
| 1930 allocation = ChunkIndexBits::encode(completed_chunks_[space].length()) | | |
| 1931 OffsetBits::encode(pending_chunk_[space]); | |
| 1932 pending_chunk_[space] = new_chunk_size; | |
| 1933 return allocation; | |
| 1934 } | 1881 } |
| 1935 | 1882 |
| 1936 | 1883 |
| 1937 int Serializer::SpaceAreaSize(int space) { | 1884 int Serializer::SpaceAreaSize(int space) { |
| 1938 if (space == CODE_SPACE) { | 1885 if (space == CODE_SPACE) { |
| 1939 return isolate_->memory_allocator()->CodePageAreaSize(); | 1886 return isolate_->memory_allocator()->CodePageAreaSize(); |
| 1940 } else { | 1887 } else { |
| 1941 return Page::kPageSize - Page::kObjectStartOffset; | 1888 return Page::kPageSize - Page::kObjectStartOffset; |
| 1942 } | 1889 } |
| 1943 } | 1890 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1969 ListSnapshotSink list_sink(&payload); | 1916 ListSnapshotSink list_sink(&payload); |
| 1970 DebugSnapshotSink debug_sink(&list_sink); | 1917 DebugSnapshotSink debug_sink(&list_sink); |
| 1971 SnapshotByteSink* sink = FLAG_trace_code_serializer | 1918 SnapshotByteSink* sink = FLAG_trace_code_serializer |
| 1972 ? static_cast<SnapshotByteSink*>(&debug_sink) | 1919 ? static_cast<SnapshotByteSink*>(&debug_sink) |
| 1973 : static_cast<SnapshotByteSink*>(&list_sink); | 1920 : static_cast<SnapshotByteSink*>(&list_sink); |
| 1974 CodeSerializer cs(isolate, sink, *source, info->code()); | 1921 CodeSerializer cs(isolate, sink, *source, info->code()); |
| 1975 DisallowHeapAllocation no_gc; | 1922 DisallowHeapAllocation no_gc; |
| 1976 Object** location = Handle<Object>::cast(info).location(); | 1923 Object** location = Handle<Object>::cast(info).location(); |
| 1977 cs.VisitPointer(location); | 1924 cs.VisitPointer(location); |
| 1978 cs.Pad(); | 1925 cs.Pad(); |
| 1979 cs.FinalizeAllocation(); | |
| 1980 | 1926 |
| 1981 SerializedCodeData data(&payload, &cs); | 1927 SerializedCodeData data(&payload, &cs); |
| 1982 ScriptData* script_data = data.GetScriptData(); | 1928 ScriptData* script_data = data.GetScriptData(); |
| 1983 | 1929 |
| 1984 if (FLAG_profile_deserialization) { | 1930 if (FLAG_profile_deserialization) { |
| 1985 double ms = timer.Elapsed().InMillisecondsF(); | 1931 double ms = timer.Elapsed().InMillisecondsF(); |
| 1986 int length = script_data->length(); | 1932 int length = script_data->length(); |
| 1987 PrintF("[Serializing to %d bytes took %0.3f ms]\n", length, ms); | 1933 PrintF("[Serializing to %d bytes took %0.3f ms]\n", length, ms); |
| 1988 } | 1934 } |
| 1989 | 1935 |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2140 void CodeSerializer::SerializeSourceObject(HowToCode how_to_code, | 2086 void CodeSerializer::SerializeSourceObject(HowToCode how_to_code, |
| 2141 WhereToPoint where_to_point) { | 2087 WhereToPoint where_to_point) { |
| 2142 if (FLAG_trace_code_serializer) PrintF("Encoding source object\n"); | 2088 if (FLAG_trace_code_serializer) PrintF("Encoding source object\n"); |
| 2143 | 2089 |
| 2144 DCHECK(how_to_code == kPlain && where_to_point == kStartOfObject); | 2090 DCHECK(how_to_code == kPlain && where_to_point == kStartOfObject); |
| 2145 sink_->Put(kAttachedReference + how_to_code + where_to_point, "Source"); | 2091 sink_->Put(kAttachedReference + how_to_code + where_to_point, "Source"); |
| 2146 sink_->PutInt(kSourceObjectIndex, "kSourceObjectIndex"); | 2092 sink_->PutInt(kSourceObjectIndex, "kSourceObjectIndex"); |
| 2147 } | 2093 } |
| 2148 | 2094 |
| 2149 | 2095 |
| 2150 MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize( | 2096 Handle<SharedFunctionInfo> CodeSerializer::Deserialize(Isolate* isolate, |
| 2151 Isolate* isolate, ScriptData* data, Handle<String> source) { | 2097 ScriptData* data, |
| 2098 Handle<String> source) { |
| 2152 base::ElapsedTimer timer; | 2099 base::ElapsedTimer timer; |
| 2153 if (FLAG_profile_deserialization) timer.Start(); | 2100 if (FLAG_profile_deserialization) timer.Start(); |
| 2154 | 2101 |
| 2155 Object* root; | 2102 Object* root; |
| 2156 | 2103 |
| 2157 { | 2104 { |
| 2158 HandleScope scope(isolate); | 2105 HandleScope scope(isolate); |
| 2159 | 2106 |
| 2160 SerializedCodeData scd(data, *source); | 2107 SerializedCodeData scd(data, *source); |
| 2161 SnapshotByteSource payload(scd.Payload(), scd.PayloadLength()); | 2108 SnapshotByteSource payload(scd.Payload(), scd.PayloadLength()); |
| 2162 Deserializer deserializer(&payload); | 2109 Deserializer deserializer(&payload); |
| 2163 | |
| 2164 STATIC_ASSERT(NEW_SPACE == 0); | 2110 STATIC_ASSERT(NEW_SPACE == 0); |
| 2165 int current_space = NEW_SPACE; | 2111 for (int i = NEW_SPACE; i < kNumberOfSpaces; i++) { |
| 2166 Vector<const SerializedCodeData::Reservation> res = scd.Reservations(); | 2112 deserializer.set_reservation(i, scd.GetReservation(i)); |
| 2167 for (const auto& r : res) { | |
| 2168 deserializer.AddReservation(current_space, r.chunk_size()); | |
| 2169 if (r.is_last_chunk()) current_space++; | |
| 2170 } | 2113 } |
| 2171 DCHECK_EQ(kNumberOfSpaces, current_space); | |
| 2172 | 2114 |
| 2173 // Prepare and register list of attached objects. | 2115 // Prepare and register list of attached objects. |
| 2174 Vector<const uint32_t> code_stub_keys = scd.CodeStubKeys(); | 2116 Vector<const uint32_t> code_stub_keys = scd.CodeStubKeys(); |
| 2175 Vector<Handle<Object> > attached_objects = Vector<Handle<Object> >::New( | 2117 Vector<Handle<Object> > attached_objects = Vector<Handle<Object> >::New( |
| 2176 code_stub_keys.length() + kCodeStubsBaseIndex); | 2118 code_stub_keys.length() + kCodeStubsBaseIndex); |
| 2177 attached_objects[kSourceObjectIndex] = source; | 2119 attached_objects[kSourceObjectIndex] = source; |
| 2178 for (int i = 0; i < code_stub_keys.length(); i++) { | 2120 for (int i = 0; i < code_stub_keys.length(); i++) { |
| 2179 attached_objects[i + kCodeStubsBaseIndex] = | 2121 attached_objects[i + kCodeStubsBaseIndex] = |
| 2180 CodeStub::GetCode(isolate, code_stub_keys[i]).ToHandleChecked(); | 2122 CodeStub::GetCode(isolate, code_stub_keys[i]).ToHandleChecked(); |
| 2181 } | 2123 } |
| 2182 deserializer.SetAttachedObjects(&attached_objects); | 2124 deserializer.SetAttachedObjects(&attached_objects); |
| 2183 | 2125 |
| 2184 // Deserialize. | 2126 // Deserialize. |
| 2185 deserializer.DeserializePartial(isolate, &root, Deserializer::NULL_ON_OOM); | 2127 deserializer.DeserializePartial(isolate, &root); |
| 2186 if (root == NULL) { | |
| 2187 // Deserializing may fail if the reservations cannot be fulfilled. | |
| 2188 if (FLAG_profile_deserialization) PrintF("[Deserializing failed]\n"); | |
| 2189 return MaybeHandle<SharedFunctionInfo>(); | |
| 2190 } | |
| 2191 deserializer.FlushICacheForNewCodeObjects(); | 2128 deserializer.FlushICacheForNewCodeObjects(); |
| 2192 } | 2129 } |
| 2193 | 2130 |
| 2194 if (FLAG_profile_deserialization) { | 2131 if (FLAG_profile_deserialization) { |
| 2195 double ms = timer.Elapsed().InMillisecondsF(); | 2132 double ms = timer.Elapsed().InMillisecondsF(); |
| 2196 int length = data->length(); | 2133 int length = data->length(); |
| 2197 PrintF("[Deserializing from %d bytes took %0.3f ms]\n", length, ms); | 2134 PrintF("[Deserializing from %d bytes took %0.3f ms]\n", length, ms); |
| 2198 } | 2135 } |
| 2199 Handle<SharedFunctionInfo> result(SharedFunctionInfo::cast(root), isolate); | 2136 Handle<SharedFunctionInfo> result(SharedFunctionInfo::cast(root), isolate); |
| 2200 result->set_deserialized(true); | 2137 result->set_deserialized(true); |
| 2201 return result; | 2138 return result; |
| 2202 } | 2139 } |
| 2203 | 2140 |
| 2204 | 2141 |
| 2205 SerializedCodeData::SerializedCodeData(List<byte>* payload, CodeSerializer* cs) | 2142 SerializedCodeData::SerializedCodeData(List<byte>* payload, CodeSerializer* cs) |
| 2206 : owns_script_data_(true) { | 2143 : owns_script_data_(true) { |
| 2207 DisallowHeapAllocation no_gc; | 2144 DisallowHeapAllocation no_gc; |
| 2208 List<uint32_t>* stub_keys = cs->stub_keys(); | 2145 List<uint32_t>* stub_keys = cs->stub_keys(); |
| 2209 | 2146 |
| 2210 // Gather reservation chunk sizes. | |
| 2211 List<uint32_t> reservations(SerializerDeserializer::kNumberOfSpaces); | |
| 2212 STATIC_ASSERT(NEW_SPACE == 0); | |
| 2213 for (int i = 0; i < SerializerDeserializer::kNumberOfSpaces; i++) { | |
| 2214 Vector<const uint32_t> chunks = cs->FinalAllocationChunks(i); | |
| 2215 for (int j = 0; j < chunks.length(); j++) { | |
| 2216 DCHECK(i == LO_SPACE || chunks[j] < Page::kMaxRegularHeapObjectSize); | |
| 2217 uint32_t chunk = ChunkSizeBits::encode(chunks[j]) | | |
| 2218 IsLastChunkBits::encode(j == chunks.length() - 1); | |
| 2219 reservations.Add(chunk); | |
| 2220 } | |
| 2221 } | |
| 2222 | |
| 2223 // Calculate sizes. | 2147 // Calculate sizes. |
| 2224 int reservation_size = reservations.length() * kInt32Size; | |
| 2225 int num_stub_keys = stub_keys->length(); | 2148 int num_stub_keys = stub_keys->length(); |
| 2226 int stub_keys_size = stub_keys->length() * kInt32Size; | 2149 int stub_keys_size = stub_keys->length() * kInt32Size; |
| 2227 int data_length = | 2150 int data_length = kHeaderSize + stub_keys_size + payload->length(); |
| 2228 kHeaderSize + reservation_size + stub_keys_size + payload->length(); | |
| 2229 | 2151 |
| 2230 // Allocate backing store and create result data. | 2152 // Allocate backing store and create result data. |
| 2231 byte* data = NewArray<byte>(data_length); | 2153 byte* data = NewArray<byte>(data_length); |
| 2232 DCHECK(IsAligned(reinterpret_cast<intptr_t>(data), kPointerAlignment)); | 2154 DCHECK(IsAligned(reinterpret_cast<intptr_t>(data), kPointerAlignment)); |
| 2233 script_data_ = new ScriptData(data, data_length); | 2155 script_data_ = new ScriptData(data, data_length); |
| 2234 script_data_->AcquireDataOwnership(); | 2156 script_data_->AcquireDataOwnership(); |
| 2235 | 2157 |
| 2236 // Set header values. | 2158 // Set header values. |
| 2237 SetHeaderValue(kCheckSumOffset, CheckSum(cs->source())); | 2159 SetHeaderValue(kCheckSumOffset, CheckSum(cs->source())); |
| 2238 SetHeaderValue(kReservationsOffset, reservations.length()); | |
| 2239 SetHeaderValue(kNumCodeStubKeysOffset, num_stub_keys); | 2160 SetHeaderValue(kNumCodeStubKeysOffset, num_stub_keys); |
| 2240 SetHeaderValue(kPayloadLengthOffset, payload->length()); | 2161 SetHeaderValue(kPayloadLengthOffset, payload->length()); |
| 2241 | 2162 STATIC_ASSERT(NEW_SPACE == 0); |
| 2242 // Copy reservation chunk sizes. | 2163 for (int i = 0; i < SerializerDeserializer::kNumberOfSpaces; i++) { |
| 2243 CopyBytes(data + kHeaderSize, reinterpret_cast<byte*>(reservations.begin()), | 2164 SetHeaderValue(kReservationsOffset + i, cs->CurrentAllocationAddress(i)); |
| 2244 reservation_size); | 2165 } |
| 2245 | 2166 |
| 2246 // Copy code stub keys. | 2167 // Copy code stub keys. |
| 2247 CopyBytes(data + kHeaderSize + reservation_size, | 2168 CopyBytes(data + kHeaderSize, reinterpret_cast<byte*>(stub_keys->begin()), |
| 2248 reinterpret_cast<byte*>(stub_keys->begin()), stub_keys_size); | 2169 stub_keys_size); |
| 2249 | 2170 |
| 2250 // Copy serialized data. | 2171 // Copy serialized data. |
| 2251 CopyBytes(data + kHeaderSize + reservation_size + stub_keys_size, | 2172 CopyBytes(data + kHeaderSize + stub_keys_size, payload->begin(), |
| 2252 payload->begin(), static_cast<size_t>(payload->length())); | 2173 static_cast<size_t>(payload->length())); |
| 2253 } | 2174 } |
| 2254 | 2175 |
| 2255 | 2176 |
| 2256 bool SerializedCodeData::IsSane(String* source) { | 2177 bool SerializedCodeData::IsSane(String* source) { |
| 2257 return GetHeaderValue(kCheckSumOffset) == CheckSum(source) && | 2178 return GetHeaderValue(kCheckSumOffset) == CheckSum(source) && |
| 2258 PayloadLength() >= SharedFunctionInfo::kSize; | 2179 PayloadLength() >= SharedFunctionInfo::kSize; |
| 2259 } | 2180 } |
| 2260 | 2181 |
| 2261 | 2182 |
| 2262 int SerializedCodeData::CheckSum(String* string) { | 2183 int SerializedCodeData::CheckSum(String* string) { |
| 2263 int checksum = Version::Hash(); | 2184 int checksum = Version::Hash(); |
| 2264 #ifdef DEBUG | 2185 #ifdef DEBUG |
| 2265 uint32_t seed = static_cast<uint32_t>(checksum); | 2186 uint32_t seed = static_cast<uint32_t>(checksum); |
| 2266 checksum = static_cast<int>(IteratingStringHasher::Hash(string, seed)); | 2187 checksum = static_cast<int>(IteratingStringHasher::Hash(string, seed)); |
| 2267 #endif // DEBUG | 2188 #endif // DEBUG |
| 2268 return checksum; | 2189 return checksum; |
| 2269 } | 2190 } |
| 2270 } } // namespace v8::internal | 2191 } } // namespace v8::internal |
| OLD | NEW |