Skip to content

Commit b61c1be

Browse files
committed
[simple] Move collector ids in the object header
When using multiple collectors, we need to use a `SimpleCollectorId` to disambiguate beteween them. Before this change, we stored this inline in the GC pointer, taking up 128 bits of space. Now, we store it indirectly in the object header. This should end up saving significant space...
1 parent f288249 commit b61c1be

File tree

2 files changed

+35
-21
lines changed

2 files changed

+35
-21
lines changed

libs/simple/src/gc.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ use super::CollectorId as SimpleCollectorId;
1717
#[repr(C)]
1818
pub struct Gc<'gc, T: GcSafe + 'gc> {
1919
ptr: NonNull<T>,
20-
id: SimpleCollectorId,
2120
marker: PhantomData<&'gc T>
2221
}
2322
impl<'gc, T: GcSafe + 'gc> Gc<'gc, T> {
@@ -29,16 +28,27 @@ impl<'gc, T: GcSafe + 'gc> Gc<'gc, T> {
2928
pub fn value(&self) -> &'gc T {
3029
unsafe { &*(&self.ptr as *const NonNull<T> as *const &T) }
3130
}
31+
#[inline]
32+
unsafe fn header(&self) -> *mut super::GcHeader {
33+
super::GcHeader::from_value_ptr(
34+
self.value() as *const T as *mut T,
35+
<T as super::StaticGcType>::STATIC_TYPE
36+
)
37+
}
3238
}
3339
unsafe impl<'gc, T: GcSafe + 'gc> GcRef<'gc, T> for Gc<'gc, T> {
3440
type Id = SimpleCollectorId;
35-
#[inline(always)]
41+
#[inline]
3642
fn collector_id(&self) -> Self::Id {
37-
self.id
43+
unsafe {
44+
(*self.header()).collector_id
45+
}
3846
}
39-
#[inline(always)]
47+
#[inline]
4048
unsafe fn from_raw(id: SimpleCollectorId, ptr: NonNull<T>) -> Self {
41-
Gc { ptr, id, marker: PhantomData }
49+
let res = Gc { ptr, marker: PhantomData };
50+
debug_assert_eq!(res.collector_id(), id);
51+
res
4252
}
4353
#[inline(always)]
4454
fn value(&self) -> &'gc T {
@@ -51,7 +61,7 @@ unsafe impl<'gc, T: GcSafe + 'gc> GcRef<'gc, T> for Gc<'gc, T> {
5161
#[inline(always)]
5262
fn system(&self) -> &'_ <Self::Id as CollectorId>::System {
5363
// This assumption is safe - see the docs
54-
unsafe { self.id.assume_valid_system() }
64+
unsafe { (*self.header()).collector_id.assume_valid_system() }
5565
}
5666
}
5767
unsafe impl<'gc, O, V> ::zerogc::GcDirectBarrier<'gc, Gc<'gc, O>> for Gc<'gc, V>

libs/simple/src/lib.rs

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -276,25 +276,27 @@ impl SimpleAlloc {
276276
if let Some(arena) = self.small_arenas.find::<T>() {
277277
let header = arena.alloc();
278278
unsafe {
279+
let collector_id = match self.collector_id {
280+
Some(collector) => collector,
281+
None => {
282+
#[cfg(debug_assertions)] {
283+
unreachable!("Invalid collector id")
284+
}
285+
#[cfg(not(debug_assertions))] {
286+
std::hint::unreachable_unchecked()
287+
}
288+
}
289+
};
279290
header.as_ptr().write(GcHeader::new(
280291
T::STATIC_TYPE,
281-
MarkState::White.to_raw(self.mark_inverted())
292+
MarkState::White.to_raw(self.mark_inverted()),
293+
collector_id
282294
));
283295
let value_ptr = header.as_ref().value().cast::<T>();
284296
value_ptr.write(value);
285297
self.add_allocated_size(small_object_size::<T>());
286298
Gc::from_raw(
287-
match self.collector_id {
288-
Some(collector) => collector,
289-
None => {
290-
#[cfg(debug_assertions)] {
291-
unreachable!("Invalid collector id")
292-
}
293-
#[cfg(not(debug_assertions))] {
294-
std::hint::unreachable_unchecked()
295-
}
296-
}
297-
},
299+
collector_id,
298300
NonNull::new_unchecked(value_ptr),
299301
)
300302
}
@@ -306,7 +308,8 @@ impl SimpleAlloc {
306308
let mut object = Box::new(BigGcObject {
307309
header: GcHeader::new(
308310
T::STATIC_TYPE,
309-
MarkState::White.to_raw(self.mark_inverted())
311+
MarkState::White.to_raw(self.mark_inverted()),
312+
self.collector_id.unwrap()
310313
),
311314
static_value: ManuallyDrop::new(value),
312315
prev: BigObjectLink::new(self.big_object_link.item()),
@@ -810,11 +813,12 @@ struct GcHeader {
810813
* Do we really need to use atomic stores?
811814
*/
812815
raw_state: AtomicCell<RawMarkState>,
816+
collector_id: CollectorId
813817
}
814818
impl GcHeader {
815819
#[inline]
816-
pub fn new(type_info: &'static GcType, raw_state: RawMarkState) -> Self {
817-
GcHeader { type_info, raw_state: AtomicCell::new(raw_state) }
820+
pub fn new(type_info: &'static GcType, raw_state: RawMarkState, collector_id: CollectorId) -> Self {
821+
GcHeader { type_info, raw_state: AtomicCell::new(raw_state), collector_id }
818822
}
819823
#[inline]
820824
pub fn value(&self) -> *mut c_void {

0 commit comments

Comments
 (0)