1
Fork 0

Don't emit useless vptrs for marker traits

This commit is contained in:
Maybe Waffle 2023-07-19 11:50:40 +00:00
parent b5d1228508
commit 1f02c75718
4 changed files with 25 additions and 13 deletions

View file

@ -147,9 +147,6 @@ fn prepare_vtable_segments_inner<'tcx, T>(
} }
} }
// Other than the left-most path, vptr should be emitted for each trait.
emit_vptr_on_new_entry = true;
// emit innermost item, move to next sibling and stop there if possible, otherwise jump to outer level. // emit innermost item, move to next sibling and stop there if possible, otherwise jump to outer level.
while let Some((inner_most_trait_ref, emit_vptr, mut siblings)) = stack.pop() { while let Some((inner_most_trait_ref, emit_vptr, mut siblings)) = stack.pop() {
segment_visitor(VtblSegment::TraitOwnEntries { segment_visitor(VtblSegment::TraitOwnEntries {
@ -157,6 +154,14 @@ fn prepare_vtable_segments_inner<'tcx, T>(
emit_vptr, emit_vptr,
})?; })?;
// If we've emitted (fed to `segment_visitor`) a trait that has methods present in the vtable,
// we'll need to emit vptrs from now on.
if !emit_vptr_on_new_entry
&& has_own_existential_vtable_entries(tcx, inner_most_trait_ref.def_id())
{
emit_vptr_on_new_entry = true;
}
if let Some(next_inner_most_trait_ref) = if let Some(next_inner_most_trait_ref) =
siblings.find(|&sibling| visited.insert(sibling.to_predicate(tcx))) siblings.find(|&sibling| visited.insert(sibling.to_predicate(tcx)))
{ {
@ -196,11 +201,23 @@ fn dump_vtable_entries<'tcx>(
}); });
} }
fn has_own_existential_vtable_entries(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
own_existential_vtable_entries_iter(tcx, trait_def_id).next().is_some()
}
fn own_existential_vtable_entries(tcx: TyCtxt<'_>, trait_def_id: DefId) -> &[DefId] { fn own_existential_vtable_entries(tcx: TyCtxt<'_>, trait_def_id: DefId) -> &[DefId] {
tcx.arena.alloc_from_iter(own_existential_vtable_entries_iter(tcx, trait_def_id))
}
fn own_existential_vtable_entries_iter(
tcx: TyCtxt<'_>,
trait_def_id: DefId,
) -> impl Iterator<Item = DefId> + '_ {
let trait_methods = tcx let trait_methods = tcx
.associated_items(trait_def_id) .associated_items(trait_def_id)
.in_definition_order() .in_definition_order()
.filter(|item| item.kind == ty::AssocKind::Fn); .filter(|item| item.kind == ty::AssocKind::Fn);
// Now list each method's DefId (for within its trait). // Now list each method's DefId (for within its trait).
let own_entries = trait_methods.filter_map(move |&trait_method| { let own_entries = trait_methods.filter_map(move |&trait_method| {
debug!("own_existential_vtable_entry: trait_method={:?}", trait_method); debug!("own_existential_vtable_entry: trait_method={:?}", trait_method);
@ -215,7 +232,7 @@ fn own_existential_vtable_entries(tcx: TyCtxt<'_>, trait_def_id: DefId) -> &[Def
Some(def_id) Some(def_id)
}); });
tcx.arena.alloc_from_iter(own_entries.into_iter()) own_entries
} }
/// Given a trait `trait_ref`, iterates the vtable entries /// Given a trait `trait_ref`, iterates the vtable entries

View file

@ -10,8 +10,9 @@ trait C {
fn x() {} // not object safe, shouldn't be reported fn x() {} // not object safe, shouldn't be reported
} }
// This ideally should not have any upcasting cost, // This does not have any upcasting cost,
// but currently does due to a bug // because both `Send` and `Sync` are traits
// with no methods
trait D: Send + Sync + help::MarkerWithSuper {} trait D: Send + Sync + help::MarkerWithSuper {}
// This can't have no cost without reordering, // This can't have no cost without reordering,

View file

@ -1,8 +1,8 @@
print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "D", "entries": "7", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "3", "upcasting_cost_percent": "75" }
print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "E", "entries": "6", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "2", "upcasting_cost_percent": "50" } print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "E", "entries": "6", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "2", "upcasting_cost_percent": "50" }
print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "G", "entries": "14", "entries_ignoring_upcasting": "11", "entries_for_upcasting": "3", "upcasting_cost_percent": "27.27272727272727" } print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "G", "entries": "14", "entries_ignoring_upcasting": "11", "entries_for_upcasting": "3", "upcasting_cost_percent": "27.27272727272727" }
print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "A", "entries": "6", "entries_ignoring_upcasting": "5", "entries_for_upcasting": "1", "upcasting_cost_percent": "20" } print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "A", "entries": "6", "entries_ignoring_upcasting": "5", "entries_for_upcasting": "1", "upcasting_cost_percent": "20" }
print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "B", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "B", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "D", "entries": "4", "entries_ignoring_upcasting": "4", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "F", "entries": "6", "entries_ignoring_upcasting": "6", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "F", "entries": "6", "entries_ignoring_upcasting": "6", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "_::S", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "_::S", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }
print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "_::S", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" } print-vtable-sizes { "crate_name": "<UNKNOWN_CRATE>", "trait_name": "_::S", "entries": "3", "entries_ignoring_upcasting": "3", "entries_for_upcasting": "0", "upcasting_cost_percent": "0" }

View file

@ -2,10 +2,7 @@ error: vtable entries for `<S as A>`: [
MetadataDropInPlace, MetadataDropInPlace,
MetadataSize, MetadataSize,
MetadataAlign, MetadataAlign,
TraitVPtr(<S as M1>),
TraitVPtr(<S as M2>),
Method(<S as T>::method), Method(<S as T>::method),
TraitVPtr(<S as T>),
] ]
--> $DIR/multiple-markers.rs:21:1 --> $DIR/multiple-markers.rs:21:1
| |
@ -16,9 +13,7 @@ error: vtable entries for `<S as B>`: [
MetadataDropInPlace, MetadataDropInPlace,
MetadataSize, MetadataSize,
MetadataAlign, MetadataAlign,
TraitVPtr(<S as M1>),
Method(<S as T>::method), Method(<S as T>::method),
TraitVPtr(<S as T>),
TraitVPtr(<S as M2>), TraitVPtr(<S as M2>),
] ]
--> $DIR/multiple-markers.rs:24:1 --> $DIR/multiple-markers.rs:24:1
@ -31,7 +26,6 @@ error: vtable entries for `<S as C>`: [
MetadataSize, MetadataSize,
MetadataAlign, MetadataAlign,
Method(<S as T>::method), Method(<S as T>::method),
TraitVPtr(<S as T>),
TraitVPtr(<S as M1>), TraitVPtr(<S as M1>),
TraitVPtr(<S as M2>), TraitVPtr(<S as M2>),
] ]