Skip to content

Commit e09bef8

Browse files
committed
avoid duplicate translation of monomorphizations, drop glue, and visit glue
Use a shared lookup table of previously-translated monomorphizations/glue functions to avoid translating those functions in every compilation unit where they're used. Instead, the function will be translated in whichever compilation unit uses it first, and the remaining compilation units will link against that original definition.
1 parent da96062 commit e09bef8

File tree

5 files changed

+114
-31
lines changed

5 files changed

+114
-31
lines changed

src/librustc/middle/trans/base.rs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2124,11 +2124,24 @@ impl<'a> Visitor<()> for TransItemVisitor<'a> {
21242124
}
21252125
}
21262126

2127-
pub fn update_linkage(ccx: &CrateContext, llval: ValueRef, id: ast::NodeId) {
2128-
if ccx.reachable().contains(&id) || ccx.sess().opts.cg.codegen_units > 1 {
2129-
llvm::SetLinkage(llval, llvm::ExternalLinkage);
2130-
} else {
2131-
llvm::SetLinkage(llval, llvm::InternalLinkage);
2127+
/// Set the appropriate linkage for an LLVM `ValueRef` (function or global).
2128+
/// If the `llval` is the direct translation of a specific Rust item, `id`
2129+
/// should be set to the `NodeId` of that item. (This mapping should be
2130+
/// 1-to-1, so monomorphizations and drop/visit glue should have `id` set to
2131+
/// `None`.)
2132+
pub fn update_linkage(ccx: &CrateContext, llval: ValueRef, id: Option<ast::NodeId>) {
2133+
match id {
2134+
Some(id) if ccx.reachable().contains(&id) => {
2135+
llvm::SetLinkage(llval, llvm::ExternalLinkage);
2136+
},
2137+
_ => {
2138+
// `id` does not refer to an item in `ccx.reachable`.
2139+
if ccx.sess().opts.cg.codegen_units > 1 {
2140+
llvm::SetLinkage(llval, llvm::ExternalLinkage);
2141+
} else {
2142+
llvm::SetLinkage(llval, llvm::InternalLinkage);
2143+
}
2144+
},
21322145
}
21332146
}
21342147

@@ -2157,7 +2170,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
21572170
item.id,
21582171
item.attrs.as_slice());
21592172
}
2160-
update_linkage(ccx, llfn, item.id);
2173+
update_linkage(ccx, llfn, Some(item.id));
21612174
}
21622175

21632176
// Be sure to travel more than just one layer deep to catch nested
@@ -2185,7 +2198,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
21852198
consts::trans_const(ccx, m, item.id);
21862199

21872200
let g = get_item_val(ccx, item.id);
2188-
update_linkage(ccx, g, item.id);
2201+
update_linkage(ccx, g, Some(item.id));
21892202

21902203
// Do static_assert checking. It can't really be done much earlier
21912204
// because we need to get the value of the bool out of LLVM

src/librustc/middle/trans/context.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ pub struct SharedCrateContext {
7272
symbol_hasher: RefCell<Sha256>,
7373
tcx: ty::ctxt,
7474
stats: Stats,
75+
76+
available_monomorphizations: RefCell<HashSet<String>>,
77+
available_drop_glues: RefCell<HashMap<ty::t, String>>,
78+
available_visit_glues: RefCell<HashMap<ty::t, String>>,
7579
}
7680

7781
/// The local portion of a `CrateContext`. There is one `LocalCrateContext`
@@ -233,6 +237,9 @@ impl SharedCrateContext {
233237
llvm_insns: RefCell::new(HashMap::new()),
234238
fn_stats: RefCell::new(Vec::new()),
235239
},
240+
available_monomorphizations: RefCell::new(HashSet::new()),
241+
available_drop_glues: RefCell::new(HashMap::new()),
242+
available_visit_glues: RefCell::new(HashMap::new()),
236243
};
237244

238245
for i in range(0, local_count) {
@@ -612,6 +619,18 @@ impl<'b> CrateContext<'b> {
612619
&self.shared.stats
613620
}
614621

622+
pub fn available_monomorphizations<'a>(&'a self) -> &'a RefCell<HashSet<String>> {
623+
&self.shared.available_monomorphizations
624+
}
625+
626+
pub fn available_drop_glues<'a>(&'a self) -> &'a RefCell<HashMap<ty::t, String>> {
627+
&self.shared.available_drop_glues
628+
}
629+
630+
pub fn available_visit_glues<'a>(&'a self) -> &'a RefCell<HashMap<ty::t, String>> {
631+
&self.shared.available_visit_glues
632+
}
633+
615634
pub fn int_type(&self) -> Type {
616635
self.local.int_type
617636
}

src/librustc/middle/trans/glue.rs

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -171,11 +171,30 @@ pub fn get_drop_glue(ccx: &CrateContext, t: ty::t) -> ValueRef {
171171
};
172172

173173
let llfnty = Type::glue_fn(ccx, llty);
174-
let glue = declare_generic_glue(ccx, t, llfnty, "drop");
174+
175+
let (glue, new_sym) = match ccx.available_drop_glues().borrow().find(&t) {
176+
Some(old_sym) => {
177+
let glue = decl_cdecl_fn(ccx, old_sym.as_slice(), llfnty, ty::mk_nil());
178+
(glue, None)
179+
},
180+
None => {
181+
let (sym, glue) = declare_generic_glue(ccx, t, llfnty, "drop");
182+
(glue, Some(sym))
183+
},
184+
};
175185

176186
ccx.drop_glues().borrow_mut().insert(t, glue);
177187

178-
make_generic_glue(ccx, t, glue, make_drop_glue, "drop");
188+
// To avoid infinite recursion, don't `make_drop_glue` until after we've
189+
// added the entry to the `drop_glues` cache.
190+
match new_sym {
191+
Some(sym) => {
192+
ccx.available_drop_glues().borrow_mut().insert(t, sym);
193+
// We're creating a new drop glue, so also generate a body.
194+
make_generic_glue(ccx, t, glue, make_drop_glue, "drop");
195+
},
196+
None => {},
197+
}
179198

180199
glue
181200
}
@@ -189,9 +208,28 @@ pub fn lazily_emit_visit_glue(ccx: &CrateContext, ti: &tydesc_info) -> ValueRef
189208
Some(visit_glue) => visit_glue,
190209
None => {
191210
debug!("+++ lazily_emit_tydesc_glue VISIT {}", ppaux::ty_to_string(ccx.tcx(), ti.ty));
192-
let glue_fn = declare_generic_glue(ccx, ti.ty, llfnty, "visit");
211+
212+
let (glue_fn, new_sym) = match ccx.available_visit_glues().borrow().find(&ti.ty) {
213+
Some(old_sym) => {
214+
let glue_fn = decl_cdecl_fn(ccx, old_sym.as_slice(), llfnty, ty::mk_nil());
215+
(glue_fn, None)
216+
},
217+
None => {
218+
let (sym, glue_fn) = declare_generic_glue(ccx, ti.ty, llfnty, "visit");
219+
(glue_fn, Some(sym))
220+
},
221+
};
222+
193223
ti.visit_glue.set(Some(glue_fn));
194-
make_generic_glue(ccx, ti.ty, glue_fn, make_visit_glue, "visit");
224+
225+
match new_sym {
226+
Some(sym) => {
227+
ccx.available_visit_glues().borrow_mut().insert(ti.ty, sym);
228+
make_generic_glue(ccx, ti.ty, glue_fn, make_visit_glue, "visit");
229+
},
230+
None => {},
231+
}
232+
195233
debug!("--- lazily_emit_tydesc_glue VISIT {}", ppaux::ty_to_string(ccx.tcx(), ti.ty));
196234
glue_fn
197235
}
@@ -602,15 +640,15 @@ pub fn declare_tydesc(ccx: &CrateContext, t: ty::t) -> tydesc_info {
602640
}
603641

604642
fn declare_generic_glue(ccx: &CrateContext, t: ty::t, llfnty: Type,
605-
name: &str) -> ValueRef {
643+
name: &str) -> (String, ValueRef) {
606644
let _icx = push_ctxt("declare_generic_glue");
607645
let fn_nm = mangle_internal_name_by_type_and_seq(
608646
ccx,
609647
t,
610648
format!("glue_{}", name).as_slice());
611649
let llfn = decl_cdecl_fn(ccx, fn_nm.as_slice(), llfnty, ty::mk_nil());
612-
note_unique_llvm_symbol(ccx, fn_nm);
613-
return llfn;
650+
note_unique_llvm_symbol(ccx, fn_nm.clone());
651+
return (fn_nm, llfn);
614652
}
615653

616654
fn make_generic_glue(ccx: &CrateContext,
@@ -631,7 +669,8 @@ fn make_generic_glue(ccx: &CrateContext,
631669

632670
let bcx = init_function(&fcx, false, ty::mk_nil());
633671

634-
llvm::SetLinkage(llfn, llvm::InternalLinkage);
672+
update_linkage(ccx, llfn, None);
673+
635674
ccx.stats().n_glues_created.set(ccx.stats().n_glues_created.get() + 1u);
636675
// All glue functions take values passed *by alias*; this is a
637676
// requirement since in many contexts glue is invoked indirectly and

src/librustc/middle/trans/meth.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ pub fn trans_impl(ccx: &CrateContext,
8585
&param_substs::empty(),
8686
method.id,
8787
[]);
88-
update_linkage(ccx, llfn, method.id);
88+
update_linkage(ccx, llfn, Some(method.id));
8989
}
9090
let mut v = TransItemVisitor {
9191
ccx: ccx,

src/librustc/middle/trans/monomorphize.rs

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -159,14 +159,18 @@ pub fn monomorphic_fn(ccx: &CrateContext,
159159
..
160160
} => {
161161
let d = mk_lldecl(abi);
162+
base::update_linkage(ccx, d, None);
162163
set_llvm_fn_attrs(i.attrs.as_slice(), d);
163164

164-
if abi != abi::Rust {
165-
foreign::trans_rust_fn_with_foreign_abi(
166-
ccx, &**decl, &**body, [], d, &psubsts, fn_id.node,
167-
Some(hash.as_slice()));
168-
} else {
169-
trans_fn(ccx, &**decl, &**body, d, &psubsts, fn_id.node, []);
165+
if !ccx.available_monomorphizations().borrow().contains(&s) {
166+
ccx.available_monomorphizations().borrow_mut().insert(s.clone());
167+
if abi != abi::Rust {
168+
foreign::trans_rust_fn_with_foreign_abi(
169+
ccx, &**decl, &**body, [], d, &psubsts, fn_id.node,
170+
Some(hash.as_slice()));
171+
} else {
172+
trans_fn(ccx, &**decl, &**body, d, &psubsts, fn_id.node, []);
173+
}
170174
}
171175

172176
d
@@ -201,14 +205,18 @@ pub fn monomorphic_fn(ccx: &CrateContext,
201205
match *ii {
202206
ast::MethodImplItem(mth) => {
203207
let d = mk_lldecl(abi::Rust);
208+
base::update_linkage(ccx, d, None);
204209
set_llvm_fn_attrs(mth.attrs.as_slice(), d);
205-
trans_fn(ccx,
206-
&*mth.pe_fn_decl(),
207-
&*mth.pe_body(),
208-
d,
209-
&psubsts,
210-
mth.id,
211-
[]);
210+
if !ccx.available_monomorphizations().borrow().contains(&s) {
211+
ccx.available_monomorphizations().borrow_mut().insert(s.clone());
212+
trans_fn(ccx,
213+
&*mth.pe_fn_decl(),
214+
&*mth.pe_body(),
215+
d,
216+
&psubsts,
217+
mth.id,
218+
[]);
219+
}
212220
d
213221
}
214222
}
@@ -217,9 +225,13 @@ pub fn monomorphic_fn(ccx: &CrateContext,
217225
match *method {
218226
ast::ProvidedMethod(mth) => {
219227
let d = mk_lldecl(abi::Rust);
228+
base::update_linkage(ccx, d, None);
220229
set_llvm_fn_attrs(mth.attrs.as_slice(), d);
221-
trans_fn(ccx, &*mth.pe_fn_decl(), &*mth.pe_body(), d,
222-
&psubsts, mth.id, []);
230+
if !ccx.available_monomorphizations().borrow().contains(&s) {
231+
ccx.available_monomorphizations().borrow_mut().insert(s.clone());
232+
trans_fn(ccx, &*mth.pe_fn_decl(), &*mth.pe_body(), d,
233+
&psubsts, mth.id, []);
234+
}
223235
d
224236
}
225237
_ => {

0 commit comments

Comments
 (0)