mmtk/policy/marksweepspace/malloc_ms/
metadata.rs

1use crate::util::metadata::side_metadata;
2use crate::util::metadata::side_metadata::SideMetadataSpec;
3use crate::util::metadata::vo_bit;
4use crate::util::Address;
5use crate::util::ObjectReference;
6use crate::vm::{ObjectModel, VMBinding};
7use std::sync::atomic::Ordering;
8
9/// Metadata spec for the active page byte
10///
11/// The active page metadata is used to accurately track the total number of pages that have
12/// been reserved by `malloc()`.
13///
14/// We use a byte instead of a bit to avoid synchronization costs, i.e. to avoid
15/// the case where two threads try to update different bits in the same byte at
16/// the same time
17// XXX: This metadata spec is currently unused as we need to add a performant way to calculate
18// how many pages are active in this metadata spec. Explore SIMD vectorization with 8-bit integers
19pub(crate) const ACTIVE_PAGE_METADATA_SPEC: SideMetadataSpec =
20    crate::util::metadata::side_metadata::spec_defs::MALLOC_MS_ACTIVE_PAGE;
21
22pub(crate) const OFFSET_MALLOC_METADATA_SPEC: SideMetadataSpec =
23    crate::util::metadata::side_metadata::spec_defs::MS_OFFSET_MALLOC;
24
25pub fn is_marked<VM: VMBinding>(object: ObjectReference, ordering: Ordering) -> bool {
26    VM::VMObjectModel::LOCAL_MARK_BIT_SPEC.load_atomic::<VM, u8>(object, None, ordering) == 1
27}
28
29pub unsafe fn is_marked_unsafe<VM: VMBinding>(object: ObjectReference) -> bool {
30    VM::VMObjectModel::LOCAL_MARK_BIT_SPEC.load::<VM, u8>(object, None) == 1
31}
32
33/// Set the page mark from 0 to 1. Return true if we set it successfully in this call.
34pub(super) fn compare_exchange_set_page_mark(page_addr: Address) -> bool {
35    // The spec has 1 byte per each page. So it won't be the case that other threads may race and access other bits for the spec.
36    // If the compare-exchange fails, we know the byte was set to 1 before this call.
37    ACTIVE_PAGE_METADATA_SPEC
38        .compare_exchange_atomic::<u8>(page_addr, 0, 1, Ordering::SeqCst, Ordering::SeqCst)
39        .is_ok()
40}
41
42#[allow(unused)]
43pub(super) fn is_page_marked(page_addr: Address) -> bool {
44    ACTIVE_PAGE_METADATA_SPEC.load_atomic::<u8>(page_addr, Ordering::SeqCst) == 1
45}
46
47#[allow(unused)]
48pub(super) unsafe fn is_page_marked_unsafe(page_addr: Address) -> bool {
49    ACTIVE_PAGE_METADATA_SPEC.load::<u8>(page_addr) == 1
50}
51
52pub fn set_vo_bit(object: ObjectReference) {
53    vo_bit::set_vo_bit(object);
54}
55
56pub fn set_mark_bit<VM: VMBinding>(object: ObjectReference, ordering: Ordering) {
57    VM::VMObjectModel::LOCAL_MARK_BIT_SPEC.store_atomic::<VM, u8>(object, 1, None, ordering);
58}
59
60#[allow(unused)]
61pub fn unset_vo_bit(object: ObjectReference) {
62    vo_bit::unset_vo_bit(object);
63}
64
65#[allow(unused)]
66pub(super) fn set_page_mark(page_addr: Address) {
67    ACTIVE_PAGE_METADATA_SPEC.store_atomic::<u8>(page_addr, 1, Ordering::SeqCst);
68}
69
70/// Is this allocation an offset malloc? The argument address should be the allocation address (object start)
71pub(super) fn is_offset_malloc(address: Address) -> bool {
72    unsafe { OFFSET_MALLOC_METADATA_SPEC.load::<u8>(address) == 1 }
73}
74
75/// Set the offset bit for the allocation. The argument address should be the allocation address (object start)
76pub(super) fn set_offset_malloc_bit(address: Address) {
77    OFFSET_MALLOC_METADATA_SPEC.store_atomic::<u8>(address, 1, Ordering::SeqCst);
78}
79
80/// Unset the offset bit for the allocation. The argument address should be the allocation address (object start)
81pub(super) unsafe fn unset_offset_malloc_bit_unsafe(address: Address) {
82    OFFSET_MALLOC_METADATA_SPEC.store::<u8>(address, 0);
83}
84
85pub unsafe fn unset_vo_bit_unsafe(object: ObjectReference) {
86    vo_bit::unset_vo_bit_unsafe(object);
87}
88
89#[allow(unused)]
90pub unsafe fn unset_mark_bit<VM: VMBinding>(object: ObjectReference) {
91    VM::VMObjectModel::LOCAL_MARK_BIT_SPEC.store::<VM, u8>(object, 0, None);
92}
93
94#[allow(unused)]
95pub(super) unsafe fn unset_page_mark_unsafe(page_addr: Address) {
96    ACTIVE_PAGE_METADATA_SPEC.store::<u8>(page_addr, 0)
97}
98
99/// Load u128 bits of side metadata
100///
101/// # Safety
102/// unsafe as it can segfault if one tries to read outside the bounds of the mapped side metadata
103pub(super) unsafe fn load128(metadata_spec: &SideMetadataSpec, data_addr: Address) -> u128 {
104    let meta_addr = side_metadata::address_to_meta_address(metadata_spec, data_addr);
105
106    #[cfg(all(debug_assertions, feature = "extreme_assertions"))]
107    metadata_spec.assert_metadata_mapped(data_addr);
108
109    meta_addr.load::<u128>()
110}