mmtk/util/
object_enum.rs

1//! Helper types for object enumeration
2
3use std::marker::PhantomData;
4
5use crate::vm::VMBinding;
6
7use super::{
8    heap::{chunk_map::ChunkMap, MonotonePageResource},
9    linear_scan::Region,
10    metadata::{side_metadata::spec_defs::VO_BIT, vo_bit},
11    Address, ObjectReference,
12};
13
14/// A trait for enumerating objects in spaces, used by [`Space::enumerate_objects`].
15///
16/// [`Space::enumerate_objects`]: crate::policy::space::Space::enumerate_objects
17pub trait ObjectEnumerator {
18    /// Visit a single object.
19    fn visit_object(&mut self, object: ObjectReference);
20    /// Visit an address range that may contain objects.
21    fn visit_address_range(&mut self, start: Address, end: Address);
22}
23
24/// An implementation of `ObjectEnumerator` that wraps a callback.
25pub struct ClosureObjectEnumerator<F, VM>
26where
27    F: FnMut(ObjectReference),
28    VM: VMBinding,
29{
30    object_callback: F,
31    phantom_data: PhantomData<VM>,
32}
33
34impl<F, VM> ClosureObjectEnumerator<F, VM>
35where
36    F: FnMut(ObjectReference),
37    VM: VMBinding,
38{
39    pub fn new(object_callback: F) -> Self {
40        Self {
41            object_callback,
42            phantom_data: PhantomData,
43        }
44    }
45}
46
47impl<F, VM> ObjectEnumerator for ClosureObjectEnumerator<F, VM>
48where
49    F: FnMut(ObjectReference),
50    VM: VMBinding,
51{
52    fn visit_object(&mut self, object: ObjectReference) {
53        (self.object_callback)(object);
54    }
55
56    fn visit_address_range(&mut self, start: Address, end: Address) {
57        VO_BIT.scan_non_zero_values::<u8>(start, end, &mut |address| {
58            let object = vo_bit::get_object_ref_for_vo_addr(address);
59            (self.object_callback)(object);
60        })
61    }
62}
63
64/// Allow querying if a block may have objects. `MarkSweepSpace` and `ImmixSpace` use different
65/// `Block` types, and they have different block states. This trait lets both `Block` types provide
66/// the same `may_have_objects` method.
67pub(crate) trait BlockMayHaveObjects: Region {
68    /// Return `true` if the block may contain valid objects (objects with the VO bit set). Return
69    /// `false` otherwise.
70    ///
71    /// This function is used during object enumeration to filter out memory regions that do not
72    /// contain objects. Because object enumeration may happen at mutator time, and another mutators
73    /// may be allocating objects, this function only needs to reflect the state of the block at the
74    /// time of calling, and is allowed to conservatively return `true`.
75    fn may_have_objects(&self) -> bool;
76}
77
78pub(crate) fn enumerate_blocks_from_chunk_map<B>(
79    enumerator: &mut dyn ObjectEnumerator,
80    chunk_map: &ChunkMap,
81) where
82    B: BlockMayHaveObjects,
83{
84    for chunk in chunk_map.all_chunks() {
85        for block in chunk.iter_region::<B>() {
86            if block.may_have_objects() {
87                enumerator.visit_address_range(block.start(), block.end());
88            }
89        }
90    }
91}
92
93pub(crate) fn enumerate_blocks_from_monotonic_page_resource<VM>(
94    enumerator: &mut dyn ObjectEnumerator,
95    pr: &MonotonePageResource<VM>,
96) where
97    VM: VMBinding,
98{
99    for (start, size) in pr.iterate_allocated_regions() {
100        enumerator.visit_address_range(start, start + size);
101    }
102}