Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 38 additions & 16 deletions oscars/src/collectors/mark_sweep/pointers/gc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,44 @@ impl<T: Trace> Gc<T> {
marker: PhantomData,
}
}

pub fn ptr_eq<U: Trace + ?Sized>(this: &Self, other: &Gc<U>) -> 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<U: Trace + 'static>(this: &Self) -> bool {
Self::type_id(this) == TypeId::of::<U>()
}

pub fn downcast<U: Trace + 'static>(this: Self) -> Option<Gc<U>> {
if !Gc::is::<U>(&this) {
return None;
}
// Safety: We've validated that the type of `this` is correct above.
Some(unsafe { Gc::cast_unchecked::<U>(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<U: Trace + 'static>(this: Self) -> Gc<U> {
Gc {
inner_ptr: this.inner_ptr,
marker: PhantomData,
}
}
}

impl<T: Trace> Gc<T> {
Expand All @@ -60,10 +98,6 @@ impl<T: Trace> Gc<T> {
}

impl<T: Trace + ?Sized> Gc<T> {
pub fn ptr_eq<U: Trace + ?Sized>(this: &Self, other: &Gc<U>) -> bool {
this.inner_ptr.as_non_null() == other.inner_ptr.as_non_null()
}

pub(crate) fn as_sized_inner_ptr(&self) -> NonNull<GcBox<NonTraceable>> {
// SAFETY: use `&raw mut` to get a raw pointer without creating
// a `&mut` reference, avoiding Stacked Borrows UB during GC tracing
Expand All @@ -82,18 +116,6 @@ impl<T: Trace + ?Sized> Gc<T> {
pub(crate) fn inner_ref(&self) -> &GcBox<NonTraceable> {
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<U: Trace + 'static>(this: &Self) -> bool {
Self::type_id(this) == TypeId::of::<U>()
}
}

impl<T: Trace> Deref for Gc<T> {
Expand Down
57 changes: 40 additions & 17 deletions oscars/src/collectors/mark_sweep_arena2/pointers/gc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ impl<T: Trace> Gc<T> {
this.inner_ptr()
}

/// Creates a `Gc` from the provided [`PoolPointer`].
/// Creates a `Gc` from the provided [`ArenaPointer`].
///
/// # Safety
///
Expand All @@ -54,6 +54,45 @@ impl<T: Trace> Gc<T> {
marker: PhantomData,
}
}

pub fn ptr_eq<U: Trace + ?Sized>(this: &Self, other: &Gc<U>) -> 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<U: Trace + 'static>(this: &Self) -> bool {
Self::type_id(this) == TypeId::of::<U>()
}

#[inline]
pub fn downcast<U: Trace + 'static>(this: Self) -> Option<Gc<U>> {
if !Gc::is::<U>(&this) {
return None;
}
// Safety: We've validated that the type of `this` is correct above.
Some(unsafe { Gc::cast_unchecked::<U>(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<U: Trace + 'static>(this: Self) -> Gc<U> {
Gc {
inner_ptr: this.inner_ptr,
marker: PhantomData,
}
}
}

impl<T: Trace> Gc<T> {
Expand All @@ -63,10 +102,6 @@ impl<T: Trace> Gc<T> {
}

impl<T: Trace + ?Sized> Gc<T> {
pub fn ptr_eq<U: Trace + ?Sized>(this: &Self, other: &Gc<U>) -> bool {
this.inner_ptr.as_non_null() == other.inner_ptr.as_non_null()
}

pub(crate) fn as_sized_inner_ptr(&self) -> NonNull<GcBox<NonTraceable>> {
// SAFETY: `&raw mut` prevents creating `&mut` reference into the
// arena to avoid stacked borrows during Gc tracing
Expand All @@ -84,18 +119,6 @@ impl<T: Trace + ?Sized> Gc<T> {
pub(crate) fn inner_ref(&self) -> &GcBox<NonTraceable> {
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<U: Trace + 'static>(this: &Self) -> bool {
Self::type_id(this) == TypeId::of::<U>()
}
}

impl<T: Trace> Deref for Gc<T> {
Expand Down