@@ -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,26 @@ 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 (
252
+ usize:: max ( mem:: align_of :: < Header < T > > ( ) , ctrl_align) ,
253
+ data_align,
254
+ ) ;
252
255
253
256
let data_size = mem:: size_of :: < T > ( ) . checked_mul ( buckets) ?;
254
257
let ctrl_size = buckets + Group :: WIDTH ;
@@ -260,11 +263,18 @@ fn calculate_layout<T>(buckets: usize) -> Option<(Layout, usize, usize)> {
260
263
261
264
Some ( (
262
265
unsafe { Layout :: from_size_align_unchecked ( len, header_align) } ,
263
- ctrl_offset,
264
266
data_offset,
265
267
) )
266
268
}
267
269
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
+
268
278
#[ inline]
269
279
#[ cfg( not( feature = "nightly" ) ) ]
270
280
fn round_size_to_align ( size : usize , align : usize ) -> Option < usize > {
@@ -365,9 +375,6 @@ pub struct Header<T> {
365
375
// number of buckets in the table.
366
376
bucket_mask : usize ,
367
377
368
- // Pointer to the array of control bytes
369
- ctrl : * const u8 ,
370
-
371
378
// Pointer to the array of buckets
372
379
data : * const T ,
373
380
@@ -378,22 +385,31 @@ pub struct Header<T> {
378
385
items : usize ,
379
386
}
380
387
381
- static EMPTY_SINGLETON : Header < ( ) > = {
388
+ static EMPTY_SINGLETON : & ' static Header < ( ) > = {
382
389
union AlignedBytes {
383
390
_align : Group ,
384
391
bytes : [ u8 ; Group :: WIDTH ] ,
385
392
} ;
386
- static ALIGNED_BYTES : AlignedBytes = AlignedBytes {
387
- bytes : [ EMPTY ; Group :: WIDTH ] ,
388
- } ;
389
393
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 ,
396
398
}
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
397
413
} ;
398
414
399
415
unsafe impl < T : Sync > Sync for Header < T > { }
@@ -407,7 +423,7 @@ impl<T> RawTable<T> {
407
423
#[ inline]
408
424
pub fn new ( ) -> Self {
409
425
Self {
410
- header : NonNull :: from ( & EMPTY_SINGLETON ) . cast ( ) ,
426
+ header : NonNull :: from ( EMPTY_SINGLETON ) . cast ( ) ,
411
427
marker : PhantomData ,
412
428
}
413
429
}
@@ -420,16 +436,14 @@ impl<T> RawTable<T> {
420
436
buckets : usize ,
421
437
fallability : Fallibility ,
422
438
) -> Result < Self , CollectionAllocErr > {
423
- let ( layout, ctrl_offset , data_offset) =
439
+ let ( layout, data_offset) =
424
440
calculate_layout :: < T > ( buckets) . ok_or_else ( || fallability. capacity_overflow ( ) ) ?;
425
441
426
442
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
443
let data = header. as_ptr ( ) . add ( data_offset) as * mut T ;
429
444
430
445
let header = header. cast ( ) ;
431
446
* header. as_ptr ( ) = Header {
432
- ctrl,
433
447
data,
434
448
bucket_mask : buckets - 1 ,
435
449
items : 0 ,
@@ -472,7 +486,7 @@ impl<T> RawTable<T> {
472
486
/// Deallocates the table without dropping any entries.
473
487
#[ inline]
474
488
unsafe fn free_buckets ( & mut self ) {
475
- let ( layout, _, _ ) =
489
+ let ( layout, _) =
476
490
calculate_layout :: < T > ( self . buckets ( ) ) . unwrap_or_else ( || hint:: unreachable_unchecked ( ) ) ;
477
491
dealloc ( self . header . as_ptr ( ) as * mut u8 , layout) ;
478
492
}
@@ -506,7 +520,7 @@ impl<T> RawTable<T> {
506
520
/// Returns a pointer to the ctrl array
507
521
#[ inline]
508
522
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 > ( ) ) }
510
524
}
511
525
512
526
#[ inline]
@@ -1000,7 +1014,7 @@ impl<T> RawTable<T> {
1000
1014
/// of 0.
1001
1015
#[ inline]
1002
1016
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 >
1004
1018
}
1005
1019
1006
1020
/// Returns an iterator over every element in the table. It is up to
@@ -1037,7 +1051,7 @@ impl<T> RawTable<T> {
1037
1051
let alloc = if self . is_empty_singleton ( ) {
1038
1052
None
1039
1053
} else {
1040
- let ( layout, _, _ ) = calculate_layout :: < T > ( self . buckets ( ) )
1054
+ let ( layout, _) = calculate_layout :: < T > ( self . buckets ( ) )
1041
1055
. unwrap_or_else ( || unsafe { hint:: unreachable_unchecked ( ) } ) ;
1042
1056
Some ( ( self . header . cast ( ) , layout) )
1043
1057
} ;
0 commit comments