mmtk/util/metadata/side_metadata/
spec_defs.rs

1use crate::util::constants::*;
2use crate::util::heap::layout::vm_layout::*;
3use crate::util::linear_scan::Region;
4use crate::util::metadata::side_metadata::constants::{
5    GLOBAL_SIDE_METADATA_BASE_OFFSET, LOCAL_SIDE_METADATA_BASE_OFFSET,
6};
7use crate::util::metadata::side_metadata::SideMetadataOffset;
8use crate::util::metadata::side_metadata::SideMetadataSpec;
9
10// This macro helps define side metadata specs, and layout their offsets one after another.
11// The macro is implemented with the incremental TT muncher pattern (see https://danielkeep.github.io/tlborm/book/pat-incremental-tt-munchers.html).
12// This should only be used twice within mmtk-core: one for global specs, and one for local specs.
13// This should not be used to layout VM specs (we have provided side_first()/side_after() for the VM side metadata specs).
14macro_rules! define_side_metadata_specs {
15    // Internal patterns
16
17    // Define the first spec with offset at either GLOBAL/LOCAL_SIDE_METADATA_BASE_OFFSET
18    (@first_spec $name: ident = (global: $is_global: expr, log_num_of_bits: $log_num_of_bits: expr, log_bytes_in_region: $log_bytes_in_region: expr)) => {
19        pub const $name: SideMetadataSpec = SideMetadataSpec {
20            name: stringify!($name),
21            is_global: $is_global,
22            offset: if $is_global { GLOBAL_SIDE_METADATA_BASE_OFFSET } else { LOCAL_SIDE_METADATA_BASE_OFFSET },
23            log_num_of_bits: $log_num_of_bits,
24            log_bytes_in_region: $log_bytes_in_region,
25        };
26    };
27    // Define any spec that follows a previous spec. The new spec will be created and laid out after the previous spec.
28    (@prev_spec $last_spec: ident as $last_spec_ident: ident, $name: ident = (global: $is_global: expr, log_num_of_bits: $log_num_of_bits: expr, log_bytes_in_region: $log_bytes_in_region: expr), $($tail:tt)*) => {
29        pub const $name: SideMetadataSpec = SideMetadataSpec {
30            name: stringify!($name),
31            is_global: $is_global,
32            offset: SideMetadataOffset::layout_after(&$last_spec),
33            log_num_of_bits: $log_num_of_bits,
34            log_bytes_in_region: $log_bytes_in_region,
35        };
36        define_side_metadata_specs!(@prev_spec $name as $last_spec_ident, $($tail)*);
37    };
38    // Define the last spec with the given identifier.
39    (@prev_spec $last_spec: ident as $last_spec_ident: ident,) => {
40        pub const $last_spec_ident: SideMetadataSpec = $last_spec;
41    };
42
43    // The actual macro
44
45    // This is the pattern that should be used outside this macro.
46    (last_spec_as $last_spec_ident: ident, $name0: ident = (global: $is_global0: expr, log_num_of_bits: $log_num_of_bits0: expr, log_bytes_in_region: $log_bytes_in_region0: expr), $($tail:tt)*) => {
47        // Defines the first spec
48        define_side_metadata_specs!(@first_spec $name0 = (global: $is_global0, log_num_of_bits: $log_num_of_bits0, log_bytes_in_region: $log_bytes_in_region0));
49        // The rest specs
50        define_side_metadata_specs!(@prev_spec $name0 as $last_spec_ident, $($tail)*);
51    };
52}
53
54// This defines all GLOBAL side metadata used by mmtk-core.
55define_side_metadata_specs!(
56    last_spec_as LAST_GLOBAL_SIDE_METADATA_SPEC,
57    // Mark the start of an object
58    VO_BIT       = (global: true, log_num_of_bits: 0, log_bytes_in_region: LOG_MIN_OBJECT_SIZE as usize),
59    // Track the index in SFT map for a chunk (only used for SFT sparse chunk map)
60    SFT_DENSE_CHUNK_MAP_INDEX   = (global: true, log_num_of_bits: 3, log_bytes_in_region: LOG_BYTES_IN_CHUNK),
61    // Mark chunks (any plan that uses the chunk map should include this spec in their global sidemetadata specs)
62    CHUNK_MARK   = (global: true, log_num_of_bits: 3, log_bytes_in_region: crate::util::heap::chunk_map::Chunk::LOG_BYTES),
63);
64
65// This defines all LOCAL side metadata used by mmtk-core.
66define_side_metadata_specs!(
67    last_spec_as LAST_LOCAL_SIDE_METADATA_SPEC,
68    // Mark pages by (malloc) marksweep
69    MALLOC_MS_ACTIVE_PAGE  = (global: false, log_num_of_bits: 3, log_bytes_in_region: crate::util::malloc::library::LOG_BYTES_IN_MALLOC_PAGE as usize),
70    // Record objects allocated with some offset
71    MS_OFFSET_MALLOC = (global: false, log_num_of_bits: 0, log_bytes_in_region: LOG_MIN_OBJECT_SIZE as usize),
72    // Mark lines by immix
73    IX_LINE_MARK    = (global: false, log_num_of_bits: 3, log_bytes_in_region: crate::policy::immix::line::Line::LOG_BYTES),
74    // Record defrag state for immix blocks
75    IX_BLOCK_DEFRAG = (global: false, log_num_of_bits: 3, log_bytes_in_region: crate::policy::immix::block::Block::LOG_BYTES),
76    // Mark blocks by immix
77    IX_BLOCK_MARK   = (global: false, log_num_of_bits: 3, log_bytes_in_region: crate::policy::immix::block::Block::LOG_BYTES),
78    // Mark blocks by (native mimalloc) marksweep
79    MS_BLOCK_MARK   = (global: false, log_num_of_bits: 3, log_bytes_in_region: crate::policy::marksweepspace::native_ms::Block::LOG_BYTES),
80    // Next block in list for native mimalloc
81    MS_BLOCK_NEXT   = (global: false, log_num_of_bits: LOG_BITS_IN_ADDRESS, log_bytes_in_region: crate::policy::marksweepspace::native_ms::Block::LOG_BYTES),
82    // Previous block in list for native mimalloc
83    MS_BLOCK_PREV   = (global: false, log_num_of_bits: LOG_BITS_IN_ADDRESS, log_bytes_in_region: crate::policy::marksweepspace::native_ms::Block::LOG_BYTES),
84    // Pointer to owning list for blocks for native mimalloc
85    MS_BLOCK_LIST   = (global: false, log_num_of_bits: LOG_BITS_IN_ADDRESS, log_bytes_in_region: crate::policy::marksweepspace::native_ms::Block::LOG_BYTES),
86    // Size of cells in block for native mimalloc FIXME: do we actually need usize?
87    MS_BLOCK_SIZE         = (global: false, log_num_of_bits: LOG_BITS_IN_ADDRESS, log_bytes_in_region: crate::policy::marksweepspace::native_ms::Block::LOG_BYTES),
88    // TLS of owning mutator of block for native mimalloc
89    MS_BLOCK_TLS    = (global: false, log_num_of_bits: LOG_BITS_IN_ADDRESS, log_bytes_in_region: crate::policy::marksweepspace::native_ms::Block::LOG_BYTES),
90    // First cell of free list in block for native mimalloc
91    MS_FREE         = (global: false, log_num_of_bits: LOG_BITS_IN_ADDRESS, log_bytes_in_region: crate::policy::marksweepspace::native_ms::Block::LOG_BYTES),
92    // The following specs are only used for manual malloc/free
93    // First cell of local free list in block for native mimalloc
94    MS_LOCAL_FREE   = (global: false, log_num_of_bits: LOG_BITS_IN_ADDRESS, log_bytes_in_region: crate::policy::marksweepspace::native_ms::Block::LOG_BYTES),
95    // First cell of thread free list in block for native mimalloc
96    MS_THREAD_FREE  = (global: false, log_num_of_bits: LOG_BITS_IN_ADDRESS, log_bytes_in_region: crate::policy::marksweepspace::native_ms::Block::LOG_BYTES),
97    // Start and end marks by Compressor
98    COMPRESSOR_MARK = (global: false, log_num_of_bits: 0, log_bytes_in_region: LOG_BYTES_IN_WORD as usize),
99    // Block offset vectors by Compressor
100    COMPRESSOR_OFFSET_VECTOR = (global: false, log_num_of_bits: LOG_BITS_IN_ADDRESS, log_bytes_in_region: crate::policy::compressor::forwarding::Block::LOG_BYTES),
101);
102
103#[cfg(test)]
104mod tests {
105    // We assert on constants to test if the macro is working properly.
106    #![allow(clippy::assertions_on_constants)]
107
108    use super::*;
109    #[test]
110    fn first_global_spec() {
111        define_side_metadata_specs!(last_spec_as LAST_GLOBAL_SPEC, TEST_SPEC = (global: true, log_num_of_bits: 0, log_bytes_in_region: 3),);
112        assert!(TEST_SPEC.is_global);
113        assert!(TEST_SPEC.offset == GLOBAL_SIDE_METADATA_BASE_OFFSET);
114        assert_eq!(TEST_SPEC.log_num_of_bits, 0);
115        assert_eq!(TEST_SPEC.log_bytes_in_region, 3);
116        assert_eq!(TEST_SPEC, LAST_GLOBAL_SPEC);
117    }
118
119    #[test]
120    fn first_local_spec() {
121        define_side_metadata_specs!(last_spec_as LAST_LOCAL_SPEC, TEST_SPEC = (global: false, log_num_of_bits: 0, log_bytes_in_region: 3),);
122        assert!(!TEST_SPEC.is_global);
123        assert!(TEST_SPEC.offset == LOCAL_SIDE_METADATA_BASE_OFFSET);
124        assert_eq!(TEST_SPEC.log_num_of_bits, 0);
125        assert_eq!(TEST_SPEC.log_bytes_in_region, 3);
126        assert_eq!(TEST_SPEC, LAST_LOCAL_SPEC);
127    }
128
129    #[test]
130    fn two_global_specs() {
131        define_side_metadata_specs!(
132            last_spec_as LAST_GLOBAL_SPEC,
133            TEST_SPEC1 = (global: true, log_num_of_bits: 0, log_bytes_in_region: 3),
134            TEST_SPEC2 = (global: true, log_num_of_bits: 1, log_bytes_in_region: 4),
135        );
136
137        assert!(TEST_SPEC1.is_global);
138        assert!(TEST_SPEC1.offset == GLOBAL_SIDE_METADATA_BASE_OFFSET);
139        assert_eq!(TEST_SPEC1.log_num_of_bits, 0);
140        assert_eq!(TEST_SPEC1.log_bytes_in_region, 3);
141
142        assert!(TEST_SPEC2.is_global);
143        assert!(TEST_SPEC2.offset == SideMetadataOffset::layout_after(&TEST_SPEC1));
144        assert_eq!(TEST_SPEC2.log_num_of_bits, 1);
145        assert_eq!(TEST_SPEC2.log_bytes_in_region, 4);
146
147        assert_eq!(TEST_SPEC2, LAST_GLOBAL_SPEC);
148    }
149
150    #[test]
151    fn three_global_specs() {
152        define_side_metadata_specs!(
153            last_spec_as LAST_GLOBAL_SPEC,
154            TEST_SPEC1 = (global: true, log_num_of_bits: 0, log_bytes_in_region: 3),
155            TEST_SPEC2 = (global: true, log_num_of_bits: 1, log_bytes_in_region: 4),
156            TEST_SPEC3 = (global: true, log_num_of_bits: 2, log_bytes_in_region: 5),
157        );
158
159        assert!(TEST_SPEC1.is_global);
160        assert!(TEST_SPEC1.offset == GLOBAL_SIDE_METADATA_BASE_OFFSET);
161        assert_eq!(TEST_SPEC1.log_num_of_bits, 0);
162        assert_eq!(TEST_SPEC1.log_bytes_in_region, 3);
163
164        assert!(TEST_SPEC2.is_global);
165        assert!(TEST_SPEC2.offset == SideMetadataOffset::layout_after(&TEST_SPEC1));
166        assert_eq!(TEST_SPEC2.log_num_of_bits, 1);
167        assert_eq!(TEST_SPEC2.log_bytes_in_region, 4);
168
169        assert!(TEST_SPEC3.is_global);
170        assert!(TEST_SPEC3.offset == SideMetadataOffset::layout_after(&TEST_SPEC2));
171        assert_eq!(TEST_SPEC3.log_num_of_bits, 2);
172        assert_eq!(TEST_SPEC3.log_bytes_in_region, 5);
173
174        assert_eq!(TEST_SPEC3, LAST_GLOBAL_SPEC);
175    }
176
177    #[test]
178    fn both_global_and_local() {
179        define_side_metadata_specs!(
180            last_spec_as LAST_GLOBAL_SPEC,
181            TEST_GSPEC1 = (global: true, log_num_of_bits: 0, log_bytes_in_region: 3),
182            TEST_GSPEC2 = (global: true, log_num_of_bits: 1, log_bytes_in_region: 4),
183        );
184        define_side_metadata_specs!(
185            last_spec_as LAST_LOCAL_SPEC,
186            TEST_LSPEC1 = (global: false, log_num_of_bits: 2, log_bytes_in_region: 5),
187            TEST_LSPEC2 = (global: false, log_num_of_bits: 3, log_bytes_in_region: 6),
188        );
189
190        assert!(TEST_GSPEC1.is_global);
191        assert!(TEST_GSPEC1.offset == GLOBAL_SIDE_METADATA_BASE_OFFSET);
192        assert_eq!(TEST_GSPEC1.log_num_of_bits, 0);
193        assert_eq!(TEST_GSPEC1.log_bytes_in_region, 3);
194
195        assert!(TEST_GSPEC2.is_global);
196        assert!(TEST_GSPEC2.offset == SideMetadataOffset::layout_after(&TEST_GSPEC1));
197        assert_eq!(TEST_GSPEC2.log_num_of_bits, 1);
198        assert_eq!(TEST_GSPEC2.log_bytes_in_region, 4);
199
200        assert_eq!(TEST_GSPEC2, LAST_GLOBAL_SPEC);
201
202        assert!(!TEST_LSPEC1.is_global);
203        assert!(TEST_LSPEC1.offset == LOCAL_SIDE_METADATA_BASE_OFFSET);
204        assert_eq!(TEST_LSPEC1.log_num_of_bits, 2);
205        assert_eq!(TEST_LSPEC1.log_bytes_in_region, 5);
206
207        assert!(!TEST_LSPEC2.is_global);
208        assert!(TEST_LSPEC2.offset == SideMetadataOffset::layout_after(&TEST_LSPEC1));
209        assert_eq!(TEST_LSPEC2.log_num_of_bits, 3);
210        assert_eq!(TEST_LSPEC2.log_bytes_in_region, 6);
211
212        assert_eq!(TEST_LSPEC2, LAST_LOCAL_SPEC);
213    }
214}