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
-
7
1
use crate :: cmp;
8
2
use crate :: fmt;
9
3
use crate :: mem:: { self , ValidAlign } ;
@@ -68,13 +62,6 @@ impl Layout {
68
62
return Err ( LayoutError ) ;
69
63
}
70
64
71
- // SAFETY: just checked that align is a power of two.
72
- Layout :: from_size_valid_align ( size, unsafe { ValidAlign :: new_unchecked ( align) } )
73
- }
74
-
75
- /// Internal helper constructor to skip revalidating alignment validity.
76
- #[ inline]
77
- const fn from_size_valid_align ( size : usize , align : ValidAlign ) -> Result < Self , LayoutError > {
78
65
// (power-of-two implies align != 0.)
79
66
80
67
// Rounded up size is:
@@ -89,12 +76,13 @@ impl Layout {
89
76
//
90
77
// Above implies that checking for summation overflow is both
91
78
// necessary and sufficient.
92
- if size > isize:: MAX as usize - ( align. as_nonzero ( ) . get ( ) - 1 ) {
79
+ if size > isize:: MAX as usize - ( align - 1 ) {
93
80
return Err ( LayoutError ) ;
94
81
}
95
82
96
- // SAFETY: Layout::size invariants checked above.
97
- Ok ( Layout { size, align } )
83
+ // SAFETY: the conditions for `from_size_align_unchecked` have been
84
+ // checked above.
85
+ unsafe { Ok ( Layout :: from_size_align_unchecked ( size, align) ) }
98
86
}
99
87
100
88
/// Creates a layout, bypassing all checks.
@@ -108,8 +96,8 @@ impl Layout {
108
96
#[ must_use]
109
97
#[ inline]
110
98
pub const unsafe fn from_size_align_unchecked ( size : usize , align : usize ) -> Self {
111
- // SAFETY: the caller is required to uphold the preconditions .
112
- unsafe { Layout { size, align : ValidAlign :: new_unchecked ( align) } }
99
+ // SAFETY: the caller must ensure that `align` is a power of two .
100
+ Layout { size, align : unsafe { ValidAlign :: new_unchecked ( align) } }
113
101
}
114
102
115
103
/// The minimum size in bytes for a memory block of this layout.
@@ -138,9 +126,10 @@ impl Layout {
138
126
#[ inline]
139
127
pub const fn new < T > ( ) -> Self {
140
128
let ( size, align) = size_align :: < T > ( ) ;
141
- // SAFETY: if the type is instantiated, rustc already ensures that its
142
- // layout is valid. Use the unchecked constructor to avoid inserting a
143
- // panicking codepath that needs to be optimized out.
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.
144
133
unsafe { Layout :: from_size_align_unchecked ( size, align) }
145
134
}
146
135
@@ -152,6 +141,7 @@ impl Layout {
152
141
#[ inline]
153
142
pub fn for_value < T : ?Sized > ( t : & T ) -> Self {
154
143
let ( size, align) = ( mem:: size_of_val ( t) , mem:: align_of_val ( t) ) ;
144
+ debug_assert ! ( Layout :: from_size_align( size, align) . is_ok( ) ) ;
155
145
// SAFETY: see rationale in `new` for why this is using the unsafe variant
156
146
unsafe { Layout :: from_size_align_unchecked ( size, align) }
157
147
}
@@ -186,6 +176,7 @@ impl Layout {
186
176
pub unsafe fn for_value_raw < T : ?Sized > ( t : * const T ) -> Self {
187
177
// SAFETY: we pass along the prerequisites of these functions to the caller
188
178
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( ) ) ;
189
180
// SAFETY: see rationale in `new` for why this is using the unsafe variant
190
181
unsafe { Layout :: from_size_align_unchecked ( size, align) }
191
182
}
@@ -289,7 +280,8 @@ impl Layout {
289
280
// > less than or equal to `isize::MAX`)
290
281
let new_size = self . size ( ) + pad;
291
282
292
- // SAFETY: padded size is guaranteed to not exceed `isize::MAX`.
283
+ // SAFETY: self.align is already known to be valid and new_size has been
284
+ // padded already.
293
285
unsafe { Layout :: from_size_align_unchecked ( new_size, self . align ( ) ) }
294
286
}
295
287
@@ -312,7 +304,7 @@ impl Layout {
312
304
let alloc_size = padded_size. checked_mul ( n) . ok_or ( LayoutError ) ?;
313
305
314
306
// The safe constructor is called here to enforce the isize size limit.
315
- Layout :: from_size_valid_align ( alloc_size, self . align ) . map ( |layout| ( layout, padded_size) )
307
+ Layout :: from_size_align ( alloc_size, self . align ( ) ) . map ( |layout| ( layout, padded_size) )
316
308
}
317
309
318
310
/// Creates a layout describing the record for `self` followed by
@@ -363,14 +355,14 @@ impl Layout {
363
355
#[ stable( feature = "alloc_layout_manipulation" , since = "1.44.0" ) ]
364
356
#[ inline]
365
357
pub fn extend ( & self , next : Self ) -> Result < ( Self , usize ) , LayoutError > {
366
- let new_align = cmp:: max ( self . align , next. align ) ;
358
+ let new_align = cmp:: max ( self . align ( ) , next. align ( ) ) ;
367
359
let pad = self . padding_needed_for ( next. align ( ) ) ;
368
360
369
361
let offset = self . size ( ) . checked_add ( pad) . ok_or ( LayoutError ) ?;
370
362
let new_size = offset. checked_add ( next. size ( ) ) . ok_or ( LayoutError ) ?;
371
363
372
364
// The safe constructor is called here to enforce the isize size limit.
373
- let layout = Layout :: from_size_valid_align ( new_size, new_align) ?;
365
+ let layout = Layout :: from_size_align ( new_size, new_align) ?;
374
366
Ok ( ( layout, offset) )
375
367
}
376
368
@@ -391,7 +383,7 @@ impl Layout {
391
383
pub fn repeat_packed ( & self , n : usize ) -> Result < Self , LayoutError > {
392
384
let size = self . size ( ) . checked_mul ( n) . ok_or ( LayoutError ) ?;
393
385
// The safe constructor is called here to enforce the isize size limit.
394
- Layout :: from_size_valid_align ( size, self . align )
386
+ Layout :: from_size_align ( size, self . align ( ) )
395
387
}
396
388
397
389
/// Creates a layout describing the record for `self` followed by
@@ -405,7 +397,7 @@ impl Layout {
405
397
pub fn extend_packed ( & self , next : Self ) -> Result < Self , LayoutError > {
406
398
let new_size = self . size ( ) . checked_add ( next. size ( ) ) . ok_or ( LayoutError ) ?;
407
399
// The safe constructor is called here to enforce the isize size limit.
408
- Layout :: from_size_valid_align ( new_size, self . align )
400
+ Layout :: from_size_align ( new_size, self . align ( ) )
409
401
}
410
402
411
403
/// Creates a layout describing the record for a `[T; n]`.
@@ -416,7 +408,7 @@ impl Layout {
416
408
pub fn array < T > ( n : usize ) -> Result < Self , LayoutError > {
417
409
let array_size = mem:: size_of :: < T > ( ) . checked_mul ( n) . ok_or ( LayoutError ) ?;
418
410
// The safe constructor is called here to enforce the isize size limit.
419
- Layout :: from_size_valid_align ( array_size, ValidAlign :: of :: < T > ( ) )
411
+ Layout :: from_size_align ( array_size, mem :: align_of :: < T > ( ) )
420
412
}
421
413
}
422
414
0 commit comments