Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(128)

Side by Side Diff: runtime/vm/hash_map.h

Issue 2083103002: Remove some uses of STL map. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/freelist.cc ('k') | runtime/vm/hash_map_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #ifndef VM_HASH_MAP_H_ 5 #ifndef VM_HASH_MAP_H_
6 #define VM_HASH_MAP_H_ 6 #define VM_HASH_MAP_H_
7 7
8 #include "vm/growable_array.h" // For Malloc, EmptyBase
8 #include "vm/zone.h" 9 #include "vm/zone.h"
9 10
10 namespace dart { 11 namespace dart {
11 12
12 template <typename KeyValueTrait> 13 template<typename KeyValueTrait, typename B, typename Allocator = Zone>
13 class DirectChainedHashMap: public ValueObject { 14 class BaseDirectChainedHashMap : public B {
14 public: 15 public:
15 DirectChainedHashMap() : array_size_(0), 16 explicit BaseDirectChainedHashMap(Allocator* allocator)
16 lists_size_(0), 17 : array_size_(0),
17 count_(0), 18 lists_size_(0),
18 array_(NULL), 19 count_(0),
19 lists_(NULL), 20 array_(NULL),
20 free_list_head_(kNil) { 21 lists_(NULL),
22 free_list_head_(kNil),
23 allocator_(allocator) {
21 ResizeLists(kInitialSize); 24 ResizeLists(kInitialSize);
22 Resize(kInitialSize); 25 Resize(kInitialSize);
23 } 26 }
24 27
25 DirectChainedHashMap(const DirectChainedHashMap& other); 28 BaseDirectChainedHashMap(const BaseDirectChainedHashMap& other);
29
30 ~BaseDirectChainedHashMap() {
31 allocator_->template Free<HashMapListElement>(array_, array_size_);
32 allocator_->template Free<HashMapListElement>(lists_, lists_size_);
33 }
26 34
27 void Insert(typename KeyValueTrait::Pair kv); 35 void Insert(typename KeyValueTrait::Pair kv);
28 36
29 typename KeyValueTrait::Value Lookup(typename KeyValueTrait::Key key) const; 37 typename KeyValueTrait::Value LookupValue(
38 typename KeyValueTrait::Key key) const;
39
40 typename KeyValueTrait::Pair* Lookup(typename KeyValueTrait::Key key) const;
30 41
31 bool IsEmpty() const { return count_ == 0; } 42 bool IsEmpty() const { return count_ == 0; }
32 43
33 void Clear() { 44 void Clear() {
34 if (!IsEmpty()) { 45 if (!IsEmpty()) {
35 count_ = 0; 46 count_ = 0;
36 InitArray(array_, array_size_); 47 InitArray(array_, array_size_);
37 InitArray(lists_, lists_size_); 48 InitArray(lists_, lists_size_);
38 lists_[0].next = kNil; 49 lists_[0].next = kNil;
39 for (intptr_t i = 1; i < lists_size_; ++i) { 50 for (intptr_t i = 1; i < lists_size_; ++i) {
40 lists_[i].next = i - 1; 51 lists_[i].next = i - 1;
41 } 52 }
42 free_list_head_ = lists_size_ - 1; 53 free_list_head_ = lists_size_ - 1;
43 } 54 }
44 } 55 }
45 56
57 class Iterator {
58 public:
59 typename KeyValueTrait::Pair* Next();
60
61 void Reset() {
62 array_index_ = 0;
63 list_index_ = kNil;
64 }
65
66 private:
67 explicit Iterator(const BaseDirectChainedHashMap& map)
68 : map_(map), array_index_(0), list_index_(kNil) {}
69
70 const BaseDirectChainedHashMap& map_;
71 intptr_t array_index_;
72 intptr_t list_index_;
73
74 template<typename T, typename Bs, typename A>
75 friend class BaseDirectChainedHashMap;
76 };
77
78 Iterator GetIterator() const { return Iterator(*this); }
79
46 protected: 80 protected:
47 // A linked list of T values. Stored in arrays. 81 // A linked list of T values. Stored in arrays.
48 struct HashMapListElement { 82 struct HashMapListElement {
49 HashMapListElement() : kv(), next(kNil) { } 83 HashMapListElement() : kv(), next(kNil) { }
50 typename KeyValueTrait::Pair kv; 84 typename KeyValueTrait::Pair kv;
51 intptr_t next; // Index in the array of the next list element. 85 intptr_t next; // Index in the array of the next list element.
52 }; 86 };
53 static const intptr_t kNil = -1; // The end of a linked list 87 static const intptr_t kNil = -1; // The end of a linked list
54 88
55 static void InitArray(HashMapListElement* array, intptr_t size) { 89 static void InitArray(HashMapListElement* array, intptr_t size) {
56 for (intptr_t i = 0; i < size; ++i) { 90 for (intptr_t i = 0; i < size; ++i) {
57 array[i] = HashMapListElement(); 91 array[i] = HashMapListElement();
58 } 92 }
59 } 93 }
60 94
61 // Must be a power of 2. 95 // Must be a power of 2.
62 static const intptr_t kInitialSize = 16; 96 static const intptr_t kInitialSize = 16;
63 97
64 void Resize(intptr_t new_size); 98 void Resize(intptr_t new_size);
65 void ResizeLists(intptr_t new_size); 99 void ResizeLists(intptr_t new_size);
66 uword Bound(uword value) const { return value & (array_size_ - 1); } 100 uword Bound(uword value) const { return value & (array_size_ - 1); }
67 101
68 intptr_t array_size_; 102 intptr_t array_size_;
69 intptr_t lists_size_; 103 intptr_t lists_size_;
70 intptr_t count_; // The number of values stored in the HashMap. 104 intptr_t count_; // The number of values stored in the HashMap.
71 HashMapListElement* array_; // Primary store - contains the first value 105 HashMapListElement* array_; // Primary store - contains the first value
72 // with a given hash. Colliding elements are stored in linked lists. 106 // with a given hash. Colliding elements are stored in linked lists.
73 HashMapListElement* lists_; // The linked lists containing hash collisions. 107 HashMapListElement* lists_; // The linked lists containing hash collisions.
74 intptr_t free_list_head_; // Unused elements in lists_ are on the free list. 108 intptr_t free_list_head_; // Unused elements in lists_ are on the free list.
109 Allocator* allocator_;
75 }; 110 };
76 111
77 112
78 template <typename KeyValueTrait> 113 template<typename KeyValueTrait, typename B, typename Allocator>
79 typename KeyValueTrait::Value 114 BaseDirectChainedHashMap<KeyValueTrait, B, Allocator>::
80 DirectChainedHashMap<KeyValueTrait>:: 115 BaseDirectChainedHashMap(const BaseDirectChainedHashMap& other)
116 : B(),
117 array_size_(other.array_size_),
118 lists_size_(other.lists_size_),
119 count_(other.count_),
120 array_(other.allocator_->template Alloc<HashMapListElement>(
121 other.array_size_)),
122 lists_(other.allocator_->template Alloc<HashMapListElement>(
123 other.lists_size_)),
124 free_list_head_(other.free_list_head_),
125 allocator_(other.allocator_) {
126 memmove(array_, other.array_, array_size_ * sizeof(HashMapListElement));
127 memmove(lists_, other.lists_, lists_size_ * sizeof(HashMapListElement));
128 }
129
130
131 template<typename KeyValueTrait, typename B, typename Allocator>
132 typename KeyValueTrait::Pair*
133 BaseDirectChainedHashMap<KeyValueTrait, B, Allocator>::
81 Lookup(typename KeyValueTrait::Key key) const { 134 Lookup(typename KeyValueTrait::Key key) const {
82 const typename KeyValueTrait::Value kNoValue = 135 const typename KeyValueTrait::Value kNoValue =
83 KeyValueTrait::ValueOf(typename KeyValueTrait::Pair()); 136 KeyValueTrait::ValueOf(typename KeyValueTrait::Pair());
84 137
85 uword hash = static_cast<uword>(KeyValueTrait::Hashcode(key)); 138 uword hash = static_cast<uword>(KeyValueTrait::Hashcode(key));
86 uword pos = Bound(hash); 139 uword pos = Bound(hash);
87 if (KeyValueTrait::ValueOf(array_[pos].kv) != kNoValue) { 140 if (KeyValueTrait::ValueOf(array_[pos].kv) != kNoValue) {
88 if (KeyValueTrait::IsKeyEqual(array_[pos].kv, key)) { 141 if (KeyValueTrait::IsKeyEqual(array_[pos].kv, key)) {
89 return KeyValueTrait::ValueOf(array_[pos].kv); 142 return &array_[pos].kv;
90 } 143 }
91 144
92 intptr_t next = array_[pos].next; 145 intptr_t next = array_[pos].next;
93 while (next != kNil) { 146 while (next != kNil) {
94 if (KeyValueTrait::IsKeyEqual(lists_[next].kv, key)) { 147 if (KeyValueTrait::IsKeyEqual(lists_[next].kv, key)) {
95 return KeyValueTrait::ValueOf(lists_[next].kv); 148 return &lists_[next].kv;
96 } 149 }
97 next = lists_[next].next; 150 next = lists_[next].next;
98 } 151 }
99 } 152 }
100 return kNoValue; 153 return NULL;
101 } 154 }
102 155
103 156
104 template <typename KeyValueTrait> 157 template<typename KeyValueTrait, typename B, typename Allocator>
105 DirectChainedHashMap<KeyValueTrait>:: 158 typename KeyValueTrait::Value
106 DirectChainedHashMap(const DirectChainedHashMap& other) 159 BaseDirectChainedHashMap<KeyValueTrait, B, Allocator>::
107 : ValueObject(), 160 LookupValue(typename KeyValueTrait::Key key) const {
108 array_size_(other.array_size_), 161 const typename KeyValueTrait::Value kNoValue =
109 lists_size_(other.lists_size_), 162 KeyValueTrait::ValueOf(typename KeyValueTrait::Pair());
110 count_(other.count_), 163 typename KeyValueTrait::Pair* pair = Lookup(key);
111 array_(Thread::Current()->zone()-> 164 return (pair == NULL) ? kNoValue : KeyValueTrait::ValueOf(*pair);
112 Alloc<HashMapListElement>(other.array_size_)),
113 lists_(Thread::Current()->zone()->
114 Alloc<HashMapListElement>(other.lists_size_)),
115 free_list_head_(other.free_list_head_) {
116 memmove(array_, other.array_, array_size_ * sizeof(HashMapListElement));
117 memmove(lists_, other.lists_, lists_size_ * sizeof(HashMapListElement));
118 } 165 }
119 166
120 167
121 template <typename KeyValueTrait> 168 template<typename KeyValueTrait, typename B, typename Allocator>
122 void DirectChainedHashMap<KeyValueTrait>::Resize(intptr_t new_size) { 169 typename KeyValueTrait::Pair*
170 BaseDirectChainedHashMap<KeyValueTrait, B, Allocator>::Iterator::Next() {
171 const typename KeyValueTrait::Pair kNoPair = typename KeyValueTrait::Pair();
172
173 if (array_index_ < map_.array_size_) {
174 // If we're not in the middle of a list, find the next array slot.
175 if (list_index_ == kNil) {
176 while ((map_.array_[array_index_].kv == kNoPair) &&
177 (array_index_ < map_.array_size_)) {
178 array_index_++;
179 }
180 if (array_index_ < map_.array_size_) {
181 // When we're done with the list, we'll continue with the next array
182 // slot.
183 const intptr_t old_array_index = array_index_;
184 array_index_++;
185 list_index_ = map_.array_[old_array_index].next;
186 return &map_.array_[old_array_index].kv;
187 } else {
188 return NULL;
189 }
190 }
191
192 // Otherwise, return the current lists_ entry, advancing list_index_.
193 intptr_t current = list_index_;
194 list_index_ = map_.lists_[current].next;
195 return &map_.lists_[current].kv;
196 }
197
198 return NULL;
199 }
200
201
202 template<typename KeyValueTrait, typename B, typename Allocator>
203 void BaseDirectChainedHashMap<KeyValueTrait, B, Allocator>::Resize(
204 intptr_t new_size) {
123 const typename KeyValueTrait::Value kNoValue = 205 const typename KeyValueTrait::Value kNoValue =
124 KeyValueTrait::ValueOf(typename KeyValueTrait::Pair()); 206 KeyValueTrait::ValueOf(typename KeyValueTrait::Pair());
125 207
126 ASSERT(new_size > count_); 208 ASSERT(new_size > count_);
127 // Hashing the values into the new array has no more collisions than in the 209 // Hashing the values into the new array has no more collisions than in the
128 // old hash map, so we can use the existing lists_ array, if we are careful. 210 // old hash map, so we can use the existing lists_ array, if we are careful.
129 211
130 // Make sure we have at least one free element. 212 // Make sure we have at least one free element.
131 if (free_list_head_ == kNil) { 213 if (free_list_head_ == kNil) {
132 ResizeLists(lists_size_ << 1); 214 ResizeLists(lists_size_ << 1);
133 } 215 }
134 216
135 HashMapListElement* new_array = 217 HashMapListElement* new_array =
136 Thread::Current()->zone()->Alloc<HashMapListElement>(new_size); 218 allocator_->template Alloc<HashMapListElement>(new_size);
137 InitArray(new_array, new_size); 219 InitArray(new_array, new_size);
138 220
139 HashMapListElement* old_array = array_; 221 HashMapListElement* old_array = array_;
140 intptr_t old_size = array_size_; 222 intptr_t old_size = array_size_;
141 223
142 intptr_t old_count = count_; 224 intptr_t old_count = count_;
143 count_ = 0; 225 count_ = 0;
144 array_size_ = new_size; 226 array_size_ = new_size;
145 array_ = new_array; 227 array_ = new_array;
146 228
147 if (old_array != NULL) { 229 if (old_array != NULL) {
148 // Iterate over all the elements in lists, rehashing them. 230 // Iterate over all the elements in lists, rehashing them.
149 for (intptr_t i = 0; i < old_size; ++i) { 231 for (intptr_t i = 0; i < old_size; ++i) {
150 if (KeyValueTrait::ValueOf(old_array[i].kv) != kNoValue) { 232 if (KeyValueTrait::ValueOf(old_array[i].kv) != kNoValue) {
151 intptr_t current = old_array[i].next; 233 intptr_t current = old_array[i].next;
152 while (current != kNil) { 234 while (current != kNil) {
153 Insert(lists_[current].kv); 235 Insert(lists_[current].kv);
154 intptr_t next = lists_[current].next; 236 intptr_t next = lists_[current].next;
155 lists_[current].next = free_list_head_; 237 lists_[current].next = free_list_head_;
156 free_list_head_ = current; 238 free_list_head_ = current;
157 current = next; 239 current = next;
158 } 240 }
159 // Rehash the directly stored value. 241 // Rehash the directly stored value.
160 Insert(old_array[i].kv); 242 Insert(old_array[i].kv);
161 } 243 }
162 } 244 }
163 } 245 }
164 USE(old_count); 246 USE(old_count);
165 ASSERT(count_ == old_count); 247 ASSERT(count_ == old_count);
248 allocator_->template Free<HashMapListElement>(old_array, old_size);
166 } 249 }
167 250
168 251
169 template <typename T> 252 template<typename KeyValueTrait, typename B, typename Allocator>
170 void DirectChainedHashMap<T>::ResizeLists(intptr_t new_size) { 253 void BaseDirectChainedHashMap<KeyValueTrait, B, Allocator>::ResizeLists(
254 intptr_t new_size) {
171 ASSERT(new_size > lists_size_); 255 ASSERT(new_size > lists_size_);
172 256
173 HashMapListElement* new_lists = 257 HashMapListElement* new_lists =
174 Thread::Current()->zone()-> 258 allocator_->template Alloc<HashMapListElement>(new_size);
175 Alloc<HashMapListElement>(new_size);
176 InitArray(new_lists, new_size); 259 InitArray(new_lists, new_size);
177 260
178 HashMapListElement* old_lists = lists_; 261 HashMapListElement* old_lists = lists_;
179 intptr_t old_size = lists_size_; 262 intptr_t old_size = lists_size_;
180 263
181 lists_size_ = new_size; 264 lists_size_ = new_size;
182 lists_ = new_lists; 265 lists_ = new_lists;
183 266
184 if (old_lists != NULL) { 267 if (old_lists != NULL) {
185 memmove(lists_, old_lists, old_size * sizeof(HashMapListElement)); 268 memmove(lists_, old_lists, old_size * sizeof(HashMapListElement));
186 } 269 }
187 for (intptr_t i = old_size; i < lists_size_; ++i) { 270 for (intptr_t i = old_size; i < lists_size_; ++i) {
188 lists_[i].next = free_list_head_; 271 lists_[i].next = free_list_head_;
189 free_list_head_ = i; 272 free_list_head_ = i;
190 } 273 }
274 allocator_->template Free<HashMapListElement>(old_lists, old_size);
191 } 275 }
192 276
193 277
194 template <typename KeyValueTrait> 278 template<typename KeyValueTrait, typename B, typename Allocator>
195 void DirectChainedHashMap<KeyValueTrait>:: 279 void BaseDirectChainedHashMap<KeyValueTrait, B, Allocator>::
196 Insert(typename KeyValueTrait::Pair kv) { 280 Insert(typename KeyValueTrait::Pair kv) {
197 const typename KeyValueTrait::Value kNoValue = 281 const typename KeyValueTrait::Value kNoValue =
198 KeyValueTrait::ValueOf(typename KeyValueTrait::Pair()); 282 KeyValueTrait::ValueOf(typename KeyValueTrait::Pair());
199 283
200 ASSERT(KeyValueTrait::ValueOf(kv) != kNoValue); 284 ASSERT(KeyValueTrait::ValueOf(kv) != kNoValue);
201 // Resizing when half of the hashtable is filled up. 285 // Resizing when half of the hashtable is filled up.
202 if (count_ >= array_size_ >> 1) Resize(array_size_ << 1); 286 if (count_ >= array_size_ >> 1) Resize(array_size_ << 1);
203 ASSERT(count_ < array_size_); 287 ASSERT(count_ < array_size_);
204 count_++; 288 count_++;
205 uword pos = Bound( 289 uword pos = Bound(
(...skipping 10 matching lines...) Expand all
216 free_list_head_ = lists_[free_list_head_].next; 300 free_list_head_ = lists_[free_list_head_].next;
217 lists_[new_element_pos].kv = kv; 301 lists_[new_element_pos].kv = kv;
218 lists_[new_element_pos].next = array_[pos].next; 302 lists_[new_element_pos].next = array_[pos].next;
219 ASSERT(array_[pos].next == kNil || 303 ASSERT(array_[pos].next == kNil ||
220 KeyValueTrait::ValueOf(lists_[array_[pos].next].kv) != kNoValue); 304 KeyValueTrait::ValueOf(lists_[array_[pos].next].kv) != kNoValue);
221 array_[pos].next = new_element_pos; 305 array_[pos].next = new_element_pos;
222 } 306 }
223 } 307 }
224 308
225 309
310 template<typename KeyValueTrait>
311 class DirectChainedHashMap
312 : public BaseDirectChainedHashMap<KeyValueTrait, ValueObject> {
313 public:
314 DirectChainedHashMap() : BaseDirectChainedHashMap<KeyValueTrait, ValueObject>(
315 ASSERT_NOTNULL(Thread::Current()->zone())) {}
316 };
317
318
319 template<typename KeyValueTrait>
320 class MallocDirectChainedHashMap
321 : public BaseDirectChainedHashMap<KeyValueTrait, EmptyBase, Malloc> {
322 public:
323 MallocDirectChainedHashMap()
324 : BaseDirectChainedHashMap<KeyValueTrait, EmptyBase, Malloc>(NULL) {}
325 };
326
327
226 template<typename T> 328 template<typename T>
227 class PointerKeyValueTrait { 329 class PointerKeyValueTrait {
228 public: 330 public:
229 typedef T* Value; 331 typedef T* Value;
230 typedef T* Key; 332 typedef T* Key;
231 typedef T* Pair; 333 typedef T* Pair;
232 334
233 static Key KeyOf(Pair kv) { 335 static Key KeyOf(Pair kv) {
234 return kv; 336 return kv;
235 } 337 }
236 338
237 static Value ValueOf(Pair kv) { 339 static Value ValueOf(Pair kv) {
238 return kv; 340 return kv;
239 } 341 }
240 342
241 static inline intptr_t Hashcode(Key key) { 343 static inline intptr_t Hashcode(Key key) {
242 return key->Hashcode(); 344 return key->Hashcode();
243 } 345 }
244 346
245 static inline bool IsKeyEqual(Pair kv, Key key) { 347 static inline bool IsKeyEqual(Pair kv, Key key) {
246 return kv->Equals(key); 348 return kv->Equals(key);
247 } 349 }
248 }; 350 };
249 351
352
353 template<typename T>
354 class NumbersKeyValueTrait {
355 public:
356 typedef T Value;
357 typedef intptr_t Key;
358 typedef T Pair;
359
360 static intptr_t KeyOf(Pair kv) { return kv.first(); }
361 static T ValueOf(Pair kv) { return kv; }
362 static inline intptr_t Hashcode(Key key) { return key; }
363 static inline bool IsKeyEqual(Pair kv, Key key) { return kv.first() == key; }
364 };
365
250 } // namespace dart 366 } // namespace dart
251 367
252 #endif // VM_HASH_MAP_H_ 368 #endif // VM_HASH_MAP_H_
OLDNEW
« no previous file with comments | « runtime/vm/freelist.cc ('k') | runtime/vm/hash_map_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698