Skip to content

Commit 7c7cb26

Browse files
committed
treat different kinds of closures differently
1 parent 35fe86d commit 7c7cb26

File tree

1 file changed

+53
-19
lines changed

1 file changed

+53
-19
lines changed

src/comp/middle/trans.rs

Lines changed: 53 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1292,20 +1292,27 @@ fn emit_tydescs(ccx: @crate_ctxt) {
12921292

12931293
fn make_take_glue(cx: @block_ctxt, v: ValueRef, t: ty::t) {
12941294
let bcx = cx;
1295+
let tcx = bcx_tcx(cx);
12951296
// NB: v is an *alias* of type t here, not a direct value.
1296-
if ty::type_is_boxed(bcx_tcx(bcx), t) {
1297+
alt ty::struct(tcx, t) {
1298+
ty::ty_box(_) {
12971299
bcx = incr_refcnt_of_boxed(bcx, Load(bcx, v));
1298-
} else if ty::type_is_unique_box(bcx_tcx(bcx), t) {
1300+
}
1301+
ty::ty_uniq(_) {
12991302
check trans_uniq::type_is_unique_box(bcx, t);
13001303
let {bcx: cx, val} = trans_uniq::duplicate(bcx, Load(bcx, v), t);
13011304
bcx = cx;
13021305
Store(bcx, val, v);
1303-
} else if ty::type_is_structural(bcx_tcx(bcx), t) {
1304-
bcx = iter_structural_ty(bcx, v, t, take_ty);
1305-
} else if ty::type_is_vec(bcx_tcx(bcx), t) {
1306+
}
1307+
ty::ty_vec(_) | ty::ty_str. {
13061308
let {bcx: cx, val} = tvec::duplicate(bcx, Load(bcx, v), t);
13071309
bcx = cx;
13081310
Store(bcx, val, v);
1311+
}
1312+
_ when ty::type_is_structural(bcx_tcx(bcx), t) {
1313+
bcx = iter_structural_ty(bcx, v, t, take_ty);
1314+
}
1315+
_ { /* fallthrough */ }
13091316
}
13101317

13111318
build_return(bcx);
@@ -1321,6 +1328,19 @@ fn incr_refcnt_of_boxed(cx: @block_ctxt, box_ptr: ValueRef) -> @block_ctxt {
13211328
ret cx;
13221329
}
13231330

1331+
fn call_bound_data_glue_for_closure(bcx: @block_ctxt,
1332+
v: ValueRef,
1333+
field: int) {
1334+
// Call through the closure's own fields-drop glue.
1335+
let ccx = bcx_ccx(bcx);
1336+
let v = PointerCast(bcx, v, T_opaque_closure_ptr(ccx));
1337+
let body = GEPi(bcx, v, [0, abi::box_rc_field_body]);
1338+
let bindings = GEPi(bcx, body, [0, abi::closure_elt_bindings]);
1339+
let tydescptr = GEPi(bcx, body, [0, abi::closure_elt_tydesc]);
1340+
let ti = none;
1341+
call_tydesc_glue_full(bcx, bindings, Load(bcx, tydescptr), field, ti);
1342+
}
1343+
13241344
fn make_free_glue(bcx: @block_ctxt, v: ValueRef, t: ty::t) {
13251345
// v is a pointer to the actual box component of the type here. The
13261346
// ValueRef will have the wrong type here (make_generic_glue is casting
@@ -1359,19 +1379,22 @@ fn make_free_glue(bcx: @block_ctxt, v: ValueRef, t: ty::t) {
13591379
trans_non_gc_free(bcx, b)
13601380
} else { bcx }
13611381
}
1362-
ty::ty_fn(_, _, _, _, _) {
1363-
// Call through the closure's own fields-drop glue first.
1364-
// Then free the body.
1365-
let ccx = bcx_ccx(bcx);
1366-
let v = PointerCast(bcx, v, T_opaque_closure_ptr(ccx));
1367-
let body = GEPi(bcx, v, [0, abi::box_rc_field_body]);
1368-
let bindings =
1369-
GEPi(bcx, body, [0, abi::closure_elt_bindings]);
1370-
let tydescptr =
1371-
GEPi(bcx, body, [0, abi::closure_elt_tydesc]);
1372-
let ti = none;
1373-
call_tydesc_glue_full(bcx, bindings, Load(bcx, tydescptr),
1374-
abi::tydesc_field_drop_glue, ti);
1382+
ty::ty_fn(ast::proto_bare., _, _, _, _) {
1383+
bcx
1384+
}
1385+
ty::ty_fn(ast::proto_block., _, _, _, _) {
1386+
bcx
1387+
}
1388+
ty::ty_fn(ast::proto_send., _, _, _, _) {
1389+
// n.b.: When we drop a function, we actually invoke the
1390+
// free glue only on the environment part.
1391+
call_bound_data_glue_for_closure(bcx, v, abi::tydesc_field_drop_glue);
1392+
trans_shared_free(bcx, v)
1393+
}
1394+
ty::ty_fn(ast::proto_shared(_), _, _, _, _) {
1395+
// n.b.: When we drop a function, we actually invoke the
1396+
// free glue only on the environment part.
1397+
call_bound_data_glue_for_closure(bcx, v, abi::tydesc_field_drop_glue);
13751398
if !bcx_ccx(bcx).sess.get_opts().do_gc {
13761399
trans_non_gc_free(bcx, v)
13771400
} else { bcx }
@@ -1398,7 +1421,18 @@ fn make_drop_glue(bcx: @block_ctxt, v0: ValueRef, t: ty::t) {
13981421
ty::ty_res(did, inner, tps) {
13991422
trans_res_drop(bcx, v0, did, inner, tps)
14001423
}
1401-
ty::ty_fn(_, _, _, _, _) {
1424+
ty::ty_fn(ast::proto_bare., _, _, _, _) {
1425+
bcx // No environment to free.
1426+
}
1427+
ty::ty_fn(ast::proto_block., _, _, _, _) {
1428+
bcx // Environment is stack allocated and needs no free.
1429+
}
1430+
ty::ty_fn(ast::proto_send., _, _, _, _) {
1431+
// Environment is a unique pointer.
1432+
let box_cell = GEPi(bcx, v0, [0, abi::fn_field_box]);
1433+
free_ty(bcx, Load(bcx, box_cell), t)
1434+
}
1435+
ty::ty_fn(ast::proto_shared(_), _, _, _, _) {
14021436
let box_cell = GEPi(bcx, v0, [0, abi::fn_field_box]);
14031437
decr_refcnt_maybe_free(bcx, Load(bcx, box_cell), t)
14041438
}

0 commit comments

Comments
 (0)