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