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_IDENTITY_MAP_H_ 6 #define V8_IDENTITY_MAP_H_ 7 8 #include "src/base/functional.h" 9 #include "src/handles.h" 10 11 namespace v8 { 12 namespace internal { 13 14 // Forward declarations. 15 class Heap; 16 17 // Base class of identity maps contains shared code for all template 18 // instantions. 19 class IdentityMapBase { 20 public: empty()21 bool empty() const { return size_ == 0; } size()22 int size() const { return size_; } capacity()23 int capacity() const { return capacity_; } is_iterable()24 bool is_iterable() const { return is_iterable_; } 25 26 protected: 27 // Allow Tester to access internals, including changing the address of objects 28 // within the {keys_} array in order to simulate a moving GC. 29 friend class IdentityMapTester; 30 31 typedef void** RawEntry; 32 IdentityMapBase(Heap * heap)33 explicit IdentityMapBase(Heap* heap) 34 : heap_(heap), 35 gc_counter_(-1), 36 size_(0), 37 capacity_(0), 38 mask_(0), 39 keys_(nullptr), 40 values_(nullptr), 41 is_iterable_(false) {} 42 virtual ~IdentityMapBase(); 43 44 RawEntry GetEntry(Object* key); 45 RawEntry FindEntry(Object* key) const; 46 void* DeleteEntry(Object* key); 47 void* DeleteIndex(int index); 48 void Clear(); 49 50 V8_EXPORT_PRIVATE RawEntry EntryAtIndex(int index) const; 51 V8_EXPORT_PRIVATE int NextIndex(int index) const; 52 53 void EnableIteration(); 54 void DisableIteration(); 55 56 virtual void** NewPointerArray(size_t length) = 0; 57 virtual void DeleteArray(void* array) = 0; 58 59 private: 60 // Internal implementation should not be called directly by subclasses. 61 int ScanKeysFor(Object* address) const; 62 int InsertKey(Object* address); 63 int Lookup(Object* key) const; 64 int LookupOrInsert(Object* key); 65 void Rehash(); 66 void Resize(int new_capacity); 67 int Hash(Object* address) const; 68 69 base::hash<uintptr_t> hasher_; 70 Heap* heap_; 71 int gc_counter_; 72 int size_; 73 int capacity_; 74 int mask_; 75 Object** keys_; 76 void** values_; 77 bool is_iterable_; 78 79 DISALLOW_COPY_AND_ASSIGN(IdentityMapBase); 80 }; 81 82 // Implements an identity map from object addresses to a given value type {V}. 83 // The map is robust w.r.t. garbage collection by synchronization with the 84 // supplied {heap}. 85 // * Keys are treated as strong roots. 86 // * The value type {V} must be reinterpret_cast'able to {void*} 87 // * The value type {V} must not be a heap type. 88 template <typename V, class AllocationPolicy> 89 class IdentityMap : public IdentityMapBase { 90 public: 91 explicit IdentityMap(Heap* heap, 92 AllocationPolicy allocator = AllocationPolicy()) IdentityMapBase(heap)93 : IdentityMapBase(heap), allocator_(allocator) {} ~IdentityMap()94 ~IdentityMap() override { Clear(); }; 95 96 // Searches this map for the given key using the object's address 97 // as the identity, returning: 98 // found => a pointer to the storage location for the value 99 // not found => a pointer to a new storage location for the value Get(Handle<Object> key)100 V* Get(Handle<Object> key) { return Get(*key); } Get(Object * key)101 V* Get(Object* key) { return reinterpret_cast<V*>(GetEntry(key)); } 102 103 // Searches this map for the given key using the object's address 104 // as the identity, returning: 105 // found => a pointer to the storage location for the value 106 // not found => {nullptr} Find(Handle<Object> key)107 V* Find(Handle<Object> key) const { return Find(*key); } Find(Object * key)108 V* Find(Object* key) const { return reinterpret_cast<V*>(FindEntry(key)); } 109 110 // Set the value for the given key. Set(Handle<Object> key,V v)111 void Set(Handle<Object> key, V v) { Set(*key, v); } Set(Object * key,V v)112 void Set(Object* key, V v) { *(reinterpret_cast<V*>(GetEntry(key))) = v; } 113 Delete(Handle<Object> key)114 V Delete(Handle<Object> key) { return Delete(*key); } Delete(Object * key)115 V Delete(Object* key) { return reinterpret_cast<V>(DeleteEntry(key)); } 116 117 // Removes all elements from the map. Clear()118 void Clear() { IdentityMapBase::Clear(); } 119 120 // Iterator over IdentityMap. The IteratableScope used to create this Iterator 121 // must be live for the duration of the iteration. 122 class Iterator { 123 public: 124 Iterator& operator++() { 125 index_ = map_->NextIndex(index_); 126 return *this; 127 } 128 DeleteAndIncrement()129 Iterator& DeleteAndIncrement() { 130 map_->DeleteIndex(index_); 131 index_ = map_->NextIndex(index_); 132 return *this; 133 } 134 135 V* operator*() { return reinterpret_cast<V*>(map_->EntryAtIndex(index_)); } 136 V* operator->() { return reinterpret_cast<V*>(map_->EntryAtIndex(index_)); } 137 bool operator!=(const Iterator& other) { return index_ != other.index_; } 138 139 private: Iterator(IdentityMap * map,int index)140 Iterator(IdentityMap* map, int index) : map_(map), index_(index) {} 141 142 IdentityMap* map_; 143 int index_; 144 145 friend class IdentityMap; 146 }; 147 148 class IteratableScope { 149 public: IteratableScope(IdentityMap * map)150 explicit IteratableScope(IdentityMap* map) : map_(map) { 151 CHECK(!map_->is_iterable()); 152 map_->EnableIteration(); 153 } ~IteratableScope()154 ~IteratableScope() { 155 CHECK(map_->is_iterable()); 156 map_->DisableIteration(); 157 } 158 begin()159 Iterator begin() { return Iterator(map_, map_->NextIndex(-1)); } end()160 Iterator end() { return Iterator(map_, map_->capacity()); } 161 162 private: 163 IdentityMap* map_; 164 DISALLOW_COPY_AND_ASSIGN(IteratableScope); 165 }; 166 167 protected: NewPointerArray(size_t length)168 void** NewPointerArray(size_t length) override { 169 return static_cast<void**>(allocator_.New(sizeof(void*) * length)); 170 } DeleteArray(void * array)171 void DeleteArray(void* array) override { allocator_.Delete(array); } 172 173 private: 174 AllocationPolicy allocator_; 175 DISALLOW_COPY_AND_ASSIGN(IdentityMap); 176 }; 177 178 } // namespace internal 179 } // namespace v8 180 181 #endif // V8_IDENTITY_MAP_H_ 182