diff options
| -rw-r--r-- | src/liballoc/heap.rs | 26 | ||||
| -rw-r--r-- | src/libarena/lib.rs | 5 | ||||
| -rw-r--r-- | src/libcore/should_not_exist.rs | 10 | ||||
| -rw-r--r-- | src/librustc/middle/trans/cleanup.rs | 11 | ||||
| -rw-r--r-- | src/librustc/middle/trans/expr.rs | 9 | ||||
| -rw-r--r-- | src/librustc/middle/trans/glue.rs | 40 | ||||
| -rw-r--r-- | src/librustc/middle/trans/tvec.rs | 5 | ||||
| -rw-r--r-- | src/libstd/slice.rs | 6 |
8 files changed, 67 insertions, 45 deletions
diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs index 69cd82a981a..631b72cb897 100644 --- a/src/liballoc/heap.rs +++ b/src/liballoc/heap.rs @@ -9,7 +9,7 @@ // except according to those terms. // FIXME: #13994: port to the sized deallocation API when available -// FIXME: #13996: need a way to mark the `allocate` and `reallocate` return values as `noalias` +// FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias` and `nonnull` use core::intrinsics::{abort, cttz32}; use core::option::{None, Option}; @@ -119,14 +119,8 @@ pub fn stats_print() { /// The allocator for unique pointers. #[cfg(not(test))] #[lang="exchange_malloc"] -#[inline(always)] -pub unsafe fn exchange_malloc_(size: uint, align: uint) -> *mut u8 { - exchange_malloc(size, align) -} - -/// The allocator for unique pointers. #[inline] -pub unsafe fn exchange_malloc(size: uint, align: uint) -> *mut u8 { +unsafe fn exchange_malloc(size: uint, align: uint) -> *mut u8 { // The compiler never calls `exchange_free` on ~ZeroSizeType, so zero-size // allocations can point to this `static`. It would be incorrect to use a null // pointer, due to enums assuming types like unique pointers are never null. @@ -139,14 +133,20 @@ pub unsafe fn exchange_malloc(size: uint, align: uint) -> *mut u8 { } } -#[cfg(not(test))] +#[cfg(not(test), stage0)] #[lang="exchange_free"] #[inline] -// FIXME: #13994 (rustc should pass align and size here) unsafe fn exchange_free(ptr: *mut u8) { deallocate(ptr, 0, 8); } +#[cfg(not(test), not(stage0))] +#[lang="exchange_free"] +#[inline] +unsafe fn exchange_free(ptr: *mut u8, size: uint, align: uint) { + deallocate(ptr, size, align); +} + // FIXME: #7496 #[cfg(not(test))] #[lang="closure_exchange_malloc"] @@ -167,8 +167,8 @@ unsafe fn closure_exchange_malloc(drop_glue: fn(*mut u8), size: uint, align: uin #[doc(hidden)] #[deprecated] #[cfg(not(test))] -pub unsafe extern "C" fn rust_malloc(size: uint, align: uint) -> *mut u8 { - exchange_malloc(size, align) +pub unsafe extern "C" fn rust_allocate(size: uint, align: uint) -> *mut u8 { + allocate(size, align) } // hack for libcore @@ -176,7 +176,7 @@ pub unsafe extern "C" fn rust_malloc(size: uint, align: uint) -> *mut u8 { #[doc(hidden)] #[deprecated] #[cfg(not(test))] -pub unsafe extern "C" fn rust_free(ptr: *mut u8, size: uint, align: uint) { +pub unsafe extern "C" fn rust_deallocate(ptr: *mut u8, size: uint, align: uint) { deallocate(ptr, size, align) } diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 3c93cdac8bb..2f654bdd300 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -38,7 +38,7 @@ use std::mem; use std::num; use std::ptr::read; use std::rc::Rc; -use std::rt::heap::exchange_malloc; +use std::rt::heap::allocate; // The way arena uses arrays is really deeply awful. The arrays are // allocated, and have capacities reserved, but the fill for the array @@ -358,8 +358,7 @@ impl<T> TypedArenaChunk<T> { size = size.checked_add(&elems_size).unwrap(); let mut chunk = unsafe { - let chunk = exchange_malloc(size, - mem::min_align_of::<TypedArenaChunk<T>>()); + let chunk = allocate(size, mem::min_align_of::<TypedArenaChunk<T>>()); let mut chunk: Box<TypedArenaChunk<T>> = mem::transmute(chunk); mem::overwrite(&mut chunk.next, next); chunk diff --git a/src/libcore/should_not_exist.rs b/src/libcore/should_not_exist.rs index ccca52c573d..2046017869d 100644 --- a/src/libcore/should_not_exist.rs +++ b/src/libcore/should_not_exist.rs @@ -44,14 +44,14 @@ use str::StrSlice; #[allow(ctypes)] extern { - fn rust_malloc(size: uint, align: uint) -> *u8; - fn rust_free(ptr: *u8, size: uint, align: uint); + fn rust_allocate(size: uint, align: uint) -> *u8; + fn rust_deallocate(ptr: *u8, size: uint, align: uint); } unsafe fn alloc(cap: uint) -> *mut Vec<()> { let cap = cap.checked_add(&mem::size_of::<Vec<()>>()).unwrap(); // this should use the real alignment, but the new representation will take care of that - let ret = rust_malloc(cap, 8) as *mut Vec<()>; + let ret = rust_allocate(cap, 8) as *mut Vec<()>; if ret.is_null() { intrinsics::abort(); } @@ -119,7 +119,7 @@ impl FromIterator<char> for ~str { &(*ptr).data, len); // FIXME: #13994: port to the sized deallocation API when available - rust_free(ptr as *u8, 0, 8); + rust_deallocate(ptr as *u8, 0, 8); mem::forget(ret); ret = mem::transmute(ptr2); ptr = ptr2; @@ -191,7 +191,7 @@ impl<A: Clone> Clone for ~[A] { for j in range(0, *i as int) { ptr::read(&*p.offset(j)); } - rust_free(ret as *u8, 0, 8); + rust_deallocate(ret as *u8, 0, 8); }); mem::transmute(ret) } diff --git a/src/librustc/middle/trans/cleanup.rs b/src/librustc/middle/trans/cleanup.rs index 87cde42e398..80ee555971d 100644 --- a/src/librustc/middle/trans/cleanup.rs +++ b/src/librustc/middle/trans/cleanup.rs @@ -278,13 +278,14 @@ impl<'a> CleanupMethods<'a> for FunctionContext<'a> { fn schedule_free_value(&self, cleanup_scope: ScopeId, val: ValueRef, - heap: Heap) { + heap: Heap, + content_ty: ty::t) { /*! * Schedules a call to `free(val)`. Note that this is a shallow * operation. */ - let drop = box FreeValue { ptr: val, heap: heap }; + let drop = box FreeValue { ptr: val, heap: heap, content_ty: content_ty }; debug!("schedule_free_value({:?}, val={}, heap={:?})", cleanup_scope, @@ -847,6 +848,7 @@ pub enum Heap { pub struct FreeValue { ptr: ValueRef, heap: Heap, + content_ty: ty::t } impl Cleanup for FreeValue { @@ -860,7 +862,7 @@ impl Cleanup for FreeValue { glue::trans_free(bcx, self.ptr) } HeapExchange => { - glue::trans_exchange_free(bcx, self.ptr) + glue::trans_exchange_free_ty(bcx, self.ptr, self.content_ty) } } } @@ -931,7 +933,8 @@ pub trait CleanupMethods<'a> { fn schedule_free_value(&self, cleanup_scope: ScopeId, val: ValueRef, - heap: Heap); + heap: Heap, + content_ty: ty::t); fn schedule_clean(&self, cleanup_scope: ScopeId, cleanup: Box<Cleanup>); diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index d3be50735be..bd25acad21d 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -1183,7 +1183,7 @@ fn trans_uniq_expr<'a>(bcx: &'a Block<'a>, } else { let custom_cleanup_scope = fcx.push_custom_cleanup_scope(); fcx.schedule_free_value(cleanup::CustomScope(custom_cleanup_scope), - val, cleanup::HeapExchange); + val, cleanup::HeapExchange, contents_ty); let bcx = trans_into(bcx, contents, SaveIn(val)); fcx.pop_custom_cleanup_scope(custom_cleanup_scope); bcx @@ -1205,7 +1205,7 @@ fn trans_managed_expr<'a>(bcx: &'a Block<'a>, let custom_cleanup_scope = fcx.push_custom_cleanup_scope(); fcx.schedule_free_value(cleanup::CustomScope(custom_cleanup_scope), - bx, cleanup::HeapManaged); + bx, cleanup::HeapManaged, contents_ty); let bcx = trans_into(bcx, contents, SaveIn(body)); fcx.pop_custom_cleanup_scope(custom_cleanup_scope); immediate_rvalue_bcx(bcx, bx, box_ty).to_expr_datumblock() @@ -1789,13 +1789,14 @@ fn deref_once<'a>(bcx: &'a Block<'a>, let scope = cleanup::temporary_scope(bcx.tcx(), expr.id); let ptr = Load(bcx, datum.val); if !type_is_zero_size(bcx.ccx(), content_ty) { - bcx.fcx.schedule_free_value(scope, ptr, cleanup::HeapExchange); + bcx.fcx.schedule_free_value(scope, ptr, cleanup::HeapExchange, content_ty); } } RvalueExpr(Rvalue { mode: ByValue }) => { let scope = cleanup::temporary_scope(bcx.tcx(), expr.id); if !type_is_zero_size(bcx.ccx(), content_ty) { - bcx.fcx.schedule_free_value(scope, datum.val, cleanup::HeapExchange); + bcx.fcx.schedule_free_value(scope, datum.val, cleanup::HeapExchange, + content_ty); } } LvalueExpr => { } diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index 8869bd010b2..b1b684ca371 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -50,15 +50,30 @@ pub fn trans_free<'a>(cx: &'a Block<'a>, v: ValueRef) -> &'a Block<'a> { Some(expr::Ignore)).bcx } -pub fn trans_exchange_free<'a>(cx: &'a Block<'a>, v: ValueRef) - -> &'a Block<'a> { +fn trans_exchange_free<'a>(cx: &'a Block<'a>, v: ValueRef, size: u64, + align: u64) -> &'a Block<'a> { let _icx = push_ctxt("trans_exchange_free"); + let ccx = cx.ccx(); callee::trans_lang_call(cx, langcall(cx, None, "", ExchangeFreeFnLangItem), - [PointerCast(cx, v, Type::i8p(cx.ccx()))], + [PointerCast(cx, v, Type::i8p(ccx)), C_uint(ccx, size as uint), C_uint(ccx, align as uint)], Some(expr::Ignore)).bcx } +pub fn trans_exchange_free_ty<'a>(bcx: &'a Block<'a>, ptr: ValueRef, + content_ty: ty::t) -> &'a Block<'a> { + let sizing_type = sizing_type_of(bcx.ccx(), content_ty); + let content_size = llsize_of_alloc(bcx.ccx(), sizing_type); + + // `Box<ZeroSizeType>` does not allocate. + if content_size != 0 { + let content_align = llalign_of_min(bcx.ccx(), sizing_type); + trans_exchange_free(bcx, ptr, content_size, content_align) + } else { + bcx + } +} + pub fn take_ty<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t) -> &'a Block<'a> { // NB: v is an *alias* of type t here, not a direct value. @@ -87,17 +102,15 @@ fn get_drop_glue_type(ccx: &CrateContext, t: ty::t) -> ty::t { ty::ty_vec(_, None) | ty::ty_str => t, _ => { let llty = sizing_type_of(ccx, typ); - // Unique boxes do not allocate for zero-size types. The standard - // library may assume that `free` is never called on the pointer - // returned for `Box<ZeroSizeType>`. + // `Box<ZeroSizeType>` does not allocate. if llsize_of_alloc(ccx, llty) == 0 { ty::mk_i8() } else { ty::mk_uniq(tcx, ty::mk_i8()) } - } - } } + } + } _ => t } } @@ -285,20 +298,22 @@ fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) -> &'a Block<' ty::ty_vec(mt, None) => { with_cond(bcx, not_null, |bcx| { let bcx = tvec::make_drop_glue_unboxed(bcx, llbox, mt.ty); - trans_exchange_free(bcx, llbox) + // FIXME: #13994: the old `Box<[T]>` will not support sized deallocation + trans_exchange_free(bcx, llbox, 0, 8) }) } ty::ty_str => { with_cond(bcx, not_null, |bcx| { let unit_ty = ty::sequence_element_type(bcx.tcx(), t); let bcx = tvec::make_drop_glue_unboxed(bcx, llbox, unit_ty); - trans_exchange_free(bcx, llbox) + // FIXME: #13994: the old `Box<str>` will not support sized deallocation + trans_exchange_free(bcx, llbox, 0, 8) }) } _ => { with_cond(bcx, not_null, |bcx| { let bcx = drop_ty(bcx, llbox, content_ty); - trans_exchange_free(bcx, llbox) + trans_exchange_free_ty(bcx, llbox, content_ty) }) } } @@ -340,7 +355,8 @@ fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) -> &'a Block<' Call(bcx, dtor, [PointerCast(bcx, cdata, Type::i8p(bcx.ccx()))], []); // Free the environment itself - trans_exchange_free(bcx, env) + // FIXME: #13994: pass align and size here + trans_exchange_free(bcx, env, 0, 8) }) } _ => { diff --git a/src/librustc/middle/trans/tvec.rs b/src/librustc/middle/trans/tvec.rs index 8ed3b76d652..24518bdeeca 100644 --- a/src/librustc/middle/trans/tvec.rs +++ b/src/librustc/middle/trans/tvec.rs @@ -287,8 +287,11 @@ pub fn trans_uniq_vstore<'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 + let content_ty = vt.unit_ty; fcx.schedule_free_value(cleanup::CustomScope(temp_scope), - val, cleanup::HeapExchange); + val, cleanup::HeapExchange, content_ty); let dataptr = get_dataptr(bcx, val); diff --git a/src/libstd/slice.rs b/src/libstd/slice.rs index e78122f699d..0838211b9a5 100644 --- a/src/libstd/slice.rs +++ b/src/libstd/slice.rs @@ -109,7 +109,7 @@ use ops::Drop; use option::{None, Option, Some}; use ptr::RawPtr; use ptr; -use rt::heap::{exchange_malloc, deallocate}; +use rt::heap::{allocate, deallocate}; use unstable::finally::try_finally; use vec::Vec; @@ -304,7 +304,7 @@ impl<'a, T: Clone> CloneableVector<T> for &'a [T] { unsafe { // this should pass the real required alignment - let ret = exchange_malloc(size, 8) as *mut RawVec<()>; + let ret = allocate(size, 8) as *mut RawVec<()>; let a_size = mem::size_of::<T>(); let a_size = if a_size == 0 {1} else {a_size}; @@ -968,7 +968,7 @@ mod tests { assert_eq!(v_b[0], 2); assert_eq!(v_b[1], 3); - // Test on exchange heap. + // Test `Box<[T]>` let vec_unique = box [1, 2, 3, 4, 5, 6]; let v_d = vec_unique.slice(1u, 6u).to_owned(); assert_eq!(v_d.len(), 5u); |
