Home | History | Annotate | Line # | Download | only in sanitizer_common
      1  1.1  mrg //===- sanitizer_dense_map.h - Dense probed hash table ----------*- C++ -*-===//
      2  1.1  mrg //
      3  1.1  mrg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4  1.1  mrg // See https://llvm.org/LICENSE.txt for license information.
      5  1.1  mrg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6  1.1  mrg //
      7  1.1  mrg //===----------------------------------------------------------------------===//
      8  1.1  mrg //
      9  1.1  mrg // This is fork of llvm/ADT/DenseMap.h class with the following changes:
     10  1.1  mrg //  * Use mmap to allocate.
     11  1.1  mrg //  * No iterators.
     12  1.1  mrg //  * Does not shrink.
     13  1.1  mrg //
     14  1.1  mrg //===----------------------------------------------------------------------===//
     15  1.1  mrg 
     16  1.1  mrg #ifndef SANITIZER_DENSE_MAP_H
     17  1.1  mrg #define SANITIZER_DENSE_MAP_H
     18  1.1  mrg 
     19  1.1  mrg #include "sanitizer_common.h"
     20  1.1  mrg #include "sanitizer_dense_map_info.h"
     21  1.1  mrg #include "sanitizer_internal_defs.h"
     22  1.1  mrg #include "sanitizer_type_traits.h"
     23  1.1  mrg 
     24  1.1  mrg namespace __sanitizer {
     25  1.1  mrg 
     26  1.1  mrg template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
     27  1.1  mrg           typename BucketT>
     28  1.1  mrg class DenseMapBase {
     29  1.1  mrg  public:
     30  1.1  mrg   using size_type = unsigned;
     31  1.1  mrg   using key_type = KeyT;
     32  1.1  mrg   using mapped_type = ValueT;
     33  1.1  mrg   using value_type = BucketT;
     34  1.1  mrg 
     35  1.1  mrg   WARN_UNUSED_RESULT bool empty() const { return getNumEntries() == 0; }
     36  1.1  mrg   unsigned size() const { return getNumEntries(); }
     37  1.1  mrg 
     38  1.1  mrg   /// Grow the densemap so that it can contain at least \p NumEntries items
     39  1.1  mrg   /// before resizing again.
     40  1.1  mrg   void reserve(size_type NumEntries) {
     41  1.1  mrg     auto NumBuckets = getMinBucketToReserveForEntries(NumEntries);
     42  1.1  mrg     if (NumBuckets > getNumBuckets())
     43  1.1  mrg       grow(NumBuckets);
     44  1.1  mrg   }
     45  1.1  mrg 
     46  1.1  mrg   void clear() {
     47  1.1  mrg     if (getNumEntries() == 0 && getNumTombstones() == 0)
     48  1.1  mrg       return;
     49  1.1  mrg 
     50  1.1  mrg     const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
     51  1.1  mrg     if (__sanitizer::is_trivially_destructible<ValueT>::value) {
     52  1.1  mrg       // Use a simpler loop when values don't need destruction.
     53  1.1  mrg       for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P)
     54  1.1  mrg         P->getFirst() = EmptyKey;
     55  1.1  mrg     } else {
     56  1.1  mrg       unsigned NumEntries = getNumEntries();
     57  1.1  mrg       for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) {
     58  1.1  mrg         if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey)) {
     59  1.1  mrg           if (!KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) {
     60  1.1  mrg             P->getSecond().~ValueT();
     61  1.1  mrg             --NumEntries;
     62  1.1  mrg           }
     63  1.1  mrg           P->getFirst() = EmptyKey;
     64  1.1  mrg         }
     65  1.1  mrg       }
     66  1.1  mrg       CHECK_EQ(NumEntries, 0);
     67  1.1  mrg     }
     68  1.1  mrg     setNumEntries(0);
     69  1.1  mrg     setNumTombstones(0);
     70  1.1  mrg   }
     71  1.1  mrg 
     72  1.1  mrg   /// Return 1 if the specified key is in the map, 0 otherwise.
     73  1.1  mrg   size_type count(const KeyT &Key) const {
     74  1.1  mrg     const BucketT *TheBucket;
     75  1.1  mrg     return LookupBucketFor(Key, TheBucket) ? 1 : 0;
     76  1.1  mrg   }
     77  1.1  mrg 
     78  1.1  mrg   value_type *find(const KeyT &Key) {
     79  1.1  mrg     BucketT *TheBucket;
     80  1.1  mrg     if (LookupBucketFor(Key, TheBucket))
     81  1.1  mrg       return TheBucket;
     82  1.1  mrg     return nullptr;
     83  1.1  mrg   }
     84  1.1  mrg   const value_type *find(const KeyT &Key) const {
     85  1.1  mrg     const BucketT *TheBucket;
     86  1.1  mrg     if (LookupBucketFor(Key, TheBucket))
     87  1.1  mrg       return TheBucket;
     88  1.1  mrg     return nullptr;
     89  1.1  mrg   }
     90  1.1  mrg 
     91  1.1  mrg   /// Alternate version of find() which allows a different, and possibly
     92  1.1  mrg   /// less expensive, key type.
     93  1.1  mrg   /// The DenseMapInfo is responsible for supplying methods
     94  1.1  mrg   /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key
     95  1.1  mrg   /// type used.
     96  1.1  mrg   template <class LookupKeyT>
     97  1.1  mrg   value_type *find_as(const LookupKeyT &Key) {
     98  1.1  mrg     BucketT *TheBucket;
     99  1.1  mrg     if (LookupBucketFor(Key, TheBucket))
    100  1.1  mrg       return TheBucket;
    101  1.1  mrg     return nullptr;
    102  1.1  mrg   }
    103  1.1  mrg   template <class LookupKeyT>
    104  1.1  mrg   const value_type *find_as(const LookupKeyT &Key) const {
    105  1.1  mrg     const BucketT *TheBucket;
    106  1.1  mrg     if (LookupBucketFor(Key, TheBucket))
    107  1.1  mrg       return TheBucket;
    108  1.1  mrg     return nullptr;
    109  1.1  mrg   }
    110  1.1  mrg 
    111  1.1  mrg   /// lookup - Return the entry for the specified key, or a default
    112  1.1  mrg   /// constructed value if no such entry exists.
    113  1.1  mrg   ValueT lookup(const KeyT &Key) const {
    114  1.1  mrg     const BucketT *TheBucket;
    115  1.1  mrg     if (LookupBucketFor(Key, TheBucket))
    116  1.1  mrg       return TheBucket->getSecond();
    117  1.1  mrg     return ValueT();
    118  1.1  mrg   }
    119  1.1  mrg 
    120  1.1  mrg   // Inserts key,value pair into the map if the key isn't already in the map.
    121  1.1  mrg   // If the key is already in the map, it returns false and doesn't update the
    122  1.1  mrg   // value.
    123  1.1  mrg   detail::DenseMapPair<value_type *, bool> insert(const value_type &KV) {
    124  1.1  mrg     return try_emplace(KV.first, KV.second);
    125  1.1  mrg   }
    126  1.1  mrg 
    127  1.1  mrg   // Inserts key,value pair into the map if the key isn't already in the map.
    128  1.1  mrg   // If the key is already in the map, it returns false and doesn't update the
    129  1.1  mrg   // value.
    130  1.1  mrg   detail::DenseMapPair<value_type *, bool> insert(value_type &&KV) {
    131  1.1  mrg     return try_emplace(__sanitizer::move(KV.first),
    132  1.1  mrg                        __sanitizer::move(KV.second));
    133  1.1  mrg   }
    134  1.1  mrg 
    135  1.1  mrg   // Inserts key,value pair into the map if the key isn't already in the map.
    136  1.1  mrg   // The value is constructed in-place if the key is not in the map, otherwise
    137  1.1  mrg   // it is not moved.
    138  1.1  mrg   template <typename... Ts>
    139  1.1  mrg   detail::DenseMapPair<value_type *, bool> try_emplace(KeyT &&Key,
    140  1.1  mrg                                                        Ts &&...Args) {
    141  1.1  mrg     BucketT *TheBucket;
    142  1.1  mrg     if (LookupBucketFor(Key, TheBucket))
    143  1.1  mrg       return {TheBucket, false};  // Already in map.
    144  1.1  mrg 
    145  1.1  mrg     // Otherwise, insert the new element.
    146  1.1  mrg     TheBucket = InsertIntoBucket(TheBucket, __sanitizer::move(Key),
    147  1.1  mrg                                  __sanitizer::forward<Ts>(Args)...);
    148  1.1  mrg     return {TheBucket, true};
    149  1.1  mrg   }
    150  1.1  mrg 
    151  1.1  mrg   // Inserts key,value pair into the map if the key isn't already in the map.
    152  1.1  mrg   // The value is constructed in-place if the key is not in the map, otherwise
    153  1.1  mrg   // it is not moved.
    154  1.1  mrg   template <typename... Ts>
    155  1.1  mrg   detail::DenseMapPair<value_type *, bool> try_emplace(const KeyT &Key,
    156  1.1  mrg                                                        Ts &&...Args) {
    157  1.1  mrg     BucketT *TheBucket;
    158  1.1  mrg     if (LookupBucketFor(Key, TheBucket))
    159  1.1  mrg       return {TheBucket, false};  // Already in map.
    160  1.1  mrg 
    161  1.1  mrg     // Otherwise, insert the new element.
    162  1.1  mrg     TheBucket =
    163  1.1  mrg         InsertIntoBucket(TheBucket, Key, __sanitizer::forward<Ts>(Args)...);
    164  1.1  mrg     return {TheBucket, true};
    165  1.1  mrg   }
    166  1.1  mrg 
    167  1.1  mrg   /// Alternate version of insert() which allows a different, and possibly
    168  1.1  mrg   /// less expensive, key type.
    169  1.1  mrg   /// The DenseMapInfo is responsible for supplying methods
    170  1.1  mrg   /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key
    171  1.1  mrg   /// type used.
    172  1.1  mrg   template <typename LookupKeyT>
    173  1.1  mrg   detail::DenseMapPair<value_type *, bool> insert_as(value_type &&KV,
    174  1.1  mrg                                                      const LookupKeyT &Val) {
    175  1.1  mrg     BucketT *TheBucket;
    176  1.1  mrg     if (LookupBucketFor(Val, TheBucket))
    177  1.1  mrg       return {TheBucket, false};  // Already in map.
    178  1.1  mrg 
    179  1.1  mrg     // Otherwise, insert the new element.
    180  1.1  mrg     TheBucket =
    181  1.1  mrg         InsertIntoBucketWithLookup(TheBucket, __sanitizer::move(KV.first),
    182  1.1  mrg                                    __sanitizer::move(KV.second), Val);
    183  1.1  mrg     return {TheBucket, true};
    184  1.1  mrg   }
    185  1.1  mrg 
    186  1.1  mrg   bool erase(const KeyT &Val) {
    187  1.1  mrg     BucketT *TheBucket;
    188  1.1  mrg     if (!LookupBucketFor(Val, TheBucket))
    189  1.1  mrg       return false;  // not in map.
    190  1.1  mrg 
    191  1.1  mrg     TheBucket->getSecond().~ValueT();
    192  1.1  mrg     TheBucket->getFirst() = getTombstoneKey();
    193  1.1  mrg     decrementNumEntries();
    194  1.1  mrg     incrementNumTombstones();
    195  1.1  mrg     return true;
    196  1.1  mrg   }
    197  1.1  mrg 
    198  1.1  mrg   void erase(value_type *I) {
    199  1.1  mrg     CHECK_NE(I, nullptr);
    200  1.1  mrg     BucketT *TheBucket = &*I;
    201  1.1  mrg     TheBucket->getSecond().~ValueT();
    202  1.1  mrg     TheBucket->getFirst() = getTombstoneKey();
    203  1.1  mrg     decrementNumEntries();
    204  1.1  mrg     incrementNumTombstones();
    205  1.1  mrg   }
    206  1.1  mrg 
    207  1.1  mrg   value_type &FindAndConstruct(const KeyT &Key) {
    208  1.1  mrg     BucketT *TheBucket;
    209  1.1  mrg     if (LookupBucketFor(Key, TheBucket))
    210  1.1  mrg       return *TheBucket;
    211  1.1  mrg 
    212  1.1  mrg     return *InsertIntoBucket(TheBucket, Key);
    213  1.1  mrg   }
    214  1.1  mrg 
    215  1.1  mrg   ValueT &operator[](const KeyT &Key) { return FindAndConstruct(Key).second; }
    216  1.1  mrg 
    217  1.1  mrg   value_type &FindAndConstruct(KeyT &&Key) {
    218  1.1  mrg     BucketT *TheBucket;
    219  1.1  mrg     if (LookupBucketFor(Key, TheBucket))
    220  1.1  mrg       return *TheBucket;
    221  1.1  mrg 
    222  1.1  mrg     return *InsertIntoBucket(TheBucket, __sanitizer::move(Key));
    223  1.1  mrg   }
    224  1.1  mrg 
    225  1.1  mrg   ValueT &operator[](KeyT &&Key) {
    226  1.1  mrg     return FindAndConstruct(__sanitizer::move(Key)).second;
    227  1.1  mrg   }
    228  1.1  mrg 
    229  1.1  mrg   /// Iterate over active entries of the container.
    230  1.1  mrg   ///
    231  1.1  mrg   /// Function can return fast to stop the process.
    232  1.1  mrg   template <class Fn>
    233  1.1  mrg   void forEach(Fn fn) {
    234  1.1  mrg     const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
    235  1.1  mrg     for (auto *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) {
    236  1.1  mrg       const KeyT K = P->getFirst();
    237  1.1  mrg       if (!KeyInfoT::isEqual(K, EmptyKey) &&
    238  1.1  mrg           !KeyInfoT::isEqual(K, TombstoneKey)) {
    239  1.1  mrg         if (!fn(*P))
    240  1.1  mrg           return;
    241  1.1  mrg       }
    242  1.1  mrg     }
    243  1.1  mrg   }
    244  1.1  mrg 
    245  1.1  mrg   template <class Fn>
    246  1.1  mrg   void forEach(Fn fn) const {
    247  1.1  mrg     const_cast<DenseMapBase *>(this)->forEach(
    248  1.1  mrg         [&](const value_type &KV) { return fn(KV); });
    249  1.1  mrg   }
    250  1.1  mrg 
    251  1.1  mrg  protected:
    252  1.1  mrg   DenseMapBase() = default;
    253  1.1  mrg 
    254  1.1  mrg   void destroyAll() {
    255  1.1  mrg     if (getNumBuckets() == 0)  // Nothing to do.
    256  1.1  mrg       return;
    257  1.1  mrg 
    258  1.1  mrg     const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
    259  1.1  mrg     for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) {
    260  1.1  mrg       if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) &&
    261  1.1  mrg           !KeyInfoT::isEqual(P->getFirst(), TombstoneKey))
    262  1.1  mrg         P->getSecond().~ValueT();
    263  1.1  mrg       P->getFirst().~KeyT();
    264  1.1  mrg     }
    265  1.1  mrg   }
    266  1.1  mrg 
    267  1.1  mrg   void initEmpty() {
    268  1.1  mrg     setNumEntries(0);
    269  1.1  mrg     setNumTombstones(0);
    270  1.1  mrg 
    271  1.1  mrg     CHECK_EQ((getNumBuckets() & (getNumBuckets() - 1)), 0);
    272  1.1  mrg     const KeyT EmptyKey = getEmptyKey();
    273  1.1  mrg     for (BucketT *B = getBuckets(), *E = getBucketsEnd(); B != E; ++B)
    274  1.1  mrg       ::new (&B->getFirst()) KeyT(EmptyKey);
    275  1.1  mrg   }
    276  1.1  mrg 
    277  1.1  mrg   /// Returns the number of buckets to allocate to ensure that the DenseMap can
    278  1.1  mrg   /// accommodate \p NumEntries without need to grow().
    279  1.1  mrg   unsigned getMinBucketToReserveForEntries(unsigned NumEntries) {
    280  1.1  mrg     // Ensure that "NumEntries * 4 < NumBuckets * 3"
    281  1.1  mrg     if (NumEntries == 0)
    282  1.1  mrg       return 0;
    283  1.1  mrg     // +1 is required because of the strict equality.
    284  1.1  mrg     // For example if NumEntries is 48, we need to return 401.
    285  1.1  mrg     return RoundUpToPowerOfTwo((NumEntries * 4 / 3 + 1) + /* NextPowerOf2 */ 1);
    286  1.1  mrg   }
    287  1.1  mrg 
    288  1.1  mrg   void moveFromOldBuckets(BucketT *OldBucketsBegin, BucketT *OldBucketsEnd) {
    289  1.1  mrg     initEmpty();
    290  1.1  mrg 
    291  1.1  mrg     // Insert all the old elements.
    292  1.1  mrg     const KeyT EmptyKey = getEmptyKey();
    293  1.1  mrg     const KeyT TombstoneKey = getTombstoneKey();
    294  1.1  mrg     for (BucketT *B = OldBucketsBegin, *E = OldBucketsEnd; B != E; ++B) {
    295  1.1  mrg       if (!KeyInfoT::isEqual(B->getFirst(), EmptyKey) &&
    296  1.1  mrg           !KeyInfoT::isEqual(B->getFirst(), TombstoneKey)) {
    297  1.1  mrg         // Insert the key/value into the new table.
    298  1.1  mrg         BucketT *DestBucket;
    299  1.1  mrg         bool FoundVal = LookupBucketFor(B->getFirst(), DestBucket);
    300  1.1  mrg         (void)FoundVal;  // silence warning.
    301  1.1  mrg         CHECK(!FoundVal);
    302  1.1  mrg         DestBucket->getFirst() = __sanitizer::move(B->getFirst());
    303  1.1  mrg         ::new (&DestBucket->getSecond())
    304  1.1  mrg             ValueT(__sanitizer::move(B->getSecond()));
    305  1.1  mrg         incrementNumEntries();
    306  1.1  mrg 
    307  1.1  mrg         // Free the value.
    308  1.1  mrg         B->getSecond().~ValueT();
    309  1.1  mrg       }
    310  1.1  mrg       B->getFirst().~KeyT();
    311  1.1  mrg     }
    312  1.1  mrg   }
    313  1.1  mrg 
    314  1.1  mrg   template <typename OtherBaseT>
    315  1.1  mrg   void copyFrom(
    316  1.1  mrg       const DenseMapBase<OtherBaseT, KeyT, ValueT, KeyInfoT, BucketT> &other) {
    317  1.1  mrg     CHECK_NE(&other, this);
    318  1.1  mrg     CHECK_EQ(getNumBuckets(), other.getNumBuckets());
    319  1.1  mrg 
    320  1.1  mrg     setNumEntries(other.getNumEntries());
    321  1.1  mrg     setNumTombstones(other.getNumTombstones());
    322  1.1  mrg 
    323  1.1  mrg     if (__sanitizer::is_trivially_copyable<KeyT>::value &&
    324  1.1  mrg         __sanitizer::is_trivially_copyable<ValueT>::value)
    325  1.1  mrg       internal_memcpy(reinterpret_cast<void *>(getBuckets()),
    326  1.1  mrg                       other.getBuckets(), getNumBuckets() * sizeof(BucketT));
    327  1.1  mrg     else
    328  1.1  mrg       for (uptr i = 0; i < getNumBuckets(); ++i) {
    329  1.1  mrg         ::new (&getBuckets()[i].getFirst())
    330  1.1  mrg             KeyT(other.getBuckets()[i].getFirst());
    331  1.1  mrg         if (!KeyInfoT::isEqual(getBuckets()[i].getFirst(), getEmptyKey()) &&
    332  1.1  mrg             !KeyInfoT::isEqual(getBuckets()[i].getFirst(), getTombstoneKey()))
    333  1.1  mrg           ::new (&getBuckets()[i].getSecond())
    334  1.1  mrg               ValueT(other.getBuckets()[i].getSecond());
    335  1.1  mrg       }
    336  1.1  mrg   }
    337  1.1  mrg 
    338  1.1  mrg   static unsigned getHashValue(const KeyT &Val) {
    339  1.1  mrg     return KeyInfoT::getHashValue(Val);
    340  1.1  mrg   }
    341  1.1  mrg 
    342  1.1  mrg   template <typename LookupKeyT>
    343  1.1  mrg   static unsigned getHashValue(const LookupKeyT &Val) {
    344  1.1  mrg     return KeyInfoT::getHashValue(Val);
    345  1.1  mrg   }
    346  1.1  mrg 
    347  1.1  mrg   static const KeyT getEmptyKey() { return KeyInfoT::getEmptyKey(); }
    348  1.1  mrg 
    349  1.1  mrg   static const KeyT getTombstoneKey() { return KeyInfoT::getTombstoneKey(); }
    350  1.1  mrg 
    351  1.1  mrg  private:
    352  1.1  mrg   unsigned getNumEntries() const {
    353  1.1  mrg     return static_cast<const DerivedT *>(this)->getNumEntries();
    354  1.1  mrg   }
    355  1.1  mrg 
    356  1.1  mrg   void setNumEntries(unsigned Num) {
    357  1.1  mrg     static_cast<DerivedT *>(this)->setNumEntries(Num);
    358  1.1  mrg   }
    359  1.1  mrg 
    360  1.1  mrg   void incrementNumEntries() { setNumEntries(getNumEntries() + 1); }
    361  1.1  mrg 
    362  1.1  mrg   void decrementNumEntries() { setNumEntries(getNumEntries() - 1); }
    363  1.1  mrg 
    364  1.1  mrg   unsigned getNumTombstones() const {
    365  1.1  mrg     return static_cast<const DerivedT *>(this)->getNumTombstones();
    366  1.1  mrg   }
    367  1.1  mrg 
    368  1.1  mrg   void setNumTombstones(unsigned Num) {
    369  1.1  mrg     static_cast<DerivedT *>(this)->setNumTombstones(Num);
    370  1.1  mrg   }
    371  1.1  mrg 
    372  1.1  mrg   void incrementNumTombstones() { setNumTombstones(getNumTombstones() + 1); }
    373  1.1  mrg 
    374  1.1  mrg   void decrementNumTombstones() { setNumTombstones(getNumTombstones() - 1); }
    375  1.1  mrg 
    376  1.1  mrg   const BucketT *getBuckets() const {
    377  1.1  mrg     return static_cast<const DerivedT *>(this)->getBuckets();
    378  1.1  mrg   }
    379  1.1  mrg 
    380  1.1  mrg   BucketT *getBuckets() { return static_cast<DerivedT *>(this)->getBuckets(); }
    381  1.1  mrg 
    382  1.1  mrg   unsigned getNumBuckets() const {
    383  1.1  mrg     return static_cast<const DerivedT *>(this)->getNumBuckets();
    384  1.1  mrg   }
    385  1.1  mrg 
    386  1.1  mrg   BucketT *getBucketsEnd() { return getBuckets() + getNumBuckets(); }
    387  1.1  mrg 
    388  1.1  mrg   const BucketT *getBucketsEnd() const {
    389  1.1  mrg     return getBuckets() + getNumBuckets();
    390  1.1  mrg   }
    391  1.1  mrg 
    392  1.1  mrg   void grow(unsigned AtLeast) { static_cast<DerivedT *>(this)->grow(AtLeast); }
    393  1.1  mrg 
    394  1.1  mrg   template <typename KeyArg, typename... ValueArgs>
    395  1.1  mrg   BucketT *InsertIntoBucket(BucketT *TheBucket, KeyArg &&Key,
    396  1.1  mrg                             ValueArgs &&...Values) {
    397  1.1  mrg     TheBucket = InsertIntoBucketImpl(Key, Key, TheBucket);
    398  1.1  mrg 
    399  1.1  mrg     TheBucket->getFirst() = __sanitizer::forward<KeyArg>(Key);
    400  1.1  mrg     ::new (&TheBucket->getSecond())
    401  1.1  mrg         ValueT(__sanitizer::forward<ValueArgs>(Values)...);
    402  1.1  mrg     return TheBucket;
    403  1.1  mrg   }
    404  1.1  mrg 
    405  1.1  mrg   template <typename LookupKeyT>
    406  1.1  mrg   BucketT *InsertIntoBucketWithLookup(BucketT *TheBucket, KeyT &&Key,
    407  1.1  mrg                                       ValueT &&Value, LookupKeyT &Lookup) {
    408  1.1  mrg     TheBucket = InsertIntoBucketImpl(Key, Lookup, TheBucket);
    409  1.1  mrg 
    410  1.1  mrg     TheBucket->getFirst() = __sanitizer::move(Key);
    411  1.1  mrg     ::new (&TheBucket->getSecond()) ValueT(__sanitizer::move(Value));
    412  1.1  mrg     return TheBucket;
    413  1.1  mrg   }
    414  1.1  mrg 
    415  1.1  mrg   template <typename LookupKeyT>
    416  1.1  mrg   BucketT *InsertIntoBucketImpl(const KeyT &Key, const LookupKeyT &Lookup,
    417  1.1  mrg                                 BucketT *TheBucket) {
    418  1.1  mrg     // If the load of the hash table is more than 3/4, or if fewer than 1/8 of
    419  1.1  mrg     // the buckets are empty (meaning that many are filled with tombstones),
    420  1.1  mrg     // grow the table.
    421  1.1  mrg     //
    422  1.1  mrg     // The later case is tricky.  For example, if we had one empty bucket with
    423  1.1  mrg     // tons of tombstones, failing lookups (e.g. for insertion) would have to
    424  1.1  mrg     // probe almost the entire table until it found the empty bucket.  If the
    425  1.1  mrg     // table completely filled with tombstones, no lookup would ever succeed,
    426  1.1  mrg     // causing infinite loops in lookup.
    427  1.1  mrg     unsigned NewNumEntries = getNumEntries() + 1;
    428  1.1  mrg     unsigned NumBuckets = getNumBuckets();
    429  1.1  mrg     if (UNLIKELY(NewNumEntries * 4 >= NumBuckets * 3)) {
    430  1.1  mrg       this->grow(NumBuckets * 2);
    431  1.1  mrg       LookupBucketFor(Lookup, TheBucket);
    432  1.1  mrg       NumBuckets = getNumBuckets();
    433  1.1  mrg     } else if (UNLIKELY(NumBuckets - (NewNumEntries + getNumTombstones()) <=
    434  1.1  mrg                         NumBuckets / 8)) {
    435  1.1  mrg       this->grow(NumBuckets);
    436  1.1  mrg       LookupBucketFor(Lookup, TheBucket);
    437  1.1  mrg     }
    438  1.1  mrg     CHECK(TheBucket);
    439  1.1  mrg 
    440  1.1  mrg     // Only update the state after we've grown our bucket space appropriately
    441  1.1  mrg     // so that when growing buckets we have self-consistent entry count.
    442  1.1  mrg     incrementNumEntries();
    443  1.1  mrg 
    444  1.1  mrg     // If we are writing over a tombstone, remember this.
    445  1.1  mrg     const KeyT EmptyKey = getEmptyKey();
    446  1.1  mrg     if (!KeyInfoT::isEqual(TheBucket->getFirst(), EmptyKey))
    447  1.1  mrg       decrementNumTombstones();
    448  1.1  mrg 
    449  1.1  mrg     return TheBucket;
    450  1.1  mrg   }
    451  1.1  mrg 
    452  1.1  mrg   /// LookupBucketFor - Lookup the appropriate bucket for Val, returning it in
    453  1.1  mrg   /// FoundBucket.  If the bucket contains the key and a value, this returns
    454  1.1  mrg   /// true, otherwise it returns a bucket with an empty marker or tombstone and
    455  1.1  mrg   /// returns false.
    456  1.1  mrg   template <typename LookupKeyT>
    457  1.1  mrg   bool LookupBucketFor(const LookupKeyT &Val,
    458  1.1  mrg                        const BucketT *&FoundBucket) const {
    459  1.1  mrg     const BucketT *BucketsPtr = getBuckets();
    460  1.1  mrg     const unsigned NumBuckets = getNumBuckets();
    461  1.1  mrg 
    462  1.1  mrg     if (NumBuckets == 0) {
    463  1.1  mrg       FoundBucket = nullptr;
    464  1.1  mrg       return false;
    465  1.1  mrg     }
    466  1.1  mrg 
    467  1.1  mrg     // FoundTombstone - Keep track of whether we find a tombstone while probing.
    468  1.1  mrg     const BucketT *FoundTombstone = nullptr;
    469  1.1  mrg     const KeyT EmptyKey = getEmptyKey();
    470  1.1  mrg     const KeyT TombstoneKey = getTombstoneKey();
    471  1.1  mrg     CHECK(!KeyInfoT::isEqual(Val, EmptyKey));
    472  1.1  mrg     CHECK(!KeyInfoT::isEqual(Val, TombstoneKey));
    473  1.1  mrg 
    474  1.1  mrg     unsigned BucketNo = getHashValue(Val) & (NumBuckets - 1);
    475  1.1  mrg     unsigned ProbeAmt = 1;
    476  1.1  mrg     while (true) {
    477  1.1  mrg       const BucketT *ThisBucket = BucketsPtr + BucketNo;
    478  1.1  mrg       // Found Val's bucket?  If so, return it.
    479  1.1  mrg       if (LIKELY(KeyInfoT::isEqual(Val, ThisBucket->getFirst()))) {
    480  1.1  mrg         FoundBucket = ThisBucket;
    481  1.1  mrg         return true;
    482  1.1  mrg       }
    483  1.1  mrg 
    484  1.1  mrg       // If we found an empty bucket, the key doesn't exist in the set.
    485  1.1  mrg       // Insert it and return the default value.
    486  1.1  mrg       if (LIKELY(KeyInfoT::isEqual(ThisBucket->getFirst(), EmptyKey))) {
    487  1.1  mrg         // If we've already seen a tombstone while probing, fill it in instead
    488  1.1  mrg         // of the empty bucket we eventually probed to.
    489  1.1  mrg         FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket;
    490  1.1  mrg         return false;
    491  1.1  mrg       }
    492  1.1  mrg 
    493  1.1  mrg       // If this is a tombstone, remember it.  If Val ends up not in the map, we
    494  1.1  mrg       // prefer to return it than something that would require more probing.
    495  1.1  mrg       if (KeyInfoT::isEqual(ThisBucket->getFirst(), TombstoneKey) &&
    496  1.1  mrg           !FoundTombstone)
    497  1.1  mrg         FoundTombstone = ThisBucket;  // Remember the first tombstone found.
    498  1.1  mrg 
    499  1.1  mrg       // Otherwise, it's a hash collision or a tombstone, continue quadratic
    500  1.1  mrg       // probing.
    501  1.1  mrg       BucketNo += ProbeAmt++;
    502  1.1  mrg       BucketNo &= (NumBuckets - 1);
    503  1.1  mrg     }
    504  1.1  mrg   }
    505  1.1  mrg 
    506  1.1  mrg   template <typename LookupKeyT>
    507  1.1  mrg   bool LookupBucketFor(const LookupKeyT &Val, BucketT *&FoundBucket) {
    508  1.1  mrg     const BucketT *ConstFoundBucket;
    509  1.1  mrg     bool Result = const_cast<const DenseMapBase *>(this)->LookupBucketFor(
    510  1.1  mrg         Val, ConstFoundBucket);
    511  1.1  mrg     FoundBucket = const_cast<BucketT *>(ConstFoundBucket);
    512  1.1  mrg     return Result;
    513  1.1  mrg   }
    514  1.1  mrg 
    515  1.1  mrg  public:
    516  1.1  mrg   /// Return the approximate size (in bytes) of the actual map.
    517  1.1  mrg   /// This is just the raw memory used by DenseMap.
    518  1.1  mrg   /// If entries are pointers to objects, the size of the referenced objects
    519  1.1  mrg   /// are not included.
    520  1.1  mrg   uptr getMemorySize() const {
    521  1.1  mrg     return RoundUpTo(getNumBuckets() * sizeof(BucketT), GetPageSizeCached());
    522  1.1  mrg   }
    523  1.1  mrg };
    524  1.1  mrg 
    525  1.1  mrg /// Equality comparison for DenseMap.
    526  1.1  mrg ///
    527  1.1  mrg /// Iterates over elements of LHS confirming that each (key, value) pair in LHS
    528  1.1  mrg /// is also in RHS, and that no additional pairs are in RHS.
    529  1.1  mrg /// Equivalent to N calls to RHS.find and N value comparisons. Amortized
    530  1.1  mrg /// complexity is linear, worst case is O(N^2) (if every hash collides).
    531  1.1  mrg template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
    532  1.1  mrg           typename BucketT>
    533  1.1  mrg bool operator==(
    534  1.1  mrg     const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &LHS,
    535  1.1  mrg     const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &RHS) {
    536  1.1  mrg   if (LHS.size() != RHS.size())
    537  1.1  mrg     return false;
    538  1.1  mrg 
    539  1.1  mrg   bool R = true;
    540  1.1  mrg   LHS.forEach(
    541  1.1  mrg       [&](const typename DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT,
    542  1.1  mrg                                       BucketT>::value_type &KV) -> bool {
    543  1.1  mrg         const auto *I = RHS.find(KV.first);
    544  1.1  mrg         if (!I || I->second != KV.second) {
    545  1.1  mrg           R = false;
    546  1.1  mrg           return false;
    547  1.1  mrg         }
    548  1.1  mrg         return true;
    549  1.1  mrg       });
    550  1.1  mrg 
    551  1.1  mrg   return R;
    552  1.1  mrg }
    553  1.1  mrg 
    554  1.1  mrg /// Inequality comparison for DenseMap.
    555  1.1  mrg ///
    556  1.1  mrg /// Equivalent to !(LHS == RHS). See operator== for performance notes.
    557  1.1  mrg template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT,
    558  1.1  mrg           typename BucketT>
    559  1.1  mrg bool operator!=(
    560  1.1  mrg     const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &LHS,
    561  1.1  mrg     const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &RHS) {
    562  1.1  mrg   return !(LHS == RHS);
    563  1.1  mrg }
    564  1.1  mrg 
    565  1.1  mrg template <typename KeyT, typename ValueT,
    566  1.1  mrg           typename KeyInfoT = DenseMapInfo<KeyT>,
    567  1.1  mrg           typename BucketT = detail::DenseMapPair<KeyT, ValueT>>
    568  1.1  mrg class DenseMap : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>,
    569  1.1  mrg                                      KeyT, ValueT, KeyInfoT, BucketT> {
    570  1.1  mrg   friend class DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
    571  1.1  mrg 
    572  1.1  mrg   // Lift some types from the dependent base class into this class for
    573  1.1  mrg   // simplicity of referring to them.
    574  1.1  mrg   using BaseT = DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
    575  1.1  mrg 
    576  1.1  mrg   BucketT *Buckets = nullptr;
    577  1.1  mrg   unsigned NumEntries = 0;
    578  1.1  mrg   unsigned NumTombstones = 0;
    579  1.1  mrg   unsigned NumBuckets = 0;
    580  1.1  mrg 
    581  1.1  mrg  public:
    582  1.1  mrg   /// Create a DenseMap with an optional \p InitialReserve that guarantee that
    583  1.1  mrg   /// this number of elements can be inserted in the map without grow()
    584  1.1  mrg   explicit DenseMap(unsigned InitialReserve) { init(InitialReserve); }
    585  1.1  mrg   constexpr DenseMap() = default;
    586  1.1  mrg 
    587  1.1  mrg   DenseMap(const DenseMap &other) : BaseT() {
    588  1.1  mrg     init(0);
    589  1.1  mrg     copyFrom(other);
    590  1.1  mrg   }
    591  1.1  mrg 
    592  1.1  mrg   DenseMap(DenseMap &&other) : BaseT() {
    593  1.1  mrg     init(0);
    594  1.1  mrg     swap(other);
    595  1.1  mrg   }
    596  1.1  mrg 
    597  1.1  mrg   ~DenseMap() {
    598  1.1  mrg     this->destroyAll();
    599  1.1  mrg     deallocate_buffer(Buckets, sizeof(BucketT) * NumBuckets);
    600  1.1  mrg   }
    601  1.1  mrg 
    602  1.1  mrg   void swap(DenseMap &RHS) {
    603  1.1  mrg     Swap(Buckets, RHS.Buckets);
    604  1.1  mrg     Swap(NumEntries, RHS.NumEntries);
    605  1.1  mrg     Swap(NumTombstones, RHS.NumTombstones);
    606  1.1  mrg     Swap(NumBuckets, RHS.NumBuckets);
    607  1.1  mrg   }
    608  1.1  mrg 
    609  1.1  mrg   DenseMap &operator=(const DenseMap &other) {
    610  1.1  mrg     if (&other != this)
    611  1.1  mrg       copyFrom(other);
    612  1.1  mrg     return *this;
    613  1.1  mrg   }
    614  1.1  mrg 
    615  1.1  mrg   DenseMap &operator=(DenseMap &&other) {
    616  1.1  mrg     this->destroyAll();
    617  1.1  mrg     deallocate_buffer(Buckets, sizeof(BucketT) * NumBuckets, alignof(BucketT));
    618  1.1  mrg     init(0);
    619  1.1  mrg     swap(other);
    620  1.1  mrg     return *this;
    621  1.1  mrg   }
    622  1.1  mrg 
    623  1.1  mrg   void copyFrom(const DenseMap &other) {
    624  1.1  mrg     this->destroyAll();
    625  1.1  mrg     deallocate_buffer(Buckets, sizeof(BucketT) * NumBuckets);
    626  1.1  mrg     if (allocateBuckets(other.NumBuckets)) {
    627  1.1  mrg       this->BaseT::copyFrom(other);
    628  1.1  mrg     } else {
    629  1.1  mrg       NumEntries = 0;
    630  1.1  mrg       NumTombstones = 0;
    631  1.1  mrg     }
    632  1.1  mrg   }
    633  1.1  mrg 
    634  1.1  mrg   void init(unsigned InitNumEntries) {
    635  1.1  mrg     auto InitBuckets = BaseT::getMinBucketToReserveForEntries(InitNumEntries);
    636  1.1  mrg     if (allocateBuckets(InitBuckets)) {
    637  1.1  mrg       this->BaseT::initEmpty();
    638  1.1  mrg     } else {
    639  1.1  mrg       NumEntries = 0;
    640  1.1  mrg       NumTombstones = 0;
    641  1.1  mrg     }
    642  1.1  mrg   }
    643  1.1  mrg 
    644  1.1  mrg   void grow(unsigned AtLeast) {
    645  1.1  mrg     unsigned OldNumBuckets = NumBuckets;
    646  1.1  mrg     BucketT *OldBuckets = Buckets;
    647  1.1  mrg 
    648  1.1  mrg     allocateBuckets(RoundUpToPowerOfTwo(Max<unsigned>(64, AtLeast)));
    649  1.1  mrg     CHECK(Buckets);
    650  1.1  mrg     if (!OldBuckets) {
    651  1.1  mrg       this->BaseT::initEmpty();
    652  1.1  mrg       return;
    653  1.1  mrg     }
    654  1.1  mrg 
    655  1.1  mrg     this->moveFromOldBuckets(OldBuckets, OldBuckets + OldNumBuckets);
    656  1.1  mrg 
    657  1.1  mrg     // Free the old table.
    658  1.1  mrg     deallocate_buffer(OldBuckets, sizeof(BucketT) * OldNumBuckets);
    659  1.1  mrg   }
    660  1.1  mrg 
    661  1.1  mrg  private:
    662  1.1  mrg   unsigned getNumEntries() const { return NumEntries; }
    663  1.1  mrg 
    664  1.1  mrg   void setNumEntries(unsigned Num) { NumEntries = Num; }
    665  1.1  mrg 
    666  1.1  mrg   unsigned getNumTombstones() const { return NumTombstones; }
    667  1.1  mrg 
    668  1.1  mrg   void setNumTombstones(unsigned Num) { NumTombstones = Num; }
    669  1.1  mrg 
    670  1.1  mrg   BucketT *getBuckets() const { return Buckets; }
    671  1.1  mrg 
    672  1.1  mrg   unsigned getNumBuckets() const { return NumBuckets; }
    673  1.1  mrg 
    674  1.1  mrg   bool allocateBuckets(unsigned Num) {
    675  1.1  mrg     NumBuckets = Num;
    676  1.1  mrg     if (NumBuckets == 0) {
    677  1.1  mrg       Buckets = nullptr;
    678  1.1  mrg       return false;
    679  1.1  mrg     }
    680  1.1  mrg 
    681  1.1  mrg     uptr Size = sizeof(BucketT) * NumBuckets;
    682  1.1  mrg     if (Size * 2 <= GetPageSizeCached()) {
    683  1.1  mrg       // We always allocate at least a page, so use entire space.
    684  1.1  mrg       unsigned Log2 = MostSignificantSetBitIndex(GetPageSizeCached() / Size);
    685  1.1  mrg       Size <<= Log2;
    686  1.1  mrg       NumBuckets <<= Log2;
    687  1.1  mrg       CHECK_EQ(Size, sizeof(BucketT) * NumBuckets);
    688  1.1  mrg       CHECK_GT(Size * 2, GetPageSizeCached());
    689  1.1  mrg     }
    690  1.1  mrg     Buckets = static_cast<BucketT *>(allocate_buffer(Size));
    691  1.1  mrg     return true;
    692  1.1  mrg   }
    693  1.1  mrg 
    694  1.1  mrg   static void *allocate_buffer(uptr Size) {
    695  1.1  mrg     return MmapOrDie(RoundUpTo(Size, GetPageSizeCached()), "DenseMap");
    696  1.1  mrg   }
    697  1.1  mrg 
    698  1.1  mrg   static void deallocate_buffer(void *Ptr, uptr Size) {
    699  1.1  mrg     UnmapOrDie(Ptr, RoundUpTo(Size, GetPageSizeCached()));
    700  1.1  mrg   }
    701  1.1  mrg };
    702  1.1  mrg 
    703  1.1  mrg }  // namespace __sanitizer
    704  1.1  mrg 
    705  1.1  mrg #endif  // SANITIZER_DENSE_MAP_H
    706