Skip to content

Commit d1bd139

Browse files
committed
fix sized deallocation for Box<[T]>
1 parent 5aa2da0 commit d1bd139

File tree

3 files changed

+77
-19
lines changed

3 files changed

+77
-19
lines changed

src/librustc/middle/trans/cleanup.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,27 @@ impl<'a> CleanupMethods<'a> for FunctionContext<'a> {
340340
self.schedule_clean(cleanup_scope, drop as CleanupObj);
341341
}
342342

343+
fn schedule_free_slice(&self,
344+
cleanup_scope: ScopeId,
345+
val: ValueRef,
346+
size: ValueRef,
347+
align: ValueRef,
348+
heap: Heap) {
349+
/*!
350+
* Schedules a call to `free(val)`. Note that this is a shallow
351+
* operation.
352+
*/
353+
354+
let drop = box FreeSlice { ptr: val, size: size, align: align, heap: heap };
355+
356+
debug!("schedule_free_slice({:?}, val={}, heap={:?})",
357+
cleanup_scope,
358+
self.ccx.tn().val_to_string(val),
359+
heap);
360+
361+
self.schedule_clean(cleanup_scope, drop as CleanupObj);
362+
}
363+
343364
fn schedule_clean(&self,
344365
cleanup_scope: ScopeId,
345366
cleanup: CleanupObj) {
@@ -926,6 +947,34 @@ impl Cleanup for FreeValue {
926947
}
927948
}
928949

950+
pub struct FreeSlice {
951+
ptr: ValueRef,
952+
size: ValueRef,
953+
align: ValueRef,
954+
heap: Heap,
955+
}
956+
957+
impl Cleanup for FreeSlice {
958+
fn must_unwind(&self) -> bool {
959+
true
960+
}
961+
962+
fn clean_on_unwind(&self) -> bool {
963+
true
964+
}
965+
966+
fn trans<'a>(&self, bcx: &'a Block<'a>) -> &'a Block<'a> {
967+
match self.heap {
968+
HeapManaged => {
969+
glue::trans_free(bcx, self.ptr)
970+
}
971+
HeapExchange => {
972+
glue::trans_exchange_free_dyn(bcx, self.ptr, self.size, self.align)
973+
}
974+
}
975+
}
976+
}
977+
929978
pub struct LifetimeEnd {
930979
ptr: ValueRef,
931980
}
@@ -1020,6 +1069,12 @@ pub trait CleanupMethods<'a> {
10201069
val: ValueRef,
10211070
heap: Heap,
10221071
content_ty: ty::t);
1072+
fn schedule_free_slice(&self,
1073+
cleanup_scope: ScopeId,
1074+
val: ValueRef,
1075+
size: ValueRef,
1076+
align: ValueRef,
1077+
heap: Heap);
10231078
fn schedule_clean(&self,
10241079
cleanup_scope: ScopeId,
10251080
cleanup: CleanupObj);

src/librustc/middle/trans/glue.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ pub fn trans_free<'a>(cx: &'a Block<'a>, v: ValueRef) -> &'a Block<'a> {
5353
Some(expr::Ignore)).bcx
5454
}
5555

56-
fn trans_exchange_free_internal<'a>(cx: &'a Block<'a>, v: ValueRef, size: ValueRef,
56+
pub fn trans_exchange_free_dyn<'a>(cx: &'a Block<'a>, v: ValueRef, size: ValueRef,
5757
align: ValueRef) -> &'a Block<'a> {
5858
let _icx = push_ctxt("trans_exchange_free");
5959
let ccx = cx.ccx();
@@ -65,10 +65,8 @@ fn trans_exchange_free_internal<'a>(cx: &'a Block<'a>, v: ValueRef, size: ValueR
6565

6666
pub fn trans_exchange_free<'a>(cx: &'a Block<'a>, v: ValueRef, size: u64,
6767
align: u64) -> &'a Block<'a> {
68-
trans_exchange_free_internal(cx,
69-
v,
70-
C_uint(cx.ccx(), size as uint),
71-
C_uint(cx.ccx(), align as uint))
68+
trans_exchange_free_dyn(cx, v, C_uint(cx.ccx(), size as uint),
69+
C_uint(cx.ccx(), align as uint))
7270
}
7371

7472
pub fn trans_exchange_free_ty<'a>(bcx: &'a Block<'a>, ptr: ValueRef,
@@ -467,7 +465,7 @@ fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) -> &'a Block<'
467465
let info = GEPi(bcx, v0, [0, abi::slice_elt_len]);
468466
let info = Load(bcx, info);
469467
let (llsize, llalign) = size_and_align_of_dst(bcx, content_ty, info);
470-
trans_exchange_free_internal(bcx, llbox, llsize, llalign)
468+
trans_exchange_free_dyn(bcx, llbox, llsize, llalign)
471469
})
472470
}
473471
_ => {

src/librustc/middle/trans/tvec.rs

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use middle::trans::datum::*;
2525
use middle::trans::expr::{Dest, Ignore, SaveIn};
2626
use middle::trans::expr;
2727
use middle::trans::glue;
28+
use middle::trans::machine;
2829
use middle::trans::machine::{nonzero_llsize_of, llsize_of_alloc};
2930
use middle::trans::type_::Type;
3031
use middle::trans::type_of;
@@ -59,6 +60,7 @@ pub fn make_drop_glue_unboxed<'a>(
5960
-> &'a Block<'a> {
6061
let not_null = IsNotNull(bcx, vptr);
6162
with_cond(bcx, not_null, |bcx| {
63+
let ccx = bcx.ccx();
6264
let tcx = bcx.tcx();
6365
let _icx = push_ctxt("tvec::make_drop_glue_unboxed");
6466

@@ -73,8 +75,11 @@ pub fn make_drop_glue_unboxed<'a>(
7375
if should_deallocate {
7476
let not_null = IsNotNull(bcx, dataptr);
7577
with_cond(bcx, not_null, |bcx| {
76-
// FIXME: #13994: the old `Box<[T]>` will not support sized deallocation
77-
glue::trans_exchange_free(bcx, dataptr, 0, 8)
78+
let llty = type_of::type_of(ccx, unit_ty);
79+
let llsize = machine::llsize_of(ccx, llty);
80+
let llalign = C_uint(ccx, machine::llalign_of_min(ccx, llty) as uint);
81+
let size = Mul(bcx, llsize, get_len(bcx, vptr));
82+
glue::trans_exchange_free_dyn(bcx, dataptr, size, llalign)
7883
})
7984
} else {
8085
bcx
@@ -281,15 +286,16 @@ pub fn trans_uniq_vec<'a>(bcx: &'a Block<'a>,
281286
debug!(" vt={}, count={:?}", vt.to_string(ccx), count);
282287
let vec_ty = node_id_type(bcx, uniq_expr.id);
283288

284-
let unit_sz = nonzero_llsize_of(ccx, type_of::type_of(ccx, vt.unit_ty));
289+
let llty = type_of::type_of(ccx, vt.unit_ty);
290+
let unit_sz = nonzero_llsize_of(ccx, llty);
285291
let llcount = if count < 4u {
286292
C_int(ccx, 4)
287293
} else {
288294
C_uint(ccx, count)
289295
};
290296
let alloc = Mul(bcx, llcount, unit_sz);
291-
let llty_ptr = type_of::type_of(ccx, vt.unit_ty).ptr_to();
292-
let align = C_uint(ccx, 8);
297+
let llty_ptr = llty.ptr_to();
298+
let align = C_uint(ccx, machine::llalign_of_min(ccx, llty) as uint);
293299
let Result { bcx: bcx, val: dataptr } = malloc_raw_dyn(bcx,
294300
llty_ptr,
295301
vec_ty,
@@ -299,16 +305,15 @@ pub fn trans_uniq_vec<'a>(bcx: &'a Block<'a>,
299305
// Create a temporary scope lest execution should fail while
300306
// constructing the vector.
301307
let temp_scope = fcx.push_custom_cleanup_scope();
302-
// FIXME: #13994: the old `Box<[T]> will not support sized deallocation,
303-
// this is a placeholder
304-
fcx.schedule_free_value(cleanup::CustomScope(temp_scope),
305-
dataptr, cleanup::HeapExchange, vt.unit_ty);
306308

307-
debug!(" alloc_uniq_vec() returned dataptr={}, len={}",
308-
bcx.val_to_string(dataptr), count);
309+
fcx.schedule_free_slice(cleanup::CustomScope(temp_scope),
310+
dataptr, alloc, align, cleanup::HeapExchange);
309311

310-
let bcx = write_content(bcx, &vt, uniq_expr,
311-
content_expr, SaveIn(dataptr));
312+
debug!(" alloc_uniq_vec() returned dataptr={}, len={}",
313+
bcx.val_to_string(dataptr), count);
314+
315+
let bcx = write_content(bcx, &vt, uniq_expr,
316+
content_expr, SaveIn(dataptr));
312317

313318
fcx.pop_custom_cleanup_scope(temp_scope);
314319

0 commit comments

Comments
 (0)