diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 24e7a65e02a..ec9d4eaed9e 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -33,6 +33,7 @@ use std::cmp; use std::intrinsics::{TyDesc, get_tydesc}; use std::intrinsics; use std::mem; +use std::mem::min_align_of; use std::num; use std::ptr::read; use std::rc::Rc; @@ -204,7 +205,7 @@ impl Arena { #[inline] fn alloc_copy<'a, T>(&'a mut self, op: || -> T) -> &'a T { unsafe { - let ptr = self.alloc_copy_inner(mem::size_of::(), mem::min_align_of::()); + let ptr = self.alloc_copy_inner(mem::size_of::(), min_align_of::()); let ptr: *mut T = transmute(ptr); mem::move_val_init(&mut (*ptr), op()); return transmute(ptr); @@ -261,7 +262,7 @@ impl Arena { unsafe { let tydesc = get_tydesc::(); let (ty_ptr, ptr) = - self.alloc_noncopy_inner(mem::size_of::(), mem::min_align_of::()); + self.alloc_noncopy_inner(mem::size_of::(), min_align_of::()); let ty_ptr: *mut uint = transmute(ty_ptr); let ptr: *mut T = transmute(ptr); // Write in our tydesc along with a bit indicating that it @@ -353,7 +354,29 @@ struct TypedArenaChunk { } impl TypedArenaChunk { + #[cfg(stage0)] #[inline] + fn new(next: Option>>, capacity: uint) + -> Box> { + let mut size = mem::size_of::>(); + size = round_up(size, min_align_of::()); + let elem_size = mem::size_of::(); + let elems_size = elem_size.checked_mul(&capacity).unwrap(); + size = size.checked_add(&elems_size).unwrap(); + + let mut chunk = unsafe { + let chunk = global_heap::exchange_malloc(size); + let mut chunk: Box> = cast::transmute(chunk); + mem::move_val_init(&mut chunk.next, next); + chunk + }; + + chunk.capacity = capacity; + chunk + } + + #[inline] + #[cfg(not(stage0))] fn new(next: Option>>, capacity: uint) -> Box> { let mut size = mem::size_of::>(); @@ -363,7 +386,7 @@ impl TypedArenaChunk { size = size.checked_add(&elems_size).unwrap(); let mut chunk = unsafe { - let chunk = global_heap::exchange_malloc(size); + let chunk = global_heap::exchange_malloc(size, min_align_of::>()); let mut chunk: Box> = cast::transmute(chunk); mem::move_val_init(&mut chunk.next, next); chunk @@ -402,7 +425,7 @@ impl TypedArenaChunk { fn start(&self) -> *u8 { let this: *TypedArenaChunk = self; unsafe { - cast::transmute(round_up(this.offset(1) as uint, mem::min_align_of::())) + cast::transmute(round_up(this.offset(1) as uint, min_align_of::())) } } diff --git a/src/libcore/should_not_exist.rs b/src/libcore/should_not_exist.rs index 0e6baaa518a..74bebc921e3 100644 --- a/src/libcore/should_not_exist.rs +++ b/src/libcore/should_not_exist.rs @@ -29,13 +29,29 @@ use str::StrSlice; #[allow(ctypes)] extern { - fn malloc(size: uint) -> *u8; - fn free(ptr: *u8); + #[cfg(stage0)] + fn rust_malloc(size: uint) -> *u8; + #[cfg(not(stage0))] + fn rust_malloc(size: uint, align: uint) -> *u8; + fn rust_free(ptr: *u8); } +#[cfg(stage0)] unsafe fn alloc(cap: uint) -> *mut Vec<()> { let cap = cap.checked_add(&mem::size_of::>()).unwrap(); - let ret = malloc(cap) as *mut Vec<()>; + let ret = rust_malloc(cap) as *mut Vec<()>; + if ret.is_null() { + intrinsics::abort(); + } + (*ret).fill = 0; + (*ret).alloc = cap; + ret +} + +#[cfg(not(stage0))] +unsafe fn alloc(cap: uint) -> *mut Vec<()> { + let cap = cap.checked_add(&mem::size_of::>()).unwrap(); + let ret = rust_malloc(cap, 8) as *mut Vec<()>; if ret.is_null() { intrinsics::abort(); } @@ -102,7 +118,7 @@ impl FromIterator for ~str { ptr::copy_nonoverlapping_memory(&mut (*ptr2).data, &(*ptr).data, len); - free(ptr as *u8); + rust_free(ptr as *u8); cast::forget(ret); ret = cast::transmute(ptr2); ptr = ptr2; @@ -172,7 +188,7 @@ impl Clone for ~[A] { for j in range(0, *i as int) { ptr::read(&*p.offset(j)); } - free(ret as *u8); + rust_free(ret as *u8); }); cast::transmute(ret) } diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 6c4566c09aa..8f878f099fc 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -345,7 +345,8 @@ fn require_alloc_fn(bcx: &Block, info_ty: ty::t, it: LangItem) -> ast::DefId { pub fn malloc_raw_dyn<'a>(bcx: &'a Block<'a>, ptr_ty: ty::t, - size: ValueRef) + size: ValueRef, + align: ValueRef) -> Result<'a> { let _icx = push_ctxt("malloc_raw_exchange"); let ccx = bcx.ccx(); @@ -353,7 +354,7 @@ pub fn malloc_raw_dyn<'a>(bcx: &'a Block<'a>, // Allocate space: let r = callee::trans_lang_call(bcx, require_alloc_fn(bcx, ptr_ty, ExchangeMallocFnLangItem), - [size], + [size, align], None); let llty_ptr = type_of::type_of(ccx, ptr_ty); diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 806fb3e125d..463aa67ac90 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -67,7 +67,7 @@ use middle::typeck::MethodCall; use util::common::indenter; use util::ppaux::Repr; use util::nodemap::NodeMap; -use middle::trans::machine::{llsize_of, llsize_of_alloc}; +use middle::trans::machine::{llalign_of_min, llsize_of, llsize_of_alloc}; use middle::trans::type_::Type; use syntax::ast; @@ -1170,10 +1170,11 @@ fn trans_uniq_expr<'a>(bcx: &'a Block<'a>, let fcx = bcx.fcx; let llty = type_of::type_of(bcx.ccx(), contents_ty); let size = llsize_of(bcx.ccx(), llty); + let align = C_uint(bcx.ccx(), llalign_of_min(bcx.ccx(), llty) as uint); // We need to a make a pointer type because box_ty is ty_bot // if content_ty is, e.g. box fail!(). let real_box_ty = ty::mk_uniq(bcx.tcx(), contents_ty); - let Result { bcx, val } = malloc_raw_dyn(bcx, real_box_ty, size); + let Result { bcx, val } = malloc_raw_dyn(bcx, real_box_ty, size, align); // 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`. diff --git a/src/librustc/middle/trans/tvec.rs b/src/librustc/middle/trans/tvec.rs index e210437a370..48179abc052 100644 --- a/src/librustc/middle/trans/tvec.rs +++ b/src/librustc/middle/trans/tvec.rs @@ -278,7 +278,9 @@ pub fn trans_uniq_vstore<'a>(bcx: &'a Block<'a>, let vecsize = Add(bcx, alloc, llsize_of(ccx, ccx.opaque_vec_type)); - let Result { bcx: bcx, val: val } = malloc_raw_dyn(bcx, vec_ty, vecsize); + // ~[T] is not going to be changed to support alignment, since it's obsolete. + let align = C_uint(ccx, 8); + let Result { bcx: bcx, val: val } = malloc_raw_dyn(bcx, vec_ty, vecsize, align); Store(bcx, fill, GEPi(bcx, val, [0u, abi::vec_elt_fill])); Store(bcx, alloc, GEPi(bcx, val, [0u, abi::vec_elt_alloc])); diff --git a/src/libstd/rt/global_heap.rs b/src/libstd/rt/global_heap.rs index 7d54c3faf42..c8808b6e821 100644 --- a/src/libstd/rt/global_heap.rs +++ b/src/libstd/rt/global_heap.rs @@ -68,7 +68,7 @@ pub unsafe fn realloc_raw(ptr: *mut u8, size: uint) -> *mut u8 { } /// The allocator for unique pointers without contained managed pointers. -#[cfg(not(test))] +#[cfg(not(test), stage0)] #[lang="exchange_malloc"] #[inline] pub unsafe fn exchange_malloc(size: uint) -> *mut u8 { @@ -85,6 +85,23 @@ pub unsafe fn exchange_malloc(size: uint) -> *mut u8 { } } +/// The allocator for unique pointers without contained managed pointers. +#[cfg(not(test), not(stage0))] +#[lang="exchange_malloc"] +#[inline] +pub 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. + static EMPTY: () = (); + + if size == 0 { + &EMPTY as *() as *mut u8 + } else { + malloc_raw(size) + } +} + // FIXME: #7496 #[cfg(not(test))] #[lang="closure_exchange_malloc"] @@ -118,6 +135,32 @@ pub unsafe fn exchange_free(ptr: *u8) { free(ptr as *mut c_void); } +// hack for libcore +#[no_mangle] +#[doc(hidden)] +#[deprecated] +#[cfg(stage0)] +pub extern "C" fn rust_malloc(size: uint) -> *mut u8 { + unsafe { exchange_malloc(size) } +} + +// hack for libcore +#[no_mangle] +#[doc(hidden)] +#[deprecated] +#[cfg(not(stage0))] +pub extern "C" fn rust_malloc(size: uint, align: uint) -> *mut u8 { + unsafe { exchange_malloc(size, align) } +} + +// hack for libcore +#[no_mangle] +#[doc(hidden)] +#[deprecated] +pub extern "C" fn rust_free(ptr: *u8) { + unsafe { exchange_free(ptr) } +} + #[cfg(test)] mod bench { extern crate test;