From 396f9106173b941e880a0f311bc2d1429a68c983 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Mon, 15 Sep 2014 15:28:25 -0400 Subject: [PATCH 1/3] heap: rm out-of-date FIXMEs --- src/liballoc/heap.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs index c7bc1bb9733..a2c406be5a9 100644 --- a/src/liballoc/heap.rs +++ b/src/liballoc/heap.rs @@ -8,9 +8,7 @@ // 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 util; From 84b37374bf31b463c36f70123e870f52db19c740 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Mon, 15 Sep 2014 15:37:01 -0400 Subject: [PATCH 2/3] heap: optimize EMPTY to avoid relocations Sized deallocation makes it pointless to provide an address that never overlaps with pointers returned by an allocator. Code can branch on the capacity of the allocation instead of a comparison with this sentinel. This improves the situation in #8859, and the remaining issues are only from the logging API, which should be disabled by default in optimized release builds anyway along with debug assertions. The remaining issues are part of #17081. Closes #8859 --- src/liballoc/heap.rs | 11 ++++++----- src/libcollections/vec.rs | 10 +++------- src/libsyntax/owned_slice.rs | 4 ++-- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs index a2c406be5a9..b6c255e7930 100644 --- a/src/liballoc/heap.rs +++ b/src/liballoc/heap.rs @@ -86,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))] @@ -97,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) } diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 6fc367474bb..3597ab285ba 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -12,7 +12,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; @@ -26,10 +26,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 @@ -122,7 +118,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. @@ -155,7 +151,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/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 }; From d206f05132566a4ae1974e7a3d892ab5788616cd Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Mon, 15 Sep 2014 16:31:32 -0400 Subject: [PATCH 3/3] remove the closure_exchange_malloc lang item --- src/liballoc/heap.rs | 18 +----------------- src/librustc/middle/lang_items.rs | 1 - src/librustc/middle/trans/base.rs | 27 ++++++++++----------------- src/librustc/middle/trans/closure.rs | 3 +-- src/librustc/middle/trans/glue.rs | 2 +- src/librustc_back/abi.rs | 2 +- 6 files changed, 14 insertions(+), 39 deletions(-) diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs index b6c255e7930..f1780b07271 100644 --- a/src/liballoc/heap.rs +++ b/src/liballoc/heap.rs @@ -10,7 +10,7 @@ // FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias` -#[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. @@ -111,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] @@ -127,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/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;