Skip to content

Object enumeration also returns the space name and the region #1300

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
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
2 changes: 1 addition & 1 deletion .github/scripts/ci-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ find ./src ./tests -type f -name "mock_test_*" | while read -r file; do
# Get the required plans.
# Some tests need to be run with multiple plans because
# some bugs can only be reproduced in some plans but not others.
PLANS=$(sed -n 's/^\/\/ *GITHUB-CI: *MMTK_PLAN=//p' $file)
PLANS=$(sed -n 's/^\/\/ *GITHUB-CI: *MMTK_PLAN=//p' $file | tr ',' '\n')
if [[ $PLANS == 'all' ]]; then
PLANS=$ALL_PLANS
elif [[ -z $PLANS ]]; then
Expand Down
11 changes: 6 additions & 5 deletions src/mmtk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ use crate::plan::Plan;
use crate::policy::sft_map::{create_sft_map, SFTMap};
use crate::scheduler::GCWorkScheduler;

#[cfg(feature = "vo_bit")]
use crate::util::address::ObjectReference;
#[cfg(feature = "analysis")]
use crate::util::analysis::AnalysisManager;
use crate::util::finalizable_processor::FinalizableProcessor;
Expand All @@ -24,6 +22,8 @@ use crate::util::sanity::sanity_checker::SanityChecker;
#[cfg(feature = "extreme_assertions")]
use crate::util::slot_logger::SlotLogger;
use crate::util::statistics::stats::Stats;
#[cfg(feature = "vo_bit")]
use crate::util::EnumeratedObject;
use crate::vm::ReferenceGlue;
use crate::vm::VMBinding;
use std::cell::UnsafeCell;
Expand Down Expand Up @@ -516,15 +516,16 @@ impl<VM: VMBinding> MMTK<VM> {
///
/// [os_eo]: https://docs.ruby-lang.org/en/master/ObjectSpace.html#method-c-each_object
#[cfg(feature = "vo_bit")]
pub fn enumerate_objects<F>(&self, f: F)
pub fn enumerate_objects<F>(&self, mut f: F)
where
F: FnMut(ObjectReference),
F: FnMut(EnumeratedObject),
{
use crate::util::object_enum;

let mut enumerator = object_enum::ClosureObjectEnumerator::<_, VM>::new(f);
let plan = self.get_plan();
plan.for_each_space(&mut |space| {
let mut enumerator =
object_enum::ClosureObjectEnumerator::<_, VM>::new(space.get_name(), &mut f);
space.enumerate_objects(&mut enumerator);
})
}
Expand Down
1 change: 1 addition & 0 deletions src/util/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,5 @@ mod raw_memory_freelist;

pub use self::address::Address;
pub use self::address::ObjectReference;
pub use self::object_enum::EnumeratedObject;
pub use self::opaque_pointer::*;
67 changes: 56 additions & 11 deletions src/util/object_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,29 @@ use super::{
Address, ObjectReference,
};

/// The object that gets enumerated.
#[derive(PartialEq, Eq, Hash, Copy, Clone)]
pub enum EnumeratedObject<'a> {
/// A single object
Single {
/// The name of the space where the object is located
space_name: &'a str,
/// The reference to the object
reference: ObjectReference,
},
/// An object in a block. Blocks are memory regions with fixed sizes.
InBlock {
/// The name of the space where the object is located
space_name: &'a str,
/// The reference to the object
reference: ObjectReference,
/// The start address of the block
block_start: Address,
/// The size of the block in bytes
block_size: usize,
},
}

/// A trait for enumerating objects in spaces, used by [`Space::enumerate_objects`].
///
/// [`Space::enumerate_objects`]: crate::policy::space::Space::enumerate_objects
Expand All @@ -22,44 +45,66 @@ pub trait ObjectEnumerator {
fn visit_object(&mut self, object: ObjectReference);
/// Visit an address range that may contain objects.
fn visit_address_range(&mut self, start: Address, end: Address);
/// Visit a block of memory that may contain objects. Blocks are address ranges with a fixed size.
fn visit_block(&mut self, block_start: Address, block_size: usize);
}

/// An implementation of `ObjectEnumerator` that wraps a callback.
pub struct ClosureObjectEnumerator<F, VM>
pub struct ClosureObjectEnumerator<'a, F, VM>
where
F: FnMut(ObjectReference),
F: FnMut(EnumeratedObject),
VM: VMBinding,
{
object_callback: F,
space_name: &'a str,
object_callback: &'a mut F,
phantom_data: PhantomData<VM>,
}

impl<F, VM> ClosureObjectEnumerator<F, VM>
impl<'a, F, VM> ClosureObjectEnumerator<'a, F, VM>
where
F: FnMut(ObjectReference),
F: FnMut(EnumeratedObject),
VM: VMBinding,
{
pub fn new(object_callback: F) -> Self {
pub fn new(space_name: &'a str, object_callback: &'a mut F) -> Self {
Self {
space_name,
object_callback,
phantom_data: PhantomData,
}
}
}

impl<F, VM> ObjectEnumerator for ClosureObjectEnumerator<F, VM>
impl<F, VM> ObjectEnumerator for ClosureObjectEnumerator<'_, F, VM>
where
F: FnMut(ObjectReference),
F: FnMut(EnumeratedObject),
VM: VMBinding,
{
fn visit_object(&mut self, object: ObjectReference) {
(self.object_callback)(object);
(self.object_callback)(EnumeratedObject::Single {
space_name: self.space_name,
reference: object,
});
}

fn visit_address_range(&mut self, start: Address, end: Address) {
VO_BIT.scan_non_zero_values::<u8>(start, end, &mut |address| {
let object = vo_bit::get_object_ref_for_vo_addr(address);
(self.object_callback)(object);
(self.object_callback)(EnumeratedObject::Single {
space_name: self.space_name,
reference: object,
});
})
}

fn visit_block(&mut self, block_start: Address, block_size: usize) {
VO_BIT.scan_non_zero_values::<u8>(block_start, block_start + block_size, &mut |address| {
let object = vo_bit::get_object_ref_for_vo_addr(address);
(self.object_callback)(EnumeratedObject::InBlock {
space_name: self.space_name,
reference: object,
block_start,
block_size,
});
})
}
}
Expand Down Expand Up @@ -88,7 +133,7 @@ pub(crate) fn enumerate_blocks_from_chunk_map<B>(
if chunk_map.get(chunk) == ChunkState::Allocated {
for block in chunk.iter_region::<B>() {
if block.may_have_objects() {
enumerator.visit_address_range(block.start(), block.end());
enumerator.visit_block(block.start(), B::BYTES);
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/vm/tests/mock_tests/mock_test_doc_mutator_storage.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// GITHUB-CI: MMTK_PLAN=NoGC,SemiSpace,Immix,GenImmix,StickyImmix
// GITHUB-CI: MMTK_PLAN=NoGC,SemiSpace,GenImmix
// The test assumes the default allocator is a bump pointer allocator, thus only works for plans that use BumpAlloator (not ImmixAllocator).

use super::mock_test_prelude::*;

Expand Down
7 changes: 5 additions & 2 deletions src/vm/tests/mock_tests/mock_test_heap_traversal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,11 @@ lazy_static! {

pub fn get_all_objects(mmtk: &'static MMTK<MockVM>) -> HashSet<ObjectReference> {
let mut result = HashSet::new();
mmtk.enumerate_objects(|object| {
result.insert(object);
mmtk.enumerate_objects(|object: EnumeratedObject| {
result.insert(match object {
EnumeratedObject::Single { reference, .. } => reference,
EnumeratedObject::InBlock { reference, .. } => reference,
});
});
result
}
Expand Down
Loading