1
Fork 0

Remove print_vtable_sizes

This commit is contained in:
Michael Goulet 2025-01-10 20:38:37 +00:00
parent 08d7e9dfe5
commit 37a430e6ea
5 changed files with 1 additions and 225 deletions

View file

@ -26,7 +26,6 @@ use rustc_parse::{
}; };
use rustc_passes::{abi_test, input_stats, layout_test}; use rustc_passes::{abi_test, input_stats, layout_test};
use rustc_resolve::Resolver; use rustc_resolve::Resolver;
use rustc_session::code_stats::VTableSizeInfo;
use rustc_session::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType}; use rustc_session::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType};
use rustc_session::cstore::Untracked; use rustc_session::cstore::Untracked;
use rustc_session::output::{collect_crate_types, filename_for_input, find_crate_name}; use rustc_session::output::{collect_crate_types, filename_for_input, find_crate_name};
@ -989,90 +988,6 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) {
// we will fail to emit overlap diagnostics. Thus we invoke it here unconditionally. // we will fail to emit overlap diagnostics. Thus we invoke it here unconditionally.
let _ = tcx.all_diagnostic_items(()); let _ = tcx.all_diagnostic_items(());
}); });
if sess.opts.unstable_opts.print_vtable_sizes {
let traits = tcx.traits(LOCAL_CRATE);
for &tr in traits {
if !tcx.is_dyn_compatible(tr) {
continue;
}
let name = ty::print::with_no_trimmed_paths!(tcx.def_path_str(tr));
let mut first_dsa = true;
// Number of vtable entries, if we didn't have upcasting
let mut entries_ignoring_upcasting = 0;
// Number of vtable entries needed solely for upcasting
let mut entries_for_upcasting = 0;
let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(tcx, tr));
// A slightly edited version of the code in
// `rustc_trait_selection::traits::vtable::vtable_entries`, that works without self
// type and just counts number of entries.
//
// Note that this is technically wrong, for traits which have associated types in
// supertraits:
//
// trait A: AsRef<Self::T> + AsRef<()> { type T; }
//
// Without self type we can't normalize `Self::T`, so we can't know if `AsRef<Self::T>`
// and `AsRef<()>` are the same trait, thus we assume that those are different, and
// potentially over-estimate how many vtable entries there are.
//
// Similarly this is wrong for traits that have methods with possibly-impossible bounds.
// For example:
//
// trait B<T> { fn f(&self) where T: Copy; }
//
// Here `dyn B<u8>` will have 4 entries, while `dyn B<String>` will only have 3.
// However, since we don't know `T`, we can't know if `T: Copy` holds or not,
// thus we lean on the bigger side and say it has 4 entries.
traits::vtable::prepare_vtable_segments(tcx, trait_ref, |segment| {
match segment {
traits::vtable::VtblSegment::MetadataDSA => {
// If this is the first dsa, it would be included either way,
// otherwise it's needed for upcasting
if std::mem::take(&mut first_dsa) {
entries_ignoring_upcasting += 3;
} else {
entries_for_upcasting += 3;
}
}
traits::vtable::VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
// Lookup the shape of vtable for the trait.
let own_existential_entries =
tcx.own_existential_vtable_entries(trait_ref.def_id());
// The original code here ignores the method if its predicates are
// impossible. We can't really do that as, for example, all not trivial
// bounds on generic parameters are impossible (since we don't know the
// parameters...), see the comment above.
entries_ignoring_upcasting += own_existential_entries.len();
if emit_vptr {
entries_for_upcasting += 1;
}
}
}
std::ops::ControlFlow::Continue::<std::convert::Infallible>(())
});
sess.code_stats.record_vtable_size(tr, &name, VTableSizeInfo {
trait_name: name.clone(),
entries: entries_ignoring_upcasting + entries_for_upcasting,
entries_ignoring_upcasting,
entries_for_upcasting,
upcasting_cost_percent: entries_for_upcasting as f64
/ entries_ignoring_upcasting as f64
* 100.,
})
}
}
} }
/// Check for the `#[rustc_error]` annotation, which forces an error in codegen. This is used /// Check for the `#[rustc_error]` annotation, which forces an error in codegen. This is used
@ -1153,12 +1068,6 @@ pub(crate) fn start_codegen<'tcx>(
tcx.sess.code_stats.print_type_sizes(); tcx.sess.code_stats.print_type_sizes();
} }
if tcx.sess.opts.unstable_opts.print_vtable_sizes {
let crate_name = tcx.crate_name(LOCAL_CRATE);
tcx.sess.code_stats.print_vtable_sizes(crate_name);
}
codegen codegen
} }

View file

@ -1,10 +1,9 @@
use std::cmp; use std::cmp;
use rustc_abi::{Align, Size}; use rustc_abi::{Align, Size};
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sync::Lock; use rustc_data_structures::sync::Lock;
use rustc_span::Symbol; use rustc_span::Symbol;
use rustc_span::def_id::DefId;
#[derive(Clone, PartialEq, Eq, Hash, Debug)] #[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct VariantInfo { pub struct VariantInfo {
@ -71,29 +70,9 @@ pub struct TypeSizeInfo {
pub variants: Vec<VariantInfo>, pub variants: Vec<VariantInfo>,
} }
pub struct VTableSizeInfo {
pub trait_name: String,
/// Number of entries in a vtable with the current algorithm
/// (i.e. with upcasting).
pub entries: usize,
/// Number of entries in a vtable, as-if we did not have trait upcasting.
pub entries_ignoring_upcasting: usize,
/// Number of entries in a vtable needed solely for upcasting
/// (i.e. `entries - entries_ignoring_upcasting`).
pub entries_for_upcasting: usize,
/// Cost of having upcasting in % relative to the number of entries without
/// upcasting (i.e. `entries_for_upcasting / entries_ignoring_upcasting * 100%`).
pub upcasting_cost_percent: f64,
}
#[derive(Default)] #[derive(Default)]
pub struct CodeStats { pub struct CodeStats {
type_sizes: Lock<FxHashSet<TypeSizeInfo>>, type_sizes: Lock<FxHashSet<TypeSizeInfo>>,
vtable_sizes: Lock<FxHashMap<DefId, VTableSizeInfo>>,
} }
impl CodeStats { impl CodeStats {
@ -127,14 +106,6 @@ impl CodeStats {
self.type_sizes.borrow_mut().insert(info); self.type_sizes.borrow_mut().insert(info);
} }
pub fn record_vtable_size(&self, trait_did: DefId, trait_name: &str, info: VTableSizeInfo) {
let prev = self.vtable_sizes.lock().insert(trait_did, info);
assert!(
prev.is_none(),
"size of vtable for `{trait_name}` ({trait_did:?}) is already recorded"
);
}
pub fn print_type_sizes(&self) { pub fn print_type_sizes(&self) {
let type_sizes = self.type_sizes.borrow(); let type_sizes = self.type_sizes.borrow();
// We will soon sort, so the initial order does not matter. // We will soon sort, so the initial order does not matter.
@ -238,33 +209,4 @@ impl CodeStats {
} }
} }
} }
pub fn print_vtable_sizes(&self, crate_name: Symbol) {
// We will soon sort, so the initial order does not matter.
#[allow(rustc::potential_query_instability)]
let mut infos =
std::mem::take(&mut *self.vtable_sizes.lock()).into_values().collect::<Vec<_>>();
// Primary sort: cost % in reverse order (from largest to smallest)
// Secondary sort: trait_name
infos.sort_by(|a, b| {
a.upcasting_cost_percent
.total_cmp(&b.upcasting_cost_percent)
.reverse()
.then_with(|| a.trait_name.cmp(&b.trait_name))
});
for VTableSizeInfo {
trait_name,
entries,
entries_ignoring_upcasting,
entries_for_upcasting,
upcasting_cost_percent,
} in infos
{
println!(
r#"print-vtable-sizes {{ "crate_name": "{crate_name}", "trait_name": "{trait_name}", "entries": "{entries}", "entries_ignoring_upcasting": "{entries_ignoring_upcasting}", "entries_for_upcasting": "{entries_for_upcasting}", "upcasting_cost_percent": "{upcasting_cost_percent}" }}"#
);
}
}
} }

View file

@ -2033,8 +2033,6 @@ options! {
Note that this overwrites the effect `-Clink-dead-code` has on collection!"), Note that this overwrites the effect `-Clink-dead-code` has on collection!"),
print_type_sizes: bool = (false, parse_bool, [UNTRACKED], print_type_sizes: bool = (false, parse_bool, [UNTRACKED],
"print layout information for each type encountered (default: no)"), "print layout information for each type encountered (default: no)"),
print_vtable_sizes: bool = (false, parse_bool, [UNTRACKED],
"print size comparison between old and new vtable layouts (default: no)"),
proc_macro_backtrace: bool = (false, parse_bool, [UNTRACKED], proc_macro_backtrace: bool = (false, parse_bool, [UNTRACKED],
"show backtraces for panics during proc-macro execution (default: no)"), "show backtraces for panics during proc-macro execution (default: no)"),
proc_macro_execution_strategy: ProcMacroExecutionStrategy = (ProcMacroExecutionStrategy::SameThread, proc_macro_execution_strategy: ProcMacroExecutionStrategy = (ProcMacroExecutionStrategy::SameThread,

View file

@ -1,62 +0,0 @@
//@ check-pass
//@ compile-flags: -Z print-vtable-sizes
#![crate_type = "lib"]
trait A<T: help::V>: AsRef<[T::V]> + AsMut<[T::V]> {}
trait B<T>: AsRef<T> + AsRef<T> + AsRef<T> + AsRef<T> {}
trait C {
fn x() {} // not dyn-compatible, shouldn't be reported
}
// This does not have any upcasting cost,
// because both `Send` and `Sync` are traits
// with no methods
trait D: Send + Sync + help::MarkerWithSuper {}
// This can't have no cost without reordering,
// because `Super::f`.
trait E: help::MarkerWithSuper + Send + Sync {}
trait F {
fn a(&self);
fn b(&self);
fn c(&self);
fn d() -> Self
where
Self: Sized;
}
trait G: AsRef<u8> + AsRef<u16> + help::MarkerWithSuper {
fn a(&self);
fn b(&self);
fn c(&self);
fn d(&self);
fn e(&self);
fn f() -> Self
where
Self: Sized;
}
// Traits with the same name
const _: () = {
trait S {}
};
const _: () = {
trait S {}
};
mod help {
pub trait V {
type V;
}
pub trait MarkerWithSuper: Super {}
pub trait Super {
fn f(&self);
}
}

View file

@ -1,11 +0,0 @@
print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "A", "entries": "6", "entries_ignoring_upcasting": "5", "entries_for_upcasting": "1", "upcasting_cost_percent": "20" }
print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "G", "entries": "13", "entries_ignoring_upcasting": "11", "entries_for_upcasting": "2", "upcasting_cost_percent": "18.181818181818183" }
print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "B", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "D", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "E", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "F", "entries": "6", "entries_ignoring_upcasting": "6", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "_::S", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "_::S", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "help::MarkerWithSuper", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "help::Super", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
print-vtable-sizes { "crate_name": "print_vtable_sizes", "trait_name": "help::V", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }