Chromium Code Reviews| 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 |