diff --git a/oscars/src/collectors/mark_sweep/pointers/gc.rs b/oscars/src/collectors/mark_sweep/pointers/gc.rs index c9e6de2..55579b7 100644 --- a/oscars/src/collectors/mark_sweep/pointers/gc.rs +++ b/oscars/src/collectors/mark_sweep/pointers/gc.rs @@ -51,6 +51,44 @@ impl Gc { marker: PhantomData, } } + + pub fn ptr_eq(this: &Self, other: &Gc) -> bool { + this.inner_ptr.as_non_null() == other.inner_ptr.as_non_null() + } + + pub fn size(&self) -> usize { + self.inner_ref().size() + } + + pub fn type_id(&self) -> TypeId { + self.inner_ref().type_id() + } + + pub fn is(this: &Self) -> bool { + Self::type_id(this) == TypeId::of::() + } + + pub fn downcast(this: Self) -> Option> { + if !Gc::is::(&this) { + return None; + } + // Safety: We've validated that the type of `this` is correct above. + Some(unsafe { Gc::cast_unchecked::(this) }) + } + + /// Cast the `Gc` from `T` to `U` + /// + /// # Safety + /// + /// Caller must ensure that `U` is valid for `this`. + #[inline] + #[must_use] + pub unsafe fn cast_unchecked(this: Self) -> Gc { + Gc { + inner_ptr: this.inner_ptr, + marker: PhantomData, + } + } } impl Gc { @@ -60,10 +98,6 @@ impl Gc { } impl Gc { - pub fn ptr_eq(this: &Self, other: &Gc) -> bool { - this.inner_ptr.as_non_null() == other.inner_ptr.as_non_null() - } - pub(crate) fn as_sized_inner_ptr(&self) -> NonNull> { // SAFETY: use `&raw mut` to get a raw pointer without creating // a `&mut` reference, avoiding Stacked Borrows UB during GC tracing @@ -82,18 +116,6 @@ impl Gc { pub(crate) fn inner_ref(&self) -> &GcBox { unsafe { self.as_sized_inner_ptr().as_ref() } } - - pub fn size(&self) -> usize { - self.inner_ref().size() - } - - pub fn type_id(&self) -> TypeId { - self.inner_ref().type_id() - } - - pub fn is(this: &Self) -> bool { - Self::type_id(this) == TypeId::of::() - } } impl Deref for Gc { diff --git a/oscars/src/collectors/mark_sweep_arena2/pointers/gc.rs b/oscars/src/collectors/mark_sweep_arena2/pointers/gc.rs index 199ecb8..1f4623b 100644 --- a/oscars/src/collectors/mark_sweep_arena2/pointers/gc.rs +++ b/oscars/src/collectors/mark_sweep_arena2/pointers/gc.rs @@ -43,7 +43,7 @@ impl Gc { this.inner_ptr() } - /// Creates a `Gc` from the provided [`PoolPointer`]. + /// Creates a `Gc` from the provided [`ArenaPointer`]. /// /// # Safety /// @@ -54,6 +54,45 @@ impl Gc { marker: PhantomData, } } + + pub fn ptr_eq(this: &Self, other: &Gc) -> bool { + this.inner_ptr.as_non_null() == other.inner_ptr.as_non_null() + } + + pub fn size(&self) -> usize { + self.inner_ref().size() + } + + pub fn type_id(&self) -> TypeId { + self.inner_ref().type_id() + } + + pub fn is(this: &Self) -> bool { + Self::type_id(this) == TypeId::of::() + } + + #[inline] + pub fn downcast(this: Self) -> Option> { + if !Gc::is::(&this) { + return None; + } + // Safety: We've validated that the type of `this` is correct above. + Some(unsafe { Gc::cast_unchecked::(this) }) + } + + /// Cast the `Gc` from `T` to `U` + /// + /// # Safety + /// + /// Caller must ensure that `U` is valid for `this`. + #[inline] + #[must_use] + pub unsafe fn cast_unchecked(this: Self) -> Gc { + Gc { + inner_ptr: this.inner_ptr, + marker: PhantomData, + } + } } impl Gc { @@ -63,10 +102,6 @@ impl Gc { } impl Gc { - pub fn ptr_eq(this: &Self, other: &Gc) -> bool { - this.inner_ptr.as_non_null() == other.inner_ptr.as_non_null() - } - pub(crate) fn as_sized_inner_ptr(&self) -> NonNull> { // SAFETY: `&raw mut` prevents creating `&mut` reference into the // arena to avoid stacked borrows during Gc tracing @@ -84,18 +119,6 @@ impl Gc { pub(crate) fn inner_ref(&self) -> &GcBox { unsafe { self.as_sized_inner_ptr().as_ref() } } - - pub fn size(&self) -> usize { - self.inner_ref().size() - } - - pub fn type_id(&self) -> TypeId { - self.inner_ref().type_id() - } - - pub fn is(this: &Self) -> bool { - Self::type_id(this) == TypeId::of::() - } } impl Deref for Gc {