use core::mem;
use crate::{
collect::{Collect, Trace},
context::Mutation,
gc::Gc,
};
#[derive(Copy, Clone)]
pub struct ZstCache<'gc, const MAX_ALIGN: usize> {
cached_ptr: Gc<'gc, ()>,
}
unsafe impl<'gc, const MAX_ALIGN: usize> Collect<'gc> for ZstCache<'gc, MAX_ALIGN> {
const NEEDS_TRACE: bool = true;
fn trace<T: Trace<'gc>>(&self, cc: &mut T) {
cc.trace_gc(self.cached_ptr);
}
}
impl<'gc, const MAX_ALIGN: usize> ZstCache<'gc, MAX_ALIGN>
where
Alignment<MAX_ALIGN>: ValidAlignment,
{
pub fn new(mc: &Mutation<'gc>) -> Self {
let cached_ptr = Gc::erase(Gc::new_static(
mc,
<Alignment<MAX_ALIGN> as HasAlignedType>::AlignedType::default(),
));
ZstCache { cached_ptr }
}
pub fn cached_ptr(&self) -> Gc<'gc, ()> {
self.cached_ptr
}
#[inline]
pub fn is_cached<T: ?Sized>(&self, p: Gc<'gc, T>) -> bool {
Gc::ptr_eq(self.cached_ptr, Gc::erase(p))
}
#[inline]
pub fn alloc_zst<T: 'gc>(&self) -> Option<Gc<'gc, T>> {
if mem::size_of::<T>() == 0 && mem::align_of::<T>() <= MAX_ALIGN {
debug_assert!(Gc::as_ptr(self.cached_ptr).align_offset(mem::align_of::<T>()) == 0);
Some(unsafe { Gc::cast::<T>(self.cached_ptr) })
} else {
None
}
}
#[inline]
pub fn alloc<T: Collect<'gc>>(&self, mc: &Mutation<'gc>, t: T) -> Gc<'gc, T> {
if let Some(ptr) = self.alloc_zst() {
ptr
} else {
Gc::new(mc, t)
}
}
#[inline]
pub fn alloc_static<T: 'static>(&self, mc: &Mutation<'gc>, t: T) -> Gc<'gc, T> {
if let Some(ptr) = self.alloc_zst() {
ptr
} else {
Gc::new_static(mc, t)
}
}
}
pub struct Alignment<const ALIGN: usize>;
#[allow(private_bounds)]
pub trait ValidAlignment: HasAlignedType {}
impl<T: HasAlignedType> ValidAlignment for T {}
trait HasAlignedType {
type AlignedType: Default;
}
macro_rules! impl_has_aligned_type {
($($align:expr),* $(,)?) => {
$(
const _: () = {
#[repr(align($align))]
struct AlignedType;
impl Default for AlignedType {
#[inline(always)]
fn default() -> Self {
Self
}
}
impl HasAlignedType for Alignment<$align> {
type AlignedType = AlignedType;
}
};
)*
};
}
impl_has_aligned_type!(
1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072,
262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728,
268435456, 536870912
);