| 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 RUNTIME_VM_HASH_TABLE_H_ | 5 #ifndef RUNTIME_VM_HASH_TABLE_H_ |
| 6 #define RUNTIME_VM_HASH_TABLE_H_ | 6 #define RUNTIME_VM_HASH_TABLE_H_ |
| 7 | 7 |
| 8 #include "platform/assert.h" | 8 #include "platform/assert.h" |
| 9 #include "vm/object.h" | 9 #include "vm/object.h" |
| 10 | 10 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 // | 48 // |
| 49 // If you *know* that no mutating operations were called, you can optimize: | 49 // If you *know* that no mutating operations were called, you can optimize: |
| 50 // ... | 50 // ... |
| 51 // obj ^= cache.GetOrNull(name); | 51 // obj ^= cache.GetOrNull(name); |
| 52 // ASSERT(cache.Release().raw() == get_foo_cache()); | 52 // ASSERT(cache.Release().raw() == get_foo_cache()); |
| 53 // | 53 // |
| 54 // TODO(koda): When exposing these to Dart code, document and assert that | 54 // TODO(koda): When exposing these to Dart code, document and assert that |
| 55 // KeyTraits methods must not run Dart code (since the C++ code doesn't check | 55 // KeyTraits methods must not run Dart code (since the C++ code doesn't check |
| 56 // for concurrent modification). | 56 // for concurrent modification). |
| 57 | 57 |
| 58 | |
| 59 // Open-addressing hash table template using a RawArray as backing storage. | 58 // Open-addressing hash table template using a RawArray as backing storage. |
| 60 // | 59 // |
| 61 // The elements of the array are partitioned into entries: | 60 // The elements of the array are partitioned into entries: |
| 62 // [ header | metadata | entry0 | entry1 | ... | entryN ] | 61 // [ header | metadata | entry0 | entry1 | ... | entryN ] |
| 63 // Each entry contains a key, followed by zero or more payload components, | 62 // Each entry contains a key, followed by zero or more payload components, |
| 64 // and has 3 possible states: unused, occupied, or deleted. | 63 // and has 3 possible states: unused, occupied, or deleted. |
| 65 // The header tracks the number of entries in each state. | 64 // The header tracks the number of entries in each state. |
| 66 // Any object except Object::sentinel() and Object::transition_sentinel() | 65 // Any object except Object::sentinel() and Object::transition_sentinel() |
| 67 // may be stored as a key. Any object may be stored in a payload. | 66 // may be stored as a key. Any object may be stored in a payload. |
| 68 // | 67 // |
| (...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 376 | 375 |
| 377 Object* key_handle_; | 376 Object* key_handle_; |
| 378 Smi* smi_handle_; | 377 Smi* smi_handle_; |
| 379 // Exactly one of these is non-NULL, depending on whether Release was called. | 378 // Exactly one of these is non-NULL, depending on whether Release was called. |
| 380 Array* data_; | 379 Array* data_; |
| 381 Array* released_data_; | 380 Array* released_data_; |
| 382 | 381 |
| 383 friend class HashTables; | 382 friend class HashTables; |
| 384 }; | 383 }; |
| 385 | 384 |
| 386 | |
| 387 // Table with unspecified iteration order. No payload overhead or metadata. | 385 // Table with unspecified iteration order. No payload overhead or metadata. |
| 388 template <typename KeyTraits, intptr_t kUserPayloadSize> | 386 template <typename KeyTraits, intptr_t kUserPayloadSize> |
| 389 class UnorderedHashTable : public HashTable<KeyTraits, kUserPayloadSize, 0> { | 387 class UnorderedHashTable : public HashTable<KeyTraits, kUserPayloadSize, 0> { |
| 390 public: | 388 public: |
| 391 typedef HashTable<KeyTraits, kUserPayloadSize, 0> BaseTable; | 389 typedef HashTable<KeyTraits, kUserPayloadSize, 0> BaseTable; |
| 392 static const intptr_t kPayloadSize = kUserPayloadSize; | 390 static const intptr_t kPayloadSize = kUserPayloadSize; |
| 393 explicit UnorderedHashTable(RawArray* data) | 391 explicit UnorderedHashTable(RawArray* data) |
| 394 : BaseTable(Thread::Current()->zone(), data) {} | 392 : BaseTable(Thread::Current()->zone(), data) {} |
| 395 UnorderedHashTable(Zone* zone, RawArray* data) : BaseTable(zone, data) {} | 393 UnorderedHashTable(Zone* zone, RawArray* data) : BaseTable(zone, data) {} |
| 396 UnorderedHashTable(Object* key, Smi* value, Array* data) | 394 UnorderedHashTable(Object* key, Smi* value, Array* data) |
| (...skipping 15 matching lines...) Expand all Loading... |
| 412 intptr_t Current() { return entry_; } | 410 intptr_t Current() { return entry_; } |
| 413 | 411 |
| 414 private: | 412 private: |
| 415 const UnorderedHashTable* table_; | 413 const UnorderedHashTable* table_; |
| 416 intptr_t entry_; | 414 intptr_t entry_; |
| 417 }; | 415 }; |
| 418 | 416 |
| 419 // No extra book-keeping needed for Initialize, InsertKey, DeleteEntry. | 417 // No extra book-keeping needed for Initialize, InsertKey, DeleteEntry. |
| 420 }; | 418 }; |
| 421 | 419 |
| 422 | |
| 423 class HashTables : public AllStatic { | 420 class HashTables : public AllStatic { |
| 424 public: | 421 public: |
| 425 // Allocates and initializes a table. | 422 // Allocates and initializes a table. |
| 426 template <typename Table> | 423 template <typename Table> |
| 427 static RawArray* New(intptr_t initial_capacity, | 424 static RawArray* New(intptr_t initial_capacity, |
| 428 Heap::Space space = Heap::kNew) { | 425 Heap::Space space = Heap::kNew) { |
| 429 Table table( | 426 Table table( |
| 430 Thread::Current()->zone(), | 427 Thread::Current()->zone(), |
| 431 Array::New(Table::ArrayLengthForNumOccupied(initial_capacity), space)); | 428 Array::New(Table::ArrayLengthForNumOccupied(initial_capacity), space)); |
| 432 table.Initialize(); | 429 table.Initialize(); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 496 for (intptr_t i = 0; i < Table::kPayloadSize; ++i) { | 493 for (intptr_t i = 0; i < Table::kPayloadSize; ++i) { |
| 497 obj = table.GetPayload(entry, i); | 494 obj = table.GetPayload(entry, i); |
| 498 result.SetAt(result_index++, obj); | 495 result.SetAt(result_index++, obj); |
| 499 } | 496 } |
| 500 } | 497 } |
| 501 } | 498 } |
| 502 return result.raw(); | 499 return result.raw(); |
| 503 } | 500 } |
| 504 }; | 501 }; |
| 505 | 502 |
| 506 | |
| 507 template <typename BaseIterTable> | 503 template <typename BaseIterTable> |
| 508 class HashMap : public BaseIterTable { | 504 class HashMap : public BaseIterTable { |
| 509 public: | 505 public: |
| 510 explicit HashMap(RawArray* data) | 506 explicit HashMap(RawArray* data) |
| 511 : BaseIterTable(Thread::Current()->zone(), data) {} | 507 : BaseIterTable(Thread::Current()->zone(), data) {} |
| 512 HashMap(Zone* zone, RawArray* data) : BaseIterTable(zone, data) {} | 508 HashMap(Zone* zone, RawArray* data) : BaseIterTable(zone, data) {} |
| 513 HashMap(Object* key, Smi* value, Array* data) | 509 HashMap(Object* key, Smi* value, Array* data) |
| 514 : BaseIterTable(key, value, data) {} | 510 : BaseIterTable(key, value, data) {} |
| 515 template <typename Key> | 511 template <typename Key> |
| 516 RawObject* GetOrNull(const Key& key, bool* present = NULL) const { | 512 RawObject* GetOrNull(const Key& key, bool* present = NULL) const { |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 582 void Clear() const { BaseIterTable::Initialize(); } | 578 void Clear() const { BaseIterTable::Initialize(); } |
| 583 | 579 |
| 584 protected: | 580 protected: |
| 585 void EnsureCapacity() const { | 581 void EnsureCapacity() const { |
| 586 static const double kMaxLoadFactor = 0.75; | 582 static const double kMaxLoadFactor = 0.75; |
| 587 // We currently never shrink. | 583 // We currently never shrink. |
| 588 HashTables::EnsureLoadFactor(0.0, kMaxLoadFactor, *this); | 584 HashTables::EnsureLoadFactor(0.0, kMaxLoadFactor, *this); |
| 589 } | 585 } |
| 590 }; | 586 }; |
| 591 | 587 |
| 592 | |
| 593 template <typename KeyTraits> | 588 template <typename KeyTraits> |
| 594 class UnorderedHashMap : public HashMap<UnorderedHashTable<KeyTraits, 1> > { | 589 class UnorderedHashMap : public HashMap<UnorderedHashTable<KeyTraits, 1> > { |
| 595 public: | 590 public: |
| 596 typedef HashMap<UnorderedHashTable<KeyTraits, 1> > BaseMap; | 591 typedef HashMap<UnorderedHashTable<KeyTraits, 1> > BaseMap; |
| 597 explicit UnorderedHashMap(RawArray* data) | 592 explicit UnorderedHashMap(RawArray* data) |
| 598 : BaseMap(Thread::Current()->zone(), data) {} | 593 : BaseMap(Thread::Current()->zone(), data) {} |
| 599 UnorderedHashMap(Zone* zone, RawArray* data) : BaseMap(zone, data) {} | 594 UnorderedHashMap(Zone* zone, RawArray* data) : BaseMap(zone, data) {} |
| 600 UnorderedHashMap(Object* key, Smi* value, Array* data) | 595 UnorderedHashMap(Object* key, Smi* value, Array* data) |
| 601 : BaseMap(key, value, data) {} | 596 : BaseMap(key, value, data) {} |
| 602 }; | 597 }; |
| 603 | 598 |
| 604 | |
| 605 template <typename BaseIterTable> | 599 template <typename BaseIterTable> |
| 606 class HashSet : public BaseIterTable { | 600 class HashSet : public BaseIterTable { |
| 607 public: | 601 public: |
| 608 explicit HashSet(RawArray* data) | 602 explicit HashSet(RawArray* data) |
| 609 : BaseIterTable(Thread::Current()->zone(), data) {} | 603 : BaseIterTable(Thread::Current()->zone(), data) {} |
| 610 HashSet(Zone* zone, RawArray* data) : BaseIterTable(zone, data) {} | 604 HashSet(Zone* zone, RawArray* data) : BaseIterTable(zone, data) {} |
| 611 HashSet(Object* key, Smi* value, Array* data) | 605 HashSet(Object* key, Smi* value, Array* data) |
| 612 : BaseIterTable(key, value, data) {} | 606 : BaseIterTable(key, value, data) {} |
| 613 bool Insert(const Object& key) { | 607 bool Insert(const Object& key) { |
| 614 EnsureCapacity(); | 608 EnsureCapacity(); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 671 void Clear() const { BaseIterTable::Initialize(); } | 665 void Clear() const { BaseIterTable::Initialize(); } |
| 672 | 666 |
| 673 protected: | 667 protected: |
| 674 void EnsureCapacity() const { | 668 void EnsureCapacity() const { |
| 675 static const double kMaxLoadFactor = 0.75; | 669 static const double kMaxLoadFactor = 0.75; |
| 676 // We currently never shrink. | 670 // We currently never shrink. |
| 677 HashTables::EnsureLoadFactor(0.0, kMaxLoadFactor, *this); | 671 HashTables::EnsureLoadFactor(0.0, kMaxLoadFactor, *this); |
| 678 } | 672 } |
| 679 }; | 673 }; |
| 680 | 674 |
| 681 | |
| 682 template <typename KeyTraits> | 675 template <typename KeyTraits> |
| 683 class UnorderedHashSet : public HashSet<UnorderedHashTable<KeyTraits, 0> > { | 676 class UnorderedHashSet : public HashSet<UnorderedHashTable<KeyTraits, 0> > { |
| 684 public: | 677 public: |
| 685 typedef HashSet<UnorderedHashTable<KeyTraits, 0> > BaseSet; | 678 typedef HashSet<UnorderedHashTable<KeyTraits, 0> > BaseSet; |
| 686 explicit UnorderedHashSet(RawArray* data) | 679 explicit UnorderedHashSet(RawArray* data) |
| 687 : BaseSet(Thread::Current()->zone(), data) { | 680 : BaseSet(Thread::Current()->zone(), data) { |
| 688 ASSERT(data != Array::null()); | 681 ASSERT(data != Array::null()); |
| 689 } | 682 } |
| 690 UnorderedHashSet(Zone* zone, RawArray* data) : BaseSet(zone, data) {} | 683 UnorderedHashSet(Zone* zone, RawArray* data) : BaseSet(zone, data) {} |
| 691 UnorderedHashSet(Object* key, Smi* value, Array* data) | 684 UnorderedHashSet(Object* key, Smi* value, Array* data) |
| 692 : BaseSet(key, value, data) {} | 685 : BaseSet(key, value, data) {} |
| 693 }; | 686 }; |
| 694 | 687 |
| 695 } // namespace dart | 688 } // namespace dart |
| 696 | 689 |
| 697 #endif // RUNTIME_VM_HASH_TABLE_H_ | 690 #endif // RUNTIME_VM_HASH_TABLE_H_ |
| OLD | NEW |