1use crate::vm::slot::{MemorySlice, Slot};
4use crate::vm::ObjectModel;
5use crate::{
6 util::{metadata::MetadataSpec, *},
7 vm::VMBinding,
8};
9use atomic::Ordering;
10use downcast_rs::Downcast;
11
12#[derive(Copy, Clone, Debug, PartialEq)]
19pub enum BarrierSelector {
20 NoBarrier,
22 ObjectBarrier,
24 FieldBarrier,
26 SATBBarrier,
29}
30
31impl BarrierSelector {
32 pub const fn equals(&self, other: BarrierSelector) -> bool {
34 *self as u8 == other as u8
36 }
37}
38
39pub trait Barrier<VM: VMBinding>: 'static + Send + Downcast {
51 fn flush(&mut self) {}
53
54 fn load_weak_reference(&mut self, _referent: ObjectReference) {}
66
67 fn object_reference_write(
69 &mut self,
70 src: ObjectReference,
71 slot: VM::VMSlot,
72 target: ObjectReference,
73 ) {
74 self.object_reference_write_pre(src, slot, Some(target));
75 slot.store(target);
76 self.object_reference_write_post(src, slot, Some(target));
77 }
78
79 fn object_reference_write_pre(
81 &mut self,
82 _src: ObjectReference,
83 _slot: VM::VMSlot,
84 _target: Option<ObjectReference>,
85 ) {
86 }
87
88 fn object_reference_write_post(
90 &mut self,
91 _src: ObjectReference,
92 _slot: VM::VMSlot,
93 _target: Option<ObjectReference>,
94 ) {
95 }
96
97 fn object_reference_write_slow(
100 &mut self,
101 _src: ObjectReference,
102 _slot: VM::VMSlot,
103 _target: Option<ObjectReference>,
104 ) {
105 }
106
107 fn memory_region_copy(&mut self, src: VM::VMMemorySlice, dst: VM::VMMemorySlice) {
109 self.memory_region_copy_pre(src.clone(), dst.clone());
110 VM::VMMemorySlice::copy(&src, &dst);
111 self.memory_region_copy_post(src, dst);
112 }
113
114 fn memory_region_copy_pre(&mut self, _src: VM::VMMemorySlice, _dst: VM::VMMemorySlice) {}
116
117 fn memory_region_copy_post(&mut self, _src: VM::VMMemorySlice, _dst: VM::VMMemorySlice) {}
119
120 fn object_probable_write(&mut self, _obj: ObjectReference) {}
136}
137
138impl_downcast!(Barrier<VM> where VM: VMBinding);
139
140pub struct NoBarrier;
145
146impl<VM: VMBinding> Barrier<VM> for NoBarrier {}
147
148pub trait BarrierSemantics: 'static + Send {
154 type VM: VMBinding;
155
156 const UNLOG_BIT_SPEC: MetadataSpec =
157 *<Self::VM as VMBinding>::VMObjectModel::GLOBAL_LOG_BIT_SPEC.as_spec();
158
159 fn flush(&mut self);
163
164 fn object_reference_write_slow(
166 &mut self,
167 src: ObjectReference,
168 slot: <Self::VM as VMBinding>::VMSlot,
169 target: Option<ObjectReference>,
170 );
171
172 fn memory_region_copy_slow(
174 &mut self,
175 src: <Self::VM as VMBinding>::VMMemorySlice,
176 dst: <Self::VM as VMBinding>::VMMemorySlice,
177 );
178
179 fn object_probable_write_slow(&mut self, _obj: ObjectReference) {}
181
182 fn load_weak_reference(&mut self, _o: ObjectReference) {}
184}
185
186pub struct ObjectBarrier<S: BarrierSemantics> {
188 semantics: S,
189}
190
191impl<S: BarrierSemantics> ObjectBarrier<S> {
192 pub fn new(semantics: S) -> Self {
194 Self { semantics }
195 }
196
197 fn object_is_unlogged(&self, object: ObjectReference) -> bool {
199 S::UNLOG_BIT_SPEC.load_atomic::<S::VM, u8>(object, None, Ordering::SeqCst) != 0
200 }
201
202 fn log_object(&self, object: ObjectReference) -> bool {
205 #[cfg(all(feature = "vo_bit", feature = "extreme_assertions"))]
206 debug_assert!(
207 crate::util::metadata::vo_bit::is_vo_bit_set(object),
208 "object bit is unset"
209 );
210 loop {
211 let old_value =
212 S::UNLOG_BIT_SPEC.load_atomic::<S::VM, u8>(object, None, Ordering::SeqCst);
213 if old_value == 0 {
214 return false;
215 }
216 if S::UNLOG_BIT_SPEC
217 .compare_exchange_metadata::<S::VM, u8>(
218 object,
219 1,
220 0,
221 None,
222 Ordering::SeqCst,
223 Ordering::SeqCst,
224 )
225 .is_ok()
226 {
227 return true;
228 }
229 }
230 }
231}
232
233impl<S: BarrierSemantics> Barrier<S::VM> for ObjectBarrier<S> {
234 fn flush(&mut self) {
235 self.semantics.flush();
236 }
237
238 fn object_reference_write_post(
239 &mut self,
240 src: ObjectReference,
241 slot: <S::VM as VMBinding>::VMSlot,
242 target: Option<ObjectReference>,
243 ) {
244 if self.object_is_unlogged(src) {
245 self.object_reference_write_slow(src, slot, target);
246 }
247 }
248
249 fn object_reference_write_slow(
250 &mut self,
251 src: ObjectReference,
252 slot: <S::VM as VMBinding>::VMSlot,
253 target: Option<ObjectReference>,
254 ) {
255 if self.log_object(src) {
256 self.semantics
257 .object_reference_write_slow(src, slot, target);
258 }
259 }
260
261 fn memory_region_copy_post(
262 &mut self,
263 src: <S::VM as VMBinding>::VMMemorySlice,
264 dst: <S::VM as VMBinding>::VMMemorySlice,
265 ) {
266 self.semantics.memory_region_copy_slow(src, dst);
267 }
268
269 fn object_probable_write(&mut self, obj: ObjectReference) {
270 if self.object_is_unlogged(obj) {
271 self.semantics.object_probable_write_slow(obj);
272 }
273 }
274}
275
276pub struct FieldBarrier<S: BarrierSemantics> {
278 semantics: S,
279}
280
281impl<S: BarrierSemantics> FieldBarrier<S> {
282 pub fn new(semantics: S) -> Self {
283 Self { semantics }
284 }
285}
286
287impl<S: BarrierSemantics> Barrier<S::VM> for FieldBarrier<S> {
288 fn flush(&mut self) {
289 self.semantics.flush();
290 }
291
292 fn load_weak_reference(&mut self, o: ObjectReference) {
293 self.semantics.load_weak_reference(o)
294 }
295
296 fn object_probable_write(&mut self, obj: ObjectReference) {
297 self.semantics.object_probable_write_slow(obj);
298 }
299
300 fn object_reference_write_pre(
301 &mut self,
302 src: ObjectReference,
303 slot: <S::VM as VMBinding>::VMSlot,
304 target: Option<ObjectReference>,
305 ) {
306 self.semantics
307 .object_reference_write_slow(src, slot, target);
308 }
309
310 fn object_reference_write_post(
311 &mut self,
312 _src: ObjectReference,
313 _slot: <S::VM as VMBinding>::VMSlot,
314 _target: Option<ObjectReference>,
315 ) {
316 unimplemented!()
317 }
318
319 fn object_reference_write_slow(
320 &mut self,
321 src: ObjectReference,
322 slot: <S::VM as VMBinding>::VMSlot,
323 target: Option<ObjectReference>,
324 ) {
325 self.semantics
326 .object_reference_write_slow(src, slot, target);
327 }
328
329 fn memory_region_copy_pre(
330 &mut self,
331 src: <S::VM as VMBinding>::VMMemorySlice,
332 dst: <S::VM as VMBinding>::VMMemorySlice,
333 ) {
334 self.semantics.memory_region_copy_slow(src, dst);
335 }
336
337 fn memory_region_copy_post(
338 &mut self,
339 _src: <S::VM as VMBinding>::VMMemorySlice,
340 _dst: <S::VM as VMBinding>::VMMemorySlice,
341 ) {
342 unimplemented!()
343 }
344}
345
346pub struct SATBBarrier<S: BarrierSemantics> {
349 weak_ref_barrier_enabled: bool,
350 semantics: S,
351}
352
353impl<S: BarrierSemantics> SATBBarrier<S> {
354 pub fn new(semantics: S) -> Self {
356 Self {
357 weak_ref_barrier_enabled: false,
358 semantics,
359 }
360 }
361
362 pub(crate) fn set_weak_ref_barrier_enabled(&mut self, value: bool) {
363 self.weak_ref_barrier_enabled = value;
364 }
365
366 fn object_is_unlogged(&self, object: ObjectReference) -> bool {
367 S::UNLOG_BIT_SPEC.load_atomic::<S::VM, u8>(object, None, Ordering::SeqCst) != 0
368 }
369}
370
371impl<S: BarrierSemantics> Barrier<S::VM> for SATBBarrier<S> {
372 fn flush(&mut self) {
373 self.semantics.flush();
374 }
375
376 fn load_weak_reference(&mut self, o: ObjectReference) {
377 if self.weak_ref_barrier_enabled {
378 self.semantics.load_weak_reference(o)
379 }
380 }
381
382 fn object_probable_write(&mut self, obj: ObjectReference) {
383 self.semantics.object_probable_write_slow(obj);
384 }
385
386 fn object_reference_write_pre(
387 &mut self,
388 src: ObjectReference,
389 slot: <S::VM as VMBinding>::VMSlot,
390 target: Option<ObjectReference>,
391 ) {
392 if self.object_is_unlogged(src) {
393 self.semantics
394 .object_reference_write_slow(src, slot, target);
395 }
396 }
397
398 fn object_reference_write_post(
399 &mut self,
400 _src: ObjectReference,
401 _slot: <S::VM as VMBinding>::VMSlot,
402 _target: Option<ObjectReference>,
403 ) {
404 unimplemented!()
405 }
406
407 fn object_reference_write_slow(
408 &mut self,
409 src: ObjectReference,
410 slot: <S::VM as VMBinding>::VMSlot,
411 target: Option<ObjectReference>,
412 ) {
413 self.semantics
414 .object_reference_write_slow(src, slot, target);
415 }
416
417 fn memory_region_copy_pre(
418 &mut self,
419 src: <S::VM as VMBinding>::VMMemorySlice,
420 dst: <S::VM as VMBinding>::VMMemorySlice,
421 ) {
422 self.semantics.memory_region_copy_slow(src, dst);
423 }
424
425 fn memory_region_copy_post(
426 &mut self,
427 _src: <S::VM as VMBinding>::VMMemorySlice,
428 _dst: <S::VM as VMBinding>::VMMemorySlice,
429 ) {
430 unimplemented!()
431 }
432}