mmtk/policy/
immortalspace.rs1use atomic::Ordering;
2
3use crate::policy::sft::SFT;
4use crate::policy::space::{CommonSpace, Space};
5use crate::util::address::Address;
6use crate::util::heap::{MonotonePageResource, PageResource};
7use crate::util::metadata::mark_bit::MarkState;
8
9use crate::util::object_enum::{self, ObjectEnumerator};
10use crate::util::{metadata, ObjectReference};
11
12use crate::plan::tracing::{ObjectQueue, OptionObjectQueue};
13
14use crate::policy::sft::GCWorkerMutRef;
15use crate::vm::{ObjectModel, VMBinding};
16
17pub struct ImmortalSpace<VM: VMBinding> {
22 mark_state: MarkState,
23 common: CommonSpace<VM>,
24 pr: MonotonePageResource<VM>,
25}
26
27impl<VM: VMBinding> SFT for ImmortalSpace<VM> {
28 fn name(&self) -> &'static str {
29 self.get_name()
30 }
31 fn is_live(&self, _object: ObjectReference) -> bool {
32 true
33 }
34 fn is_reachable(&self, object: ObjectReference) -> bool {
35 self.mark_state.is_marked::<VM>(object)
36 }
37 #[cfg(feature = "object_pinning")]
38 fn pin_object(&self, _object: ObjectReference) -> bool {
39 false
40 }
41 #[cfg(feature = "object_pinning")]
42 fn unpin_object(&self, _object: ObjectReference) -> bool {
43 false
44 }
45 #[cfg(feature = "object_pinning")]
46 fn is_object_pinned(&self, _object: ObjectReference) -> bool {
47 true
48 }
49 fn is_movable(&self) -> bool {
50 false
51 }
52 #[cfg(feature = "sanity")]
53 fn is_sane(&self) -> bool {
54 true
55 }
56 fn initialize_object_metadata(&self, object: ObjectReference, bytes: usize) {
57 self.mark_state
58 .on_object_metadata_initialization::<VM>(object);
59 if self.common.unlog_allocated_object {
60 VM::VMObjectModel::GLOBAL_LOG_BIT_SPEC.mark_as_unlogged::<VM>(object, Ordering::SeqCst);
61 if self.common.needs_field_log_bit {
62 VM::VMObjectModel::GLOBAL_FIELD_UNLOG_BIT_SPEC
63 .as_spec()
64 .extract_side_spec()
65 .bset_metadata(object.to_object_start::<VM>(), bytes);
66 }
67 }
68 #[cfg(feature = "vo_bit")]
69 crate::util::metadata::vo_bit::set_vo_bit(object);
70 }
71 #[cfg(feature = "vo_bit")]
72 fn is_mmtk_object(&self, addr: Address) -> Option<ObjectReference> {
73 crate::util::metadata::vo_bit::is_vo_bit_set_for_addr(addr)
74 }
75 #[cfg(feature = "vo_bit")]
76 fn find_object_from_internal_pointer(
77 &self,
78 ptr: Address,
79 max_search_bytes: usize,
80 ) -> Option<ObjectReference> {
81 crate::util::metadata::vo_bit::find_object_from_internal_pointer::<VM>(
82 ptr,
83 max_search_bytes,
84 )
85 }
86 fn sft_trace_object(
87 &self,
88 queue: &mut OptionObjectQueue,
89 object: ObjectReference,
90 _worker: GCWorkerMutRef,
91 ) -> ObjectReference {
92 self.trace_object(queue, object)
93 }
94 fn debug_print_object_info(&self, object: ObjectReference) {
95 println!("marked = {}", self.mark_state.is_marked::<VM>(object));
96 self.common.debug_print_object_global_info(object);
97 }
98}
99
100impl<VM: VMBinding> Space<VM> for ImmortalSpace<VM> {
101 fn as_space(&self) -> &dyn Space<VM> {
102 self
103 }
104 fn as_sft(&self) -> &(dyn SFT + Sync + 'static) {
105 self
106 }
107 fn get_page_resource(&self) -> &dyn PageResource<VM> {
108 &self.pr
109 }
110 fn maybe_get_page_resource_mut(&mut self) -> Option<&mut dyn PageResource<VM>> {
111 Some(&mut self.pr)
112 }
113 fn common(&self) -> &CommonSpace<VM> {
114 &self.common
115 }
116
117 fn initialize_sft(&self, sft_map: &mut dyn crate::policy::sft_map::SFTMap) {
118 self.common().initialize_sft(self.as_sft(), sft_map)
119 }
120
121 fn release_multiple_pages(&mut self, _start: Address) {
122 panic!("immortalspace only releases pages enmasse")
123 }
124
125 fn enumerate_objects(&self, enumerator: &mut dyn ObjectEnumerator) {
126 object_enum::enumerate_blocks_from_monotonic_page_resource(enumerator, &self.pr);
127 }
128
129 fn clear_side_log_bits(&self) {
130 let log_bit = VM::VMObjectModel::GLOBAL_LOG_BIT_SPEC.extract_side_spec();
131 for (start, size) in self.pr.iterate_allocated_regions() {
132 log_bit.bzero_metadata(start, size);
133 }
134 }
135
136 fn set_side_log_bits(&self) {
137 let log_bit = VM::VMObjectModel::GLOBAL_LOG_BIT_SPEC.extract_side_spec();
138 for (start, size) in self.pr.iterate_allocated_regions() {
139 log_bit.bset_metadata(start, size);
140 }
141 }
142}
143
144use crate::scheduler::GCWorker;
145use crate::util::copy::CopySemantics;
146
147impl<VM: VMBinding> crate::policy::gc_work::PolicyTraceObject<VM> for ImmortalSpace<VM> {
148 fn trace_object<Q: ObjectQueue, const KIND: crate::policy::gc_work::TraceKind>(
149 &self,
150 queue: &mut Q,
151 object: ObjectReference,
152 _copy: Option<CopySemantics>,
153 _worker: &mut GCWorker<VM>,
154 ) -> ObjectReference {
155 self.trace_object(queue, object)
156 }
157 fn may_move_objects<const KIND: crate::policy::gc_work::TraceKind>() -> bool {
158 false
159 }
160}
161
162impl<VM: VMBinding> ImmortalSpace<VM> {
163 pub fn new(args: crate::policy::space::PlanCreateSpaceArgs<VM>) -> Self {
164 let vm_map = args.vm_map;
165 let is_discontiguous = args.vmrequest.is_discontiguous();
166 let common = CommonSpace::new(args.into_policy_args(
167 false,
168 true,
169 metadata::extract_side_metadata(&[*VM::VMObjectModel::LOCAL_MARK_BIT_SPEC]),
170 ));
171 ImmortalSpace {
172 mark_state: MarkState::new(),
173 pr: if is_discontiguous {
174 MonotonePageResource::new_discontiguous(vm_map)
175 } else {
176 MonotonePageResource::new_contiguous(common.start, common.extent, vm_map)
177 },
178 common,
179 }
180 }
181
182 pub fn prepare(&mut self) {
183 self.mark_state.on_global_prepare::<VM>();
184 for (addr, size) in self.pr.iterate_allocated_regions() {
186 debug!(
187 "{:?}: reset mark bit from {} to {}",
188 self.name(),
189 addr,
190 addr + size
191 );
192 self.mark_state.on_block_reset::<VM>(addr, size);
193 }
194 }
195
196 pub fn release(&mut self) {
197 self.mark_state.on_global_release::<VM>();
198 }
199
200 pub fn trace_object<Q: ObjectQueue>(
201 &self,
202 queue: &mut Q,
203 object: ObjectReference,
204 ) -> ObjectReference {
205 #[cfg(feature = "vo_bit")]
206 debug_assert!(
207 crate::util::metadata::vo_bit::is_vo_bit_set(object),
208 "{:x}: VO bit not set",
209 object
210 );
211 if self.mark_state.test_and_mark::<VM>(object) {
212 if self.common.unlog_traced_object {
214 VM::VMObjectModel::GLOBAL_LOG_BIT_SPEC.store_atomic::<VM, u8>(
215 object,
216 1,
217 None,
218 Ordering::SeqCst,
219 );
220 }
221 queue.enqueue(object);
222 }
223 object
224 }
225}