Skip to content

Add support for bumpalo #231

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 2 commits into from
Jan 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ core = { version = "1.0.0", optional = true, package = "rustc-std-workspace-core
compiler_builtins = { version = "0.1.2", optional = true }
alloc = { version = "1.0.0", optional = true, package = "rustc-std-workspace-alloc" }

# Optional support for bumpalo
bumpalo = { version = "3.5.0", optional = true }

[dev-dependencies]
lazy_static = "1.4"
rand = { version = "0.7.3", features = ["small_rng"] }
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ This crate has the following Cargo features:
- `raw`: Enables access to the experimental and unsafe `RawTable` API.
- `inline-more`: Adds inline hints to most functions, improving run-time performance at the cost
of compilation time. (enabled by default)
- `bumpalo`: Provides a `BumpWrapper` type which allows `bumpalo` to be used for memory allocation.
- `ahash`: Compiles with ahash as default hasher. (enabled by default)
- `ahash-compile-time-rng`: Activates the `compile-time-rng` feature of ahash. For targets with no random number generator
this pre-generates seeds at compile time and embeds them as constants. See [aHash's documentation](https://github.com/tkaitchuck/aHash#flags) (disabled by default)
Expand Down
2 changes: 1 addition & 1 deletion ci/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ if [ "${NO_STD}" = "1" ]; then
FEATURES="rustc-internal-api"
OP="build"
else
FEATURES="rustc-internal-api,serde,rayon,raw"
FEATURES="rustc-internal-api,serde,rayon,raw,bumpalo"
OP="test"
fi
if [ "${TRAVIS_RUST_VERSION}" = "nightly" ]; then
Expand Down
21 changes: 20 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
min_specialization,
extend_one,
allocator_api,
slice_ptr_get
slice_ptr_get,
nonnull_slice_from_raw_parts
)
)]
#![allow(
Expand Down Expand Up @@ -124,3 +125,21 @@ pub enum TryReserveError {
layout: alloc::alloc::Layout,
},
}

/// Wrapper around `Bump` which allows it to be used as an allocator for
/// `HashMap`, `HashSet` and `RawTable`.
///
/// `Bump` can be used directly without this wrapper on nightly if you enable
/// the `allocator-api` feature of the `bumpalo` crate.
#[cfg(feature = "bumpalo")]
#[derive(Clone, Copy, Debug)]
pub struct BumpWrapper<'a>(&'a bumpalo::Bump);

#[cfg(feature = "bumpalo")]
#[test]
fn test_bumpalo() {
use bumpalo::Bump;
let bump = Bump::new();
let mut map = HashMap::new_in(BumpWrapper(&bump));
map.insert(0, 1);
}
36 changes: 29 additions & 7 deletions src/raw/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,38 +13,60 @@ mod inner {
.map(|ptr| ptr.as_non_null_ptr())
.map_err(|_| ())
}

#[cfg(feature = "bumpalo")]
unsafe impl Allocator for crate::BumpWrapper<'_> {
#[inline]
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, core::alloc::AllocError> {
match self.0.try_alloc_layout(layout) {
Ok(ptr) => Ok(NonNull::slice_from_raw_parts(ptr, layout.size())),
Err(_) => Err(core::alloc::AllocError),
}
}
#[inline]
unsafe fn deallocate(&self, _ptr: NonNull<u8>, _layout: Layout) {}
}
}

#[cfg(not(feature = "nightly"))]
mod inner {
use crate::alloc::alloc::{alloc, dealloc, Layout};
use core::ptr::NonNull;

pub struct AllocError;

pub unsafe trait Allocator {
fn allocate(&self, layout: Layout) -> Result<NonNull<u8>, AllocError>;
fn allocate(&self, layout: Layout) -> Result<NonNull<u8>, ()>;
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout);
}

#[derive(Copy, Clone)]
pub struct Global;
unsafe impl Allocator for Global {
fn allocate(&self, layout: Layout) -> Result<NonNull<u8>, AllocError> {
unsafe { NonNull::new(alloc(layout)).ok_or(AllocError) }
#[inline]
fn allocate(&self, layout: Layout) -> Result<NonNull<u8>, ()> {
unsafe { NonNull::new(alloc(layout)).ok_or(()) }
}
#[inline]
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
dealloc(ptr.as_ptr(), layout)
}
}
impl Default for Global {
#[inline]
fn default() -> Self {
Global
}
}

#[allow(clippy::map_err_ignore)]
pub fn do_alloc<A: Allocator>(alloc: &A, layout: Layout) -> Result<NonNull<u8>, ()> {
alloc.allocate(layout).map_err(|_| ())
alloc.allocate(layout)
}

#[cfg(feature = "bumpalo")]
unsafe impl Allocator for crate::BumpWrapper<'_> {
#[allow(clippy::map_err_ignore)]
fn allocate(&self, layout: Layout) -> Result<NonNull<u8>, ()> {
self.0.try_alloc_layout(layout).map_err(|_| ())
}
unsafe fn deallocate(&self, _ptr: NonNull<u8>, _layout: Layout) {}
}
}
3 changes: 1 addition & 2 deletions src/raw/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1989,8 +1989,7 @@ impl<T, A: Allocator + Clone> Drop for RawIntoIter<T, A> {

// Free the table
if let Some((ptr, layout)) = self.allocation {
self.alloc
.deallocate(NonNull::new_unchecked(ptr.as_ptr()), layout);
self.alloc.deallocate(ptr, layout);
}
}
}
Expand Down