Skip to content

Introduce SpaceInspector and RegionInspector #1322

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 2 commits 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
4 changes: 2 additions & 2 deletions macros/src/has_spaces_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,12 @@ pub(crate) fn generate_impl_items<'a>(
};

quote! {
fn for_each_space(&self, __func: &mut dyn FnMut(&dyn Space<VM>)) {
fn for_each_space<'a>(&'a self, __func: &mut dyn FnMut(&'a dyn Space<VM>)) {
#(#space_visitors)*
#parent_visitor
}

fn for_each_space_mut(&mut self, __func: &mut dyn FnMut(&mut dyn Space<VM>)) {
fn for_each_space_mut<'a>(&'a mut self, __func: &mut dyn FnMut(&'a mut dyn Space<VM>)) {
#(#space_visitors_mut)*
#parent_visitor_mut
}
Expand Down
11 changes: 11 additions & 0 deletions src/mmtk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::util::address::ObjectReference;
use crate::util::analysis::AnalysisManager;
use crate::util::finalizable_processor::FinalizableProcessor;
use crate::util::heap::gc_trigger::GCTrigger;
use crate::util::heap::inspection::SpaceInspector;
use crate::util::heap::layout::heap_parameters::MAX_SPACES;
use crate::util::heap::layout::vm_layout::VMLayout;
use crate::util::heap::layout::{self, Mmapper, VMMap};
Expand Down Expand Up @@ -596,4 +597,14 @@ impl<VM: VMBinding> MMTK<VM> {
.vm_space
.initialize_object_metadata(object, false)
}

/// Inspect MMTk spaces. The space inspector allows users to inspect the heap hierarchically,
/// with all levels of regions. Users can further inspect objects in the regions if vo_bit is enabled.
pub fn inspect_spaces(&self) -> Vec<&dyn SpaceInspector> {
let mut ret = vec![];
self.get_plan().for_each_space(&mut |space| {
ret.push(space.as_inspector());
});
ret
}
}
4 changes: 2 additions & 2 deletions src/plan/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -714,13 +714,13 @@ pub trait HasSpaces {
///
/// If `Self` contains nested fields that contain more spaces, this method shall visit spaces
/// in the outer struct first.
fn for_each_space(&self, func: &mut dyn FnMut(&dyn Space<Self::VM>));
fn for_each_space<'a>(&'a self, func: &mut dyn FnMut(&'a dyn Space<Self::VM>));

/// Visit each space field mutably.
///
/// If `Self` contains nested fields that contain more spaces, this method shall visit spaces
/// in the outer struct first.
fn for_each_space_mut(&mut self, func: &mut dyn FnMut(&mut dyn Space<Self::VM>));
fn for_each_space_mut<'a>(&'a mut self, func: &mut dyn FnMut(&'a mut dyn Space<Self::VM>));
}

/// A plan that uses `PlanProcessEdges` needs to provide an implementation for this trait.
Expand Down
20 changes: 20 additions & 0 deletions src/policy/copyspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ impl<VM: VMBinding> Space<VM> for CopySpace<VM> {
self
}

fn as_inspector(&self) -> &dyn crate::util::heap::inspection::SpaceInspector {
self
}

fn get_page_resource(&self) -> &dyn PageResource<VM> {
&self.pr
}
Expand Down Expand Up @@ -160,6 +164,22 @@ impl<VM: VMBinding> crate::policy::gc_work::PolicyTraceObject<VM> for CopySpace<
}
}

use crate::util::heap::inspection::{RegionInspector, SpaceInspector};
impl<VM: VMBinding> SpaceInspector for CopySpace<VM> {
fn list_top_regions(&self) -> Vec<Box<dyn RegionInspector>> {
crate::util::heap::inspection::into_regions::<crate::util::heap::chunk_map::Chunk>(
&mut self.pr.iterate_allocated_regions(),
)
}

fn list_sub_regions(
&self,
_parent_region: &dyn RegionInspector,
) -> Vec<Box<dyn RegionInspector>> {
vec![]
}
}

impl<VM: VMBinding> CopySpace<VM> {
pub fn new(args: crate::policy::space::PlanCreateSpaceArgs<VM>, from_space: bool) -> Self {
let vm_map = args.vm_map;
Expand Down
31 changes: 31 additions & 0 deletions src/policy/immix/immixspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ impl<VM: VMBinding> Space<VM> for ImmixSpace<VM> {
fn as_sft(&self) -> &(dyn SFT + Sync + 'static) {
self
}
fn as_inspector(&self) -> &dyn crate::util::heap::inspection::SpaceInspector {
self
}
fn get_page_resource(&self) -> &dyn PageResource<VM> {
&self.pr
}
Expand Down Expand Up @@ -1178,3 +1181,31 @@ impl ClearVOBitsAfterPrepare {
}
}
}

mod inspector {
use super::*;
use crate::util::heap::inspection::{list_sub_regions, RegionInspector, SpaceInspector};
impl<VM: VMBinding> SpaceInspector for ImmixSpace<VM> {
fn list_top_regions(&self) -> Vec<Box<dyn RegionInspector>> {
self.chunk_map
.all_chunks()
.map(|r: Chunk| Box::new(r) as Box<dyn RegionInspector>)
.collect()
}

fn list_sub_regions(
&self,
parent_region: &dyn RegionInspector,
) -> Vec<Box<dyn RegionInspector>> {
if let Some(regions) = list_sub_regions::<Chunk, Block>(parent_region) {
return regions;
}
if !crate::policy::immix::BLOCK_ONLY {
if let Some(regions) = list_sub_regions::<Block, Line>(parent_region) {
return regions;
}
}
vec![]
}
}
}
23 changes: 23 additions & 0 deletions src/policy/immortalspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ impl<VM: VMBinding> Space<VM> for ImmortalSpace<VM> {
fn as_sft(&self) -> &(dyn SFT + Sync + 'static) {
self
}
fn as_inspector(&self) -> &dyn crate::util::heap::inspection::SpaceInspector {
self
}
fn get_page_resource(&self) -> &dyn PageResource<VM> {
&self.pr
}
Expand Down Expand Up @@ -227,3 +230,23 @@ impl<VM: VMBinding> ImmortalSpace<VM> {
object
}
}

mod inspector {
use super::*;
use crate::util::heap::inspection::{RegionInspector, SpaceInspector};

impl<VM: VMBinding> SpaceInspector for ImmortalSpace<VM> {
fn list_top_regions(&self) -> Vec<Box<dyn RegionInspector>> {
crate::util::heap::inspection::into_regions::<crate::util::heap::chunk_map::Chunk>(
&mut self.pr.iterate_allocated_regions(),
)
}

fn list_sub_regions(
&self,
_parent_region: &dyn RegionInspector,
) -> Vec<Box<dyn RegionInspector>> {
vec![]
}
}
}
24 changes: 24 additions & 0 deletions src/policy/largeobjectspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@ impl<VM: VMBinding> Space<VM> for LargeObjectSpace<VM> {
fn as_sft(&self) -> &(dyn SFT + Sync + 'static) {
self
}
fn as_inspector(&self) -> &dyn crate::util::heap::inspection::SpaceInspector {
self
}
fn get_page_resource(&self) -> &dyn PageResource<VM> {
&self.pr
}
Expand Down Expand Up @@ -380,3 +383,24 @@ impl<VM: VMBinding> LargeObjectSpace<VM> {
fn get_super_page(cell: Address) -> Address {
cell.align_down(BYTES_IN_PAGE)
}

mod inspector {
use super::*;
use crate::util::heap::inspection::{RegionInspector, SpaceInspector};

impl<VM: VMBinding> SpaceInspector for LargeObjectSpace<VM> {
fn list_top_regions(&self) -> Vec<Box<dyn RegionInspector>> {
let space = unsafe { &*(self as *const Self) };
vec![Box::new(crate::util::heap::inspection::SpaceAsRegion::new(
space,
))]
}

fn list_sub_regions(
&self,
_parent_region: &dyn RegionInspector,
) -> Vec<Box<dyn RegionInspector>> {
vec![]
}
}
}
24 changes: 24 additions & 0 deletions src/policy/lockfreeimmortalspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ impl<VM: VMBinding> Space<VM> for LockFreeImmortalSpace<VM> {
fn as_sft(&self) -> &(dyn SFT + Sync + 'static) {
self
}
fn as_inspector(&self) -> &dyn crate::util::heap::inspection::SpaceInspector {
self
}
fn get_page_resource(&self) -> &dyn PageResource<VM> {
unimplemented!()
}
Expand Down Expand Up @@ -271,3 +274,24 @@ impl<VM: VMBinding> LockFreeImmortalSpace<VM> {
space
}
}

mod inspector {
use super::*;
use crate::util::heap::inspection::{RegionInspector, SpaceInspector};

impl<VM: VMBinding> SpaceInspector for LockFreeImmortalSpace<VM> {
fn list_top_regions(&self) -> Vec<Box<dyn RegionInspector>> {
let space = unsafe { &*(self as *const Self) };
vec![Box::new(crate::util::heap::inspection::SpaceAsRegion::new(
space,
))]
}

fn list_sub_regions(
&self,
_parent_region: &dyn RegionInspector,
) -> Vec<Box<dyn RegionInspector>> {
vec![]
}
}
}
24 changes: 24 additions & 0 deletions src/policy/markcompactspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ impl<VM: VMBinding> Space<VM> for MarkCompactSpace<VM> {
self
}

fn as_inspector(&self) -> &dyn crate::util::heap::inspection::SpaceInspector {
self
}

fn get_page_resource(&self) -> &dyn PageResource<VM> {
&self.pr
}
Expand Down Expand Up @@ -438,3 +442,23 @@ impl<VM: VMBinding> crate::util::linear_scan::LinearScanObjectSize for MarkCompa
VM::VMObjectModel::get_current_size(object)
}
}

mod inspector {
use super::*;
use crate::util::heap::inspection::{RegionInspector, SpaceInspector};

impl<VM: VMBinding> SpaceInspector for MarkCompactSpace<VM> {
fn list_top_regions(&self) -> Vec<Box<dyn RegionInspector>> {
crate::util::heap::inspection::into_regions::<crate::util::heap::chunk_map::Chunk>(
&mut self.pr.iterate_allocated_regions(),
)
}

fn list_sub_regions(
&self,
_parent_region: &dyn RegionInspector,
) -> Vec<Box<dyn RegionInspector>> {
vec![]
}
}
}
24 changes: 24 additions & 0 deletions src/policy/marksweepspace/malloc_ms/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ impl<VM: VMBinding> Space<VM> for MallocSpace<VM> {
self
}

fn as_inspector(&self) -> &dyn crate::util::heap::inspection::SpaceInspector {
self
}

fn get_page_resource(&self) -> &dyn PageResource<VM> {
unreachable!()
}
Expand Down Expand Up @@ -895,3 +899,23 @@ impl<VM: VMBinding> GCWork<VM> for MSSweepChunk<VM> {
self.ms.sweep_chunk(self.chunk);
}
}

mod inspector {
use super::*;
use crate::util::heap::inspection::{RegionInspector, SpaceInspector};
impl<VM: VMBinding> SpaceInspector for MallocSpace<VM> {
fn list_top_regions(&self) -> Vec<Box<dyn RegionInspector>> {
self.chunk_map
.all_chunks()
.map(|r: Chunk| Box::new(r) as Box<dyn RegionInspector>)
.collect()
}

fn list_sub_regions(
&self,
_parent_region: &dyn RegionInspector,
) -> Vec<Box<dyn RegionInspector>> {
vec![]
}
}
}
27 changes: 27 additions & 0 deletions src/policy/marksweepspace/native_ms/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,10 @@ impl<VM: VMBinding> Space<VM> for MarkSweepSpace<VM> {
self
}

fn as_inspector(&self) -> &dyn crate::util::heap::inspection::SpaceInspector {
self
}

fn get_page_resource(&self) -> &dyn crate::util::heap::PageResource<VM> {
&self.pr
}
Expand Down Expand Up @@ -667,3 +671,26 @@ impl<VM: VMBinding> Drop for RecycleBlocks<VM> {
epilogue::debug_assert_counter_zero(&self.counter, "RecycleBlocks::counter");
}
}

mod inspector {
use super::*;
use crate::util::heap::inspection::{list_sub_regions, RegionInspector, SpaceInspector};
impl<VM: VMBinding> SpaceInspector for MarkSweepSpace<VM> {
fn list_top_regions(&self) -> Vec<Box<dyn RegionInspector>> {
self.chunk_map
.all_chunks()
.map(|r: Chunk| Box::new(r) as Box<dyn RegionInspector>)
.collect()
}

fn list_sub_regions(
&self,
parent_region: &dyn RegionInspector,
) -> Vec<Box<dyn RegionInspector>> {
if let Some(regions) = list_sub_regions::<Chunk, Block>(parent_region) {
return regions;
}
vec![]
}
}
}
2 changes: 2 additions & 0 deletions src/policy/space.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::global_state::GlobalState;
use crate::plan::PlanConstraints;
use crate::scheduler::GCWorkScheduler;
use crate::util::conversions::*;
use crate::util::heap::inspection::SpaceInspector;
use crate::util::metadata::side_metadata::{
SideMetadataContext, SideMetadataSanity, SideMetadataSpec,
};
Expand Down Expand Up @@ -42,6 +43,7 @@ use downcast_rs::Downcast;
pub trait Space<VM: VMBinding>: 'static + SFT + Sync + Downcast {
fn as_space(&self) -> &dyn Space<VM>;
fn as_sft(&self) -> &(dyn SFT + Sync + 'static);
fn as_inspector(&self) -> &dyn SpaceInspector;
fn get_page_resource(&self) -> &dyn PageResource<VM>;

/// Get a mutable reference to the underlying page resource, or `None` if the space does not
Expand Down
24 changes: 24 additions & 0 deletions src/policy/vmspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ impl<VM: VMBinding> Space<VM> for VMSpace<VM> {
fn as_sft(&self) -> &(dyn SFT + Sync + 'static) {
self
}
fn as_inspector(&self) -> &dyn crate::util::heap::inspection::SpaceInspector {
self
}
fn get_page_resource(&self) -> &dyn PageResource<VM> {
&self.pr
}
Expand Down Expand Up @@ -300,3 +303,24 @@ impl<VM: VMBinding> VMSpace<VM> {
object
}
}

mod inspector {
use super::*;
use crate::util::heap::inspection::{RegionInspector, SpaceInspector};

impl<VM: VMBinding> SpaceInspector for VMSpace<VM> {
fn list_top_regions(&self) -> Vec<Box<dyn RegionInspector>> {
let space = unsafe { &*(self as *const Self) };
vec![Box::new(crate::util::heap::inspection::SpaceAsRegion::new(
space,
))]
}

fn list_sub_regions(
&self,
_parent_region: &dyn RegionInspector,
) -> Vec<Box<dyn RegionInspector>> {
vec![]
}
}
}
Loading
Loading