1 // Copyright 2018 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_SNAPSHOT_REFERENCES_H_ 6 #define V8_SNAPSHOT_REFERENCES_H_ 7 8 #include "src/assert-scope.h" 9 #include "src/base/hashmap.h" 10 #include "src/utils.h" 11 12 namespace v8 { 13 namespace internal { 14 15 class SerializerReference { 16 private: 17 enum SpecialValueType { 18 kInvalidValue, 19 kAttachedReference, 20 kOffHeapBackingStore, 21 kBuiltinReference, 22 }; 23 24 static const int kSpecialValueSpace = LAST_SPACE + 1; 25 STATIC_ASSERT(kSpecialValueSpace < (1 << kSpaceTagSize)); 26 SerializerReference(SpecialValueType type,uint32_t value)27 SerializerReference(SpecialValueType type, uint32_t value) 28 : bitfield_(SpaceBits::encode(kSpecialValueSpace) | 29 SpecialValueTypeBits::encode(type)), 30 value_(value) {} 31 32 public: SerializerReference()33 SerializerReference() : SerializerReference(kInvalidValue, 0) {} 34 SerializerReference(uint32_t space,uint32_t chunk_index,uint32_t chunk_offset)35 SerializerReference(uint32_t space, uint32_t chunk_index, 36 uint32_t chunk_offset) 37 : bitfield_(SpaceBits::encode(space) | 38 ChunkIndexBits::encode(chunk_index)), 39 value_(chunk_offset) {} 40 BackReference(AllocationSpace space,uint32_t chunk_index,uint32_t chunk_offset)41 static SerializerReference BackReference(AllocationSpace space, 42 uint32_t chunk_index, 43 uint32_t chunk_offset) { 44 DCHECK(IsAligned(chunk_offset, kObjectAlignment)); 45 DCHECK_LT(space, LO_SPACE); 46 return SerializerReference(space, chunk_index, chunk_offset); 47 } 48 MapReference(uint32_t index)49 static SerializerReference MapReference(uint32_t index) { 50 return SerializerReference(MAP_SPACE, 0, index); 51 } 52 OffHeapBackingStoreReference(uint32_t index)53 static SerializerReference OffHeapBackingStoreReference(uint32_t index) { 54 return SerializerReference(kOffHeapBackingStore, index); 55 } 56 LargeObjectReference(uint32_t index)57 static SerializerReference LargeObjectReference(uint32_t index) { 58 return SerializerReference(LO_SPACE, 0, index); 59 } 60 AttachedReference(uint32_t index)61 static SerializerReference AttachedReference(uint32_t index) { 62 return SerializerReference(kAttachedReference, index); 63 } 64 BuiltinReference(uint32_t index)65 static SerializerReference BuiltinReference(uint32_t index) { 66 return SerializerReference(kBuiltinReference, index); 67 } 68 is_valid()69 bool is_valid() const { 70 return SpaceBits::decode(bitfield_) != kSpecialValueSpace || 71 SpecialValueTypeBits::decode(bitfield_) != kInvalidValue; 72 } 73 is_back_reference()74 bool is_back_reference() const { 75 return SpaceBits::decode(bitfield_) <= LAST_SPACE; 76 } 77 space()78 AllocationSpace space() const { 79 DCHECK(is_back_reference()); 80 return static_cast<AllocationSpace>(SpaceBits::decode(bitfield_)); 81 } 82 chunk_offset()83 uint32_t chunk_offset() const { 84 DCHECK(is_back_reference()); 85 return value_; 86 } 87 chunk_index()88 uint32_t chunk_index() const { 89 DCHECK(space() != MAP_SPACE && space() != LO_SPACE); 90 return ChunkIndexBits::decode(bitfield_); 91 } 92 map_index()93 uint32_t map_index() const { 94 DCHECK_EQ(MAP_SPACE, SpaceBits::decode(bitfield_)); 95 return value_; 96 } 97 is_off_heap_backing_store_reference()98 bool is_off_heap_backing_store_reference() const { 99 return SpaceBits::decode(bitfield_) == kSpecialValueSpace && 100 SpecialValueTypeBits::decode(bitfield_) == kOffHeapBackingStore; 101 } 102 off_heap_backing_store_index()103 uint32_t off_heap_backing_store_index() const { 104 DCHECK(is_off_heap_backing_store_reference()); 105 return value_; 106 } 107 large_object_index()108 uint32_t large_object_index() const { 109 DCHECK_EQ(LO_SPACE, SpaceBits::decode(bitfield_)); 110 return value_; 111 } 112 is_attached_reference()113 bool is_attached_reference() const { 114 return SpaceBits::decode(bitfield_) == kSpecialValueSpace && 115 SpecialValueTypeBits::decode(bitfield_) == kAttachedReference; 116 } 117 attached_reference_index()118 uint32_t attached_reference_index() const { 119 DCHECK(is_attached_reference()); 120 return value_; 121 } 122 is_builtin_reference()123 bool is_builtin_reference() const { 124 return SpaceBits::decode(bitfield_) == kSpecialValueSpace && 125 SpecialValueTypeBits::decode(bitfield_) == kBuiltinReference; 126 } 127 builtin_index()128 uint32_t builtin_index() const { 129 DCHECK(is_builtin_reference()); 130 return value_; 131 } 132 133 private: 134 class SpaceBits : public BitField<int, 0, kSpaceTagSize> {}; 135 class ChunkIndexBits 136 : public BitField<uint32_t, SpaceBits::kNext, 32 - kSpaceTagSize> {}; 137 class SpecialValueTypeBits 138 : public BitField<SpecialValueType, SpaceBits::kNext, 139 32 - kSpaceTagSize> {}; 140 141 // We use two fields to store a reference. 142 // In case of a normal back reference, the bitfield_ stores the space and 143 // the chunk index. In case of special references, it uses a special value 144 // for space and stores the special value type. 145 uint32_t bitfield_; 146 // value_ stores either chunk offset or special value. 147 uint32_t value_; 148 149 friend class SerializerReferenceMap; 150 }; 151 152 class SerializerReferenceMap 153 : public base::TemplateHashMapImpl<uintptr_t, SerializerReference, 154 base::KeyEqualityMatcher<intptr_t>, 155 base::DefaultAllocationPolicy> { 156 public: 157 typedef base::TemplateHashMapEntry<uintptr_t, SerializerReference> Entry; 158 SerializerReferenceMap()159 SerializerReferenceMap() : no_allocation_(), attached_reference_index_(0) {} 160 LookupReference(void * value)161 SerializerReference LookupReference(void* value) const { 162 uintptr_t key = Key(value); 163 Entry* entry = Lookup(key, Hash(key)); 164 if (entry == nullptr) return SerializerReference(); 165 return entry->value; 166 } 167 Add(void * obj,SerializerReference reference)168 void Add(void* obj, SerializerReference reference) { 169 DCHECK(reference.is_valid()); 170 DCHECK(!LookupReference(obj).is_valid()); 171 uintptr_t key = Key(obj); 172 LookupOrInsert(key, Hash(key))->value = reference; 173 } 174 AddAttachedReference(void * attached_reference)175 SerializerReference AddAttachedReference(void* attached_reference) { 176 SerializerReference reference = 177 SerializerReference::AttachedReference(attached_reference_index_++); 178 Add(attached_reference, reference); 179 return reference; 180 } 181 182 private: Key(void * value)183 static inline uintptr_t Key(void* value) { 184 return reinterpret_cast<uintptr_t>(value); 185 } 186 Hash(uintptr_t key)187 static uint32_t Hash(uintptr_t key) { return static_cast<uint32_t>(key); } 188 189 DisallowHeapAllocation no_allocation_; 190 int attached_reference_index_; 191 DISALLOW_COPY_AND_ASSIGN(SerializerReferenceMap); 192 }; 193 194 } // namespace internal 195 } // namespace v8 196 197 #endif // V8_SNAPSHOT_REFERENCES_H_ 198