diff --git a/oscars/src/collectors/mark_sweep_branded/ephemeron.rs b/oscars/src/collectors/mark_sweep_branded/ephemeron.rs index e77771b..82e5887 100644 --- a/oscars/src/collectors/mark_sweep_branded/ephemeron.rs +++ b/oscars/src/collectors/mark_sweep_branded/ephemeron.rs @@ -17,6 +17,19 @@ pub struct Ephemeron<'id, K: Trace, V: Trace> { } impl<'id, K: Trace, V: Trace> Ephemeron<'id, K, V> { + pub(crate) fn new( + key_ptr: Option>>, + key_alloc_id: usize, + value_ptr: PoolPointer<'static, GcBox>, + ) -> Self { + Self { + key_ptr, + key_alloc_id, + value_ptr, + _marker: PhantomData, + } + } + /// Returns the value if the key is alive. pub fn get_value<'gc>(&self, _cx: &MutationContext<'id, 'gc>) -> Option> { // SAFETY: `_cx` proves the collector is alive, alloc_id guards ABA @@ -24,10 +37,7 @@ impl<'id, K: Trace, V: Trace> Ephemeron<'id, K, V> { .key_ptr .is_some_and(|p| unsafe { (*p.as_ptr().as_ptr()).0.alloc_id == self.key_alloc_id }); if key_alive { - Some(Gc { - ptr: self.value_ptr, - _marker: PhantomData, - }) + Some(Gc::with_pointer(self.value_ptr)) } else { None } diff --git a/oscars/src/collectors/mark_sweep_branded/gc.rs b/oscars/src/collectors/mark_sweep_branded/gc.rs index 032d540..2c1cf96 100644 --- a/oscars/src/collectors/mark_sweep_branded/gc.rs +++ b/oscars/src/collectors/mark_sweep_branded/gc.rs @@ -25,6 +25,16 @@ impl<'gc, T: Trace + ?Sized + 'gc> Clone for Gc<'gc, T> { } } +impl<'gc, T: Trace + ?Sized + 'gc> Gc<'gc, T> { + #[inline] + pub(crate) fn with_pointer(ptr: PoolPointer<'static, GcBox>) -> Self { + Self { + ptr, + _marker: PhantomData, + } + } +} + impl<'gc, T: Trace + 'gc> Gc<'gc, T> { /// Returns a shared reference to the value. #[inline] diff --git a/oscars/src/collectors/mark_sweep_branded/mod.rs b/oscars/src/collectors/mark_sweep_branded/mod.rs index 3f78a24..702b61c 100644 --- a/oscars/src/collectors/mark_sweep_branded/mod.rs +++ b/oscars/src/collectors/mark_sweep_branded/mod.rs @@ -139,10 +139,7 @@ impl Collector { drop(pool); - Ok(Gc { - ptr: unsafe { ptr.extend_lifetime() }, - _marker: PhantomData, - }) + Ok(Gc::with_pointer(unsafe { ptr.extend_lifetime() })) } /// Runs a collection cycle diff --git a/oscars/src/collectors/mark_sweep_branded/mutation_ctx.rs b/oscars/src/collectors/mark_sweep_branded/mutation_ctx.rs index 7c9d788..5c3c26d 100644 --- a/oscars/src/collectors/mark_sweep_branded/mutation_ctx.rs +++ b/oscars/src/collectors/mark_sweep_branded/mutation_ctx.rs @@ -32,11 +32,7 @@ impl<'id, 'gc> MutationContext<'id, 'gc> { /// Downgrades a `Gc` into a weak reference pub fn alloc_weak(&self, gc: Gc<'gc, T>) -> WeakGc<'id, T> { let alloc_id = unsafe { (*gc.ptr.as_ptr().as_ptr()).0.alloc_id }; - WeakGc { - ptr: gc.ptr, - alloc_id, - _marker: PhantomData, - } + WeakGc::with_pointer_and_alloc_id(gc.ptr, alloc_id) } /// Promotes a `Gc` pointer to a `Root` @@ -45,7 +41,7 @@ impl<'id, 'gc> MutationContext<'id, 'gc> { gc: Gc<'gc, T>, ) -> Result, PoolAllocError> { let raw = self.collector.try_alloc_root_node(gc.ptr)?; - Ok(Root { raw }) + Ok(Root::from_raw(raw)) } /// Creates an ephemeron binding `key` to `value`. @@ -66,12 +62,7 @@ impl<'id, 'gc> MutationContext<'id, 'gc> { let erased_value: PoolPointer<'static, GcBox<()>> = unsafe { value.ptr.to_erased().to_typed_pool_pointer::>() }; self.collector.register_ephemeron(erased_key, erased_value); - Ephemeron { - key_ptr: Some(key.ptr), - key_alloc_id, - value_ptr: value.ptr, - _marker: core::marker::PhantomData, - } + Ephemeron::new(Some(key.ptr), key_alloc_id, value.ptr) } /// Triggers a gc cycle. diff --git a/oscars/src/collectors/mark_sweep_branded/root.rs b/oscars/src/collectors/mark_sweep_branded/root.rs index a77fa1c..1ec8529 100644 --- a/oscars/src/collectors/mark_sweep_branded/root.rs +++ b/oscars/src/collectors/mark_sweep_branded/root.rs @@ -170,13 +170,14 @@ pub struct Root<'id, T: Trace> { } impl<'id, T: Trace> Root<'id, T> { + pub(crate) fn from_raw(raw: NonNull>) -> Self { + Self { raw } + } + /// Converts this root into a `Gc` pointer pub fn get<'gc>(&self, _cx: &MutationContext<'id, 'gc>) -> Gc<'gc, T> { - Gc { - // SAFETY: `raw` is non null and valid - ptr: unsafe { self.raw.as_ref().gc_ptr }, - _marker: PhantomData, - } + // SAFETY: `raw` is non null and valid + Gc::with_pointer(unsafe { self.raw.as_ref().gc_ptr }) } } diff --git a/oscars/src/collectors/mark_sweep_branded/weak.rs b/oscars/src/collectors/mark_sweep_branded/weak.rs index bb60895..63e4a2c 100644 --- a/oscars/src/collectors/mark_sweep_branded/weak.rs +++ b/oscars/src/collectors/mark_sweep_branded/weak.rs @@ -18,6 +18,17 @@ pub struct WeakGc<'id, T: Trace + ?Sized> { } impl<'id, T: Trace> WeakGc<'id, T> { + pub(crate) fn with_pointer_and_alloc_id( + ptr: PoolPointer<'static, GcBox>, + alloc_id: usize, + ) -> Self { + Self { + ptr, + alloc_id, + _marker: PhantomData, + } + } + /// Attempts to upgrade to a strong `Gc<'gc, T>`. pub fn upgrade<'gc>( &self, @@ -29,10 +40,7 @@ impl<'id, T: Trace> WeakGc<'id, T> { let is_valid = unsafe { (*self.ptr.as_ptr().as_ptr()).0.alloc_id == self.alloc_id }; if is_valid { - Some(Gc { - ptr: self.ptr, - _marker: PhantomData, - }) + Some(Gc::with_pointer(self.ptr)) } else { None } diff --git a/oscars/src/collectors/null_collector_branded/ephemeron.rs b/oscars/src/collectors/null_collector_branded/ephemeron.rs index 2548e22..b87591c 100644 --- a/oscars/src/collectors/null_collector_branded/ephemeron.rs +++ b/oscars/src/collectors/null_collector_branded/ephemeron.rs @@ -16,14 +16,22 @@ pub struct Ephemeron<'id, K: Trace, V: Trace> { } impl<'id, K: Trace, V: Trace> Ephemeron<'id, K, V> { + pub(crate) fn new( + key_ptr: Option>>, + value_ptr: PoolPointer<'static, GcBox>, + ) -> Self { + Self { + key_ptr, + value_ptr, + _marker: PhantomData, + } + } + /// Returns the value if the key is alive. pub fn get_value<'gc>(&self, _cx: &MutationContext<'id, 'gc>) -> Option> { // In the null collector, everything stays alive until context drops. if self.key_ptr.is_some() { - Some(Gc { - ptr: self.value_ptr, - _marker: PhantomData, - }) + Some(Gc::with_pointer(self.value_ptr)) } else { None } diff --git a/oscars/src/collectors/null_collector_branded/gc.rs b/oscars/src/collectors/null_collector_branded/gc.rs index 11a19ef..63bd636 100644 --- a/oscars/src/collectors/null_collector_branded/gc.rs +++ b/oscars/src/collectors/null_collector_branded/gc.rs @@ -25,6 +25,16 @@ impl<'gc, T: Trace + ?Sized + 'gc> Clone for Gc<'gc, T> { } } +impl<'gc, T: Trace + ?Sized + 'gc> Gc<'gc, T> { + #[inline] + pub(crate) fn with_pointer(ptr: PoolPointer<'static, GcBox>) -> Self { + Self { + ptr, + _marker: PhantomData, + } + } +} + impl<'gc, T: Trace + 'gc> Gc<'gc, T> { /// Returns a shared reference to the value. #[inline] diff --git a/oscars/src/collectors/null_collector_branded/mod.rs b/oscars/src/collectors/null_collector_branded/mod.rs index b16f027..854ab43 100644 --- a/oscars/src/collectors/null_collector_branded/mod.rs +++ b/oscars/src/collectors/null_collector_branded/mod.rs @@ -62,10 +62,7 @@ impl Collector { drop(pool); - Ok(Gc { - ptr: unsafe { ptr.extend_lifetime() }, - _marker: PhantomData, - }) + Ok(Gc::with_pointer(unsafe { ptr.extend_lifetime() })) } /// Runs a collection cycle (no-op for null collector) diff --git a/oscars/src/collectors/null_collector_branded/mutation_ctx.rs b/oscars/src/collectors/null_collector_branded/mutation_ctx.rs index 952db1c..93a81b8 100644 --- a/oscars/src/collectors/null_collector_branded/mutation_ctx.rs +++ b/oscars/src/collectors/null_collector_branded/mutation_ctx.rs @@ -28,10 +28,7 @@ impl<'id, 'gc> MutationContext<'id, 'gc> { /// Downgrades a `Gc` into weak reference pub fn alloc_weak(&self, gc: Gc<'gc, T>) -> WeakGc<'id, T> { - WeakGc { - ptr: gc.ptr, - _marker: PhantomData, - } + WeakGc::with_pointer(gc.ptr) } pub fn root( @@ -53,11 +50,7 @@ impl<'id, 'gc> MutationContext<'id, 'gc> { ) -> Ephemeron<'id, K, V> { // In the null collector, ephemerons don't need to be registered // since the collector never collects. - Ephemeron { - key_ptr: Some(key.ptr), - value_ptr: value.ptr, - _marker: core::marker::PhantomData, - } + Ephemeron::new(Some(key.ptr), value.ptr) } pub fn collect(&self) { diff --git a/oscars/src/collectors/null_collector_branded/root.rs b/oscars/src/collectors/null_collector_branded/root.rs index c3baa68..4bc1298 100644 --- a/oscars/src/collectors/null_collector_branded/root.rs +++ b/oscars/src/collectors/null_collector_branded/root.rs @@ -26,9 +26,6 @@ impl<'id, T: Trace> Root<'id, T> { /// Converts this root into a `Gc` pointer pub fn get<'gc>(&self, _cx: &MutationContext<'id, 'gc>) -> Gc<'gc, T> { - Gc { - ptr: self.gc_ptr, - _marker: PhantomData, - } + Gc::with_pointer(self.gc_ptr) } } diff --git a/oscars/src/collectors/null_collector_branded/weak.rs b/oscars/src/collectors/null_collector_branded/weak.rs index 1d8ef28..b9a8152 100644 --- a/oscars/src/collectors/null_collector_branded/weak.rs +++ b/oscars/src/collectors/null_collector_branded/weak.rs @@ -15,16 +15,20 @@ pub struct WeakGc<'id, T: Trace + ?Sized> { } impl<'id, T: Trace> WeakGc<'id, T> { + pub(crate) fn with_pointer(ptr: PoolPointer<'static, GcBox>) -> Self { + Self { + ptr, + _marker: PhantomData, + } + } + /// Attempts to upgrade to a strong `Gc<'gc, T>` pub fn upgrade<'gc>( &self, _cx: &crate::collectors::null_collector_branded::MutationContext<'id, 'gc>, ) -> Option> { // In the null collector, everything stays alive until context drops. - Some(Gc { - ptr: self.ptr, - _marker: PhantomData, - }) + Some(Gc::with_pointer(self.ptr)) } }