1use crate::plan::global::BasePlan;
2use crate::plan::global::CreateGeneralPlanArgs;
3use crate::plan::global::CreateSpecificPlanArgs;
4use crate::plan::nogc::mutator::ALLOCATOR_MAPPING;
5use crate::plan::AllocationSemantics;
6use crate::plan::Plan;
7use crate::plan::PlanConstraints;
8use crate::policy::immortalspace::ImmortalSpace;
9use crate::policy::space::Space;
10use crate::scheduler::GCWorkScheduler;
11use crate::util::alloc::allocators::AllocatorSelector;
12use crate::util::heap::gc_trigger::SpaceStats;
13#[allow(unused_imports)]
14use crate::util::heap::VMRequest;
15use crate::util::metadata::side_metadata::SideMetadataContext;
16use crate::util::opaque_pointer::*;
17use crate::vm::VMBinding;
18use enum_map::EnumMap;
19use mmtk_macros::HasSpaces;
20
21#[cfg(not(feature = "nogc_lock_free"))]
22use crate::policy::immortalspace::ImmortalSpace as NoGCImmortalSpace;
23#[cfg(feature = "nogc_lock_free")]
24use crate::policy::lockfreeimmortalspace::LockFreeImmortalSpace as NoGCImmortalSpace;
25
26#[derive(HasSpaces)]
27pub struct NoGC<VM: VMBinding> {
28 #[parent]
29 pub base: BasePlan<VM>,
30 #[space]
31 pub nogc_space: NoGCImmortalSpace<VM>,
32 #[space]
33 pub immortal: ImmortalSpace<VM>,
34 #[space]
35 pub los: ImmortalSpace<VM>,
36}
37
38pub const NOGC_CONSTRAINTS: PlanConstraints = PlanConstraints {
40 collects_garbage: false,
41 ..PlanConstraints::default()
42};
43
44impl<VM: VMBinding> Plan for NoGC<VM> {
45 fn constraints(&self) -> &'static PlanConstraints {
46 &NOGC_CONSTRAINTS
47 }
48
49 fn collection_required(&self, space_full: bool, _space: Option<SpaceStats<Self::VM>>) -> bool {
50 self.base().collection_required(self, space_full)
51 }
52
53 fn base(&self) -> &BasePlan<VM> {
54 &self.base
55 }
56
57 fn base_mut(&mut self) -> &mut BasePlan<Self::VM> {
58 &mut self.base
59 }
60
61 fn prepare(&mut self, _tls: VMWorkerThread) {
62 unreachable!()
63 }
64
65 fn release(&mut self, _tls: VMWorkerThread) {
66 unreachable!()
67 }
68
69 fn end_of_gc(&mut self, _tls: VMWorkerThread) {
70 unreachable!()
71 }
72
73 fn get_allocator_mapping(&self) -> &'static EnumMap<AllocationSemantics, AllocatorSelector> {
74 &ALLOCATOR_MAPPING
75 }
76
77 fn schedule_collection(&'static self, _scheduler: &GCWorkScheduler<VM>) {
78 unreachable!("GC triggered in nogc")
79 }
80
81 fn current_gc_may_move_object(&self) -> bool {
82 false
83 }
84
85 fn get_used_pages(&self) -> usize {
86 self.nogc_space.reserved_pages()
87 + self.immortal.reserved_pages()
88 + self.los.reserved_pages()
89 + self.base.get_used_pages()
90 }
91}
92
93impl<VM: VMBinding> NoGC<VM> {
94 pub fn new(args: CreateGeneralPlanArgs<VM>) -> Self {
95 let mut plan_args = CreateSpecificPlanArgs {
96 global_args: args,
97 constraints: &NOGC_CONSTRAINTS,
98 global_side_metadata_specs: SideMetadataContext::new_global_specs(&[]),
99 };
100
101 let res = NoGC {
102 nogc_space: NoGCImmortalSpace::new(plan_args.get_normal_space_args(
103 "nogc_space",
104 cfg!(not(feature = "nogc_no_zeroing")),
105 false,
106 VMRequest::discontiguous(),
107 )),
108 immortal: ImmortalSpace::new(plan_args.get_normal_space_args(
109 "immortal",
110 true,
111 false,
112 VMRequest::discontiguous(),
113 )),
114 los: ImmortalSpace::new(plan_args.get_normal_space_args(
115 "los",
116 true,
117 false,
118 VMRequest::discontiguous(),
119 )),
120 base: BasePlan::new(plan_args),
121 };
122
123 res.verify_side_metadata_sanity();
124
125 res
126 }
127}