about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-06-04 18:36:50 +0000
committerbors <bors@rust-lang.org>2018-06-04 18:36:50 +0000
commit41affd03eb169830773cd1b11efda562ab81fad0 (patch)
tree0c05503cee2272a9dd4abe4aac25588152ae402c /src/libstd
parentcdc193db993eadab74d9ea439613e8f9d3725ac7 (diff)
parentb69724f37cca68249340e7245e5ac2832d8b2c30 (diff)
downloadrust-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.rs19
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