Skip to content

Commit

Permalink
Associate an allocator to boxes
Browse files Browse the repository at this point in the history
This turns `Box<T>` into `Box<T, A = Global>`, with a `A: Alloc` bound
for impls.

Ideally, inherent methods like `Box::new` would be applied to
`Box<T, A: Alloc + Default>`, but as of now, that would be backwards
incompatible because it would require type annotations in places where
they currently aren't required.

`impl FromIterator` is not covered because it relies on `Vec`, which
would need allocator awareness.

`DispatchFromDyn` is left out or being generic over `A` because there
is no bound that would make it work currently. `FnBox` is left out
because it's related to `DispatchFromDyn`.
  • Loading branch information
glandium committed May 3, 2019
1 parent 07a364e commit 4e69e86
Show file tree
Hide file tree
Showing 11 changed files with 252 additions and 122 deletions.
51 changes: 40 additions & 11 deletions src/liballoc/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,35 @@
#![stable(feature = "alloc_module", since = "1.28.0")]

use core::intrinsics::{min_align_of_val, size_of_val};
#[cfg(stage0)]
use core::marker::PhantomData;
use core::ptr::{NonNull, Unique};
use core::usize;

#[stable(feature = "alloc_module", since = "1.28.0")]
#[doc(inline)]
pub use core::alloc::*;

#[cfg(stage0)]
#[unstable(feature = "allocator_api", issue = "32838")]
// pub to make the compiler happy wrt the trait being made public by the impls in e.g. boxed.rs.
pub trait Stage0Alloc = Alloc + Default;

#[cfg(not(stage0))]
pub(crate) use Alloc as Stage0Alloc;

#[cfg(stage0)]
pub(crate) fn stage0_phantom<A>(_a: A) -> PhantomData<A> { PhantomData }

#[cfg(not(stage0))]
pub(crate) fn stage0_phantom<A>(a: A) -> A { a }

#[cfg(stage0)]
pub(crate) fn stage0_unphantom<A: Default>(_a: PhantomData<A>) -> A { A::default() }

#[cfg(not(stage0))]
pub(crate) fn stage0_unphantom<A>(a: A) -> A { a }

extern "Rust" {
// These are the magic symbols to call the global allocator. rustc generates
// them from the `#[global_allocator]` attribute if there is one, or uses the
Expand Down Expand Up @@ -37,10 +59,14 @@ extern "Rust" {
///
/// Note: while this type is unstable, the functionality it provides can be
/// accessed through the [free functions in `alloc`](index.html#functions).
#[cfg(not(test))]
#[unstable(feature = "allocator_api", issue = "32838")]
#[derive(Copy, Clone, Default, Debug)]
pub struct Global;

#[cfg(test)]
pub use std::alloc::Global;

/// Allocate memory with the global allocator.
///
/// This function forwards calls to the [`GlobalAlloc::alloc`] method
Expand Down Expand Up @@ -144,6 +170,7 @@ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 {
__rust_alloc_zeroed(layout.size(), layout.align())
}

#[cfg(not(test))]
#[unstable(feature = "allocator_api", issue = "32838")]
unsafe impl Alloc for Global {
#[inline]
Expand Down Expand Up @@ -182,25 +209,27 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
align as *mut u8
} else {
let layout = Layout::from_size_align_unchecked(size, align);
let ptr = alloc(layout);
if !ptr.is_null() {
ptr
} else {
handle_alloc_error(layout)
match Global.alloc(layout) {
Ok(ptr) => ptr.as_ptr(),
Err(_) => handle_alloc_error(layout),
}
}
}

#[cfg(stage0)]
type BoxFreeAlloc<A> = PhantomData<A>;
#[cfg(not(stage0))]
type BoxFreeAlloc<A> = A;

#[cfg_attr(not(test), lang = "box_free")]
#[inline]
pub(crate) unsafe fn box_free<T: ?Sized>(ptr: Unique<T>) {
let ptr = ptr.as_ptr();
let size = size_of_val(&*ptr);
let align = min_align_of_val(&*ptr);
// We do not allocate for Box<T> when T is ZST, so deallocation is also not necessary.
pub(crate) unsafe fn box_free<T: ?Sized, A: Stage0Alloc>(ptr: Unique<T>, a: BoxFreeAlloc<A>) {
let size = size_of_val(&*ptr.as_ptr());
let align = min_align_of_val(&*ptr.as_ptr());
// We do not allocate for Box<T, A> when T is ZST, so deallocation is also not necessary.
if size != 0 {
let layout = Layout::from_size_align_unchecked(size, align);
dealloc(ptr as *mut u8, layout);
stage0_unphantom(a).dealloc(NonNull::from(ptr).cast(), layout);
}
}

Expand Down
Loading

0 comments on commit 4e69e86

Please sign in to comment.