]> git.lizzy.rs Git - rust.git/commitdiff
Avoid redundant work for drop-glue translation items in trans::collector
authorMichael Woerister <michaelwoerister@posteo.net>
Tue, 26 Jan 2016 15:11:41 +0000 (10:11 -0500)
committerMichael Woerister <michaelwoerister@posteo.net>
Tue, 26 Jan 2016 15:17:54 +0000 (10:17 -0500)
src/librustc_trans/trans/collector.rs

index f8aaa2fcdcab782911f3e1f2f37978389fc7648e..6ec73788598485566d1c1d0eb9e8267d308cdc5e 100644 (file)
@@ -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 @@ fn visit_lvalue(&mut self,
                                                       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));
-
-        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");
-
-                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);
-
-                output.push(exchange_free_fn_trans_item);
-            }
-
-            // 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
-            };
-
-            if let Some(destructor_did) = destructor_did {
-                use rustc::middle::ty::ToPolyTraitRef;
+    debug!("find_drop_glue_neighbors: {}", type_to_string(ccx, 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");
+
+        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());
+
+        output.push(exchange_free_fn_trans_item);
+    }
 
-                let drop_trait_def_id = ccx.tcx()
-                                           .lang_items
-                                           .drop_trait()
-                                           .unwrap();
+    // 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 self_type_substs = ccx.tcx().mk_substs(
-                    Substs::trans_empty().with_self_ty(ty));
+    if let Some(destructor_did) = destructor_did {
+        use rustc::middle::ty::ToPolyTraitRef;
 
-                let trait_ref = ty::TraitRef {
-                    def_id: drop_trait_def_id,
-                    substs: self_type_substs,
-                }.to_poly_trait_ref();
+        let drop_trait_def_id = ccx.tcx()
+                                   .lang_items
+                                   .drop_trait()
+                                   .unwrap();
 
-                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);
-                }
-            }
+        let self_type_substs = ccx.tcx().mk_substs(
+            Substs::trans_empty().with_self_ty(ty));
 
-            true
-        } else {
-            false
-        }
-    });
+        let trait_ref = ty::TraitRef {
+            def_id: drop_trait_def_id,
+            substs: self_type_substs,
+        }.to_poly_trait_ref();
 
-    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);
+        let substs = match fulfill_obligation(ccx, DUMMY_SP, trait_ref) {
+            traits::VtableImpl(data) => data.substs,
+            _ => unreachable!()
+        };
 
-        if !visited.insert(ty) {
-            return;
+        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);
         }
+    }
 
-        if !f(ty) {
-            // Don't recurse further
-            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 */
         }
-
-        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::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 glue::type_needs_drop(ccx.tcx(), field_type) {
+                    output.push(TransItem::DropGlue(field_type));
                 }
             }
-            ty::TyClosure(_, ref substs) => {
-                for upvar_ty in &substs.upvar_tys {
-                    visit_types_of_owned_components(ccx, upvar_ty, 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::TyBox(inner_type)      |
-            ty::TyArray(inner_type, _) => {
-                visit_types_of_owned_components(ccx, inner_type, 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 {
-                    visit_types_of_owned_components(ccx, arg, visited, f);
+        }
+        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::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 @@ fn visit_item(&mut self, item: &'v hir::Item) {
                                                 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));
                     }
                 }
             }