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