Skip to content

Commit a837672

Browse files
committed
Finish defining the interface to object formats
The complexity seems too high. I think I'm going to remove the 'GcInternalLayout' implementation.
1 parent 8eae944 commit a837672

File tree

11 files changed

+763
-422
lines changed

11 files changed

+763
-422
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ default = ["std"]
2727
# Depend on the standard library (optional)
2828
#
2929
# This implements tracing
30-
std = []
30+
std = ["alloc"]
3131
# Depend on `extern crate alloc` in addition to the Rust `core`
3232
# This is implied by using the standard library (feature="std")
3333
#

libs/context/src/collector.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use zerogc::{Gc, GcSafe, GcSystem, Trace, GcSimpleAlloc, NullTrace, TraceImmutab
1212

1313
use crate::{CollectorContext};
1414
use crate::state::{CollectionManager, RawContext};
15+
use std::ffi::c_void;
1516

1617
/// A specific implementation of a collector
1718
pub unsafe trait RawCollectorImpl: 'static + Sized {
@@ -21,6 +22,8 @@ pub unsafe trait RawCollectorImpl: 'static + Sized {
2122
/// a trait object pointer.
2223
type GcDynPointer: Copy + Debug + 'static;
2324

25+
unsafe fn dyn_ptr_from_raw(raw: *mut c_void) -> Self::GcDynPointer;
26+
2427
/// A pointer to this collector
2528
///
2629
/// Must be a ZST if the collector is a singleton.
@@ -45,7 +48,7 @@ pub unsafe trait RawCollectorImpl: 'static + Sized {
4548
where 'gc: 'a, T: GcSafe + ?Sized + 'gc;
4649

4750
/// Convert the specified value into a dyn pointer
48-
unsafe fn create_dyn_pointer<T: Trace>(t: *mut T) -> Self::GcDynPointer;
51+
unsafe fn create_dyn_pointer<T: GcSafe>(&self, t: *mut T) -> Self::GcDynPointer;
4952

5053
/// Initialize an instance of the collector
5154
///

libs/context/src/handle.rs

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,17 @@ use alloc::vec::Vec;
1111
use zerogc::{Trace, GcSafe, GcErase, GcRebrand, GcVisitor, NullTrace, TraceImmutable, GcHandleSystem, GcBindHandle};
1212
use crate::{Gc, WeakCollectorRef, CollectorId, CollectorContext, CollectorRef, CollectionManager};
1313
use crate::collector::RawCollectorImpl;
14+
use std::ffi::c_void;
15+
use crate::utils::AtomicCell;
1416

1517
const INITIAL_HANDLE_CAPACITY: usize = 64;
1618

1719
/// A [RawCollectorImpl] that supports handles
1820
pub unsafe trait RawHandleImpl: RawCollectorImpl {
1921
/// Type information
20-
type TypeInfo: Sized;
22+
type TypeInfo: Sized + Copy;
2123

22-
fn type_info_for_val<T: GcSafe + ?Sized>(val: &T) -> &'_ Self::TypeInfo;
24+
fn type_info_for_val<T: GcSafe>(&self, val: &T) -> Self::TypeInfo;
2325

2426
fn handle_list(&self) -> &GcHandleList<Self>;
2527
}
@@ -232,7 +234,7 @@ impl<C: RawHandleImpl> GcHandleList<C> {
232234
/// Now that's behind a layer of abstraction,
233235
/// the unsafety has technically been moved to the caller.
234236
pub unsafe fn trace<F, E>(&mut self, mut visitor: F) -> Result<(), E>
235-
where F: FnMut(*mut (), &C::TypeInfo) -> Result<(), E> {
237+
where F: FnMut(C::GcDynPointer, &C::TypeInfo) -> Result<(), E> {
236238
/*
237239
* TODO: This fence seems unnecessary since we should
238240
* already have exclusive access.....
@@ -361,8 +363,7 @@ pub struct GcRawHandle<C: RawHandleImpl> {
361363
value: AtomicPtr<()>,
362364
/// I think this should be protected by the other atomic
363365
/// accesses. Regardless, I'll put it in an AtomicPtr anyways.
364-
// TODO: Encapsulate
365-
pub(crate) type_info: AtomicPtr<C::TypeInfo>,
366+
pub(crate) type_info: AtomicCell<C::TypeInfo>,
366367
/// The reference count to the handle
367368
///
368369
/// If this is zero the value can be freed
@@ -379,9 +380,13 @@ impl<C: RawHandleImpl> GcRawHandle<C> {
379380
/// - It is assumed that the appropriate atomic fences (if any)
380381
/// have already been applied (TODO: Don't we have exclusive access?)
381382
unsafe fn trace_inner<F, E>(&self, trace: &mut F) -> Result<(), E>
382-
where F: FnMut(*mut (), &C::TypeInfo) -> Result<(), E> {
383-
let value = self.value.load(Ordering::Relaxed);
384-
if value.is_null() {
383+
where F: FnMut(C::GcDynPointer, &C::TypeInfo) -> Result<(), E> {
384+
let raw_value = self.value.load(Ordering::Relaxed);
385+
assert_eq!(
386+
std::mem::size_of::<*mut ()>(),
387+
std::mem::size_of::<C::GcDynPointer>(),
388+
);
389+
if raw_value.is_null() {
385390
debug_assert_eq!(
386391
self.refcnt.load(Ordering::Relaxed),
387392
0
@@ -392,8 +397,9 @@ impl<C: RawHandleImpl> GcRawHandle<C> {
392397
self.refcnt.load(Ordering::Relaxed),
393398
0
394399
);
395-
let type_info = &*self.type_info.load(Ordering::Relaxed);
396-
trace(value, type_info)
400+
let value = C::dyn_ptr_from_raw(raw_value as *mut c_void);
401+
let type_info = self.type_info.load();
402+
trace(value, &type_info)
397403
}
398404
}
399405
pub struct GcHandle<T: GcSafe, C: RawHandleImpl> {
@@ -598,7 +604,7 @@ unsafe impl<T: GcSafe + Sync, C: RawHandleImpl + Sync> Sync for GcHandle<T, C> {
598604
/// We support handles
599605
unsafe impl<'gc, 'a, T, C> GcHandleSystem<'gc, 'a, T> for CollectorRef<C>
600606
where C: RawHandleImpl,
601-
T: GcSafe + 'gc + ?Sized,
607+
T: GcSafe + 'gc,
602608
T: GcErase<'a, CollectorId<C>>,
603609
T::Erased: GcSafe {
604610
type Handle = GcHandle<T::Erased, C>;
@@ -616,10 +622,7 @@ unsafe impl<'gc, 'a, T, C> GcHandleSystem<'gc, 'a, T> for CollectorRef<C>
616622
* the handle!!!
617623
*/
618624
raw.type_info.store(
619-
C::type_info_for_val::<T>(gc.value())
620-
as *const C::TypeInfo
621-
as *mut C::TypeInfo,
622-
Ordering::Release
625+
collector.as_ref().type_info_for_val::<T>(gc.value())
623626
);
624627
raw.refcnt.store(1, Ordering::Release);
625628
let weak_collector = collector.weak_ref();

libs/context/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ impl<C: RawCollectorImpl> CollectorContext<C> {
134134
) -> R {
135135
let old_link = (*(*self.raw).shadow_stack_ptr()).last;
136136
let new_link = ShadowStackLink {
137-
element: C::create_dyn_pointer(value),
137+
element: (*self.raw).collector().create_dyn_pointer(value),
138138
prev: old_link
139139
};
140140
(*(*self.raw).shadow_stack_ptr()).last = &new_link;

libs/simple/src/alloc.rs

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ use parking_lot::Mutex;
1313
#[cfg(not(feature = "sync"))]
1414
use std::cell::RefCell;
1515

16-
use crate::layout::{GcHeader};
1716
use zerogc_context::utils::AtomicCell;
17+
use zerogc::format::{ObjectFormat, OpenAllocObjectFormat};
1818

1919
/// The minimum size of supported memory (in words)
2020
///
@@ -26,11 +26,18 @@ pub const MINIMUM_WORDS: usize = 2;
2626
/// Past this we have to fallback to the global allocator
2727
pub const MAXIMUM_SMALL_WORDS: usize = 32;
2828
/// The alignment of elements in the arena
29-
pub const ARENA_ELEMENT_ALIGN: usize = mem::align_of::<GcHeader>();
29+
pub const ARENA_ELEMENT_ALIGN: usize = ARENA_HEADER_LAYOUT.align();
30+
/// The size of headers in the arena
31+
///
32+
/// This is the same regardless of the underlying object format
33+
const ARENA_HEADER_LAYOUT: Layout = Layout::new::<DummyGcHeader>();
34+
35+
use super::DummyGcHeader;
36+
use crate::{RawSimpleCollector, RawObjectFormat};
3037

3138
#[inline]
3239
pub const fn small_object_size<T>() -> usize {
33-
let header_layout = Layout::new::<GcHeader>();
40+
let header_layout = ARENA_HEADER_LAYOUT;
3441
header_layout.size() + header_layout
3542
.padding_needed_for(std::mem::align_of::<T>())
3643
+ mem::size_of::<T>()
@@ -114,7 +121,7 @@ pub struct FreeSlot {
114121
#[repr(C)]
115122
pub(crate) union MaybeFreeSlot {
116123
pub free: FreeSlot,
117-
pub header: GcHeader,
124+
pub header: DummyGcHeader,
118125
}
119126

120127
impl MaybeFreeSlot {
@@ -192,7 +199,7 @@ impl ArenaState {
192199
self.current_chunk.store(ptr);
193200
}
194201
#[inline]
195-
fn alloc(&self, element_size: usize) -> NonNull<GcHeader> {
202+
fn alloc(&self, element_size: usize) -> NonNull<DummyGcHeader> {
196203
unsafe {
197204
let chunk = &*self.current_chunk().as_ptr();
198205
match chunk.try_alloc(element_size) {
@@ -204,7 +211,7 @@ impl ArenaState {
204211

205212
#[cold]
206213
#[inline(never)]
207-
fn alloc_fallback(&self, element_size: usize) -> NonNull<GcHeader> {
214+
fn alloc_fallback(&self, element_size: usize) -> NonNull<DummyGcHeader> {
208215
let mut chunks = self.lock_chunks();
209216
// Now that we hold the lock, check the current chunk again
210217
unsafe {
@@ -220,7 +227,7 @@ impl ArenaState {
220227
self.force_current_chunk(NonNull::from(&**chunks.last().unwrap()));
221228
self.current_chunk().as_ref()
222229
.try_alloc(element_size).unwrap()
223-
.cast::<GcHeader>()
230+
.cast::<DummyGcHeader>()
224231
}
225232
}
226233
}
@@ -242,7 +249,7 @@ impl FreeList {
242249
self.next.store(next)
243250
}
244251
#[inline]
245-
fn take_free(&self) -> Option<NonNull<GcHeader>> {
252+
fn take_free(&self) -> Option<NonNull<DummyGcHeader>> {
246253
loop {
247254
let next_free = match self.next.load() {
248255
Some(free) => free,
@@ -264,25 +271,27 @@ impl FreeList {
264271
}
265272
}
266273

267-
pub struct SmallArena {
274+
pub struct SmallArena<Fmt: RawObjectFormat> {
268275
pub(crate) element_size: usize,
269276
state: ArenaState,
270-
pub(crate) free: FreeList
277+
pub(crate) free: FreeList,
278+
format: &'static Fmt
271279
}
272-
impl SmallArena {
280+
impl<Fmt: RawObjectFormat> SmallArena<Fmt> {
273281
#[cold] // Initialization is the slow path
274-
fn with_words(num_words: usize) -> SmallArena {
282+
fn with_words(format: &'static Fmt, num_words: usize) -> SmallArena<Fmt> {
275283
assert!(num_words >= MINIMUM_WORDS);
276284
let element_size = num_words * mem::size_of::<usize>();
277285
assert!(INITIAL_SIZE >= element_size * 2);
278286
let chunks = vec![Chunk::alloc(INITIAL_SIZE)];
279287
SmallArena {
280288
state: ArenaState::new(chunks),
281289
element_size, free: Default::default(),
290+
format
282291
}
283292
}
284293
#[inline]
285-
pub(crate) fn alloc(&self) -> NonNull<GcHeader> {
294+
pub(crate) fn alloc(&self) -> NonNull<DummyGcHeader> {
286295
// Check the free list
287296
if let Some(free) = self.free.take_free() {
288297
free
@@ -303,11 +312,11 @@ impl SmallArena {
303312
}
304313
}
305314
macro_rules! arena_match {
306-
($arenas:expr, $target:ident, max = $max:expr; $($size:pat => $num_words:literal @ $idx:expr),*) => {
315+
($format:expr, $arenas:expr, $target:ident, max = $max:expr; $($size:pat => $num_words:literal @ $idx:expr),*) => {
307316
Some(match $target {
308317
$($size => $arenas[$idx].get_or_init(|| {
309318
assert_eq!(SMALL_ARENA_SIZES[$idx], $num_words);
310-
SmallArena::with_words($num_words)
319+
SmallArena::with_words($format, $num_words)
311320
}),)*
312321
_ => {
313322
assert!($target > $max);
@@ -321,35 +330,35 @@ const SMALL_ARENA_SIZES: [usize; NUM_SMALL_ARENAS] = [
321330
10, 12, 14, 16,
322331
20, 24, 28, 32
323332
];
324-
pub struct SmallArenaList {
333+
pub struct SmallArenaList<Fmt: RawObjectFormat> {
325334
// NOTE: Internally boxed to avoid bloating main struct
326-
arenas: Box<[OnceCell<SmallArena>; NUM_SMALL_ARENAS]>
335+
arenas: Box<[OnceCell<SmallArena<Fmt>>; NUM_SMALL_ARENAS]>
327336
}
328-
impl SmallArenaList {
337+
impl<Fmt: RawObjectFormat> SmallArenaList<Fmt> {
329338
pub fn new() -> Self {
330339
// NOTE: Why does writing arrays have to be so difficult:?
331340
unsafe {
332341
let mut arenas: Box<[
333-
MaybeUninit<OnceCell<SmallArena>>;
342+
MaybeUninit<OnceCell<SmallArena<Fmt>>>;
334343
NUM_SMALL_ARENAS
335344
]> = Box::new_uninit().assume_init();
336345
for i in 0..NUM_SMALL_ARENAS {
337346
arenas[i].as_mut_ptr().write(OnceCell::new());
338347
}
339348
SmallArenaList {
340-
// NOTE: This is done becuase I want to explicitly specifiy types
349+
// NOTE: This is done because I want to explicitly specify types
341350
arenas: mem::transmute::<
342-
Box<[MaybeUninit<OnceCell<SmallArena>>; NUM_SMALL_ARENAS]>,
343-
Box<[OnceCell<SmallArena>; NUM_SMALL_ARENAS]>
351+
Box<[MaybeUninit<OnceCell<SmallArena<Fmt>>>; NUM_SMALL_ARENAS]>,
352+
Box<[OnceCell<SmallArena<Fmt>>; NUM_SMALL_ARENAS]>
344353
>(arenas)
345354
}
346355
}
347356
}
348-
pub fn iter(&self) -> impl Iterator<Item=&SmallArena> + '_ {
357+
pub fn iter(&self) -> impl Iterator<Item=&SmallArena<Fmt>> + '_ {
349358
self.arenas.iter().filter_map(OnceCell::get)
350359
}
351360
#[inline] // This should be constant folded away (size/align is const)
352-
pub fn find<T>(&self) -> Option<&SmallArena> {
361+
pub fn find<T>(&self) -> Option<&SmallArena<Fmt>> {
353362
if std::mem::align_of::<T>() > ARENA_ELEMENT_ALIGN {
354363
return None
355364
}
@@ -359,9 +368,9 @@ impl SmallArenaList {
359368
/ word_size;
360369
self.find_raw(num_words)
361370
}
362-
#[inline(always)] // We want this constant-folded away......
363-
fn find_raw(&self, num_words: usize) -> Option<&SmallArena> {
364-
arena_match!(
371+
#[inline] // We want this constant-folded away......
372+
fn find_raw(&self, num_words: usize) -> Option<&SmallArena<Fmt>> {
373+
arena_match!(self.format,
365374
self.arenas, num_words, max = 32;
366375
0..=2 => 2 @ 0,
367376
3 => 3 @ 1,

0 commit comments

Comments
 (0)