Skip to content

Commit

Permalink
Make AllocErr a zero-size unit struct
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonSapin committed Apr 12, 2018
1 parent a4caac5 commit ba7081a
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 135 deletions.
32 changes: 16 additions & 16 deletions src/liballoc/alloc.rs
Expand Up @@ -16,7 +16,7 @@
issue = "32838")]

use core::intrinsics::{min_align_of_val, size_of_val};
use core::mem::{self, ManuallyDrop};
use core::mem;
use core::usize;

#[doc(inline)]
Expand Down Expand Up @@ -86,12 +86,12 @@ pub const Heap: Global = Global;
unsafe impl Alloc for Global {
#[inline]
unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
let mut err = ManuallyDrop::new(mem::uninitialized::<AllocErr>());
let mut err = AllocErr;
let ptr = __rust_alloc(layout.size(),
layout.align(),
&mut *err as *mut AllocErr as *mut u8);
&mut err as *mut AllocErr as *mut u8);
if ptr.is_null() {
Err(ManuallyDrop::into_inner(err))
Err(AllocErr)
} else {
Ok(ptr)
}
Expand Down Expand Up @@ -129,15 +129,15 @@ unsafe impl Alloc for Global {
new_layout: Layout)
-> Result<*mut u8, AllocErr>
{
let mut err = ManuallyDrop::new(mem::uninitialized::<AllocErr>());
let mut err = AllocErr;
let ptr = __rust_realloc(ptr,
layout.size(),
layout.align(),
new_layout.size(),
new_layout.align(),
&mut *err as *mut AllocErr as *mut u8);
&mut err as *mut AllocErr as *mut u8);
if ptr.is_null() {
Err(ManuallyDrop::into_inner(err))
Err(AllocErr)
} else {
mem::forget(err);
Ok(ptr)
Expand All @@ -146,27 +146,27 @@ unsafe impl Alloc for Global {

#[inline]
unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
let mut err = ManuallyDrop::new(mem::uninitialized::<AllocErr>());
let mut err = AllocErr;
let ptr = __rust_alloc_zeroed(layout.size(),
layout.align(),
&mut *err as *mut AllocErr as *mut u8);
&mut err as *mut AllocErr as *mut u8);
if ptr.is_null() {
Err(ManuallyDrop::into_inner(err))
Err(AllocErr)
} else {
Ok(ptr)
}
}

#[inline]
unsafe fn alloc_excess(&mut self, layout: Layout) -> Result<Excess, AllocErr> {
let mut err = ManuallyDrop::new(mem::uninitialized::<AllocErr>());
let mut err = AllocErr;
let mut size = 0;
let ptr = __rust_alloc_excess(layout.size(),
layout.align(),
&mut size,
&mut *err as *mut AllocErr as *mut u8);
&mut err as *mut AllocErr as *mut u8);
if ptr.is_null() {
Err(ManuallyDrop::into_inner(err))
Err(AllocErr)
} else {
Ok(Excess(ptr, size))
}
Expand All @@ -177,17 +177,17 @@ unsafe impl Alloc for Global {
ptr: *mut u8,
layout: Layout,
new_layout: Layout) -> Result<Excess, AllocErr> {
let mut err = ManuallyDrop::new(mem::uninitialized::<AllocErr>());
let mut err = AllocErr;
let mut size = 0;
let ptr = __rust_realloc_excess(ptr,
layout.size(),
layout.align(),
new_layout.size(),
new_layout.align(),
&mut size,
&mut *err as *mut AllocErr as *mut u8);
&mut err as *mut AllocErr as *mut u8);
if ptr.is_null() {
Err(ManuallyDrop::into_inner(err))
Err(AllocErr)
} else {
Ok(Excess(ptr, size))
}
Expand Down
2 changes: 1 addition & 1 deletion src/liballoc/raw_vec.rs
Expand Up @@ -760,7 +760,7 @@ mod tests {
unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
let size = layout.size();
if size > self.fuel {
return Err(AllocErr::Unsupported { details: "fuel exhausted" });
return Err(AllocErr);
}
match Global.alloc(layout) {
ok @ Ok(_) => { self.fuel -= size; ok }
Expand Down
25 changes: 3 additions & 22 deletions src/liballoc_jemalloc/lib.rs
Expand Up @@ -30,8 +30,6 @@ extern crate libc;
pub use contents::*;
#[cfg(not(dummy_jemalloc))]
mod contents {
use core::ptr;

use core::alloc::{Alloc, AllocErr, Layout};
use alloc_system::System;
use libc::{c_int, c_void, size_t};
Expand Down Expand Up @@ -106,14 +104,9 @@ mod contents {
#[rustc_std_internal_symbol]
pub unsafe extern fn __rde_alloc(size: usize,
align: usize,
err: *mut u8) -> *mut u8 {
_err: *mut u8) -> *mut u8 {
let flags = align_to_flags(align, size);
let ptr = mallocx(size as size_t, flags) as *mut u8;
if ptr.is_null() {
let layout = Layout::from_size_align_unchecked(size, align);
ptr::write(err as *mut AllocErr,
AllocErr::Exhausted { request: layout });
}
ptr
}

Expand Down Expand Up @@ -155,39 +148,27 @@ mod contents {
old_align: usize,
new_size: usize,
new_align: usize,
err: *mut u8) -> *mut u8 {
_err: *mut u8) -> *mut u8 {
if new_align != old_align {
ptr::write(err as *mut AllocErr,
AllocErr::Unsupported { details: "can't change alignments" });
return 0 as *mut u8
}

let flags = align_to_flags(new_align, new_size);
let ptr = rallocx(ptr as *mut c_void, new_size, flags) as *mut u8;
if ptr.is_null() {
let layout = Layout::from_size_align_unchecked(new_size, new_align);
ptr::write(err as *mut AllocErr,
AllocErr::Exhausted { request: layout });
}
ptr
}

#[no_mangle]
#[rustc_std_internal_symbol]
pub unsafe extern fn __rde_alloc_zeroed(size: usize,
align: usize,
err: *mut u8) -> *mut u8 {
_err: *mut u8) -> *mut u8 {
let ptr = if align <= MIN_ALIGN && align <= size {
calloc(size as size_t, 1) as *mut u8
} else {
let flags = align_to_flags(align, size) | MALLOCX_ZERO;
mallocx(size as size_t, flags) as *mut u8
};
if ptr.is_null() {
let layout = Layout::from_size_align_unchecked(size, align);
ptr::write(err as *mut AllocErr,
AllocErr::Exhausted { request: layout });
}
ptr
}

Expand Down
24 changes: 9 additions & 15 deletions src/liballoc_system/lib.rs
Expand Up @@ -133,17 +133,15 @@ mod platform {
#[cfg(target_os = "macos")]
{
if layout.align() > (1 << 31) {
return Err(AllocErr::Unsupported {
details: "requested alignment too large"
})
return Err(AllocErr)
}
}
aligned_malloc(&layout)
};
if !ptr.is_null() {
Ok(ptr)
} else {
Err(AllocErr::Exhausted { request: layout })
Err(AllocErr)
}
}

Expand All @@ -156,7 +154,7 @@ mod platform {
if !ptr.is_null() {
Ok(ptr)
} else {
Err(AllocErr::Exhausted { request: layout })
Err(AllocErr)
}
} else {
let ret = self.alloc(layout.clone());
Expand All @@ -178,17 +176,15 @@ mod platform {
old_layout: Layout,
new_layout: Layout) -> Result<*mut u8, AllocErr> {
if old_layout.align() != new_layout.align() {
return Err(AllocErr::Unsupported {
details: "cannot change alignment on `realloc`",
})
return Err(AllocErr)
}

if new_layout.align() <= MIN_ALIGN && new_layout.align() <= new_layout.size(){
let ptr = libc::realloc(ptr as *mut libc::c_void, new_layout.size());
if !ptr.is_null() {
Ok(ptr as *mut u8)
} else {
Err(AllocErr::Exhausted { request: new_layout })
Err(AllocErr)
}
} else {
let res = self.alloc(new_layout.clone());
Expand Down Expand Up @@ -342,7 +338,7 @@ mod platform {
}
};
if ptr.is_null() {
Err(AllocErr::Exhausted { request: layout })
Err(AllocErr)
} else {
Ok(ptr as *mut u8)
}
Expand Down Expand Up @@ -382,9 +378,7 @@ mod platform {
old_layout: Layout,
new_layout: Layout) -> Result<*mut u8, AllocErr> {
if old_layout.align() != new_layout.align() {
return Err(AllocErr::Unsupported {
details: "cannot change alignment on `realloc`",
})
return Err(AllocErr)
}

if new_layout.align() <= MIN_ALIGN {
Expand All @@ -395,7 +389,7 @@ mod platform {
if !ptr.is_null() {
Ok(ptr as *mut u8)
} else {
Err(AllocErr::Exhausted { request: new_layout })
Err(AllocErr)
}
} else {
let res = self.alloc(new_layout.clone());
Expand Down Expand Up @@ -505,7 +499,7 @@ mod platform {
if !ptr.is_null() {
Ok(ptr)
} else {
Err(AllocErr::Unsupported { details: "" })
Err(AllocErr)
}
}

Expand Down
58 changes: 8 additions & 50 deletions src/libcore/alloc.rs
Expand Up @@ -320,50 +320,12 @@ impl Layout {
/// something wrong when combining the given input arguments with this
/// allocator.
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum AllocErr {
/// Error due to hitting some resource limit or otherwise running
/// out of memory. This condition strongly implies that *some*
/// series of deallocations would allow a subsequent reissuing of
/// the original allocation request to succeed.
Exhausted { request: Layout },

/// Error due to allocator being fundamentally incapable of
/// satisfying the original request. This condition implies that
/// such an allocation request will never succeed on the given
/// allocator, regardless of environment, memory pressure, or
/// other contextual conditions.
///
/// For example, an allocator that does not support requests for
/// large memory blocks might return this error variant.
Unsupported { details: &'static str },
}

impl AllocErr {
#[inline]
pub fn invalid_input(details: &'static str) -> Self {
AllocErr::Unsupported { details: details }
}
#[inline]
pub fn is_memory_exhausted(&self) -> bool {
if let AllocErr::Exhausted { .. } = *self { true } else { false }
}
#[inline]
pub fn is_request_unsupported(&self) -> bool {
if let AllocErr::Unsupported { .. } = *self { true } else { false }
}
#[inline]
pub fn description(&self) -> &str {
match *self {
AllocErr::Exhausted { .. } => "allocator memory exhausted",
AllocErr::Unsupported { .. } => "unsupported allocator request",
}
}
}
pub struct AllocErr;

// (we need this for downstream impl of trait Error)
impl fmt::Display for AllocErr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.description())
f.write_str("memory allocation failed")
}
}

Expand Down Expand Up @@ -592,12 +554,8 @@ pub unsafe trait Alloc {
/// aborting.
///
/// `oom` is meant to be used by clients unable to cope with an
/// unsatisfied allocation request (signaled by an error such as
/// `AllocErr::Exhausted`), and wish to abandon computation rather
/// than attempt to recover locally. Such clients should pass the
/// signaling error value back into `oom`, where the allocator
/// may incorporate that error value into its diagnostic report
/// before aborting.
/// unsatisfied allocation request, and wish to abandon
/// computation rather than attempt to recover locally.
///
/// Implementations of the `oom` method are discouraged from
/// infinitely regressing in nested calls to `oom`. In
Expand Down Expand Up @@ -963,7 +921,7 @@ pub unsafe trait Alloc {
if k.size() > 0 {
unsafe { self.alloc(k).map(|p| NonNull::new_unchecked(p as *mut T)) }
} else {
Err(AllocErr::invalid_input("zero-sized type invalid for alloc_one"))
Err(AllocErr)
}
}

Expand Down Expand Up @@ -1036,7 +994,7 @@ pub unsafe trait Alloc {
})
}
}
_ => Err(AllocErr::invalid_input("invalid layout for alloc_array")),
_ => Err(AllocErr),
}
}

Expand Down Expand Up @@ -1084,7 +1042,7 @@ pub unsafe trait Alloc {
.map(|p| NonNull::new_unchecked(p as *mut T))
}
_ => {
Err(AllocErr::invalid_input("invalid layout for realloc_array"))
Err(AllocErr)
}
}
}
Expand Down Expand Up @@ -1118,7 +1076,7 @@ pub unsafe trait Alloc {
Ok(self.dealloc(raw_ptr, k.clone()))
}
_ => {
Err(AllocErr::invalid_input("invalid layout for dealloc_array"))
Err(AllocErr)
}
}
}
Expand Down

0 comments on commit ba7081a

Please sign in to comment.