mmtk/plan/tracing/gc_work/
weakref.rs

1use std::marker::PhantomData;
2
3use crate::{
4    plan::tracing::{gc_work::DefaultObjectTracerContext, Trace},
5    scheduler::{GCWork, GCWorker, WorkBucketStage},
6    vm::{Collection, Scanning, VMBinding},
7    MMTK,
8};
9
10/// Delegate to the VM binding for weak reference processing.
11///
12/// Some VMs (e.g. v8) do not have a Java-like global weak reference storage, and the
13/// processing of those weakrefs may be more complex. For such case, we delegate to the
14/// VM binding to process weak references.
15///
16/// NOTE: This will replace `{Soft,Weak,Phantom}RefProcessing` and `Finalization` in the future.
17pub struct VMProcessWeakRefs<T: Trace> {
18    phantom_data: PhantomData<T>,
19}
20
21impl<T: Trace> VMProcessWeakRefs<T> {
22    pub fn new() -> Self {
23        Self {
24            phantom_data: PhantomData,
25        }
26    }
27}
28
29impl<T: Trace> GCWork<T::VM> for VMProcessWeakRefs<T> {
30    fn do_work(&mut self, worker: &mut GCWorker<T::VM>, _mmtk: &'static MMTK<T::VM>) {
31        trace!("VMProcessWeakRefs");
32
33        let stage = WorkBucketStage::VMRefClosure;
34
35        let need_to_repeat = {
36            let tracer_factory = DefaultObjectTracerContext::<T>::new(stage);
37            <T::VM as VMBinding>::VMScanning::process_weak_refs(worker, tracer_factory)
38        };
39
40        if need_to_repeat {
41            // Schedule Self as the new sentinel so we'll call `process_weak_refs` again after the
42            // current transitive closure.
43            let new_self = Box::new(Self::new());
44
45            worker.scheduler().work_buckets[stage].set_sentinel(new_self);
46        }
47    }
48}
49
50/// Delegate to the VM binding for forwarding weak references.
51///
52/// Some VMs (e.g. v8) do not have a Java-like global weak reference storage, and the
53/// processing of those weakrefs may be more complex. For such case, we delegate to the
54/// VM binding to process weak references.
55///
56/// NOTE: This will replace `RefForwarding` and `ForwardFinalization` in the future.
57pub struct VMForwardWeakRefs<T: Trace> {
58    phantom_data: PhantomData<T>,
59}
60
61impl<T: Trace> VMForwardWeakRefs<T> {
62    pub fn new() -> Self {
63        Self {
64            phantom_data: PhantomData,
65        }
66    }
67}
68
69impl<T: Trace> GCWork<T::VM> for VMForwardWeakRefs<T> {
70    fn do_work(&mut self, worker: &mut GCWorker<T::VM>, _mmtk: &'static MMTK<T::VM>) {
71        trace!("VMForwardWeakRefs");
72
73        let stage = WorkBucketStage::VMRefForwarding;
74
75        let tracer_factory = DefaultObjectTracerContext::<T>::new(stage);
76        <T::VM as VMBinding>::VMScanning::forward_weak_refs(worker, tracer_factory)
77    }
78}
79
80/// This work packet calls `Collection::post_forwarding`.
81///
82/// NOTE: This will replace `RefEnqueue` in the future.
83///
84/// NOTE: Although this work packet runs in parallel with the `Release` work packet, it does not
85/// access the `Plan` instance.
86#[derive(Default)]
87pub struct VMPostForwarding<VM: VMBinding> {
88    phantom_data: PhantomData<VM>,
89}
90
91impl<VM: VMBinding> GCWork<VM> for VMPostForwarding<VM> {
92    fn do_work(&mut self, worker: &mut GCWorker<VM>, _mmtk: &'static MMTK<VM>) {
93        trace!("VMPostForwarding start");
94        <VM as VMBinding>::VMCollection::post_forwarding(worker.tls);
95        trace!("VMPostForwarding end");
96    }
97}