From a4c0c6aff048141b1e61e6ba51ada90f7b071ca7 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Thu, 21 Jan 2021 17:38:55 +0000 Subject: [PATCH 1/2] Add support for bumpalo --- Cargo.toml | 3 +++ README.md | 1 + src/lib.rs | 12 +++++++++++- src/raw/alloc.rs | 36 +++++++++++++++++++++++++++++------- src/raw/mod.rs | 3 +-- 5 files changed, 45 insertions(+), 10 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 719932aff9..91e2e1e90c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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"] } diff --git a/README.md b/README.md index 3ce3d507b5..939dfee107 100644 --- a/README.md +++ b/README.md @@ -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) diff --git a/src/lib.rs b/src/lib.rs index b8f2322bef..2b49521268 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,7 +19,8 @@ min_specialization, extend_one, allocator_api, - slice_ptr_get + slice_ptr_get, + nonnull_slice_from_raw_parts ) )] #![allow( @@ -124,3 +125,12 @@ 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); diff --git a/src/raw/alloc.rs b/src/raw/alloc.rs index 20fcd1cd0f..de6c455064 100644 --- a/src/raw/alloc.rs +++ b/src/raw/alloc.rs @@ -13,6 +13,19 @@ 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, 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, _layout: Layout) {} + } } #[cfg(not(feature = "nightly"))] @@ -20,31 +33,40 @@ 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, AllocError>; + fn allocate(&self, layout: Layout) -> Result, ()>; unsafe fn deallocate(&self, ptr: NonNull, layout: Layout); } #[derive(Copy, Clone)] pub struct Global; unsafe impl Allocator for Global { - fn allocate(&self, layout: Layout) -> Result, AllocError> { - unsafe { NonNull::new(alloc(layout)).ok_or(AllocError) } + #[inline] + fn allocate(&self, layout: Layout) -> Result, ()> { + unsafe { NonNull::new(alloc(layout)).ok_or(()) } } + #[inline] unsafe fn deallocate(&self, ptr: NonNull, 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(alloc: &A, layout: Layout) -> Result, ()> { - 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, ()> { + self.0.try_alloc_layout(layout).map_err(|_| ()) + } + unsafe fn deallocate(&self, _ptr: NonNull, _layout: Layout) {} } } diff --git a/src/raw/mod.rs b/src/raw/mod.rs index ca575a149c..d5e312c674 100644 --- a/src/raw/mod.rs +++ b/src/raw/mod.rs @@ -1989,8 +1989,7 @@ impl Drop for RawIntoIter { // 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); } } } From 5467e3f3f44173674f453e4b80b38997f365fb84 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Tue, 26 Jan 2021 23:23:29 +0000 Subject: [PATCH 2/2] Add test for bumpalo --- ci/run.sh | 2 +- src/lib.rs | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/ci/run.sh b/ci/run.sh index 5b75fd1183..4e0a5a59d0 100644 --- a/ci/run.sh +++ b/ci/run.sh @@ -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 diff --git a/src/lib.rs b/src/lib.rs index 2b49521268..b1c98a8046 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -134,3 +134,12 @@ pub enum TryReserveError { #[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); +}