From c5ce42139000b21510096147dfa8a92979bf11fd Mon Sep 17 00:00:00 2001 From: Yi Lin Date: Mon, 30 Oct 2023 05:32:17 +0000 Subject: [PATCH 1/3] Implement get_gc_trigger for LockFreeImmortalSpace --- src/policy/lockfreeimmortalspace.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/policy/lockfreeimmortalspace.rs b/src/policy/lockfreeimmortalspace.rs index bd2cabad40..66ba8f5990 100644 --- a/src/policy/lockfreeimmortalspace.rs +++ b/src/policy/lockfreeimmortalspace.rs @@ -1,7 +1,7 @@ use atomic::Atomic; -use std::marker::PhantomData; use std::sync::atomic::Ordering; +use std::sync::Arc; use crate::policy::sft::GCWorkerMutRef; use crate::policy::sft::SFT; @@ -9,6 +9,7 @@ use crate::policy::space::{CommonSpace, Space}; use crate::util::address::Address; use crate::util::conversions; +use crate::util::heap::gc_trigger::GCTrigger; use crate::util::heap::layout::vm_layout::vm_layout; use crate::util::heap::PageResource; use crate::util::memory::MmapStrategy; @@ -38,7 +39,7 @@ pub struct LockFreeImmortalSpace { /// Zero memory after slow-path allocation slow_path_zeroing: bool, metadata: SideMetadataContext, - phantom: PhantomData, + gc_trigger: Arc>, } impl SFT for LockFreeImmortalSpace { @@ -99,6 +100,10 @@ impl Space for LockFreeImmortalSpace { unimplemented!() } + fn get_gc_trigger(&self) -> &GCTrigger { + &self.gc_trigger + } + fn release_multiple_pages(&mut self, _start: Address) { panic!("immortalspace only releases pages enmasse") } @@ -196,7 +201,7 @@ impl LockFreeImmortalSpace { global: args.global_side_metadata_specs, local: vec![], }, - phantom: PhantomData, + gc_trigger: args.gc_trigger, }; // Eagerly memory map the entire heap (also zero all the memory) From 7273a15ba45e49322df271155c46216d229efdbc Mon Sep 17 00:00:00 2001 From: Yi Lin Date: Mon, 30 Oct 2023 06:25:28 +0000 Subject: [PATCH 2/3] Add a test for LockFreeImmortalSpace. Fix space reservation. --- src/policy/lockfreeimmortalspace.rs | 38 ++++++++++++------- vmbindings/dummyvm/Cargo.toml | 1 + vmbindings/dummyvm/src/tests/mod.rs | 2 + .../dummyvm/src/tests/nogc_lock_free.rs | 35 +++++++++++++++++ 4 files changed, 63 insertions(+), 13 deletions(-) create mode 100644 vmbindings/dummyvm/src/tests/nogc_lock_free.rs diff --git a/src/policy/lockfreeimmortalspace.rs b/src/policy/lockfreeimmortalspace.rs index 66ba8f5990..359cd2c64d 100644 --- a/src/policy/lockfreeimmortalspace.rs +++ b/src/policy/lockfreeimmortalspace.rs @@ -12,6 +12,7 @@ use crate::util::conversions; use crate::util::heap::gc_trigger::GCTrigger; use crate::util::heap::layout::vm_layout::vm_layout; use crate::util::heap::PageResource; +use crate::util::heap::VMRequest; use crate::util::memory::MmapStrategy; use crate::util::metadata::side_metadata::SideMetadataContext; use crate::util::metadata::side_metadata::SideMetadataSanity; @@ -35,7 +36,7 @@ pub struct LockFreeImmortalSpace { /// start of this space start: Address, /// Total bytes for the space - extent: usize, + total_bytes: usize, /// Zero memory after slow-path allocation slow_path_zeroing: bool, metadata: SideMetadataContext, @@ -109,7 +110,7 @@ impl Space for LockFreeImmortalSpace { } fn initialize_sft(&self, sft_map: &mut dyn crate::policy::sft_map::SFTMap) { - unsafe { sft_map.eager_initialize(self.as_sft(), self.start, self.extent) }; + unsafe { sft_map.eager_initialize(self.as_sft(), self.start, self.total_bytes) }; } fn reserved_pages(&self) -> usize { @@ -120,6 +121,7 @@ impl Space for LockFreeImmortalSpace { } fn acquire(&self, _tls: VMThread, pages: usize) -> Address { + trace!("LockFreeImmortalSpace::acquire"); let bytes = conversions::pages_to_bytes(pages); let start = self .cursor @@ -130,9 +132,11 @@ impl Space for LockFreeImmortalSpace { if start + bytes > self.limit { panic!("OutOfMemory") } + trace!("Going to zero"); if self.slow_path_zeroing { crate::util::memory::zero(start, bytes); } + trace!("Going to zero - done"); start } @@ -175,8 +179,8 @@ impl LockFreeImmortalSpace { #[allow(dead_code)] // Only used with certain features. pub fn new(args: crate::policy::space::PlanCreateSpaceArgs) -> Self { let slow_path_zeroing = args.zeroed; - // FIXME: This space assumes that it can use the entire heap range, which is definitely wrong. - // https://github.com/mmtk/mmtk-core/issues/314 + + // Get the total bytes for the heap. let total_bytes = match *args.options.gc_trigger { crate::util::options::GCTriggerSelector::FixedHeapSize(bytes) => bytes, _ => unimplemented!(), @@ -187,15 +191,24 @@ impl LockFreeImmortalSpace { total_bytes, vm_layout().available_bytes() ); + // Align up to chunks + let aligned_total_bytes = crate::util::conversions::raw_align_up( + total_bytes, + crate::util::heap::vm_layout::BYTES_IN_CHUNK, + ); + + // Create a VM request of fixed size + let vmrequest = VMRequest::fixed_size(aligned_total_bytes); + // Reserve the space + let VMRequest::Extent{ extent, top } = vmrequest else { unreachable!() }; + let start = args.heap.reserve(extent, top); - // FIXME: This space assumes that it can use the entire heap range, which is definitely wrong. - // https://github.com/mmtk/mmtk-core/issues/314 let space = Self { name: args.name, - cursor: Atomic::new(vm_layout().available_start()), - limit: vm_layout().available_start() + total_bytes, - start: vm_layout().available_start(), - extent: total_bytes, + cursor: Atomic::new(start), + limit: start + aligned_total_bytes, + start, + total_bytes: aligned_total_bytes, slow_path_zeroing, metadata: SideMetadataContext { global: args.global_side_metadata_specs, @@ -210,11 +223,10 @@ impl LockFreeImmortalSpace { } else { MmapStrategy::Normal }; - crate::util::memory::dzmmap_noreplace(vm_layout().available_start(), total_bytes, strategy) - .unwrap(); + crate::util::memory::dzmmap_noreplace(start, aligned_total_bytes, strategy).unwrap(); if space .metadata - .try_map_metadata_space(vm_layout().available_start(), total_bytes) + .try_map_metadata_space(start, aligned_total_bytes) .is_err() { // TODO(Javad): handle meta space allocation failure diff --git a/vmbindings/dummyvm/Cargo.toml b/vmbindings/dummyvm/Cargo.toml index a1a3af254b..13def039a5 100644 --- a/vmbindings/dummyvm/Cargo.toml +++ b/vmbindings/dummyvm/Cargo.toml @@ -36,6 +36,7 @@ malloc_counted_size = ["mmtk/malloc_counted_size"] malloc_mark_sweep = ["mmtk/malloc_mark_sweep"] vo_bit = ["mmtk/vo_bit"] extreme_assertions = ["mmtk/extreme_assertions"] +nogc_lock_free=["mmtk/nogc_lock_free"] # Feature to control which benchmarks to run. See benches/main.rs bench_sft = [] diff --git a/vmbindings/dummyvm/src/tests/mod.rs b/vmbindings/dummyvm/src/tests/mod.rs index a0ed565f53..c65b0aff43 100644 --- a/vmbindings/dummyvm/src/tests/mod.rs +++ b/vmbindings/dummyvm/src/tests/mod.rs @@ -25,6 +25,8 @@ mod malloc_api; #[cfg(feature = "malloc_counted_size")] mod malloc_counted; mod malloc_ms; +#[cfg(feature = "nogc_lock_free")] +mod nogc_lock_free; #[cfg(target_pointer_width = "64")] mod vm_layout_compressed_pointer_64; mod vm_layout_default; diff --git a/vmbindings/dummyvm/src/tests/nogc_lock_free.rs b/vmbindings/dummyvm/src/tests/nogc_lock_free.rs new file mode 100644 index 0000000000..f69bee7178 --- /dev/null +++ b/vmbindings/dummyvm/src/tests/nogc_lock_free.rs @@ -0,0 +1,35 @@ +// GITHUB-CI: MMTK_PLAN=NoGC +// GITHUB-CI: FEATURES=nogc_lock_free + +use crate::api; +use crate::test_fixtures::{MutatorFixture, SerialFixture}; +use crate::DummyVM; +use log::info; +use mmtk::plan::AllocationSemantics; +use mmtk::vm::VMBinding; + +lazy_static! { + static ref MUTATOR: SerialFixture = SerialFixture::new(); +} + +#[test] +pub fn nogc_lock_free_allocate() { + MUTATOR.with_fixture(|fixture| { + let min = DummyVM::MIN_ALIGNMENT; + let max = DummyVM::MAX_ALIGNMENT; + info!("Allowed alignment between {} and {}", min, max); + let mut align = min; + while align <= max { + info!("Test allocation with alignment {}", align); + let addr = api::mmtk_alloc(fixture.mutator, 8, align, 0, AllocationSemantics::Default); + info!("addr = {}", addr); + assert!( + addr.is_aligned_to(align), + "Expected allocation alignment {}, returned address is {:?}", + align, + addr + ); + align *= 2; + } + }) +} From 588c5abd58004ae1cf0abe323105c547572c3886 Mon Sep 17 00:00:00 2001 From: Yi Lin Date: Tue, 31 Oct 2023 20:04:57 +1300 Subject: [PATCH 3/3] Remove unnecessary logging --- src/policy/lockfreeimmortalspace.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/policy/lockfreeimmortalspace.rs b/src/policy/lockfreeimmortalspace.rs index 359cd2c64d..e78f95e30a 100644 --- a/src/policy/lockfreeimmortalspace.rs +++ b/src/policy/lockfreeimmortalspace.rs @@ -132,11 +132,9 @@ impl Space for LockFreeImmortalSpace { if start + bytes > self.limit { panic!("OutOfMemory") } - trace!("Going to zero"); if self.slow_path_zeroing { crate::util::memory::zero(start, bytes); } - trace!("Going to zero - done"); start }