mmtk/plan/lxr/gc_work/
nursery_sweeping.rs

1use atomic::Ordering;
2
3use crate::plan::lxr::{LazySweepingJobsCounter, LXR};
4use crate::policy::immix::block::Block;
5use crate::scheduler::WorkBucketStage;
6use crate::scheduler::{GCWork, GCWorker};
7use crate::vm::VMBinding;
8use crate::MMTK;
9
10pub struct RCLazySweepNurseryBlocks {
11    blocks: Vec<Block>,
12    _counter: LazySweepingJobsCounter,
13}
14
15impl RCLazySweepNurseryBlocks {
16    pub fn new(blocks: Vec<Block>) -> Self {
17        Self {
18            blocks,
19            _counter: LazySweepingJobsCounter::new_decs(),
20        }
21    }
22}
23
24impl<VM: VMBinding> GCWork<VM> for RCLazySweepNurseryBlocks {
25    fn do_work(&mut self, _worker: &mut GCWorker<VM>, mmtk: &'static MMTK<VM>) {
26        let lxr = &mmtk.get_plan().downcast_ref::<LXR<VM>>().unwrap();
27        let mut released_blocks = 0;
28        for block in &self.blocks {
29            if block.rc_sweep_nursery(&lxr.immix_space) {
30                released_blocks += 1;
31            }
32        }
33        lxr.num_clean_blocks_released_lazy
34            .fetch_add(released_blocks, Ordering::SeqCst);
35    }
36}
37
38pub struct RCSTWSweepNurseryBlocks {
39    blocks: Vec<Block>,
40    _counter: LazySweepingJobsCounter,
41}
42
43impl RCSTWSweepNurseryBlocks {
44    pub fn new(blocks: Vec<Block>) -> Self {
45        Self {
46            blocks,
47            _counter: LazySweepingJobsCounter::new_decs(),
48        }
49    }
50}
51
52impl<VM: VMBinding> GCWork<VM> for RCSTWSweepNurseryBlocks {
53    fn do_work(&mut self, _worker: &mut GCWorker<VM>, mmtk: &'static MMTK<VM>) {
54        let space = &mmtk
55            .get_plan()
56            .downcast_ref::<LXR<VM>>()
57            .unwrap()
58            .immix_space;
59        for block in &self.blocks {
60            block.rc_sweep_nursery(space);
61        }
62    }
63}
64
65pub struct SweepBlocksAfterDecs {
66    blocks: Vec<(Block, bool)>,
67    _counter: LazySweepingJobsCounter,
68}
69
70impl SweepBlocksAfterDecs {
71    pub fn new(blocks: Vec<(Block, bool)>, counter: LazySweepingJobsCounter) -> Self {
72        Self {
73            blocks,
74            _counter: counter,
75        }
76    }
77}
78
79impl<VM: VMBinding> GCWork<VM> for SweepBlocksAfterDecs {
80    fn do_work(&mut self, _worker: &mut GCWorker<VM>, mmtk: &'static MMTK<VM>) {
81        let lxr = mmtk.get_plan().downcast_ref::<LXR<VM>>().unwrap();
82        if self.blocks.is_empty() {
83            return;
84        }
85        let mut count = 0;
86        for (block, defrag) in &self.blocks {
87            block.unlog();
88            if block.rc_sweep_mature::<VM>(&lxr.immix_space, *defrag) {
89                count += 1;
90            } else {
91                assert!(
92                    !*defrag,
93                    "defrag block is freed? {:?} {:?} {}",
94                    block,
95                    block.get_state(),
96                    block.is_defrag_source()
97                );
98            }
99        }
100        if count != 0
101            && (lxr.current_pause().is_none()
102                || mmtk.scheduler.work_buckets[WorkBucketStage::STWRCDecsAndSweep].is_open())
103        {
104            lxr.num_clean_blocks_released_lazy
105                .fetch_add(count, Ordering::Relaxed);
106        }
107    }
108}
109
110pub struct ReleaseLOSNursery;
111
112impl<VM: VMBinding> GCWork<VM> for ReleaseLOSNursery {
113    fn do_work(&mut self, _worker: &mut GCWorker<VM>, mmtk: &'static MMTK<VM>) {
114        let lxr = mmtk.get_plan().downcast_ref::<LXR<VM>>().unwrap();
115        lxr.los().release_rc_nursery_objects();
116    }
117}