Skip to content

Commit fa12953

Browse files
committed
Make free glue take a pointer to the heap part (box)
This way, it can be used to drop values without first spilling them. Issue #1012
1 parent 96f6a18 commit fa12953

File tree

2 files changed

+67
-70
lines changed

2 files changed

+67
-70
lines changed

src/comp/middle/trans.rs

Lines changed: 66 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ import trans_build::*;
4646
import trans_objects::{trans_anon_obj, trans_obj};
4747
import tvec = trans_vec;
4848

49+
fn type_of_1(bcx: @block_ctxt, t: ty::t) -> TypeRef {
50+
let cx = bcx_ccx(bcx);
51+
check type_has_static_size(cx, t);
52+
type_of(cx, bcx.sp, t)
53+
}
54+
4955
fn type_of(cx: @crate_ctxt, sp: span, t: ty::t) : type_has_static_size(cx, t)
5056
-> TypeRef {
5157
// Should follow from type_has_static_size -- argh.
@@ -1335,62 +1341,59 @@ fn incr_refcnt_of_boxed(cx: @block_ctxt, box_ptr: ValueRef) -> @block_ctxt {
13351341
ret cx;
13361342
}
13371343

1338-
fn make_free_glue(bcx: @block_ctxt, v0: ValueRef, t: ty::t) {
1339-
// NB: v is an *alias* of type t here, not a direct value.
1340-
let bcx =
1341-
alt ty::struct(bcx_tcx(bcx), t) {
1342-
ty::ty_box(body_mt) {
1343-
let v = Load(bcx, v0);
1344-
let body = GEP(bcx, v, [C_int(0), C_int(abi::box_rc_field_body)]);
1345-
let bcx = drop_ty(bcx, body, body_mt.ty);
1346-
if !bcx_ccx(bcx).sess.get_opts().do_gc {
1347-
trans_non_gc_free(bcx, v)
1348-
} else { bcx }
1349-
}
1350-
ty::ty_uniq(content_mt) {
1351-
check trans_uniq::type_is_unique_box(bcx, t);
1352-
trans_uniq::make_free_glue(bcx, v0, t)
1353-
}
1354-
ty::ty_obj(_) {
1355-
// Call through the obj's own fields-drop glue first.
1356-
// Then free the body.
1357-
let box_cell =
1358-
GEP(bcx, v0, [C_int(0), C_int(abi::obj_field_box)]);
1359-
let b = Load(bcx, box_cell);
1360-
let ccx = bcx_ccx(bcx);
1361-
let llbox_ty = T_opaque_obj_ptr(*ccx);
1362-
b = PointerCast(bcx, b, llbox_ty);
1363-
let body = GEP(bcx, b, [C_int(0), C_int(abi::box_rc_field_body)]);
1364-
let tydescptr =
1365-
GEP(bcx, body, [C_int(0), C_int(abi::obj_body_elt_tydesc)]);
1366-
let tydesc = Load(bcx, tydescptr);
1367-
let ti = none;
1368-
call_tydesc_glue_full(bcx, body, tydesc,
1369-
abi::tydesc_field_drop_glue, ti);
1370-
if !bcx_ccx(bcx).sess.get_opts().do_gc {
1371-
trans_non_gc_free(bcx, b)
1372-
} else { bcx }
1373-
}
1374-
ty::ty_fn(_, _, _, _, _) {
1375-
// Call through the closure's own fields-drop glue first.
1376-
// Then free the body.
1377-
let box_cell = GEP(bcx, v0, [C_int(0), C_int(abi::fn_field_box)]);
1378-
let v = Load(bcx, box_cell);
1379-
let body = GEP(bcx, v, [C_int(0), C_int(abi::box_rc_field_body)]);
1380-
let bindings =
1381-
GEP(bcx, body, [C_int(0), C_int(abi::closure_elt_bindings)]);
1382-
let tydescptr =
1383-
GEP(bcx, body, [C_int(0), C_int(abi::closure_elt_tydesc)]);
1384-
let ti = none;
1385-
call_tydesc_glue_full(bcx, bindings, Load(bcx, tydescptr),
1386-
abi::tydesc_field_drop_glue, ti);
1387-
if !bcx_ccx(bcx).sess.get_opts().do_gc {
1388-
trans_non_gc_free(bcx, v)
1389-
} else { bcx }
1390-
}
1391-
_ { bcx }
1392-
};
1393-
1344+
fn make_free_glue(bcx: @block_ctxt, v: ValueRef, t: ty::t) {
1345+
// v is a pointer to the actual box component of the type here. The
1346+
// ValueRef will have the wrong type here (make_generic_glue is casting
1347+
// everything to a pointer to the type that the glue acts on).
1348+
let bcx = alt ty::struct(bcx_tcx(bcx), t) {
1349+
ty::ty_box(body_mt) {
1350+
v = PointerCast(bcx, v, type_of_1(bcx, t));
1351+
let body = GEP(bcx, v, [C_int(0), C_int(abi::box_rc_field_body)]);
1352+
let bcx = drop_ty(bcx, body, body_mt.ty);
1353+
if !bcx_ccx(bcx).sess.get_opts().do_gc {
1354+
trans_non_gc_free(bcx, v)
1355+
} else { bcx }
1356+
}
1357+
ty::ty_uniq(content_mt) {
1358+
check trans_uniq::type_is_unique_box(bcx, t);
1359+
v = PointerCast(bcx, v, type_of_1(bcx, t));
1360+
trans_uniq::make_free_glue(bcx, v, t)
1361+
}
1362+
ty::ty_obj(_) {
1363+
// Call through the obj's own fields-drop glue first.
1364+
// Then free the body.
1365+
let ccx = bcx_ccx(bcx);
1366+
let llbox_ty = T_opaque_obj_ptr(*ccx);
1367+
let b = PointerCast(bcx, v, llbox_ty);
1368+
let body = GEP(bcx, b, [C_int(0), C_int(abi::box_rc_field_body)]);
1369+
let tydescptr =
1370+
GEP(bcx, body, [C_int(0), C_int(abi::obj_body_elt_tydesc)]);
1371+
let tydesc = Load(bcx, tydescptr);
1372+
let ti = none;
1373+
call_tydesc_glue_full(bcx, body, tydesc,
1374+
abi::tydesc_field_drop_glue, ti);
1375+
if !bcx_ccx(bcx).sess.get_opts().do_gc {
1376+
trans_non_gc_free(bcx, b)
1377+
} else { bcx }
1378+
}
1379+
ty::ty_fn(_, _, _, _, _) {
1380+
// Call through the closure's own fields-drop glue first.
1381+
// Then free the body.
1382+
v = PointerCast(bcx, v, T_opaque_closure_ptr(*bcx_ccx(bcx)));
1383+
let body = GEP(bcx, v, [C_int(0), C_int(abi::box_rc_field_body)]);
1384+
let bindings =
1385+
GEP(bcx, body, [C_int(0), C_int(abi::closure_elt_bindings)]);
1386+
let tydescptr =
1387+
GEP(bcx, body, [C_int(0), C_int(abi::closure_elt_tydesc)]);
1388+
let ti = none;
1389+
call_tydesc_glue_full(bcx, bindings, Load(bcx, tydescptr),
1390+
abi::tydesc_field_drop_glue, ti);
1391+
if !bcx_ccx(bcx).sess.get_opts().do_gc {
1392+
trans_non_gc_free(bcx, v)
1393+
} else { bcx }
1394+
}
1395+
_ { bcx }
1396+
};
13941397
build_return(bcx);
13951398
}
13961399

@@ -1401,21 +1404,19 @@ fn make_drop_glue(bcx: @block_ctxt, v0: ValueRef, t: ty::t) {
14011404
alt ty::struct(ccx.tcx, t) {
14021405
ty::ty_vec(_) { tvec::make_drop_glue(bcx, v0, t) }
14031406
ty::ty_str. { tvec::make_drop_glue(bcx, v0, t) }
1404-
ty::ty_box(_) { decr_refcnt_maybe_free(bcx, v0, v0, t) }
1405-
ty::ty_uniq(_) {
1406-
free_ty(bcx, v0, t)
1407-
}
1407+
ty::ty_box(_) { decr_refcnt_maybe_free(bcx, Load(bcx, v0), t) }
1408+
ty::ty_uniq(_) { free_ty(bcx, Load(bcx, v0), t) }
14081409
ty::ty_obj(_) {
14091410
let box_cell =
14101411
GEP(bcx, v0, [C_int(0), C_int(abi::obj_field_box)]);
1411-
decr_refcnt_maybe_free(bcx, box_cell, v0, t)
1412+
decr_refcnt_maybe_free(bcx, Load(bcx, box_cell), t)
14121413
}
14131414
ty::ty_res(did, inner, tps) {
14141415
trans_res_drop(bcx, v0, did, inner, tps)
14151416
}
14161417
ty::ty_fn(_, _, _, _, _) {
14171418
let box_cell = GEP(bcx, v0, [C_int(0), C_int(abi::fn_field_box)]);
1418-
decr_refcnt_maybe_free(bcx, box_cell, v0, t)
1419+
decr_refcnt_maybe_free(bcx, Load(bcx, box_cell), t)
14191420
}
14201421
_ {
14211422
if ty::type_has_pointers(ccx.tcx, t) &&
@@ -1470,13 +1471,12 @@ fn trans_res_drop(cx: @block_ctxt, rs: ValueRef, did: ast::def_id,
14701471
ret next_cx;
14711472
}
14721473

1473-
fn decr_refcnt_maybe_free(cx: @block_ctxt, box_ptr_alias: ValueRef,
1474-
full_alias: ValueRef, t: ty::t) -> @block_ctxt {
1474+
fn decr_refcnt_maybe_free(cx: @block_ctxt, box_ptr: ValueRef, t: ty::t)
1475+
-> @block_ctxt {
14751476
let ccx = bcx_ccx(cx);
14761477
let rc_adj_cx = new_sub_block_ctxt(cx, "rc--");
14771478
let free_cx = new_sub_block_ctxt(cx, "free");
14781479
let next_cx = new_sub_block_ctxt(cx, "next");
1479-
let box_ptr = Load(cx, box_ptr_alias);
14801480
let llbox_ty = T_opaque_obj_ptr(*ccx);
14811481
box_ptr = PointerCast(cx, box_ptr, llbox_ty);
14821482
let null_test = IsNull(cx, box_ptr);
@@ -1488,7 +1488,7 @@ fn decr_refcnt_maybe_free(cx: @block_ctxt, box_ptr_alias: ValueRef,
14881488
Store(rc_adj_cx, rc, rc_ptr);
14891489
let zero_test = ICmp(rc_adj_cx, lib::llvm::LLVMIntEQ, C_int(0), rc);
14901490
CondBr(rc_adj_cx, zero_test, free_cx.llbb, next_cx.llbb);
1491-
let free_cx = free_ty(free_cx, full_alias, t);
1491+
let free_cx = free_ty(free_cx, box_ptr, t);
14921492
Br(free_cx, next_cx.llbb);
14931493
ret next_cx;
14941494
}

src/comp/middle/trans_uniq.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,22 +53,19 @@ fn alloc_uniq(cx: @block_ctxt, uniq_ty: ty::t)
5353
ret rslt(bcx, llptr);
5454
}
5555

56-
fn make_free_glue(cx: @block_ctxt, v: ValueRef, t: ty::t)
56+
fn make_free_glue(cx: @block_ctxt, vptr: ValueRef, t: ty::t)
5757
: type_is_unique_box(cx, t) -> @block_ctxt {
5858

5959
let bcx = cx;
6060
let free_cx = new_sub_block_ctxt(bcx, "uniq_free");
6161
let next_cx = new_sub_block_ctxt(bcx, "uniq_free_next");
62-
let vptr = Load(bcx, v);
6362
let null_test = IsNull(bcx, vptr);
6463
CondBr(bcx, null_test, next_cx.llbb, free_cx.llbb);
6564

6665
let bcx = free_cx;
6766
let bcx = drop_ty(bcx, vptr, content_ty(cx, t));
6867
let bcx = trans_shared_free(bcx, vptr);
69-
Store(bcx, C_null(val_ty(vptr)), v);
7068
Br(bcx, next_cx.llbb);
71-
7269
next_cx
7370
}
7471

0 commit comments

Comments
 (0)