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