@@ -213,7 +213,7 @@ fn bucket_mask_to_capacity(bucket_mask: usize) -> usize {
213213/// Returns `None` if an overflow occurs.
214214#[ inline]
215215#[ cfg( feature = "nightly" ) ]
216- fn calculate_layout < T > ( buckets : usize ) -> Option < ( Layout , usize , usize ) > {
216+ fn calculate_layout < T > ( buckets : usize ) -> Option < ( Layout , usize ) > {
217217 debug_assert ! ( buckets. is_power_of_two( ) ) ;
218218
219219 // Misc fields of the map
@@ -232,23 +232,26 @@ fn calculate_layout<T>(buckets: usize) -> Option<(Layout, usize, usize)> {
232232 // Array of buckets
233233 let data = Layout :: array :: < T > ( buckets) . ok ( ) ?;
234234
235- let ( temp_layout, ctrl_offset ) = header. extend ( ctrl) . ok ( ) ?;
235+ let ( temp_layout, _ctrl_offset ) = header. extend ( ctrl) . ok ( ) ?;
236236 let ( final_layout, data_offset) = temp_layout. extend ( data) . ok ( ) ?;
237237
238- Some ( ( final_layout, ctrl_offset , data_offset) )
238+ Some ( ( final_layout, data_offset) )
239239}
240240
241241// Returns a Layout which describes the allocation required for a hash table,
242242// and the offset of the buckets in the allocation.
243243#[ inline]
244244#[ cfg( not( feature = "nightly" ) ) ]
245- fn calculate_layout < T > ( buckets : usize ) -> Option < ( Layout , usize , usize ) > {
245+ fn calculate_layout < T > ( buckets : usize ) -> Option < ( Layout , usize ) > {
246246 debug_assert ! ( buckets. is_power_of_two( ) ) ;
247247
248248 // Manual layout calculation since Layout methods are not yet stable.
249249 let data_align = mem:: align_of :: < T > ( ) ;
250- let ctrl_align = usize:: max ( Group :: WIDTH , data_align) ;
251- let header_align = usize:: max ( mem:: align_of :: < Header < T > > ( ) , ctrl_align) ;
250+ let ctrl_align = Group :: WIDTH ;
251+ let header_align = usize:: max (
252+ usize:: max ( mem:: align_of :: < Header < T > > ( ) , ctrl_align) ,
253+ data_align,
254+ ) ;
252255
253256 let data_size = mem:: size_of :: < T > ( ) . checked_mul ( buckets) ?;
254257 let ctrl_size = buckets + Group :: WIDTH ;
@@ -260,11 +263,18 @@ fn calculate_layout<T>(buckets: usize) -> Option<(Layout, usize, usize)> {
260263
261264 Some ( (
262265 unsafe { Layout :: from_size_align_unchecked ( len, header_align) } ,
263- ctrl_offset,
264266 data_offset,
265267 ) )
266268}
267269
270+ #[ inline]
271+ fn ctrl_offset < T > ( ) -> usize {
272+ let header_size = mem:: size_of :: < Header < T > > ( ) ;
273+ let ctrl_align = Group :: WIDTH ;
274+ let mask = ctrl_align - 1 ;
275+ ( header_size + mask) & !mask
276+ }
277+
268278#[ inline]
269279#[ cfg( not( feature = "nightly" ) ) ]
270280fn round_size_to_align ( size : usize , align : usize ) -> Option < usize > {
@@ -365,9 +375,6 @@ pub struct Header<T> {
365375 // number of buckets in the table.
366376 bucket_mask : usize ,
367377
368- // Pointer to the array of control bytes
369- ctrl : * const u8 ,
370-
371378 // Pointer to the array of buckets
372379 data : * const T ,
373380
@@ -378,22 +385,31 @@ pub struct Header<T> {
378385 items : usize ,
379386}
380387
381- static EMPTY_SINGLETON : Header < ( ) > = {
388+ static EMPTY_SINGLETON : & ' static Header < ( ) > = {
382389 union AlignedBytes {
383390 _align : Group ,
384391 bytes : [ u8 ; Group :: WIDTH ] ,
385392 } ;
386- static ALIGNED_BYTES : AlignedBytes = AlignedBytes {
387- bytes : [ EMPTY ; Group :: WIDTH ] ,
388- } ;
389393
390- Header {
391- data : core:: ptr:: null ( ) ,
392- ctrl : unsafe { & ALIGNED_BYTES . bytes as * const u8 } ,
393- bucket_mask : 0 ,
394- items : 0 ,
395- growth_left : 0 ,
394+ #[ repr( C ) ]
395+ struct HeaderWithCtrl {
396+ header : Header < ( ) > ,
397+ bytes : AlignedBytes ,
396398 }
399+
400+ static ALIGNED_HEADER_WITH_CTRL : HeaderWithCtrl = HeaderWithCtrl {
401+ header : Header {
402+ data : core:: ptr:: null ( ) ,
403+ bucket_mask : 0 ,
404+ items : 0 ,
405+ growth_left : 0 ,
406+ } ,
407+ bytes : AlignedBytes {
408+ bytes : [ EMPTY ; Group :: WIDTH ] ,
409+ } ,
410+ } ;
411+
412+ & ALIGNED_HEADER_WITH_CTRL . header
397413} ;
398414
399415unsafe impl < T : Sync > Sync for Header < T > { }
@@ -407,7 +423,7 @@ impl<T> RawTable<T> {
407423 #[ inline]
408424 pub fn new ( ) -> Self {
409425 Self {
410- header : NonNull :: from ( & EMPTY_SINGLETON ) . cast ( ) ,
426+ header : NonNull :: from ( EMPTY_SINGLETON ) . cast ( ) ,
411427 marker : PhantomData ,
412428 }
413429 }
@@ -420,16 +436,14 @@ impl<T> RawTable<T> {
420436 buckets : usize ,
421437 fallability : Fallibility ,
422438 ) -> Result < Self , CollectionAllocErr > {
423- let ( layout, ctrl_offset , data_offset) =
439+ let ( layout, data_offset) =
424440 calculate_layout :: < T > ( buckets) . ok_or_else ( || fallability. capacity_overflow ( ) ) ?;
425441
426442 let header = NonNull :: new ( alloc ( layout) ) . ok_or_else ( || fallability. alloc_err ( layout) ) ?;
427- let ctrl = header. as_ptr ( ) . add ( ctrl_offset) as * mut u8 ;
428443 let data = header. as_ptr ( ) . add ( data_offset) as * mut T ;
429444
430445 let header = header. cast ( ) ;
431446 * header. as_ptr ( ) = Header {
432- ctrl,
433447 data,
434448 bucket_mask : buckets - 1 ,
435449 items : 0 ,
@@ -472,7 +486,7 @@ impl<T> RawTable<T> {
472486 /// Deallocates the table without dropping any entries.
473487 #[ inline]
474488 unsafe fn free_buckets ( & mut self ) {
475- let ( layout, _, _ ) =
489+ let ( layout, _) =
476490 calculate_layout :: < T > ( self . buckets ( ) ) . unwrap_or_else ( || hint:: unreachable_unchecked ( ) ) ;
477491 dealloc ( self . header . as_ptr ( ) as * mut u8 , layout) ;
478492 }
@@ -506,7 +520,7 @@ impl<T> RawTable<T> {
506520 /// Returns a pointer to the ctrl array
507521 #[ inline]
508522 fn ctrl_ptr ( & self ) -> * mut u8 {
509- self . header ( ) . ctrl as * mut u8
523+ unsafe { ( self . header . as_ptr ( ) as * mut u8 ) . add ( ctrl_offset :: < T > ( ) ) }
510524 }
511525
512526 #[ inline]
@@ -1000,7 +1014,7 @@ impl<T> RawTable<T> {
10001014 /// of 0.
10011015 #[ inline]
10021016 fn is_empty_singleton ( & self ) -> bool {
1003- self . header ( ) as * const Header < T > == & EMPTY_SINGLETON as * const _ as * const Header < T >
1017+ self . header ( ) as * const Header < T > == EMPTY_SINGLETON as * const _ as * const Header < T >
10041018 }
10051019
10061020 /// Returns an iterator over every element in the table. It is up to
@@ -1037,7 +1051,7 @@ impl<T> RawTable<T> {
10371051 let alloc = if self . is_empty_singleton ( ) {
10381052 None
10391053 } else {
1040- let ( layout, _, _ ) = calculate_layout :: < T > ( self . buckets ( ) )
1054+ let ( layout, _) = calculate_layout :: < T > ( self . buckets ( ) )
10411055 . unwrap_or_else ( || unsafe { hint:: unreachable_unchecked ( ) } ) ;
10421056 Some ( ( self . header . cast ( ) , layout) )
10431057 } ;
0 commit comments