1use 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
14pub trait ObjectEnumerator {
18 fn visit_object(&mut self, object: ObjectReference);
20 fn visit_address_range(&mut self, start: Address, end: Address);
22}
23
24pub 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
64pub(crate) trait BlockMayHaveObjects: Region {
68 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}