@@ -413,11 +413,13 @@ class DenseMapBase : public DebugEpochBase {
413413 return NextPowerOf2(NumEntries * 4 / 3 + 1);
414414 }
415415
416- void moveFromImpl(iterator_range<BucketT *> OldBuckets) {
416+ // Move key/value from Other to *this.
417+ // Other is left in a valid but empty state.
418+ void moveFrom(DerivedT &Other) {
417419 // Insert all the old elements.
418420 const KeyT EmptyKey = KeyInfoT::getEmptyKey();
419421 const KeyT TombstoneKey = KeyInfoT::getTombstoneKey();
420- for (BucketT &B : OldBuckets ) {
422+ for (BucketT &B : Other.buckets() ) {
421423 if (!KeyInfoT::isEqual(B.getFirst(), EmptyKey) &&
422424 !KeyInfoT::isEqual(B.getFirst(), TombstoneKey)) {
423425 // Insert the key/value into the new table.
@@ -434,17 +436,6 @@ class DenseMapBase : public DebugEpochBase {
434436 }
435437 B.getFirst().~KeyT();
436438 }
437- }
438-
439- void moveFromOldBuckets(iterator_range<BucketT *> OldBuckets) {
440- initEmpty();
441- moveFromImpl(OldBuckets);
442- }
443-
444- // Move key/value from Other to *this.
445- // Other is left in a valid but empty state.
446- void moveFrom(DerivedT &Other) {
447- moveFromImpl(Other.buckets());
448439 Other.derived().kill();
449440 }
450441
@@ -738,6 +729,11 @@ class DenseMap : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>,
738729 unsigned NumTombstones;
739730 unsigned NumBuckets;
740731
732+ struct ExactBucketCount {};
733+ explicit DenseMap(unsigned NumBuckets, ExactBucketCount) {
734+ initWithExactBucketCount(NumBuckets);
735+ }
736+
741737public:
742738 /// Create a DenseMap with an optional \p NumElementsToReserve to guarantee
743739 /// that this number of elements can be inserted in the map without grow().
@@ -822,16 +818,20 @@ class DenseMap : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>,
822818 return true;
823819 }
824820
825- void init(unsigned InitNumEntries) {
826- auto InitBuckets = BaseT::getMinBucketToReserveForEntries(InitNumEntries);
827- if (allocateBuckets(InitBuckets)) {
821+ void initWithExactBucketCount(unsigned NewNumBuckets) {
822+ if (allocateBuckets(NewNumBuckets)) {
828823 this->BaseT::initEmpty();
829824 } else {
830825 NumEntries = 0;
831826 NumTombstones = 0;
832827 }
833828 }
834829
830+ void init(unsigned InitNumEntries) {
831+ auto InitBuckets = BaseT::getMinBucketToReserveForEntries(InitNumEntries);
832+ initWithExactBucketCount(InitBuckets);
833+ }
834+
835835 // Put the zombie instance in a known good state after a move.
836836 void kill() {
837837 deallocateBuckets();
@@ -840,23 +840,10 @@ class DenseMap : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>,
840840 }
841841
842842 void grow(unsigned AtLeast) {
843- unsigned OldNumBuckets = NumBuckets;
844- BucketT *OldBuckets = Buckets;
845-
846- allocateBuckets(std::max<unsigned>(
847- 64, static_cast<unsigned>(NextPowerOf2(AtLeast - 1))));
848- assert(Buckets);
849- if (!OldBuckets) {
850- this->BaseT::initEmpty();
851- return;
852- }
853-
854- this->moveFromOldBuckets(
855- llvm::make_range(OldBuckets, OldBuckets + OldNumBuckets));
856-
857- // Free the old table.
858- deallocate_buffer(OldBuckets, sizeof(BucketT) * OldNumBuckets,
859- alignof(BucketT));
843+ AtLeast = std::max<unsigned>(64, NextPowerOf2(AtLeast - 1));
844+ DenseMap Tmp(AtLeast, ExactBucketCount{});
845+ Tmp.moveFrom(*this);
846+ swapImpl(Tmp);
860847 }
861848
862849 // Plan how to shrink the bucket table. Return:
0 commit comments