mmtk/util/metadata/
log_bit.rs

1use crate::util::Address;
2use crate::util::ObjectReference;
3use crate::vm::ObjectModel;
4use crate::vm::VMBinding;
5use crate::vm::VMGlobalLogBitSpec;
6use std::sync::atomic::Ordering;
7
8use super::MetadataSpec;
9
10impl VMGlobalLogBitSpec {
11    /// Clear the unlog bit to log object (0 means logged)
12    pub fn clear<VM: VMBinding>(&self, object: ObjectReference, order: Ordering) {
13        self.store_atomic::<VM, u8>(object, 0, None, order)
14    }
15
16    /// Mark the log bit as unlogged (1 means unlogged)
17    pub fn mark_as_unlogged<VM: VMBinding>(&self, object: ObjectReference, order: Ordering) {
18        self.store_atomic::<VM, u8>(object, 1, None, order)
19    }
20
21    /// Mark the entire byte as unlogged if the log bit is in the side metadata. As it marks the entire byte,
22    /// it may unlog adjacent objects. This method should only be used
23    /// when adjacent objects are also in the mature space, and there is no harm if we also unlog them.
24    /// This method is meant to be an optimization, and can always be replaced with `mark_as_unlogged`.
25    pub fn mark_byte_as_unlogged<VM: VMBinding>(&self, object: ObjectReference, order: Ordering) {
26        match self.as_spec() {
27            // If the log bit is in the header, there is nothing we can do. We just call `mark_as_unlogged`.
28            MetadataSpec::InHeader(_) => self.mark_as_unlogged::<VM>(object, order),
29            // If the log bit is in the side metadata, we can simply set the entire byte to 0xff. Because we
30            // know we are setting log bit for mature space, and every object in the space should have log
31            // bit as 1.
32            MetadataSpec::OnSide(spec) => unsafe {
33                spec.set_raw_byte_atomic(object.to_raw_address(), order)
34            },
35        }
36    }
37
38    /// Check if the log bit represents the unlogged state (the bit is 1).
39    pub fn is_unlogged<VM: VMBinding>(&self, object: ObjectReference, order: Ordering) -> bool {
40        self.load_atomic::<VM, u8>(object, None, order) == 1
41    }
42}
43
44/// This specifies what to do to the global side unlog bits in various functions or work packets.
45#[derive(Clone, Copy, PartialEq, Eq)]
46pub(crate) enum UnlogBitsOperation {
47    /// Do nothing.
48    NoOp,
49    /// Bulk set unlog bits to all 1s.
50    BulkSet,
51    /// Bulk clear unlog bits to all 0s.
52    BulkClear,
53}
54
55impl UnlogBitsOperation {
56    /// Run the specified operation on the address range from `start` to `start + size`.
57    pub(crate) fn execute<VM: VMBinding>(&self, start: Address, size: usize) {
58        if let MetadataSpec::OnSide(ref unlog_bits) = *VM::VMObjectModel::GLOBAL_LOG_BIT_SPEC {
59            match self {
60                UnlogBitsOperation::NoOp => {}
61                UnlogBitsOperation::BulkSet => {
62                    unlog_bits.bset_metadata(start, size);
63                }
64                UnlogBitsOperation::BulkClear => {
65                    unlog_bits.bzero_metadata(start, size);
66                }
67            }
68        }
69    }
70}