diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs index c7bc1bb9733..f1780b07271 100644 --- a/src/liballoc/heap.rs +++ b/src/liballoc/heap.rs @@ -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, 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`. 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. diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 14b74c17e9b..c933690b58f 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -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 Vec { // 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 Vec { #[inline] pub fn with_capacity(capacity: uint) -> Vec { if mem::size_of::() == 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 { diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 24782240f06..507ba3e9d5b 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -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; diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index e86df865118..5187ecb8b3b 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -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) } diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index 7bbdf332fe1..2fac6e80ba0 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -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"); diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index 259f85098af..fa2b192615d 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -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 diff --git a/src/librustc_back/abi.rs b/src/librustc_back/abi.rs index e859a5d21d7..72acba54246 100644 --- a/src/librustc_back/abi.rs +++ b/src/librustc_back/abi.rs @@ -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; diff --git a/src/libsyntax/owned_slice.rs b/src/libsyntax/owned_slice.rs index 7d8a9e08ba0..33482ec0eb3 100644 --- a/src/libsyntax/owned_slice.rs +++ b/src/libsyntax/owned_slice.rs @@ -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 OwnedSlice { } 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 };