1 //===- llvm/ADT/DenseMap.h - Dense probed hash table ------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// 9 /// \file 10 /// This file defines the DenseMap class. 11 /// 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_ADT_DENSEMAP_H 15 #define LLVM_ADT_DENSEMAP_H 16 17 #include "llvm/ADT/DenseMapInfo.h" 18 #include "llvm/ADT/EpochTracker.h" 19 #include "llvm/Support/AlignOf.h" 20 #include "llvm/Support/Compiler.h" 21 #include "llvm/Support/MathExtras.h" 22 #include "llvm/Support/MemAlloc.h" 23 #include "llvm/Support/ReverseIteration.h" 24 #include "llvm/Support/type_traits.h" 25 #include <algorithm> 26 #include <cassert> 27 #include <cstddef> 28 #include <cstring> 29 #include <initializer_list> 30 #include <iterator> 31 #include <new> 32 #include <type_traits> 33 #include <utility> 34 35 namespace llvm { 36 37 namespace detail { 38 39 // We extend a pair to allow users to override the bucket type with their own 40 // implementation without requiring two members. 41 template <typename KeyT, typename ValueT> 42 struct DenseMapPair : public std::pair<KeyT, ValueT> { 43 using std::pair<KeyT, ValueT>::pair; 44 45 KeyT &getFirst() { return std::pair<KeyT, ValueT>::first; } 46 const KeyT &getFirst() const { return std::pair<KeyT, ValueT>::first; } 47 ValueT &getSecond() { return std::pair<KeyT, ValueT>::second; } 48 const ValueT &getSecond() const { return std::pair<KeyT, ValueT>::second; } 49 }; 50 51 } // end namespace detail 52 53 template <typename KeyT, typename ValueT, 54 typename KeyInfoT = DenseMapInfo<KeyT>, 55 typename Bucket = llvm::detail::DenseMapPair<KeyT, ValueT>, 56 bool IsConst = false> 57 class DenseMapIterator; 58 59 template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT, 60 typename BucketT> 61 class DenseMapBase : public DebugEpochBase { 62 template <typename T> 63 using const_arg_type_t = typename const_pointer_or_const_ref<T>::type; 64 65 public: 66 using size_type = unsigned; 67 using key_type = KeyT; 68 using mapped_type = ValueT; 69 using value_type = BucketT; 70 71 using iterator = DenseMapIterator<KeyT, ValueT, KeyInfoT, BucketT>; 72 using const_iterator = 73 DenseMapIterator<KeyT, ValueT, KeyInfoT, BucketT, true>; 74 75 inline iterator begin() { 76 // When the map is empty, avoid the overhead of advancing/retreating past 77 // empty buckets. 78 if (empty()) 79 return end(); 80 if (shouldReverseIterate<KeyT>()) 81 return makeIterator(getBucketsEnd() - 1, getBuckets(), *this); 82 return makeIterator(getBuckets(), getBucketsEnd(), *this); 83 } 84 inline iterator end() { 85 return makeIterator(getBucketsEnd(), getBucketsEnd(), *this, true); 86 } 87 inline const_iterator begin() const { 88 if (empty()) 89 return end(); 90 if (shouldReverseIterate<KeyT>()) 91 return makeConstIterator(getBucketsEnd() - 1, getBuckets(), *this); 92 return makeConstIterator(getBuckets(), getBucketsEnd(), *this); 93 } 94 inline const_iterator end() const { 95 return makeConstIterator(getBucketsEnd(), getBucketsEnd(), *this, true); 96 } 97 98 [[nodiscard]] bool empty() const { return getNumEntries() == 0; } 99 unsigned size() const { return getNumEntries(); } 100 101 /// Grow the densemap so that it can contain at least \p NumEntries items 102 /// before resizing again. 103 void reserve(size_type NumEntries) { 104 auto NumBuckets = getMinBucketToReserveForEntries(NumEntries); 105 incrementEpoch(); 106 if (NumBuckets > getNumBuckets()) 107 grow(NumBuckets); 108 } 109 110 void clear() { 111 incrementEpoch(); 112 if (getNumEntries() == 0 && getNumTombstones() == 0) 113 return; 114 115 // If the capacity of the array is huge, and the # elements used is small, 116 // shrink the array. 117 if (getNumEntries() * 4 < getNumBuckets() && getNumBuckets() > 64) { 118 shrink_and_clear(); 119 return; 120 } 121 122 const KeyT EmptyKey = getEmptyKey(); 123 if constexpr (std::is_trivially_destructible_v<ValueT>) { 124 // Use a simpler loop when values don't need destruction. 125 for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) 126 P->getFirst() = EmptyKey; 127 } else { 128 const KeyT TombstoneKey = getTombstoneKey(); 129 unsigned NumEntries = getNumEntries(); 130 for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) { 131 if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey)) { 132 if (!KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) { 133 P->getSecond().~ValueT(); 134 --NumEntries; 135 } 136 P->getFirst() = EmptyKey; 137 } 138 } 139 assert(NumEntries == 0 && "Node count imbalance!"); 140 (void)NumEntries; 141 } 142 setNumEntries(0); 143 setNumTombstones(0); 144 } 145 146 /// Return true if the specified key is in the map, false otherwise. 147 bool contains(const_arg_type_t<KeyT> Val) const { 148 return doFind(Val) != nullptr; 149 } 150 151 /// Return 1 if the specified key is in the map, 0 otherwise. 152 size_type count(const_arg_type_t<KeyT> Val) const { 153 return contains(Val) ? 1 : 0; 154 } 155 156 iterator find(const_arg_type_t<KeyT> Val) { 157 if (BucketT *Bucket = doFind(Val)) 158 return makeIterator( 159 Bucket, shouldReverseIterate<KeyT>() ? getBuckets() : getBucketsEnd(), 160 *this, true); 161 return end(); 162 } 163 const_iterator find(const_arg_type_t<KeyT> Val) const { 164 if (const BucketT *Bucket = doFind(Val)) 165 return makeConstIterator( 166 Bucket, shouldReverseIterate<KeyT>() ? getBuckets() : getBucketsEnd(), 167 *this, true); 168 return end(); 169 } 170 171 /// Alternate version of find() which allows a different, and possibly 172 /// less expensive, key type. 173 /// The DenseMapInfo is responsible for supplying methods 174 /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key 175 /// type used. 176 template <class LookupKeyT> iterator find_as(const LookupKeyT &Val) { 177 if (BucketT *Bucket = doFind(Val)) 178 return makeIterator( 179 Bucket, shouldReverseIterate<KeyT>() ? getBuckets() : getBucketsEnd(), 180 *this, true); 181 return end(); 182 } 183 template <class LookupKeyT> 184 const_iterator find_as(const LookupKeyT &Val) const { 185 if (const BucketT *Bucket = doFind(Val)) 186 return makeConstIterator( 187 Bucket, shouldReverseIterate<KeyT>() ? getBuckets() : getBucketsEnd(), 188 *this, true); 189 return end(); 190 } 191 192 /// lookup - Return the entry for the specified key, or a default 193 /// constructed value if no such entry exists. 194 ValueT lookup(const_arg_type_t<KeyT> Val) const { 195 if (const BucketT *Bucket = doFind(Val)) 196 return Bucket->getSecond(); 197 return ValueT(); 198 } 199 200 /// at - Return the entry for the specified key, or abort if no such 201 /// entry exists. 202 const ValueT &at(const_arg_type_t<KeyT> Val) const { 203 auto Iter = this->find(std::move(Val)); 204 assert(Iter != this->end() && "DenseMap::at failed due to a missing key"); 205 return Iter->second; 206 } 207 208 // Inserts key,value pair into the map if the key isn't already in the map. 209 // If the key is already in the map, it returns false and doesn't update the 210 // value. 211 std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) { 212 return try_emplace(KV.first, KV.second); 213 } 214 215 // Inserts key,value pair into the map if the key isn't already in the map. 216 // If the key is already in the map, it returns false and doesn't update the 217 // value. 218 std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) { 219 return try_emplace(std::move(KV.first), std::move(KV.second)); 220 } 221 222 // Inserts key,value pair into the map if the key isn't already in the map. 223 // The value is constructed in-place if the key is not in the map, otherwise 224 // it is not moved. 225 template <typename... Ts> 226 std::pair<iterator, bool> try_emplace(KeyT &&Key, Ts &&...Args) { 227 BucketT *TheBucket; 228 if (LookupBucketFor(Key, TheBucket)) 229 return std::make_pair(makeIterator(TheBucket, 230 shouldReverseIterate<KeyT>() 231 ? getBuckets() 232 : getBucketsEnd(), 233 *this, true), 234 false); // Already in map. 235 236 // Otherwise, insert the new element. 237 TheBucket = 238 InsertIntoBucket(TheBucket, std::move(Key), std::forward<Ts>(Args)...); 239 return std::make_pair(makeIterator(TheBucket, 240 shouldReverseIterate<KeyT>() 241 ? getBuckets() 242 : getBucketsEnd(), 243 *this, true), 244 true); 245 } 246 247 // Inserts key,value pair into the map if the key isn't already in the map. 248 // The value is constructed in-place if the key is not in the map, otherwise 249 // it is not moved. 250 template <typename... Ts> 251 std::pair<iterator, bool> try_emplace(const KeyT &Key, Ts &&...Args) { 252 BucketT *TheBucket; 253 if (LookupBucketFor(Key, TheBucket)) 254 return std::make_pair(makeIterator(TheBucket, 255 shouldReverseIterate<KeyT>() 256 ? getBuckets() 257 : getBucketsEnd(), 258 *this, true), 259 false); // Already in map. 260 261 // Otherwise, insert the new element. 262 TheBucket = InsertIntoBucket(TheBucket, Key, std::forward<Ts>(Args)...); 263 return std::make_pair(makeIterator(TheBucket, 264 shouldReverseIterate<KeyT>() 265 ? getBuckets() 266 : getBucketsEnd(), 267 *this, true), 268 true); 269 } 270 271 /// Alternate version of insert() which allows a different, and possibly 272 /// less expensive, key type. 273 /// The DenseMapInfo is responsible for supplying methods 274 /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key 275 /// type used. 276 template <typename LookupKeyT> 277 std::pair<iterator, bool> insert_as(std::pair<KeyT, ValueT> &&KV, 278 const LookupKeyT &Val) { 279 BucketT *TheBucket; 280 if (LookupBucketFor(Val, TheBucket)) 281 return std::make_pair(makeIterator(TheBucket, 282 shouldReverseIterate<KeyT>() 283 ? getBuckets() 284 : getBucketsEnd(), 285 *this, true), 286 false); // Already in map. 287 288 // Otherwise, insert the new element. 289 TheBucket = InsertIntoBucketWithLookup(TheBucket, std::move(KV.first), 290 std::move(KV.second), Val); 291 return std::make_pair(makeIterator(TheBucket, 292 shouldReverseIterate<KeyT>() 293 ? getBuckets() 294 : getBucketsEnd(), 295 *this, true), 296 true); 297 } 298 299 /// insert - Range insertion of pairs. 300 template <typename InputIt> void insert(InputIt I, InputIt E) { 301 for (; I != E; ++I) 302 insert(*I); 303 } 304 305 template <typename V> 306 std::pair<iterator, bool> insert_or_assign(const KeyT &Key, V &&Val) { 307 auto Ret = try_emplace(Key, std::forward<V>(Val)); 308 if (!Ret.second) 309 Ret.first->second = std::forward<V>(Val); 310 return Ret; 311 } 312 313 template <typename V> 314 std::pair<iterator, bool> insert_or_assign(KeyT &&Key, V &&Val) { 315 auto Ret = try_emplace(std::move(Key), std::forward<V>(Val)); 316 if (!Ret.second) 317 Ret.first->second = std::forward<V>(Val); 318 return Ret; 319 } 320 321 bool erase(const KeyT &Val) { 322 BucketT *TheBucket = doFind(Val); 323 if (!TheBucket) 324 return false; // not in map. 325 326 TheBucket->getSecond().~ValueT(); 327 TheBucket->getFirst() = getTombstoneKey(); 328 decrementNumEntries(); 329 incrementNumTombstones(); 330 return true; 331 } 332 void erase(iterator I) { 333 BucketT *TheBucket = &*I; 334 TheBucket->getSecond().~ValueT(); 335 TheBucket->getFirst() = getTombstoneKey(); 336 decrementNumEntries(); 337 incrementNumTombstones(); 338 } 339 340 ValueT &operator[](const KeyT &Key) { 341 BucketT *TheBucket; 342 if (LookupBucketFor(Key, TheBucket)) 343 return TheBucket->second; 344 345 return InsertIntoBucket(TheBucket, Key)->second; 346 } 347 348 ValueT &operator[](KeyT &&Key) { 349 BucketT *TheBucket; 350 if (LookupBucketFor(Key, TheBucket)) 351 return TheBucket->second; 352 353 return InsertIntoBucket(TheBucket, std::move(Key))->second; 354 } 355 356 /// isPointerIntoBucketsArray - Return true if the specified pointer points 357 /// somewhere into the DenseMap's array of buckets (i.e. either to a key or 358 /// value in the DenseMap). 359 bool isPointerIntoBucketsArray(const void *Ptr) const { 360 return Ptr >= getBuckets() && Ptr < getBucketsEnd(); 361 } 362 363 /// getPointerIntoBucketsArray() - Return an opaque pointer into the buckets 364 /// array. In conjunction with the previous method, this can be used to 365 /// determine whether an insertion caused the DenseMap to reallocate. 366 const void *getPointerIntoBucketsArray() const { return getBuckets(); } 367 368 protected: 369 DenseMapBase() = default; 370 371 void destroyAll() { 372 if (getNumBuckets() == 0) // Nothing to do. 373 return; 374 375 const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); 376 for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) { 377 if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) && 378 !KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) 379 P->getSecond().~ValueT(); 380 P->getFirst().~KeyT(); 381 } 382 } 383 384 void initEmpty() { 385 setNumEntries(0); 386 setNumTombstones(0); 387 388 assert((getNumBuckets() & (getNumBuckets() - 1)) == 0 && 389 "# initial buckets must be a power of two!"); 390 const KeyT EmptyKey = getEmptyKey(); 391 for (BucketT *B = getBuckets(), *E = getBucketsEnd(); B != E; ++B) 392 ::new (&B->getFirst()) KeyT(EmptyKey); 393 } 394 395 /// Returns the number of buckets to allocate to ensure that the DenseMap can 396 /// accommodate \p NumEntries without need to grow(). 397 unsigned getMinBucketToReserveForEntries(unsigned NumEntries) { 398 // Ensure that "NumEntries * 4 < NumBuckets * 3" 399 if (NumEntries == 0) 400 return 0; 401 // +1 is required because of the strict equality. 402 // For example if NumEntries is 48, we need to return 401. 403 return NextPowerOf2(NumEntries * 4 / 3 + 1); 404 } 405 406 void moveFromOldBuckets(BucketT *OldBucketsBegin, BucketT *OldBucketsEnd) { 407 initEmpty(); 408 409 // Insert all the old elements. 410 const KeyT EmptyKey = getEmptyKey(); 411 const KeyT TombstoneKey = getTombstoneKey(); 412 for (BucketT *B = OldBucketsBegin, *E = OldBucketsEnd; B != E; ++B) { 413 if (!KeyInfoT::isEqual(B->getFirst(), EmptyKey) && 414 !KeyInfoT::isEqual(B->getFirst(), TombstoneKey)) { 415 // Insert the key/value into the new table. 416 BucketT *DestBucket; 417 bool FoundVal = LookupBucketFor(B->getFirst(), DestBucket); 418 (void)FoundVal; // silence warning. 419 assert(!FoundVal && "Key already in new map?"); 420 DestBucket->getFirst() = std::move(B->getFirst()); 421 ::new (&DestBucket->getSecond()) ValueT(std::move(B->getSecond())); 422 incrementNumEntries(); 423 424 // Free the value. 425 B->getSecond().~ValueT(); 426 } 427 B->getFirst().~KeyT(); 428 } 429 } 430 431 template <typename OtherBaseT> 432 void copyFrom( 433 const DenseMapBase<OtherBaseT, KeyT, ValueT, KeyInfoT, BucketT> &other) { 434 assert(&other != this); 435 assert(getNumBuckets() == other.getNumBuckets()); 436 437 setNumEntries(other.getNumEntries()); 438 setNumTombstones(other.getNumTombstones()); 439 440 BucketT *Buckets = getBuckets(); 441 const BucketT *OtherBuckets = other.getBuckets(); 442 const size_t NumBuckets = getNumBuckets(); 443 if constexpr (std::is_trivially_copyable_v<KeyT> && 444 std::is_trivially_copyable_v<ValueT>) { 445 memcpy(reinterpret_cast<void *>(Buckets), OtherBuckets, 446 NumBuckets * sizeof(BucketT)); 447 } else { 448 const KeyT EmptyKey = getEmptyKey(); 449 const KeyT TombstoneKey = getTombstoneKey(); 450 for (size_t I = 0; I < NumBuckets; ++I) { 451 ::new (&Buckets[I].getFirst()) KeyT(OtherBuckets[I].getFirst()); 452 if (!KeyInfoT::isEqual(Buckets[I].getFirst(), EmptyKey) && 453 !KeyInfoT::isEqual(Buckets[I].getFirst(), TombstoneKey)) 454 ::new (&Buckets[I].getSecond()) ValueT(OtherBuckets[I].getSecond()); 455 } 456 } 457 } 458 459 static unsigned getHashValue(const KeyT &Val) { 460 return KeyInfoT::getHashValue(Val); 461 } 462 463 template <typename LookupKeyT> 464 static unsigned getHashValue(const LookupKeyT &Val) { 465 return KeyInfoT::getHashValue(Val); 466 } 467 468 static const KeyT getEmptyKey() { 469 static_assert(std::is_base_of_v<DenseMapBase, DerivedT>, 470 "Must pass the derived type to this template!"); 471 return KeyInfoT::getEmptyKey(); 472 } 473 474 static const KeyT getTombstoneKey() { return KeyInfoT::getTombstoneKey(); } 475 476 private: 477 iterator makeIterator(BucketT *P, BucketT *E, DebugEpochBase &Epoch, 478 bool NoAdvance = false) { 479 if (shouldReverseIterate<KeyT>()) { 480 BucketT *B = P == getBucketsEnd() ? getBuckets() : P + 1; 481 return iterator(B, E, Epoch, NoAdvance); 482 } 483 return iterator(P, E, Epoch, NoAdvance); 484 } 485 486 const_iterator makeConstIterator(const BucketT *P, const BucketT *E, 487 const DebugEpochBase &Epoch, 488 const bool NoAdvance = false) const { 489 if (shouldReverseIterate<KeyT>()) { 490 const BucketT *B = P == getBucketsEnd() ? getBuckets() : P + 1; 491 return const_iterator(B, E, Epoch, NoAdvance); 492 } 493 return const_iterator(P, E, Epoch, NoAdvance); 494 } 495 496 unsigned getNumEntries() const { 497 return static_cast<const DerivedT *>(this)->getNumEntries(); 498 } 499 500 void setNumEntries(unsigned Num) { 501 static_cast<DerivedT *>(this)->setNumEntries(Num); 502 } 503 504 void incrementNumEntries() { setNumEntries(getNumEntries() + 1); } 505 506 void decrementNumEntries() { setNumEntries(getNumEntries() - 1); } 507 508 unsigned getNumTombstones() const { 509 return static_cast<const DerivedT *>(this)->getNumTombstones(); 510 } 511 512 void setNumTombstones(unsigned Num) { 513 static_cast<DerivedT *>(this)->setNumTombstones(Num); 514 } 515 516 void incrementNumTombstones() { setNumTombstones(getNumTombstones() + 1); } 517 518 void decrementNumTombstones() { setNumTombstones(getNumTombstones() - 1); } 519 520 const BucketT *getBuckets() const { 521 return static_cast<const DerivedT *>(this)->getBuckets(); 522 } 523 524 BucketT *getBuckets() { return static_cast<DerivedT *>(this)->getBuckets(); } 525 526 unsigned getNumBuckets() const { 527 return static_cast<const DerivedT *>(this)->getNumBuckets(); 528 } 529 530 BucketT *getBucketsEnd() { return getBuckets() + getNumBuckets(); } 531 532 const BucketT *getBucketsEnd() const { 533 return getBuckets() + getNumBuckets(); 534 } 535 536 void grow(unsigned AtLeast) { static_cast<DerivedT *>(this)->grow(AtLeast); } 537 538 void shrink_and_clear() { static_cast<DerivedT *>(this)->shrink_and_clear(); } 539 540 template <typename KeyArg, typename... ValueArgs> 541 BucketT *InsertIntoBucket(BucketT *TheBucket, KeyArg &&Key, 542 ValueArgs &&...Values) { 543 TheBucket = InsertIntoBucketImpl(Key, TheBucket); 544 545 TheBucket->getFirst() = std::forward<KeyArg>(Key); 546 ::new (&TheBucket->getSecond()) ValueT(std::forward<ValueArgs>(Values)...); 547 return TheBucket; 548 } 549 550 template <typename LookupKeyT> 551 BucketT *InsertIntoBucketWithLookup(BucketT *TheBucket, KeyT &&Key, 552 ValueT &&Value, LookupKeyT &Lookup) { 553 TheBucket = InsertIntoBucketImpl(Lookup, TheBucket); 554 555 TheBucket->getFirst() = std::move(Key); 556 ::new (&TheBucket->getSecond()) ValueT(std::move(Value)); 557 return TheBucket; 558 } 559 560 template <typename LookupKeyT> 561 BucketT *InsertIntoBucketImpl(const LookupKeyT &Lookup, BucketT *TheBucket) { 562 incrementEpoch(); 563 564 // If the load of the hash table is more than 3/4, or if fewer than 1/8 of 565 // the buckets are empty (meaning that many are filled with tombstones), 566 // grow the table. 567 // 568 // The later case is tricky. For example, if we had one empty bucket with 569 // tons of tombstones, failing lookups (e.g. for insertion) would have to 570 // probe almost the entire table until it found the empty bucket. If the 571 // table completely filled with tombstones, no lookup would ever succeed, 572 // causing infinite loops in lookup. 573 unsigned NewNumEntries = getNumEntries() + 1; 574 unsigned NumBuckets = getNumBuckets(); 575 if (LLVM_UNLIKELY(NewNumEntries * 4 >= NumBuckets * 3)) { 576 this->grow(NumBuckets * 2); 577 LookupBucketFor(Lookup, TheBucket); 578 NumBuckets = getNumBuckets(); 579 } else if (LLVM_UNLIKELY(NumBuckets - 580 (NewNumEntries + getNumTombstones()) <= 581 NumBuckets / 8)) { 582 this->grow(NumBuckets); 583 LookupBucketFor(Lookup, TheBucket); 584 } 585 assert(TheBucket); 586 587 // Only update the state after we've grown our bucket space appropriately 588 // so that when growing buckets we have self-consistent entry count. 589 incrementNumEntries(); 590 591 // If we are writing over a tombstone, remember this. 592 const KeyT EmptyKey = getEmptyKey(); 593 if (!KeyInfoT::isEqual(TheBucket->getFirst(), EmptyKey)) 594 decrementNumTombstones(); 595 596 return TheBucket; 597 } 598 599 template <typename LookupKeyT> BucketT *doFind(const LookupKeyT &Val) { 600 BucketT *BucketsPtr = getBuckets(); 601 const unsigned NumBuckets = getNumBuckets(); 602 if (NumBuckets == 0) 603 return nullptr; 604 605 const KeyT EmptyKey = getEmptyKey(); 606 unsigned BucketNo = getHashValue(Val) & (NumBuckets - 1); 607 unsigned ProbeAmt = 1; 608 while (true) { 609 BucketT *Bucket = BucketsPtr + BucketNo; 610 if (LLVM_LIKELY(KeyInfoT::isEqual(Val, Bucket->getFirst()))) 611 return Bucket; 612 if (LLVM_LIKELY(KeyInfoT::isEqual(Bucket->getFirst(), EmptyKey))) 613 return nullptr; 614 615 // Otherwise, it's a hash collision or a tombstone, continue quadratic 616 // probing. 617 BucketNo += ProbeAmt++; 618 BucketNo &= NumBuckets - 1; 619 } 620 } 621 622 template <typename LookupKeyT> 623 const BucketT *doFind(const LookupKeyT &Val) const { 624 return const_cast<DenseMapBase *>(this)->doFind(Val); // NOLINT 625 } 626 627 /// LookupBucketFor - Lookup the appropriate bucket for Val, returning it in 628 /// FoundBucket. If the bucket contains the key and a value, this returns 629 /// true, otherwise it returns a bucket with an empty marker or tombstone and 630 /// returns false. 631 template <typename LookupKeyT> 632 bool LookupBucketFor(const LookupKeyT &Val, BucketT *&FoundBucket) { 633 BucketT *BucketsPtr = getBuckets(); 634 const unsigned NumBuckets = getNumBuckets(); 635 636 if (NumBuckets == 0) { 637 FoundBucket = nullptr; 638 return false; 639 } 640 641 // FoundTombstone - Keep track of whether we find a tombstone while probing. 642 BucketT *FoundTombstone = nullptr; 643 const KeyT EmptyKey = getEmptyKey(); 644 const KeyT TombstoneKey = getTombstoneKey(); 645 assert(!KeyInfoT::isEqual(Val, EmptyKey) && 646 !KeyInfoT::isEqual(Val, TombstoneKey) && 647 "Empty/Tombstone value shouldn't be inserted into map!"); 648 649 unsigned BucketNo = getHashValue(Val) & (NumBuckets - 1); 650 unsigned ProbeAmt = 1; 651 while (true) { 652 BucketT *ThisBucket = BucketsPtr + BucketNo; 653 // Found Val's bucket? If so, return it. 654 if (LLVM_LIKELY(KeyInfoT::isEqual(Val, ThisBucket->getFirst()))) { 655 FoundBucket = ThisBucket; 656 return true; 657 } 658 659 // If we found an empty bucket, the key doesn't exist in the set. 660 // Insert it and return the default value. 661 if (LLVM_LIKELY(KeyInfoT::isEqual(ThisBucket->getFirst(), EmptyKey))) { 662 // If we've already seen a tombstone while probing, fill it in instead 663 // of the empty bucket we eventually probed to. 664 FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket; 665 return false; 666 } 667 668 // If this is a tombstone, remember it. If Val ends up not in the map, we 669 // prefer to return it than something that would require more probing. 670 if (KeyInfoT::isEqual(ThisBucket->getFirst(), TombstoneKey) && 671 !FoundTombstone) 672 FoundTombstone = ThisBucket; // Remember the first tombstone found. 673 674 // Otherwise, it's a hash collision or a tombstone, continue quadratic 675 // probing. 676 BucketNo += ProbeAmt++; 677 BucketNo &= (NumBuckets - 1); 678 } 679 } 680 681 public: 682 /// Return the approximate size (in bytes) of the actual map. 683 /// This is just the raw memory used by DenseMap. 684 /// If entries are pointers to objects, the size of the referenced objects 685 /// are not included. 686 size_t getMemorySize() const { return getNumBuckets() * sizeof(BucketT); } 687 }; 688 689 /// Equality comparison for DenseMap. 690 /// 691 /// Iterates over elements of LHS confirming that each (key, value) pair in LHS 692 /// is also in RHS, and that no additional pairs are in RHS. 693 /// Equivalent to N calls to RHS.find and N value comparisons. Amortized 694 /// complexity is linear, worst case is O(N^2) (if every hash collides). 695 template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT, 696 typename BucketT> 697 bool operator==( 698 const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &LHS, 699 const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &RHS) { 700 if (LHS.size() != RHS.size()) 701 return false; 702 703 for (auto &KV : LHS) { 704 auto I = RHS.find(KV.first); 705 if (I == RHS.end() || I->second != KV.second) 706 return false; 707 } 708 709 return true; 710 } 711 712 /// Inequality comparison for DenseMap. 713 /// 714 /// Equivalent to !(LHS == RHS). See operator== for performance notes. 715 template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT, 716 typename BucketT> 717 bool operator!=( 718 const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &LHS, 719 const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &RHS) { 720 return !(LHS == RHS); 721 } 722 723 template <typename KeyT, typename ValueT, 724 typename KeyInfoT = DenseMapInfo<KeyT>, 725 typename BucketT = llvm::detail::DenseMapPair<KeyT, ValueT>> 726 class DenseMap : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>, 727 KeyT, ValueT, KeyInfoT, BucketT> { 728 friend class DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT>; 729 730 // Lift some types from the dependent base class into this class for 731 // simplicity of referring to them. 732 using BaseT = DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT>; 733 734 BucketT *Buckets; 735 unsigned NumEntries; 736 unsigned NumTombstones; 737 unsigned NumBuckets; 738 739 public: 740 /// Create a DenseMap with an optional \p InitialReserve that guarantee that 741 /// this number of elements can be inserted in the map without grow() 742 explicit DenseMap(unsigned InitialReserve = 0) { init(InitialReserve); } 743 744 DenseMap(const DenseMap &other) : BaseT() { 745 init(0); 746 copyFrom(other); 747 } 748 749 DenseMap(DenseMap &&other) : BaseT() { 750 init(0); 751 swap(other); 752 } 753 754 template <typename InputIt> DenseMap(const InputIt &I, const InputIt &E) { 755 init(std::distance(I, E)); 756 this->insert(I, E); 757 } 758 759 DenseMap(std::initializer_list<typename BaseT::value_type> Vals) { 760 init(Vals.size()); 761 this->insert(Vals.begin(), Vals.end()); 762 } 763 764 ~DenseMap() { 765 this->destroyAll(); 766 deallocate_buffer(Buckets, sizeof(BucketT) * NumBuckets, alignof(BucketT)); 767 } 768 769 void swap(DenseMap &RHS) { 770 this->incrementEpoch(); 771 RHS.incrementEpoch(); 772 std::swap(Buckets, RHS.Buckets); 773 std::swap(NumEntries, RHS.NumEntries); 774 std::swap(NumTombstones, RHS.NumTombstones); 775 std::swap(NumBuckets, RHS.NumBuckets); 776 } 777 778 DenseMap &operator=(const DenseMap &other) { 779 if (&other != this) 780 copyFrom(other); 781 return *this; 782 } 783 784 DenseMap &operator=(DenseMap &&other) { 785 this->destroyAll(); 786 deallocate_buffer(Buckets, sizeof(BucketT) * NumBuckets, alignof(BucketT)); 787 init(0); 788 swap(other); 789 return *this; 790 } 791 792 void copyFrom(const DenseMap &other) { 793 this->destroyAll(); 794 deallocate_buffer(Buckets, sizeof(BucketT) * NumBuckets, alignof(BucketT)); 795 if (allocateBuckets(other.NumBuckets)) { 796 this->BaseT::copyFrom(other); 797 } else { 798 NumEntries = 0; 799 NumTombstones = 0; 800 } 801 } 802 803 void init(unsigned InitNumEntries) { 804 auto InitBuckets = BaseT::getMinBucketToReserveForEntries(InitNumEntries); 805 if (allocateBuckets(InitBuckets)) { 806 this->BaseT::initEmpty(); 807 } else { 808 NumEntries = 0; 809 NumTombstones = 0; 810 } 811 } 812 813 void grow(unsigned AtLeast) { 814 unsigned OldNumBuckets = NumBuckets; 815 BucketT *OldBuckets = Buckets; 816 817 allocateBuckets(std::max<unsigned>( 818 64, static_cast<unsigned>(NextPowerOf2(AtLeast - 1)))); 819 assert(Buckets); 820 if (!OldBuckets) { 821 this->BaseT::initEmpty(); 822 return; 823 } 824 825 this->moveFromOldBuckets(OldBuckets, OldBuckets + OldNumBuckets); 826 827 // Free the old table. 828 deallocate_buffer(OldBuckets, sizeof(BucketT) * OldNumBuckets, 829 alignof(BucketT)); 830 } 831 832 void shrink_and_clear() { 833 unsigned OldNumBuckets = NumBuckets; 834 unsigned OldNumEntries = NumEntries; 835 this->destroyAll(); 836 837 // Reduce the number of buckets. 838 unsigned NewNumBuckets = 0; 839 if (OldNumEntries) 840 NewNumBuckets = std::max(64, 1 << (Log2_32_Ceil(OldNumEntries) + 1)); 841 if (NewNumBuckets == NumBuckets) { 842 this->BaseT::initEmpty(); 843 return; 844 } 845 846 deallocate_buffer(Buckets, sizeof(BucketT) * OldNumBuckets, 847 alignof(BucketT)); 848 init(NewNumBuckets); 849 } 850 851 private: 852 unsigned getNumEntries() const { return NumEntries; } 853 854 void setNumEntries(unsigned Num) { NumEntries = Num; } 855 856 unsigned getNumTombstones() const { return NumTombstones; } 857 858 void setNumTombstones(unsigned Num) { NumTombstones = Num; } 859 860 BucketT *getBuckets() const { return Buckets; } 861 862 unsigned getNumBuckets() const { return NumBuckets; } 863 864 bool allocateBuckets(unsigned Num) { 865 NumBuckets = Num; 866 if (NumBuckets == 0) { 867 Buckets = nullptr; 868 return false; 869 } 870 871 Buckets = static_cast<BucketT *>( 872 allocate_buffer(sizeof(BucketT) * NumBuckets, alignof(BucketT))); 873 return true; 874 } 875 }; 876 877 template <typename KeyT, typename ValueT, unsigned InlineBuckets = 4, 878 typename KeyInfoT = DenseMapInfo<KeyT>, 879 typename BucketT = llvm::detail::DenseMapPair<KeyT, ValueT>> 880 class SmallDenseMap 881 : public DenseMapBase< 882 SmallDenseMap<KeyT, ValueT, InlineBuckets, KeyInfoT, BucketT>, KeyT, 883 ValueT, KeyInfoT, BucketT> { 884 friend class DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT, BucketT>; 885 886 // Lift some types from the dependent base class into this class for 887 // simplicity of referring to them. 888 using BaseT = DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT, BucketT>; 889 890 static_assert(isPowerOf2_64(InlineBuckets), 891 "InlineBuckets must be a power of 2."); 892 893 unsigned Small : 1; 894 unsigned NumEntries : 31; 895 unsigned NumTombstones; 896 897 struct LargeRep { 898 BucketT *Buckets; 899 unsigned NumBuckets; 900 }; 901 902 /// A "union" of an inline bucket array and the struct representing 903 /// a large bucket. This union will be discriminated by the 'Small' bit. 904 AlignedCharArrayUnion<BucketT[InlineBuckets], LargeRep> storage; 905 906 public: 907 explicit SmallDenseMap(unsigned NumInitBuckets = 0) { 908 if (NumInitBuckets > InlineBuckets) 909 NumInitBuckets = llvm::bit_ceil(NumInitBuckets); 910 init(NumInitBuckets); 911 } 912 913 SmallDenseMap(const SmallDenseMap &other) : BaseT() { 914 init(0); 915 copyFrom(other); 916 } 917 918 SmallDenseMap(SmallDenseMap &&other) : BaseT() { 919 init(0); 920 swap(other); 921 } 922 923 template <typename InputIt> 924 SmallDenseMap(const InputIt &I, const InputIt &E) { 925 init(NextPowerOf2(std::distance(I, E))); 926 this->insert(I, E); 927 } 928 929 SmallDenseMap(std::initializer_list<typename BaseT::value_type> Vals) 930 : SmallDenseMap(Vals.begin(), Vals.end()) {} 931 932 ~SmallDenseMap() { 933 this->destroyAll(); 934 deallocateBuckets(); 935 } 936 937 void swap(SmallDenseMap &RHS) { 938 unsigned TmpNumEntries = RHS.NumEntries; 939 RHS.NumEntries = NumEntries; 940 NumEntries = TmpNumEntries; 941 std::swap(NumTombstones, RHS.NumTombstones); 942 943 const KeyT EmptyKey = this->getEmptyKey(); 944 const KeyT TombstoneKey = this->getTombstoneKey(); 945 if (Small && RHS.Small) { 946 // If we're swapping inline bucket arrays, we have to cope with some of 947 // the tricky bits of DenseMap's storage system: the buckets are not 948 // fully initialized. Thus we swap every key, but we may have 949 // a one-directional move of the value. 950 for (unsigned i = 0, e = InlineBuckets; i != e; ++i) { 951 BucketT *LHSB = &getInlineBuckets()[i], 952 *RHSB = &RHS.getInlineBuckets()[i]; 953 bool hasLHSValue = (!KeyInfoT::isEqual(LHSB->getFirst(), EmptyKey) && 954 !KeyInfoT::isEqual(LHSB->getFirst(), TombstoneKey)); 955 bool hasRHSValue = (!KeyInfoT::isEqual(RHSB->getFirst(), EmptyKey) && 956 !KeyInfoT::isEqual(RHSB->getFirst(), TombstoneKey)); 957 if (hasLHSValue && hasRHSValue) { 958 // Swap together if we can... 959 std::swap(*LHSB, *RHSB); 960 continue; 961 } 962 // Swap separately and handle any asymmetry. 963 std::swap(LHSB->getFirst(), RHSB->getFirst()); 964 if (hasLHSValue) { 965 ::new (&RHSB->getSecond()) ValueT(std::move(LHSB->getSecond())); 966 LHSB->getSecond().~ValueT(); 967 } else if (hasRHSValue) { 968 ::new (&LHSB->getSecond()) ValueT(std::move(RHSB->getSecond())); 969 RHSB->getSecond().~ValueT(); 970 } 971 } 972 return; 973 } 974 if (!Small && !RHS.Small) { 975 std::swap(getLargeRep()->Buckets, RHS.getLargeRep()->Buckets); 976 std::swap(getLargeRep()->NumBuckets, RHS.getLargeRep()->NumBuckets); 977 return; 978 } 979 980 SmallDenseMap &SmallSide = Small ? *this : RHS; 981 SmallDenseMap &LargeSide = Small ? RHS : *this; 982 983 // First stash the large side's rep and move the small side across. 984 LargeRep TmpRep = std::move(*LargeSide.getLargeRep()); 985 LargeSide.getLargeRep()->~LargeRep(); 986 LargeSide.Small = true; 987 // This is similar to the standard move-from-old-buckets, but the bucket 988 // count hasn't actually rotated in this case. So we have to carefully 989 // move construct the keys and values into their new locations, but there 990 // is no need to re-hash things. 991 for (unsigned i = 0, e = InlineBuckets; i != e; ++i) { 992 BucketT *NewB = &LargeSide.getInlineBuckets()[i], 993 *OldB = &SmallSide.getInlineBuckets()[i]; 994 ::new (&NewB->getFirst()) KeyT(std::move(OldB->getFirst())); 995 OldB->getFirst().~KeyT(); 996 if (!KeyInfoT::isEqual(NewB->getFirst(), EmptyKey) && 997 !KeyInfoT::isEqual(NewB->getFirst(), TombstoneKey)) { 998 ::new (&NewB->getSecond()) ValueT(std::move(OldB->getSecond())); 999 OldB->getSecond().~ValueT(); 1000 } 1001 } 1002 1003 // The hard part of moving the small buckets across is done, just move 1004 // the TmpRep into its new home. 1005 SmallSide.Small = false; 1006 new (SmallSide.getLargeRep()) LargeRep(std::move(TmpRep)); 1007 } 1008 1009 SmallDenseMap &operator=(const SmallDenseMap &other) { 1010 if (&other != this) 1011 copyFrom(other); 1012 return *this; 1013 } 1014 1015 SmallDenseMap &operator=(SmallDenseMap &&other) { 1016 this->destroyAll(); 1017 deallocateBuckets(); 1018 init(0); 1019 swap(other); 1020 return *this; 1021 } 1022 1023 void copyFrom(const SmallDenseMap &other) { 1024 this->destroyAll(); 1025 deallocateBuckets(); 1026 Small = true; 1027 if (other.getNumBuckets() > InlineBuckets) { 1028 Small = false; 1029 new (getLargeRep()) LargeRep(allocateBuckets(other.getNumBuckets())); 1030 } 1031 this->BaseT::copyFrom(other); 1032 } 1033 1034 void init(unsigned InitBuckets) { 1035 Small = true; 1036 if (InitBuckets > InlineBuckets) { 1037 Small = false; 1038 new (getLargeRep()) LargeRep(allocateBuckets(InitBuckets)); 1039 } 1040 this->BaseT::initEmpty(); 1041 } 1042 1043 void grow(unsigned AtLeast) { 1044 if (AtLeast > InlineBuckets) 1045 AtLeast = std::max<unsigned>(64, NextPowerOf2(AtLeast - 1)); 1046 1047 if (Small) { 1048 // First move the inline buckets into a temporary storage. 1049 AlignedCharArrayUnion<BucketT[InlineBuckets]> TmpStorage; 1050 BucketT *TmpBegin = reinterpret_cast<BucketT *>(&TmpStorage); 1051 BucketT *TmpEnd = TmpBegin; 1052 1053 // Loop over the buckets, moving non-empty, non-tombstones into the 1054 // temporary storage. Have the loop move the TmpEnd forward as it goes. 1055 const KeyT EmptyKey = this->getEmptyKey(); 1056 const KeyT TombstoneKey = this->getTombstoneKey(); 1057 for (BucketT *P = getBuckets(), *E = P + InlineBuckets; P != E; ++P) { 1058 if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) && 1059 !KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) { 1060 assert(size_t(TmpEnd - TmpBegin) < InlineBuckets && 1061 "Too many inline buckets!"); 1062 ::new (&TmpEnd->getFirst()) KeyT(std::move(P->getFirst())); 1063 ::new (&TmpEnd->getSecond()) ValueT(std::move(P->getSecond())); 1064 ++TmpEnd; 1065 P->getSecond().~ValueT(); 1066 } 1067 P->getFirst().~KeyT(); 1068 } 1069 1070 // AtLeast == InlineBuckets can happen if there are many tombstones, 1071 // and grow() is used to remove them. Usually we always switch to the 1072 // large rep here. 1073 if (AtLeast > InlineBuckets) { 1074 Small = false; 1075 new (getLargeRep()) LargeRep(allocateBuckets(AtLeast)); 1076 } 1077 this->moveFromOldBuckets(TmpBegin, TmpEnd); 1078 return; 1079 } 1080 1081 LargeRep OldRep = std::move(*getLargeRep()); 1082 getLargeRep()->~LargeRep(); 1083 if (AtLeast <= InlineBuckets) { 1084 Small = true; 1085 } else { 1086 new (getLargeRep()) LargeRep(allocateBuckets(AtLeast)); 1087 } 1088 1089 this->moveFromOldBuckets(OldRep.Buckets, 1090 OldRep.Buckets + OldRep.NumBuckets); 1091 1092 // Free the old table. 1093 deallocate_buffer(OldRep.Buckets, sizeof(BucketT) * OldRep.NumBuckets, 1094 alignof(BucketT)); 1095 } 1096 1097 void shrink_and_clear() { 1098 unsigned OldSize = this->size(); 1099 this->destroyAll(); 1100 1101 // Reduce the number of buckets. 1102 unsigned NewNumBuckets = 0; 1103 if (OldSize) { 1104 NewNumBuckets = 1 << (Log2_32_Ceil(OldSize) + 1); 1105 if (NewNumBuckets > InlineBuckets && NewNumBuckets < 64u) 1106 NewNumBuckets = 64; 1107 } 1108 if ((Small && NewNumBuckets <= InlineBuckets) || 1109 (!Small && NewNumBuckets == getLargeRep()->NumBuckets)) { 1110 this->BaseT::initEmpty(); 1111 return; 1112 } 1113 1114 deallocateBuckets(); 1115 init(NewNumBuckets); 1116 } 1117 1118 private: 1119 unsigned getNumEntries() const { return NumEntries; } 1120 1121 void setNumEntries(unsigned Num) { 1122 // NumEntries is hardcoded to be 31 bits wide. 1123 assert(Num < (1U << 31) && "Cannot support more than 1<<31 entries"); 1124 NumEntries = Num; 1125 } 1126 1127 unsigned getNumTombstones() const { return NumTombstones; } 1128 1129 void setNumTombstones(unsigned Num) { NumTombstones = Num; } 1130 1131 const BucketT *getInlineBuckets() const { 1132 assert(Small); 1133 // Note that this cast does not violate aliasing rules as we assert that 1134 // the memory's dynamic type is the small, inline bucket buffer, and the 1135 // 'storage' is a POD containing a char buffer. 1136 return reinterpret_cast<const BucketT *>(&storage); 1137 } 1138 1139 BucketT *getInlineBuckets() { 1140 return const_cast<BucketT *>( 1141 const_cast<const SmallDenseMap *>(this)->getInlineBuckets()); 1142 } 1143 1144 const LargeRep *getLargeRep() const { 1145 assert(!Small); 1146 // Note, same rule about aliasing as with getInlineBuckets. 1147 return reinterpret_cast<const LargeRep *>(&storage); 1148 } 1149 1150 LargeRep *getLargeRep() { 1151 return const_cast<LargeRep *>( 1152 const_cast<const SmallDenseMap *>(this)->getLargeRep()); 1153 } 1154 1155 const BucketT *getBuckets() const { 1156 return Small ? getInlineBuckets() : getLargeRep()->Buckets; 1157 } 1158 1159 BucketT *getBuckets() { 1160 return const_cast<BucketT *>( 1161 const_cast<const SmallDenseMap *>(this)->getBuckets()); 1162 } 1163 1164 unsigned getNumBuckets() const { 1165 return Small ? InlineBuckets : getLargeRep()->NumBuckets; 1166 } 1167 1168 void deallocateBuckets() { 1169 if (Small) 1170 return; 1171 1172 deallocate_buffer(getLargeRep()->Buckets, 1173 sizeof(BucketT) * getLargeRep()->NumBuckets, 1174 alignof(BucketT)); 1175 getLargeRep()->~LargeRep(); 1176 } 1177 1178 LargeRep allocateBuckets(unsigned Num) { 1179 assert(Num > InlineBuckets && "Must allocate more buckets than are inline"); 1180 LargeRep Rep = {static_cast<BucketT *>(allocate_buffer( 1181 sizeof(BucketT) * Num, alignof(BucketT))), 1182 Num}; 1183 return Rep; 1184 } 1185 }; 1186 1187 template <typename KeyT, typename ValueT, typename KeyInfoT, typename Bucket, 1188 bool IsConst> 1189 class DenseMapIterator : DebugEpochBase::HandleBase { 1190 friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true>; 1191 friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, false>; 1192 1193 public: 1194 using difference_type = ptrdiff_t; 1195 using value_type = std::conditional_t<IsConst, const Bucket, Bucket>; 1196 using pointer = value_type *; 1197 using reference = value_type &; 1198 using iterator_category = std::forward_iterator_tag; 1199 1200 private: 1201 pointer Ptr = nullptr; 1202 pointer End = nullptr; 1203 1204 public: 1205 DenseMapIterator() = default; 1206 1207 DenseMapIterator(pointer Pos, pointer E, const DebugEpochBase &Epoch, 1208 bool NoAdvance = false) 1209 : DebugEpochBase::HandleBase(&Epoch), Ptr(Pos), End(E) { 1210 assert(isHandleInSync() && "invalid construction!"); 1211 1212 if (NoAdvance) 1213 return; 1214 if (shouldReverseIterate<KeyT>()) { 1215 RetreatPastEmptyBuckets(); 1216 return; 1217 } 1218 AdvancePastEmptyBuckets(); 1219 } 1220 1221 // Converting ctor from non-const iterators to const iterators. SFINAE'd out 1222 // for const iterator destinations so it doesn't end up as a user defined copy 1223 // constructor. 1224 template <bool IsConstSrc, 1225 typename = std::enable_if_t<!IsConstSrc && IsConst>> 1226 DenseMapIterator( 1227 const DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, IsConstSrc> &I) 1228 : DebugEpochBase::HandleBase(I), Ptr(I.Ptr), End(I.End) {} 1229 1230 reference operator*() const { 1231 assert(isHandleInSync() && "invalid iterator access!"); 1232 assert(Ptr != End && "dereferencing end() iterator"); 1233 if (shouldReverseIterate<KeyT>()) 1234 return Ptr[-1]; 1235 return *Ptr; 1236 } 1237 pointer operator->() const { 1238 assert(isHandleInSync() && "invalid iterator access!"); 1239 assert(Ptr != End && "dereferencing end() iterator"); 1240 if (shouldReverseIterate<KeyT>()) 1241 return &(Ptr[-1]); 1242 return Ptr; 1243 } 1244 1245 friend bool operator==(const DenseMapIterator &LHS, 1246 const DenseMapIterator &RHS) { 1247 assert((!LHS.Ptr || LHS.isHandleInSync()) && "handle not in sync!"); 1248 assert((!RHS.Ptr || RHS.isHandleInSync()) && "handle not in sync!"); 1249 assert(LHS.getEpochAddress() == RHS.getEpochAddress() && 1250 "comparing incomparable iterators!"); 1251 return LHS.Ptr == RHS.Ptr; 1252 } 1253 1254 friend bool operator!=(const DenseMapIterator &LHS, 1255 const DenseMapIterator &RHS) { 1256 return !(LHS == RHS); 1257 } 1258 1259 inline DenseMapIterator &operator++() { // Preincrement 1260 assert(isHandleInSync() && "invalid iterator access!"); 1261 assert(Ptr != End && "incrementing end() iterator"); 1262 if (shouldReverseIterate<KeyT>()) { 1263 --Ptr; 1264 RetreatPastEmptyBuckets(); 1265 return *this; 1266 } 1267 ++Ptr; 1268 AdvancePastEmptyBuckets(); 1269 return *this; 1270 } 1271 DenseMapIterator operator++(int) { // Postincrement 1272 assert(isHandleInSync() && "invalid iterator access!"); 1273 DenseMapIterator tmp = *this; 1274 ++*this; 1275 return tmp; 1276 } 1277 1278 private: 1279 void AdvancePastEmptyBuckets() { 1280 assert(Ptr <= End); 1281 const KeyT Empty = KeyInfoT::getEmptyKey(); 1282 const KeyT Tombstone = KeyInfoT::getTombstoneKey(); 1283 1284 while (Ptr != End && (KeyInfoT::isEqual(Ptr->getFirst(), Empty) || 1285 KeyInfoT::isEqual(Ptr->getFirst(), Tombstone))) 1286 ++Ptr; 1287 } 1288 1289 void RetreatPastEmptyBuckets() { 1290 assert(Ptr >= End); 1291 const KeyT Empty = KeyInfoT::getEmptyKey(); 1292 const KeyT Tombstone = KeyInfoT::getTombstoneKey(); 1293 1294 while (Ptr != End && (KeyInfoT::isEqual(Ptr[-1].getFirst(), Empty) || 1295 KeyInfoT::isEqual(Ptr[-1].getFirst(), Tombstone))) 1296 --Ptr; 1297 } 1298 }; 1299 1300 template <typename KeyT, typename ValueT, typename KeyInfoT> 1301 inline size_t capacity_in_bytes(const DenseMap<KeyT, ValueT, KeyInfoT> &X) { 1302 return X.getMemorySize(); 1303 } 1304 1305 } // end namespace llvm 1306 1307 #endif // LLVM_ADT_DENSEMAP_H 1308