Avoid redundant work for drop-glue translation items in trans::collector
This commit is contained in:
parent
9e969808e2
commit
4d074b8c4c
@ -350,14 +350,14 @@ fn collect_items_rec<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>,
|
||||
let recursion_depth_reset;
|
||||
|
||||
match starting_point {
|
||||
TransItem::DropGlue(_) |
|
||||
TransItem::DropGlue(t) => {
|
||||
find_drop_glue_neighbors(ccx, t, &mut neighbors);
|
||||
recursion_depth_reset = None;
|
||||
}
|
||||
TransItem::Static(_) => {
|
||||
recursion_depth_reset = None;
|
||||
}
|
||||
TransItem::Fn {
|
||||
def_id,
|
||||
substs: ref param_substs
|
||||
} => {
|
||||
TransItem::Fn { def_id, substs: ref param_substs } => {
|
||||
// Keep track of the monomorphization recursion depth
|
||||
recursion_depth_reset = Some(check_recursion_limit(ccx,
|
||||
def_id,
|
||||
@ -531,11 +531,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
||||
self.param_substs,
|
||||
&ty);
|
||||
let ty = self.ccx.tcx().erase_regions(&ty);
|
||||
|
||||
create_drop_glue_trans_items(self.ccx,
|
||||
ty,
|
||||
self.param_substs,
|
||||
&mut self.output);
|
||||
let ty = glue::get_drop_glue_type(self.ccx, ty);
|
||||
self.output.push(TransItem::DropGlue(ty));
|
||||
}
|
||||
|
||||
self.super_lvalue(lvalue, context);
|
||||
@ -636,145 +633,124 @@ fn can_have_local_instance<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
def_id.is_local() || ccx.sess().cstore.is_item_mir_available(def_id)
|
||||
}
|
||||
|
||||
fn create_drop_glue_trans_items<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
mono_ty: ty::Ty<'tcx>,
|
||||
param_substs: &'tcx Substs<'tcx>,
|
||||
output: &mut Vec<TransItem<'tcx>>)
|
||||
fn find_drop_glue_neighbors<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
ty: ty::Ty<'tcx>,
|
||||
output: &mut Vec<TransItem<'tcx>>)
|
||||
{
|
||||
visit_types_of_owned_components(ccx,
|
||||
mono_ty,
|
||||
&mut FnvHashSet(),
|
||||
&mut |ty| {
|
||||
debug!("create_drop_glue_trans_items: {}", type_to_string(ccx, ty));
|
||||
// Add a translation item for the drop glue, if even this type does not
|
||||
// need to be dropped (in which case it has been mapped to i8)
|
||||
output.push(TransItem::DropGlue(ty));
|
||||
debug!("find_drop_glue_neighbors: {}", type_to_string(ccx, ty));
|
||||
|
||||
if glue::type_needs_drop(ccx.tcx(), ty) {
|
||||
// Make sure the exchange_free_fn() lang-item gets translated if
|
||||
// there is a boxed value.
|
||||
if let ty::TyBox(_) = ty.sty {
|
||||
let exchange_free_fn_def_id = ccx.tcx()
|
||||
.lang_items
|
||||
.require(ExchangeFreeFnLangItem)
|
||||
.expect("Could not find ExchangeFreeFnLangItem");
|
||||
|
||||
// Make sure the exchange_free_fn() lang-item gets translated if
|
||||
// there is a boxed value.
|
||||
if let ty::TyBox(_) = ty.sty {
|
||||
assert!(can_have_local_instance(ccx, exchange_free_fn_def_id));
|
||||
let exchange_free_fn_trans_item =
|
||||
create_fn_trans_item(ccx,
|
||||
exchange_free_fn_def_id,
|
||||
&Substs::trans_empty(),
|
||||
&Substs::trans_empty());
|
||||
|
||||
let exchange_free_fn_def_id = ccx.tcx()
|
||||
.lang_items
|
||||
.require(ExchangeFreeFnLangItem)
|
||||
.expect("Could not find ExchangeFreeFnLangItem");
|
||||
output.push(exchange_free_fn_trans_item);
|
||||
}
|
||||
|
||||
assert!(can_have_local_instance(ccx, exchange_free_fn_def_id));
|
||||
let exchange_free_fn_trans_item =
|
||||
create_fn_trans_item(ccx,
|
||||
exchange_free_fn_def_id,
|
||||
&Substs::trans_empty(),
|
||||
param_substs);
|
||||
// If the type implements Drop, also add a translation item for the
|
||||
// monomorphized Drop::drop() implementation.
|
||||
let destructor_did = match ty.sty {
|
||||
ty::TyStruct(def, _) |
|
||||
ty::TyEnum(def, _) => def.destructor(),
|
||||
_ => None
|
||||
};
|
||||
|
||||
output.push(exchange_free_fn_trans_item);
|
||||
}
|
||||
if let Some(destructor_did) = destructor_did {
|
||||
use rustc::middle::ty::ToPolyTraitRef;
|
||||
|
||||
// If the type implements Drop, also add a translation item for the
|
||||
// monomorphized Drop::drop() implementation.
|
||||
let destructor_did = match ty.sty {
|
||||
ty::TyStruct(def, _) |
|
||||
ty::TyEnum(def, _) => def.destructor(),
|
||||
_ => None
|
||||
};
|
||||
let drop_trait_def_id = ccx.tcx()
|
||||
.lang_items
|
||||
.drop_trait()
|
||||
.unwrap();
|
||||
|
||||
if let Some(destructor_did) = destructor_did {
|
||||
use rustc::middle::ty::ToPolyTraitRef;
|
||||
let self_type_substs = ccx.tcx().mk_substs(
|
||||
Substs::trans_empty().with_self_ty(ty));
|
||||
|
||||
let drop_trait_def_id = ccx.tcx()
|
||||
.lang_items
|
||||
.drop_trait()
|
||||
.unwrap();
|
||||
let trait_ref = ty::TraitRef {
|
||||
def_id: drop_trait_def_id,
|
||||
substs: self_type_substs,
|
||||
}.to_poly_trait_ref();
|
||||
|
||||
let self_type_substs = ccx.tcx().mk_substs(
|
||||
Substs::trans_empty().with_self_ty(ty));
|
||||
let substs = match fulfill_obligation(ccx, DUMMY_SP, trait_ref) {
|
||||
traits::VtableImpl(data) => data.substs,
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
let trait_ref = ty::TraitRef {
|
||||
def_id: drop_trait_def_id,
|
||||
substs: self_type_substs,
|
||||
}.to_poly_trait_ref();
|
||||
|
||||
let substs = match fulfill_obligation(ccx, DUMMY_SP, trait_ref) {
|
||||
traits::VtableImpl(data) => data.substs,
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
if can_have_local_instance(ccx, destructor_did) {
|
||||
let trans_item = create_fn_trans_item(ccx,
|
||||
destructor_did,
|
||||
ccx.tcx().mk_substs(substs),
|
||||
param_substs);
|
||||
output.push(trans_item);
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
} else {
|
||||
false
|
||||
if can_have_local_instance(ccx, destructor_did) {
|
||||
let trans_item = create_fn_trans_item(ccx,
|
||||
destructor_did,
|
||||
ccx.tcx().mk_substs(substs),
|
||||
&Substs::trans_empty());
|
||||
output.push(trans_item);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_types_of_owned_components<'a, 'tcx, F>(ccx: &CrateContext<'a, 'tcx>,
|
||||
ty: ty::Ty<'tcx>,
|
||||
visited: &mut FnvHashSet<ty::Ty<'tcx>>,
|
||||
mut f: &mut F)
|
||||
where F: FnMut(ty::Ty<'tcx>) -> bool
|
||||
{
|
||||
let ty = glue::get_drop_glue_type(ccx, ty);
|
||||
|
||||
if !visited.insert(ty) {
|
||||
return;
|
||||
// Finally add the types of nested values
|
||||
match ty.sty {
|
||||
ty::TyBool |
|
||||
ty::TyChar |
|
||||
ty::TyInt(_) |
|
||||
ty::TyUint(_) |
|
||||
ty::TyStr |
|
||||
ty::TyFloat(_) |
|
||||
ty::TyRawPtr(_) |
|
||||
ty::TyRef(..) |
|
||||
ty::TyBareFn(..) |
|
||||
ty::TySlice(_) |
|
||||
ty::TyTrait(_) => {
|
||||
/* nothing to do */
|
||||
}
|
||||
ty::TyStruct(ref adt_def, substs) |
|
||||
ty::TyEnum(ref adt_def, substs) => {
|
||||
for field in adt_def.all_fields() {
|
||||
let field_type = monomorphize::apply_param_substs(ccx.tcx(),
|
||||
substs,
|
||||
&field.unsubst_ty());
|
||||
let field_type = glue::get_drop_glue_type(ccx, field_type);
|
||||
|
||||
if !f(ty) {
|
||||
// Don't recurse further
|
||||
return;
|
||||
if glue::type_needs_drop(ccx.tcx(), field_type) {
|
||||
output.push(TransItem::DropGlue(field_type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match ty.sty {
|
||||
ty::TyBool |
|
||||
ty::TyChar |
|
||||
ty::TyInt(_) |
|
||||
ty::TyUint(_) |
|
||||
ty::TyStr |
|
||||
ty::TyFloat(_) |
|
||||
ty::TyRawPtr(_) |
|
||||
ty::TyRef(..) |
|
||||
ty::TyBareFn(..) |
|
||||
ty::TySlice(_) |
|
||||
ty::TyTrait(_) => {
|
||||
/* nothing to do */
|
||||
}
|
||||
ty::TyStruct(ref adt_def, substs) |
|
||||
ty::TyEnum(ref adt_def, substs) => {
|
||||
for field in adt_def.all_fields() {
|
||||
let field_type = monomorphize::apply_param_substs(ccx.tcx(),
|
||||
substs,
|
||||
&field.unsubst_ty());
|
||||
visit_types_of_owned_components(ccx, field_type, visited, f);
|
||||
ty::TyClosure(_, ref substs) => {
|
||||
for upvar_ty in &substs.upvar_tys {
|
||||
let upvar_ty = glue::get_drop_glue_type(ccx, upvar_ty);
|
||||
if glue::type_needs_drop(ccx.tcx(), upvar_ty) {
|
||||
output.push(TransItem::DropGlue(upvar_ty));
|
||||
}
|
||||
}
|
||||
ty::TyClosure(_, ref substs) => {
|
||||
for upvar_ty in &substs.upvar_tys {
|
||||
visit_types_of_owned_components(ccx, upvar_ty, visited, f);
|
||||
}
|
||||
ty::TyBox(inner_type) |
|
||||
ty::TyArray(inner_type, _) => {
|
||||
let inner_type = glue::get_drop_glue_type(ccx, inner_type);
|
||||
if glue::type_needs_drop(ccx.tcx(), inner_type) {
|
||||
output.push(TransItem::DropGlue(inner_type));
|
||||
}
|
||||
}
|
||||
ty::TyTuple(ref args) => {
|
||||
for arg in args {
|
||||
let arg = glue::get_drop_glue_type(ccx, arg);
|
||||
if glue::type_needs_drop(ccx.tcx(), arg) {
|
||||
output.push(TransItem::DropGlue(arg));
|
||||
}
|
||||
}
|
||||
ty::TyBox(inner_type) |
|
||||
ty::TyArray(inner_type, _) => {
|
||||
visit_types_of_owned_components(ccx, inner_type, visited, f);
|
||||
}
|
||||
ty::TyTuple(ref args) => {
|
||||
for arg in args {
|
||||
visit_types_of_owned_components(ccx, arg, visited, f);
|
||||
}
|
||||
}
|
||||
ty::TyProjection(_) |
|
||||
ty::TyParam(_) |
|
||||
ty::TyInfer(_) |
|
||||
ty::TyError => {
|
||||
ccx.sess().bug("encountered unexpected type");
|
||||
}
|
||||
}
|
||||
ty::TyProjection(_) |
|
||||
ty::TyParam(_) |
|
||||
ty::TyInfer(_) |
|
||||
ty::TyError => {
|
||||
ccx.sess().bug("encountered unexpected type");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1086,10 +1062,8 @@ impl<'b, 'a, 'v> hir_visit::Visitor<'v> for RootCollector<'b, 'a, 'v> {
|
||||
self.ccx.tcx().map.local_def_id(item.id),
|
||||
None));
|
||||
|
||||
create_drop_glue_trans_items(self.ccx,
|
||||
ty,
|
||||
self.trans_empty_substs,
|
||||
self.output);
|
||||
let ty = glue::get_drop_glue_type(self.ccx, ty);
|
||||
self.output.push(TransItem::DropGlue(ty));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user