fixes for Box<[T]>

The pointer in the slice must not be null, because enum representations
make that assumption. The `exchange_malloc` function returns a non-null
sentinel for the zero size case, and it must not be passed to the
`exchange_free` lang item.

Since the length is always equal to the true capacity, a branch on the
length is enough for most types. Slices of zero size types are
statically special cased to never attempt deallocation. This is the same
implementation as `Vec<T>`.

Closes #14395
This commit is contained in:
Daniel Micay 2014-09-08 19:27:06 -04:00
parent b625d43f8f
commit 9639cafd36
4 changed files with 24 additions and 37 deletions

View File

@ -12,7 +12,6 @@
// FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias`
// and `nonnull`
use core::ptr::RawPtr;
#[cfg(not(test))] use core::raw;
#[cfg(stage0, not(test))] use util;
@ -70,11 +69,6 @@ pub unsafe fn reallocate_inplace(ptr: *mut u8, size: uint, align: uint,
/// the value returned by `usable_size` for the requested size.
#[inline]
pub unsafe fn deallocate(ptr: *mut u8, size: uint, align: uint) {
// FIXME(14395) This is only required for DST ~[T], it should be removed once
// we fix that representation to not use null pointers.
if ptr.is_null() {
return;
}
imp::deallocate(ptr, size, align)
}

View File

@ -412,29 +412,11 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let vec_ty = ty::mk_uniq(tcx, ty::mk_vec(tcx, unit_ty, None));
let scratch = rvalue_scratch_datum(bcx, vec_ty, "__unsize_unique");
if len == 0 {
Store(bcx,
C_null(type_of::type_of(bcx.ccx(), unit_ty).ptr_to()),
get_dataptr(bcx, scratch.val));
} else {
// Box<[(), ..n]> will not allocate, but ~[()] expects an
// allocation of n bytes, so we must allocate here (yuck).
let llty = type_of::type_of(bcx.ccx(), unit_ty);
if llsize_of_alloc(bcx.ccx(), llty) == 0 {
let ptr_unit_ty = type_of::type_of(bcx.ccx(), unit_ty).ptr_to();
let align = C_uint(bcx.ccx(), 8);
let alloc_result = malloc_raw_dyn(bcx, ptr_unit_ty, vec_ty, ll_len, align);
bcx = alloc_result.bcx;
let base = get_dataptr(bcx, scratch.val);
Store(bcx, alloc_result.val, base);
} else {
let base = get_dataptr(bcx, scratch.val);
let base = PointerCast(bcx,
base,
type_of::type_of(bcx.ccx(), datum_ty).ptr_to());
bcx = lval.store_to(bcx, base);
}
}
let base = get_dataptr(bcx, scratch.val);
let base = PointerCast(bcx,
base,
type_of::type_of(bcx.ccx(), datum_ty).ptr_to());
bcx = lval.store_to(bcx, base);
Store(bcx, ll_len, get_len(bcx, scratch.val));
DatumBlock::new(bcx, scratch.to_expr_datum())

View File

@ -72,14 +72,19 @@ pub fn make_drop_glue_unboxed<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
};
if should_deallocate {
let not_null = IsNotNull(bcx, dataptr);
with_cond(bcx, not_null, |bcx| {
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)
})
let llty = type_of::type_of(ccx, unit_ty);
let unit_size = llsize_of_alloc(ccx, llty);
if unit_size != 0 {
let len = get_len(bcx, vptr);
let not_empty = ICmp(bcx, llvm::IntNE, len, C_uint(ccx, 0));
with_cond(bcx, not_empty, |bcx| {
let llalign = C_uint(ccx, machine::llalign_of_min(ccx, llty) as uint);
let size = Mul(bcx, C_uint(ccx, unit_size as uint), len);
glue::trans_exchange_free_dyn(bcx, dataptr, size, llalign)
})
} else {
bcx
}
} else {
bcx
}

View File

@ -11,6 +11,12 @@
pub fn main() {
assert!(Some(box() ()).is_some());
let xs: Box<[()]> = box [];
assert!(Some(xs).is_some());
struct Foo;
assert!(Some(box Foo).is_some());
let ys: Box<[Foo]> = box [];
assert!(Some(ys).is_some());
}