Merge pull request #236 from japaric/lazy-init-anchor

CAS Pool x86_64: lazily initialized ANCHOR
This commit is contained in:
Emil Fresk 2021-08-26 15:43:12 +02:00 committed by GitHub
commit 59bc89f297
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 25 additions and 5 deletions

View File

@ -35,6 +35,9 @@ atomic-polyfill = { version = "0.1.2", optional = true }
[dependencies] [dependencies]
hash32 = "0.2.1" hash32 = "0.2.1"
[target.'cfg(target_arch = "x86_64")'.dependencies]
spin = "0.9.2"
[dependencies.serde] [dependencies.serde]
version = "1" version = "1"
optional = true optional = true

View File

@ -87,9 +87,26 @@ impl<T> Stack<T> {
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
fn anchor<T>() -> *mut T { fn anchor<T>(init: Option<*mut T>) -> *mut T {
static mut ANCHOR: u8 = 0; use core::sync::atomic::AtomicU8;
(unsafe { &mut ANCHOR } as *mut u8 as usize & !(core::mem::align_of::<T>() - 1)) as *mut T
use spin::Once;
static LAZY_ANCHOR: Once<usize> = Once::new();
let likely_unaligned_address = if let Some(init) = init {
*LAZY_ANCHOR.call_once(|| init as usize)
} else {
LAZY_ANCHOR.get().copied().unwrap_or_else(|| {
// we may hit this branch with Pool of ZSTs where `grow` does not need to be called
static BSS_ANCHOR: AtomicU8 = AtomicU8::new(0);
&BSS_ANCHOR as *const _ as usize
})
};
let alignment_mask = !(core::mem::align_of::<T>() - 1);
let well_aligned_address = likely_unaligned_address & alignment_mask;
well_aligned_address as *mut T
} }
/// On x86_64, anchored pointer. This is a (signed) 32-bit offset from `anchor` plus a 32-bit tag /// On x86_64, anchored pointer. This is a (signed) 32-bit offset from `anchor` plus a 32-bit tag
@ -116,7 +133,7 @@ impl<T> Ptr<T> {
pub fn new(p: *mut T) -> Option<Self> { pub fn new(p: *mut T) -> Option<Self> {
use core::convert::TryFrom; use core::convert::TryFrom;
i32::try_from((p as isize).wrapping_sub(anchor::<T>() as isize)) i32::try_from((p as isize).wrapping_sub(anchor::<T>(Some(p)) as isize))
.ok() .ok()
.map(|offset| unsafe { Ptr::from_parts(initial_tag_value(), offset) }) .map(|offset| unsafe { Ptr::from_parts(initial_tag_value(), offset) })
} }
@ -166,7 +183,7 @@ impl<T> Ptr<T> {
fn as_raw(&self) -> NonNull<T> { fn as_raw(&self) -> NonNull<T> {
unsafe { unsafe {
NonNull::new_unchecked( NonNull::new_unchecked(
(anchor::<T>() as *mut u8).offset(self.offset() as isize) as *mut T (anchor::<T>(None) as *mut u8).offset(self.offset() as isize) as *mut T,
) )
} }
} }