diff options
| author | bors <bors@rust-lang.org> | 2018-06-04 18:36:50 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2018-06-04 18:36:50 +0000 |
| commit | 41affd03eb169830773cd1b11efda562ab81fad0 (patch) | |
| tree | 0c05503cee2272a9dd4abe4aac25588152ae402c /src/libstd | |
| parent | cdc193db993eadab74d9ea439613e8f9d3725ac7 (diff) | |
| parent | b69724f37cca68249340e7245e5ac2832d8b2c30 (diff) | |
| download | rust-41affd03eb169830773cd1b11efda562ab81fad0.tar.gz rust-41affd03eb169830773cd1b11efda562ab81fad0.zip | |
Auto merge of #51340 - Amanieu:hashmap_layout2, r=SimonSapin
Optimize layout calculations in HashMap This now produces the same assembly code as the previous implementation. cc #51163 @nnethercote @gnzlbg @andjo403
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/collections/hash/table.rs | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index c62a409ac02..d997fb28d42 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -15,6 +15,7 @@ use mem::{size_of, needs_drop}; use mem; use ops::{Deref, DerefMut}; use ptr::{self, Unique, NonNull}; +use hint; use self::BucketState::*; @@ -655,7 +656,17 @@ impl<K, V, M> GapThenFull<K, V, M> fn calculate_layout<K, V>(capacity: usize) -> Result<(Layout, usize), LayoutErr> { let hashes = Layout::array::<HashUint>(capacity)?; let pairs = Layout::array::<(K, V)>(capacity)?; - hashes.extend(pairs) + hashes.extend(pairs).map(|(layout, _)| { + // LLVM seems to have trouble properly const-propagating pairs.align(), + // possibly due to the use of NonZeroUsize. This little hack allows it + // to generate optimal code. + // + // See https://github.com/rust-lang/rust/issues/51346 for more details. + ( + layout, + hashes.size() + hashes.padding_needed_for(mem::align_of::<(K, V)>()), + ) + }) } pub(crate) enum Fallibility { @@ -711,7 +722,8 @@ impl<K, V> RawTable<K, V> { } fn raw_bucket_at(&self, index: usize) -> RawBucket<K, V> { - let (_, pairs_offset) = calculate_layout::<K, V>(self.capacity()).unwrap(); + let (_, pairs_offset) = calculate_layout::<K, V>(self.capacity()) + .unwrap_or_else(|_| unsafe { hint::unreachable_unchecked() }); let buffer = self.hashes.ptr() as *mut u8; unsafe { RawBucket { @@ -1109,7 +1121,8 @@ unsafe impl<#[may_dangle] K, #[may_dangle] V> Drop for RawTable<K, V> { } } - let (layout, _) = calculate_layout::<K, V>(self.capacity()).unwrap(); + let (layout, _) = calculate_layout::<K, V>(self.capacity()) + .unwrap_or_else(|_| unsafe { hint::unreachable_unchecked() }); unsafe { Global.dealloc(NonNull::new_unchecked(self.hashes.ptr()).as_opaque(), layout); // Remember how everything was allocated out of one buffer |
