From 029ba5dfa880bb33e99ca7e00e1dfe48cdd7ef95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20A=2E=20Muci=C3=B1o?= Date: Sun, 9 Aug 2020 11:03:56 -0500 Subject: [PATCH] Port of Hasbrown #183 "Avoid closures to improve compile times" (#14) Port of the relevant changes from hashbrown from rust-lang/hashbrown#183 --- src/map.rs | 98 ++++++++++++++++++++++++++++++++++++------------------ src/set.rs | 18 ++++++++-- 2 files changed, 81 insertions(+), 35 deletions(-) diff --git a/src/map.rs b/src/map.rs index c7505d3..70d6752 100644 --- a/src/map.rs +++ b/src/map.rs @@ -787,7 +787,11 @@ where K: Borrow, Q: Hash + Eq, { - self.get_key_value(k).map(|(_, v)| v) + // Avoid `Option::map` because it bloats LLVM IR. + match self.get_key_value(k) { + Some((_, v)) => Some(v), + None => None, + } } /// Returns the key-value pair corresponding to the supplied key. @@ -816,12 +820,14 @@ where Q: Hash + Eq, { let hash = make_hash(&self.hash_builder, k); - self.table - .find(hash, |x| k.eq(x.0.borrow())) - .map(|item| unsafe { + // Avoid `Option::map` because it bloats LLVM IR. + match self.table.find(hash, |x| k.eq(x.0.borrow())) { + Some(item) => unsafe { let &(ref key, ref value) = item.as_ref(); - (key, value) - }) + Some((key, value)) + }, + None => None, + } } /// Returns the key-value pair corresponding to the supplied key, with a mutable reference to value. @@ -854,12 +860,14 @@ where Q: Hash + Eq, { let hash = make_hash(&self.hash_builder, k); - self.table - .find(hash, |x| k.eq(x.0.borrow())) - .map(|item| unsafe { + // Avoid `Option::map` because it bloats LLVM IR. + match self.table.find(hash, |x| k.eq(x.0.borrow())) { + Some(item) => unsafe { let &mut (ref key, ref mut value) = item.as_mut(); - (key, value) - }) + Some((key, value)) + }, + None => None, + } } /// Returns `true` if the map contains a value for the specified key. @@ -918,9 +926,11 @@ where Q: Hash + Eq, { let hash = make_hash(&self.hash_builder, k); - self.table - .find(hash, |x| k.eq(x.0.borrow())) - .map(|item| unsafe { &mut item.as_mut().1 }) + // Avoid `Option::map` because it bloats LLVM IR. + match self.table.find(hash, |x| k.eq(x.0.borrow())) { + Some(item) => Some(unsafe { &mut item.as_mut().1 }), + None => None, + } } /// Inserts a key-value pair into the map. @@ -995,7 +1005,11 @@ where K: Borrow, Q: Hash + Eq, { - self.remove_entry(k).map(|(_, v)| v) + // Avoid `Option::map` because it bloats LLVM IR. + match self.remove_entry(k) { + Some((_, v)) => Some(v), + None => None, + } } /// Removes a key from the map, returning the stored key and value if the @@ -1478,13 +1492,13 @@ impl<'a, K, V, S> RawEntryBuilder<'a, K, V, S> { where F: FnMut(&K) -> bool, { - self.map - .table - .find(hash, |(k, _)| is_match(k)) - .map(|item| unsafe { + match self.map.table.find(hash, |(k, _)| is_match(k)) { + Some(item) => unsafe { let &(ref key, ref value) = item.as_ref(); - (key, value) - }) + Some((key, value)) + }, + None => None, + } } /// Access an entry by hash. @@ -1947,10 +1961,14 @@ impl<'a, K, V> Iterator for Iter<'a, K, V> { #[cfg_attr(feature = "inline-more", inline)] fn next(&mut self) -> Option<(&'a K, &'a V)> { - self.inner.next().map(|x| unsafe { - let r = x.as_ref(); - (&r.0, &r.1) - }) + // Avoid `Option::map` because it bloats LLVM IR. + match self.inner.next() { + Some(x) => unsafe { + let r = x.as_ref(); + Some((&r.0, &r.1)) + }, + None => None, + } } #[cfg_attr(feature = "inline-more", inline)] fn size_hint(&self) -> (usize, Option) { @@ -1971,10 +1989,14 @@ impl<'a, K, V> Iterator for IterMut<'a, K, V> { #[cfg_attr(feature = "inline-more", inline)] fn next(&mut self) -> Option<(&'a K, &'a mut V)> { - self.inner.next().map(|x| unsafe { - let r = x.as_mut(); - (&r.0, &mut r.1) - }) + // Avoid `Option::map` because it bloats LLVM IR. + match self.inner.next() { + Some(x) => unsafe { + let r = x.as_mut(); + Some((&r.0, &mut r.1)) + }, + None => None, + } } #[cfg_attr(feature = "inline-more", inline)] fn size_hint(&self) -> (usize, Option) { @@ -2030,7 +2052,11 @@ impl<'a, K, V> Iterator for Keys<'a, K, V> { #[cfg_attr(feature = "inline-more", inline)] fn next(&mut self) -> Option<&'a K> { - self.inner.next().map(|(k, _)| k) + // Avoid `Option::map` because it bloats LLVM IR. + match self.inner.next() { + Some((k, _)) => Some(k), + None => None, + } } #[cfg_attr(feature = "inline-more", inline)] fn size_hint(&self) -> (usize, Option) { @@ -2050,7 +2076,11 @@ impl<'a, K, V> Iterator for Values<'a, K, V> { #[cfg_attr(feature = "inline-more", inline)] fn next(&mut self) -> Option<&'a V> { - self.inner.next().map(|(_, v)| v) + // Avoid `Option::map` because it bloats LLVM IR. + match self.inner.next() { + Some((_, v)) => Some(v), + None => None, + } } #[cfg_attr(feature = "inline-more", inline)] fn size_hint(&self) -> (usize, Option) { @@ -2070,7 +2100,11 @@ impl<'a, K, V> Iterator for ValuesMut<'a, K, V> { #[cfg_attr(feature = "inline-more", inline)] fn next(&mut self) -> Option<&'a mut V> { - self.inner.next().map(|(_, v)| v) + // Avoid `Option::map` because it bloats LLVM IR. + match self.inner.next() { + Some((_, v)) => Some(v), + None => None, + } } #[cfg_attr(feature = "inline-more", inline)] fn size_hint(&self) -> (usize, Option) { diff --git a/src/set.rs b/src/set.rs index 744ad5d..02c6c33 100644 --- a/src/set.rs +++ b/src/set.rs @@ -628,7 +628,11 @@ where T: Borrow, Q: Hash + Eq, { - self.map.get_key_value(value).map(|(k, _)| k) + // Avoid `Option::map` because it bloats LLVM IR. + match self.map.get_key_value(value) { + Some((k, _)) => Some(k), + None => None, + } } /// Returns `true` if `self` has no elements in common with `other`. @@ -800,7 +804,11 @@ where T: Borrow, Q: Hash + Eq, { - self.map.remove_entry(value).map(|(k, _)| k) + // Avoid `Option::map` because it bloats LLVM IR. + match self.map.remove_entry(value) { + Some((k, _)) => Some(k), + None => None, + } } } @@ -1188,7 +1196,11 @@ impl Iterator for IntoIter { #[cfg_attr(feature = "inline-more", inline)] fn next(&mut self) -> Option { - self.iter.next().map(|(k, _)| k) + // Avoid `Option::map` because it bloats LLVM IR. + match self.iter.next() { + Some((k, _)) => Some(k), + None => None, + } } #[cfg_attr(feature = "inline-more", inline)] fn size_hint(&self) -> (usize, Option) {