Skip to content

Commit 9c5d534

Browse files
committed
Auto merge of #106 - Amanieu:insert_on_tombstone, r=Amanieu
Do not grow the container if an insertion is on a tombstone. Rebased and fixed version of #75.
2 parents 49cfef7 + c59bc90 commit 9c5d534

File tree

1 file changed

+22
-2
lines changed

1 file changed

+22
-2
lines changed

src/raw/mod.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,7 @@ impl<T> RawTable<T> {
374374
buckets: usize,
375375
fallability: Fallibility,
376376
) -> Result<Self, CollectionAllocErr> {
377+
debug_assert!(buckets.is_power_of_two());
377378
let (layout, data_offset) =
378379
calculate_layout::<T>(buckets).ok_or_else(|| fallability.capacity_overflow())?;
379380
let ctrl = NonNull::new(alloc(layout)).ok_or_else(|| fallability.alloc_err(layout))?;
@@ -452,6 +453,7 @@ impl<T> RawTable<T> {
452453
#[inline]
453454
pub unsafe fn erase_no_drop(&mut self, item: &Bucket<T>) {
454455
let index = self.bucket_index(item);
456+
debug_assert!(is_full(*self.ctrl(index)));
455457
let index_before = index.wrapping_sub(Group::WIDTH) & self.bucket_mask;
456458
let empty_before = Group::load(self.ctrl(index_before)).match_empty();
457459
let empty_after = Group::load(self.ctrl(index)).match_empty();
@@ -825,8 +827,25 @@ impl<T> RawTable<T> {
825827
/// This does not check if the given element already exists in the table.
826828
#[inline]
827829
pub fn insert(&mut self, hash: u64, value: T, hasher: impl Fn(&T) -> u64) -> Bucket<T> {
828-
self.reserve(1, hasher);
829-
self.insert_no_grow(hash, value)
830+
unsafe {
831+
let mut index = self.find_insert_slot(hash);
832+
833+
// We can avoid growing the table once we have reached our load
834+
// factor if we are replacing a tombstone. This works since the
835+
// number of EMPTY slots does not change in this case.
836+
let old_ctrl = *self.ctrl(index);
837+
if unlikely(self.growth_left == 0 && special_is_empty(old_ctrl)) {
838+
self.reserve(1, hasher);
839+
index = self.find_insert_slot(hash);
840+
}
841+
842+
let bucket = self.bucket(index);
843+
self.growth_left -= special_is_empty(old_ctrl) as usize;
844+
self.set_ctrl(index, h2(hash));
845+
bucket.write(value);
846+
self.items += 1;
847+
bucket
848+
}
830849
}
831850

832851
/// Inserts a new element into the table, without growing the table.
@@ -835,6 +854,7 @@ impl<T> RawTable<T> {
835854
///
836855
/// This does not check if the given element already exists in the table.
837856
#[inline]
857+
#[cfg(feature = "rustc-internal-api")]
838858
pub fn insert_no_grow(&mut self, hash: u64, value: T) -> Bucket<T> {
839859
unsafe {
840860
let index = self.find_insert_slot(hash);

0 commit comments

Comments
 (0)