OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 26 matching lines...) Expand all Loading... |
37 #include "runtime.h" | 37 #include "runtime.h" |
38 #include "serialize.h" | 38 #include "serialize.h" |
39 #include "stub-cache.h" | 39 #include "stub-cache.h" |
40 #include "v8threads.h" | 40 #include "v8threads.h" |
41 #include "top.h" | 41 #include "top.h" |
42 #include "bootstrapper.h" | 42 #include "bootstrapper.h" |
43 | 43 |
44 namespace v8 { | 44 namespace v8 { |
45 namespace internal { | 45 namespace internal { |
46 | 46 |
47 // Mapping objects to their location after deserialization. | |
48 // This is used during building, but not at runtime by V8. | |
49 class SerializationAddressMapper { | |
50 public: | |
51 static bool IsMapped(HeapObject* obj) { | |
52 EnsureMapExists(); | |
53 return serialization_map_->Lookup(Key(obj), Hash(obj), false) != NULL; | |
54 } | |
55 | |
56 static int MappedTo(HeapObject* obj) { | |
57 ASSERT(IsMapped(obj)); | |
58 return static_cast<int>(reinterpret_cast<intptr_t>( | |
59 serialization_map_->Lookup(Key(obj), Hash(obj), false)->value)); | |
60 } | |
61 | |
62 static void Map(HeapObject* obj, int to) { | |
63 EnsureMapExists(); | |
64 ASSERT(!IsMapped(obj)); | |
65 HashMap::Entry* entry = | |
66 serialization_map_->Lookup(Key(obj), Hash(obj), true); | |
67 entry->value = Value(to); | |
68 } | |
69 | |
70 static void Zap() { | |
71 if (serialization_map_ != NULL) { | |
72 delete serialization_map_; | |
73 } | |
74 serialization_map_ = NULL; | |
75 } | |
76 | |
77 private: | |
78 static bool SerializationMatchFun(void* key1, void* key2) { | |
79 return key1 == key2; | |
80 } | |
81 | |
82 static uint32_t Hash(HeapObject* obj) { | |
83 return static_cast<int32_t>(reinterpret_cast<intptr_t>(obj->address())); | |
84 } | |
85 | |
86 static void* Key(HeapObject* obj) { | |
87 return reinterpret_cast<void*>(obj->address()); | |
88 } | |
89 | |
90 static void* Value(int v) { | |
91 return reinterpret_cast<void*>(v); | |
92 } | |
93 | |
94 static void EnsureMapExists() { | |
95 if (serialization_map_ == NULL) { | |
96 serialization_map_ = new HashMap(&SerializationMatchFun); | |
97 } | |
98 } | |
99 | |
100 static HashMap* serialization_map_; | |
101 }; | |
102 | |
103 | |
104 HashMap* SerializationAddressMapper::serialization_map_ = NULL; | |
105 | |
106 | |
107 | |
108 | 47 |
109 // ----------------------------------------------------------------------------- | 48 // ----------------------------------------------------------------------------- |
110 // Coding of external references. | 49 // Coding of external references. |
111 | 50 |
112 // The encoding of an external reference. The type is in the high word. | 51 // The encoding of an external reference. The type is in the high word. |
113 // The id is in the low word. | 52 // The id is in the low word. |
114 static uint32_t EncodeExternal(TypeCode type, uint16_t id) { | 53 static uint32_t EncodeExternal(TypeCode type, uint16_t id) { |
115 return static_cast<uint32_t>(type) << 16 | id; | 54 return static_cast<uint32_t>(type) << 16 | id; |
116 } | 55 } |
117 | 56 |
(...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
640 | 579 |
641 void Deserializer::Deserialize() { | 580 void Deserializer::Deserialize() { |
642 // Don't GC while deserializing - just expand the heap. | 581 // Don't GC while deserializing - just expand the heap. |
643 AlwaysAllocateScope always_allocate; | 582 AlwaysAllocateScope always_allocate; |
644 // Don't use the free lists while deserializing. | 583 // Don't use the free lists while deserializing. |
645 LinearAllocationScope allocate_linearly; | 584 LinearAllocationScope allocate_linearly; |
646 // No active threads. | 585 // No active threads. |
647 ASSERT_EQ(NULL, ThreadState::FirstInUse()); | 586 ASSERT_EQ(NULL, ThreadState::FirstInUse()); |
648 // No active handles. | 587 // No active handles. |
649 ASSERT(HandleScopeImplementer::instance()->blocks()->is_empty()); | 588 ASSERT(HandleScopeImplementer::instance()->blocks()->is_empty()); |
| 589 // Make sure the entire partial snapshot cache is traversed, filling it with |
| 590 // valid object pointers. |
| 591 partial_snapshot_cache_length_ = kPartialSnapshotCacheCapacity; |
650 ASSERT_EQ(NULL, external_reference_decoder_); | 592 ASSERT_EQ(NULL, external_reference_decoder_); |
651 external_reference_decoder_ = new ExternalReferenceDecoder(); | 593 external_reference_decoder_ = new ExternalReferenceDecoder(); |
652 Heap::IterateRoots(this, VISIT_ONLY_STRONG); | 594 Heap::IterateStrongRoots(this, VISIT_ONLY_STRONG); |
653 ASSERT(source_->AtEOF()); | 595 Heap::IterateWeakRoots(this, VISIT_ALL); |
654 } | 596 } |
655 | 597 |
656 | 598 |
657 void Deserializer::DeserializePartial(Object** root) { | 599 void Deserializer::DeserializePartial(Object** root) { |
658 // Don't GC while deserializing - just expand the heap. | 600 // Don't GC while deserializing - just expand the heap. |
659 AlwaysAllocateScope always_allocate; | 601 AlwaysAllocateScope always_allocate; |
660 // Don't use the free lists while deserializing. | 602 // Don't use the free lists while deserializing. |
661 LinearAllocationScope allocate_linearly; | 603 LinearAllocationScope allocate_linearly; |
662 if (external_reference_decoder_ == NULL) { | 604 if (external_reference_decoder_ == NULL) { |
663 external_reference_decoder_ = new ExternalReferenceDecoder(); | 605 external_reference_decoder_ = new ExternalReferenceDecoder(); |
664 } | 606 } |
665 VisitPointer(root); | 607 VisitPointer(root); |
666 } | 608 } |
667 | 609 |
668 | 610 |
669 void Deserializer::TearDown() { | 611 Deserializer::~Deserializer() { |
| 612 ASSERT(source_->AtEOF()); |
670 if (external_reference_decoder_ != NULL) { | 613 if (external_reference_decoder_ != NULL) { |
671 delete external_reference_decoder_; | 614 delete external_reference_decoder_; |
672 external_reference_decoder_ = NULL; | 615 external_reference_decoder_ = NULL; |
673 } | 616 } |
674 } | 617 } |
675 | 618 |
676 | 619 |
677 // This is called on the roots. It is the driver of the deserialization | 620 // This is called on the roots. It is the driver of the deserialization |
678 // process. It is also called on the body of each function. | 621 // process. It is also called on the body of each function. |
679 void Deserializer::VisitPointers(Object** start, Object** end) { | 622 void Deserializer::VisitPointers(Object** start, Object** end) { |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
884 NativesExternalStringResource* resource = | 827 NativesExternalStringResource* resource = |
885 new NativesExternalStringResource(source_vector.start()); | 828 new NativesExternalStringResource(source_vector.start()); |
886 *current++ = reinterpret_cast<Object*>(resource); | 829 *current++ = reinterpret_cast<Object*>(resource); |
887 break; | 830 break; |
888 } | 831 } |
889 case ROOT_SERIALIZATION: { | 832 case ROOT_SERIALIZATION: { |
890 int root_id = source_->GetInt(); | 833 int root_id = source_->GetInt(); |
891 *current++ = Heap::roots_address()[root_id]; | 834 *current++ = Heap::roots_address()[root_id]; |
892 break; | 835 break; |
893 } | 836 } |
| 837 case PARTIAL_SNAPSHOT_CACHE_ENTRY: { |
| 838 int cache_index = source_->GetInt(); |
| 839 *current++ = partial_snapshot_cache_[cache_index]; |
| 840 break; |
| 841 } |
| 842 case SYNCHRONIZE: { |
| 843 // If we get here then that indicates that you have a mismatch between |
| 844 // the number of GC roots when serializing and deserializing. |
| 845 UNREACHABLE(); |
| 846 } |
894 default: | 847 default: |
895 UNREACHABLE(); | 848 UNREACHABLE(); |
896 } | 849 } |
897 } | 850 } |
898 ASSERT_EQ(current, limit); | 851 ASSERT_EQ(current, limit); |
899 } | 852 } |
900 | 853 |
901 | 854 |
902 void SnapshotByteSink::PutInt(uintptr_t integer, const char* description) { | 855 void SnapshotByteSink::PutInt(uintptr_t integer, const char* description) { |
903 const int max_shift = ((kPointerSize * kBitsPerByte) / 7) * 7; | 856 const int max_shift = ((kPointerSize * kBitsPerByte) / 7) * 7; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
937 sink_->PutSection(character, "TagCharacter"); | 890 sink_->PutSection(character, "TagCharacter"); |
938 } while (character != 0); | 891 } while (character != 0); |
939 } | 892 } |
940 | 893 |
941 #endif | 894 #endif |
942 | 895 |
943 Serializer::Serializer(SnapshotByteSink* sink) | 896 Serializer::Serializer(SnapshotByteSink* sink) |
944 : sink_(sink), | 897 : sink_(sink), |
945 current_root_index_(0), | 898 current_root_index_(0), |
946 external_reference_encoder_(NULL), | 899 external_reference_encoder_(NULL), |
947 partial_(false), | |
948 large_object_total_(0) { | 900 large_object_total_(0) { |
949 for (int i = 0; i <= LAST_SPACE; i++) { | 901 for (int i = 0; i <= LAST_SPACE; i++) { |
950 fullness_[i] = 0; | 902 fullness_[i] = 0; |
951 } | 903 } |
952 } | 904 } |
953 | 905 |
954 | 906 |
955 void Serializer::Serialize() { | 907 void StartupSerializer::SerializeStrongReferences() { |
956 // No active threads. | 908 // No active threads. |
957 CHECK_EQ(NULL, ThreadState::FirstInUse()); | 909 CHECK_EQ(NULL, ThreadState::FirstInUse()); |
958 // No active or weak handles. | 910 // No active or weak handles. |
959 CHECK(HandleScopeImplementer::instance()->blocks()->is_empty()); | 911 CHECK(HandleScopeImplementer::instance()->blocks()->is_empty()); |
960 CHECK_EQ(0, GlobalHandles::NumberOfWeakHandles()); | 912 CHECK_EQ(0, GlobalHandles::NumberOfWeakHandles()); |
961 CHECK_EQ(NULL, external_reference_encoder_); | 913 CHECK_EQ(NULL, external_reference_encoder_); |
962 // We don't support serializing installed extensions. | 914 // We don't support serializing installed extensions. |
963 for (RegisteredExtension* ext = RegisteredExtension::first_extension(); | 915 for (RegisteredExtension* ext = RegisteredExtension::first_extension(); |
964 ext != NULL; | 916 ext != NULL; |
965 ext = ext->next()) { | 917 ext = ext->next()) { |
966 CHECK_NE(v8::INSTALLED, ext->state()); | 918 CHECK_NE(v8::INSTALLED, ext->state()); |
967 } | 919 } |
968 external_reference_encoder_ = new ExternalReferenceEncoder(); | 920 external_reference_encoder_ = new ExternalReferenceEncoder(); |
969 Heap::IterateRoots(this, VISIT_ONLY_STRONG); | 921 Heap::IterateStrongRoots(this, VISIT_ONLY_STRONG); |
970 delete external_reference_encoder_; | 922 delete external_reference_encoder_; |
971 external_reference_encoder_ = NULL; | 923 external_reference_encoder_ = NULL; |
972 SerializationAddressMapper::Zap(); | |
973 } | 924 } |
974 | 925 |
975 | 926 |
976 void Serializer::SerializePartial(Object** object) { | 927 void PartialSerializer::Serialize(Object** object) { |
977 partial_ = true; | |
978 external_reference_encoder_ = new ExternalReferenceEncoder(); | 928 external_reference_encoder_ = new ExternalReferenceEncoder(); |
979 this->VisitPointer(object); | 929 this->VisitPointer(object); |
| 930 |
| 931 // After we have done the partial serialization the partial snapshot cache |
| 932 // will contain some references needed to decode the partial snapshot. We |
| 933 // fill it up with undefineds so it has a predictable length so the |
| 934 // deserialization code doesn't need to know the length. |
| 935 for (int index = partial_snapshot_cache_length_; |
| 936 index < kPartialSnapshotCacheCapacity; |
| 937 index++) { |
| 938 partial_snapshot_cache_[index] = Heap::undefined_value(); |
| 939 startup_serializer_->VisitPointer(&partial_snapshot_cache_[index]); |
| 940 } |
| 941 partial_snapshot_cache_length_ = kPartialSnapshotCacheCapacity; |
| 942 |
980 delete external_reference_encoder_; | 943 delete external_reference_encoder_; |
981 external_reference_encoder_ = NULL; | 944 external_reference_encoder_ = NULL; |
982 SerializationAddressMapper::Zap(); | |
983 } | 945 } |
984 | 946 |
985 | 947 |
986 void Serializer::VisitPointers(Object** start, Object** end) { | 948 void Serializer::VisitPointers(Object** start, Object** end) { |
987 for (Object** current = start; current < end; current++) { | 949 for (Object** current = start; current < end; current++) { |
988 if ((*current)->IsSmi()) { | 950 if ((*current)->IsSmi()) { |
989 sink_->Put(RAW_DATA_SERIALIZATION, "RawData"); | 951 sink_->Put(RAW_DATA_SERIALIZATION, "RawData"); |
990 sink_->PutInt(kPointerSize, "length"); | 952 sink_->PutInt(kPointerSize, "length"); |
991 for (int i = 0; i < kPointerSize; i++) { | 953 for (int i = 0; i < kPointerSize; i++) { |
992 sink_->Put(reinterpret_cast<byte*>(current)[i], "Byte"); | 954 sink_->Put(reinterpret_cast<byte*>(current)[i], "Byte"); |
993 } | 955 } |
994 } else { | 956 } else { |
995 SerializeObject(*current, TAGGED_REPRESENTATION); | 957 SerializeObject(*current, TAGGED_REPRESENTATION); |
996 } | 958 } |
997 } | 959 } |
998 } | 960 } |
999 | 961 |
1000 | 962 |
1001 int Serializer::RootIndex(HeapObject* heap_object) { | 963 Object* SerializerDeserializer::partial_snapshot_cache_[ |
| 964 kPartialSnapshotCacheCapacity]; |
| 965 int SerializerDeserializer::partial_snapshot_cache_length_ = 0; |
| 966 |
| 967 |
| 968 // This ensures that the partial snapshot cache keeps things alive during GC and |
| 969 // tracks their movement. When it is called during serialization of the startup |
| 970 // snapshot the partial snapshot is empty, so nothing happens. When the partial |
| 971 // (context) snapshot is created, this array is populated with the pointers that |
| 972 // the partial snapshot will need. As that happens we emit serialized objects to |
| 973 // the startup snapshot that correspond to the elements of this cache array. On |
| 974 // deserialization we therefore need to visit the cache array. This fills it up |
| 975 // with pointers to deserialized objects. |
| 976 void SerializerDeserializer::Iterate(ObjectVisitor *visitor) { |
| 977 visitor->VisitPointers( |
| 978 &partial_snapshot_cache_[0], |
| 979 &partial_snapshot_cache_[partial_snapshot_cache_length_]); |
| 980 } |
| 981 |
| 982 |
| 983 // When deserializing we need to set the size of the snapshot cache. This means |
| 984 // the root iteration code (above) will iterate over array elements, writing the |
| 985 // references to deserialized objects in them. |
| 986 void SerializerDeserializer::SetSnapshotCacheSize(int size) { |
| 987 partial_snapshot_cache_length_ = size; |
| 988 } |
| 989 |
| 990 |
| 991 int PartialSerializer::PartialSnapshotCacheIndex(HeapObject* heap_object) { |
| 992 for (int i = 0; i < partial_snapshot_cache_length_; i++) { |
| 993 Object* entry = partial_snapshot_cache_[i]; |
| 994 if (entry == heap_object) return i; |
| 995 } |
| 996 // We didn't find the object in the cache. So we add it to the cache and |
| 997 // then visit the pointer so that it becomes part of the startup snapshot |
| 998 // and we can refer to it from the partial snapshot. |
| 999 int length = partial_snapshot_cache_length_; |
| 1000 CHECK(length < kPartialSnapshotCacheCapacity); |
| 1001 partial_snapshot_cache_[length] = heap_object; |
| 1002 startup_serializer_->VisitPointer(&partial_snapshot_cache_[length]); |
| 1003 // We don't recurse from the startup snapshot generator into the partial |
| 1004 // snapshot generator. |
| 1005 ASSERT(length == partial_snapshot_cache_length_); |
| 1006 return partial_snapshot_cache_length_++; |
| 1007 } |
| 1008 |
| 1009 |
| 1010 int PartialSerializer::RootIndex(HeapObject* heap_object) { |
1002 for (int i = 0; i < Heap::kRootListLength; i++) { | 1011 for (int i = 0; i < Heap::kRootListLength; i++) { |
1003 Object* root = Heap::roots_address()[i]; | 1012 Object* root = Heap::roots_address()[i]; |
1004 if (root == heap_object) return i; | 1013 if (root == heap_object) return i; |
1005 } | 1014 } |
1006 return kInvalidRootIndex; | 1015 return kInvalidRootIndex; |
1007 } | 1016 } |
1008 | 1017 |
1009 | 1018 |
1010 void Serializer::SerializeObject( | 1019 // Encode the location of an already deserialized object in order to write its |
| 1020 // location into a later object. We can encode the location as an offset from |
| 1021 // the start of the deserialized objects or as an offset backwards from the |
| 1022 // current allocation pointer. |
| 1023 void Serializer::SerializeReferenceToPreviousObject( |
| 1024 int space, |
| 1025 int address, |
| 1026 ReferenceRepresentation reference_representation) { |
| 1027 int offset = CurrentAllocationAddress(space) - address; |
| 1028 bool from_start = true; |
| 1029 if (SpaceIsPaged(space)) { |
| 1030 // For paged space it is simple to encode back from current allocation if |
| 1031 // the object is on the same page as the current allocation pointer. |
| 1032 if ((CurrentAllocationAddress(space) >> kPageSizeBits) == |
| 1033 (address >> kPageSizeBits)) { |
| 1034 from_start = false; |
| 1035 address = offset; |
| 1036 } |
| 1037 } else if (space == NEW_SPACE) { |
| 1038 // For new space it is always simple to encode back from current allocation. |
| 1039 if (offset < address) { |
| 1040 from_start = false; |
| 1041 address = offset; |
| 1042 } |
| 1043 } |
| 1044 // If we are actually dealing with real offsets (and not a numbering of |
| 1045 // all objects) then we should shift out the bits that are always 0. |
| 1046 if (!SpaceIsLarge(space)) address >>= kObjectAlignmentBits; |
| 1047 // On some architectures references between code objects are encoded |
| 1048 // specially (as relative offsets). Such references have their own |
| 1049 // special tags to simplify the deserializer. |
| 1050 if (reference_representation == CODE_TARGET_REPRESENTATION) { |
| 1051 if (from_start) { |
| 1052 sink_->Put(CODE_REFERENCE_SERIALIZATION + space, "RefCodeSer"); |
| 1053 sink_->PutInt(address, "address"); |
| 1054 } else { |
| 1055 sink_->Put(CODE_BACKREF_SERIALIZATION + space, "BackRefCodeSer"); |
| 1056 sink_->PutInt(address, "address"); |
| 1057 } |
| 1058 } else { |
| 1059 // Regular absolute references. |
| 1060 CHECK_EQ(TAGGED_REPRESENTATION, reference_representation); |
| 1061 if (from_start) { |
| 1062 // There are some common offsets that have their own specialized encoding. |
| 1063 #define COMMON_REFS_CASE(tag, common_space, common_offset) \ |
| 1064 if (space == common_space && address == common_offset) { \ |
| 1065 sink_->PutSection(tag + REFERENCE_SERIALIZATION, "RefSer"); \ |
| 1066 } else /* NOLINT */ |
| 1067 COMMON_REFERENCE_PATTERNS(COMMON_REFS_CASE) |
| 1068 #undef COMMON_REFS_CASE |
| 1069 { /* NOLINT */ |
| 1070 sink_->Put(REFERENCE_SERIALIZATION + space, "RefSer"); |
| 1071 sink_->PutInt(address, "address"); |
| 1072 } |
| 1073 } else { |
| 1074 sink_->Put(BACKREF_SERIALIZATION + space, "BackRefSer"); |
| 1075 sink_->PutInt(address, "address"); |
| 1076 } |
| 1077 } |
| 1078 } |
| 1079 |
| 1080 |
| 1081 void StartupSerializer::SerializeObject( |
1011 Object* o, | 1082 Object* o, |
1012 ReferenceRepresentation reference_representation) { | 1083 ReferenceRepresentation reference_representation) { |
1013 CHECK(o->IsHeapObject()); | 1084 CHECK(o->IsHeapObject()); |
1014 HeapObject* heap_object = HeapObject::cast(o); | 1085 HeapObject* heap_object = HeapObject::cast(o); |
1015 if (partial_) { | 1086 |
1016 int root_index = RootIndex(heap_object); | 1087 if (address_mapper_.IsMapped(heap_object)) { |
1017 if (root_index != kInvalidRootIndex) { | 1088 int space = SpaceOfAlreadySerializedObject(heap_object); |
1018 sink_->Put(ROOT_SERIALIZATION, "RootSerialization"); | 1089 int address = address_mapper_.MappedTo(heap_object); |
1019 sink_->PutInt(root_index, "root_index"); | 1090 SerializeReferenceToPreviousObject(space, |
1020 return; | 1091 address, |
1021 } | 1092 reference_representation); |
1022 // All the symbols that the snapshot needs should be in the root table. | 1093 } else { |
1023 ASSERT(!heap_object->IsSymbol()); | 1094 // Object has not yet been serialized. Serialize it here. |
| 1095 ObjectSerializer object_serializer(this, |
| 1096 heap_object, |
| 1097 sink_, |
| 1098 reference_representation); |
| 1099 object_serializer.Serialize(); |
1024 } | 1100 } |
1025 if (SerializationAddressMapper::IsMapped(heap_object)) { | 1101 } |
| 1102 |
| 1103 |
| 1104 void StartupSerializer::SerializeWeakReferences() { |
| 1105 for (int i = partial_snapshot_cache_length_; |
| 1106 i < kPartialSnapshotCacheCapacity; |
| 1107 i++) { |
| 1108 sink_->Put(ROOT_SERIALIZATION, "RootSerialization"); |
| 1109 sink_->PutInt(Heap::kUndefinedValueRootIndex, "root_index"); |
| 1110 } |
| 1111 Heap::IterateWeakRoots(this, VISIT_ALL); |
| 1112 } |
| 1113 |
| 1114 |
| 1115 void PartialSerializer::SerializeObject( |
| 1116 Object* o, |
| 1117 ReferenceRepresentation reference_representation) { |
| 1118 CHECK(o->IsHeapObject()); |
| 1119 HeapObject* heap_object = HeapObject::cast(o); |
| 1120 |
| 1121 int root_index; |
| 1122 if ((root_index = RootIndex(heap_object)) != kInvalidRootIndex) { |
| 1123 sink_->Put(ROOT_SERIALIZATION, "RootSerialization"); |
| 1124 sink_->PutInt(root_index, "root_index"); |
| 1125 return; |
| 1126 } |
| 1127 |
| 1128 if (ShouldBeInThePartialSnapshotCache(heap_object)) { |
| 1129 int cache_index = PartialSnapshotCacheIndex(heap_object); |
| 1130 sink_->Put(PARTIAL_SNAPSHOT_CACHE_ENTRY, "PartialSnapshotCache"); |
| 1131 sink_->PutInt(cache_index, "partial_snapshot_cache_index"); |
| 1132 return; |
| 1133 } |
| 1134 |
| 1135 // Pointers from the partial snapshot to the objects in the startup snapshot |
| 1136 // should go through the root array or through the partial snapshot cache. |
| 1137 // If this is not the case you may have to add something to the root array. |
| 1138 ASSERT(!startup_serializer_->address_mapper()->IsMapped(heap_object)); |
| 1139 // All the symbols that the partial snapshot needs should be either in the |
| 1140 // root table or in the partial snapshot cache. |
| 1141 ASSERT(!heap_object->IsSymbol()); |
| 1142 |
| 1143 if (address_mapper_.IsMapped(heap_object)) { |
1026 int space = SpaceOfAlreadySerializedObject(heap_object); | 1144 int space = SpaceOfAlreadySerializedObject(heap_object); |
1027 int address = SerializationAddressMapper::MappedTo(heap_object); | 1145 int address = address_mapper_.MappedTo(heap_object); |
1028 int offset = CurrentAllocationAddress(space) - address; | 1146 SerializeReferenceToPreviousObject(space, |
1029 bool from_start = true; | 1147 address, |
1030 if (SpaceIsPaged(space)) { | 1148 reference_representation); |
1031 if ((CurrentAllocationAddress(space) >> kPageSizeBits) == | |
1032 (address >> kPageSizeBits)) { | |
1033 from_start = false; | |
1034 address = offset; | |
1035 } | |
1036 } else if (space == NEW_SPACE) { | |
1037 if (offset < address) { | |
1038 from_start = false; | |
1039 address = offset; | |
1040 } | |
1041 } | |
1042 // If we are actually dealing with real offsets (and not a numbering of | |
1043 // all objects) then we should shift out the bits that are always 0. | |
1044 if (!SpaceIsLarge(space)) address >>= kObjectAlignmentBits; | |
1045 if (reference_representation == CODE_TARGET_REPRESENTATION) { | |
1046 if (from_start) { | |
1047 sink_->Put(CODE_REFERENCE_SERIALIZATION + space, "RefCodeSer"); | |
1048 sink_->PutInt(address, "address"); | |
1049 } else { | |
1050 sink_->Put(CODE_BACKREF_SERIALIZATION + space, "BackRefCodeSer"); | |
1051 sink_->PutInt(address, "address"); | |
1052 } | |
1053 } else { | |
1054 CHECK_EQ(TAGGED_REPRESENTATION, reference_representation); | |
1055 if (from_start) { | |
1056 #define COMMON_REFS_CASE(tag, common_space, common_offset) \ | |
1057 if (space == common_space && address == common_offset) { \ | |
1058 sink_->PutSection(tag + REFERENCE_SERIALIZATION, "RefSer"); \ | |
1059 } else /* NOLINT */ | |
1060 COMMON_REFERENCE_PATTERNS(COMMON_REFS_CASE) | |
1061 #undef COMMON_REFS_CASE | |
1062 { /* NOLINT */ | |
1063 sink_->Put(REFERENCE_SERIALIZATION + space, "RefSer"); | |
1064 sink_->PutInt(address, "address"); | |
1065 } | |
1066 } else { | |
1067 sink_->Put(BACKREF_SERIALIZATION + space, "BackRefSer"); | |
1068 sink_->PutInt(address, "address"); | |
1069 } | |
1070 } | |
1071 } else { | 1149 } else { |
1072 // Object has not yet been serialized. Serialize it here. | 1150 // Object has not yet been serialized. Serialize it here. |
1073 ObjectSerializer serializer(this, | 1151 ObjectSerializer serializer(this, |
1074 heap_object, | 1152 heap_object, |
1075 sink_, | 1153 sink_, |
1076 reference_representation); | 1154 reference_representation); |
1077 serializer.Serialize(); | 1155 serializer.Serialize(); |
1078 } | 1156 } |
1079 } | 1157 } |
1080 | 1158 |
1081 | 1159 |
1082 | |
1083 void Serializer::ObjectSerializer::Serialize() { | 1160 void Serializer::ObjectSerializer::Serialize() { |
1084 int space = Serializer::SpaceOfObject(object_); | 1161 int space = Serializer::SpaceOfObject(object_); |
1085 int size = object_->Size(); | 1162 int size = object_->Size(); |
1086 | 1163 |
1087 if (reference_representation_ == TAGGED_REPRESENTATION) { | 1164 if (reference_representation_ == TAGGED_REPRESENTATION) { |
1088 sink_->Put(OBJECT_SERIALIZATION + space, "ObjectSerialization"); | 1165 sink_->Put(OBJECT_SERIALIZATION + space, "ObjectSerialization"); |
1089 } else { | 1166 } else { |
1090 CHECK_EQ(CODE_TARGET_REPRESENTATION, reference_representation_); | 1167 CHECK_EQ(CODE_TARGET_REPRESENTATION, reference_representation_); |
1091 sink_->Put(CODE_OBJECT_SERIALIZATION + space, "ObjectSerialization"); | 1168 sink_->Put(CODE_OBJECT_SERIALIZATION + space, "ObjectSerialization"); |
1092 } | 1169 } |
1093 sink_->PutInt(size >> kObjectAlignmentBits, "Size in words"); | 1170 sink_->PutInt(size >> kObjectAlignmentBits, "Size in words"); |
1094 | 1171 |
1095 LOG(SnapshotPositionEvent(object_->address(), sink_->Position())); | 1172 LOG(SnapshotPositionEvent(object_->address(), sink_->Position())); |
1096 | 1173 |
1097 // Mark this object as already serialized. | 1174 // Mark this object as already serialized. |
1098 bool start_new_page; | 1175 bool start_new_page; |
1099 SerializationAddressMapper::Map( | 1176 int offset = serializer_->Allocate(space, size, &start_new_page); |
1100 object_, | 1177 serializer_->address_mapper()->AddMapping(object_, offset); |
1101 serializer_->Allocate(space, size, &start_new_page)); | |
1102 if (start_new_page) { | 1178 if (start_new_page) { |
1103 sink_->Put(START_NEW_PAGE_SERIALIZATION, "NewPage"); | 1179 sink_->Put(START_NEW_PAGE_SERIALIZATION, "NewPage"); |
1104 sink_->PutSection(space, "NewPageSpace"); | 1180 sink_->PutSection(space, "NewPageSpace"); |
1105 } | 1181 } |
1106 | 1182 |
1107 // Serialize the map (first word of the object). | 1183 // Serialize the map (first word of the object). |
1108 serializer_->SerializeObject(object_->map(), TAGGED_REPRESENTATION); | 1184 serializer_->SerializeObject(object_->map(), TAGGED_REPRESENTATION); |
1109 | 1185 |
1110 // Serialize the rest of the object. | 1186 // Serialize the rest of the object. |
1111 CHECK_EQ(0, bytes_processed_so_far_); | 1187 CHECK_EQ(0, bytes_processed_so_far_); |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1280 fullness_[space] = RoundUp(fullness_[space], Page::kPageSize); | 1356 fullness_[space] = RoundUp(fullness_[space], Page::kPageSize); |
1281 } | 1357 } |
1282 } | 1358 } |
1283 int allocation_address = fullness_[space]; | 1359 int allocation_address = fullness_[space]; |
1284 fullness_[space] = allocation_address + size; | 1360 fullness_[space] = allocation_address + size; |
1285 return allocation_address; | 1361 return allocation_address; |
1286 } | 1362 } |
1287 | 1363 |
1288 | 1364 |
1289 } } // namespace v8::internal | 1365 } } // namespace v8::internal |
OLD | NEW |