Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't instantiate so many copies of drop_in_place #67332

Merged
merged 2 commits into from
Feb 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 21 additions & 4 deletions src/librustc/ty/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@ pub enum InstanceDef<'tcx> {
call_once: DefId,
},

/// `drop_in_place::<T>; None` for empty drop glue.
/// `core::ptr::drop_in_place::<T>`.
/// The `DefId` is for `core::ptr::drop_in_place`.
/// The `Option<Ty<'tcx>>` is either `Some(T)`, or `None` for empty drop
/// glue.
DropGlue(DefId, Option<Ty<'tcx>>),

///`<T as Clone>::clone` shim.
Expand Down Expand Up @@ -177,11 +180,25 @@ impl<'tcx> InstanceDef<'tcx> {
if self.requires_inline(tcx) {
return true;
}
if let ty::InstanceDef::DropGlue(..) = *self {
// Drop glue wants to be instantiated at every codegen
if let ty::InstanceDef::DropGlue(.., Some(ty)) = *self {
// Drop glue generally wants to be instantiated at every codegen
// unit, but without an #[inline] hint. We should make this
// available to normal end-users.
return true;
if tcx.sess.opts.incremental.is_none() {
return true;
}
// When compiling with incremental, we can generate a *lot* of
// codegen units. Including drop glue into all of them has a
// considerable compile time cost.
//
// We include enums without destructors to allow, say, optimizing
// drops of `Option::None` before LTO. We also respect the intent of
// `#[inline]` on `Drop::drop` implementations.
return ty.ty_adt_def().map_or(true, |adt_def| {
adt_def.destructor(tcx).map_or(adt_def.is_enum(), |dtor| {
tcx.codegen_fn_attrs(dtor.did).requests_inline()
})
});
}
tcx.codegen_fn_attrs(self.def_id()).requests_inline()
}
Expand Down
13 changes: 10 additions & 3 deletions src/librustc_mir/monomorphize/partitioning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -680,13 +680,20 @@ fn characteristic_def_id_of_mono_item<'tcx>(

if tcx.trait_of_item(def_id).is_some() {
let self_ty = instance.substs.type_at(0);
// This is an implementation of a trait method.
// This is a default implementation of a trait method.
return characteristic_def_id_of_type(self_ty).or(Some(def_id));
}

if let Some(impl_def_id) = tcx.impl_of_method(def_id) {
// This is a method within an inherent impl, find out what the
// self-type is:
if tcx.sess.opts.incremental.is_some()
&& tcx.trait_id_of_impl(impl_def_id) == tcx.lang_items().drop_trait()
{
// Put `Drop::drop` into the same cgu as `drop_in_place`
// since `drop_in_place` is the only thing that can
// call it.
return None;
}
// This is a method within an impl, find out what the self-type is:
let impl_self_ty = tcx.subst_and_normalize_erasing_regions(
instance.substs,
ty::ParamEnv::reveal_all(),
Expand Down
17 changes: 8 additions & 9 deletions src/test/codegen-units/partitioning/extern-drop-glue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@

// We specify -Z incremental here because we want to test the partitioning for
// incremental compilation
// We specify opt-level=0 because `drop_in_place` is `Internal` when optimizing
// compile-flags:-Zprint-mono-items=lazy -Zincremental=tmp/partitioning-tests/extern-drop-glue
// compile-flags:-Zinline-in-all-cgus
// compile-flags:-Zinline-in-all-cgus -Copt-level=0

#![allow(dead_code)]
#![crate_type="rlib"]
#![crate_type = "rlib"]

// aux-build:cgu_extern_drop_glue.rs
extern crate cgu_extern_drop_glue;

//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<cgu_extern_drop_glue::Struct[0]> @@ extern_drop_glue[Internal] extern_drop_glue-mod1[Internal]
//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<cgu_extern_drop_glue::Struct[0]> @@ extern_drop_glue-fallback.cgu[External]

struct LocalStruct(cgu_extern_drop_glue::Struct);

//~ MONO_ITEM fn extern_drop_glue::user[0] @@ extern_drop_glue[External]
pub fn user()
{
//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<extern_drop_glue::LocalStruct[0]> @@ extern_drop_glue[Internal]
pub fn user() {
//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<extern_drop_glue::LocalStruct[0]> @@ extern_drop_glue-fallback.cgu[External]
let _ = LocalStruct(cgu_extern_drop_glue::Struct(0));
}

Expand All @@ -28,9 +28,8 @@ pub mod mod1 {
struct LocalStruct(cgu_extern_drop_glue::Struct);

//~ MONO_ITEM fn extern_drop_glue::mod1[0]::user[0] @@ extern_drop_glue-mod1[External]
pub fn user()
{
//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<extern_drop_glue::mod1[0]::LocalStruct[0]> @@ extern_drop_glue-mod1[Internal]
pub fn user() {
//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<extern_drop_glue::mod1[0]::LocalStruct[0]> @@ extern_drop_glue-fallback.cgu[External]
let _ = LocalStruct(cgu_extern_drop_glue::Struct(0));
}
}
39 changes: 15 additions & 24 deletions src/test/codegen-units/partitioning/local-drop-glue.rs
Original file line number Diff line number Diff line change
@@ -1,54 +1,45 @@
// ignore-tidy-linelength
// We specify -Z incremental here because we want to test the partitioning for
// incremental compilation
// We specify opt-level=0 because `drop_in_place` is `Internal` when optimizing
// compile-flags:-Zprint-mono-items=lazy -Zincremental=tmp/partitioning-tests/local-drop-glue
// compile-flags:-Zinline-in-all-cgus
// compile-flags:-Zinline-in-all-cgus -Copt-level=0

#![allow(dead_code)]
#![crate_type="rlib"]
#![crate_type = "rlib"]

//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<local_drop_glue::Struct[0]> @@ local_drop_glue[Internal] local_drop_glue-mod1[Internal]
//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<local_drop_glue::Struct[0]> @@ local_drop_glue-fallback.cgu[External]
struct Struct {
_a: u32
_a: u32,
}

impl Drop for Struct {
//~ MONO_ITEM fn local_drop_glue::{{impl}}[0]::drop[0] @@ local_drop_glue[External]
//~ MONO_ITEM fn local_drop_glue::{{impl}}[0]::drop[0] @@ local_drop_glue-fallback.cgu[External]
fn drop(&mut self) {}
}

//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<local_drop_glue::Outer[0]> @@ local_drop_glue[Internal]
//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<local_drop_glue::Outer[0]> @@ local_drop_glue-fallback.cgu[External]
struct Outer {
_a: Struct
_a: Struct,
}

//~ MONO_ITEM fn local_drop_glue::user[0] @@ local_drop_glue[External]
pub fn user()
{
let _ = Outer {
_a: Struct {
_a: 0
}
};
pub fn user() {
let _ = Outer { _a: Struct { _a: 0 } };
}

pub mod mod1
{
pub mod mod1 {
use super::Struct;

//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<local_drop_glue::mod1[0]::Struct2[0]> @@ local_drop_glue-mod1[Internal]
//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<local_drop_glue::mod1[0]::Struct2[0]> @@ local_drop_glue-fallback.cgu[External]
struct Struct2 {
_a: Struct,
//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(u32, local_drop_glue::Struct[0])> @@ local_drop_glue-mod1[Internal]
//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(u32, local_drop_glue::Struct[0])> @@ local_drop_glue-fallback.cgu[Internal]
_b: (u32, Struct),
}

//~ MONO_ITEM fn local_drop_glue::mod1[0]::user[0] @@ local_drop_glue-mod1[External]
pub fn user()
{
let _ = Struct2 {
_a: Struct { _a: 0 },
_b: (0, Struct { _a: 0 }),
};
pub fn user() {
let _ = Struct2 { _a: Struct { _a: 0 }, _b: (0, Struct { _a: 0 }) };
}
}