Skip to content

Commit 589353b

Browse files
new layout
Co-authored-by: Dario Nieuwenhuis <[email protected]>
1 parent 204c18d commit 589353b

File tree

8 files changed

+335
-23
lines changed

8 files changed

+335
-23
lines changed

compiler/rustc_abi/src/lib.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -1508,8 +1508,10 @@ pub enum Variants<FieldIdx: Idx, VariantIdx: Idx> {
15081508
/// a struct, and they all have space reserved for the tag.
15091509
/// For enums, the tag is the sole field of the layout.
15101510
Multiple {
1511+
/// Tag definition
15111512
tag: Scalar,
15121513
tag_encoding: TagEncoding<VariantIdx>,
1514+
/// Index of tag among fields
15131515
tag_field: usize,
15141516
variants: IndexVec<VariantIdx, LayoutData<FieldIdx, VariantIdx>>,
15151517
},
@@ -1545,6 +1547,7 @@ pub enum TagEncoding<VariantIdx: Idx> {
15451547
pub struct Niche {
15461548
pub offset: Size,
15471549
pub value: Primitive,
1550+
/// A range of valid values with both endpoints being inclusive
15481551
pub valid_range: WrappingRange,
15491552
}
15501553

@@ -1555,17 +1558,23 @@ impl Niche {
15551558
if niche.available(cx) > 0 { Some(niche) } else { None }
15561559
}
15571560

1561+
/// Compute how many values are outside the valid range, available for optimisation through niche filling
15581562
pub fn available<C: HasDataLayout>(&self, cx: &C) -> u128 {
15591563
let Self { value, valid_range: v, .. } = *self;
15601564
let size = value.size(cx);
15611565
assert!(size.bits() <= 128);
15621566
let max_value = size.unsigned_int_max();
15631567

1564-
// Find out how many values are outside the valid range.
15651568
let niche = v.end.wrapping_add(1)..v.start;
15661569
niche.end.wrapping_sub(niche.start) & max_value
15671570
}
15681571

1572+
/// Try to enlarge the valid value range to include another `count` values,
1573+
/// so that they can be used for niche-filling optimisation.
1574+
/// `None` signals impossibility of reservation.
1575+
/// Otherwise, `Some((start, scalar))` signifies that a reservation is possible,
1576+
/// the first value in the reservation is `start`, and the new scalar including
1577+
/// the reserved values is defined in `scalar`.
15691578
pub fn reserve<C: HasDataLayout>(&self, cx: &C, count: u128) -> Option<(u128, Scalar)> {
15701579
assert!(count > 0);
15711580

compiler/rustc_feature/src/unstable.rs

+2
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,8 @@ declare_features! (
434434
(unstable, const_try, "1.56.0", Some(74935)),
435435
/// Allows coroutines to be cloned.
436436
(unstable, coroutine_clone, "1.65.0", Some(95360)),
437+
/// Allows aggressive merging coroutine saved slots
438+
(unstable, coroutine_new_layout, "CURRENT_RUSTC_VERSION", Some(99999)),
437439
/// Allows defining coroutines.
438440
(unstable, coroutines, "1.21.0", Some(43122)),
439441
/// Allows function attribute `#[coverage(on/off)]`, to control coverage

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,7 @@ symbols! {
661661
core_panic_macro,
662662
coroutine,
663663
coroutine_clone,
664+
coroutine_new_layout,
664665
coroutine_resume,
665666
coroutine_return,
666667
coroutine_state,

compiler/rustc_ty_utils/src/layout.rs

+15-7
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use crate::errors::{
3131
MultipleArrayFieldsSimdType, NonPrimitiveSimdType, OversizedSimdType, ZeroLengthSimdType,
3232
};
3333

34+
mod coroutine;
3435
mod invariant;
3536

3637
pub(crate) fn provide(providers: &mut Providers) {
@@ -393,7 +394,13 @@ fn layout_of_uncached<'tcx>(
393394
tcx.mk_layout(unit)
394395
}
395396

396-
ty::Coroutine(def_id, args) => coroutine_layout(cx, ty, def_id, args)?,
397+
ty::Coroutine(def_id, args) => {
398+
if tcx.features().coroutine_new_layout() {
399+
coroutine::coroutine_layout(cx, ty, def_id, args)?
400+
} else {
401+
coroutine_layout(cx, ty, def_id, args)?
402+
}
403+
}
397404

398405
ty::Closure(_, args) => {
399406
let tys = args.as_closure().upvar_tys();
@@ -1156,8 +1163,10 @@ fn variant_info_for_coroutine<'tcx>(
11561163
.zip_eq(upvar_names)
11571164
.enumerate()
11581165
.map(|(field_idx, (_, name))| {
1159-
let field_layout = layout.field(cx, field_idx);
1160-
let offset = layout.fields.offset(field_idx);
1166+
// Upvars occupies the Unresumed variant at index zero
1167+
let variant_layout = layout.for_variant(cx, VariantIdx::ZERO);
1168+
let field_layout = variant_layout.field(cx, field_idx);
1169+
let offset = variant_layout.fields.offset(field_idx);
11611170
upvars_size = upvars_size.max(offset + field_layout.size);
11621171
FieldInfo {
11631172
kind: FieldKind::Upvar,
@@ -1177,12 +1186,11 @@ fn variant_info_for_coroutine<'tcx>(
11771186
let variant_layout = layout.for_variant(cx, variant_idx);
11781187
let mut variant_size = Size::ZERO;
11791188
let fields = variant_def
1180-
.iter()
1181-
.enumerate()
1189+
.iter_enumerated()
11821190
.map(|(field_idx, local)| {
11831191
let field_name = coroutine.field_names[*local];
1184-
let field_layout = variant_layout.field(cx, field_idx);
1185-
let offset = variant_layout.fields.offset(field_idx);
1192+
let field_layout = variant_layout.field(cx, field_idx.index());
1193+
let offset = variant_layout.fields.offset(field_idx.index());
11861194
// The struct is as large as the last field's end
11871195
variant_size = variant_size.max(offset + field_layout.size);
11881196
FieldInfo {

0 commit comments

Comments
 (0)