about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/collections/hash/table.rs11
-rw-r--r--src/libstd/error.rs4
-rw-r--r--src/libstd/heap.rs165
-rw-r--r--src/libstd/lib.rs14
-rw-r--r--src/libstd/sys/unix/mod.rs20
-rw-r--r--src/libstd/sys/windows/mod.rs18
6 files changed, 178 insertions, 54 deletions
diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs
index 50c721db849..06f4f7643ec 100644
--- a/src/libstd/collections/hash/table.rs
+++ b/src/libstd/collections/hash/table.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use alloc::heap::{allocate, deallocate};
+use alloc::heap::{Heap, Alloc, Layout};
 
 use cmp;
 use hash::{BuildHasher, Hash, Hasher};
@@ -781,10 +781,8 @@ impl<K, V> RawTable<K, V> {
                     .expect("capacity overflow"),
                 "capacity overflow");
 
-        let buffer = allocate(size, alignment);
-        if buffer.is_null() {
-            ::alloc::oom()
-        }
+        let buffer = Heap.alloc(Layout::from_size_align(size, alignment).unwrap())
+            .unwrap_or_else(|e| Heap.oom(e));
 
         let hashes = buffer.offset(hash_offset as isize) as *mut HashUint;
 
@@ -1193,7 +1191,8 @@ unsafe impl<#[may_dangle] K, #[may_dangle] V> Drop for RawTable<K, V> {
         debug_assert!(!oflo, "should be impossible");
 
         unsafe {
-            deallocate(self.hashes.ptr() as *mut u8, size, align);
+            Heap.dealloc(self.hashes.ptr() as *mut u8,
+                         Layout::from_size_align(size, align).unwrap());
             // Remember how everything was allocated out of one buffer
             // during initialization? We only need one call to free here.
         }
diff --git a/src/libstd/error.rs b/src/libstd/error.rs
index 4b340f70fbc..d77f817659c 100644
--- a/src/libstd/error.rs
+++ b/src/libstd/error.rs
@@ -224,7 +224,7 @@ impl Error for ! {
 
 #[unstable(feature = "allocator_api",
            reason = "the precise API and guarantees it provides may be tweaked.",
-           issue = "27700")]
+           issue = "32838")]
 impl Error for allocator::AllocErr {
     fn description(&self) -> &str {
         allocator::AllocErr::description(self)
@@ -233,7 +233,7 @@ impl Error for allocator::AllocErr {
 
 #[unstable(feature = "allocator_api",
            reason = "the precise API and guarantees it provides may be tweaked.",
-           issue = "27700")]
+           issue = "32838")]
 impl Error for allocator::CannotReallocInPlace {
     fn description(&self) -> &str {
         allocator::CannotReallocInPlace::description(self)
diff --git a/src/libstd/heap.rs b/src/libstd/heap.rs
new file mode 100644
index 00000000000..83bd3b04b4d
--- /dev/null
+++ b/src/libstd/heap.rs
@@ -0,0 +1,165 @@
+// Copyright 2017 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.
+
+//! dox
+
+#![unstable(issue = "32838", feature = "allocator_api")]
+
+pub use alloc::heap::{Heap, Alloc, Layout, Excess, CannotReallocInPlace, AllocErr};
+#[cfg(not(stage0))]
+pub use alloc_system::System;
+
+#[cfg(all(not(stage0), not(test)))]
+#[doc(hidden)]
+pub mod __default_lib_allocator {
+    use super::{System, Layout, Alloc, AllocErr};
+    use ptr;
+
+    // for symbol names src/librustc/middle/allocator.rs
+    // for signatures src/librustc_allocator/lib.rs
+
+    // linkage directives are provided as part of the current compiler allocator
+    // ABI
+
+    #[no_mangle]
+    pub unsafe extern fn __rdl_alloc(size: usize,
+                                     align: usize,
+                                     err: *mut u8) -> *mut u8 {
+        let layout = Layout::from_size_align_unchecked(size, align);
+        match System.alloc(layout) {
+            Ok(p) => p,
+            Err(e) => {
+                ptr::write(err as *mut AllocErr, e);
+                0 as *mut u8
+            }
+        }
+    }
+
+    #[no_mangle]
+    pub unsafe extern fn __rdl_oom(err: *const u8) -> ! {
+        System.oom((*(err as *const AllocErr)).clone())
+    }
+
+    #[no_mangle]
+    pub unsafe extern fn __rdl_dealloc(ptr: *mut u8,
+                                       size: usize,
+                                       align: usize) {
+        System.dealloc(ptr, Layout::from_size_align_unchecked(size, align))
+    }
+
+    #[no_mangle]
+    pub unsafe extern fn __rdl_usable_size(layout: *const u8,
+                                           min: *mut usize,
+                                           max: *mut usize) {
+        let pair = System.usable_size(&*(layout as *const Layout));
+        *min = pair.0;
+        *max = pair.1;
+    }
+
+    #[no_mangle]
+    pub unsafe extern fn __rdl_realloc(ptr: *mut u8,
+                                       old_size: usize,
+                                       old_align: usize,
+                                       new_size: usize,
+                                       new_align: usize,
+                                       err: *mut u8) -> *mut u8 {
+        let old_layout = Layout::from_size_align_unchecked(old_size, old_align);
+        let new_layout = Layout::from_size_align_unchecked(new_size, new_align);
+        match System.realloc(ptr, old_layout, new_layout) {
+            Ok(p) => p,
+            Err(e) => {
+                ptr::write(err as *mut AllocErr, e);
+                0 as *mut u8
+            }
+        }
+    }
+
+    #[no_mangle]
+    pub unsafe extern fn __rdl_alloc_zeroed(size: usize,
+                                            align: usize,
+                                            err: *mut u8) -> *mut u8 {
+        let layout = Layout::from_size_align_unchecked(size, align);
+        match System.alloc_zeroed(layout) {
+            Ok(p) => p,
+            Err(e) => {
+                ptr::write(err as *mut AllocErr, e);
+                0 as *mut u8
+            }
+        }
+    }
+
+    #[no_mangle]
+    pub unsafe extern fn __rdl_alloc_excess(size: usize,
+                                            align: usize,
+                                            excess: *mut usize,
+                                            err: *mut u8) -> *mut u8 {
+        let layout = Layout::from_size_align_unchecked(size, align);
+        match System.alloc_excess(layout) {
+            Ok(p) => {
+                *excess = p.1;
+                p.0
+            }
+            Err(e) => {
+                ptr::write(err as *mut AllocErr, e);
+                0 as *mut u8
+            }
+        }
+    }
+
+    #[no_mangle]
+    pub unsafe extern fn __rdl_realloc_excess(ptr: *mut u8,
+                                              old_size: usize,
+                                              old_align: usize,
+                                              new_size: usize,
+                                              new_align: usize,
+                                              excess: *mut usize,
+                                              err: *mut u8) -> *mut u8 {
+        let old_layout = Layout::from_size_align_unchecked(old_size, old_align);
+        let new_layout = Layout::from_size_align_unchecked(new_size, new_align);
+        match System.realloc_excess(ptr, old_layout, new_layout) {
+            Ok(p) => {
+                *excess = p.1;
+                p.0
+            }
+            Err(e) => {
+                ptr::write(err as *mut AllocErr, e);
+                0 as *mut u8
+            }
+        }
+    }
+
+    #[no_mangle]
+    pub unsafe extern fn __rdl_grow_in_place(ptr: *mut u8,
+                                             old_size: usize,
+                                             old_align: usize,
+                                             new_size: usize,
+                                             new_align: usize) -> u8 {
+        let old_layout = Layout::from_size_align_unchecked(old_size, old_align);
+        let new_layout = Layout::from_size_align_unchecked(new_size, new_align);
+        match System.grow_in_place(ptr, old_layout, new_layout) {
+            Ok(()) => 1,
+            Err(_) => 0,
+        }
+    }
+
+    #[no_mangle]
+    pub unsafe extern fn __rdl_shrink_in_place(ptr: *mut u8,
+                                               old_size: usize,
+                                               old_align: usize,
+                                               new_size: usize,
+                                               new_align: usize) -> u8 {
+        let old_layout = Layout::from_size_align_unchecked(old_size, old_align);
+        let new_layout = Layout::from_size_align_unchecked(new_size, new_align);
+        match System.shrink_in_place(ptr, old_layout, new_layout) {
+            Ok(()) => 1,
+            Err(_) => 0,
+        }
+    }
+}
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index bafe23e80a0..c4bdf7c5b82 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -230,11 +230,6 @@
 // Tell the compiler to link to either panic_abort or panic_unwind
 #![needs_panic_runtime]
 
-// Always use alloc_system during stage0 since we don't know if the alloc_*
-// crate the stage0 compiler will pick by default is available (most
-// obviously, if the user has disabled jemalloc in `./configure`).
-#![cfg_attr(any(stage0, feature = "force_alloc_system"), feature(alloc_system))]
-
 // Turn warnings into errors, but only after stage0, where it can be useful for
 // code to emit warnings during language transitions
 #![deny(warnings)]
@@ -246,6 +241,8 @@
 // compiler details that will never be stable
 #![feature(alloc)]
 #![feature(allocator_api)]
+#![feature(alloc_system)]
+#![feature(allocator_internals)]
 #![feature(allow_internal_unstable)]
 #![feature(asm)]
 #![feature(associated_consts)]
@@ -322,6 +319,8 @@
 #![cfg_attr(test, feature(update_panic_count))]
 #![cfg_attr(test, feature(float_bits_conv))]
 
+#![cfg_attr(not(stage0), default_lib_allocator)]
+
 // Explicitly import the prelude. The compiler uses this same unstable attribute
 // to import the prelude implicitly when building crates that depend on std.
 #[prelude_import]
@@ -342,15 +341,13 @@ extern crate core as __core;
 #[macro_use]
 #[macro_reexport(vec, format)]
 extern crate alloc;
+extern crate alloc_system;
 extern crate std_unicode;
 extern crate libc;
 
 // We always need an unwinder currently for backtraces
 extern crate unwind;
 
-#[cfg(any(stage0, feature = "force_alloc_system"))]
-extern crate alloc_system;
-
 // compiler-rt intrinsics
 extern crate compiler_builtins;
 
@@ -465,6 +462,7 @@ pub mod path;
 pub mod process;
 pub mod sync;
 pub mod time;
+pub mod heap;
 
 // Platform-abstraction modules
 #[macro_use]
diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs
index 854d380d128..46e5acdf3d2 100644
--- a/src/libstd/sys/unix/mod.rs
+++ b/src/libstd/sys/unix/mod.rs
@@ -59,8 +59,6 @@ pub mod stdio;
 
 #[cfg(not(test))]
 pub fn init() {
-    use alloc::oom;
-
     // By default, some platforms will send a *signal* when an EPIPE error
     // would otherwise be delivered. This runtime doesn't install a SIGPIPE
     // handler, causing it to kill the program, which isn't exactly what we
@@ -72,24 +70,6 @@ pub fn init() {
         reset_sigpipe();
     }
 
-    oom::set_oom_handler(oom_handler);
-
-    // A nicer handler for out-of-memory situations than the default one. This
-    // one prints a message to stderr before aborting. It is critical that this
-    // code does not allocate any memory since we are in an OOM situation. Any
-    // errors are ignored while printing since there's nothing we can do about
-    // them and we are about to exit anyways.
-    fn oom_handler() -> ! {
-        use intrinsics;
-        let msg = "fatal runtime error: out of memory\n";
-        unsafe {
-            libc::write(libc::STDERR_FILENO,
-                        msg.as_ptr() as *const libc::c_void,
-                        msg.len());
-            intrinsics::abort();
-        }
-    }
-
     #[cfg(not(any(target_os = "nacl", target_os = "emscripten", target_os="fuchsia")))]
     unsafe fn reset_sigpipe() {
         assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR);
diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs
index 840e7fdfc9b..ee58efc5144 100644
--- a/src/libstd/sys/windows/mod.rs
+++ b/src/libstd/sys/windows/mod.rs
@@ -47,24 +47,6 @@ pub mod stdio;
 
 #[cfg(not(test))]
 pub fn init() {
-    ::alloc::oom::set_oom_handler(oom_handler);
-
-    // See comment in sys/unix/mod.rs
-    fn oom_handler() -> ! {
-        use intrinsics;
-        use ptr;
-        let msg = "fatal runtime error: out of memory\n";
-        unsafe {
-            // WriteFile silently fails if it is passed an invalid handle, so
-            // there is no need to check the result of GetStdHandle.
-            c::WriteFile(c::GetStdHandle(c::STD_ERROR_HANDLE),
-                         msg.as_ptr() as c::LPVOID,
-                         msg.len() as c::DWORD,
-                         ptr::null_mut(),
-                         ptr::null_mut());
-            intrinsics::abort();
-        }
-    }
 }
 
 pub fn decode_error_kind(errno: i32) -> ErrorKind {