Skip to content

Commit 11dc1eb

Browse files
committed
reduce dupliaction between mark_sweep and mark_sweep_arena2
1 parent 794371d commit 11dc1eb

File tree

15 files changed

+87
-1360
lines changed

15 files changed

+87
-1360
lines changed

oscars/src/alloc/arena2/alloc.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@ impl<T: ?Sized> ArenaHeapItem<T> {
4444
&mut self.value as *mut T
4545
}
4646

47+
/// Returns a raw mutable pointer to the value
48+
///
49+
/// This avoids creating a `&mut self` reference, which can lead to stacked borrows
50+
/// if shared references to the heap item exist
51+
pub(crate) fn as_value_ptr(&self) -> *mut T {
52+
// SAFETY: `&raw mut` computes the field address without creating a
53+
// reference
54+
unsafe { &raw mut (*(&raw const *self as *mut Self)).value }
55+
}
56+
4757
pub(crate) fn value_mut(&mut self) -> &mut T {
4858
&mut self.value
4959
}
@@ -133,6 +143,15 @@ impl<'arena> ErasedArenaPointer<'arena> {
133143
self.0.as_ptr()
134144
}
135145

146+
/// Extend the lifetime of this erased arena pointer to 'static
147+
///
148+
/// SAFETY:
149+
///
150+
/// safe because the gc collector owns the arena and keeps it alive
151+
pub(crate) unsafe fn extend_lifetime(self) -> ErasedArenaPointer<'static> {
152+
ErasedArenaPointer(self.0, PhantomData)
153+
}
154+
136155
/// Returns an [`ArenaPointer`] for the current [`ErasedArenaPointer`]
137156
///
138157
/// # Safety
@@ -178,6 +197,15 @@ impl<'arena, T> ArenaPointer<'arena, T> {
178197
pub fn to_erased(self) -> ErasedArenaPointer<'arena> {
179198
self.0
180199
}
200+
201+
/// extend the lifetime of this arena pointer to 'static
202+
///
203+
/// SAFETY:
204+
///
205+
/// safe because the gc collector owns the arena and keeps it alive
206+
pub(crate) unsafe fn extend_lifetime(self) -> ArenaPointer<'static, T> {
207+
ArenaPointer(unsafe { self.0.extend_lifetime() }, PhantomData)
208+
}
181209
}
182210

183211
const FULL_MASK: u8 = 0b0100_0000;

oscars/src/collectors/mark_sweep/cell.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,14 @@ impl<T: ?Sized> GcRefCell<T> {
171171
}
172172
}
173173

174+
// returns a raw pointer to the inner value or `None` if currently mutably borrowed
175+
pub(crate) fn get_raw(&self) -> Option<*mut T> {
176+
match self.borrow.get().borrowed() {
177+
BorrowState::Writing => None,
178+
_ => Some(self.cell.get()),
179+
}
180+
}
181+
174182
/// Mutably borrows the wrapped value, returning an error if the value is currently borrowed.
175183
///
176184
/// The borrow lasts until the returned `GcCellRefMut` exits scope.

oscars/src/collectors/mark_sweep/internals/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod gc_header;
44
mod vtable;
55

66
pub(crate) use ephemeron::Ephemeron;
7+
pub(crate) use gc_header::{GcHeader, HeaderColor};
78
pub(crate) use vtable::{DropFn, TraceFn, VTable, vtable_of};
89

910
pub use self::gc_box::{GcBox, NonTraceable, WeakGcBox};

oscars/src/collectors/mark_sweep/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,10 @@ impl MarkSweepGarbageCollector {
171171

172172
// Force drops all elements in the internal tracking queues and clears
173173
// them without regard for reachability.
174+
//
175+
// NOTE: This intentionally differs from arena2's sweep_all_queues.
176+
// arena3 uses`free_slot` calls to reclaim memory.
177+
// arena2 uses a bitmap (`mark_dropped`) and reclaims automatically
174178
fn sweep_all_queues(&self) {
175179
let ephemerons = core::mem::take(&mut *self.ephemeron_queue.borrow_mut());
176180
for ephemeron in ephemerons {

oscars/src/collectors/mark_sweep/pointers/gc.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,12 @@ impl<T: Trace> Gc<T> {
4444

4545
impl<T: Trace + ?Sized> Gc<T> {
4646
pub(crate) fn as_sized_inner_ptr(&self) -> NonNull<GcBox<NonTraceable>> {
47-
// SAFETY: use `addr_of_mut!` to get a raw pointer without creating
47+
// SAFETY: use `&raw mut` to get a raw pointer without creating
4848
// a `&mut` reference, avoiding Stacked Borrows UB during GC tracing
49-
let raw: *mut ArenaHeapItem<GcBox<NonTraceable>> = self.as_heap_ptr().as_ptr();
49+
let raw: *mut PoolItem<GcBox<NonTraceable>> = self.as_heap_ptr().as_ptr();
5050
// SAFETY: `raw` is non-null because it comes from `as_heap_ptr()`
51-
// `ArenaHeapItem` is `#[repr(transparent)]` so it shares the same address as field 0
52-
unsafe { NonNull::new_unchecked(core::ptr::addr_of_mut!((*raw).0)) }
51+
// `PoolItem` is `#[repr(transparent)]` so it shares the same address as field 0
52+
unsafe { NonNull::new_unchecked(&raw mut (*raw).0) }
5353
}
5454

5555
pub(crate) fn as_heap_ptr(&self) -> NonNull<PoolItem<GcBox<NonTraceable>>> {

0 commit comments

Comments
 (0)