Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,13 @@ ro_space = []
# TODO: This is not properly implemented yet. We currently use an immortal space instead, and all our spaces have execution permission at the moment.
code_space = []

# metadata
global_alloc_bit = []
# Global valid object (VO) bit metadata.
# The VO bit is set when an object is allocated, and cleared when it is reclaimed.
# See `src/util/metadata/vo_bit.rs`
vo_bit = []

# conservative garbage collection support
is_mmtk_object = ["global_alloc_bit"]
is_mmtk_object = ["vo_bit"]

# Enable object pinning, in particular, enable pinning/unpinning, and its metadata
object_pinning = []
Expand Down
14 changes: 7 additions & 7 deletions src/memory_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -582,28 +582,28 @@ pub fn is_live_object(object: ObjectReference) -> bool {
/// 2. Also return true if there exists an `objref: ObjectReference` such that
/// - `objref` is a valid object reference to an object in any space in MMTk, and
/// - `lo <= objref.to_address() < hi`, where
/// - `lo = addr.align_down(ALLOC_BIT_REGION_SIZE)` and
/// - `hi = lo + ALLOC_BIT_REGION_SIZE` and
/// - `ALLOC_BIT_REGION_SIZE` is [`crate::util::is_mmtk_object::ALLOC_BIT_REGION_SIZE`].
/// It is the byte granularity of the alloc bit.
/// - `lo = addr.align_down(VO_BIT_REGION_SIZE)` and
/// - `hi = lo + VO_BIT_REGION_SIZE` and
/// - `VO_BIT_REGION_SIZE` is [`crate::util::is_mmtk_object::VO_BIT_REGION_SIZE`].
/// It is the byte granularity of the valid object (VO) bit.
/// 3. Return false otherwise. This function never panics.
///
/// Case 2 means **this function is imprecise for misaligned addresses**.
/// This function uses the "alloc bits" side metadata, i.e. a bitmap.
/// This function uses the "valid object (VO) bits" side metadata, i.e. a bitmap.
/// For space efficiency, each bit of the bitmap governs a small region of memory.
/// The size of a region is currently defined as the [minimum object size](crate::util::constants::MIN_OBJECT_SIZE),
/// which is currently defined as the [word size](crate::util::constants::BYTES_IN_WORD),
/// which is 4 bytes on 32-bit systems or 8 bytes on 64-bit systems.
/// The alignment of a region is also the region size.
/// If an alloc bit is `1`, the bitmap cannot tell which address within the 4-byte or 8-byte region
/// If a VO bit is `1`, the bitmap cannot tell which address within the 4-byte or 8-byte region
/// is the valid object reference.
/// Therefore, if the input `addr` is not properly aligned, but is close to a valid object
/// reference, this function may still return true.
///
/// For the reason above, the VM **must check if `addr` is properly aligned** before calling this
/// function. For most VMs, valid object references are always aligned to the word size, so
/// checking `addr.is_aligned_to(BYTES_IN_WORD)` should usually work. If you are paranoid, you can
/// always check against [`crate::util::is_mmtk_object::ALLOC_BIT_REGION_SIZE`].
/// always check against [`crate::util::is_mmtk_object::VO_BIT_REGION_SIZE`].
///
/// This function is useful for conservative root scanning. The VM can iterate through all words in
/// a stack, filter out zeros, misaligned words, obviously out-of-range words (such as addresses
Expand Down
2 changes: 1 addition & 1 deletion src/plan/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ pub struct BasePlan<VM: VMBinding> {
/// If VM space is present, it has some special interaction with the
/// `memory_manager::is_mmtk_object` and the `memory_manager::is_in_mmtk_spaces` functions.
///
/// - The `is_mmtk_object` funciton requires the alloc_bit side metadata to identify objects,
/// - The `is_mmtk_object` funciton requires the valid object (VO) bit side metadata to identify objects,
/// but currently we do not require the boot image to provide it, so it will not work if the
/// address argument is in the VM space.
///
Expand Down
16 changes: 8 additions & 8 deletions src/plan/markcompact/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ use crate::policy::space::Space;
use crate::scheduler::gc_work::*;
use crate::scheduler::*;
use crate::util::alloc::allocators::AllocatorSelector;
#[cfg(not(feature = "global_alloc_bit"))]
use crate::util::alloc_bit::ALLOC_SIDE_METADATA_SPEC;
use crate::util::copy::CopySemantics;
use crate::util::heap::VMRequest;
use crate::util::metadata::side_metadata::{SideMetadataContext, SideMetadataSanity};
#[cfg(not(feature = "vo_bit"))]
use crate::util::metadata::vo_bit::VO_BIT_SIDE_METADATA_SPEC;
use crate::util::opaque_pointer::*;
use crate::vm::VMBinding;

Expand Down Expand Up @@ -180,15 +180,15 @@ impl<VM: VMBinding> Plan for MarkCompact<VM> {

impl<VM: VMBinding> MarkCompact<VM> {
pub fn new(args: CreateGeneralPlanArgs<VM>) -> Self {
// if global_alloc_bit is enabled, ALLOC_SIDE_METADATA_SPEC will be added to
// if vo_bit is enabled, VO_BIT_SIDE_METADATA_SPEC will be added to
// SideMetadataContext by default, so we don't need to add it here.
#[cfg(feature = "global_alloc_bit")]
#[cfg(feature = "vo_bit")]
let global_side_metadata_specs = SideMetadataContext::new_global_specs(&[]);
// if global_alloc_bit is NOT enabled,
// we need to add ALLOC_SIDE_METADATA_SPEC to SideMetadataContext here.
#[cfg(not(feature = "global_alloc_bit"))]
// if vo_bit is NOT enabled,
// we need to add VO_BIT_SIDE_METADATA_SPEC to SideMetadataContext here.
#[cfg(not(feature = "vo_bit"))]
let global_side_metadata_specs =
SideMetadataContext::new_global_specs(&[ALLOC_SIDE_METADATA_SPEC]);
SideMetadataContext::new_global_specs(&[VO_BIT_SIDE_METADATA_SPEC]);

let mut plan_args = CreateSpecificPlanArgs {
global_args: args,
Expand Down
26 changes: 13 additions & 13 deletions src/policy/copyspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::policy::sft::SFT;
use crate::policy::space::{CommonSpace, Space};
use crate::scheduler::GCWorker;
use crate::util::copy::*;
#[cfg(feature = "global_alloc_bit")]
#[cfg(feature = "vo_bit")]
use crate::util::heap::layout::vm_layout_constants::BYTES_IN_CHUNK;
use crate::util::heap::{MonotonePageResource, PageResource};
use crate::util::metadata::{extract_side_metadata, MetadataSpec};
Expand Down Expand Up @@ -56,8 +56,8 @@ impl<VM: VMBinding> SFT for CopySpace<VM> {
}

fn initialize_object_metadata(&self, _object: ObjectReference, _alloc: bool) {
#[cfg(feature = "global_alloc_bit")]
crate::util::alloc_bit::set_alloc_bit::<VM>(_object);
#[cfg(feature = "vo_bit")]
crate::util::metadata::vo_bit::set_vo_bit::<VM>(_object);
}

fn get_forwarded_object(&self, object: ObjectReference) -> Option<ObjectReference> {
Expand All @@ -74,7 +74,7 @@ impl<VM: VMBinding> SFT for CopySpace<VM> {

#[cfg(feature = "is_mmtk_object")]
fn is_mmtk_object(&self, addr: Address) -> bool {
crate::util::alloc_bit::is_alloced_object::<VM>(addr).is_some()
crate::util::metadata::vo_bit::is_vo_bit_set_for_addr::<VM>(addr).is_some()
}

fn sft_trace_object(
Expand Down Expand Up @@ -172,21 +172,21 @@ impl<VM: VMBinding> CopySpace<VM> {

pub fn release(&self) {
unsafe {
#[cfg(feature = "global_alloc_bit")]
self.reset_alloc_bit();
#[cfg(feature = "vo_bit")]
self.reset_vo_bit();
self.pr.reset();
}
self.common.metadata.reset();
self.from_space.store(false, Ordering::SeqCst);
}

#[cfg(feature = "global_alloc_bit")]
unsafe fn reset_alloc_bit(&self) {
#[cfg(feature = "vo_bit")]
unsafe fn reset_vo_bit(&self) {
let current_chunk = self.pr.get_current_chunk();
if self.common.contiguous {
// If we have allocated something into this space, we need to clear its alloc bit.
// If we have allocated something into this space, we need to clear its VO bit.
if current_chunk != self.common.start {
crate::util::alloc_bit::bzero_alloc_bit(
crate::util::metadata::vo_bit::bzero_vo_bit(
self.common.start,
current_chunk + BYTES_IN_CHUNK - self.common.start,
);
Expand Down Expand Up @@ -218,10 +218,10 @@ impl<VM: VMBinding> CopySpace<VM> {
// This object is in from space, we will copy. Make sure we have a valid copy semantic.
debug_assert!(semantics.is_some());

#[cfg(feature = "global_alloc_bit")]
#[cfg(feature = "vo_bit")]
debug_assert!(
crate::util::alloc_bit::is_alloced::<VM>(object),
"{:x}: alloc bit not set",
crate::util::metadata::vo_bit::is_vo_bit_set::<VM>(object),
"{:x}: VO bit not set",
object
);

Expand Down
8 changes: 4 additions & 4 deletions src/policy/immix/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,8 @@ impl Block {

/// Deinitalize a block before releasing.
pub fn deinit(&self) {
#[cfg(feature = "global_alloc_bit")]
crate::util::alloc_bit::bzero_alloc_bit(self.start(), Self::BYTES);
#[cfg(feature = "vo_bit")]
crate::util::metadata::vo_bit::bzero_vo_bit(self.start(), Self::BYTES);
self.set_state(BlockState::Unallocated);
}

Expand Down Expand Up @@ -224,8 +224,8 @@ impl Block {
holes += 1;
}

#[cfg(feature = "global_alloc_bit")]
crate::util::alloc_bit::bzero_alloc_bit(line.start(), Line::BYTES);
#[cfg(feature = "vo_bit")]
crate::util::metadata::vo_bit::bzero_vo_bit(line.start(), Line::BYTES);

#[cfg(feature = "immix_zero_on_release")]
crate::util::memory::zero(line.start(), Line::BYTES);
Expand Down
18 changes: 9 additions & 9 deletions src/policy/immix/immixspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,12 @@ impl<VM: VMBinding> SFT for ImmixSpace<VM> {
true
}
fn initialize_object_metadata(&self, _object: ObjectReference, _alloc: bool) {
#[cfg(feature = "global_alloc_bit")]
crate::util::alloc_bit::set_alloc_bit::<VM>(_object);
#[cfg(feature = "vo_bit")]
crate::util::metadata::vo_bit::set_vo_bit::<VM>(_object);
}
#[cfg(feature = "is_mmtk_object")]
fn is_mmtk_object(&self, addr: Address) -> bool {
crate::util::alloc_bit::is_alloced_object::<VM>(addr).is_some()
crate::util::metadata::vo_bit::is_vo_bit_set_for_addr::<VM>(addr).is_some()
}
fn sft_trace_object(
&self,
Expand Down Expand Up @@ -485,10 +485,10 @@ impl<VM: VMBinding> ImmixSpace<VM> {
queue: &mut impl ObjectQueue,
object: ObjectReference,
) -> ObjectReference {
#[cfg(feature = "global_alloc_bit")]
#[cfg(feature = "vo_bit")]
debug_assert!(
crate::util::alloc_bit::is_alloced::<VM>(object),
"{:x}: alloc bit not set",
crate::util::metadata::vo_bit::is_vo_bit_set::<VM>(object),
"{:x}: VO bit not set",
object
);
if self.attempt_mark(object, self.mark_state) {
Expand Down Expand Up @@ -520,10 +520,10 @@ impl<VM: VMBinding> ImmixSpace<VM> {
) -> ObjectReference {
let copy_context = worker.get_copy_context_mut();
debug_assert!(!super::BLOCK_ONLY);
#[cfg(feature = "global_alloc_bit")]
#[cfg(feature = "vo_bit")]
debug_assert!(
crate::util::alloc_bit::is_alloced::<VM>(object),
"{:x}: alloc bit not set",
crate::util::metadata::vo_bit::is_vo_bit_set::<VM>(object),
"{:x}: VO bit not set",
object
);
let forwarding_status = ForwardingWord::attempt_to_forward::<VM>(object);
Expand Down
12 changes: 6 additions & 6 deletions src/policy/immortalspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,12 @@ impl<VM: VMBinding> SFT for ImmortalSpace<VM> {
if self.common.needs_log_bit {
VM::VMObjectModel::GLOBAL_LOG_BIT_SPEC.mark_as_unlogged::<VM>(object, Ordering::SeqCst);
}
#[cfg(feature = "global_alloc_bit")]
crate::util::alloc_bit::set_alloc_bit::<VM>(object);
#[cfg(feature = "vo_bit")]
crate::util::metadata::vo_bit::set_vo_bit::<VM>(object);
}
#[cfg(feature = "is_mmtk_object")]
fn is_mmtk_object(&self, addr: Address) -> bool {
crate::util::alloc_bit::is_alloced_object::<VM>(addr).is_some()
crate::util::metadata::vo_bit::is_vo_bit_set_for_addr::<VM>(addr).is_some()
}
fn sft_trace_object(
&self,
Expand Down Expand Up @@ -192,10 +192,10 @@ impl<VM: VMBinding> ImmortalSpace<VM> {
queue: &mut Q,
object: ObjectReference,
) -> ObjectReference {
#[cfg(feature = "global_alloc_bit")]
#[cfg(feature = "vo_bit")]
debug_assert!(
crate::util::alloc_bit::is_alloced::<VM>(object),
"{:x}: alloc bit not set",
crate::util::metadata::vo_bit::is_vo_bit_set::<VM>(object),
"{:x}: VO bit not set",
object
);
if ImmortalSpace::<VM>::test_and_mark(object, self.mark_state) {
Expand Down
16 changes: 8 additions & 8 deletions src/policy/largeobjectspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,13 @@ impl<VM: VMBinding> SFT for LargeObjectSpace<VM> {
VM::VMObjectModel::GLOBAL_LOG_BIT_SPEC.mark_as_unlogged::<VM>(object, Ordering::SeqCst);
}

#[cfg(feature = "global_alloc_bit")]
crate::util::alloc_bit::set_alloc_bit::<VM>(object);
#[cfg(feature = "vo_bit")]
crate::util::metadata::vo_bit::set_vo_bit::<VM>(object);
self.treadmill.add_to_treadmill(object, alloc);
}
#[cfg(feature = "is_mmtk_object")]
fn is_mmtk_object(&self, addr: Address) -> bool {
crate::util::alloc_bit::is_alloced_object::<VM>(addr).is_some()
crate::util::metadata::vo_bit::is_vo_bit_set_for_addr::<VM>(addr).is_some()
}
fn sft_trace_object(
&self,
Expand Down Expand Up @@ -189,10 +189,10 @@ impl<VM: VMBinding> LargeObjectSpace<VM> {
queue: &mut Q,
object: ObjectReference,
) -> ObjectReference {
#[cfg(feature = "global_alloc_bit")]
#[cfg(feature = "vo_bit")]
debug_assert!(
crate::util::alloc_bit::is_alloced::<VM>(object),
"{:x}: alloc bit not set",
crate::util::metadata::vo_bit::is_vo_bit_set::<VM>(object),
"{:x}: VO bit not set",
object
);
let nursery_object = self.is_in_nursery(object);
Expand Down Expand Up @@ -225,8 +225,8 @@ impl<VM: VMBinding> LargeObjectSpace<VM> {

fn sweep_large_pages(&mut self, sweep_nursery: bool) {
let sweep = |object: ObjectReference| {
#[cfg(feature = "global_alloc_bit")]
crate::util::alloc_bit::unset_alloc_bit::<VM>(object);
#[cfg(feature = "vo_bit")]
crate::util::metadata::vo_bit::unset_vo_bit::<VM>(object);
self.pr
.release_pages(get_super_page(object.to_object_start::<VM>()));
};
Expand Down
6 changes: 3 additions & 3 deletions src/policy/lockfreeimmortalspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,12 @@ impl<VM: VMBinding> SFT for LockFreeImmortalSpace<VM> {
unimplemented!()
}
fn initialize_object_metadata(&self, _object: ObjectReference, _alloc: bool) {
#[cfg(feature = "global_alloc_bit")]
crate::util::alloc_bit::set_alloc_bit::<VM>(_object);
#[cfg(feature = "vo_bit")]
crate::util::metadata::vo_bit::set_vo_bit::<VM>(_object);
}
#[cfg(feature = "is_mmtk_object")]
fn is_mmtk_object(&self, addr: Address) -> bool {
crate::util::alloc_bit::is_alloced_object::<VM>(addr).is_some()
crate::util::metadata::vo_bit::is_vo_bit_set_for_addr::<VM>(addr).is_some()
}
fn sft_trace_object(
&self,
Expand Down
24 changes: 12 additions & 12 deletions src/policy/markcompactspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use crate::util::alloc::allocator::align_allocation_no_fill;
use crate::util::constants::LOG_BYTES_IN_WORD;
use crate::util::copy::CopySemantics;
use crate::util::heap::{MonotonePageResource, PageResource};
use crate::util::metadata::extract_side_metadata;
use crate::util::{alloc_bit, Address, ObjectReference};
use crate::util::metadata::{extract_side_metadata, vo_bit};
use crate::util::{Address, ObjectReference};
use crate::{vm::*, ObjectQueue};
use atomic::Ordering;

Expand Down Expand Up @@ -69,7 +69,7 @@ impl<VM: VMBinding> SFT for MarkCompactSpace<VM> {
}

fn initialize_object_metadata(&self, object: ObjectReference, _alloc: bool) {
crate::util::alloc_bit::set_alloc_bit::<VM>(object);
crate::util::metadata::vo_bit::set_vo_bit::<VM>(object);
}

#[cfg(feature = "sanity")]
Expand All @@ -79,7 +79,7 @@ impl<VM: VMBinding> SFT for MarkCompactSpace<VM> {

#[cfg(feature = "is_mmtk_object")]
fn is_mmtk_object(&self, addr: Address) -> bool {
crate::util::alloc_bit::is_alloced_object::<VM>(addr).is_some()
crate::util::metadata::vo_bit::is_vo_bit_set_for_addr::<VM>(addr).is_some()
}

fn sft_trace_object(
Expand Down Expand Up @@ -218,8 +218,8 @@ impl<VM: VMBinding> MarkCompactSpace<VM> {
object: ObjectReference,
) -> ObjectReference {
debug_assert!(
crate::util::alloc_bit::is_alloced::<VM>(object),
"{:x}: alloc bit not set",
crate::util::metadata::vo_bit::is_vo_bit_set::<VM>(object),
"{:x}: VO bit not set",
object
);
if MarkCompactSpace::<VM>::test_and_mark(object) {
Expand All @@ -234,8 +234,8 @@ impl<VM: VMBinding> MarkCompactSpace<VM> {
object: ObjectReference,
) -> ObjectReference {
debug_assert!(
crate::util::alloc_bit::is_alloced::<VM>(object),
"{:x}: alloc bit not set",
crate::util::metadata::vo_bit::is_vo_bit_set::<VM>(object),
"{:x}: VO bit not set",
object
);
// from this stage and onwards, mark bit is no longer needed
Expand Down Expand Up @@ -363,8 +363,8 @@ impl<VM: VMBinding> MarkCompactSpace<VM> {
start, end,
);
for obj in linear_scan {
// clear the alloc bit
alloc_bit::unset_alloc_bit::<VM>(obj);
// clear the VO bit
vo_bit::unset_vo_bit::<VM>(obj);

let forwarding_pointer = Self::get_header_forwarding_pointer(obj);

Expand All @@ -377,8 +377,8 @@ impl<VM: VMBinding> MarkCompactSpace<VM> {
// copy object
trace!(" copy from {} to {}", obj, new_object);
let end_of_new_object = VM::VMObjectModel::copy_to(obj, new_object, Address::ZERO);
// update alloc_bit,
alloc_bit::set_alloc_bit::<VM>(new_object);
// update VO bit,
vo_bit::set_vo_bit::<VM>(new_object);
to = new_object.to_object_start::<VM>() + copied_size;
debug_assert_eq!(end_of_new_object, to);
}
Expand Down
Loading