@@ -213,7 +213,7 @@ fn bucket_mask_to_capacity(bucket_mask: usize) -> usize {
213
213
/// Returns `None` if an overflow occurs.
214
214
#[ inline]
215
215
#[ cfg( feature = "nightly" ) ]
216
- fn calculate_layout < T > ( buckets : usize ) -> Option < ( Layout , usize , usize ) > {
216
+ fn calculate_layout < T > ( buckets : usize ) -> Option < ( Layout , usize ) > {
217
217
debug_assert ! ( buckets. is_power_of_two( ) ) ;
218
218
219
219
// Misc fields of the map
@@ -232,23 +232,23 @@ fn calculate_layout<T>(buckets: usize) -> Option<(Layout, usize, usize)> {
232
232
// Array of buckets
233
233
let data = Layout :: array :: < T > ( buckets) . ok ( ) ?;
234
234
235
- let ( temp_layout, ctrl_offset ) = header. extend ( ctrl) . ok ( ) ?;
235
+ let ( temp_layout, _ctrl_offset ) = header. extend ( ctrl) . ok ( ) ?;
236
236
let ( final_layout, data_offset) = temp_layout. extend ( data) . ok ( ) ?;
237
237
238
- Some ( ( final_layout, ctrl_offset , data_offset) )
238
+ Some ( ( final_layout, data_offset) )
239
239
}
240
240
241
241
// Returns a Layout which describes the allocation required for a hash table,
242
242
// and the offset of the buckets in the allocation.
243
243
#[ inline]
244
244
#[ 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 ) > {
246
246
debug_assert ! ( buckets. is_power_of_two( ) ) ;
247
247
248
248
// Manual layout calculation since Layout methods are not yet stable.
249
249
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 ( usize :: max ( mem:: align_of :: < Header < T > > ( ) , ctrl_align) , data_align ) ;
252
252
253
253
let data_size = mem:: size_of :: < T > ( ) . checked_mul ( buckets) ?;
254
254
let ctrl_size = buckets + Group :: WIDTH ;
@@ -260,11 +260,18 @@ fn calculate_layout<T>(buckets: usize) -> Option<(Layout, usize, usize)> {
260
260
261
261
Some ( (
262
262
unsafe { Layout :: from_size_align_unchecked ( len, header_align) } ,
263
- ctrl_offset,
264
263
data_offset,
265
264
) )
266
265
}
267
266
267
+ #[ inline]
268
+ fn ctrl_offset < T > ( ) -> usize {
269
+ let header_size = mem:: size_of :: < Header < T > > ( ) ;
270
+ let ctrl_align = Group :: WIDTH ;
271
+ let mask = ctrl_align - 1 ;
272
+ ( header_size + mask) & !mask
273
+ }
274
+
268
275
#[ inline]
269
276
#[ cfg( not( feature = "nightly" ) ) ]
270
277
fn round_size_to_align ( size : usize , align : usize ) -> Option < usize > {
@@ -365,9 +372,6 @@ pub struct Header<T> {
365
372
// number of buckets in the table.
366
373
bucket_mask : usize ,
367
374
368
- // Pointer to the array of control bytes
369
- ctrl : * const u8 ,
370
-
371
375
// Pointer to the array of buckets
372
376
data : * const T ,
373
377
@@ -378,22 +382,31 @@ pub struct Header<T> {
378
382
items : usize ,
379
383
}
380
384
381
- static EMPTY_SINGLETON : Header < ( ) > = {
385
+ static EMPTY_SINGLETON : & ' static Header < ( ) > = {
382
386
union AlignedBytes {
383
387
_align : Group ,
384
388
bytes : [ u8 ; Group :: WIDTH ] ,
385
389
} ;
386
- static ALIGNED_BYTES : AlignedBytes = AlignedBytes {
387
- bytes : [ EMPTY ; Group :: WIDTH ] ,
388
- } ;
389
390
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 ,
391
+ #[ repr( C ) ]
392
+ struct HeaderWithCtrl {
393
+ header : Header < ( ) > ,
394
+ bytes : AlignedBytes ,
396
395
}
396
+
397
+ static ALIGNED_HEADER_WITH_CTRL : HeaderWithCtrl = HeaderWithCtrl {
398
+ header : Header {
399
+ data : core:: ptr:: null ( ) ,
400
+ bucket_mask : 0 ,
401
+ items : 0 ,
402
+ growth_left : 0 ,
403
+ } ,
404
+ bytes : AlignedBytes {
405
+ bytes : [ EMPTY ; Group :: WIDTH ] ,
406
+ } ,
407
+ } ;
408
+
409
+ & ALIGNED_HEADER_WITH_CTRL . header
397
410
} ;
398
411
399
412
unsafe impl < T : Sync > Sync for Header < T > { }
@@ -407,7 +420,7 @@ impl<T> RawTable<T> {
407
420
#[ inline]
408
421
pub fn new ( ) -> Self {
409
422
Self {
410
- header : NonNull :: from ( & EMPTY_SINGLETON ) . cast ( ) ,
423
+ header : NonNull :: from ( EMPTY_SINGLETON ) . cast ( ) ,
411
424
marker : PhantomData ,
412
425
}
413
426
}
@@ -420,16 +433,14 @@ impl<T> RawTable<T> {
420
433
buckets : usize ,
421
434
fallability : Fallibility ,
422
435
) -> Result < Self , CollectionAllocErr > {
423
- let ( layout, ctrl_offset , data_offset) =
436
+ let ( layout, data_offset) =
424
437
calculate_layout :: < T > ( buckets) . ok_or_else ( || fallability. capacity_overflow ( ) ) ?;
425
438
426
439
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 ;
428
440
let data = header. as_ptr ( ) . add ( data_offset) as * mut T ;
429
441
430
442
let header = header. cast ( ) ;
431
443
* header. as_ptr ( ) = Header {
432
- ctrl,
433
444
data,
434
445
bucket_mask : buckets - 1 ,
435
446
items : 0 ,
@@ -472,7 +483,7 @@ impl<T> RawTable<T> {
472
483
/// Deallocates the table without dropping any entries.
473
484
#[ inline]
474
485
unsafe fn free_buckets ( & mut self ) {
475
- let ( layout, _, _ ) =
486
+ let ( layout, _) =
476
487
calculate_layout :: < T > ( self . buckets ( ) ) . unwrap_or_else ( || hint:: unreachable_unchecked ( ) ) ;
477
488
dealloc ( self . header . as_ptr ( ) as * mut u8 , layout) ;
478
489
}
@@ -506,7 +517,7 @@ impl<T> RawTable<T> {
506
517
/// Returns a pointer to the ctrl array
507
518
#[ inline]
508
519
fn ctrl_ptr ( & self ) -> * mut u8 {
509
- self . header ( ) . ctrl as * mut u8
520
+ unsafe { ( self . header . as_ptr ( ) as * mut u8 ) . add ( ctrl_offset :: < T > ( ) ) }
510
521
}
511
522
512
523
#[ inline]
@@ -1000,7 +1011,7 @@ impl<T> RawTable<T> {
1000
1011
/// of 0.
1001
1012
#[ inline]
1002
1013
fn is_empty_singleton ( & self ) -> bool {
1003
- self . header ( ) as * const Header < T > == & EMPTY_SINGLETON as * const _ as * const Header < T >
1014
+ self . header ( ) as * const Header < T > == EMPTY_SINGLETON as * const _ as * const Header < T >
1004
1015
}
1005
1016
1006
1017
/// Returns an iterator over every element in the table. It is up to
@@ -1037,7 +1048,7 @@ impl<T> RawTable<T> {
1037
1048
let alloc = if self . is_empty_singleton ( ) {
1038
1049
None
1039
1050
} else {
1040
- let ( layout, _, _ ) = calculate_layout :: < T > ( self . buckets ( ) )
1051
+ let ( layout, _) = calculate_layout :: < T > ( self . buckets ( ) )
1041
1052
. unwrap_or_else ( || unsafe { hint:: unreachable_unchecked ( ) } ) ;
1042
1053
Some ( ( self . header . cast ( ) , layout) )
1043
1054
} ;
0 commit comments