Skip to content

Commit 2e548e5

Browse files
authored
Allow setting object metadata for VM space objects. Expose VO bit under a feature. (#1248)
This PR changes a few things for vo bit: 1. Add a function to set object metadata for an object in the VM space: `MMTK::initialize_vm_space_object`. 2. Add a feature `vo_bit_access` to expose VO bit and a binding may use it at its own risk. 3. Mark VO bit side metadata base address only avilable for 64 bits. The second is needed for Julia. The Julia binding uses MMTk immortal allocation or VM space for a region of memory, and pop the regions with boot image objects with no clear way to identify each object. The easist workaround is to bulk set VO bit for the region. The problem from this is that MMTk cannot identify valid objects in those regions. However, Julia binding only uses VO bit for pinning objects. Objects in the immortal space or the VM space will not be moved so failing to pinning objects in those regions is benign. Currently the Julia binding duplicates a bunch of side metadata code to bulk set VO bit only using the VO bit side metadata base address. See mmtk/mmtk-julia#200
1 parent 3c1418a commit 2e548e5

File tree

5 files changed

+53
-18
lines changed

5 files changed

+53
-18
lines changed

Cargo.toml

+10
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,16 @@ bpftrace_workaround = []
183183
# users can disable such annotations by enabling this Cargo feature.
184184
no_mmap_annotation = []
185185

186+
# Allow the binding to access Valid Object (VO) bit.
187+
# MMTk uses VO bit to identify a valid object. Thus VO bit is carefully managed by MMTk in cooperation with the binding.
188+
# So normally this feature is not needed, and its use should be discouraged.
189+
# However, in rare cases, a binding may want to directly access and manipulate VO bit. For example, a binding cannot cooperate
190+
# with MMTk to identify each object for setting the VO bit. This is usually due to the limitation of the VM.
191+
# In such cases, a binding may use this feature and manipulate the VO bit to their needs. The binding's manipulation on VO bit
192+
# may violate MMTk's semantics, and may result in undefined behaviors for VO bit related APIs. This feature should
193+
# only be used if you understand how VO bit works internally. Use at your own risk.
194+
vo_bit_access = []
195+
186196
# Do not modify the following line - ci-common.sh matches it
187197
# -- Mutally exclusive features --
188198
# Only one feature from each group can be provided. Otherwise build will fail.

src/mmtk.rs

+12
Original file line numberDiff line numberDiff line change
@@ -584,4 +584,16 @@ impl<VM: VMBinding> MMTK<VM> {
584584
});
585585
result_so_far
586586
}
587+
588+
/// Initialize object metadata for a VM space object.
589+
/// Objects in the VM space are allocated/managed by the binding. This function provides a way for
590+
/// the binding to set object metadata in MMTk for an object in the space.
591+
#[cfg(feature = "vm_space")]
592+
pub fn initialize_vm_space_object(&self, object: crate::util::ObjectReference) {
593+
use crate::policy::sft::SFT;
594+
self.get_plan()
595+
.base()
596+
.vm_space
597+
.initialize_object_metadata(object, false)
598+
}
587599
}

src/util/metadata/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -222,11 +222,11 @@ mod global;
222222
pub mod header_metadata;
223223
mod metadata_val_traits;
224224
pub mod side_metadata;
225+
pub mod vo_bit;
225226
pub use metadata_val_traits::*;
226227

227228
pub(crate) mod log_bit;
228229
pub(crate) mod mark_bit;
229230
pub(crate) mod pin_bit;
230-
pub(crate) mod vo_bit;
231231

232232
pub use global::*;

src/util/metadata/side_metadata/constants.rs

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ pub(crate) const GLOBAL_SIDE_METADATA_BASE_OFFSET: SideMetadataOffset =
3030
SideMetadataOffset::addr(GLOBAL_SIDE_METADATA_BASE_ADDRESS);
3131

3232
/// Base address of VO bit, public to VM bindings which may need to use this.
33+
#[cfg(target_pointer_width = "64")]
3334
pub const VO_BIT_SIDE_METADATA_ADDR: Address =
3435
crate::util::metadata::vo_bit::VO_BIT_SIDE_METADATA_ADDR;
3536

src/util/metadata/vo_bit/mod.rs

+29-17
Original file line numberDiff line numberDiff line change
@@ -54,26 +54,38 @@ use crate::util::ObjectReference;
5454
use crate::vm::object_model::ObjectModel;
5555
use crate::vm::VMBinding;
5656

57-
/// A VO bit is required per min-object-size aligned address, rather than per object, and can only exist as side metadata.
58-
pub(crate) const VO_BIT_SIDE_METADATA_SPEC: SideMetadataSpec =
59-
crate::util::metadata::side_metadata::spec_defs::VO_BIT;
57+
cfg_if::cfg_if! {
58+
if #[cfg(feature = "vo_bit_access")] {
59+
/// A VO bit is required per min-object-size aligned address, rather than per object, and can only exist as side metadata.
60+
/// This is only publicly available when the feature "vo_bit_access" is enabled.
61+
/// Check the comments on "vo_bit_access" in `Cargo.toml` before use. Use at your own risk.
62+
pub const VO_BIT_SIDE_METADATA_SPEC: SideMetadataSpec =
63+
crate::util::metadata::side_metadata::spec_defs::VO_BIT;
64+
} else {
65+
/// A VO bit is required per min-object-size aligned address, rather than per object, and can only exist as side metadata.
66+
pub(crate) const VO_BIT_SIDE_METADATA_SPEC: SideMetadataSpec =
67+
crate::util::metadata::side_metadata::spec_defs::VO_BIT;
68+
}
69+
}
6070

71+
/// The base address for VO bit side metadata on 64 bits platforms.
72+
#[cfg(target_pointer_width = "64")]
6173
pub const VO_BIT_SIDE_METADATA_ADDR: Address = VO_BIT_SIDE_METADATA_SPEC.get_absolute_offset();
6274

6375
/// Atomically set the VO bit for an object.
64-
pub fn set_vo_bit(object: ObjectReference) {
76+
pub(crate) fn set_vo_bit(object: ObjectReference) {
6577
debug_assert!(!is_vo_bit_set(object), "{:x}: VO bit already set", object);
6678
VO_BIT_SIDE_METADATA_SPEC.store_atomic::<u8>(object.to_raw_address(), 1, Ordering::SeqCst);
6779
}
6880

6981
/// Atomically unset the VO bit for an object.
70-
pub fn unset_vo_bit(object: ObjectReference) {
82+
pub(crate) fn unset_vo_bit(object: ObjectReference) {
7183
debug_assert!(is_vo_bit_set(object), "{:x}: VO bit not set", object);
7284
VO_BIT_SIDE_METADATA_SPEC.store_atomic::<u8>(object.to_raw_address(), 0, Ordering::SeqCst);
7385
}
7486

7587
/// Atomically unset the VO bit for an object, regardless whether the bit is set or not.
76-
pub fn unset_vo_bit_nocheck(object: ObjectReference) {
88+
pub(crate) fn unset_vo_bit_nocheck(object: ObjectReference) {
7789
VO_BIT_SIDE_METADATA_SPEC.store_atomic::<u8>(object.to_raw_address(), 0, Ordering::SeqCst);
7890
}
7991

@@ -83,21 +95,21 @@ pub fn unset_vo_bit_nocheck(object: ObjectReference) {
8395
/// # Safety
8496
///
8597
/// This is unsafe: check the comment on `side_metadata::store`
86-
pub unsafe fn unset_vo_bit_unsafe(object: ObjectReference) {
98+
pub(crate) unsafe fn unset_vo_bit_unsafe(object: ObjectReference) {
8799
debug_assert!(is_vo_bit_set(object), "{:x}: VO bit not set", object);
88100
VO_BIT_SIDE_METADATA_SPEC.store::<u8>(object.to_raw_address(), 0);
89101
}
90102

91103
/// Check if the VO bit is set for an object.
92-
pub fn is_vo_bit_set(object: ObjectReference) -> bool {
104+
pub(crate) fn is_vo_bit_set(object: ObjectReference) -> bool {
93105
VO_BIT_SIDE_METADATA_SPEC.load_atomic::<u8>(object.to_raw_address(), Ordering::SeqCst) == 1
94106
}
95107

96108
/// Check if an address can be turned directly into an object reference using the VO bit.
97109
/// If so, return `Some(object)`. Otherwise return `None`.
98110
///
99111
/// The `address` must be word-aligned.
100-
pub fn is_vo_bit_set_for_addr(address: Address) -> Option<ObjectReference> {
112+
pub(crate) fn is_vo_bit_set_for_addr(address: Address) -> Option<ObjectReference> {
101113
is_vo_bit_set_inner::<true>(address)
102114
}
103115

@@ -110,7 +122,7 @@ pub fn is_vo_bit_set_for_addr(address: Address) -> Option<ObjectReference> {
110122
/// # Safety
111123
///
112124
/// This is unsafe: check the comment on `side_metadata::load`
113-
pub unsafe fn is_vo_bit_set_unsafe(address: Address) -> Option<ObjectReference> {
125+
pub(crate) unsafe fn is_vo_bit_set_unsafe(address: Address) -> Option<ObjectReference> {
114126
is_vo_bit_set_inner::<false>(address)
115127
}
116128

@@ -135,7 +147,7 @@ fn is_vo_bit_set_inner<const ATOMIC: bool>(addr: Address) -> Option<ObjectRefere
135147
}
136148

137149
/// Bulk zero the VO bit.
138-
pub fn bzero_vo_bit(start: Address, size: usize) {
150+
pub(crate) fn bzero_vo_bit(start: Address, size: usize) {
139151
VO_BIT_SIDE_METADATA_SPEC.bzero_metadata(start, size);
140152
}
141153

@@ -145,7 +157,7 @@ pub fn bzero_vo_bit(start: Address, size: usize) {
145157
/// As an alternative, this function copies the mark bits metadata to VO bits.
146158
/// The caller needs to ensure the mark bits are set exactly wherever VO bits need to be set before
147159
/// calling this function.
148-
pub fn bcopy_vo_bit_from_mark_bit<VM: VMBinding>(start: Address, size: usize) {
160+
pub(crate) fn bcopy_vo_bit_from_mark_bit<VM: VMBinding>(start: Address, size: usize) {
149161
let mark_bit_spec = VM::VMObjectModel::LOCAL_MARK_BIT_SPEC;
150162
debug_assert!(
151163
mark_bit_spec.is_on_side(),
@@ -158,19 +170,19 @@ pub fn bcopy_vo_bit_from_mark_bit<VM: VMBinding>(start: Address, size: usize) {
158170
use crate::util::constants::{LOG_BITS_IN_BYTE, LOG_BYTES_IN_ADDRESS};
159171

160172
/// How many data memory bytes does 1 word in the VO bit side metadata represents?
161-
pub const VO_BIT_WORD_TO_REGION: usize = 1
173+
pub(crate) const VO_BIT_WORD_TO_REGION: usize = 1
162174
<< (VO_BIT_SIDE_METADATA_SPEC.log_bytes_in_region
163175
+ LOG_BITS_IN_BYTE as usize
164176
+ LOG_BYTES_IN_ADDRESS as usize
165177
- VO_BIT_SIDE_METADATA_SPEC.log_num_of_bits);
166178

167179
/// Bulk check if a VO bit word. Return true if there is any bit set in the word.
168-
pub fn get_raw_vo_bit_word(addr: Address) -> usize {
180+
pub(crate) fn get_raw_vo_bit_word(addr: Address) -> usize {
169181
unsafe { VO_BIT_SIDE_METADATA_SPEC.load_raw_word(addr) }
170182
}
171183

172184
/// Find the base reference to the object from a potential internal pointer.
173-
pub fn find_object_from_internal_pointer<VM: VMBinding>(
185+
pub(crate) fn find_object_from_internal_pointer<VM: VMBinding>(
174186
start: Address,
175187
search_limit_bytes: usize,
176188
) -> Option<ObjectReference> {
@@ -203,7 +215,7 @@ fn is_internal_ptr<VM: VMBinding>(obj: ObjectReference, internal_ptr: Address) -
203215
}
204216

205217
/// Check if the address could be an internal pointer based on where VO bit is set.
206-
pub fn is_internal_ptr_from_vo_bit<VM: VMBinding>(
218+
pub(crate) fn is_internal_ptr_from_vo_bit<VM: VMBinding>(
207219
vo_addr: Address,
208220
internal_ptr: Address,
209221
) -> Option<ObjectReference> {
@@ -219,6 +231,6 @@ pub fn is_internal_ptr_from_vo_bit<VM: VMBinding>(
219231
///
220232
/// # Safety
221233
/// The caller needs to make sure that no one is modifying VO bit.
222-
pub unsafe fn is_vo_addr(addr: Address) -> bool {
234+
pub(crate) unsafe fn is_vo_addr(addr: Address) -> bool {
223235
VO_BIT_SIDE_METADATA_SPEC.load::<u8>(addr) != 0
224236
}

0 commit comments

Comments
 (0)