Skip to content

Commit 7c0a62c

Browse files
committed
Trace the singleton empty vec
If we want to keep using it, we need the garbage collector to preserve it.... Fix GcVec::extend_from_slice to correctly do set_len
1 parent 559dcf9 commit 7c0a62c

File tree

2 files changed

+34
-10
lines changed

2 files changed

+34
-10
lines changed

libs/simple/src/lib.rs

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ struct GcHeap {
266266
config: Arc<GcConfig>,
267267
threshold: AtomicUsize,
268268
allocator: SimpleAlloc,
269-
// TODO: This needs to be traced!!
269+
// NOTE: This is only public so it can be traced
270270
cached_empty_vec: Cell<Option<*mut GcVecHeader>>
271271
}
272272
impl GcHeap {
@@ -768,19 +768,41 @@ impl RawSimpleCollector {
768768
&self, contexts: &[*mut RawContext<Self>]
769769
) {
770770
debug_assert!(self.manager.is_collecting());
771-
let roots: Vec<*mut dyn DynTrace> = contexts.iter()
772-
.flat_map(|ctx| {
773-
(**ctx).assume_valid_shadow_stack()
774-
.reverse_iter().map(NonNull::as_ptr)
775-
})
776-
.chain(std::iter::once(&self.handle_list
771+
let roots = {
772+
let mut roots: Vec<*mut dyn DynTrace> = Vec::new();
773+
for ctx in contexts.iter() {
774+
roots.extend((**ctx).assume_valid_shadow_stack()
775+
.reverse_iter().map(NonNull::as_ptr));
776+
}
777+
roots.push(&self.handle_list
777778
// Cast to wrapper type
778779
as *const GcHandleList<Self> as *const GcHandleListWrapper
779780
// Make into virtual pointer
780781
as *const dyn DynTrace
781782
as *mut dyn DynTrace
782-
))
783-
.collect();
783+
);
784+
#[repr(transparent)]
785+
struct CachedEmptyVec(GcVecHeader);
786+
unsafe impl DynTrace for CachedEmptyVec {
787+
fn trace(&mut self, visitor: &mut MarkVisitor) {
788+
let cached_vec_header = self as *mut Self as *mut GcVecHeader;
789+
unsafe {
790+
let target_repr = (cached_vec_header as *mut u8)
791+
.add(GcVecHeader::LAYOUT.value_offset(EMPTY_VEC_ALIGNMENT))
792+
.cast::<SimpleVecRepr<()>>();
793+
let mut target_gc = *(&target_repr
794+
as *const *mut SimpleVecRepr<()>
795+
as *const Gc<SimpleVecRepr<DynamicObj>>);
796+
// TODO: Assert not moving?
797+
let Ok(()) = visitor.visit_vec::<(), _>(&mut target_gc);
798+
}
799+
}
800+
}
801+
if let Some(cached_vec_header) = self.heap.cached_empty_vec.get() {
802+
roots.push(cached_vec_header as *mut CachedEmptyVec as *mut dyn DynTrace)
803+
}
804+
roots
805+
};
784806
let num_roots = roots.len();
785807
let mut task = CollectionTask {
786808
config: &*self.config,

src/vec.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,13 @@ impl<'gc, T: GcSafe, Ctx: GcSimpleAlloc> GcVec<'gc, T, Ctx> {
9090
#[inline]
9191
pub fn extend_from_slice(&mut self, src: &[T])
9292
where T: Copy {
93+
let old_len = self.len();
9394
self.reserve(src.len());
9495
// TODO: Write barriers?
9596
unsafe {
9697
(self.raw.as_repr_mut().ptr() as *mut T).add(self.len())
97-
.copy_from_nonoverlapping(src.as_ptr(), src.len())
98+
.copy_from_nonoverlapping(src.as_ptr(), src.len());
99+
self.raw.as_repr_mut().set_len(old_len + src.len());
98100
}
99101
}
100102
/// Push the specified value onto the vector

0 commit comments

Comments
 (0)