OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All rights reserv ed. | 2 * Copyright (C) 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All rights reserv ed. |
3 * Copyright (C) 2008 David Levin <levin@chromium.org> | 3 * Copyright (C) 2008 David Levin <levin@chromium.org> |
4 * | 4 * |
5 * This library is free software; you can redistribute it and/or | 5 * This library is free software; you can redistribute it and/or |
6 * modify it under the terms of the GNU Library General Public | 6 * modify it under the terms of the GNU Library General Public |
7 * License as published by the Free Software Foundation; either | 7 * License as published by the Free Software Foundation; either |
8 * version 2 of the License, or (at your option) any later version. | 8 * version 2 of the License, or (at your option) any later version. |
9 * | 9 * |
10 * This library is distributed in the hope that it will be useful, | 10 * This library is distributed in the hope that it will be useful, |
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
478 #endif | 478 #endif |
479 | 479 |
480 #if CHECK_HASHTABLE_ITERATORS | 480 #if CHECK_HASHTABLE_ITERATORS |
481 void invalidateIterators(); | 481 void invalidateIterators(); |
482 #else | 482 #else |
483 static void invalidateIterators() { } | 483 static void invalidateIterators() { } |
484 #endif | 484 #endif |
485 | 485 |
486 static const int m_maxLoad = 2; | 486 static const int m_maxLoad = 2; |
487 static const int m_minLoad = 6; | 487 static const int m_minLoad = 6; |
488 static const int perturbShift = 5; | |
488 | 489 |
489 ValueType* m_table; | 490 ValueType* m_table; |
490 int m_tableSize; | 491 int m_tableSize; |
491 int m_tableSizeMask; | 492 int m_tableSizeMask; |
492 int m_keyCount; | 493 int m_keyCount; |
493 int m_deletedCount; | 494 int m_deletedCount; |
494 | 495 |
495 #if CHECK_HASHTABLE_ITERATORS | 496 #if CHECK_HASHTABLE_ITERATORS |
496 public: | 497 public: |
497 // All access to m_iterators should be guarded with m_mutex. | 498 // All access to m_iterators should be guarded with m_mutex. |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
554 #if CHECK_HASHTABLE_ITERATORS | 555 #if CHECK_HASHTABLE_ITERATORS |
555 , m_iterators(0) | 556 , m_iterators(0) |
556 , m_mutex(adoptPtr(new Mutex)) | 557 , m_mutex(adoptPtr(new Mutex)) |
557 #endif | 558 #endif |
558 #if DUMP_HASHTABLE_STATS_PER_TABLE | 559 #if DUMP_HASHTABLE_STATS_PER_TABLE |
559 , m_stats(adoptPtr(new Stats)) | 560 , m_stats(adoptPtr(new Stats)) |
560 #endif | 561 #endif |
561 { | 562 { |
562 } | 563 } |
563 | 564 |
564 inline unsigned doubleHash(unsigned key) | |
565 { | |
566 key = ~key + (key >> 23); | |
567 key ^= (key << 12); | |
568 key ^= (key >> 7); | |
569 key ^= (key << 2); | |
570 key ^= (key >> 20); | |
571 return key; | |
572 } | |
573 | |
574 #if ASSERT_DISABLED | 565 #if ASSERT_DISABLED |
575 | 566 |
576 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits> | 567 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits> |
577 template<typename HashTranslator, typename T> | 568 template<typename HashTranslator, typename T> |
578 inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTrait s>::checkKey(const T&) | 569 inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTrait s>::checkKey(const T&) |
579 { | 570 { |
580 } | 571 } |
581 | 572 |
582 #else | 573 #else |
583 | 574 |
(...skipping 12 matching lines...) Expand all Loading... | |
596 } | 587 } |
597 | 588 |
598 #endif | 589 #endif |
599 | 590 |
600 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits> | 591 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits> |
601 template<typename HashTranslator, typename T> | 592 template<typename HashTranslator, typename T> |
602 inline Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTra its>::lookup(const T& key) | 593 inline Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTra its>::lookup(const T& key) |
603 { | 594 { |
604 checkKey<HashTranslator>(key); | 595 checkKey<HashTranslator>(key); |
605 | 596 |
606 int k = 0; | |
607 int sizeMask = m_tableSizeMask; | |
608 ValueType* table = m_table; | 597 ValueType* table = m_table; |
609 unsigned h = HashTranslator::hash(key); | 598 unsigned h = HashTranslator::hash(key); |
610 int i = h & sizeMask; | 599 unsigned i = h; |
600 unsigned perturb = h; | |
611 | 601 |
612 if (!table) | 602 if (!table) |
613 return 0; | 603 return 0; |
614 | 604 |
615 #if DUMP_HASHTABLE_STATS | 605 #if DUMP_HASHTABLE_STATS |
616 atomicIncrement(&HashTableStats::numAccesses); | 606 atomicIncrement(&HashTableStats::numAccesses); |
617 int probeCount = 0; | 607 int probeCount = 0; |
618 #endif | 608 #endif |
619 | 609 |
620 #if DUMP_HASHTABLE_STATS_PER_TABLE | 610 #if DUMP_HASHTABLE_STATS_PER_TABLE |
621 ++m_stats->numAccesses; | 611 ++m_stats->numAccesses; |
622 int perTableProbeCount = 0; | 612 int perTableProbeCount = 0; |
623 #endif | 613 #endif |
624 | 614 |
625 while (1) { | 615 while (1) { |
626 ValueType* entry = table + i; | 616 ValueType* entry = table + (i & m_tableSizeMask); |
627 | 617 |
628 // we count on the compiler to optimize out this branch | 618 // we count on the compiler to optimize out this branch |
629 if (HashFunctions::safeToCompareToEmptyOrDeleted) { | 619 if (HashFunctions::safeToCompareToEmptyOrDeleted) { |
630 if (HashTranslator::equal(Extractor::extract(*entry), key)) | 620 if (HashTranslator::equal(Extractor::extract(*entry), key)) |
631 return entry; | 621 return entry; |
632 | 622 |
633 if (isEmptyBucket(*entry)) | 623 if (isEmptyBucket(*entry)) |
634 return 0; | 624 return 0; |
635 } else { | 625 } else { |
636 if (isEmptyBucket(*entry)) | 626 if (isEmptyBucket(*entry)) |
637 return 0; | 627 return 0; |
638 | 628 |
639 if (!isDeletedBucket(*entry) && HashTranslator::equal(Extractor: :extract(*entry), key)) | 629 if (!isDeletedBucket(*entry) && HashTranslator::equal(Extractor: :extract(*entry), key)) |
640 return entry; | 630 return entry; |
641 } | 631 } |
642 #if DUMP_HASHTABLE_STATS | 632 #if DUMP_HASHTABLE_STATS |
643 ++probeCount; | 633 ++probeCount; |
644 HashTableStats::recordCollisionAtCount(probeCount); | 634 HashTableStats::recordCollisionAtCount(probeCount); |
645 #endif | 635 #endif |
646 | 636 |
647 #if DUMP_HASHTABLE_STATS_PER_TABLE | 637 #if DUMP_HASHTABLE_STATS_PER_TABLE |
648 ++perTableProbeCount; | 638 ++perTableProbeCount; |
649 m_stats->recordCollisionAtCount(perTableProbeCount); | 639 m_stats->recordCollisionAtCount(perTableProbeCount); |
650 #endif | 640 #endif |
651 | 641 |
652 if (k == 0) | 642 perturb >>= perturbShift; |
653 k = 1 | doubleHash(h); | 643 i = i*5 + perturb + 1; |
654 i = (i + k) & sizeMask; | |
655 } | 644 } |
656 } | 645 } |
657 | 646 |
658 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits> | 647 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits> |
659 template<typename HashTranslator, typename T> | 648 template<typename HashTranslator, typename T> |
660 inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyT raits>::LookupType HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTr aits>::lookupForWriting(const T& key) | 649 inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyT raits>::LookupType HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTr aits>::lookupForWriting(const T& key) |
661 { | 650 { |
662 ASSERT(m_table); | 651 ASSERT(m_table); |
663 checkKey<HashTranslator>(key); | 652 checkKey<HashTranslator>(key); |
664 | 653 |
665 int k = 0; | |
666 ValueType* table = m_table; | 654 ValueType* table = m_table; |
667 int sizeMask = m_tableSizeMask; | |
abarth-chromium
2013/06/25 05:03:38
Is there a reason you remove the copy of m_tableSi
| |
668 unsigned h = HashTranslator::hash(key); | 655 unsigned h = HashTranslator::hash(key); |
669 int i = h & sizeMask; | 656 unsigned i = h; |
657 unsigned perturb = h; | |
670 | 658 |
671 #if DUMP_HASHTABLE_STATS | 659 #if DUMP_HASHTABLE_STATS |
672 atomicIncrement(&HashTableStats::numAccesses); | 660 atomicIncrement(&HashTableStats::numAccesses); |
673 int probeCount = 0; | 661 int probeCount = 0; |
674 #endif | 662 #endif |
675 | 663 |
676 #if DUMP_HASHTABLE_STATS_PER_TABLE | 664 #if DUMP_HASHTABLE_STATS_PER_TABLE |
677 ++m_stats->numAccesses; | 665 ++m_stats->numAccesses; |
678 int perTableProbeCount = 0; | 666 int perTableProbeCount = 0; |
679 #endif | 667 #endif |
680 | 668 |
681 ValueType* deletedEntry = 0; | 669 ValueType* deletedEntry = 0; |
682 | 670 |
683 while (1) { | 671 while (1) { |
684 ValueType* entry = table + i; | 672 ValueType* entry = table + (i & m_tableSizeMask); |
685 | 673 |
686 // we count on the compiler to optimize out this branch | 674 // we count on the compiler to optimize out this branch |
687 if (HashFunctions::safeToCompareToEmptyOrDeleted) { | 675 if (HashFunctions::safeToCompareToEmptyOrDeleted) { |
688 if (isEmptyBucket(*entry)) | 676 if (isEmptyBucket(*entry)) |
689 return LookupType(deletedEntry ? deletedEntry : entry, false ); | 677 return LookupType(deletedEntry ? deletedEntry : entry, false ); |
690 | 678 |
691 if (HashTranslator::equal(Extractor::extract(*entry), key)) | 679 if (HashTranslator::equal(Extractor::extract(*entry), key)) |
692 return LookupType(entry, true); | 680 return LookupType(entry, true); |
693 | 681 |
694 if (isDeletedBucket(*entry)) | 682 if (isDeletedBucket(*entry)) |
(...skipping 10 matching lines...) Expand all Loading... | |
705 #if DUMP_HASHTABLE_STATS | 693 #if DUMP_HASHTABLE_STATS |
706 ++probeCount; | 694 ++probeCount; |
707 HashTableStats::recordCollisionAtCount(probeCount); | 695 HashTableStats::recordCollisionAtCount(probeCount); |
708 #endif | 696 #endif |
709 | 697 |
710 #if DUMP_HASHTABLE_STATS_PER_TABLE | 698 #if DUMP_HASHTABLE_STATS_PER_TABLE |
711 ++perTableProbeCount; | 699 ++perTableProbeCount; |
712 m_stats->recordCollisionAtCount(perTableProbeCount); | 700 m_stats->recordCollisionAtCount(perTableProbeCount); |
713 #endif | 701 #endif |
714 | 702 |
715 if (k == 0) | 703 perturb >>= perturbShift; |
716 k = 1 | doubleHash(h); | 704 i = i*5 + perturb + 1; |
717 i = (i + k) & sizeMask; | |
718 } | 705 } |
719 } | 706 } |
720 | 707 |
721 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits> | 708 template<typename Key, typename Value, typename Extractor, typename HashFunc tions, typename Traits, typename KeyTraits> |
722 template<typename HashTranslator, typename T> | 709 template<typename HashTranslator, typename T> |
723 inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyT raits>::FullLookupType HashTable<Key, Value, Extractor, HashFunctions, Traits, K eyTraits>::fullLookupForWriting(const T& key) | 710 inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyT raits>::FullLookupType HashTable<Key, Value, Extractor, HashFunctions, Traits, K eyTraits>::fullLookupForWriting(const T& key) |
724 { | 711 { |
725 ASSERT(m_table); | 712 ASSERT(m_table); |
726 checkKey<HashTranslator>(key); | 713 checkKey<HashTranslator>(key); |
727 | 714 |
728 int k = 0; | |
729 ValueType* table = m_table; | 715 ValueType* table = m_table; |
730 int sizeMask = m_tableSizeMask; | |
731 unsigned h = HashTranslator::hash(key); | 716 unsigned h = HashTranslator::hash(key); |
732 int i = h & sizeMask; | 717 unsigned i = h; |
718 unsigned perturb = h; | |
733 | 719 |
734 #if DUMP_HASHTABLE_STATS | 720 #if DUMP_HASHTABLE_STATS |
735 atomicIncrement(&HashTableStats::numAccesses); | 721 atomicIncrement(&HashTableStats::numAccesses); |
736 int probeCount = 0; | 722 int probeCount = 0; |
737 #endif | 723 #endif |
738 | 724 |
739 #if DUMP_HASHTABLE_STATS_PER_TABLE | 725 #if DUMP_HASHTABLE_STATS_PER_TABLE |
740 ++m_stats->numAccesses; | 726 ++m_stats->numAccesses; |
741 int perTableProbeCount = 0; | 727 int perTableProbeCount = 0; |
742 #endif | 728 #endif |
743 | 729 |
744 ValueType* deletedEntry = 0; | 730 ValueType* deletedEntry = 0; |
745 | 731 |
746 while (1) { | 732 while (1) { |
747 ValueType* entry = table + i; | 733 ValueType* entry = table + (i & m_tableSizeMask); |
748 | 734 |
749 // we count on the compiler to optimize out this branch | 735 // we count on the compiler to optimize out this branch |
750 if (HashFunctions::safeToCompareToEmptyOrDeleted) { | 736 if (HashFunctions::safeToCompareToEmptyOrDeleted) { |
751 if (isEmptyBucket(*entry)) | 737 if (isEmptyBucket(*entry)) |
752 return makeLookupResult(deletedEntry ? deletedEntry : entry, false, h); | 738 return makeLookupResult(deletedEntry ? deletedEntry : entry, false, h); |
753 | 739 |
754 if (HashTranslator::equal(Extractor::extract(*entry), key)) | 740 if (HashTranslator::equal(Extractor::extract(*entry), key)) |
755 return makeLookupResult(entry, true, h); | 741 return makeLookupResult(entry, true, h); |
756 | 742 |
757 if (isDeletedBucket(*entry)) | 743 if (isDeletedBucket(*entry)) |
(...skipping 10 matching lines...) Expand all Loading... | |
768 #if DUMP_HASHTABLE_STATS | 754 #if DUMP_HASHTABLE_STATS |
769 ++probeCount; | 755 ++probeCount; |
770 HashTableStats::recordCollisionAtCount(probeCount); | 756 HashTableStats::recordCollisionAtCount(probeCount); |
771 #endif | 757 #endif |
772 | 758 |
773 #if DUMP_HASHTABLE_STATS_PER_TABLE | 759 #if DUMP_HASHTABLE_STATS_PER_TABLE |
774 ++perTableProbeCount; | 760 ++perTableProbeCount; |
775 m_stats->recordCollisionAtCount(perTableProbeCount); | 761 m_stats->recordCollisionAtCount(perTableProbeCount); |
776 #endif | 762 #endif |
777 | 763 |
778 if (k == 0) | 764 perturb >>= perturbShift; |
779 k = 1 | doubleHash(h); | 765 i = i*5 + perturb + 1; |
780 i = (i + k) & sizeMask; | |
781 } | 766 } |
782 } | 767 } |
783 | 768 |
784 template<bool emptyValueIsZero> struct HashTableBucketInitializer; | 769 template<bool emptyValueIsZero> struct HashTableBucketInitializer; |
785 | 770 |
786 template<> struct HashTableBucketInitializer<false> { | 771 template<> struct HashTableBucketInitializer<false> { |
787 template<typename Traits, typename Value> static void initialize(Value& bucket) | 772 template<typename Traits, typename Value> static void initialize(Value& bucket) |
788 { | 773 { |
789 new (NotNull, &bucket) Value(Traits::emptyValue()); | 774 new (NotNull, &bucket) Value(Traits::emptyValue()); |
790 } | 775 } |
(...skipping 23 matching lines...) Expand all Loading... | |
814 | 799 |
815 invalidateIterators(); | 800 invalidateIterators(); |
816 | 801 |
817 if (!m_table) | 802 if (!m_table) |
818 expand(); | 803 expand(); |
819 | 804 |
820 internalCheckTableConsistency(); | 805 internalCheckTableConsistency(); |
821 | 806 |
822 ASSERT(m_table); | 807 ASSERT(m_table); |
823 | 808 |
824 int k = 0; | |
825 ValueType* table = m_table; | 809 ValueType* table = m_table; |
826 int sizeMask = m_tableSizeMask; | |
827 unsigned h = HashTranslator::hash(key); | 810 unsigned h = HashTranslator::hash(key); |
828 int i = h & sizeMask; | 811 unsigned i = h; |
812 unsigned perturb = h; | |
829 | 813 |
830 #if DUMP_HASHTABLE_STATS | 814 #if DUMP_HASHTABLE_STATS |
831 atomicIncrement(&HashTableStats::numAccesses); | 815 atomicIncrement(&HashTableStats::numAccesses); |
832 int probeCount = 0; | 816 int probeCount = 0; |
833 #endif | 817 #endif |
834 | 818 |
835 #if DUMP_HASHTABLE_STATS_PER_TABLE | 819 #if DUMP_HASHTABLE_STATS_PER_TABLE |
836 ++m_stats->numAccesses; | 820 ++m_stats->numAccesses; |
837 int perTableProbeCount = 0; | 821 int perTableProbeCount = 0; |
838 #endif | 822 #endif |
839 | 823 |
840 ValueType* deletedEntry = 0; | 824 ValueType* deletedEntry = 0; |
841 ValueType* entry; | 825 ValueType* entry; |
842 while (1) { | 826 while (1) { |
843 entry = table + i; | 827 entry = table + (i & m_tableSizeMask); |
844 | 828 |
845 // we count on the compiler to optimize out this branch | 829 // we count on the compiler to optimize out this branch |
846 if (HashFunctions::safeToCompareToEmptyOrDeleted) { | 830 if (HashFunctions::safeToCompareToEmptyOrDeleted) { |
847 if (isEmptyBucket(*entry)) | 831 if (isEmptyBucket(*entry)) |
848 break; | 832 break; |
849 | 833 |
850 if (HashTranslator::equal(Extractor::extract(*entry), key)) | 834 if (HashTranslator::equal(Extractor::extract(*entry), key)) |
851 return AddResult(makeKnownGoodIterator(entry), false); | 835 return AddResult(makeKnownGoodIterator(entry), false); |
852 | 836 |
853 if (isDeletedBucket(*entry)) | 837 if (isDeletedBucket(*entry)) |
(...skipping 10 matching lines...) Expand all Loading... | |
864 #if DUMP_HASHTABLE_STATS | 848 #if DUMP_HASHTABLE_STATS |
865 ++probeCount; | 849 ++probeCount; |
866 HashTableStats::recordCollisionAtCount(probeCount); | 850 HashTableStats::recordCollisionAtCount(probeCount); |
867 #endif | 851 #endif |
868 | 852 |
869 #if DUMP_HASHTABLE_STATS_PER_TABLE | 853 #if DUMP_HASHTABLE_STATS_PER_TABLE |
870 ++perTableProbeCount; | 854 ++perTableProbeCount; |
871 m_stats->recordCollisionAtCount(perTableProbeCount); | 855 m_stats->recordCollisionAtCount(perTableProbeCount); |
872 #endif | 856 #endif |
873 | 857 |
874 if (k == 0) | 858 perturb >>= perturbShift; |
875 k = 1 | doubleHash(h); | 859 i = i*5 + perturb + 1; |
876 i = (i + k) & sizeMask; | |
877 } | 860 } |
878 | 861 |
879 if (deletedEntry) { | 862 if (deletedEntry) { |
880 initializeBucket(*deletedEntry); | 863 initializeBucket(*deletedEntry); |
881 entry = deletedEntry; | 864 entry = deletedEntry; |
882 --m_deletedCount; | 865 --m_deletedCount; |
883 } | 866 } |
884 | 867 |
885 HashTranslator::translate(*entry, key, extra); | 868 HashTranslator::translate(*entry, key, extra); |
886 | 869 |
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1411 inline bool operator!=(const HashTableIteratorAdapter<T, U>& a, const HashTa bleConstIteratorAdapter<T, U>& b) | 1394 inline bool operator!=(const HashTableIteratorAdapter<T, U>& a, const HashTa bleConstIteratorAdapter<T, U>& b) |
1412 { | 1395 { |
1413 return a.m_impl != b.m_impl; | 1396 return a.m_impl != b.m_impl; |
1414 } | 1397 } |
1415 | 1398 |
1416 } // namespace WTF | 1399 } // namespace WTF |
1417 | 1400 |
1418 #include <wtf/HashIterators.h> | 1401 #include <wtf/HashIterators.h> |
1419 | 1402 |
1420 #endif // WTF_HashTable_h | 1403 #endif // WTF_HashTable_h |
OLD | NEW |