Skip to content

Commit 31ec26d

Browse files
committed
Make calling resource destructors work cross-crate
Tydescs are currently re-created for each compilation unit (and I guess for structural types, they have to be, though the duplication still bothers me). This means a destructor can not be inlined in the drop glue for a resource type, since other crates don't have access to the destructor body. Destructors are now compiled as separate functions with an external symbol that can be looked up in the crate (under the resource type's def_id), and called from the drop glue.
1 parent 8c36a76 commit 31ec26d

File tree

3 files changed

+60
-29
lines changed

3 files changed

+60
-29
lines changed

src/comp/metadata/decoder.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ import pretty::pprust;
1818
export get_symbol;
1919
export get_tag_variants;
2020
export get_type;
21+
export get_type_param_count;
2122
export lookup_defs;
22-
export get_type;
2323
export get_crate_attributes;
2424
export list_crate_metadata;
2525
export get_exported_metadata;
@@ -98,7 +98,7 @@ fn item_type(&ebml::doc item, int this_cnum, ty::ctxt tcx) -> ty::t {
9898
bind parse_external_def_id(this_cnum, _), tcx);
9999
}
100100

101-
fn item_ty_param_count(&ebml::doc item, int this_cnum) -> uint {
101+
fn item_ty_param_count(&ebml::doc item) -> uint {
102102
let uint ty_param_count = 0u;
103103
auto tp = tag_items_data_item_ty_param_count;
104104
for each (ebml::doc p in ebml::tagged_docs(item, tp)) {
@@ -178,11 +178,16 @@ fn get_type(ty::ctxt tcx, ast::def_id def) -> ty::ty_param_count_and_ty {
178178
auto kind_ch = item_kind(item);
179179
auto has_ty_params = kind_has_type_params(kind_ch);
180180
if (has_ty_params) {
181-
tp_count = item_ty_param_count(item, external_crate_id);
181+
tp_count = item_ty_param_count(item);
182182
} else { tp_count = 0u; }
183183
ret tup(tp_count, t);
184184
}
185185

186+
fn get_type_param_count(ty::ctxt tcx, &ast::def_id def) -> uint {
187+
auto data = tcx.sess.get_external_crate(def._0).data;
188+
ret item_ty_param_count(lookup_item(def._1, data));
189+
}
190+
186191
fn get_symbol(session::session sess, ast::def_id def) -> str {
187192
auto external_crate_id = def._0;
188193
auto data = sess.get_external_crate(external_crate_id).data;

src/comp/metadata/encoder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,14 +282,14 @@ fn encode_info_for_item(@crate_ctxt cx, &ebml::writer ebml_w,
282282
tps);
283283
}
284284
case (item_res(_, _, ?tps, ?ctor_id)) {
285-
286285
auto fn_ty = node_id_type(cx, ctor_id);
287286

288287
ebml::start_tag(ebml_w, tag_items_data_item);
289288
encode_def_id(ebml_w, local_def(ctor_id));
290289
encode_kind(ebml_w, 'y' as u8);
291290
encode_type_param_count(ebml_w, tps);
292291
encode_type(cx, ebml_w, ty::ty_fn_ret(cx.tcx, fn_ty));
292+
encode_symbol(cx, ebml_w, item.id);
293293
ebml::end_tag(ebml_w);
294294

295295
index += [tup(ctor_id, ebml_w.writer.tell())];

src/comp/middle/trans.rs

Lines changed: 51 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2090,15 +2090,7 @@ fn make_drop_glue(&@block_ctxt cx, ValueRef v0, &ty::t t) {
20902090
decr_refcnt_maybe_free(cx, box_cell, v0, t)
20912091
}
20922092
case (ty::ty_res(?did, ?inner)) {
2093-
(alt (ccx.ast_map.get(did._1)) {
2094-
case (ast_map::node_item(?i)) {
2095-
alt (i.node) {
2096-
case (ast::item_res(?dtor, _, _, _)) {
2097-
drop_res(cx, v0, inner, dtor)
2098-
}
2099-
}
2100-
}
2101-
})
2093+
trans_res_drop(cx, v0, did, inner)
21022094
}
21032095
case (ty::ty_fn(_, _, _, _, _)) {
21042096
auto box_cell =
@@ -2115,8 +2107,8 @@ fn make_drop_glue(&@block_ctxt cx, ValueRef v0, &ty::t t) {
21152107
rs.bcx.build.RetVoid();
21162108
}
21172109

2118-
fn drop_res(@block_ctxt cx, ValueRef rs, ty::t inner_t, &ast::_fn dtor)
2119-
-> result {
2110+
fn trans_res_drop(@block_ctxt cx, ValueRef rs, &ast::def_id did,
2111+
ty::t inner_t) -> result {
21202112
auto ccx = cx.fcx.lcx.ccx;
21212113
auto tup_ty = ty::mk_imm_tup(ccx.tcx, [ty::mk_int(ccx.tcx), inner_t]);
21222114
auto drop_cx = new_sub_block_ctxt(cx, "drop res");
@@ -2126,12 +2118,29 @@ fn drop_res(@block_ctxt cx, ValueRef rs, ty::t inner_t, &ast::_fn dtor)
21262118
cx = drop_flag.bcx;
21272119
auto null_test = cx.build.IsNull(cx.build.Load(drop_flag.val));
21282120
cx.build.CondBr(null_test, next_cx.llbb, drop_cx.llbb);
2129-
21302121
cx = drop_cx;
2131-
auto val = GEP_tup_like(cx, tup_ty, rs, [0, 1]);
2122+
2123+
// Find and call the actual destructor.
2124+
auto dtor_pair = if (did._0 == ast::local_crate) {
2125+
ccx.fn_pairs.get(did._1)
2126+
} else {
2127+
auto params = decoder::get_type_param_count(ccx.tcx, did);
2128+
auto f_t = type_of_fn(ccx, cx.sp, ast::proto_fn,
2129+
[rec(mode=ty::mo_alias(false), ty=inner_t)],
2130+
ty::mk_nil(ccx.tcx), params);
2131+
get_extern_const(ccx.externs, ccx.llmod,
2132+
decoder::get_symbol(ccx.sess, did),
2133+
T_fn_pair(ccx.tn, f_t))
2134+
};
2135+
auto dtor_addr = cx.build.Load
2136+
(cx.build.GEP(dtor_pair, [C_int(0), C_int(abi::fn_field_code)]));
2137+
auto dtor_env = cx.build.Load
2138+
(cx.build.GEP(dtor_pair, [C_int(0), C_int(abi::fn_field_box)]));
2139+
auto val = GEP_tup_like(cx, tup_ty, rs, [0, 1]);
21322140
cx = val.bcx;
2133-
cx.fcx.llargs.insert(dtor.decl.inputs.(0).id, val.val);
2134-
cx = trans_block(cx, dtor.body, return).bcx;
2141+
cx.build.FastCall(dtor_addr, [cx.fcx.llretptr, cx.fcx.lltaskptr, dtor_env]
2142+
+ cx.fcx.lltydescs + [val.val]);
2143+
21352144
cx = drop_slot(cx, val.val, inner_t).bcx;
21362145
cx.build.Store(C_int(0), drop_flag.val);
21372146
cx.build.Br(next_cx.llbb);
@@ -7827,19 +7836,20 @@ fn trans_obj(@local_ctxt cx, &span sp, &ast::_obj ob, ast::node_id ctor_id,
78277836
finish_fn(fcx, lltop);
78287837
}
78297838

7830-
fn trans_res(@local_ctxt cx, &span sp, &ast::_fn f, ast::node_id ctor_id,
7831-
&vec[ast::ty_param] ty_params) {
7839+
fn trans_res_ctor(@local_ctxt cx, &span sp, &ast::_fn dtor,
7840+
ast::node_id ctor_id, &vec[ast::ty_param] ty_params) {
7841+
// Create a function for the constructor
78327842
auto llctor_decl = cx.ccx.item_ids.get(ctor_id);
78337843
auto fcx = new_fn_ctxt(cx, sp, llctor_decl);
78347844
auto ret_t = ty::ret_ty_of_fn(cx.ccx.tcx, ctor_id);
78357845
create_llargs_for_fn_args(fcx, ast::proto_fn, none[ty_self_pair],
7836-
ret_t, f.decl.inputs, ty_params);
7846+
ret_t, dtor.decl.inputs, ty_params);
78377847
auto bcx = new_top_block_ctxt(fcx);
78387848
auto lltop = bcx.llbb;
78397849
auto arg_t = arg_tys_of_fn(cx.ccx, ctor_id).(0).ty;
78407850
auto tup_t = ty::mk_imm_tup(cx.ccx.tcx, [ty::mk_int(cx.ccx.tcx), arg_t]);
78417851
auto arg = load_if_immediate
7842-
(bcx, fcx.llargs.get(f.decl.inputs.(0).id), arg_t);
7852+
(bcx, fcx.llargs.get(dtor.decl.inputs.(0).id), arg_t);
78437853
auto dst = GEP_tup_like(bcx, tup_t, fcx.llretptr, [0, 1]);
78447854
bcx = dst.bcx;
78457855
bcx = copy_val(bcx, INIT, dst.val, arg, arg_t).bcx;
@@ -7959,8 +7969,11 @@ fn trans_item(@local_ctxt cx, &ast::item item) {
79597969
with *extend_path(cx, item.ident));
79607970
trans_obj(sub_cx, item.span, ob, ctor_id, tps);
79617971
}
7962-
case (ast::item_res(?decl, _, ?tps, ?ctor_id)) {
7963-
trans_res(cx, item.span, decl, ctor_id, tps);
7972+
case (ast::item_res(?dtor, ?dtor_id, ?tps, ?ctor_id)) {
7973+
trans_res_ctor(cx, item.span, dtor, ctor_id, tps);
7974+
// Create a function for the destructor
7975+
auto lldtor_decl = cx.ccx.item_ids.get(item.id);
7976+
trans_fn(cx, item.span, dtor, lldtor_decl, none, tps, dtor_id);
79647977
}
79657978
case (ast::item_mod(?m)) {
79667979
auto sub_cx =
@@ -7999,10 +8012,17 @@ fn get_pair_fn_ty(TypeRef llpairty) -> TypeRef {
79998012
ret struct_elt(llpairty, 0u);
80008013
}
80018014

8002-
fn decl_fn_and_pair(&@crate_ctxt ccx, &span sp, vec[str] path, str flav,
8015+
fn decl_fn_and_pair(&@crate_ctxt ccx, &span sp, &vec[str] path, str flav,
80038016
vec[ast::ty_param] ty_params, ast::node_id node_id) {
8017+
decl_fn_and_pair_full(ccx, sp, path, flav, ty_params, node_id,
8018+
node_id_type(ccx, node_id));
8019+
}
8020+
8021+
fn decl_fn_and_pair_full(&@crate_ctxt ccx, &span sp, &vec[str] path, str flav,
8022+
vec[ast::ty_param] ty_params, ast::node_id node_id,
8023+
ty::t node_type) {
80048024
auto llfty;
8005-
alt (ty::struct(ccx.tcx, node_id_type(ccx, node_id))) {
8025+
alt (ty::struct(ccx.tcx, node_type)) {
80068026
case (ty::ty_fn(?proto, ?inputs, ?output, _, _)) {
80078027
llfty =
80088028
type_of_fn(ccx, sp, proto, inputs, output,
@@ -8023,7 +8043,7 @@ fn decl_fn_and_pair(&@crate_ctxt ccx, &span sp, vec[str] path, str flav,
80238043
let ValueRef llfn = decl_internal_fastcall_fn(ccx.llmod, s, llfty);
80248044
// Declare the global constant pair that points to it.
80258045

8026-
let str ps = mangle_exported_name(ccx, path, node_id_type(ccx, node_id));
8046+
let str ps = mangle_exported_name(ccx, path, node_type);
80278047
register_fn_pair(ccx, ps, llfty, llfn, node_id);
80288048
if (is_main) {
80298049
if (ccx.main_fn != none[ValueRef]) {
@@ -8295,8 +8315,14 @@ fn collect_item_2(&@crate_ctxt ccx, &@ast::item i, &vec[str] pt,
82958315
ccx.obj_methods.insert(m.node.id, ());
82968316
}
82978317
}
8298-
case (ast::item_res(?decl, _, ?tps, ?ctor_id)) {
8318+
case (ast::item_res(_, ?dtor_id, ?tps, ?ctor_id)) {
82998319
decl_fn_and_pair(ccx, i.span, new_pt, "res_ctor", tps, ctor_id);
8320+
// Note that the destructor is associated with the item's id, not
8321+
// the dtor_id. This is a bit counter-intuitive, but simplifies
8322+
// ty_res, which would have to carry around two def_ids otherwise
8323+
// -- one to identify the type, and one to find the dtor symbol.
8324+
decl_fn_and_pair_full(ccx, i.span, new_pt, "res_dtor", tps, i.id,
8325+
node_id_type(ccx, dtor_id));
83008326
}
83018327
case (_) { }
83028328
}

0 commit comments

Comments
 (0)