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 3 // found in the LICENSE file. 4 5 #ifndef V8_ADDRESS_MAP_H_ 6 #define V8_ADDRESS_MAP_H_ 7 8 #include "include/v8.h" 9 #include "src/assert-scope.h" 10 #include "src/base/hashmap.h" 11 #include "src/objects.h" 12 13 namespace v8 { 14 namespace internal { 15 16 template <typename Type> 17 class PointerToIndexHashMap 18 : public base::TemplateHashMapImpl<uintptr_t, uint32_t, 19 base::KeyEqualityMatcher<intptr_t>, 20 base::DefaultAllocationPolicy> { 21 public: 22 typedef base::TemplateHashMapEntry<uintptr_t, uint32_t> Entry; 23 Set(Type value,uint32_t index)24 inline void Set(Type value, uint32_t index) { 25 uintptr_t key = Key(value); 26 LookupOrInsert(key, Hash(key))->value = index; 27 } 28 Get(Type value)29 inline Maybe<uint32_t> Get(Type value) const { 30 uintptr_t key = Key(value); 31 Entry* entry = Lookup(key, Hash(key)); 32 if (entry == nullptr) return Nothing<uint32_t>(); 33 return Just(entry->value); 34 } 35 36 private: Key(Type value)37 static uintptr_t Key(Type value) { 38 return reinterpret_cast<uintptr_t>(value); 39 } 40 Hash(uintptr_t key)41 static uint32_t Hash(uintptr_t key) { return static_cast<uint32_t>(key); } 42 }; 43 44 class AddressToIndexHashMap : public PointerToIndexHashMap<Address> {}; 45 class HeapObjectToIndexHashMap : public PointerToIndexHashMap<HeapObject*> {}; 46 47 class RootIndexMap { 48 public: 49 explicit RootIndexMap(Isolate* isolate); 50 51 static const int kInvalidRootIndex = -1; 52 Lookup(HeapObject * obj)53 int Lookup(HeapObject* obj) { 54 Maybe<uint32_t> maybe_index = map_->Get(obj); 55 return maybe_index.IsJust() ? maybe_index.FromJust() : kInvalidRootIndex; 56 } 57 58 private: 59 HeapObjectToIndexHashMap* map_; 60 61 DISALLOW_COPY_AND_ASSIGN(RootIndexMap); 62 }; 63 64 class SerializerReference { 65 public: SerializerReference()66 SerializerReference() : bitfield_(Special(kInvalidValue)) {} 67 FromBitfield(uint32_t bitfield)68 static SerializerReference FromBitfield(uint32_t bitfield) { 69 return SerializerReference(bitfield); 70 } 71 BackReference(AllocationSpace space,uint32_t chunk_index,uint32_t chunk_offset)72 static SerializerReference BackReference(AllocationSpace space, 73 uint32_t chunk_index, 74 uint32_t chunk_offset) { 75 DCHECK(IsAligned(chunk_offset, kObjectAlignment)); 76 DCHECK_NE(LO_SPACE, space); 77 return SerializerReference( 78 SpaceBits::encode(space) | ChunkIndexBits::encode(chunk_index) | 79 ChunkOffsetBits::encode(chunk_offset >> kObjectAlignmentBits)); 80 } 81 MapReference(uint32_t index)82 static SerializerReference MapReference(uint32_t index) { 83 return SerializerReference(SpaceBits::encode(MAP_SPACE) | 84 ValueIndexBits::encode(index)); 85 } 86 LargeObjectReference(uint32_t index)87 static SerializerReference LargeObjectReference(uint32_t index) { 88 return SerializerReference(SpaceBits::encode(LO_SPACE) | 89 ValueIndexBits::encode(index)); 90 } 91 AttachedReference(uint32_t index)92 static SerializerReference AttachedReference(uint32_t index) { 93 return SerializerReference(SpaceBits::encode(kAttachedReferenceSpace) | 94 ValueIndexBits::encode(index)); 95 } 96 DummyReference()97 static SerializerReference DummyReference() { 98 return SerializerReference(Special(kDummyValue)); 99 } 100 is_valid()101 bool is_valid() const { return bitfield_ != Special(kInvalidValue); } 102 is_back_reference()103 bool is_back_reference() const { 104 return SpaceBits::decode(bitfield_) <= LAST_SPACE; 105 } 106 space()107 AllocationSpace space() const { 108 DCHECK(is_back_reference()); 109 return static_cast<AllocationSpace>(SpaceBits::decode(bitfield_)); 110 } 111 chunk_offset()112 uint32_t chunk_offset() const { 113 DCHECK(is_back_reference()); 114 return ChunkOffsetBits::decode(bitfield_) << kObjectAlignmentBits; 115 } 116 map_index()117 uint32_t map_index() const { 118 DCHECK(is_back_reference()); 119 return ValueIndexBits::decode(bitfield_); 120 } 121 large_object_index()122 uint32_t large_object_index() const { 123 DCHECK(is_back_reference()); 124 return ValueIndexBits::decode(bitfield_); 125 } 126 chunk_index()127 uint32_t chunk_index() const { 128 DCHECK(is_back_reference()); 129 return ChunkIndexBits::decode(bitfield_); 130 } 131 back_reference()132 uint32_t back_reference() const { 133 DCHECK(is_back_reference()); 134 return bitfield_ & (ChunkOffsetBits::kMask | ChunkIndexBits::kMask); 135 } 136 is_attached_reference()137 bool is_attached_reference() const { 138 return SpaceBits::decode(bitfield_) == kAttachedReferenceSpace; 139 } 140 attached_reference_index()141 int attached_reference_index() const { 142 DCHECK(is_attached_reference()); 143 return ValueIndexBits::decode(bitfield_); 144 } 145 146 private: SerializerReference(uint32_t bitfield)147 explicit SerializerReference(uint32_t bitfield) : bitfield_(bitfield) {} 148 Special(int value)149 inline static uint32_t Special(int value) { 150 return SpaceBits::encode(kSpecialValueSpace) | 151 ValueIndexBits::encode(value); 152 } 153 154 // We use the 32-bit bitfield to encode either a back reference, a special 155 // value, or an attached reference index. 156 // Back reference: 157 // [ Space index ] [ Chunk index ] [ Chunk offset ] 158 // [ LO_SPACE ] [ large object index ] 159 // Special value 160 // [ kSpecialValueSpace ] [ Special value index ] 161 // Attached reference 162 // [ kAttachedReferenceSpace ] [ Attached reference index ] 163 164 static const int kChunkOffsetSize = kPageSizeBits - kObjectAlignmentBits; 165 static const int kChunkIndexSize = 32 - kChunkOffsetSize - kSpaceTagSize; 166 static const int kValueIndexSize = kChunkOffsetSize + kChunkIndexSize; 167 168 static const int kSpecialValueSpace = LAST_SPACE + 1; 169 static const int kAttachedReferenceSpace = kSpecialValueSpace + 1; 170 STATIC_ASSERT(kAttachedReferenceSpace < (1 << kSpaceTagSize)); 171 172 static const int kInvalidValue = 0; 173 static const int kDummyValue = 1; 174 175 // The chunk offset can also be used to encode the index of special values. 176 class ChunkOffsetBits : public BitField<uint32_t, 0, kChunkOffsetSize> {}; 177 class ChunkIndexBits 178 : public BitField<uint32_t, ChunkOffsetBits::kNext, kChunkIndexSize> {}; 179 class ValueIndexBits : public BitField<uint32_t, 0, kValueIndexSize> {}; 180 STATIC_ASSERT(ChunkIndexBits::kNext == ValueIndexBits::kNext); 181 class SpaceBits : public BitField<int, kValueIndexSize, kSpaceTagSize> {}; 182 STATIC_ASSERT(SpaceBits::kNext == 32); 183 184 uint32_t bitfield_; 185 186 friend class SerializerReferenceMap; 187 }; 188 189 // Mapping objects to their location after deserialization. 190 // This is used during building, but not at runtime by V8. 191 class SerializerReferenceMap { 192 public: SerializerReferenceMap()193 SerializerReferenceMap() 194 : no_allocation_(), map_(), attached_reference_index_(0) {} 195 Lookup(HeapObject * obj)196 SerializerReference Lookup(HeapObject* obj) { 197 Maybe<uint32_t> maybe_index = map_.Get(obj); 198 return maybe_index.IsJust() ? SerializerReference(maybe_index.FromJust()) 199 : SerializerReference(); 200 } 201 Add(HeapObject * obj,SerializerReference b)202 void Add(HeapObject* obj, SerializerReference b) { 203 DCHECK(b.is_valid()); 204 DCHECK(map_.Get(obj).IsNothing()); 205 map_.Set(obj, b.bitfield_); 206 } 207 AddAttachedReference(HeapObject * attached_reference)208 SerializerReference AddAttachedReference(HeapObject* attached_reference) { 209 SerializerReference reference = 210 SerializerReference::AttachedReference(attached_reference_index_++); 211 Add(attached_reference, reference); 212 return reference; 213 } 214 215 private: 216 DisallowHeapAllocation no_allocation_; 217 HeapObjectToIndexHashMap map_; 218 int attached_reference_index_; 219 DISALLOW_COPY_AND_ASSIGN(SerializerReferenceMap); 220 }; 221 222 } // namespace internal 223 } // namespace v8 224 225 #endif // V8_ADDRESS_MAP_H_ 226