Skip to content

Commit 408bd9d

Browse files
authored
Merge pull request #406 from JustForFun88/find_inner
2 parents f238820 + eaf361b commit 408bd9d

File tree

1 file changed

+24
-2
lines changed

1 file changed

+24
-2
lines changed

src/raw/mod.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1622,17 +1622,39 @@ impl<A: Allocator + Clone> RawTableInner<A> {
16221622
}
16231623
}
16241624

1625-
/// Searches for an element in the table. This uses dynamic dispatch to reduce the amount of
1626-
/// code generated, but it is eliminated by LLVM optimizations.
1625+
/// Searches for an element in a table, returning the `index` of the found element.
1626+
/// This uses dynamic dispatch to reduce the amount of code generated, but it is
1627+
/// eliminated by LLVM optimizations.
1628+
///
1629+
/// This function does not make any changes to the `data` part of the table, or any
1630+
/// changes to the `items` or `growth_left` field of the table.
1631+
///
1632+
/// The table must have at least 1 empty `bucket`, otherwise, if the
1633+
/// `eq: &mut dyn FnMut(usize) -> bool` function does not return `true`,
1634+
/// this function will also never return (will go into an infinite loop).
16271635
#[inline(always)]
16281636
fn find_inner(&self, hash: u64, eq: &mut dyn FnMut(usize) -> bool) -> Option<usize> {
16291637
let h2_hash = h2(hash);
16301638
let mut probe_seq = self.probe_seq(hash);
16311639

16321640
loop {
1641+
// SAFETY:
1642+
// * `ProbeSeq.pos` cannot be greater than `self.bucket_mask = self.buckets() - 1`
1643+
// of the table due to masking with `self.bucket_mask`.
1644+
//
1645+
// * Even if `ProbeSeq.pos` returns `position == self.bucket_mask`, it is safe to
1646+
// call `Group::load` due to the extended control bytes range, which is
1647+
// `self.bucket_mask + 1 + Group::WIDTH` (in fact, this means that the last control
1648+
// byte will never be read for the allocated table);
1649+
//
1650+
// * Also, even if `RawTableInner` is not already allocated, `ProbeSeq.pos` will
1651+
// always return "0" (zero), so Group::load will read unaligned `Group::static_empty()`
1652+
// bytes, which is safe (see RawTableInner::new_in).
16331653
let group = unsafe { Group::load(self.ctrl(probe_seq.pos)) };
16341654

16351655
for bit in group.match_byte(h2_hash) {
1656+
// This is the same as `(probe_seq.pos + bit) % self.buckets()` because the number
1657+
// of buckets is a power of two, and `self.bucket_mask = self.buckets() - 1`.
16361658
let index = (probe_seq.pos + bit) & self.bucket_mask;
16371659

16381660
if likely(eq(index)) {

0 commit comments

Comments
 (0)