auto merge of #17280 : thestinger/rust/heap, r=pcwalton
This commit is contained in:
commit
3212d70302
src
liballoc
libcollections
librustc/middle
librustc_back
libsyntax
@ -8,11 +8,9 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// FIXME: #13994: port to the sized deallocation API when available
|
||||
// FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias`
|
||||
// and `nonnull`
|
||||
|
||||
#[cfg(not(test))] use core::raw;
|
||||
#[cfg(stage0, not(test))] use core::raw;
|
||||
#[cfg(stage0, not(test))] use util;
|
||||
|
||||
/// Returns a pointer to `size` bytes of memory.
|
||||
@ -88,10 +86,11 @@ pub fn stats_print() {
|
||||
imp::stats_print();
|
||||
}
|
||||
|
||||
// The compiler never calls `exchange_free` on Box<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.
|
||||
pub static mut EMPTY: uint = 12345;
|
||||
/// An arbitrary non-null address to represent zero-size allocations.
|
||||
///
|
||||
/// This preserves the non-null invariant for types like `Box<T>`. The address may overlap with
|
||||
/// non-zero-size memory allocations.
|
||||
pub static EMPTY: *mut () = 0x1 as *mut ();
|
||||
|
||||
/// The allocator for unique pointers.
|
||||
#[cfg(not(test))]
|
||||
@ -99,7 +98,7 @@ pub static mut EMPTY: uint = 12345;
|
||||
#[inline]
|
||||
unsafe fn exchange_malloc(size: uint, align: uint) -> *mut u8 {
|
||||
if size == 0 {
|
||||
&EMPTY as *const uint as *mut u8
|
||||
EMPTY as *mut u8
|
||||
} else {
|
||||
allocate(size, align)
|
||||
}
|
||||
@ -112,7 +111,6 @@ unsafe fn exchange_free(ptr: *mut u8, size: uint, align: uint) {
|
||||
deallocate(ptr, size, align);
|
||||
}
|
||||
|
||||
// FIXME: #7496
|
||||
#[cfg(stage0, not(test))]
|
||||
#[lang="closure_exchange_malloc"]
|
||||
#[inline]
|
||||
@ -128,21 +126,6 @@ unsafe fn closure_exchange_malloc(drop_glue: fn(*mut u8), size: uint,
|
||||
alloc as *mut u8
|
||||
}
|
||||
|
||||
// FIXME: #7496
|
||||
#[cfg(not(stage0), not(test))]
|
||||
#[lang="closure_exchange_malloc"]
|
||||
#[inline]
|
||||
#[allow(deprecated)]
|
||||
unsafe fn closure_exchange_malloc(drop_glue: fn(*mut u8), size: uint,
|
||||
align: uint) -> *mut u8 {
|
||||
let p = allocate(size, align);
|
||||
|
||||
let alloc = p as *mut raw::Box<()>;
|
||||
(*alloc).drop_glue = drop_glue;
|
||||
|
||||
alloc as *mut u8
|
||||
}
|
||||
|
||||
// The minimum alignment guaranteed by the architecture. This value is used to
|
||||
// add fast paths for low alignment values. In practice, the alignment is a
|
||||
// constant at the call site and the branch will be optimized out.
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
use core::prelude::*;
|
||||
|
||||
use alloc::heap::{allocate, reallocate, deallocate};
|
||||
use alloc::heap::{EMPTY, allocate, reallocate, deallocate};
|
||||
use core::cmp::max;
|
||||
use core::default::Default;
|
||||
use core::fmt;
|
||||
@ -28,10 +28,6 @@ use {Mutable, MutableSeq};
|
||||
use slice::{MutableOrdSlice, MutableSliceAllocating, CloneableVector};
|
||||
use slice::{Items, MutItems};
|
||||
|
||||
|
||||
#[doc(hidden)]
|
||||
pub static PTR_MARKER: u8 = 0;
|
||||
|
||||
/// An owned, growable vector.
|
||||
///
|
||||
/// # Examples
|
||||
@ -124,7 +120,7 @@ impl<T> Vec<T> {
|
||||
// non-null value which is fine since we never call deallocate on the ptr
|
||||
// if cap is 0. The reason for this is because the pointer of a slice
|
||||
// being NULL would break the null pointer optimization for enums.
|
||||
Vec { len: 0, cap: 0, ptr: &PTR_MARKER as *const _ as *mut T }
|
||||
Vec { len: 0, cap: 0, ptr: EMPTY as *mut T }
|
||||
}
|
||||
|
||||
/// Constructs a new, empty `Vec` with the specified capacity.
|
||||
@ -157,7 +153,7 @@ impl<T> Vec<T> {
|
||||
#[inline]
|
||||
pub fn with_capacity(capacity: uint) -> Vec<T> {
|
||||
if mem::size_of::<T>() == 0 {
|
||||
Vec { len: 0, cap: uint::MAX, ptr: &PTR_MARKER as *const _ as *mut T }
|
||||
Vec { len: 0, cap: uint::MAX, ptr: EMPTY as *mut T }
|
||||
} else if capacity == 0 {
|
||||
Vec::new()
|
||||
} else {
|
||||
|
@ -265,7 +265,6 @@ lets_do_this! {
|
||||
BeginUnwindLangItem, "begin_unwind", begin_unwind;
|
||||
|
||||
ExchangeMallocFnLangItem, "exchange_malloc", exchange_malloc_fn;
|
||||
ClosureExchangeMallocFnLangItem, "closure_exchange_malloc", closure_exchange_malloc_fn;
|
||||
ExchangeFreeFnLangItem, "exchange_free", exchange_free_fn;
|
||||
MallocFnLangItem, "malloc", malloc_fn;
|
||||
FreeFnLangItem, "free", free_fn;
|
||||
|
@ -383,14 +383,10 @@ pub fn malloc_raw_dyn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
Result::new(r.bcx, PointerCast(r.bcx, r.val, llty_ptr))
|
||||
}
|
||||
|
||||
pub fn malloc_raw_dyn_proc<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
t: ty::t, alloc_fn: LangItem)
|
||||
-> Result<'blk, 'tcx> {
|
||||
pub fn malloc_raw_dyn_proc<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: ty::t) -> Result<'blk, 'tcx> {
|
||||
let _icx = push_ctxt("malloc_raw_dyn_proc");
|
||||
let ccx = bcx.ccx();
|
||||
|
||||
let langcall = require_alloc_fn(bcx, t, alloc_fn);
|
||||
|
||||
// Grab the TypeRef type of ptr_ty.
|
||||
let ptr_ty = ty::mk_uniq(bcx.tcx(), t);
|
||||
let ptr_llty = type_of(ccx, ptr_ty);
|
||||
@ -399,18 +395,15 @@ pub fn malloc_raw_dyn_proc<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
let size = llsize_of(bcx.ccx(), llty);
|
||||
let llalign = C_uint(ccx, llalign_of_min(bcx.ccx(), llty) as uint);
|
||||
|
||||
// Allocate space:
|
||||
let drop_glue = glue::get_drop_glue(ccx, ty::mk_uniq(bcx.tcx(), t));
|
||||
let r = callee::trans_lang_call(
|
||||
bcx,
|
||||
langcall,
|
||||
[
|
||||
PointerCast(bcx, drop_glue, Type::glue_fn(ccx, Type::i8p(ccx)).ptr_to()),
|
||||
size,
|
||||
llalign
|
||||
],
|
||||
None);
|
||||
Result::new(r.bcx, PointerCast(r.bcx, r.val, ptr_llty))
|
||||
// Allocate space and store the destructor pointer:
|
||||
let Result {bcx: bcx, val: llbox} = malloc_raw_dyn(bcx, ptr_llty, t, size, llalign);
|
||||
let dtor_ptr = GEPi(bcx, llbox, [0u, abi::box_field_drop_glue]);
|
||||
let drop_glue_field_ty = type_of(ccx, ty::mk_nil_ptr(bcx.tcx()));
|
||||
let drop_glue = PointerCast(bcx, glue::get_drop_glue(ccx, ty::mk_uniq(bcx.tcx(), t)),
|
||||
drop_glue_field_ty);
|
||||
Store(bcx, drop_glue, dtor_ptr);
|
||||
|
||||
Result::new(bcx, llbox)
|
||||
}
|
||||
|
||||
|
||||
|
@ -15,7 +15,6 @@ use driver::config::FullDebugInfo;
|
||||
use llvm::ValueRef;
|
||||
use middle::def;
|
||||
use middle::freevars;
|
||||
use middle::lang_items::ClosureExchangeMallocFnLangItem;
|
||||
use middle::trans::adt;
|
||||
use middle::trans::base::*;
|
||||
use middle::trans::build::*;
|
||||
@ -146,7 +145,7 @@ fn allocate_cbox<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
let cbox_ty = tuplify_box_ty(tcx, cdata_ty);
|
||||
match store {
|
||||
ty::UniqTraitStore => {
|
||||
malloc_raw_dyn_proc(bcx, cbox_ty, ClosureExchangeMallocFnLangItem)
|
||||
malloc_raw_dyn_proc(bcx, cbox_ty)
|
||||
}
|
||||
ty::RegionTraitStore(..) => {
|
||||
let llbox = alloc_ty(bcx, cbox_ty, "__closure");
|
||||
|
@ -519,7 +519,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: ty::t)
|
||||
let env_ptr_ty = Type::at_box(bcx.ccx(), Type::i8(bcx.ccx())).ptr_to();
|
||||
let env = PointerCast(bcx, env, env_ptr_ty);
|
||||
with_cond(bcx, IsNotNull(bcx, env), |bcx| {
|
||||
let dtor_ptr = GEPi(bcx, env, [0u, abi::box_field_tydesc]);
|
||||
let dtor_ptr = GEPi(bcx, env, [0u, abi::box_field_drop_glue]);
|
||||
let dtor = Load(bcx, dtor_ptr);
|
||||
Call(bcx, dtor, [PointerCast(bcx, box_cell_v, Type::i8p(bcx.ccx()))], None);
|
||||
bcx
|
||||
|
@ -9,7 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
pub static box_field_refcnt: uint = 0u;
|
||||
pub static box_field_tydesc: uint = 1u;
|
||||
pub static box_field_drop_glue: uint = 1u;
|
||||
pub static box_field_body: uint = 4u;
|
||||
|
||||
pub static tydesc_field_visit_glue: uint = 3u;
|
||||
|
@ -12,6 +12,7 @@ use std::fmt;
|
||||
use std::default::Default;
|
||||
use std::hash;
|
||||
use std::{mem, raw, ptr, slice, vec};
|
||||
use std::rt::heap::EMPTY;
|
||||
use serialize::{Encodable, Decodable, Encoder, Decoder};
|
||||
|
||||
/// A non-growable owned slice. This would preferably become `~[T]`
|
||||
@ -81,10 +82,9 @@ impl<T> OwnedSlice<T> {
|
||||
}
|
||||
|
||||
pub fn as_slice<'a>(&'a self) -> &'a [T] {
|
||||
static PTR_MARKER: u8 = 0;
|
||||
let ptr = if self.data.is_null() {
|
||||
// length zero, i.e. this will never be read as a T.
|
||||
&PTR_MARKER as *const u8 as *const T
|
||||
EMPTY as *const T
|
||||
} else {
|
||||
self.data as *const T
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user