[llvm] b1b0be2 - [ADT] Make DenseMapBase::moveFrom safer (NFC) (#168180)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Nov 15 10:53:58 PST 2025
Author: Kazu Hirata
Date: 2025-11-15T10:53:53-08:00
New Revision: b1b0be201b9043c3c417a58f24eb9ced62a52638
URL: https://github.com/llvm/llvm-project/commit/b1b0be201b9043c3c417a58f24eb9ced62a52638
DIFF: https://github.com/llvm/llvm-project/commit/b1b0be201b9043c3c417a58f24eb9ced62a52638.diff
LOG: [ADT] Make DenseMapBase::moveFrom safer (NFC) (#168180)
Without this patch, DenseMapBase::moveFrom() moves buckets and leaves
the moved-from object in a zombie state. This patch teaches
moveFrom() to call kill() so that the move-from object is in a known
good state. This brings moveFrom()'s behavior in line with standard
C++ move semantics.
kill() is implemented so that it takes the fast path in the destructor
-- both destroyAll() and deallocateBuckets().
Added:
Modified:
llvm/include/llvm/ADT/DenseMap.h
Removed:
################################################################################
diff --git a/llvm/include/llvm/ADT/DenseMap.h b/llvm/include/llvm/ADT/DenseMap.h
index 333bbcb9399ce..db59bd595bca7 100644
--- a/llvm/include/llvm/ADT/DenseMap.h
+++ b/llvm/include/llvm/ADT/DenseMap.h
@@ -441,8 +441,12 @@ class DenseMapBase : public DebugEpochBase {
moveFromImpl(OldBuckets);
}
- // Move key/value from Other to *this. Other will be in a zombie state.
- void moveFrom(DerivedT &Other) { moveFromImpl(Other.buckets()); }
+ // Move key/value from Other to *this.
+ // Other is left in a valid but empty state.
+ void moveFrom(DerivedT &Other) {
+ moveFromImpl(Other.buckets());
+ Other.derived().kill();
+ }
void copyFrom(const DerivedT &other) {
this->destroyAll();
@@ -830,6 +834,13 @@ class DenseMap : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>,
}
}
+ // Put the zombie instance in a known good state after a move.
+ void kill() {
+ deallocateBuckets();
+ Buckets = nullptr;
+ NumBuckets = 0;
+ }
+
void grow(unsigned AtLeast) {
unsigned OldNumBuckets = NumBuckets;
BucketT *OldBuckets = Buckets;
@@ -1107,6 +1118,13 @@ class SmallDenseMap
this->BaseT::initEmpty();
}
+ // Put the zombie instance in a known good state after a move.
+ void kill() {
+ deallocateBuckets();
+ Small = false;
+ new (getLargeRep()) LargeRep{nullptr, 0};
+ }
+
void grow(unsigned AtLeast) {
if (AtLeast > InlineBuckets)
AtLeast = std::max<unsigned>(64, NextPowerOf2(AtLeast - 1));
@@ -1117,14 +1135,13 @@ class SmallDenseMap
if (Tmp.Small) {
// Use moveFrom in those rare cases where we stay in the small mode. This
// can happen when we have many tombstones.
+ Small = true;
this->BaseT::initEmpty();
this->moveFrom(Tmp);
- Tmp.Small = false;
- Tmp.getLargeRep()->NumBuckets = 0;
} else {
- deallocateBuckets();
Small = false;
- NumTombstones = 0;
+ NumEntries = Tmp.NumEntries;
+ NumTombstones = Tmp.NumTombstones;
*getLargeRep() = std::move(*Tmp.getLargeRep());
Tmp.getLargeRep()->NumBuckets = 0;
}
More information about the llvm-commits
mailing list