Skip to content

Commit 9bc5986

Browse files
committed
38880 don't compute hash when searching an empty HashMap
This addresses issue #38880
1 parent ca7d839 commit 9bc5986

File tree

1 file changed

+35
-5
lines changed
  • src/libstd/collections/hash

1 file changed

+35
-5
lines changed

src/libstd/collections/hash/map.rs

+35-5
Original file line numberDiff line numberDiff line change
@@ -397,9 +397,21 @@ pub struct HashMap<K, V, S = RandomState> {
397397
resize_policy: DefaultResizePolicy,
398398
}
399399

400+
/// Search for a pre-hashed key when the hash map is known to be non-empty.
401+
#[inline]
402+
fn search_hashed_nonempty<K, V, M, F>(table: M, hash: SafeHash, is_match: F)
403+
-> InternalEntry<K, V, M>
404+
where M: Deref<Target = RawTable<K, V>>,
405+
F: FnMut(&K) -> bool
406+
{
407+
// Do not check the capacity as an extra branch could slow the lookup.
408+
search_hashed_body(table, hash, is_match)
409+
}
410+
400411
/// Search for a pre-hashed key.
412+
/// If you don't already know the hash, use search or search_mut instead
401413
#[inline]
402-
fn search_hashed<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F) -> InternalEntry<K, V, M>
414+
fn search_hashed<K, V, M, F>(table: M, hash: SafeHash, is_match: F) -> InternalEntry<K, V, M>
403415
where M: Deref<Target = RawTable<K, V>>,
404416
F: FnMut(&K) -> bool
405417
{
@@ -410,6 +422,16 @@ fn search_hashed<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F) -> Inter
410422
return InternalEntry::TableIsEmpty;
411423
}
412424

425+
search_hashed_body(table, hash, is_match)
426+
}
427+
428+
/// The body of the search_hashed[_nonempty] functions
429+
#[inline]
430+
fn search_hashed_body<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F)
431+
-> InternalEntry<K, V, M>
432+
where M: Deref<Target = RawTable<K, V>>,
433+
F: FnMut(&K) -> bool
434+
{
413435
let size = table.size();
414436
let mut probe = Bucket::new(table, hash);
415437
let mut displacement = 0;
@@ -550,17 +572,25 @@ impl<K, V, S> HashMap<K, V, S>
550572
where K: Borrow<Q>,
551573
Q: Eq + Hash
552574
{
553-
let hash = self.make_hash(q);
554-
search_hashed(&self.table, hash, |k| q.eq(k.borrow()))
575+
if self.table.capacity() != 0 {
576+
let hash = self.make_hash(q);
577+
search_hashed_nonempty(&self.table, hash, |k| q.eq(k.borrow()))
578+
} else {
579+
InternalEntry::TableIsEmpty
580+
}
555581
}
556582

557583
#[inline]
558584
fn search_mut<'a, Q: ?Sized>(&'a mut self, q: &Q) -> InternalEntry<K, V, &'a mut RawTable<K, V>>
559585
where K: Borrow<Q>,
560586
Q: Eq + Hash
561587
{
562-
let hash = self.make_hash(q);
563-
search_hashed(&mut self.table, hash, |k| q.eq(k.borrow()))
588+
if self.table.capacity() != 0 {
589+
let hash = self.make_hash(q);
590+
search_hashed_nonempty(&mut self.table, hash, |k| q.eq(k.borrow()))
591+
} else {
592+
InternalEntry::TableIsEmpty
593+
}
564594
}
565595

566596
// The caller should ensure that invariants by Robin Hood Hashing hold

0 commit comments

Comments
 (0)