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 |