From 80ab87784108b1a26e9670a029283567b23cf1ad Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Sun, 30 Jun 2013 22:12:26 -0400 Subject: [PATCH 1/4] global_heap: inline malloc_raw and add realloc_raw --- src/libstd/libc.rs | 2 +- src/libstd/rt/global_heap.rs | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/libstd/libc.rs b/src/libstd/libc.rs index 41b78afded1a8..f4ea29b5c05e4 100644 --- a/src/libstd/libc.rs +++ b/src/libstd/libc.rs @@ -1945,7 +1945,7 @@ pub mod funcs { #[fast_ffi] unsafe fn malloc(size: size_t) -> *c_void; #[fast_ffi] - unsafe fn realloc(p: *c_void, size: size_t) -> *c_void; + unsafe fn realloc(p: *mut c_void, size: size_t) -> *mut c_void; #[fast_ffi] unsafe fn free(p: *c_void); unsafe fn abort() -> !; diff --git a/src/libstd/rt/global_heap.rs b/src/libstd/rt/global_heap.rs index f669dc753d60d..a7fbed2dd70b7 100644 --- a/src/libstd/rt/global_heap.rs +++ b/src/libstd/rt/global_heap.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use libc::{c_char, c_void, size_t, uintptr_t, free, malloc}; +use libc::{c_char, c_void, size_t, uintptr_t, free, malloc, realloc}; use managed::raw::{BoxHeaderRepr, BoxRepr}; use unstable::intrinsics::TyDesc; use sys::size_of; @@ -33,6 +33,7 @@ fn align_to(size: uint, align: uint) -> uint { } /// A wrapper around libc::malloc, aborting on out-of-memory +#[inline] pub unsafe fn malloc_raw(size: uint) -> *c_void { let p = malloc(size as size_t); if p.is_null() { @@ -42,6 +43,17 @@ pub unsafe fn malloc_raw(size: uint) -> *c_void { p } +/// A wrapper around libc::realloc, aborting on out-of-memory +#[inline] +pub unsafe fn realloc_raw(ptr: *mut c_void, size: uint) -> *mut c_void { + let p = realloc(ptr, size as size_t); + if p.is_null() { + // we need a non-allocating way to print an error here + abort(); + } + p +} + // FIXME #4942: Make these signatures agree with exchange_alloc's signatures #[cfg(stage0, not(test))] #[lang="exchange_malloc"] From b731d96b4f2a8d5733e79a863c40632425456520 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Sun, 30 Jun 2013 22:18:17 -0400 Subject: [PATCH 2/4] vec: implement exchange vector reserve in Rust --- src/libstd/vec.rs | 26 ++++++++++++++------------ src/rt/rust_builtin.cpp | 7 ------- src/rt/rustrt.def.in | 1 - 3 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 272ad0ac705f4..310b7e6a1d473 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -22,12 +22,14 @@ use iterator::{FromIterator, Iterator, IteratorUtil}; use iter::FromIter; use kinds::Copy; use libc; +use libc::c_void; use num::Zero; use ops::Add; use option::{None, Option, Some}; use ptr::to_unsafe_ptr; use ptr; use ptr::RawPtr; +use rt::global_heap::realloc_raw; use sys; use sys::size_of; use uint; @@ -52,12 +54,6 @@ pub mod rustrt { #[abi = "cdecl"] pub extern { - // These names are terrible. reserve_shared applies - // to ~[] and reserve_shared_actual applies to @[]. - #[fast_ffi] - unsafe fn vec_reserve_shared(t: *TyDesc, - v: **raw::VecRepr, - n: libc::size_t); #[fast_ffi] unsafe fn vec_reserve_shared_actual(t: *TyDesc, v: **raw::VecRepr, @@ -1523,13 +1519,16 @@ impl OwnedVector for ~[T] { use managed; if self.capacity() < n { unsafe { - let ptr: **raw::VecRepr = cast::transmute(self); + let ptr: *mut *mut raw::VecRepr = cast::transmute(self); let td = get_tydesc::(); if ((**ptr).box_header.ref_count == managed::raw::RC_MANAGED_UNIQUE) { - rustrt::vec_reserve_shared_actual(td, ptr, n as libc::size_t); + rustrt::vec_reserve_shared_actual(td, ptr as **raw::VecRepr, n as libc::size_t); } else { - rustrt::vec_reserve_shared(td, ptr, n as libc::size_t); + let alloc = n * sys::nonzero_size_of::(); + *ptr = realloc_raw(*ptr as *mut c_void, alloc + size_of::()) + as *mut raw::VecRepr; + (**ptr).unboxed.alloc = alloc; } } } @@ -1551,12 +1550,15 @@ impl OwnedVector for ~[T] { // Only make the (slow) call into the runtime if we have to if self.capacity() < n { unsafe { - let ptr: **raw::VecRepr = cast::transmute(self); + let ptr: *mut *mut raw::VecRepr = cast::transmute(self); let td = get_tydesc::(); if contains_managed::() { - rustrt::vec_reserve_shared_actual(td, ptr, n as libc::size_t); + rustrt::vec_reserve_shared_actual(td, ptr as **raw::VecRepr, n as libc::size_t); } else { - rustrt::vec_reserve_shared(td, ptr, n as libc::size_t); + let alloc = n * sys::nonzero_size_of::(); + *ptr = realloc_raw(*ptr as *mut c_void, alloc + size_of::()) + as *mut raw::VecRepr; + (**ptr).unboxed.alloc = alloc; } } } diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index de46d7b3e8ae7..17f36e810cd1a 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -75,13 +75,6 @@ vec_reserve_shared_actual(type_desc* ty, rust_vec_box** vp, reserve_vec_exact_shared(task, vp, n_elts * ty->size); } -// This is completely misnamed. -extern "C" CDECL void -vec_reserve_shared(type_desc* ty, rust_vec_box** vp, - size_t n_elts) { - reserve_vec_exact(vp, n_elts * ty->size); -} - extern "C" CDECL size_t rand_seed_size() { return rng_seed_size(); diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index b572f1aba6a53..0da04e34f495d 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -55,7 +55,6 @@ rust_get_c_stack rust_log_str start_task vec_reserve_shared_actual -vec_reserve_shared task_clear_event_reject task_wait_event task_signal_event From 0d7799d3048eea4039d59c0cca98449e1c52a561 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Sun, 30 Jun 2013 22:41:51 -0400 Subject: [PATCH 3/4] global_heap: inline get_box_size and align_to --- src/libstd/rt/global_heap.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libstd/rt/global_heap.rs b/src/libstd/rt/global_heap.rs index a7fbed2dd70b7..1e0ad3352fef7 100644 --- a/src/libstd/rt/global_heap.rs +++ b/src/libstd/rt/global_heap.rs @@ -18,6 +18,7 @@ extern { fn abort(); } +#[inline] fn get_box_size(body_size: uint, body_align: uint) -> uint { let header_size = size_of::(); // FIXME (#2699): This alignment calculation is suspicious. Is it right? @@ -27,6 +28,7 @@ fn get_box_size(body_size: uint, body_align: uint) -> uint { // Rounds |size| to the nearest |alignment|. Invariant: |alignment| is a power // of two. +#[inline] fn align_to(size: uint, align: uint) -> uint { assert!(align != 0); (size + align - 1) & !(align - 1) From 5b40f2ae5b4357a9488bd97da011bd07aebf6aaa Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Sun, 30 Jun 2013 23:30:40 -0400 Subject: [PATCH 4/4] pass exchange_malloc an alignment, not a tydesc --- src/librustc/middle/trans/base.rs | 56 ++++++++++++++++++++----------- src/libstd/rt/global_heap.rs | 9 ++--- 2 files changed, 39 insertions(+), 26 deletions(-) diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index cf671bdce6776..411cbcbe9eb76 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -258,25 +258,43 @@ pub fn malloc_raw_dyn(bcx: block, } }; - // Grab the TypeRef type of box_ptr_ty. - let box_ptr_ty = mk_fn(bcx.tcx(), t); - let llty = type_of(ccx, box_ptr_ty); - - // Get the tydesc for the body: - let static_ti = get_tydesc(ccx, t); - glue::lazily_emit_all_tydesc_glue(ccx, static_ti); - - // Allocate space: - let tydesc = PointerCast(bcx, static_ti.tydesc, Type::i8p()); - let rval = alloca(bcx, Type::i8p()); - let bcx = callee::trans_lang_call( - bcx, - langcall, - [tydesc, size], - expr::SaveIn(rval)); - let r = rslt(bcx, PointerCast(bcx, Load(bcx, rval), llty)); - maybe_set_managed_unique_rc(r.bcx, r.val, heap); - r + if heap == heap_exchange { + // Grab the TypeRef type of box_ptr_ty. + let box_ptr_ty = mk_fn(bcx.tcx(), t); + let llty = type_of(ccx, box_ptr_ty); + + let llty_value = type_of::type_of(ccx, t); + let llalign = llalign_of_min(ccx, llty_value); + + // Allocate space: + let rval = alloca(bcx, Type::i8p()); + let bcx = callee::trans_lang_call( + bcx, + langcall, + [C_i32(llalign as i32), size], + expr::SaveIn(rval)); + rslt(bcx, PointerCast(bcx, Load(bcx, rval), llty)) + } else { + // Grab the TypeRef type of box_ptr_ty. + let box_ptr_ty = mk_fn(bcx.tcx(), t); + let llty = type_of(ccx, box_ptr_ty); + + // Get the tydesc for the body: + let static_ti = get_tydesc(ccx, t); + glue::lazily_emit_all_tydesc_glue(ccx, static_ti); + + // Allocate space: + let tydesc = PointerCast(bcx, static_ti.tydesc, Type::i8p()); + let rval = alloca(bcx, Type::i8p()); + let bcx = callee::trans_lang_call( + bcx, + langcall, + [tydesc, size], + expr::SaveIn(rval)); + let r = rslt(bcx, PointerCast(bcx, Load(bcx, rval), llty)); + maybe_set_managed_unique_rc(r.bcx, r.val, heap); + r + } } // malloc_raw: expects an unboxed type and returns a pointer to diff --git a/src/libstd/rt/global_heap.rs b/src/libstd/rt/global_heap.rs index 1e0ad3352fef7..1020580d52c00 100644 --- a/src/libstd/rt/global_heap.rs +++ b/src/libstd/rt/global_heap.rs @@ -80,13 +80,8 @@ pub unsafe fn exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char { #[cfg(not(stage0), not(test))] #[lang="exchange_malloc"] #[inline] -pub unsafe fn exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char { - let td = td as *TyDesc; - let size = size as uint; - - assert!(td.is_not_null()); - - let total_size = get_box_size(size, (*td).align); +pub unsafe fn exchange_malloc(align: u32, size: uintptr_t) -> *c_char { + let total_size = get_box_size(size as uint, align as uint); malloc_raw(total_size as uint) as *c_char }