mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
-Zprint-type-sizes: print the types of awaitees and unnamed coroutine locals.
This should assist comprehending the size of coroutines. In particular, whenever a future is suspended while awaiting another future, the latter is given the special name `__awaitee`, and now the type of the awaited future will be printed, allowing identifying caller/callee — er, I mean, poller/pollee — relationships. It would be possible to include the type name in more cases, but I thought that that might be overly verbose (`print-type-sizes` is already a lot of text) and ordinary named fields or variables are easier for readers to discover the types of.
This commit is contained in:
parent
85e449a323
commit
44d185b0d0
@ -44,6 +44,10 @@ pub struct FieldInfo {
|
||||
pub offset: u64,
|
||||
pub size: u64,
|
||||
pub align: u64,
|
||||
/// Name of the type of this field.
|
||||
/// Present only if the creator thought that this would be important for identifying the field,
|
||||
/// typically because the field name is uninformative.
|
||||
pub type_name: Option<Symbol>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
@ -192,7 +196,7 @@ impl CodeStats {
|
||||
fields.sort_by_key(|f| (f.offset, f.size));
|
||||
|
||||
for field in fields {
|
||||
let FieldInfo { kind, ref name, offset, size, align } = field;
|
||||
let FieldInfo { kind, ref name, offset, size, align, type_name } = field;
|
||||
|
||||
if offset > min_offset {
|
||||
let pad = offset - min_offset;
|
||||
@ -201,21 +205,27 @@ impl CodeStats {
|
||||
|
||||
if offset < min_offset {
|
||||
// If this happens it's probably a union.
|
||||
println!(
|
||||
print!(
|
||||
"print-type-size {indent}{kind} `.{name}`: {size} bytes, \
|
||||
offset: {offset} bytes, \
|
||||
alignment: {align} bytes"
|
||||
);
|
||||
} else if info.packed || offset == min_offset {
|
||||
println!("print-type-size {indent}{kind} `.{name}`: {size} bytes");
|
||||
print!("print-type-size {indent}{kind} `.{name}`: {size} bytes");
|
||||
} else {
|
||||
// Include field alignment in output only if it caused padding injection
|
||||
println!(
|
||||
print!(
|
||||
"print-type-size {indent}{kind} `.{name}`: {size} bytes, \
|
||||
alignment: {align} bytes"
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(type_name) = type_name {
|
||||
println!(", type: {type_name}");
|
||||
} else {
|
||||
println!();
|
||||
}
|
||||
|
||||
min_offset = offset + size;
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ use rustc_middle::ty::layout::{
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{self, AdtDef, EarlyBinder, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_session::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo};
|
||||
use rustc_span::sym;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_target::abi::*;
|
||||
|
||||
@ -1007,6 +1008,7 @@ fn variant_info_for_adt<'tcx>(
|
||||
offset: offset.bytes(),
|
||||
size: field_layout.size.bytes(),
|
||||
align: field_layout.align.abi.bytes(),
|
||||
type_name: None,
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
@ -1090,6 +1092,7 @@ fn variant_info_for_coroutine<'tcx>(
|
||||
offset: offset.bytes(),
|
||||
size: field_layout.size.bytes(),
|
||||
align: field_layout.align.abi.bytes(),
|
||||
type_name: None,
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
@ -1104,19 +1107,24 @@ fn variant_info_for_coroutine<'tcx>(
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(field_idx, local)| {
|
||||
let field_name = coroutine.field_names[*local];
|
||||
let field_layout = variant_layout.field(cx, field_idx);
|
||||
let offset = variant_layout.fields.offset(field_idx);
|
||||
// The struct is as large as the last field's end
|
||||
variant_size = variant_size.max(offset + field_layout.size);
|
||||
FieldInfo {
|
||||
kind: FieldKind::CoroutineLocal,
|
||||
name: coroutine.field_names[*local].unwrap_or(Symbol::intern(&format!(
|
||||
name: field_name.unwrap_or(Symbol::intern(&format!(
|
||||
".coroutine_field{}",
|
||||
local.as_usize()
|
||||
))),
|
||||
offset: offset.bytes(),
|
||||
size: field_layout.size.bytes(),
|
||||
align: field_layout.align.abi.bytes(),
|
||||
// Include the type name if there is no field name, or if the name is the
|
||||
// __awaitee placeholder symbol which means a child future being `.await`ed.
|
||||
type_name: (field_name.is_none() || field_name == Some(sym::__awaitee))
|
||||
.then(|| Symbol::intern(&field_layout.ty.to_string())),
|
||||
}
|
||||
})
|
||||
.chain(upvar_fields.iter().copied())
|
||||
|
@ -2,7 +2,7 @@ print-type-size type: `{async fn body@$DIR/async-awaiting-fut.rs:21:21: 24:2}`:
|
||||
print-type-size discriminant: 1 bytes
|
||||
print-type-size variant `Unresumed`: 0 bytes
|
||||
print-type-size variant `Suspend0`: 3077 bytes
|
||||
print-type-size local `.__awaitee`: 3077 bytes
|
||||
print-type-size local `.__awaitee`: 3077 bytes, type: {async fn body@$DIR/async-awaiting-fut.rs:10:64: 19:2}
|
||||
print-type-size variant `Returned`: 0 bytes
|
||||
print-type-size variant `Panicked`: 0 bytes
|
||||
print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/async-awaiting-fut.rs:10:64: 19:2}>`: 3077 bytes, alignment: 1 bytes
|
||||
@ -19,19 +19,19 @@ print-type-size variant `Suspend0`: 2052 bytes
|
||||
print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
|
||||
print-type-size padding: 1 bytes
|
||||
print-type-size local `.fut`: 1025 bytes, alignment: 1 bytes
|
||||
print-type-size local `..coroutine_field4`: 1 bytes
|
||||
print-type-size local `.__awaitee`: 1 bytes
|
||||
print-type-size local `..coroutine_field4`: 1 bytes, type: bool
|
||||
print-type-size local `.__awaitee`: 1 bytes, type: {async fn body@$DIR/async-awaiting-fut.rs:6:17: 6:19}
|
||||
print-type-size variant `Suspend1`: 3076 bytes
|
||||
print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
|
||||
print-type-size padding: 1026 bytes
|
||||
print-type-size local `..coroutine_field4`: 1 bytes, alignment: 1 bytes
|
||||
print-type-size local `.__awaitee`: 1025 bytes
|
||||
print-type-size local `..coroutine_field4`: 1 bytes, alignment: 1 bytes, type: bool
|
||||
print-type-size local `.__awaitee`: 1025 bytes, type: {async fn body@$DIR/async-awaiting-fut.rs:8:35: 8:37}
|
||||
print-type-size variant `Suspend2`: 2052 bytes
|
||||
print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
|
||||
print-type-size padding: 1 bytes
|
||||
print-type-size local `.fut`: 1025 bytes, alignment: 1 bytes
|
||||
print-type-size local `..coroutine_field4`: 1 bytes
|
||||
print-type-size local `.__awaitee`: 1 bytes
|
||||
print-type-size local `..coroutine_field4`: 1 bytes, type: bool
|
||||
print-type-size local `.__awaitee`: 1 bytes, type: {async fn body@$DIR/async-awaiting-fut.rs:6:17: 6:19}
|
||||
print-type-size variant `Returned`: 1025 bytes
|
||||
print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
|
||||
print-type-size variant `Panicked`: 1025 bytes
|
||||
|
@ -2,7 +2,7 @@ print-type-size type: `{async fn body@$DIR/large-arg.rs:6:21: 8:2}`: 3076 bytes,
|
||||
print-type-size discriminant: 1 bytes
|
||||
print-type-size variant `Unresumed`: 0 bytes
|
||||
print-type-size variant `Suspend0`: 3075 bytes
|
||||
print-type-size local `.__awaitee`: 3075 bytes
|
||||
print-type-size local `.__awaitee`: 3075 bytes, type: {async fn body@$DIR/large-arg.rs:10:30: 12:2}
|
||||
print-type-size variant `Returned`: 0 bytes
|
||||
print-type-size variant `Panicked`: 0 bytes
|
||||
print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/large-arg.rs:10:30: 12:2}>`: 3075 bytes, alignment: 1 bytes
|
||||
@ -17,7 +17,7 @@ print-type-size variant `Unresumed`: 1024 bytes
|
||||
print-type-size upvar `.t`: 1024 bytes
|
||||
print-type-size variant `Suspend0`: 3074 bytes
|
||||
print-type-size upvar `.t`: 1024 bytes
|
||||
print-type-size local `.__awaitee`: 2050 bytes
|
||||
print-type-size local `.__awaitee`: 2050 bytes, type: {async fn body@$DIR/large-arg.rs:13:26: 15:2}
|
||||
print-type-size variant `Returned`: 1024 bytes
|
||||
print-type-size upvar `.t`: 1024 bytes
|
||||
print-type-size variant `Panicked`: 1024 bytes
|
||||
@ -34,7 +34,7 @@ print-type-size variant `Unresumed`: 1024 bytes
|
||||
print-type-size upvar `.t`: 1024 bytes
|
||||
print-type-size variant `Suspend0`: 2049 bytes
|
||||
print-type-size upvar `.t`: 1024 bytes
|
||||
print-type-size local `.__awaitee`: 1025 bytes
|
||||
print-type-size local `.__awaitee`: 1025 bytes, type: {async fn body@$DIR/large-arg.rs:16:26: 18:2}
|
||||
print-type-size variant `Returned`: 1024 bytes
|
||||
print-type-size upvar `.t`: 1024 bytes
|
||||
print-type-size variant `Panicked`: 1024 bytes
|
||||
|
@ -5,7 +5,7 @@ print-type-size upvar `.arg`: 8192 bytes
|
||||
print-type-size variant `Suspend0`: 16385 bytes
|
||||
print-type-size upvar `.arg`: 8192 bytes
|
||||
print-type-size local `.arg`: 8192 bytes
|
||||
print-type-size local `.__awaitee`: 1 bytes
|
||||
print-type-size local `.__awaitee`: 1 bytes, type: {async fn body@$DIR/async.rs:8:17: 8:19}
|
||||
print-type-size variant `Returned`: 8192 bytes
|
||||
print-type-size upvar `.arg`: 8192 bytes
|
||||
print-type-size variant `Panicked`: 8192 bytes
|
||||
|
Loading…
Reference in New Issue
Block a user