about summary refs log tree commit diff
path: root/src/libstd/rt
diff options
context:
space:
mode:
authorDaniel Micay <danielmicay@gmail.com>2014-05-06 22:03:14 -0400
committerDaniel Micay <danielmicay@gmail.com>2014-05-10 19:58:17 -0400
commit138437956c9ab78aede9bb698aa80f9367b3b75a (patch)
treeb1614baf6a134ee7e8a6f728c86ceb9f4996dd60 /src/libstd/rt
parentaaf6e06b01c4f7490e71693d3c96f466032e80d0 (diff)
downloadrust-138437956c9ab78aede9bb698aa80f9367b3b75a.tar.gz
rust-138437956c9ab78aede9bb698aa80f9367b3b75a.zip
initial port of the exchange allocator to jemalloc
In stage0, all allocations are 8-byte aligned. Passing a size and
alignment to free is not yet implemented everywhere (0 size and 8 align
are used as placeholders). Fixing this is part of #13994.

Closes #13616
Diffstat (limited to 'src/libstd/rt')
-rw-r--r--src/libstd/rt/global_heap.rs131
-rw-r--r--src/libstd/rt/heap.rs122
-rw-r--r--src/libstd/rt/local_heap.rs5
-rw-r--r--src/libstd/rt/util.rs17
4 files changed, 142 insertions, 133 deletions
diff --git a/src/libstd/rt/global_heap.rs b/src/libstd/rt/global_heap.rs
index c8808b6e821..ece51ab9989 100644
--- a/src/libstd/rt/global_heap.rs
+++ b/src/libstd/rt/global_heap.rs
@@ -14,23 +14,6 @@
 use libc::{c_void, size_t, free, malloc, realloc};
 use ptr::{RawPtr, mut_null};
 use intrinsics::abort;
-use raw;
-use mem::size_of;
-
-#[inline]
-pub fn get_box_size(body_size: uint, body_align: uint) -> uint {
-    let header_size = 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)
-}
 
 /// A wrapper around libc::malloc, aborting on out-of-memory
 #[inline]
@@ -66,117 +49,3 @@ pub unsafe fn realloc_raw(ptr: *mut u8, size: uint) -> *mut u8 {
         p as *mut u8
     }
 }
-
-/// The allocator for unique pointers without contained managed pointers.
-#[cfg(not(test), stage0)]
-#[lang="exchange_malloc"]
-#[inline]
-pub unsafe fn exchange_malloc(size: uint) -> *mut u8 {
-    // The compiler never calls `exchange_free` on Box<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)
-    }
-}
-
-/// 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"]
-#[inline]
-pub unsafe fn closure_exchange_malloc_(drop_glue: fn(*mut u8), size: uint, align: uint) -> *u8 {
-    closure_exchange_malloc(drop_glue, size, align)
-}
-
-#[inline]
-pub unsafe fn closure_exchange_malloc(drop_glue: fn(*mut u8), size: uint, align: uint) -> *u8 {
-    let total_size = get_box_size(size, align);
-    let p = malloc_raw(total_size);
-
-    let alloc = p as *mut raw::Box<()>;
-    (*alloc).drop_glue = drop_glue;
-
-    alloc as *u8
-}
-
-// NB: Calls to free CANNOT be allowed to fail, as throwing an exception from
-// inside a landing pad may corrupt the state of the exception handler.
-#[cfg(not(test))]
-#[lang="exchange_free"]
-#[inline]
-pub unsafe fn exchange_free_(ptr: *u8) {
-    exchange_free(ptr)
-}
-
-#[inline]
-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;
-    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/heap.rs b/src/libstd/rt/heap.rs
index 1b4b1e444fe..30583f76330 100644
--- a/src/libstd/rt/heap.rs
+++ b/src/libstd/rt/heap.rs
@@ -98,3 +98,125 @@ pub unsafe fn deallocate(ptr: *mut u8, size: uint, align: uint) {
 pub fn usable_size(size: uint, align: uint) -> uint {
     unsafe { je_nallocx(size as size_t, mallocx_align(align)) as uint }
 }
+
+/// The allocator for unique pointers.
+#[cfg(stage0)]
+#[lang="exchange_malloc"]
+#[inline(always)]
+pub unsafe fn exchange_malloc_(size: uint) -> *mut u8 {
+    exchange_malloc(size)
+}
+
+/// The allocator for unique pointers.
+#[cfg(not(test), not(stage0))]
+#[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.
+#[cfg(stage0)]
+#[inline]
+pub unsafe fn exchange_malloc(size: 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, 8)
+    }
+}
+
+/// The allocator for unique pointers.
+#[cfg(not(stage0))]
+#[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)
+pub unsafe fn exchange_free_(ptr: *mut u8) {
+    exchange_free(ptr, 0, 8)
+}
+
+#[inline]
+pub unsafe fn exchange_free(ptr: *mut u8, size: uint, align: uint) {
+    deallocate(ptr, size, align);
+}
+
+// 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(stage0, not(test))]
+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), not(test))]
+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]
+#[cfg(not(test))]
+pub extern "C" fn rust_free(ptr: *mut u8, size: uint, align: uint) {
+    unsafe { exchange_free(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/local_heap.rs b/src/libstd/rt/local_heap.rs
index caf0d9028c5..8795736b3f5 100644
--- a/src/libstd/rt/local_heap.rs
+++ b/src/libstd/rt/local_heap.rs
@@ -12,6 +12,7 @@
 
 use cast;
 use iter::Iterator;
+use libc::{c_void, free};
 use mem;
 use ops::Drop;
 use option::{Option, None, Some};
@@ -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 = global_heap::get_box_size(size, align);
+        let total_size = ::rt::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
@@ -226,7 +227,7 @@ impl MemoryRegion {
             self.release(cast::transmute(alloc));
             rtassert!(self.live_allocations > 0);
             self.live_allocations -= 1;
-            global_heap::exchange_free(alloc as *u8)
+            free(alloc as *mut c_void)
         }
     }
 
diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs
index 84284ca1faf..e8b1acb1024 100644
--- a/src/libstd/rt/util.rs
+++ b/src/libstd/rt/util.rs
@@ -26,6 +26,23 @@ 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 {