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 |