OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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_ADDRESS_MAP_H_ | 5 #ifndef V8_ADDRESS_MAP_H_ |
6 #define V8_ADDRESS_MAP_H_ | 6 #define V8_ADDRESS_MAP_H_ |
7 | 7 |
8 #include "src/assert-scope.h" | 8 #include "src/assert-scope.h" |
9 #include "src/hashmap.h" | 9 #include "src/hashmap.h" |
10 #include "src/objects.h" | 10 #include "src/objects.h" |
(...skipping 22 matching lines...) Expand all Loading... |
33 private: | 33 private: |
34 static uint32_t Hash(HeapObject* obj) { | 34 static uint32_t Hash(HeapObject* obj) { |
35 return static_cast<int32_t>(reinterpret_cast<intptr_t>(obj->address())); | 35 return static_cast<int32_t>(reinterpret_cast<intptr_t>(obj->address())); |
36 } | 36 } |
37 | 37 |
38 static void* Key(HeapObject* obj) { | 38 static void* Key(HeapObject* obj) { |
39 return reinterpret_cast<void*>(obj->address()); | 39 return reinterpret_cast<void*>(obj->address()); |
40 } | 40 } |
41 }; | 41 }; |
42 | 42 |
43 | |
44 class RootIndexMap : public AddressMapBase { | 43 class RootIndexMap : public AddressMapBase { |
45 public: | 44 public: |
46 explicit RootIndexMap(Isolate* isolate); | 45 explicit RootIndexMap(Isolate* isolate); |
47 | 46 |
48 static const int kInvalidRootIndex = -1; | 47 static const int kInvalidRootIndex = -1; |
49 | 48 |
50 int Lookup(HeapObject* obj) { | 49 int Lookup(HeapObject* obj) { |
51 HashMap::Entry* entry = LookupEntry(map_, obj, false); | 50 HashMap::Entry* entry = LookupEntry(map_, obj, false); |
52 if (entry) return GetValue(entry); | 51 if (entry) return GetValue(entry); |
53 return kInvalidRootIndex; | 52 return kInvalidRootIndex; |
54 } | 53 } |
55 | 54 |
56 private: | 55 private: |
57 HashMap* map_; | 56 HashMap* map_; |
58 | 57 |
59 DISALLOW_COPY_AND_ASSIGN(RootIndexMap); | 58 DISALLOW_COPY_AND_ASSIGN(RootIndexMap); |
60 }; | 59 }; |
61 | 60 |
| 61 class SerializerReference { |
| 62 public: |
| 63 SerializerReference() : bitfield_(Special(kInvalidValue)) {} |
62 | 64 |
63 class BackReference { | 65 static SerializerReference FromBitfield(uint32_t bitfield) { |
64 public: | 66 return SerializerReference(bitfield); |
65 explicit BackReference(uint32_t bitfield) : bitfield_(bitfield) {} | |
66 | |
67 BackReference() : bitfield_(kInvalidValue) {} | |
68 | |
69 static BackReference SourceReference() { return BackReference(kSourceValue); } | |
70 | |
71 static BackReference GlobalProxyReference() { | |
72 return BackReference(kGlobalProxyValue); | |
73 } | 67 } |
74 | 68 |
75 static BackReference LargeObjectReference(uint32_t index) { | 69 static SerializerReference BackReference(AllocationSpace space, |
76 return BackReference(SpaceBits::encode(LO_SPACE) | | 70 uint32_t chunk_index, |
77 ChunkOffsetBits::encode(index)); | 71 uint32_t chunk_offset) { |
78 } | |
79 | |
80 static BackReference DummyReference() { return BackReference(kDummyValue); } | |
81 | |
82 static BackReference Reference(AllocationSpace space, uint32_t chunk_index, | |
83 uint32_t chunk_offset) { | |
84 DCHECK(IsAligned(chunk_offset, kObjectAlignment)); | 72 DCHECK(IsAligned(chunk_offset, kObjectAlignment)); |
85 DCHECK_NE(LO_SPACE, space); | 73 DCHECK_NE(LO_SPACE, space); |
86 return BackReference( | 74 return SerializerReference( |
87 SpaceBits::encode(space) | ChunkIndexBits::encode(chunk_index) | | 75 SpaceBits::encode(space) | ChunkIndexBits::encode(chunk_index) | |
88 ChunkOffsetBits::encode(chunk_offset >> kObjectAlignmentBits)); | 76 ChunkOffsetBits::encode(chunk_offset >> kObjectAlignmentBits)); |
89 } | 77 } |
90 | 78 |
91 bool is_valid() const { return bitfield_ != kInvalidValue; } | 79 static SerializerReference LargeObjectReference(uint32_t index) { |
92 bool is_source() const { return bitfield_ == kSourceValue; } | 80 return SerializerReference(SpaceBits::encode(LO_SPACE) | |
93 bool is_global_proxy() const { return bitfield_ == kGlobalProxyValue; } | 81 ValueIndexBits::encode(index)); |
| 82 } |
| 83 |
| 84 static SerializerReference AttachedReference(uint32_t index) { |
| 85 return SerializerReference(SpaceBits::encode(kAttachedReferenceSpace) | |
| 86 ValueIndexBits::encode(index)); |
| 87 } |
| 88 |
| 89 static SerializerReference DummyReference() { |
| 90 return SerializerReference(Special(kDummyValue)); |
| 91 } |
| 92 |
| 93 bool is_valid() const { return bitfield_ != Special(kInvalidValue); } |
| 94 |
| 95 bool is_back_reference() const { |
| 96 return SpaceBits::decode(bitfield_) <= LAST_SPACE; |
| 97 } |
94 | 98 |
95 AllocationSpace space() const { | 99 AllocationSpace space() const { |
96 DCHECK(is_valid()); | 100 DCHECK(is_back_reference()); |
97 return SpaceBits::decode(bitfield_); | 101 return static_cast<AllocationSpace>(SpaceBits::decode(bitfield_)); |
98 } | 102 } |
99 | 103 |
100 uint32_t chunk_offset() const { | 104 uint32_t chunk_offset() const { |
101 DCHECK(is_valid()); | 105 DCHECK(is_back_reference()); |
102 return ChunkOffsetBits::decode(bitfield_) << kObjectAlignmentBits; | 106 return ChunkOffsetBits::decode(bitfield_) << kObjectAlignmentBits; |
103 } | 107 } |
104 | 108 |
105 uint32_t large_object_index() const { | 109 uint32_t large_object_index() const { |
106 DCHECK(is_valid()); | 110 DCHECK(is_back_reference()); |
107 DCHECK(chunk_index() == 0); | 111 DCHECK(chunk_index() == 0); |
108 return ChunkOffsetBits::decode(bitfield_); | 112 return ChunkOffsetBits::decode(bitfield_); |
109 } | 113 } |
110 | 114 |
111 uint32_t chunk_index() const { | 115 uint32_t chunk_index() const { |
112 DCHECK(is_valid()); | 116 DCHECK(is_back_reference()); |
113 return ChunkIndexBits::decode(bitfield_); | 117 return ChunkIndexBits::decode(bitfield_); |
114 } | 118 } |
115 | 119 |
116 uint32_t reference() const { | 120 uint32_t back_reference() const { |
117 DCHECK(is_valid()); | 121 DCHECK(is_back_reference()); |
118 return bitfield_ & (ChunkOffsetBits::kMask | ChunkIndexBits::kMask); | 122 return bitfield_ & (ChunkOffsetBits::kMask | ChunkIndexBits::kMask); |
119 } | 123 } |
120 | 124 |
121 uint32_t bitfield() const { return bitfield_; } | 125 bool is_attached_reference() const { |
| 126 return SpaceBits::decode(bitfield_) == kAttachedReferenceSpace; |
| 127 } |
| 128 |
| 129 int attached_reference_index() const { |
| 130 DCHECK(is_attached_reference()); |
| 131 return ValueIndexBits::decode(bitfield_); |
| 132 } |
122 | 133 |
123 private: | 134 private: |
124 static const uint32_t kInvalidValue = 0xFFFFFFFF; | 135 explicit SerializerReference(uint32_t bitfield) : bitfield_(bitfield) {} |
125 static const uint32_t kSourceValue = 0xFFFFFFFE; | 136 |
126 static const uint32_t kGlobalProxyValue = 0xFFFFFFFD; | 137 inline static uint32_t Special(int value) { |
127 static const uint32_t kDummyValue = 0xFFFFFFFC; | 138 return SpaceBits::encode(kSpecialValueSpace) | |
| 139 ValueIndexBits::encode(value); |
| 140 } |
| 141 |
| 142 // We use the 32-bit bitfield to encode either a back reference, a special |
| 143 // value, or an attached reference index. |
| 144 // Back reference: |
| 145 // [ Space index ] [ Chunk index ] [ Chunk offset ] |
| 146 // [ LO_SPACE ] [ large object index ] |
| 147 // Special value |
| 148 // [ kSpecialValueSpace ] [ Special value index ] |
| 149 // Attached reference |
| 150 // [ kAttachedReferenceSpace ] [ Attached reference index ] |
| 151 |
128 static const int kChunkOffsetSize = kPageSizeBits - kObjectAlignmentBits; | 152 static const int kChunkOffsetSize = kPageSizeBits - kObjectAlignmentBits; |
129 static const int kChunkIndexSize = 32 - kChunkOffsetSize - kSpaceTagSize; | 153 static const int kChunkIndexSize = 32 - kChunkOffsetSize - kSpaceTagSize; |
| 154 static const int kValueIndexSize = kChunkOffsetSize + kChunkIndexSize; |
130 | 155 |
131 public: | 156 static const int kSpecialValueSpace = LAST_SPACE + 1; |
132 static const int kMaxChunkIndex = (1 << kChunkIndexSize) - 1; | 157 static const int kAttachedReferenceSpace = kSpecialValueSpace + 1; |
| 158 STATIC_ASSERT(kAttachedReferenceSpace < (1 << kSpaceTagSize)); |
133 | 159 |
134 private: | 160 static const int kInvalidValue = 0; |
| 161 static const int kDummyValue = 1; |
| 162 |
| 163 // The chunk offset can also be used to encode the index of special values. |
135 class ChunkOffsetBits : public BitField<uint32_t, 0, kChunkOffsetSize> {}; | 164 class ChunkOffsetBits : public BitField<uint32_t, 0, kChunkOffsetSize> {}; |
136 class ChunkIndexBits | 165 class ChunkIndexBits |
137 : public BitField<uint32_t, ChunkOffsetBits::kNext, kChunkIndexSize> {}; | 166 : public BitField<uint32_t, ChunkOffsetBits::kNext, kChunkIndexSize> {}; |
138 class SpaceBits | 167 class ValueIndexBits : public BitField<uint32_t, 0, kValueIndexSize> {}; |
139 : public BitField<AllocationSpace, ChunkIndexBits::kNext, kSpaceTagSize> { | 168 STATIC_ASSERT(ChunkIndexBits::kNext == ValueIndexBits::kNext); |
140 }; | 169 class SpaceBits : public BitField<int, kValueIndexSize, kSpaceTagSize> {}; |
| 170 STATIC_ASSERT(SpaceBits::kNext == 32); |
141 | 171 |
142 uint32_t bitfield_; | 172 uint32_t bitfield_; |
| 173 |
| 174 friend class SerializerReferenceMap; |
143 }; | 175 }; |
144 | 176 |
145 | |
146 // Mapping objects to their location after deserialization. | 177 // Mapping objects to their location after deserialization. |
147 // This is used during building, but not at runtime by V8. | 178 // This is used during building, but not at runtime by V8. |
148 class BackReferenceMap : public AddressMapBase { | 179 class SerializerReferenceMap : public AddressMapBase { |
149 public: | 180 public: |
150 BackReferenceMap() | 181 SerializerReferenceMap() |
151 : no_allocation_(), map_(new HashMap(HashMap::PointersMatch)) {} | 182 : no_allocation_(), |
| 183 map_(HashMap::PointersMatch), |
| 184 attached_reference_index_(0) {} |
152 | 185 |
153 ~BackReferenceMap() { delete map_; } | 186 SerializerReference Lookup(HeapObject* obj) { |
154 | 187 HashMap::Entry* entry = LookupEntry(&map_, obj, false); |
155 BackReference Lookup(HeapObject* obj) { | 188 return entry ? SerializerReference(GetValue(entry)) : SerializerReference(); |
156 HashMap::Entry* entry = LookupEntry(map_, obj, false); | |
157 return entry ? BackReference(GetValue(entry)) : BackReference(); | |
158 } | 189 } |
159 | 190 |
160 void Add(HeapObject* obj, BackReference b) { | 191 void Add(HeapObject* obj, SerializerReference b) { |
161 DCHECK(b.is_valid()); | 192 DCHECK(b.is_valid()); |
162 DCHECK_NULL(LookupEntry(map_, obj, false)); | 193 DCHECK_NULL(LookupEntry(&map_, obj, false)); |
163 HashMap::Entry* entry = LookupEntry(map_, obj, true); | 194 HashMap::Entry* entry = LookupEntry(&map_, obj, true); |
164 SetValue(entry, b.bitfield()); | 195 SetValue(entry, b.bitfield_); |
165 } | 196 } |
166 | 197 |
167 void AddSourceString(String* string) { | 198 SerializerReference AddAttachedReference(HeapObject* attached_reference) { |
168 Add(string, BackReference::SourceReference()); | 199 SerializerReference reference = |
169 } | 200 SerializerReference::AttachedReference(attached_reference_index_++); |
170 | 201 Add(attached_reference, reference); |
171 void AddGlobalProxy(HeapObject* global_proxy) { | 202 return reference; |
172 Add(global_proxy, BackReference::GlobalProxyReference()); | |
173 } | 203 } |
174 | 204 |
175 private: | 205 private: |
176 DisallowHeapAllocation no_allocation_; | 206 DisallowHeapAllocation no_allocation_; |
177 HashMap* map_; | 207 HashMap map_; |
178 DISALLOW_COPY_AND_ASSIGN(BackReferenceMap); | 208 int attached_reference_index_; |
| 209 DISALLOW_COPY_AND_ASSIGN(SerializerReferenceMap); |
179 }; | 210 }; |
180 | 211 |
181 } // namespace internal | 212 } // namespace internal |
182 } // namespace v8 | 213 } // namespace v8 |
183 | 214 |
184 #endif // V8_ADDRESS_MAP_H_ | 215 #endif // V8_ADDRESS_MAP_H_ |
OLD | NEW |