| 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 'isolate' for handle allocation. 'Release' must be called at the end | 88 // Uses 'zone' for handle allocation. 'Release' must be called at the end |
| 89 // to obtain the final table after potential growth/shrinkage. | 89 // to obtain the final table after potential growth/shrinkage. |
| 90 HashTable(Isolate* isolate, RawArray* data) | 90 HashTable(Zone* zone, RawArray* data) |
| 91 : isolate_(isolate), | 91 : zone_(zone), |
| 92 key_handle_(Object::Handle(isolate_)), | 92 key_handle_(Object::Handle(zone_)), |
| 93 smi_handle_(Smi::Handle(isolate_)), | 93 smi_handle_(Smi::Handle(zone_)), |
| 94 data_(&Array::Handle(isolate_, data)), | 94 data_(&Array::Handle(zone_, data)), |
| 95 released_data_(NULL) {} | 95 released_data_(NULL) {} |
| 96 // Like above, except uses current isolate. | 96 // Like above, except uses current zone. |
| 97 explicit HashTable(RawArray* data) | 97 explicit HashTable(RawArray* data) |
| 98 : isolate_(Isolate::Current()), | 98 : zone_(Thread::Current()->zone()), |
| 99 key_handle_(Object::Handle(isolate_)), | 99 key_handle_(Object::Handle(zone_)), |
| 100 smi_handle_(Smi::Handle(isolate_)), | 100 smi_handle_(Smi::Handle(zone_)), |
| 101 data_(&Array::Handle(isolate_, data)), | 101 data_(&Array::Handle(zone_, data)), |
| 102 released_data_(NULL) {} | 102 released_data_(NULL) {} |
| 103 | 103 |
| 104 // 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 |
| 105 // destroyed. | 105 // destroyed. |
| 106 Array& Release() { | 106 Array& Release() { |
| 107 ASSERT(data_ != NULL); | 107 ASSERT(data_ != NULL); |
| 108 ASSERT(released_data_ == NULL); | 108 ASSERT(released_data_ == NULL); |
| 109 // Ensure that no methods are called after 'Release'. | 109 // Ensure that no methods are called after 'Release'. |
| 110 released_data_ = data_; | 110 released_data_ = data_; |
| 111 data_ = NULL; | 111 data_ = NULL; |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 289 | 289 |
| 290 RawObject* InternalGetKey(intptr_t entry) const { | 290 RawObject* InternalGetKey(intptr_t entry) const { |
| 291 return data_->At(KeyIndex(entry)); | 291 return data_->At(KeyIndex(entry)); |
| 292 } | 292 } |
| 293 | 293 |
| 294 void InternalSetKey(intptr_t entry, const Object& key) const { | 294 void InternalSetKey(intptr_t entry, const Object& key) const { |
| 295 data_->SetAt(KeyIndex(entry), key); | 295 data_->SetAt(KeyIndex(entry), key); |
| 296 } | 296 } |
| 297 | 297 |
| 298 intptr_t GetSmiValueAt(intptr_t index) const { | 298 intptr_t GetSmiValueAt(intptr_t index) const { |
| 299 ASSERT(Object::Handle(isolate(), data_->At(index)).IsSmi()); | 299 ASSERT(Object::Handle(zone(), data_->At(index)).IsSmi()); |
| 300 return Smi::Value(Smi::RawCast(data_->At(index))); | 300 return Smi::Value(Smi::RawCast(data_->At(index))); |
| 301 } | 301 } |
| 302 | 302 |
| 303 void SetSmiValueAt(intptr_t index, intptr_t value) const { | 303 void SetSmiValueAt(intptr_t index, intptr_t value) const { |
| 304 smi_handle_ = Smi::New(value); | 304 smi_handle_ = Smi::New(value); |
| 305 data_->SetAt(index, smi_handle_); | 305 data_->SetAt(index, smi_handle_); |
| 306 } | 306 } |
| 307 | 307 |
| 308 void AdjustSmiValueAt(intptr_t index, intptr_t delta) const { | 308 void AdjustSmiValueAt(intptr_t index, intptr_t delta) const { |
| 309 SetSmiValueAt(index, (GetSmiValueAt(index) + delta)); | 309 SetSmiValueAt(index, (GetSmiValueAt(index) + delta)); |
| 310 } | 310 } |
| 311 | 311 |
| 312 Isolate* isolate() const { return isolate_; } | 312 Zone* zone() const { return zone_; } |
| 313 | 313 |
| 314 Isolate* isolate_; | 314 Zone* zone_; |
| 315 Object& key_handle_; | 315 Object& key_handle_; |
| 316 Smi& smi_handle_; | 316 Smi& smi_handle_; |
| 317 // Exactly one of these is non-NULL, depending on whether Release was called. | 317 // Exactly one of these is non-NULL, depending on whether Release was called. |
| 318 Array* data_; | 318 Array* data_; |
| 319 Array* released_data_; | 319 Array* released_data_; |
| 320 | 320 |
| 321 friend class HashTables; | 321 friend class HashTables; |
| 322 }; | 322 }; |
| 323 | 323 |
| 324 | 324 |
| 325 // Table with unspecified iteration order. No payload overhead or metadata. | 325 // Table with unspecified iteration order. No payload overhead or metadata. |
| 326 template<typename KeyTraits, intptr_t kUserPayloadSize> | 326 template<typename KeyTraits, intptr_t kUserPayloadSize> |
| 327 class UnorderedHashTable : public HashTable<KeyTraits, kUserPayloadSize, 0> { | 327 class UnorderedHashTable : public HashTable<KeyTraits, kUserPayloadSize, 0> { |
| 328 public: | 328 public: |
| 329 typedef HashTable<KeyTraits, kUserPayloadSize, 0> BaseTable; | 329 typedef HashTable<KeyTraits, kUserPayloadSize, 0> BaseTable; |
| 330 static const intptr_t kPayloadSize = kUserPayloadSize; | 330 static const intptr_t kPayloadSize = kUserPayloadSize; |
| 331 explicit UnorderedHashTable(RawArray* data) : BaseTable(data) {} | 331 explicit UnorderedHashTable(RawArray* data) : BaseTable(data) {} |
| 332 UnorderedHashTable(Isolate* isolate, RawArray* data) | 332 UnorderedHashTable(Zone* zone, RawArray* data) |
| 333 : BaseTable(isolate, data) {} | 333 : BaseTable(zone, data) {} |
| 334 // Note: Does not check for concurrent modification. | 334 // Note: Does not check for concurrent modification. |
| 335 class Iterator { | 335 class Iterator { |
| 336 public: | 336 public: |
| 337 explicit Iterator(const UnorderedHashTable* table) | 337 explicit Iterator(const UnorderedHashTable* table) |
| 338 : table_(table), entry_(-1) {} | 338 : table_(table), entry_(-1) {} |
| 339 bool MoveNext() { | 339 bool MoveNext() { |
| 340 while (entry_ < (table_->NumEntries() - 1)) { | 340 while (entry_ < (table_->NumEntries() - 1)) { |
| 341 ++entry_; | 341 ++entry_; |
| 342 if (table_->IsOccupied(entry_)) { | 342 if (table_->IsOccupied(entry_)) { |
| 343 return true; | 343 return true; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 360 | 360 |
| 361 // Table with insertion order, using one payload component for the enumeration | 361 // Table with insertion order, using one payload component for the enumeration |
| 362 // index, and one metadata element for the next enumeration index. | 362 // index, and one metadata element for the next enumeration index. |
| 363 template<typename KeyTraits, intptr_t kUserPayloadSize> | 363 template<typename KeyTraits, intptr_t kUserPayloadSize> |
| 364 class EnumIndexHashTable | 364 class EnumIndexHashTable |
| 365 : public HashTable<KeyTraits, kUserPayloadSize + 1, 1> { | 365 : public HashTable<KeyTraits, kUserPayloadSize + 1, 1> { |
| 366 public: | 366 public: |
| 367 typedef HashTable<KeyTraits, kUserPayloadSize + 1, 1> BaseTable; | 367 typedef HashTable<KeyTraits, kUserPayloadSize + 1, 1> BaseTable; |
| 368 static const intptr_t kPayloadSize = kUserPayloadSize; | 368 static const intptr_t kPayloadSize = kUserPayloadSize; |
| 369 static const intptr_t kNextEnumIndex = BaseTable::kMetaDataIndex; | 369 static const intptr_t kNextEnumIndex = BaseTable::kMetaDataIndex; |
| 370 EnumIndexHashTable(Isolate* isolate, RawArray* data) | 370 EnumIndexHashTable(Zone* zone, RawArray* data) |
| 371 : BaseTable(isolate, data) {} | 371 : BaseTable(zone, data) {} |
| 372 explicit EnumIndexHashTable(RawArray* data) : BaseTable(data) {} | 372 explicit EnumIndexHashTable(RawArray* data) : BaseTable(data) {} |
| 373 // Note: Does not check for concurrent modification. | 373 // Note: Does not check for concurrent modification. |
| 374 class Iterator { | 374 class Iterator { |
| 375 public: | 375 public: |
| 376 explicit Iterator(const EnumIndexHashTable* table) : index_(-1) { | 376 explicit Iterator(const EnumIndexHashTable* table) : index_(-1) { |
| 377 // TODO(koda): Use GrowableArray after adding stateful comparator support. | 377 // TODO(koda): Use GrowableArray after adding stateful comparator support. |
| 378 std::map<intptr_t, intptr_t> enum_to_entry; | 378 std::map<intptr_t, intptr_t> enum_to_entry; |
| 379 for (intptr_t i = 0; i < table->NumEntries(); ++i) { | 379 for (intptr_t i = 0; i < table->NumEntries(); ++i) { |
| 380 if (table->IsOccupied(i)) { | 380 if (table->IsOccupied(i)) { |
| 381 intptr_t enum_index = | 381 intptr_t enum_index = |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 496 } | 496 } |
| 497 return result.raw(); | 497 return result.raw(); |
| 498 } | 498 } |
| 499 }; | 499 }; |
| 500 | 500 |
| 501 | 501 |
| 502 template<typename BaseIterTable> | 502 template<typename BaseIterTable> |
| 503 class HashMap : public BaseIterTable { | 503 class HashMap : public BaseIterTable { |
| 504 public: | 504 public: |
| 505 explicit HashMap(RawArray* data) : BaseIterTable(data) {} | 505 explicit HashMap(RawArray* data) : BaseIterTable(data) {} |
| 506 HashMap(Isolate* isolate, RawArray* data) : BaseIterTable(isolate, data) {} | 506 HashMap(Zone* zone, RawArray* data) : BaseIterTable(zone, data) {} |
| 507 template<typename Key> | 507 template<typename Key> |
| 508 RawObject* GetOrNull(const Key& key, bool* present = NULL) const { | 508 RawObject* GetOrNull(const Key& key, bool* present = NULL) const { |
| 509 intptr_t entry = BaseIterTable::FindKey(key); | 509 intptr_t entry = BaseIterTable::FindKey(key); |
| 510 if (present != NULL) { | 510 if (present != NULL) { |
| 511 *present = (entry != -1); | 511 *present = (entry != -1); |
| 512 } | 512 } |
| 513 return (entry == -1) ? Object::null() : BaseIterTable::GetPayload(entry, 0); | 513 return (entry == -1) ? Object::null() : BaseIterTable::GetPayload(entry, 0); |
| 514 } | 514 } |
| 515 bool UpdateOrInsert(const Object& key, const Object& value) const { | 515 bool UpdateOrInsert(const Object& key, const Object& value) const { |
| 516 EnsureCapacity(); | 516 EnsureCapacity(); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 582 HashTables::EnsureLoadFactor(0.0, kMaxLoadFactor, *this); | 582 HashTables::EnsureLoadFactor(0.0, kMaxLoadFactor, *this); |
| 583 } | 583 } |
| 584 }; | 584 }; |
| 585 | 585 |
| 586 | 586 |
| 587 template<typename KeyTraits> | 587 template<typename KeyTraits> |
| 588 class UnorderedHashMap : public HashMap<UnorderedHashTable<KeyTraits, 1> > { | 588 class UnorderedHashMap : public HashMap<UnorderedHashTable<KeyTraits, 1> > { |
| 589 public: | 589 public: |
| 590 typedef HashMap<UnorderedHashTable<KeyTraits, 1> > BaseMap; | 590 typedef HashMap<UnorderedHashTable<KeyTraits, 1> > BaseMap; |
| 591 explicit UnorderedHashMap(RawArray* data) : BaseMap(data) {} | 591 explicit UnorderedHashMap(RawArray* data) : BaseMap(data) {} |
| 592 UnorderedHashMap(Isolate* isolate, RawArray* data) : BaseMap(isolate, data) {} | 592 UnorderedHashMap(Zone* zone, RawArray* data) : BaseMap(zone, data) {} |
| 593 }; | 593 }; |
| 594 | 594 |
| 595 | 595 |
| 596 template<typename KeyTraits> | 596 template<typename KeyTraits> |
| 597 class EnumIndexHashMap : public HashMap<EnumIndexHashTable<KeyTraits, 1> > { | 597 class EnumIndexHashMap : public HashMap<EnumIndexHashTable<KeyTraits, 1> > { |
| 598 public: | 598 public: |
| 599 typedef HashMap<EnumIndexHashTable<KeyTraits, 1> > BaseMap; | 599 typedef HashMap<EnumIndexHashTable<KeyTraits, 1> > BaseMap; |
| 600 explicit EnumIndexHashMap(RawArray* data) : BaseMap(data) {} | 600 explicit EnumIndexHashMap(RawArray* data) : BaseMap(data) {} |
| 601 EnumIndexHashMap(Isolate* isolate, RawArray* data) : BaseMap(isolate, data) {} | 601 EnumIndexHashMap(Zone* zone, RawArray* data) : BaseMap(zone, data) {} |
| 602 }; | 602 }; |
| 603 | 603 |
| 604 | 604 |
| 605 template<typename BaseIterTable> | 605 template<typename BaseIterTable> |
| 606 class HashSet : public BaseIterTable { | 606 class HashSet : public BaseIterTable { |
| 607 public: | 607 public: |
| 608 explicit HashSet(RawArray* data) : BaseIterTable(data) {} | 608 explicit HashSet(RawArray* data) : BaseIterTable(data) {} |
| 609 HashSet(Isolate* isolate, RawArray* data) : BaseIterTable(isolate, data) {} | 609 HashSet(Zone* zone, RawArray* data) : BaseIterTable(zone, data) {} |
| 610 bool Insert(const Object& key) { | 610 bool Insert(const Object& key) { |
| 611 EnsureCapacity(); | 611 EnsureCapacity(); |
| 612 intptr_t entry = -1; | 612 intptr_t entry = -1; |
| 613 bool present = BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry); | 613 bool present = BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry); |
| 614 if (!present) { | 614 if (!present) { |
| 615 BaseIterTable::InsertKey(entry, key); | 615 BaseIterTable::InsertKey(entry, key); |
| 616 } | 616 } |
| 617 return present; | 617 return present; |
| 618 } | 618 } |
| 619 | 619 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 676 HashTables::EnsureLoadFactor(0.0, kMaxLoadFactor, *this); | 676 HashTables::EnsureLoadFactor(0.0, kMaxLoadFactor, *this); |
| 677 } | 677 } |
| 678 }; | 678 }; |
| 679 | 679 |
| 680 | 680 |
| 681 template<typename KeyTraits> | 681 template<typename KeyTraits> |
| 682 class UnorderedHashSet : public HashSet<UnorderedHashTable<KeyTraits, 0> > { | 682 class UnorderedHashSet : public HashSet<UnorderedHashTable<KeyTraits, 0> > { |
| 683 public: | 683 public: |
| 684 typedef HashSet<UnorderedHashTable<KeyTraits, 0> > BaseSet; | 684 typedef HashSet<UnorderedHashTable<KeyTraits, 0> > BaseSet; |
| 685 explicit UnorderedHashSet(RawArray* data) : BaseSet(data) {} | 685 explicit UnorderedHashSet(RawArray* data) : BaseSet(data) {} |
| 686 UnorderedHashSet(Isolate* isolate, RawArray* data) : BaseSet(isolate, data) {} | 686 UnorderedHashSet(Zone* zone, RawArray* data) : BaseSet(zone, data) {} |
| 687 }; | 687 }; |
| 688 | 688 |
| 689 | 689 |
| 690 template<typename KeyTraits> | 690 template<typename KeyTraits> |
| 691 class EnumIndexHashSet : public HashSet<EnumIndexHashTable<KeyTraits, 0> > { | 691 class EnumIndexHashSet : public HashSet<EnumIndexHashTable<KeyTraits, 0> > { |
| 692 public: | 692 public: |
| 693 typedef HashSet<EnumIndexHashTable<KeyTraits, 0> > BaseSet; | 693 typedef HashSet<EnumIndexHashTable<KeyTraits, 0> > BaseSet; |
| 694 explicit EnumIndexHashSet(RawArray* data) : BaseSet(data) {} | 694 explicit EnumIndexHashSet(RawArray* data) : BaseSet(data) {} |
| 695 EnumIndexHashSet(Isolate* isolate, RawArray* data) : BaseSet(isolate, data) {} | 695 EnumIndexHashSet(Zone* zone, RawArray* data) : BaseSet(zone, data) {} |
| 696 }; | 696 }; |
| 697 | 697 |
| 698 } // namespace dart | 698 } // namespace dart |
| 699 | 699 |
| 700 #endif // VM_HASH_TABLE_H_ | 700 #endif // VM_HASH_TABLE_H_ |
| OLD | NEW |