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 bool DeleteEntry(Object* key, void** deleted_value); 47 void Clear(); 48 49 Object* KeyAtIndex(int index) const; 50 51 V8_EXPORT_PRIVATE RawEntry EntryAtIndex(int index) const; 52 V8_EXPORT_PRIVATE int NextIndex(int index) const; 53 54 void EnableIteration(); 55 void DisableIteration(); 56 57 virtual void** NewPointerArray(size_t length) = 0; 58 virtual void DeleteArray(void* array) = 0; 59 60 private: 61 // Internal implementation should not be called directly by subclasses. 62 int ScanKeysFor(Object* address) const; 63 int InsertKey(Object* address); 64 int Lookup(Object* key) const; 65 int LookupOrInsert(Object* key); 66 bool DeleteIndex(int index, void** deleted_value); 67 void Rehash(); 68 void Resize(int new_capacity); 69 int Hash(Object* address) const; 70 71 base::hash<uintptr_t> hasher_; 72 Heap* heap_; 73 int gc_counter_; 74 int size_; 75 int capacity_; 76 int mask_; 77 Object** keys_; 78 void** values_; 79 bool is_iterable_; 80 81 DISALLOW_COPY_AND_ASSIGN(IdentityMapBase); 82 }; 83 84 // Implements an identity map from object addresses to a given value type {V}. 85 // The map is robust w.r.t. garbage collection by synchronization with the 86 // supplied {heap}. 87 // * Keys are treated as strong roots. 88 // * The value type {V} must be reinterpret_cast'able to {void*} 89 // * The value type {V} must not be a heap type. 90 template <typename V, class AllocationPolicy> 91 class IdentityMap : public IdentityMapBase { 92 public: 93 explicit IdentityMap(Heap* heap, 94 AllocationPolicy allocator = AllocationPolicy()) IdentityMapBase(heap)95 : IdentityMapBase(heap), allocator_(allocator) {} ~IdentityMap()96 ~IdentityMap() override { Clear(); }; 97 98 // Searches this map for the given key using the object's address 99 // as the identity, returning: 100 // found => a pointer to the storage location for the value 101 // not found => a pointer to a new storage location for the value Get(Handle<Object> key)102 V* Get(Handle<Object> key) { return Get(*key); } Get(Object * key)103 V* Get(Object* key) { return reinterpret_cast<V*>(GetEntry(key)); } 104 105 // Searches this map for the given key using the object's address 106 // as the identity, returning: 107 // found => a pointer to the storage location for the value 108 // not found => {nullptr} Find(Handle<Object> key)109 V* Find(Handle<Object> key) const { return Find(*key); } Find(Object * key)110 V* Find(Object* key) const { return reinterpret_cast<V*>(FindEntry(key)); } 111 112 // Set the value for the given key. Set(Handle<Object> key,V v)113 void Set(Handle<Object> key, V v) { Set(*key, v); } Set(Object * key,V v)114 void Set(Object* key, V v) { *(reinterpret_cast<V*>(GetEntry(key))) = v; } 115 Delete(Handle<Object> key,V * deleted_value)116 bool Delete(Handle<Object> key, V* deleted_value) { 117 return Delete(*key, deleted_value); 118 } Delete(Object * key,V * deleted_value)119 bool Delete(Object* key, V* deleted_value) { 120 void* v = nullptr; 121 bool deleted_something = DeleteEntry(key, &v); 122 if (deleted_value != nullptr && deleted_something) { 123 *deleted_value = (V) reinterpret_cast<intptr_t>(v); 124 } 125 return deleted_something; 126 } 127 128 // Removes all elements from the map. Clear()129 void Clear() { IdentityMapBase::Clear(); } 130 131 // Iterator over IdentityMap. The IteratableScope used to create this Iterator 132 // must be live for the duration of the iteration. 133 class Iterator { 134 public: 135 Iterator& operator++() { 136 index_ = map_->NextIndex(index_); 137 return *this; 138 } 139 key()140 Object* key() const { return map_->KeyAtIndex(index_); } entry()141 V* entry() const { 142 return reinterpret_cast<V*>(map_->EntryAtIndex(index_)); 143 } 144 145 V* operator*() { return entry(); } 146 V* operator->() { return entry(); } 147 bool operator!=(const Iterator& other) { return index_ != other.index_; } 148 149 private: Iterator(IdentityMap * map,int index)150 Iterator(IdentityMap* map, int index) : map_(map), index_(index) {} 151 152 IdentityMap* map_; 153 int index_; 154 155 friend class IdentityMap; 156 }; 157 158 class IteratableScope { 159 public: IteratableScope(IdentityMap * map)160 explicit IteratableScope(IdentityMap* map) : map_(map) { 161 CHECK(!map_->is_iterable()); 162 map_->EnableIteration(); 163 } ~IteratableScope()164 ~IteratableScope() { 165 CHECK(map_->is_iterable()); 166 map_->DisableIteration(); 167 } 168 begin()169 Iterator begin() { return Iterator(map_, map_->NextIndex(-1)); } end()170 Iterator end() { return Iterator(map_, map_->capacity()); } 171 172 private: 173 IdentityMap* map_; 174 DISALLOW_COPY_AND_ASSIGN(IteratableScope); 175 }; 176 177 protected: NewPointerArray(size_t length)178 void** NewPointerArray(size_t length) override { 179 return static_cast<void**>(allocator_.New(sizeof(void*) * length)); 180 } DeleteArray(void * array)181 void DeleteArray(void* array) override { allocator_.Delete(array); } 182 183 private: 184 AllocationPolicy allocator_; 185 DISALLOW_COPY_AND_ASSIGN(IdentityMap); 186 }; 187 188 } // namespace internal 189 } // namespace v8 190 191 #endif // V8_IDENTITY_MAP_H_ 192