From d1bd139251be4b1c51ace8d180757ca7b59e675a Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Fri, 5 Sep 2014 03:39:15 -0400 Subject: [PATCH] fix sized deallocation for Box<[T]> --- src/librustc/middle/trans/cleanup.rs | 55 ++++++++++++++++++++++++++++ src/librustc/middle/trans/glue.rs | 10 ++--- src/librustc/middle/trans/tvec.rs | 31 +++++++++------- 3 files changed, 77 insertions(+), 19 deletions(-) diff --git a/src/librustc/middle/trans/cleanup.rs b/src/librustc/middle/trans/cleanup.rs index 15d296ac72371..cdfb8e48a460e 100644 --- a/src/librustc/middle/trans/cleanup.rs +++ b/src/librustc/middle/trans/cleanup.rs @@ -340,6 +340,27 @@ impl<'a> CleanupMethods<'a> for FunctionContext<'a> { self.schedule_clean(cleanup_scope, drop as CleanupObj); } + fn schedule_free_slice(&self, + cleanup_scope: ScopeId, + val: ValueRef, + size: ValueRef, + align: ValueRef, + heap: Heap) { + /*! + * Schedules a call to `free(val)`. Note that this is a shallow + * operation. + */ + + let drop = box FreeSlice { ptr: val, size: size, align: align, heap: heap }; + + debug!("schedule_free_slice({:?}, val={}, heap={:?})", + cleanup_scope, + self.ccx.tn().val_to_string(val), + heap); + + self.schedule_clean(cleanup_scope, drop as CleanupObj); + } + fn schedule_clean(&self, cleanup_scope: ScopeId, cleanup: CleanupObj) { @@ -926,6 +947,34 @@ impl Cleanup for FreeValue { } } +pub struct FreeSlice { + ptr: ValueRef, + size: ValueRef, + align: ValueRef, + heap: Heap, +} + +impl Cleanup for FreeSlice { + fn must_unwind(&self) -> bool { + true + } + + fn clean_on_unwind(&self) -> bool { + true + } + + fn trans<'a>(&self, bcx: &'a Block<'a>) -> &'a Block<'a> { + match self.heap { + HeapManaged => { + glue::trans_free(bcx, self.ptr) + } + HeapExchange => { + glue::trans_exchange_free_dyn(bcx, self.ptr, self.size, self.align) + } + } + } +} + pub struct LifetimeEnd { ptr: ValueRef, } @@ -1020,6 +1069,12 @@ pub trait CleanupMethods<'a> { val: ValueRef, heap: Heap, content_ty: ty::t); + fn schedule_free_slice(&self, + cleanup_scope: ScopeId, + val: ValueRef, + size: ValueRef, + align: ValueRef, + heap: Heap); fn schedule_clean(&self, cleanup_scope: ScopeId, cleanup: CleanupObj); diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index ce6bdc8545463..09d28f03392cf 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -53,7 +53,7 @@ pub fn trans_free<'a>(cx: &'a Block<'a>, v: ValueRef) -> &'a Block<'a> { Some(expr::Ignore)).bcx } -fn trans_exchange_free_internal<'a>(cx: &'a Block<'a>, v: ValueRef, size: ValueRef, +pub fn trans_exchange_free_dyn<'a>(cx: &'a Block<'a>, v: ValueRef, size: ValueRef, align: ValueRef) -> &'a Block<'a> { let _icx = push_ctxt("trans_exchange_free"); let ccx = cx.ccx(); @@ -65,10 +65,8 @@ fn trans_exchange_free_internal<'a>(cx: &'a Block<'a>, v: ValueRef, size: ValueR pub fn trans_exchange_free<'a>(cx: &'a Block<'a>, v: ValueRef, size: u64, align: u64) -> &'a Block<'a> { - trans_exchange_free_internal(cx, - v, - C_uint(cx.ccx(), size as uint), - C_uint(cx.ccx(), align as uint)) + trans_exchange_free_dyn(cx, v, C_uint(cx.ccx(), size as uint), + C_uint(cx.ccx(), align as uint)) } 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<' let info = GEPi(bcx, v0, [0, abi::slice_elt_len]); let info = Load(bcx, info); let (llsize, llalign) = size_and_align_of_dst(bcx, content_ty, info); - trans_exchange_free_internal(bcx, llbox, llsize, llalign) + trans_exchange_free_dyn(bcx, llbox, llsize, llalign) }) } _ => { diff --git a/src/librustc/middle/trans/tvec.rs b/src/librustc/middle/trans/tvec.rs index 3701d83d6a122..285105d22f675 100644 --- a/src/librustc/middle/trans/tvec.rs +++ b/src/librustc/middle/trans/tvec.rs @@ -25,6 +25,7 @@ use middle::trans::datum::*; use middle::trans::expr::{Dest, Ignore, SaveIn}; use middle::trans::expr; use middle::trans::glue; +use middle::trans::machine; use middle::trans::machine::{nonzero_llsize_of, llsize_of_alloc}; use middle::trans::type_::Type; use middle::trans::type_of; @@ -59,6 +60,7 @@ pub fn make_drop_glue_unboxed<'a>( -> &'a Block<'a> { let not_null = IsNotNull(bcx, vptr); with_cond(bcx, not_null, |bcx| { + let ccx = bcx.ccx(); let tcx = bcx.tcx(); let _icx = push_ctxt("tvec::make_drop_glue_unboxed"); @@ -73,8 +75,11 @@ pub fn make_drop_glue_unboxed<'a>( if should_deallocate { let not_null = IsNotNull(bcx, dataptr); with_cond(bcx, not_null, |bcx| { - // FIXME: #13994: the old `Box<[T]>` will not support sized deallocation - glue::trans_exchange_free(bcx, dataptr, 0, 8) + let llty = type_of::type_of(ccx, unit_ty); + let llsize = machine::llsize_of(ccx, llty); + let llalign = C_uint(ccx, machine::llalign_of_min(ccx, llty) as uint); + let size = Mul(bcx, llsize, get_len(bcx, vptr)); + glue::trans_exchange_free_dyn(bcx, dataptr, size, llalign) }) } else { bcx @@ -281,15 +286,16 @@ pub fn trans_uniq_vec<'a>(bcx: &'a Block<'a>, debug!(" vt={}, count={:?}", vt.to_string(ccx), count); let vec_ty = node_id_type(bcx, uniq_expr.id); - let unit_sz = nonzero_llsize_of(ccx, type_of::type_of(ccx, vt.unit_ty)); + let llty = type_of::type_of(ccx, vt.unit_ty); + let unit_sz = nonzero_llsize_of(ccx, llty); let llcount = if count < 4u { C_int(ccx, 4) } else { C_uint(ccx, count) }; let alloc = Mul(bcx, llcount, unit_sz); - let llty_ptr = type_of::type_of(ccx, vt.unit_ty).ptr_to(); - let align = C_uint(ccx, 8); + let llty_ptr = llty.ptr_to(); + let align = C_uint(ccx, machine::llalign_of_min(ccx, llty) as uint); let Result { bcx: bcx, val: dataptr } = malloc_raw_dyn(bcx, llty_ptr, vec_ty, @@ -299,16 +305,15 @@ pub fn trans_uniq_vec<'a>(bcx: &'a Block<'a>, // Create a temporary scope lest execution should fail while // constructing the vector. let temp_scope = fcx.push_custom_cleanup_scope(); - // FIXME: #13994: the old `Box<[T]> will not support sized deallocation, - // this is a placeholder - fcx.schedule_free_value(cleanup::CustomScope(temp_scope), - dataptr, cleanup::HeapExchange, vt.unit_ty); - debug!(" alloc_uniq_vec() returned dataptr={}, len={}", - bcx.val_to_string(dataptr), count); + fcx.schedule_free_slice(cleanup::CustomScope(temp_scope), + dataptr, alloc, align, cleanup::HeapExchange); - let bcx = write_content(bcx, &vt, uniq_expr, - content_expr, SaveIn(dataptr)); + debug!(" alloc_uniq_vec() returned dataptr={}, len={}", + bcx.val_to_string(dataptr), count); + + let bcx = write_content(bcx, &vt, uniq_expr, + content_expr, SaveIn(dataptr)); fcx.pop_custom_cleanup_scope(temp_scope);