alter exchange_free
for sized deallocation
The support for sized deallocation is nearly complete. The only known missing pieces are `Box<str>`, `Box<[T]>` and `proc`.
This commit is contained in:
parent
945019830b
commit
f1ce693e61
@ -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};
|
||||
@ -133,14 +133,20 @@ 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"]
|
||||
|
@ -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>);
|
||||
|
@ -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 => { }
|
||||
|
@ -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)
|
||||
})
|
||||
}
|
||||
_ => {
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user