Skip to content

Commit

Permalink
38880 don't compute hash when searching an empty HashMap
Browse files Browse the repository at this point in the history
This addresses issue #38880
  • Loading branch information
technicalguy committed Feb 6, 2018
1 parent ca7d839 commit 9bc5986
Showing 1 changed file with 35 additions and 5 deletions.
40 changes: 35 additions & 5 deletions src/libstd/collections/hash/map.rs
Expand Up @@ -397,9 +397,21 @@ pub struct HashMap<K, V, S = RandomState> {
resize_policy: DefaultResizePolicy,
}

/// Search for a pre-hashed key when the hash map is known to be non-empty.
#[inline]
fn search_hashed_nonempty<K, V, M, F>(table: M, hash: SafeHash, is_match: F)
-> InternalEntry<K, V, M>
where M: Deref<Target = RawTable<K, V>>,
F: FnMut(&K) -> bool
{
// Do not check the capacity as an extra branch could slow the lookup.
search_hashed_body(table, hash, is_match)
}

/// Search for a pre-hashed key.
/// If you don't already know the hash, use search or search_mut instead
#[inline]
fn search_hashed<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F) -> InternalEntry<K, V, M>
fn search_hashed<K, V, M, F>(table: M, hash: SafeHash, is_match: F) -> InternalEntry<K, V, M>
where M: Deref<Target = RawTable<K, V>>,
F: FnMut(&K) -> bool
{
Expand All @@ -410,6 +422,16 @@ fn search_hashed<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F) -> Inter
return InternalEntry::TableIsEmpty;
}

search_hashed_body(table, hash, is_match)
}

/// The body of the search_hashed[_nonempty] functions
#[inline]
fn search_hashed_body<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F)
-> InternalEntry<K, V, M>
where M: Deref<Target = RawTable<K, V>>,
F: FnMut(&K) -> bool
{
let size = table.size();
let mut probe = Bucket::new(table, hash);
let mut displacement = 0;
Expand Down Expand Up @@ -550,17 +572,25 @@ impl<K, V, S> HashMap<K, V, S>
where K: Borrow<Q>,
Q: Eq + Hash
{
let hash = self.make_hash(q);
search_hashed(&self.table, hash, |k| q.eq(k.borrow()))
if self.table.capacity() != 0 {
let hash = self.make_hash(q);
search_hashed_nonempty(&self.table, hash, |k| q.eq(k.borrow()))
} else {
InternalEntry::TableIsEmpty
}
}

#[inline]
fn search_mut<'a, Q: ?Sized>(&'a mut self, q: &Q) -> InternalEntry<K, V, &'a mut RawTable<K, V>>
where K: Borrow<Q>,
Q: Eq + Hash
{
let hash = self.make_hash(q);
search_hashed(&mut self.table, hash, |k| q.eq(k.borrow()))
if self.table.capacity() != 0 {
let hash = self.make_hash(q);
search_hashed_nonempty(&mut self.table, hash, |k| q.eq(k.borrow()))
} else {
InternalEntry::TableIsEmpty
}
}

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

0 comments on commit 9bc5986

Please sign in to comment.