1
Fork 0

Refactor tagged ptr packing into a function

This commit is contained in:
Maybe Waffle 2023-04-11 21:40:39 +00:00
parent 3c6f4c1260
commit 12fd610e01

View file

@ -50,6 +50,10 @@ where
P: Pointer, P: Pointer,
T: Tag, T: Tag,
{ {
pub fn new(pointer: P, tag: T) -> Self {
Self { packed: Self::pack(P::into_ptr(pointer), tag), data: PhantomData }
}
const TAG_BIT_SHIFT: usize = usize::BITS as usize - T::BITS; const TAG_BIT_SHIFT: usize = usize::BITS as usize - T::BITS;
const ASSERTION: () = { const ASSERTION: () = {
assert!(T::BITS <= P::BITS); assert!(T::BITS <= P::BITS);
@ -58,14 +62,16 @@ where
assert!(std::mem::size_of::<&P::Target>() == std::mem::size_of::<usize>()); assert!(std::mem::size_of::<&P::Target>() == std::mem::size_of::<usize>());
}; };
pub fn new(pointer: P, tag: T) -> Self { /// Pack pointer `ptr` that comes from [`P::into_ptr`] with a `tag`.
///
/// [`P::into_ptr`]: Pointer::into_ptr
fn pack(ptr: NonNull<P::Target>, tag: T) -> NonNull<P::Target> {
// Trigger assert! // Trigger assert!
let () = Self::ASSERTION; let () = Self::ASSERTION;
let packed_tag = tag.into_usize() << Self::TAG_BIT_SHIFT; let packed_tag = tag.into_usize() << Self::TAG_BIT_SHIFT;
Self { ptr.map_addr(|addr| {
packed: P::into_ptr(pointer).map_addr(|addr| {
// SAFETY: // SAFETY:
// - The pointer is `NonNull` => it's address is `NonZeroUsize` // - The pointer is `NonNull` => it's address is `NonZeroUsize`
// - `P::BITS` least significant bits are always zero (`Pointer` contract) // - `P::BITS` least significant bits are always zero (`Pointer` contract)
@ -77,9 +83,7 @@ where
let packed = (addr.get() >> T::BITS) | packed_tag; let packed = (addr.get() >> T::BITS) | packed_tag;
unsafe { NonZeroUsize::new_unchecked(packed) } unsafe { NonZeroUsize::new_unchecked(packed) }
}), })
data: PhantomData,
}
} }
pub(super) fn pointer_raw(&self) -> NonNull<P::Target> { pub(super) fn pointer_raw(&self) -> NonNull<P::Target> {
@ -117,12 +121,7 @@ where
#[inline] #[inline]
pub fn set_tag(&mut self, tag: T) { pub fn set_tag(&mut self, tag: T) {
// TODO: refactor packing into a function and reuse it here self.packed = Self::pack(self.pointer_raw(), tag);
let new_tag = T::into_usize(tag) << Self::TAG_BIT_SHIFT;
let tag_mask = (1 << T::BITS) - 1;
self.packed = self.packed.map_addr(|addr| unsafe {
NonZeroUsize::new_unchecked(addr.get() & !(tag_mask << Self::TAG_BIT_SHIFT) | new_tag)
});
} }
} }