Skip to content

Commit 7373168

Browse files
authored
Allow bindings to handle unknown objects in trace_object() (#593)
This PR adds a new method to `ActivePlan` to allow bindings to handle unknown objects encountered in object tracing.
1 parent d8bc02e commit 7373168

File tree

7 files changed

+40
-19
lines changed

7 files changed

+40
-19
lines changed

docs/tutorial/code/mygc_semispace/gc_work.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ impl<VM:VMBinding> ProcessEdgesWork for MyGCProcessEdges<VM> {
6868
worker,
6969
)
7070
} else {
71-
self.plan.common.trace_object(queue, object)
71+
self.plan.common.trace_object(queue, object, worker)
7272
}
7373
}
7474
}

macros/src/plan_trace_object_impl.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ pub(crate) fn generate_trace_object<'a>(
4848
}
4949
} else {
5050
quote! {
51-
panic!("No more spaces to try")
51+
<VM::VMActivePlan as crate::vm::ActivePlan<VM>>::vm_trace_object::<Q>(__mmtk_queue, __mmtk_objref, __mmtk_worker)
5252
}
5353
};
5454

src/plan/generational/global.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ impl<VM: VMBinding> Gen<VM> {
192192
worker,
193193
);
194194
}
195-
self.common.trace_object::<Q>(queue, object)
195+
self.common.trace_object::<Q>(queue, object, worker)
196196
}
197197

198198
/// Trace objects for spaces in generational and common plans for a nursery GC.

src/plan/global.rs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -603,33 +603,35 @@ impl<VM: VMBinding> BasePlan<VM> {
603603

604604
pub fn trace_object<Q: ObjectQueue>(
605605
&self,
606-
_queue: &mut Q,
607-
_object: ObjectReference,
606+
queue: &mut Q,
607+
object: ObjectReference,
608+
worker: &mut GCWorker<VM>,
608609
) -> ObjectReference {
609610
#[cfg(feature = "code_space")]
610-
if self.code_space.in_space(_object) {
611+
if self.code_space.in_space(object) {
611612
trace!("trace_object: object in code space");
612-
return self.code_space.trace_object::<Q>(_queue, _object);
613+
return self.code_space.trace_object::<Q>(queue, object);
613614
}
614615

615616
#[cfg(feature = "code_space")]
616-
if self.code_lo_space.in_space(_object) {
617+
if self.code_lo_space.in_space(object) {
617618
trace!("trace_object: object in large code space");
618-
return self.code_lo_space.trace_object::<Q>(_queue, _object);
619+
return self.code_lo_space.trace_object::<Q>(queue, object);
619620
}
620621

621622
#[cfg(feature = "ro_space")]
622-
if self.ro_space.in_space(_object) {
623+
if self.ro_space.in_space(object) {
623624
trace!("trace_object: object in ro_space space");
624-
return self.ro_space.trace_object(_queue, _object);
625+
return self.ro_space.trace_object(queue, object);
625626
}
626627

627628
#[cfg(feature = "vm_space")]
628-
if self.vm_space.in_space(_object) {
629+
if self.vm_space.in_space(object) {
629630
trace!("trace_object: object in boot space");
630-
return self.vm_space.trace_object(_queue, _object);
631+
return self.vm_space.trace_object(queue, object);
631632
}
632-
panic!("No special case for space in trace_object({:?})", _object);
633+
634+
VM::VMActivePlan::vm_trace_object::<Q>(queue, object, worker)
633635
}
634636

635637
pub fn prepare(&mut self, _tls: VMWorkerThread, _full_heap: bool) {
@@ -907,6 +909,7 @@ impl<VM: VMBinding> CommonPlan<VM> {
907909
&self,
908910
queue: &mut Q,
909911
object: ObjectReference,
912+
worker: &mut GCWorker<VM>,
910913
) -> ObjectReference {
911914
if self.immortal.in_space(object) {
912915
trace!("trace_object: object in immortal space");
@@ -916,7 +919,7 @@ impl<VM: VMBinding> CommonPlan<VM> {
916919
trace!("trace_object: object in los");
917920
return self.los.trace_object(queue, object);
918921
}
919-
self.base.trace_object::<Q>(queue, object)
922+
self.base.trace_object::<Q>(queue, object, worker)
920923
}
921924

922925
pub fn prepare(&mut self, tls: VMWorkerThread, full_heap: bool) {

src/policy/space.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,13 +178,14 @@ impl SFT for EmptySpaceSFT {
178178
fn sft_trace_object(
179179
&self,
180180
_queue: &mut VectorObjectQueue,
181-
_object: ObjectReference,
181+
object: ObjectReference,
182182
_worker: GCWorkerMutRef,
183183
) -> ObjectReference {
184+
// We do not have the `VM` type parameter here, so we cannot forward the call to the VM.
184185
panic!(
185-
"Call trace_object() on {} (chunk {}), which maps to an empty space",
186-
_object,
187-
conversions::chunk_align_down(_object.to_address()),
186+
"Call trace_object() on {} (chunk {}), which maps to an empty space. SFTProcessEdges does not support the fallback to vm_trace_object().",
187+
object,
188+
conversions::chunk_align_down(object.to_address()),
188189
)
189190
}
190191
}

src/scheduler/gc_work.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,11 @@ pub trait ProcessEdgesWork:
399399
const OVERWRITE_REFERENCE: bool = true;
400400
const SCAN_OBJECTS_IMMEDIATELY: bool = true;
401401
fn new(edges: Vec<Address>, roots: bool, mmtk: &'static MMTK<Self::VM>) -> Self;
402+
403+
/// Trace an MMTk object. The implementation should forward this call to the policy-specific
404+
/// `trace_object()` methods, depending on which space this object is in.
405+
/// If the object is not in any MMTk space, the implementation should forward the call to
406+
/// `ActivePlan::vm_trace_object()` to let the binding handle the tracing.
402407
fn trace_object(&mut self, object: ObjectReference) -> ObjectReference;
403408

404409
#[cfg(feature = "sanity")]

src/vm/active_plan.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
use crate::plan::Mutator;
22
use crate::plan::Plan;
3+
use crate::scheduler::GCWorker;
34
use crate::util::opaque_pointer::*;
5+
use crate::util::ObjectReference;
46
use crate::vm::VMBinding;
7+
use crate::ObjectQueue;
58
use std::marker::PhantomData;
69
use std::sync::MutexGuard;
710

@@ -68,4 +71,13 @@ pub trait ActivePlan<VM: VMBinding> {
6871

6972
/// Return the total count of mutators.
7073
fn number_of_mutators() -> usize;
74+
75+
/// The fallback for object tracing.
76+
fn vm_trace_object<Q: ObjectQueue>(
77+
_queue: &mut Q,
78+
object: ObjectReference,
79+
_worker: &mut GCWorker<VM>,
80+
) -> ObjectReference {
81+
panic!("MMTk cannot trace object {:?} as it does not belong to any MMTk space. If the object is known to the VM, the binding can override this method and handle its tracing.", object)
82+
}
7183
}

0 commit comments

Comments
 (0)