From 59de8f37e00e1d053f19ee06edde5c3c7cd0fcb6 Mon Sep 17 00:00:00 2001 From: Kevin Ness Date: Thu, 26 Mar 2026 23:10:19 -0500 Subject: [PATCH] Implement upgrade method plus fix issue with previous PRs --- .../src/collectors/mark_sweep/internals/ephemeron.rs | 10 ++++++++++ oscars/src/collectors/mark_sweep/pointers/gc.rs | 8 ++++++-- oscars/src/collectors/mark_sweep/pointers/weak.rs | 7 ++++++- .../mark_sweep_arena2/internals/ephemeron.rs | 10 ++++++++++ oscars/src/collectors/mark_sweep_arena2/pointers/gc.rs | 8 ++++++-- .../src/collectors/mark_sweep_arena2/pointers/weak.rs | 6 +++++- 6 files changed, 43 insertions(+), 6 deletions(-) diff --git a/oscars/src/collectors/mark_sweep/internals/ephemeron.rs b/oscars/src/collectors/mark_sweep/internals/ephemeron.rs index 4a927fd..52b389c 100644 --- a/oscars/src/collectors/mark_sweep/internals/ephemeron.rs +++ b/oscars/src/collectors/mark_sweep/internals/ephemeron.rs @@ -47,6 +47,16 @@ impl Ephemeron { None } + pub fn upgrade(&self) -> Option> { + self.key.inner_ptr().map(|ptr| { + // Increment the roots, since we are creating a new root. + ptr.as_inner_ref().inc_roots(); + // Safety: This is safe because WeakGc's collection insures + // the liveliness of the underlying pointer + unsafe { Gc::from_raw(ptr) } + }) + } + pub fn is_reachable(&self, color: TraceColor) -> bool { self.key.is_reachable(color) } diff --git a/oscars/src/collectors/mark_sweep/pointers/gc.rs b/oscars/src/collectors/mark_sweep/pointers/gc.rs index 55579b7..c7d6bfd 100644 --- a/oscars/src/collectors/mark_sweep/pointers/gc.rs +++ b/oscars/src/collectors/mark_sweep/pointers/gc.rs @@ -37,7 +37,9 @@ impl Gc { /// Converts a `Gc` into a raw [`PoolPointer`]. pub fn into_raw(this: Self) -> PoolPointer<'static, GcBox> { - this.inner_ptr() + let ptr = this.inner_ptr(); + core::mem::forget(this); + ptr } /// Creates a `Gc` from the provided [`PoolPointer`]. @@ -84,8 +86,10 @@ impl Gc { #[inline] #[must_use] pub unsafe fn cast_unchecked(this: Self) -> Gc { + let inner_ptr = this.inner_ptr; + core::mem::forget(this); Gc { - inner_ptr: this.inner_ptr, + inner_ptr, marker: PhantomData, } } diff --git a/oscars/src/collectors/mark_sweep/pointers/weak.rs b/oscars/src/collectors/mark_sweep/pointers/weak.rs index b4a333c..fa1aa8a 100644 --- a/oscars/src/collectors/mark_sweep/pointers/weak.rs +++ b/oscars/src/collectors/mark_sweep/pointers/weak.rs @@ -3,7 +3,7 @@ // optimized in the future use crate::{ alloc::mempool3::PoolPointer, - collectors::mark_sweep::{Collector, Trace, internals::Ephemeron}, + collectors::mark_sweep::{Collector, Gc, Trace, internals::Ephemeron}, }; #[repr(transparent)] @@ -26,7 +26,12 @@ impl WeakGc { Self { inner_ptr } } + /// Returns the value of this [`WeakGc`] if the underlying value is alive. pub fn value(&self) -> Option<&T> { self.inner_ptr.as_inner_ref().key() } + + pub fn upgrade(&self) -> Option> { + self.inner_ptr.as_inner_ref().upgrade() + } } diff --git a/oscars/src/collectors/mark_sweep_arena2/internals/ephemeron.rs b/oscars/src/collectors/mark_sweep_arena2/internals/ephemeron.rs index 533a08c..793fd0b 100644 --- a/oscars/src/collectors/mark_sweep_arena2/internals/ephemeron.rs +++ b/oscars/src/collectors/mark_sweep_arena2/internals/ephemeron.rs @@ -50,6 +50,16 @@ impl Ephemeron { pub(crate) fn invalidate(&self) { self.active.set(false); } + + pub fn upgrade(&self) -> Option> { + self.key.inner_ptr().map(|ptr| { + // Increment the root by one since we are upgrading this value. + ptr.as_inner_ref().inc_roots(); + // Safety: This is safe because WeakGc's collection insures + // the liveliness of the underlying pointer + unsafe { Gc::from_raw(ptr) } + }) + } } impl Ephemeron { diff --git a/oscars/src/collectors/mark_sweep_arena2/pointers/gc.rs b/oscars/src/collectors/mark_sweep_arena2/pointers/gc.rs index 1f4623b..cd88f28 100644 --- a/oscars/src/collectors/mark_sweep_arena2/pointers/gc.rs +++ b/oscars/src/collectors/mark_sweep_arena2/pointers/gc.rs @@ -40,7 +40,9 @@ impl Gc { /// Converts a `Gc` into a raw [`ArenaPointer`]. pub fn into_raw(this: Self) -> ArenaPointer<'static, GcBox> { - this.inner_ptr() + let ptr = this.inner_ptr(); + core::mem::forget(this); + ptr } /// Creates a `Gc` from the provided [`ArenaPointer`]. @@ -88,8 +90,10 @@ impl Gc { #[inline] #[must_use] pub unsafe fn cast_unchecked(this: Self) -> Gc { + let inner_ptr = this.inner_ptr; + core::mem::forget(this); Gc { - inner_ptr: this.inner_ptr, + inner_ptr, marker: PhantomData, } } diff --git a/oscars/src/collectors/mark_sweep_arena2/pointers/weak.rs b/oscars/src/collectors/mark_sweep_arena2/pointers/weak.rs index b284f46..0438098 100644 --- a/oscars/src/collectors/mark_sweep_arena2/pointers/weak.rs +++ b/oscars/src/collectors/mark_sweep_arena2/pointers/weak.rs @@ -3,7 +3,7 @@ // optimized in the future use crate::{ alloc::arena2::ArenaPointer, - collectors::mark_sweep_arena2::{Trace, internals::Ephemeron}, + collectors::mark_sweep_arena2::{Gc, Trace, internals::Ephemeron}, }; #[repr(transparent)] @@ -33,4 +33,8 @@ impl WeakGc { pub fn value(&self) -> Option<&T> { self.inner_ptr.as_inner_ref().key() } + + pub fn upgrade(&self) -> Option> { + self.inner_ptr.as_inner_ref().upgrade() + } }