OLD | NEW |
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 namespace dart { | 8 namespace dart { |
9 | 9 |
10 template <typename T> | 10 template <typename T> |
11 class DirectChainedHashMap: public ValueObject { | 11 class DirectChainedHashMap: public ValueObject { |
12 public: | 12 public: |
13 DirectChainedHashMap() : array_size_(0), | 13 DirectChainedHashMap() : array_size_(0), |
14 lists_size_(0), | 14 lists_size_(0), |
15 count_(0), | 15 count_(0), |
16 array_(NULL), | 16 array_(NULL), |
17 lists_(NULL), | 17 lists_(NULL), |
18 free_list_head_(kNil) { | 18 free_list_head_(kNil) { |
19 ResizeLists(kInitialSize); | 19 ResizeLists(kInitialSize); |
20 Resize(kInitialSize); | 20 Resize(kInitialSize); |
21 } | 21 } |
22 | 22 |
| 23 DirectChainedHashMap(const DirectChainedHashMap& other); |
| 24 |
23 void Insert(T value); | 25 void Insert(T value); |
24 | 26 |
25 T Lookup(T value) const; | 27 T Lookup(T value) const; |
26 | 28 |
27 bool IsEmpty() const { return count_ == 0; } | 29 bool IsEmpty() const { return count_ == 0; } |
28 | 30 |
29 private: | 31 private: |
30 // A linked list of T values. Stored in arrays. | 32 // A linked list of T values. Stored in arrays. |
31 struct HashMapListElement { | 33 struct HashMapListElement { |
32 T value; | 34 T value; |
33 intptr_t next; // Index in the array of the next list element. | 35 intptr_t next; // Index in the array of the next list element. |
34 }; | 36 }; |
35 static const intptr_t kNil = -1; // The end of a linked list | 37 static const intptr_t kNil = -1; // The end of a linked list |
36 | 38 |
37 // Must be a power of 2. | 39 // Must be a power of 2. |
38 static const intptr_t kInitialSize = 16; | 40 static const intptr_t kInitialSize = 16; |
39 | 41 |
40 void Resize(intptr_t new_size); | 42 void Resize(intptr_t new_size); |
41 void ResizeLists(intptr_t new_size); | 43 void ResizeLists(intptr_t new_size); |
42 uword Bound(uword value) const { return value & (array_size_ - 1); } | 44 uword Bound(uword value) const { return value & (array_size_ - 1); } |
43 | 45 |
44 intptr_t array_size_; | 46 intptr_t array_size_; |
45 intptr_t lists_size_; | 47 intptr_t lists_size_; |
46 intptr_t count_; // The number of values stored in the HashMap. | 48 intptr_t count_; // The number of values stored in the HashMap. |
47 HashMapListElement* array_; // Primary store - contains the first value | 49 HashMapListElement* array_; // Primary store - contains the first value |
48 // with a given hash. Colliding elements are stored in linked lists. | 50 // with a given hash. Colliding elements are stored in linked lists. |
49 HashMapListElement* lists_; // The linked lists containing hash collisions. | 51 HashMapListElement* lists_; // The linked lists containing hash collisions. |
50 intptr_t free_list_head_; // Unused elements in lists_ are on the free list. | 52 intptr_t free_list_head_; // Unused elements in lists_ are on the free list. |
51 | |
52 DISALLOW_COPY_AND_ASSIGN(DirectChainedHashMap); | |
53 }; | 53 }; |
54 | 54 |
55 | 55 |
56 template <typename T> | 56 template <typename T> |
57 T DirectChainedHashMap<T>::Lookup(T value) const { | 57 T DirectChainedHashMap<T>::Lookup(T value) const { |
58 uword hash = static_cast<uword>(value->Hashcode()); | 58 uword hash = static_cast<uword>(value->Hashcode()); |
59 uword pos = Bound(hash); | 59 uword pos = Bound(hash); |
60 if (array_[pos].value != NULL) { | 60 if (array_[pos].value != NULL) { |
61 if (array_[pos].value->Equals(value)) return array_[pos].value; | 61 if (array_[pos].value->Equals(value)) return array_[pos].value; |
62 intptr_t next = array_[pos].next; | 62 intptr_t next = array_[pos].next; |
63 while (next != kNil) { | 63 while (next != kNil) { |
64 if (lists_[next].value->Equals(value)) return lists_[next].value; | 64 if (lists_[next].value->Equals(value)) return lists_[next].value; |
65 next = lists_[next].next; | 65 next = lists_[next].next; |
66 } | 66 } |
67 } | 67 } |
68 return NULL; | 68 return NULL; |
69 } | 69 } |
70 | 70 |
71 | 71 |
72 template <typename T> | 72 template <typename T> |
| 73 DirectChainedHashMap<T>::DirectChainedHashMap(const DirectChainedHashMap& other) |
| 74 : array_size_(other.array_size_), |
| 75 lists_size_(other.lists_size_), |
| 76 count_(other.count_), |
| 77 array_(Isolate::Current()->current_zone()-> |
| 78 Alloc<HashMapListElement>(other.array_size_)), |
| 79 lists_(Isolate::Current()->current_zone()-> |
| 80 Alloc<HashMapListElement>(other.lists_size_)), |
| 81 free_list_head_(other.free_list_head_) { |
| 82 memmove(array_, other.array_, array_size_ * sizeof(HashMapListElement)); |
| 83 memmove(lists_, other.lists_, lists_size_ * sizeof(HashMapListElement)); |
| 84 } |
| 85 |
| 86 |
| 87 template <typename T> |
73 void DirectChainedHashMap<T>::Resize(intptr_t new_size) { | 88 void DirectChainedHashMap<T>::Resize(intptr_t new_size) { |
74 ASSERT(new_size > count_); | 89 ASSERT(new_size > count_); |
75 // Hashing the values into the new array has no more collisions than in the | 90 // Hashing the values into the new array has no more collisions than in the |
76 // old hash map, so we can use the existing lists_ array, if we are careful. | 91 // old hash map, so we can use the existing lists_ array, if we are careful. |
77 | 92 |
78 // Make sure we have at least one free element. | 93 // Make sure we have at least one free element. |
79 if (free_list_head_ == kNil) { | 94 if (free_list_head_ == kNil) { |
80 ResizeLists(lists_size_ << 1); | 95 ResizeLists(lists_size_ << 1); |
81 } | 96 } |
82 | 97 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 lists_[new_element_pos].value = value; | 175 lists_[new_element_pos].value = value; |
161 lists_[new_element_pos].next = array_[pos].next; | 176 lists_[new_element_pos].next = array_[pos].next; |
162 ASSERT(array_[pos].next == kNil || lists_[array_[pos].next].value != NULL); | 177 ASSERT(array_[pos].next == kNil || lists_[array_[pos].next].value != NULL); |
163 array_[pos].next = new_element_pos; | 178 array_[pos].next = new_element_pos; |
164 } | 179 } |
165 } | 180 } |
166 | 181 |
167 } // namespace dart | 182 } // namespace dart |
168 | 183 |
169 #endif // VM_HASH_MAP_H_ | 184 #endif // VM_HASH_MAP_H_ |
OLD | NEW |