OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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_TABLE_H_ | 5 #ifndef VM_HASH_TABLE_H_ |
6 #define VM_HASH_TABLE_H_ | 6 #define VM_HASH_TABLE_H_ |
7 | 7 |
8 // Temporarily used when sorting the indices in EnumIndexHashTable. | 8 // Temporarily used when sorting the indices in EnumIndexHashTable. |
9 // TODO(koda): Remove these dependencies before using in production. | 9 // TODO(koda): Remove these dependencies before using in production. |
10 #include <map> | 10 #include <map> |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 // Parameters | 78 // Parameters |
79 // KeyTraits: defines static methods | 79 // KeyTraits: defines static methods |
80 // bool IsMatch(const Key& key, const Object& obj) and | 80 // bool IsMatch(const Key& key, const Object& obj) and |
81 // uword Hash(const Key& key) for any number of desired lookup key types. | 81 // uword Hash(const Key& key) for any number of desired lookup key types. |
82 // kPayloadSize: number of components of the payload in each entry. | 82 // kPayloadSize: number of components of the payload in each entry. |
83 // kMetaDataSize: number of elements reserved (e.g., for iteration order data). | 83 // kMetaDataSize: number of elements reserved (e.g., for iteration order data). |
84 template<typename KeyTraits, intptr_t kPayloadSize, intptr_t kMetaDataSize> | 84 template<typename KeyTraits, intptr_t kPayloadSize, intptr_t kMetaDataSize> |
85 class HashTable : public ValueObject { | 85 class HashTable : public ValueObject { |
86 public: | 86 public: |
87 typedef KeyTraits Traits; | 87 typedef KeyTraits Traits; |
| 88 // Uses the passed in handles for all handle operations. |
| 89 // 'Release' must be called at the end to obtain the final table |
| 90 // after potential growth/shrinkage. |
| 91 HashTable(Object* key, Smi* index, Array* data) |
| 92 : key_handle_(key), |
| 93 smi_handle_(index), |
| 94 data_(data), |
| 95 released_data_(NULL) {} |
88 // Uses 'zone' for handle allocation. 'Release' must be called at the end | 96 // Uses 'zone' for handle allocation. 'Release' must be called at the end |
89 // to obtain the final table after potential growth/shrinkage. | 97 // to obtain the final table after potential growth/shrinkage. |
90 HashTable(Zone* zone, RawArray* data) | 98 HashTable(Zone* zone, RawArray* data) |
91 : zone_(zone), | 99 : key_handle_(&Object::Handle(zone)), |
92 key_handle_(Object::Handle(zone_)), | 100 smi_handle_(&Smi::Handle(zone)), |
93 smi_handle_(Smi::Handle(zone_)), | 101 data_(&Array::Handle(zone, data)), |
94 data_(&Array::Handle(zone_, data)), | |
95 released_data_(NULL) {} | 102 released_data_(NULL) {} |
96 // Like above, except uses current zone. | |
97 explicit HashTable(RawArray* data) | |
98 : zone_(Thread::Current()->zone()), | |
99 key_handle_(Object::Handle(zone_)), | |
100 smi_handle_(Smi::Handle(zone_)), | |
101 data_(&Array::Handle(zone_, data)), | |
102 released_data_(NULL) { | |
103 ASSERT(!data_->IsNull()); | |
104 } | |
105 | 103 |
106 // Returns the final table. The handle is cleared when this HashTable is | 104 // Returns the final table. The handle is cleared when this HashTable is |
107 // destroyed. | 105 // destroyed. |
108 Array& Release() { | 106 Array& Release() { |
109 ASSERT(data_ != NULL); | 107 ASSERT(data_ != NULL); |
110 ASSERT(released_data_ == NULL); | 108 ASSERT(released_data_ == NULL); |
111 // Ensure that no methods are called after 'Release'. | 109 // Ensure that no methods are called after 'Release'. |
112 released_data_ = data_; | 110 released_data_ = data_; |
113 data_ = NULL; | 111 data_ = NULL; |
114 return *released_data_; | 112 return *released_data_; |
(...skipping 12 matching lines...) Expand all Loading... |
127 static intptr_t ArrayLengthForNumOccupied(intptr_t num_occupied) { | 125 static intptr_t ArrayLengthForNumOccupied(intptr_t num_occupied) { |
128 // The current invariant requires at least one unoccupied entry. | 126 // The current invariant requires at least one unoccupied entry. |
129 // TODO(koda): Adjust if moving to quadratic probing. | 127 // TODO(koda): Adjust if moving to quadratic probing. |
130 intptr_t num_entries = num_occupied + 1; | 128 intptr_t num_entries = num_occupied + 1; |
131 return kFirstKeyIndex + (kEntrySize * num_entries); | 129 return kFirstKeyIndex + (kEntrySize * num_entries); |
132 } | 130 } |
133 | 131 |
134 // Initializes an empty table. | 132 // Initializes an empty table. |
135 void Initialize() const { | 133 void Initialize() const { |
136 ASSERT(data_->Length() >= ArrayLengthForNumOccupied(0)); | 134 ASSERT(data_->Length() >= ArrayLengthForNumOccupied(0)); |
137 smi_handle_ = Smi::New(0); | 135 *smi_handle_ = Smi::New(0); |
138 data_->SetAt(kOccupiedEntriesIndex, smi_handle_); | 136 data_->SetAt(kOccupiedEntriesIndex, *smi_handle_); |
139 data_->SetAt(kDeletedEntriesIndex, smi_handle_); | 137 data_->SetAt(kDeletedEntriesIndex, *smi_handle_); |
140 | 138 |
141 NOT_IN_PRODUCT( | 139 NOT_IN_PRODUCT( |
142 data_->SetAt(kNumGrowsIndex, smi_handle_); | 140 data_->SetAt(kNumGrowsIndex, *smi_handle_); |
143 data_->SetAt(kNumLT5LookupsIndex, smi_handle_); | 141 data_->SetAt(kNumLT5LookupsIndex, *smi_handle_); |
144 data_->SetAt(kNumLT25LookupsIndex, smi_handle_); | 142 data_->SetAt(kNumLT25LookupsIndex, *smi_handle_); |
145 data_->SetAt(kNumGT25LookupsIndex, smi_handle_); | 143 data_->SetAt(kNumGT25LookupsIndex, *smi_handle_); |
146 ) // !PRODUCT | 144 ) // !PRODUCT |
147 | 145 |
148 for (intptr_t i = kHeaderSize; i < data_->Length(); ++i) { | 146 for (intptr_t i = kHeaderSize; i < data_->Length(); ++i) { |
149 data_->SetAt(i, Object::sentinel()); | 147 data_->SetAt(i, Object::sentinel()); |
150 } | 148 } |
151 } | 149 } |
152 | 150 |
153 // Returns whether 'key' matches any key in the table. | 151 // Returns whether 'key' matches any key in the table. |
154 template<typename Key> | 152 template<typename Key> |
155 bool ContainsKey(const Key& key) const { | 153 bool ContainsKey(const Key& key) const { |
156 return FindKey(key) != -1; | 154 return FindKey(key) != -1; |
157 } | 155 } |
158 | 156 |
159 // Returns the entry that matches 'key', or -1 if none exists. | 157 // Returns the entry that matches 'key', or -1 if none exists. |
160 template<typename Key> | 158 template<typename Key> |
161 intptr_t FindKey(const Key& key) const { | 159 intptr_t FindKey(const Key& key) const { |
162 const intptr_t num_entries = NumEntries(); | 160 const intptr_t num_entries = NumEntries(); |
163 ASSERT(NumOccupied() < num_entries); | 161 ASSERT(NumOccupied() < num_entries); |
164 // TODO(koda): Add salt. | 162 // TODO(koda): Add salt. |
165 NOT_IN_PRODUCT(intptr_t collisions = 0;) | 163 NOT_IN_PRODUCT(intptr_t collisions = 0;) |
166 uword hash = KeyTraits::Hash(key); | 164 uword hash = KeyTraits::Hash(key); |
167 intptr_t probe = hash % num_entries; | 165 intptr_t probe = hash % num_entries; |
168 // TODO(koda): Consider quadratic probing. | 166 // TODO(koda): Consider quadratic probing. |
169 while (true) { | 167 while (true) { |
170 if (IsUnused(probe)) { | 168 if (IsUnused(probe)) { |
171 NOT_IN_PRODUCT(UpdateCollisions(collisions);) | 169 NOT_IN_PRODUCT(UpdateCollisions(collisions);) |
172 return -1; | 170 return -1; |
173 } else if (!IsDeleted(probe)) { | 171 } else if (!IsDeleted(probe)) { |
174 key_handle_ = GetKey(probe); | 172 *key_handle_ = GetKey(probe); |
175 if (KeyTraits::IsMatch(key, key_handle_)) { | 173 if (KeyTraits::IsMatch(key, *key_handle_)) { |
176 NOT_IN_PRODUCT(UpdateCollisions(collisions);) | 174 NOT_IN_PRODUCT(UpdateCollisions(collisions);) |
177 return probe; | 175 return probe; |
178 } | 176 } |
179 NOT_IN_PRODUCT(collisions += 1;) | 177 NOT_IN_PRODUCT(collisions += 1;) |
180 } | 178 } |
181 // Advance probe. | 179 // Advance probe. |
182 probe++; | 180 probe++; |
183 probe = (probe == num_entries) ? 0 : probe; | 181 probe = (probe == num_entries) ? 0 : probe; |
184 } | 182 } |
185 UNREACHABLE(); | 183 UNREACHABLE(); |
(...skipping 17 matching lines...) Expand all Loading... |
203 while (true) { | 201 while (true) { |
204 if (IsUnused(probe)) { | 202 if (IsUnused(probe)) { |
205 *entry = (deleted != -1) ? deleted : probe; | 203 *entry = (deleted != -1) ? deleted : probe; |
206 NOT_IN_PRODUCT(UpdateCollisions(collisions);) | 204 NOT_IN_PRODUCT(UpdateCollisions(collisions);) |
207 return false; | 205 return false; |
208 } else if (IsDeleted(probe)) { | 206 } else if (IsDeleted(probe)) { |
209 if (deleted == -1) { | 207 if (deleted == -1) { |
210 deleted = probe; | 208 deleted = probe; |
211 } | 209 } |
212 } else { | 210 } else { |
213 key_handle_ = GetKey(probe); | 211 *key_handle_ = GetKey(probe); |
214 if (KeyTraits::IsMatch(key, key_handle_)) { | 212 if (KeyTraits::IsMatch(key, *key_handle_)) { |
215 *entry = probe; | 213 *entry = probe; |
216 NOT_IN_PRODUCT(UpdateCollisions(collisions);) | 214 NOT_IN_PRODUCT(UpdateCollisions(collisions);) |
217 return true; | 215 return true; |
218 } | 216 } |
219 NOT_IN_PRODUCT(collisions += 1;) | 217 NOT_IN_PRODUCT(collisions += 1;) |
220 } | 218 } |
221 // Advance probe. | 219 // Advance probe. |
222 probe++; | 220 probe++; |
223 probe = (probe == num_entries) ? 0 : probe; | 221 probe = (probe == num_entries) ? 0 : probe; |
224 } | 222 } |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 intptr_t NumUnused() const { | 280 intptr_t NumUnused() const { |
283 return NumEntries() - NumOccupied() - NumDeleted(); | 281 return NumEntries() - NumOccupied() - NumDeleted(); |
284 } | 282 } |
285 intptr_t NumOccupied() const { | 283 intptr_t NumOccupied() const { |
286 return GetSmiValueAt(kOccupiedEntriesIndex); | 284 return GetSmiValueAt(kOccupiedEntriesIndex); |
287 } | 285 } |
288 intptr_t NumDeleted() const { | 286 intptr_t NumDeleted() const { |
289 return GetSmiValueAt(kDeletedEntriesIndex); | 287 return GetSmiValueAt(kDeletedEntriesIndex); |
290 } | 288 } |
291 Object& KeyHandle() const { | 289 Object& KeyHandle() const { |
292 return key_handle_; | 290 return *key_handle_; |
293 } | 291 } |
294 Smi& SmiHandle() const { | 292 Smi& SmiHandle() const { |
295 return smi_handle_; | 293 return *smi_handle_; |
296 } | 294 } |
297 | 295 |
298 NOT_IN_PRODUCT( | 296 NOT_IN_PRODUCT( |
299 intptr_t NumGrows() const { | 297 intptr_t NumGrows() const { |
300 return GetSmiValueAt(kNumGrowsIndex); | 298 return GetSmiValueAt(kNumGrowsIndex); |
301 } | 299 } |
302 intptr_t NumLT5Collisions() const { | 300 intptr_t NumLT5Collisions() const { |
303 return GetSmiValueAt(kNumLT5LookupsIndex); | 301 return GetSmiValueAt(kNumLT5LookupsIndex); |
304 } | 302 } |
305 intptr_t NumLT25Collisions() const { | 303 intptr_t NumLT25Collisions() const { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
369 RawObject* InternalGetKey(intptr_t entry) const { | 367 RawObject* InternalGetKey(intptr_t entry) const { |
370 return data_->At(KeyIndex(entry)); | 368 return data_->At(KeyIndex(entry)); |
371 } | 369 } |
372 | 370 |
373 void InternalSetKey(intptr_t entry, const Object& key) const { | 371 void InternalSetKey(intptr_t entry, const Object& key) const { |
374 data_->SetAt(KeyIndex(entry), key); | 372 data_->SetAt(KeyIndex(entry), key); |
375 } | 373 } |
376 | 374 |
377 intptr_t GetSmiValueAt(intptr_t index) const { | 375 intptr_t GetSmiValueAt(intptr_t index) const { |
378 ASSERT(!data_->IsNull()); | 376 ASSERT(!data_->IsNull()); |
379 ASSERT(Object::Handle(zone(), data_->At(index)).IsSmi()); | 377 ASSERT(!data_->At(index)->IsHeapObject()); |
380 return Smi::Value(Smi::RawCast(data_->At(index))); | 378 return Smi::Value(Smi::RawCast(data_->At(index))); |
381 } | 379 } |
382 | 380 |
383 void SetSmiValueAt(intptr_t index, intptr_t value) const { | 381 void SetSmiValueAt(intptr_t index, intptr_t value) const { |
384 smi_handle_ = Smi::New(value); | 382 *smi_handle_ = Smi::New(value); |
385 data_->SetAt(index, smi_handle_); | 383 data_->SetAt(index, *smi_handle_); |
386 } | 384 } |
387 | 385 |
388 void AdjustSmiValueAt(intptr_t index, intptr_t delta) const { | 386 void AdjustSmiValueAt(intptr_t index, intptr_t delta) const { |
389 SetSmiValueAt(index, (GetSmiValueAt(index) + delta)); | 387 SetSmiValueAt(index, (GetSmiValueAt(index) + delta)); |
390 } | 388 } |
391 | 389 |
392 Zone* zone() const { return zone_; } | 390 Object* key_handle_; |
393 | 391 Smi* smi_handle_; |
394 Zone* zone_; | |
395 Object& key_handle_; | |
396 Smi& smi_handle_; | |
397 // Exactly one of these is non-NULL, depending on whether Release was called. | 392 // Exactly one of these is non-NULL, depending on whether Release was called. |
398 Array* data_; | 393 Array* data_; |
399 Array* released_data_; | 394 Array* released_data_; |
400 | 395 |
401 friend class HashTables; | 396 friend class HashTables; |
402 }; | 397 }; |
403 | 398 |
404 | 399 |
405 // Table with unspecified iteration order. No payload overhead or metadata. | 400 // Table with unspecified iteration order. No payload overhead or metadata. |
406 template<typename KeyTraits, intptr_t kUserPayloadSize> | 401 template<typename KeyTraits, intptr_t kUserPayloadSize> |
407 class UnorderedHashTable : public HashTable<KeyTraits, kUserPayloadSize, 0> { | 402 class UnorderedHashTable : public HashTable<KeyTraits, kUserPayloadSize, 0> { |
408 public: | 403 public: |
409 typedef HashTable<KeyTraits, kUserPayloadSize, 0> BaseTable; | 404 typedef HashTable<KeyTraits, kUserPayloadSize, 0> BaseTable; |
410 static const intptr_t kPayloadSize = kUserPayloadSize; | 405 static const intptr_t kPayloadSize = kUserPayloadSize; |
411 explicit UnorderedHashTable(RawArray* data) : BaseTable(data) {} | 406 explicit UnorderedHashTable(RawArray* data) |
412 UnorderedHashTable(Zone* zone, RawArray* data) | 407 : BaseTable(Thread::Current()->zone(), data) {} |
413 : BaseTable(zone, data) {} | 408 UnorderedHashTable(Zone* zone, RawArray* data) : BaseTable(zone, data) {} |
| 409 UnorderedHashTable(Object* key, Smi* value, Array* data) |
| 410 : BaseTable(key, value, data) {} |
414 // Note: Does not check for concurrent modification. | 411 // Note: Does not check for concurrent modification. |
415 class Iterator { | 412 class Iterator { |
416 public: | 413 public: |
417 explicit Iterator(const UnorderedHashTable* table) | 414 explicit Iterator(const UnorderedHashTable* table) |
418 : table_(table), entry_(-1) {} | 415 : table_(table), entry_(-1) {} |
419 bool MoveNext() { | 416 bool MoveNext() { |
420 while (entry_ < (table_->NumEntries() - 1)) { | 417 while (entry_ < (table_->NumEntries() - 1)) { |
421 ++entry_; | 418 ++entry_; |
422 if (table_->IsOccupied(entry_)) { | 419 if (table_->IsOccupied(entry_)) { |
423 return true; | 420 return true; |
(...skipping 16 matching lines...) Expand all Loading... |
440 | 437 |
441 // Table with insertion order, using one payload component for the enumeration | 438 // Table with insertion order, using one payload component for the enumeration |
442 // index, and one metadata element for the next enumeration index. | 439 // index, and one metadata element for the next enumeration index. |
443 template<typename KeyTraits, intptr_t kUserPayloadSize> | 440 template<typename KeyTraits, intptr_t kUserPayloadSize> |
444 class EnumIndexHashTable | 441 class EnumIndexHashTable |
445 : public HashTable<KeyTraits, kUserPayloadSize + 1, 1> { | 442 : public HashTable<KeyTraits, kUserPayloadSize + 1, 1> { |
446 public: | 443 public: |
447 typedef HashTable<KeyTraits, kUserPayloadSize + 1, 1> BaseTable; | 444 typedef HashTable<KeyTraits, kUserPayloadSize + 1, 1> BaseTable; |
448 static const intptr_t kPayloadSize = kUserPayloadSize; | 445 static const intptr_t kPayloadSize = kUserPayloadSize; |
449 static const intptr_t kNextEnumIndex = BaseTable::kMetaDataIndex; | 446 static const intptr_t kNextEnumIndex = BaseTable::kMetaDataIndex; |
| 447 EnumIndexHashTable(Object* key, Smi* value, Array* data) |
| 448 : BaseTable(key, value, data) {} |
450 EnumIndexHashTable(Zone* zone, RawArray* data) | 449 EnumIndexHashTable(Zone* zone, RawArray* data) |
451 : BaseTable(zone, data) {} | 450 : BaseTable(zone, data) {} |
452 explicit EnumIndexHashTable(RawArray* data) : BaseTable(data) {} | 451 explicit EnumIndexHashTable(RawArray* data) |
| 452 : BaseTable(Thread::Current()->zone(), data) {} |
453 // Note: Does not check for concurrent modification. | 453 // Note: Does not check for concurrent modification. |
454 class Iterator { | 454 class Iterator { |
455 public: | 455 public: |
456 explicit Iterator(const EnumIndexHashTable* table) : index_(-1) { | 456 explicit Iterator(const EnumIndexHashTable* table) : index_(-1) { |
457 // TODO(koda): Use GrowableArray after adding stateful comparator support. | 457 // TODO(koda): Use GrowableArray after adding stateful comparator support. |
458 std::map<intptr_t, intptr_t> enum_to_entry; | 458 std::map<intptr_t, intptr_t> enum_to_entry; |
459 for (intptr_t i = 0; i < table->NumEntries(); ++i) { | 459 for (intptr_t i = 0; i < table->NumEntries(); ++i) { |
460 if (table->IsOccupied(i)) { | 460 if (table->IsOccupied(i)) { |
461 intptr_t enum_index = | 461 intptr_t enum_index = |
462 table->GetSmiValueAt(table->PayloadIndex(i, kPayloadSize)); | 462 table->GetSmiValueAt(table->PayloadIndex(i, kPayloadSize)); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
502 // No extra book-keeping needed for DeleteEntry. | 502 // No extra book-keeping needed for DeleteEntry. |
503 }; | 503 }; |
504 | 504 |
505 | 505 |
506 class HashTables : public AllStatic { | 506 class HashTables : public AllStatic { |
507 public: | 507 public: |
508 // Allocates and initializes a table. | 508 // Allocates and initializes a table. |
509 template<typename Table> | 509 template<typename Table> |
510 static RawArray* New(intptr_t initial_capacity, | 510 static RawArray* New(intptr_t initial_capacity, |
511 Heap::Space space = Heap::kNew) { | 511 Heap::Space space = Heap::kNew) { |
512 Table table(Array::New( | 512 Table table(Thread::Current()->zone(), Array::New( |
513 Table::ArrayLengthForNumOccupied(initial_capacity), space)); | 513 Table::ArrayLengthForNumOccupied(initial_capacity), space)); |
514 table.Initialize(); | 514 table.Initialize(); |
515 return table.Release().raw(); | 515 return table.Release().raw(); |
516 } | 516 } |
517 | 517 |
518 template<typename Table> | 518 template<typename Table> |
519 static RawArray* New(const Array& array) { | 519 static RawArray* New(const Array& array) { |
520 Table table(array.raw()); | 520 Table table(Thread::Current()->zone(), array.raw()); |
521 table.Initialize(); | 521 table.Initialize(); |
522 return table.Release().raw(); | 522 return table.Release().raw(); |
523 } | 523 } |
524 | 524 |
525 // Clears 'to' and inserts all elements from 'from', in iteration order. | 525 // Clears 'to' and inserts all elements from 'from', in iteration order. |
526 // The tables must have the same user payload size. | 526 // The tables must have the same user payload size. |
527 template<typename From, typename To> | 527 template<typename From, typename To> |
528 static void Copy(const From& from, const To& to) { | 528 static void Copy(const From& from, const To& to) { |
529 COMPILE_ASSERT(From::kPayloadSize == To::kPayloadSize); | 529 COMPILE_ASSERT(From::kPayloadSize == To::kPayloadSize); |
530 to.Initialize(); | 530 to.Initialize(); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
583 } | 583 } |
584 } | 584 } |
585 return result.raw(); | 585 return result.raw(); |
586 } | 586 } |
587 }; | 587 }; |
588 | 588 |
589 | 589 |
590 template<typename BaseIterTable> | 590 template<typename BaseIterTable> |
591 class HashMap : public BaseIterTable { | 591 class HashMap : public BaseIterTable { |
592 public: | 592 public: |
593 explicit HashMap(RawArray* data) : BaseIterTable(data) {} | 593 explicit HashMap(RawArray* data) |
| 594 : BaseIterTable(Thread::Current()->zone(), data) {} |
594 HashMap(Zone* zone, RawArray* data) : BaseIterTable(zone, data) {} | 595 HashMap(Zone* zone, RawArray* data) : BaseIterTable(zone, data) {} |
| 596 HashMap(Object* key, Smi* value, Array* data) |
| 597 : BaseIterTable(key, value, data) {} |
595 template<typename Key> | 598 template<typename Key> |
596 RawObject* GetOrNull(const Key& key, bool* present = NULL) const { | 599 RawObject* GetOrNull(const Key& key, bool* present = NULL) const { |
597 intptr_t entry = BaseIterTable::FindKey(key); | 600 intptr_t entry = BaseIterTable::FindKey(key); |
598 if (present != NULL) { | 601 if (present != NULL) { |
599 *present = (entry != -1); | 602 *present = (entry != -1); |
600 } | 603 } |
601 return (entry == -1) ? Object::null() : BaseIterTable::GetPayload(entry, 0); | 604 return (entry == -1) ? Object::null() : BaseIterTable::GetPayload(entry, 0); |
602 } | 605 } |
603 bool UpdateOrInsert(const Object& key, const Object& value) const { | 606 bool UpdateOrInsert(const Object& key, const Object& value) const { |
604 EnsureCapacity(); | 607 EnsureCapacity(); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
669 // We currently never shrink. | 672 // We currently never shrink. |
670 HashTables::EnsureLoadFactor(0.0, kMaxLoadFactor, *this); | 673 HashTables::EnsureLoadFactor(0.0, kMaxLoadFactor, *this); |
671 } | 674 } |
672 }; | 675 }; |
673 | 676 |
674 | 677 |
675 template<typename KeyTraits> | 678 template<typename KeyTraits> |
676 class UnorderedHashMap : public HashMap<UnorderedHashTable<KeyTraits, 1> > { | 679 class UnorderedHashMap : public HashMap<UnorderedHashTable<KeyTraits, 1> > { |
677 public: | 680 public: |
678 typedef HashMap<UnorderedHashTable<KeyTraits, 1> > BaseMap; | 681 typedef HashMap<UnorderedHashTable<KeyTraits, 1> > BaseMap; |
679 explicit UnorderedHashMap(RawArray* data) : BaseMap(data) {} | 682 explicit UnorderedHashMap(RawArray* data) |
| 683 : BaseMap(Thread::Current()->zone(), data) {} |
680 UnorderedHashMap(Zone* zone, RawArray* data) : BaseMap(zone, data) {} | 684 UnorderedHashMap(Zone* zone, RawArray* data) : BaseMap(zone, data) {} |
| 685 UnorderedHashMap(Object* key, Smi* value, Array* data) |
| 686 : BaseMap(key, value, data) {} |
681 }; | 687 }; |
682 | 688 |
683 | 689 |
684 template<typename KeyTraits> | 690 template<typename KeyTraits> |
685 class EnumIndexHashMap : public HashMap<EnumIndexHashTable<KeyTraits, 1> > { | 691 class EnumIndexHashMap : public HashMap<EnumIndexHashTable<KeyTraits, 1> > { |
686 public: | 692 public: |
687 typedef HashMap<EnumIndexHashTable<KeyTraits, 1> > BaseMap; | 693 typedef HashMap<EnumIndexHashTable<KeyTraits, 1> > BaseMap; |
688 explicit EnumIndexHashMap(RawArray* data) : BaseMap(data) {} | 694 explicit EnumIndexHashMap(RawArray* data) |
| 695 : BaseMap(Thread::Current()->zone(), data) {} |
689 EnumIndexHashMap(Zone* zone, RawArray* data) : BaseMap(zone, data) {} | 696 EnumIndexHashMap(Zone* zone, RawArray* data) : BaseMap(zone, data) {} |
| 697 EnumIndexHashMap(Object* key, Smi* value, Array* data) |
| 698 : BaseMap(key, value, data) {} |
690 }; | 699 }; |
691 | 700 |
692 | 701 |
693 template<typename BaseIterTable> | 702 template<typename BaseIterTable> |
694 class HashSet : public BaseIterTable { | 703 class HashSet : public BaseIterTable { |
695 public: | 704 public: |
696 explicit HashSet(RawArray* data) : BaseIterTable(data) {} | 705 explicit HashSet(RawArray* data) |
| 706 : BaseIterTable(Thread::Current()->zone(), data) {} |
697 HashSet(Zone* zone, RawArray* data) : BaseIterTable(zone, data) {} | 707 HashSet(Zone* zone, RawArray* data) : BaseIterTable(zone, data) {} |
| 708 HashSet(Object* key, Smi* value, Array* data) |
| 709 : BaseIterTable(key, value, data) {} |
698 bool Insert(const Object& key) { | 710 bool Insert(const Object& key) { |
699 EnsureCapacity(); | 711 EnsureCapacity(); |
700 intptr_t entry = -1; | 712 intptr_t entry = -1; |
701 bool present = BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry); | 713 bool present = BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry); |
702 if (!present) { | 714 if (!present) { |
703 BaseIterTable::InsertKey(entry, key); | 715 BaseIterTable::InsertKey(entry, key); |
704 } | 716 } |
705 return present; | 717 return present; |
706 } | 718 } |
707 | 719 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
763 // We currently never shrink. | 775 // We currently never shrink. |
764 HashTables::EnsureLoadFactor(0.0, kMaxLoadFactor, *this); | 776 HashTables::EnsureLoadFactor(0.0, kMaxLoadFactor, *this); |
765 } | 777 } |
766 }; | 778 }; |
767 | 779 |
768 | 780 |
769 template<typename KeyTraits> | 781 template<typename KeyTraits> |
770 class UnorderedHashSet : public HashSet<UnorderedHashTable<KeyTraits, 0> > { | 782 class UnorderedHashSet : public HashSet<UnorderedHashTable<KeyTraits, 0> > { |
771 public: | 783 public: |
772 typedef HashSet<UnorderedHashTable<KeyTraits, 0> > BaseSet; | 784 typedef HashSet<UnorderedHashTable<KeyTraits, 0> > BaseSet; |
773 explicit UnorderedHashSet(RawArray* data) : BaseSet(data) { | 785 explicit UnorderedHashSet(RawArray* data) |
| 786 : BaseSet(Thread::Current()->zone(), data) { |
774 ASSERT(data != Array::null()); | 787 ASSERT(data != Array::null()); |
775 } | 788 } |
776 UnorderedHashSet(Zone* zone, RawArray* data) : BaseSet(zone, data) {} | 789 UnorderedHashSet(Zone* zone, RawArray* data) : BaseSet(zone, data) {} |
| 790 UnorderedHashSet(Object* key, Smi* value, Array* data) |
| 791 : BaseSet(key, value, data) {} |
777 }; | 792 }; |
778 | 793 |
779 | 794 |
780 template<typename KeyTraits> | 795 template<typename KeyTraits> |
781 class EnumIndexHashSet : public HashSet<EnumIndexHashTable<KeyTraits, 0> > { | 796 class EnumIndexHashSet : public HashSet<EnumIndexHashTable<KeyTraits, 0> > { |
782 public: | 797 public: |
783 typedef HashSet<EnumIndexHashTable<KeyTraits, 0> > BaseSet; | 798 typedef HashSet<EnumIndexHashTable<KeyTraits, 0> > BaseSet; |
784 explicit EnumIndexHashSet(RawArray* data) : BaseSet(data) {} | 799 explicit EnumIndexHashSet(RawArray* data) |
| 800 : BaseSet(Thread::Current()->zone(), data) {} |
785 EnumIndexHashSet(Zone* zone, RawArray* data) : BaseSet(zone, data) {} | 801 EnumIndexHashSet(Zone* zone, RawArray* data) : BaseSet(zone, data) {} |
| 802 EnumIndexHashSet(Object* key, Smi* value, Array* data) |
| 803 : BaseSet(key, value, data) {} |
786 }; | 804 }; |
787 | 805 |
788 } // namespace dart | 806 } // namespace dart |
789 | 807 |
790 #endif // VM_HASH_TABLE_H_ | 808 #endif // VM_HASH_TABLE_H_ |
OLD | NEW |