Skip to content

Commit fb9ab95

Browse files
pcwaltonmarijnh
authored andcommitted
rustc: When revoking a cleanup of a unique pointer, zero it out so that the GC won't try to visit it
1 parent 7a0c975 commit fb9ab95

File tree

2 files changed

+25
-15
lines changed

2 files changed

+25
-15
lines changed

src/comp/middle/trans.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2179,18 +2179,15 @@ fn move_val(cx: @block_ctxt, action: copy_action, dst: ValueRef,
21792179
if src.is_mem { ret zero_alloca(cx, src.res.val, t).bcx; }
21802180

21812181
// If we're here, it must be a temporary.
2182-
revoke_clean(cx, src_val);
2183-
ret cx;
2182+
ret revoke_clean(cx, src_val, t);
21842183
} else if ty::type_is_unique(tcx, t) ||
21852184
type_is_structural_or_param(tcx, t) {
21862185
if action == DROP_EXISTING { cx = drop_ty(cx, dst, t); }
21872186
cx = memmove_ty(cx, dst, src_val, t).bcx;
2188-
if src.is_mem {
2189-
ret zero_alloca(cx, src_val, t).bcx;
2190-
} else { // Temporary value
2191-
revoke_clean(cx, src_val);
2192-
ret cx;
2193-
}
2187+
if src.is_mem { ret zero_alloca(cx, src_val, t).bcx; }
2188+
2189+
// If we're here, it must be a temporary.
2190+
ret revoke_clean(cx, src_val, t);
21942191
}
21952192
bcx_ccx(cx).sess.bug("unexpected type in trans::move_val: " +
21962193
ty_to_str(tcx, t));
@@ -3620,7 +3617,8 @@ fn trans_bind_1(cx: &@block_ctxt, f: &@ast::expr, f_res: &lval_result,
36203617

36213618
fn trans_arg_expr(cx: &@block_ctxt, arg: &ty::arg, lldestty0: TypeRef,
36223619
to_zero: &mutable [{v: ValueRef, t: ty::t}],
3623-
to_revoke: &mutable [ValueRef], e: &@ast::expr) -> result {
3620+
to_revoke: &mutable [{v: ValueRef, t: ty::t}],
3621+
e: &@ast::expr) -> result {
36243622
let ccx = bcx_ccx(cx);
36253623
let e_ty = ty::expr_ty(ccx.tcx, e);
36263624
let is_bot = ty::type_is_bot(ccx.tcx, e_ty);
@@ -3672,7 +3670,9 @@ fn trans_arg_expr(cx: &@block_ctxt, arg: &ty::arg, lldestty0: TypeRef,
36723670
// Use actual ty, not declared ty -- anything else doesn't make
36733671
// sense if declared ty is a ty param
36743672
to_zero += [{v: lv.res.val, t: e_ty}];
3675-
} else { to_revoke += [lv.res.val]; }
3673+
} else {
3674+
to_revoke += [{v: lv.res.val, t: e_ty}];
3675+
}
36763676
}
36773677
ret rslt(bcx, val);
36783678
}
@@ -3691,7 +3691,7 @@ fn trans_args(cx: &@block_ctxt, llenv: ValueRef,
36913691
args: [ValueRef],
36923692
retslot: ValueRef,
36933693
to_zero: [{v: ValueRef, t: ty::t}],
3694-
to_revoke: [ValueRef]} {
3694+
to_revoke: [{v: ValueRef, t: ty::t}]} {
36953695

36963696
let args: [ty::arg] = ty::ty_fn_args(bcx_tcx(cx), fn_ty);
36973697
let llargs: [ValueRef] = [];
@@ -3869,9 +3869,11 @@ fn trans_call(in_cx: &@block_ctxt, f: &@ast::expr,
38693869

38703870
// Forget about anything we moved out.
38713871
for {v: v, t: t}: {v: ValueRef, t: ty::t} in args_res.to_zero {
3872-
zero_alloca(bcx, v, t)
3872+
bcx = zero_alloca(bcx, v, t).bcx;
3873+
}
3874+
for {v: v, t: t} in args_res.to_revoke {
3875+
bcx = revoke_clean(bcx, v, t);
38733876
}
3874-
for v: ValueRef in args_res.to_revoke { revoke_clean(bcx, v) }
38753877
bcx = trans_block_cleanups(bcx, cx);
38763878
let next_cx = new_sub_block_ctxt(in_cx, "next");
38773879
Br(bcx, next_cx.llbb);

src/comp/middle/trans_common.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,13 @@ fn add_clean_temp(cx: &@block_ctxt, val: ValueRef, ty: ty::t) {
314314
// to a system where we can also cancel the cleanup on local variables, but
315315
// this will be more involved. For now, we simply zero out the local, and the
316316
// drop glue checks whether it is zero.
317-
fn revoke_clean(cx: &@block_ctxt, val: ValueRef) {
317+
fn revoke_clean(cx: &@block_ctxt, val: ValueRef, t: ty::t) -> @block_ctxt {
318+
if ty::type_is_unique(bcx_tcx(cx), t) {
319+
// Just zero out the allocation. This ensures that the GC won't try to
320+
// traverse dangling pointers.
321+
ret trans::zero_alloca(cx, val, t).bcx;
322+
}
323+
318324
let sc_cx = find_scope_cx(cx);
319325
let found = -1;
320326
let i = 0;
@@ -329,12 +335,14 @@ fn revoke_clean(cx: &@block_ctxt, val: ValueRef) {
329335
}
330336
// The value does not have a cleanup associated with it. Might be a
331337
// constant or some immediate value.
332-
if found == -1 { ret; }
338+
if found == -1 { ret cx; }
333339
// We found the cleanup and remove it
334340
sc_cx.cleanups =
335341
std::vec::slice(sc_cx.cleanups, 0u, found as uint) +
336342
std::vec::slice(sc_cx.cleanups, (found as uint) + 1u,
337343
std::vec::len(sc_cx.cleanups));
344+
345+
ret cx;
338346
}
339347

340348
fn get_res_dtor(ccx: &@crate_ctxt, sp: &span, did: &ast::def_id,

0 commit comments

Comments
 (0)