diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2014-05-13 16:10:05 -0700 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2014-05-17 21:52:23 -0700 |
| commit | 639759b7f46b2ea7fd93cbfdb6fa39ab24f8774f (patch) | |
| tree | c6c817beed1f623f9d933326c75e0a45e6f196c9 /src/libstd/rt | |
| parent | 3da5a5cd18dc2a2177160772725946c3b4512f7c (diff) | |
| download | rust-639759b7f46b2ea7fd93cbfdb6fa39ab24f8774f.tar.gz rust-639759b7f46b2ea7fd93cbfdb6fa39ab24f8774f.zip | |
std: Refactor liballoc out of lib{std,sync}
This commit is part of the libstd facade RFC, issue #13851. This creates a new library, liballoc, which is intended to be the core allocation library for all of Rust. It is pinned on the basic assumption that an allocation failure is an abort or failure. This module has inherited the heap/libc_heap modules from std::rt, the owned/rc modules from std, and the arc module from libsync. These three pointers are currently the three most core pointer implementations in Rust. The UnsafeArc type in std::sync should be considered deprecated and replaced by Arc<Unsafe<T>>. This commit does not currently migrate to this type, but future commits will continue this refactoring.
Diffstat (limited to 'src/libstd/rt')
| -rw-r--r-- | src/libstd/rt/heap.rs | 197 | ||||
| -rw-r--r-- | src/libstd/rt/libc_heap.rs | 51 | ||||
| -rw-r--r-- | src/libstd/rt/local_heap.rs | 3 | ||||
| -rw-r--r-- | src/libstd/rt/mod.rs | 8 | ||||
| -rw-r--r-- | src/libstd/rt/util.rs | 17 |
5 files changed, 4 insertions, 272 deletions
diff --git a/src/libstd/rt/heap.rs b/src/libstd/rt/heap.rs deleted file mode 100644 index e616b9b8beb..00000000000 --- a/src/libstd/rt/heap.rs +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// 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: need a way to mark the `allocate` and `reallocate` return values as `noalias` - -use intrinsics::{abort, cttz32}; -use libc::{c_char, c_int, c_void, size_t}; -use ptr::{RawPtr, mut_null, null}; -use option::{None, Option}; - -#[link(name = "jemalloc", kind = "static")] -extern { - fn je_mallocx(size: size_t, flags: c_int) -> *mut c_void; - fn je_rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void; - fn je_xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t; - fn je_dallocx(ptr: *mut c_void, flags: c_int); - fn je_nallocx(size: size_t, flags: c_int) -> size_t; - fn je_malloc_stats_print(write_cb: Option<extern "C" fn(cbopaque: *mut c_void, *c_char)>, - cbopaque: *mut c_void, - opts: *c_char); -} - -// -lpthread needs to occur after -ljemalloc, the earlier argument isn't enough -#[cfg(not(windows), not(target_os = "android"))] -#[link(name = "pthread")] -extern {} - -// MALLOCX_ALIGN(a) macro -#[inline(always)] -fn mallocx_align(a: uint) -> c_int { unsafe { cttz32(a as u32) as c_int } } - -/// Return a pointer to `size` bytes of memory. -/// -/// Behavior is undefined if the requested size is 0 or the alignment is not a power of 2. The -/// alignment must be no larger than the largest supported page size on the platform. -#[inline] -pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 { - let ptr = je_mallocx(size as size_t, mallocx_align(align)) as *mut u8; - if ptr.is_null() { - abort() - } - ptr -} - -/// Extend or shrink the allocation referenced by `ptr` to `size` bytes of memory. -/// -/// Behavior is undefined if the requested size is 0 or the alignment is not a power of 2. The -/// alignment must be no larger than the largest supported page size on the platform. -/// -/// The `old_size` and `align` parameters are the parameters that were used to create the -/// allocation referenced by `ptr`. The `old_size` parameter may also be the value returned by -/// `usable_size` for the requested size. -#[inline] -#[allow(unused_variable)] // for the parameter names in the documentation -pub unsafe fn reallocate(ptr: *mut u8, size: uint, align: uint, old_size: uint) -> *mut u8 { - let ptr = je_rallocx(ptr as *mut c_void, size as size_t, mallocx_align(align)) as *mut u8; - if ptr.is_null() { - abort() - } - ptr -} - -/// Extend or shrink the allocation referenced by `ptr` to `size` bytes of memory in-place. -/// -/// Return true if successful, otherwise false if the allocation was not altered. -/// -/// Behavior is undefined if the requested size is 0 or the alignment is not a power of 2. The -/// alignment must be no larger than the largest supported page size on the platform. -/// -/// The `old_size` and `align` parameters are the parameters that were used to -/// create the allocation referenced by `ptr`. The `old_size` parameter may be -/// any value in range_inclusive(requested_size, usable_size). -#[inline] -#[allow(unused_variable)] // for the parameter names in the documentation -pub unsafe fn reallocate_inplace(ptr: *mut u8, size: uint, align: uint, old_size: uint) -> bool { - je_xallocx(ptr as *mut c_void, size as size_t, 0, mallocx_align(align)) == size as size_t -} - -/// Deallocate the memory referenced by `ptr`. -/// -/// The `ptr` parameter must not be null. -/// -/// The `size` and `align` parameters are the parameters that were used to create the -/// allocation referenced by `ptr`. The `size` parameter may also be the value returned by -/// `usable_size` for the requested size. -#[inline] -#[allow(unused_variable)] // for the parameter names in the documentation -pub unsafe fn deallocate(ptr: *mut u8, size: uint, align: uint) { - je_dallocx(ptr as *mut c_void, mallocx_align(align)) -} - -/// Return the usable size of an allocation created with the specified the `size` and `align`. -#[inline] -pub fn usable_size(size: uint, align: uint) -> uint { - unsafe { je_nallocx(size as size_t, mallocx_align(align)) as uint } -} - -/// Print implementation-defined allocator statistics. -/// -/// These statistics may be inconsistent if other threads use the allocator during the call. -#[unstable] -pub fn stats_print() { - unsafe { - je_malloc_stats_print(None, mut_null(), null()) - } -} - -/// The allocator for unique pointers. -#[cfg(not(test))] -#[lang="exchange_malloc"] -#[inline(always)] -pub unsafe fn exchange_malloc_(size: uint, align: uint) -> *mut u8 { - exchange_malloc(size, align) -} - -/// The allocator for unique pointers. -#[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 { - allocate(size, align) - } -} - -#[cfg(not(test))] -#[lang="exchange_free"] -#[inline] -// FIXME: #13994 (rustc should pass align and size here) -unsafe fn exchange_free(ptr: *mut u8) { - deallocate(ptr, 0, 8); -} - -// FIXME: #7496 -#[cfg(not(test))] -#[lang="closure_exchange_malloc"] -#[inline] -unsafe fn closure_exchange_malloc(drop_glue: fn(*mut u8), size: uint, align: uint) -> *mut u8 { - let total_size = ::rt::util::get_box_size(size, align); - let p = allocate(total_size, 8); - - let alloc = p as *mut ::raw::Box<()>; - (*alloc).drop_glue = drop_glue; - - alloc as *mut u8 -} - -// hack for libcore -#[no_mangle] -#[doc(hidden)] -#[deprecated] -#[cfg(not(test))] -pub unsafe extern "C" fn rust_malloc(size: uint, align: uint) -> *mut u8 { - exchange_malloc(size, align) -} - -// hack for libcore -#[no_mangle] -#[doc(hidden)] -#[deprecated] -#[cfg(not(test))] -pub unsafe extern "C" fn rust_free(ptr: *mut u8, size: uint, align: uint) { - deallocate(ptr, size, align) -} - -#[cfg(test)] -mod bench { - extern crate test; - use self::test::Bencher; - - #[bench] - fn alloc_owned_small(b: &mut Bencher) { - b.iter(|| { - box 10 - }) - } - - #[bench] - fn alloc_owned_big(b: &mut Bencher) { - b.iter(|| { - box [10, ..1000] - }) - } -} diff --git a/src/libstd/rt/libc_heap.rs b/src/libstd/rt/libc_heap.rs deleted file mode 100644 index ece51ab9989..00000000000 --- a/src/libstd/rt/libc_heap.rs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -//! The global (exchange) heap. - -use libc::{c_void, size_t, free, malloc, realloc}; -use ptr::{RawPtr, mut_null}; -use intrinsics::abort; - -/// A wrapper around libc::malloc, aborting on out-of-memory -#[inline] -pub unsafe fn malloc_raw(size: uint) -> *mut u8 { - // `malloc(0)` may allocate, but it may also return a null pointer - // http://pubs.opengroup.org/onlinepubs/9699919799/functions/malloc.html - if size == 0 { - mut_null() - } else { - let p = malloc(size as size_t); - if p.is_null() { - // we need a non-allocating way to print an error here - abort(); - } - p as *mut u8 - } -} - -/// A wrapper around libc::realloc, aborting on out-of-memory -#[inline] -pub unsafe fn realloc_raw(ptr: *mut u8, size: uint) -> *mut u8 { - // `realloc(ptr, 0)` may allocate, but it may also return a null pointer - // http://pubs.opengroup.org/onlinepubs/9699919799/functions/realloc.html - if size == 0 { - free(ptr as *mut c_void); - mut_null() - } else { - let p = realloc(ptr as *mut c_void, size as size_t); - if p.is_null() { - // we need a non-allocating way to print an error here - abort(); - } - p as *mut u8 - } -} diff --git a/src/libstd/rt/local_heap.rs b/src/libstd/rt/local_heap.rs index 5feec7fd9d2..240d137adc6 100644 --- a/src/libstd/rt/local_heap.rs +++ b/src/libstd/rt/local_heap.rs @@ -10,6 +10,7 @@ //! The local, garbage collected heap +use alloc::util; use iter::Iterator; use libc::{c_void, free}; use mem; @@ -58,7 +59,7 @@ impl LocalHeap { #[inline] pub fn alloc(&mut self, drop_glue: fn(*mut u8), size: uint, align: uint) -> *mut Box { - let total_size = ::rt::util::get_box_size(size, align); + let total_size = util::get_box_size(size, align); let alloc = self.memory_region.malloc(total_size); { // Make sure that we can't use `mybox` outside of this scope diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs index a04cbabedd6..daf18346fee 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -74,6 +74,8 @@ pub use self::unwind::{begin_unwind, begin_unwind_fmt}; pub use self::util::{Stdio, Stdout, Stderr}; +pub use alloc::{heap, libc_heap}; + // FIXME: these probably shouldn't be public... #[doc(hidden)] pub mod shouldnt_be_public { @@ -86,12 +88,6 @@ pub mod shouldnt_be_public { // Internal macros used by the runtime. mod macros; -/// Wrappers around malloc / realloc aborting on out-of-memory. -pub mod libc_heap; - -/// The low-level memory allocation API. -pub mod heap; - /// Implementations of language-critical runtime features like @. pub mod task; diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs index 5f9ea14a647..c9e82bd16e5 100644 --- a/src/libstd/rt/util.rs +++ b/src/libstd/rt/util.rs @@ -26,23 +26,6 @@ use slice::ImmutableVector; // FIXME: Once the runtime matures remove the `true` below to turn off rtassert, etc. pub static ENFORCE_SANITY: bool = true || !cfg!(rtopt) || cfg!(rtdebug) || cfg!(rtassert); -#[deprecated] -#[doc(hidden)] -#[inline] -pub fn get_box_size(body_size: uint, body_align: uint) -> uint { - let header_size = ::mem::size_of::<::raw::Box<()>>(); - let total_size = align_to(header_size, body_align) + body_size; - total_size -} - -// 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) -} - /// Get the number of cores available pub fn num_cpus() -> uint { unsafe { |
