| 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 #ifndef V8_SNAPSHOT_SERIALIZE_H_ | 5 #ifndef V8_SNAPSHOT_SERIALIZE_H_ |
| 6 #define V8_SNAPSHOT_SERIALIZE_H_ | 6 #define V8_SNAPSHOT_SERIALIZE_H_ |
| 7 | 7 |
| 8 #include "src/hashmap.h" | 8 #include "src/hashmap.h" |
| 9 #include "src/isolate.h" | 9 #include "src/heap/heap.h" |
| 10 #include "src/objects.h" |
| 10 #include "src/snapshot/snapshot-source-sink.h" | 11 #include "src/snapshot/snapshot-source-sink.h" |
| 11 | 12 |
| 12 namespace v8 { | 13 namespace v8 { |
| 13 namespace internal { | 14 namespace internal { |
| 14 | 15 |
| 16 class Isolate; |
| 15 class ScriptData; | 17 class ScriptData; |
| 16 | 18 |
| 17 static const int kDeoptTableSerializeEntryCount = 64; | 19 static const int kDeoptTableSerializeEntryCount = 64; |
| 18 | 20 |
| 19 // ExternalReferenceTable is a helper class that defines the relationship | 21 // ExternalReferenceTable is a helper class that defines the relationship |
| 20 // between external references and their encodings. It is used to build | 22 // between external references and their encodings. It is used to build |
| 21 // hashmaps in ExternalReferenceEncoder and ExternalReferenceDecoder. | 23 // hashmaps in ExternalReferenceEncoder and ExternalReferenceDecoder. |
| 22 class ExternalReferenceTable { | 24 class ExternalReferenceTable { |
| 23 public: | 25 public: |
| 24 static ExternalReferenceTable* instance(Isolate* isolate); | 26 static ExternalReferenceTable* instance(Isolate* isolate); |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 301 public: | 303 public: |
| 302 static void Iterate(Isolate* isolate, ObjectVisitor* visitor); | 304 static void Iterate(Isolate* isolate, ObjectVisitor* visitor); |
| 303 | 305 |
| 304 static int nop() { return kNop; } | 306 static int nop() { return kNop; } |
| 305 | 307 |
| 306 // No reservation for large object space necessary. | 308 // No reservation for large object space necessary. |
| 307 static const int kNumberOfPreallocatedSpaces = LAST_PAGED_SPACE + 1; | 309 static const int kNumberOfPreallocatedSpaces = LAST_PAGED_SPACE + 1; |
| 308 static const int kNumberOfSpaces = LAST_SPACE + 1; | 310 static const int kNumberOfSpaces = LAST_SPACE + 1; |
| 309 | 311 |
| 310 protected: | 312 protected: |
| 311 static bool CanBeDeferred(HeapObject* o) { | 313 static bool CanBeDeferred(HeapObject* o); |
| 312 return !o->IsString() && !o->IsScript(); | |
| 313 } | |
| 314 | 314 |
| 315 // ---------- byte code range 0x00..0x7f ---------- | 315 // ---------- byte code range 0x00..0x7f ---------- |
| 316 // Byte codes in this range represent Where, HowToCode and WhereToPoint. | 316 // Byte codes in this range represent Where, HowToCode and WhereToPoint. |
| 317 // Where the pointed-to object can be found: | 317 // Where the pointed-to object can be found: |
| 318 // The static assert below will trigger when the number of preallocated spaces | 318 // The static assert below will trigger when the number of preallocated spaces |
| 319 // changed. If that happens, update the bytecode ranges in the comments below. | 319 // changed. If that happens, update the bytecode ranges in the comments below. |
| 320 STATIC_ASSERT(5 == kNumberOfSpaces); | 320 STATIC_ASSERT(5 == kNumberOfSpaces); |
| 321 enum Where { | 321 enum Where { |
| 322 // 0x00..0x04 Allocate new object, in specified space. | 322 // 0x00..0x04 Allocate new object, in specified space. |
| 323 kNewObject = 0, | 323 kNewObject = 0, |
| (...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 646 Isolate* isolate() const { return isolate_; } | 646 Isolate* isolate() const { return isolate_; } |
| 647 | 647 |
| 648 BackReferenceMap* back_reference_map() { return &back_reference_map_; } | 648 BackReferenceMap* back_reference_map() { return &back_reference_map_; } |
| 649 RootIndexMap* root_index_map() { return &root_index_map_; } | 649 RootIndexMap* root_index_map() { return &root_index_map_; } |
| 650 | 650 |
| 651 #ifdef OBJECT_PRINT | 651 #ifdef OBJECT_PRINT |
| 652 void CountInstanceType(Map* map, int size); | 652 void CountInstanceType(Map* map, int size); |
| 653 #endif // OBJECT_PRINT | 653 #endif // OBJECT_PRINT |
| 654 | 654 |
| 655 protected: | 655 protected: |
| 656 class ObjectSerializer : public ObjectVisitor { | 656 class ObjectSerializer; |
| 657 public: | |
| 658 ObjectSerializer(Serializer* serializer, Object* o, SnapshotByteSink* sink, | |
| 659 HowToCode how_to_code, WhereToPoint where_to_point) | |
| 660 : serializer_(serializer), | |
| 661 object_(HeapObject::cast(o)), | |
| 662 sink_(sink), | |
| 663 reference_representation_(how_to_code + where_to_point), | |
| 664 bytes_processed_so_far_(0), | |
| 665 is_code_object_(o->IsCode()), | |
| 666 code_has_been_output_(false) {} | |
| 667 void Serialize(); | |
| 668 void SerializeDeferred(); | |
| 669 void VisitPointers(Object** start, Object** end); | |
| 670 void VisitEmbeddedPointer(RelocInfo* target); | |
| 671 void VisitExternalReference(Address* p); | |
| 672 void VisitExternalReference(RelocInfo* rinfo); | |
| 673 void VisitInternalReference(RelocInfo* rinfo); | |
| 674 void VisitCodeTarget(RelocInfo* target); | |
| 675 void VisitCodeEntry(Address entry_address); | |
| 676 void VisitCell(RelocInfo* rinfo); | |
| 677 void VisitRuntimeEntry(RelocInfo* reloc); | |
| 678 // Used for seralizing the external strings that hold the natives source. | |
| 679 void VisitExternalOneByteString( | |
| 680 v8::String::ExternalOneByteStringResource** resource); | |
| 681 // We can't serialize a heap with external two byte strings. | |
| 682 void VisitExternalTwoByteString( | |
| 683 v8::String::ExternalStringResource** resource) { | |
| 684 UNREACHABLE(); | |
| 685 } | |
| 686 | |
| 687 private: | |
| 688 void SerializePrologue(AllocationSpace space, int size, Map* map); | |
| 689 | |
| 690 bool SerializeExternalNativeSourceString( | |
| 691 int builtin_count, | |
| 692 v8::String::ExternalOneByteStringResource** resource_pointer, | |
| 693 FixedArray* source_cache, int resource_index); | |
| 694 | |
| 695 enum ReturnSkip { kCanReturnSkipInsteadOfSkipping, kIgnoringReturn }; | |
| 696 // This function outputs or skips the raw data between the last pointer and | |
| 697 // up to the current position. It optionally can just return the number of | |
| 698 // bytes to skip instead of performing a skip instruction, in case the skip | |
| 699 // can be merged into the next instruction. | |
| 700 int OutputRawData(Address up_to, ReturnSkip return_skip = kIgnoringReturn); | |
| 701 // External strings are serialized in a way to resemble sequential strings. | |
| 702 void SerializeExternalString(); | |
| 703 | |
| 704 Address PrepareCode(); | |
| 705 | |
| 706 Serializer* serializer_; | |
| 707 HeapObject* object_; | |
| 708 SnapshotByteSink* sink_; | |
| 709 int reference_representation_; | |
| 710 int bytes_processed_so_far_; | |
| 711 bool is_code_object_; | |
| 712 bool code_has_been_output_; | |
| 713 }; | |
| 714 | |
| 715 class RecursionScope { | 657 class RecursionScope { |
| 716 public: | 658 public: |
| 717 explicit RecursionScope(Serializer* serializer) : serializer_(serializer) { | 659 explicit RecursionScope(Serializer* serializer) : serializer_(serializer) { |
| 718 serializer_->recursion_depth_++; | 660 serializer_->recursion_depth_++; |
| 719 } | 661 } |
| 720 ~RecursionScope() { serializer_->recursion_depth_--; } | 662 ~RecursionScope() { serializer_->recursion_depth_--; } |
| 721 bool ExceedsMaximum() { | 663 bool ExceedsMaximum() { |
| 722 return serializer_->recursion_depth_ >= kMaxRecursionDepth; | 664 return serializer_->recursion_depth_ >= kMaxRecursionDepth; |
| 723 } | 665 } |
| 724 | 666 |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 843 | 785 |
| 844 ~PartialSerializer() { OutputStatistics("PartialSerializer"); } | 786 ~PartialSerializer() { OutputStatistics("PartialSerializer"); } |
| 845 | 787 |
| 846 // Serialize the objects reachable from a single object pointer. | 788 // Serialize the objects reachable from a single object pointer. |
| 847 void Serialize(Object** o); | 789 void Serialize(Object** o); |
| 848 virtual void SerializeObject(HeapObject* o, HowToCode how_to_code, | 790 virtual void SerializeObject(HeapObject* o, HowToCode how_to_code, |
| 849 WhereToPoint where_to_point, int skip) override; | 791 WhereToPoint where_to_point, int skip) override; |
| 850 | 792 |
| 851 private: | 793 private: |
| 852 int PartialSnapshotCacheIndex(HeapObject* o); | 794 int PartialSnapshotCacheIndex(HeapObject* o); |
| 853 bool ShouldBeInThePartialSnapshotCache(HeapObject* o) { | 795 bool ShouldBeInThePartialSnapshotCache(HeapObject* o); |
| 854 // Scripts should be referred only through shared function infos. We can't | |
| 855 // allow them to be part of the partial snapshot because they contain a | |
| 856 // unique ID, and deserializing several partial snapshots containing script | |
| 857 // would cause dupes. | |
| 858 DCHECK(!o->IsScript()); | |
| 859 return o->IsName() || o->IsSharedFunctionInfo() || o->IsHeapNumber() || | |
| 860 o->IsCode() || o->IsScopeInfo() || o->IsExecutableAccessorInfo() || | |
| 861 o->map() == | |
| 862 startup_serializer_->isolate()->heap()->fixed_cow_array_map(); | |
| 863 } | |
| 864 | 796 |
| 865 void SerializeOutdatedContextsAsFixedArray(); | 797 void SerializeOutdatedContextsAsFixedArray(); |
| 866 | 798 |
| 867 Serializer* startup_serializer_; | 799 Serializer* startup_serializer_; |
| 868 List<Context*> outdated_contexts_; | 800 List<Context*> outdated_contexts_; |
| 869 Object* global_object_; | 801 Object* global_object_; |
| 870 PartialCacheIndexMap partial_cache_index_map_; | 802 PartialCacheIndexMap partial_cache_index_map_; |
| 871 DISALLOW_COPY_AND_ASSIGN(PartialSerializer); | 803 DISALLOW_COPY_AND_ASSIGN(PartialSerializer); |
| 872 }; | 804 }; |
| 873 | 805 |
| 874 | 806 |
| 875 class StartupSerializer : public Serializer { | 807 class StartupSerializer : public Serializer { |
| 876 public: | 808 public: |
| 877 StartupSerializer(Isolate* isolate, SnapshotByteSink* sink) | 809 StartupSerializer(Isolate* isolate, SnapshotByteSink* sink); |
| 878 : Serializer(isolate, sink), root_index_wave_front_(0) { | |
| 879 // Clear the cache of objects used by the partial snapshot. After the | |
| 880 // strong roots have been serialized we can create a partial snapshot | |
| 881 // which will repopulate the cache with objects needed by that partial | |
| 882 // snapshot. | |
| 883 isolate->partial_snapshot_cache()->Clear(); | |
| 884 InitializeCodeAddressMap(); | |
| 885 } | |
| 886 | |
| 887 ~StartupSerializer() { OutputStatistics("StartupSerializer"); } | 810 ~StartupSerializer() { OutputStatistics("StartupSerializer"); } |
| 888 | 811 |
| 889 // The StartupSerializer has to serialize the root array, which is slightly | 812 // The StartupSerializer has to serialize the root array, which is slightly |
| 890 // different. | 813 // different. |
| 891 void VisitPointers(Object** start, Object** end) override; | 814 void VisitPointers(Object** start, Object** end) override; |
| 892 | 815 |
| 893 // Serialize the current state of the heap. The order is: | 816 // Serialize the current state of the heap. The order is: |
| 894 // 1) Strong references. | 817 // 1) Strong references. |
| 895 // 2) Partial snapshot cache. | 818 // 2) Partial snapshot cache. |
| 896 // 3) Weak references (e.g. the string table). | 819 // 3) Weak references (e.g. the string table). |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1023 MAGIC_NUMBER_MISMATCH = 1, | 946 MAGIC_NUMBER_MISMATCH = 1, |
| 1024 VERSION_MISMATCH = 2, | 947 VERSION_MISMATCH = 2, |
| 1025 SOURCE_MISMATCH = 3, | 948 SOURCE_MISMATCH = 3, |
| 1026 CPU_FEATURES_MISMATCH = 4, | 949 CPU_FEATURES_MISMATCH = 4, |
| 1027 FLAGS_MISMATCH = 5, | 950 FLAGS_MISMATCH = 5, |
| 1028 CHECKSUM_MISMATCH = 6 | 951 CHECKSUM_MISMATCH = 6 |
| 1029 }; | 952 }; |
| 1030 | 953 |
| 1031 SanityCheckResult SanityCheck(Isolate* isolate, String* source) const; | 954 SanityCheckResult SanityCheck(Isolate* isolate, String* source) const; |
| 1032 | 955 |
| 1033 uint32_t SourceHash(String* source) const { return source->length(); } | 956 uint32_t SourceHash(String* source) const; |
| 1034 | 957 |
| 1035 // The data header consists of uint32_t-sized entries: | 958 // The data header consists of uint32_t-sized entries: |
| 1036 // [0] magic number and external reference count | 959 // [0] magic number and external reference count |
| 1037 // [1] version hash | 960 // [1] version hash |
| 1038 // [2] source hash | 961 // [2] source hash |
| 1039 // [3] cpu features | 962 // [3] cpu features |
| 1040 // [4] flag hash | 963 // [4] flag hash |
| 1041 // [5] number of code stub keys | 964 // [5] number of code stub keys |
| 1042 // [6] number of reservation size entries | 965 // [6] number of reservation size entries |
| 1043 // [7] payload length | 966 // [7] payload length |
| 1044 // [8] payload checksum part 1 | 967 // [8] payload checksum part 1 |
| 1045 // [9] payload checksum part 2 | 968 // [9] payload checksum part 2 |
| 1046 // ... reservations | 969 // ... reservations |
| 1047 // ... code stub keys | 970 // ... code stub keys |
| 1048 // ... serialized payload | 971 // ... serialized payload |
| 1049 static const int kVersionHashOffset = kMagicNumberOffset + kInt32Size; | 972 static const int kVersionHashOffset = kMagicNumberOffset + kInt32Size; |
| 1050 static const int kSourceHashOffset = kVersionHashOffset + kInt32Size; | 973 static const int kSourceHashOffset = kVersionHashOffset + kInt32Size; |
| 1051 static const int kCpuFeaturesOffset = kSourceHashOffset + kInt32Size; | 974 static const int kCpuFeaturesOffset = kSourceHashOffset + kInt32Size; |
| 1052 static const int kFlagHashOffset = kCpuFeaturesOffset + kInt32Size; | 975 static const int kFlagHashOffset = kCpuFeaturesOffset + kInt32Size; |
| 1053 static const int kNumReservationsOffset = kFlagHashOffset + kInt32Size; | 976 static const int kNumReservationsOffset = kFlagHashOffset + kInt32Size; |
| 1054 static const int kNumCodeStubKeysOffset = kNumReservationsOffset + kInt32Size; | 977 static const int kNumCodeStubKeysOffset = kNumReservationsOffset + kInt32Size; |
| 1055 static const int kPayloadLengthOffset = kNumCodeStubKeysOffset + kInt32Size; | 978 static const int kPayloadLengthOffset = kNumCodeStubKeysOffset + kInt32Size; |
| 1056 static const int kChecksum1Offset = kPayloadLengthOffset + kInt32Size; | 979 static const int kChecksum1Offset = kPayloadLengthOffset + kInt32Size; |
| 1057 static const int kChecksum2Offset = kChecksum1Offset + kInt32Size; | 980 static const int kChecksum2Offset = kChecksum1Offset + kInt32Size; |
| 1058 static const int kHeaderSize = kChecksum2Offset + kInt32Size; | 981 static const int kHeaderSize = kChecksum2Offset + kInt32Size; |
| 1059 }; | 982 }; |
| 1060 } } // namespace v8::internal | 983 } } // namespace v8::internal |
| 1061 | 984 |
| 1062 #endif // V8_SNAPSHOT_SERIALIZE_H_ | 985 #endif // V8_SNAPSHOT_SERIALIZE_H_ |
| OLD | NEW |