1
+ // Seemingly inconsequential code changes to this file can lead to measurable
2
+ // performance impact on compilation times, due at least in part to the fact
3
+ // that the layout code gets called from many instantiations of the various
4
+ // collections, resulting in having to optimize down excess IR multiple times.
5
+ // Your performance intuition is useless. Run perf.
6
+
1
7
use crate :: cmp;
2
8
use crate :: fmt;
3
9
use crate :: mem:: { self , ValidAlign } ;
@@ -85,6 +91,17 @@ impl Layout {
85
91
unsafe { Ok ( Layout :: from_size_align_unchecked ( size, align) ) }
86
92
}
87
93
94
+ /// Internal helper constructor to skip revalidating alignment validity.
95
+ #[ inline]
96
+ const fn from_size_valid_align ( size : usize , align : ValidAlign ) -> Result < Self , LayoutError > {
97
+ // See above for the correctness of this check.
98
+ if size > isize:: MAX as usize - ( align. as_nonzero ( ) . get ( ) - 1 ) {
99
+ return Err ( LayoutError ) ;
100
+ }
101
+ // SAFTEY: as above, this check is sufficient.
102
+ Ok ( Layout { size, align } )
103
+ }
104
+
88
105
/// Creates a layout, bypassing all checks.
89
106
///
90
107
/// # Safety
@@ -126,10 +143,9 @@ impl Layout {
126
143
#[ inline]
127
144
pub const fn new < T > ( ) -> Self {
128
145
let ( size, align) = size_align :: < T > ( ) ;
129
- // SAFETY: the align is guaranteed by Rust to be a power of two and
130
- // the size+align combo is guaranteed to fit in our address space. As a
131
- // result use the unchecked constructor here to avoid inserting code
132
- // that panics if it isn't optimized well enough.
146
+ // SAFETY: if the type is instantiated, rustc already ensures that its
147
+ // layout is valid. Use the unchecked constructor to avoid inserting a
148
+ // panicking codepath that needs to be optimized out.
133
149
unsafe { Layout :: from_size_align_unchecked ( size, align) }
134
150
}
135
151
@@ -141,7 +157,6 @@ impl Layout {
141
157
#[ inline]
142
158
pub fn for_value < T : ?Sized > ( t : & T ) -> Self {
143
159
let ( size, align) = ( mem:: size_of_val ( t) , mem:: align_of_val ( t) ) ;
144
- debug_assert ! ( Layout :: from_size_align( size, align) . is_ok( ) ) ;
145
160
// SAFETY: see rationale in `new` for why this is using the unsafe variant
146
161
unsafe { Layout :: from_size_align_unchecked ( size, align) }
147
162
}
@@ -176,7 +191,6 @@ impl Layout {
176
191
pub unsafe fn for_value_raw < T : ?Sized > ( t : * const T ) -> Self {
177
192
// SAFETY: we pass along the prerequisites of these functions to the caller
178
193
let ( size, align) = unsafe { ( mem:: size_of_val_raw ( t) , mem:: align_of_val_raw ( t) ) } ;
179
- debug_assert ! ( Layout :: from_size_align( size, align) . is_ok( ) ) ;
180
194
// SAFETY: see rationale in `new` for why this is using the unsafe variant
181
195
unsafe { Layout :: from_size_align_unchecked ( size, align) }
182
196
}
@@ -280,8 +294,7 @@ impl Layout {
280
294
// > less than or equal to `isize::MAX`)
281
295
let new_size = self . size ( ) + pad;
282
296
283
- // SAFETY: self.align is already known to be valid and new_size has been
284
- // padded already.
297
+ // SAFETY: padded size is guaranteed to not exceed `isize::MAX`.
285
298
unsafe { Layout :: from_size_align_unchecked ( new_size, self . align ( ) ) }
286
299
}
287
300
@@ -304,7 +317,7 @@ impl Layout {
304
317
let alloc_size = padded_size. checked_mul ( n) . ok_or ( LayoutError ) ?;
305
318
306
319
// The safe constructor is called here to enforce the isize size limit.
307
- Layout :: from_size_align ( alloc_size, self . align ( ) ) . map ( |layout| ( layout, padded_size) )
320
+ Layout :: from_size_valid_align ( alloc_size, self . align ) . map ( |layout| ( layout, padded_size) )
308
321
}
309
322
310
323
/// Creates a layout describing the record for `self` followed by
@@ -355,14 +368,14 @@ impl Layout {
355
368
#[ stable( feature = "alloc_layout_manipulation" , since = "1.44.0" ) ]
356
369
#[ inline]
357
370
pub fn extend ( & self , next : Self ) -> Result < ( Self , usize ) , LayoutError > {
358
- let new_align = cmp:: max ( self . align ( ) , next. align ( ) ) ;
371
+ let new_align = cmp:: max ( self . align , next. align ) ;
359
372
let pad = self . padding_needed_for ( next. align ( ) ) ;
360
373
361
374
let offset = self . size ( ) . checked_add ( pad) . ok_or ( LayoutError ) ?;
362
375
let new_size = offset. checked_add ( next. size ( ) ) . ok_or ( LayoutError ) ?;
363
376
364
377
// The safe constructor is called here to enforce the isize size limit.
365
- let layout = Layout :: from_size_align ( new_size, new_align) ?;
378
+ let layout = Layout :: from_size_valid_align ( new_size, new_align) ?;
366
379
Ok ( ( layout, offset) )
367
380
}
368
381
@@ -383,7 +396,7 @@ impl Layout {
383
396
pub fn repeat_packed ( & self , n : usize ) -> Result < Self , LayoutError > {
384
397
let size = self . size ( ) . checked_mul ( n) . ok_or ( LayoutError ) ?;
385
398
// The safe constructor is called here to enforce the isize size limit.
386
- Layout :: from_size_align ( size, self . align ( ) )
399
+ Layout :: from_size_valid_align ( size, self . align )
387
400
}
388
401
389
402
/// Creates a layout describing the record for `self` followed by
@@ -397,7 +410,7 @@ impl Layout {
397
410
pub fn extend_packed ( & self , next : Self ) -> Result < Self , LayoutError > {
398
411
let new_size = self . size ( ) . checked_add ( next. size ( ) ) . ok_or ( LayoutError ) ?;
399
412
// The safe constructor is called here to enforce the isize size limit.
400
- Layout :: from_size_align ( new_size, self . align ( ) )
413
+ Layout :: from_size_valid_align ( new_size, self . align )
401
414
}
402
415
403
416
/// Creates a layout describing the record for a `[T; n]`.
@@ -408,7 +421,7 @@ impl Layout {
408
421
pub fn array < T > ( n : usize ) -> Result < Self , LayoutError > {
409
422
let array_size = mem:: size_of :: < T > ( ) . checked_mul ( n) . ok_or ( LayoutError ) ?;
410
423
// The safe constructor is called here to enforce the isize size limit.
411
- Layout :: from_size_align ( array_size, mem :: align_of :: < T > ( ) )
424
+ Layout :: from_size_valid_align ( array_size, ValidAlign :: of :: < T > ( ) )
412
425
}
413
426
}
414
427
0 commit comments