• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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