Refactor tagged ptr packing into a function
This commit is contained in:
parent
3c6f4c1260
commit
12fd610e01
1 changed files with 21 additions and 22 deletions
|
@ -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)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue