From ebfbaf50cee3d5ecb2c3fda4703ac6bf1ecaf276 Mon Sep 17 00:00:00 2001 From: Kunshan Wang Date: Wed, 10 Aug 2022 16:52:05 +0800 Subject: [PATCH 1/6] Use MMTk finalizer processor --- mmtk/src/api.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/mmtk/src/api.rs b/mmtk/src/api.rs index 530f248..0d2f6c2 100644 --- a/mmtk/src/api.rs +++ b/mmtk/src/api.rs @@ -209,15 +209,10 @@ pub extern "C" fn mmtk_last_heap_address() -> Address { #[no_mangle] pub extern "C" fn mmtk_register_finalizable(reff: ObjectReference) { - crate::binding() - .finalizer_processor - .register_finalizable(reff); + memory_manager::add_finalizer(crate::mmtk(), reff) } #[no_mangle] -pub extern "C" fn mmtk_poll_finalizable(include_live: bool) -> ObjectReference { - crate::binding() - .finalizer_processor - .poll_finalizable(include_live) - .unwrap_or_else(|| unsafe { Address::zero().to_object_reference() }) +pub extern "C" fn mmtk_poll_finalizable(_include_live: bool) -> ObjectReference { + memory_manager::get_finalized_object(crate::mmtk()).unwrap_or(ObjectReference::NULL) } From 2a9711f59a62cc1e84e2ad50e3bb08b14c112497 Mon Sep 17 00:00:00 2001 From: Kunshan Wang Date: Tue, 9 Aug 2022 22:44:00 +0800 Subject: [PATCH 2/6] Expect C to expose obj_free --- mmtk/src/abi.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/mmtk/src/abi.rs b/mmtk/src/abi.rs index 4876e31..c7d1c68 100644 --- a/mmtk/src/abi.rs +++ b/mmtk/src/abi.rs @@ -157,6 +157,7 @@ pub struct RubyUpcalls { pub scan_thread_roots: extern "C" fn(), pub scan_thread_root: extern "C" fn(mutator_tls: VMMutatorThread, worker_tls: VMWorkerThread), pub scan_object_ruby_style: extern "C" fn(object: ObjectReference), + pub obj_free: extern "C" fn(object: ObjectReference), } unsafe impl Sync for RubyUpcalls {} From 8cee581202e36745de75c2891b93845f7ff8ba54 Mon Sep 17 00:00:00 2001 From: Kunshan Wang Date: Fri, 12 Aug 2022 15:27:32 +0800 Subject: [PATCH 3/6] Remove our fake FinalizerProcessor --- mmtk/src/binding.rs | 3 --- mmtk/src/finalize.rs | 37 ------------------------------------- mmtk/src/lib.rs | 1 - mmtk/src/scanning.rs | 9 --------- 4 files changed, 50 deletions(-) delete mode 100644 mmtk/src/finalize.rs diff --git a/mmtk/src/binding.rs b/mmtk/src/binding.rs index d2699cc..c0ddd70 100644 --- a/mmtk/src/binding.rs +++ b/mmtk/src/binding.rs @@ -4,13 +4,11 @@ use std::sync::Mutex; use mmtk::MMTK; use crate::abi; -use crate::finalize; use crate::Ruby; pub struct RubyBinding { pub mmtk: &'static MMTK, pub upcalls: *const abi::RubyUpcalls, - pub finalizer_processor: finalize::FinalizerProcessor, pub plan_name: Mutex>, } @@ -22,7 +20,6 @@ impl RubyBinding { Self { mmtk, upcalls, - finalizer_processor: finalize::FinalizerProcessor::new(), plan_name: Mutex::new(None), } } diff --git a/mmtk/src/finalize.rs b/mmtk/src/finalize.rs deleted file mode 100644 index 69948c8..0000000 --- a/mmtk/src/finalize.rs +++ /dev/null @@ -1,37 +0,0 @@ -use mmtk::util::ObjectReference; - -use std::{sync::Mutex, vec}; - -/// TODO: This is a workaround to support Ruby's semantics that finalizes everything on exit. -/// In the future, it should be supported to upstream. -pub struct FinalizerProcessor { - candidates: Mutex>, -} - -impl FinalizerProcessor { - pub fn new() -> Self { - Self { - candidates: Mutex::new(vec![]), - } - } - - pub(crate) fn with_candidates(&self, callback: F) -> T - where - F: FnOnce(&Vec) -> T, - { - let guard = self.candidates.lock().unwrap(); - callback(&guard) - } - - pub fn register_finalizable(&self, reff: ObjectReference) { - self.candidates.lock().unwrap().push(reff); - } - - pub fn poll_finalizable(&self, include_live: bool) -> Option { - if include_live { - self.candidates.lock().unwrap().pop() - } else { - None - } - } -} diff --git a/mmtk/src/lib.rs b/mmtk/src/lib.rs index d69a01d..e1a2a74 100644 --- a/mmtk/src/lib.rs +++ b/mmtk/src/lib.rs @@ -14,7 +14,6 @@ pub mod active_plan; pub mod api; pub mod binding; pub mod collection; -pub mod finalize; pub mod object_model; pub mod reference_glue; pub mod scanning; diff --git a/mmtk/src/scanning.rs b/mmtk/src/scanning.rs index f6e4c72..6eb0b97 100644 --- a/mmtk/src/scanning.rs +++ b/mmtk/src/scanning.rs @@ -66,15 +66,6 @@ impl Scanning for VMScanning { Self::collect_object_roots_in("scan_vm_specific_roots", gc_tls, &mut factory, || { (upcalls().scan_vm_specific_roots)(); }); - { - // FIXME: This is a workaround. Obviously it will keep all finalizable objects alive until program exits. - debug!("[scan_vm_specific_roots] Enqueueing candidates."); - let candidates = crate::binding() - .finalizer_processor - .with_candidates(|v| v.to_vec()); - factory.create_process_node_roots_work(candidates); - debug!("[scan_vm_specific_roots] Finished Enqueueing candidates."); - } } fn supports_return_barrier() -> bool { From 812c2326ea2868b5864558a35588aef6471ff9ab Mon Sep 17 00:00:00 2001 From: Kunshan Wang Date: Fri, 12 Aug 2022 16:47:19 +0800 Subject: [PATCH 4/6] Expose MMTk's official finalization API --- mmtk/src/abi.rs | 8 ++++++++ mmtk/src/api.rs | 21 +++++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/mmtk/src/abi.rs b/mmtk/src/abi.rs index c7d1c68..731982e 100644 --- a/mmtk/src/abi.rs +++ b/mmtk/src/abi.rs @@ -142,6 +142,14 @@ impl GCThreadTLS { } } +#[repr(C)] +#[derive(Clone)] +pub struct RawVecOfObjRef { + pub ptr: *mut ObjectReference, + pub len: usize, + pub capa: usize, +} + #[repr(C)] #[derive(Clone)] pub struct RubyUpcalls { diff --git a/mmtk/src/api.rs b/mmtk/src/api.rs index 0d2f6c2..299b744 100644 --- a/mmtk/src/api.rs +++ b/mmtk/src/api.rs @@ -4,6 +4,7 @@ use std::ffi::CStr; use crate::abi; +use crate::abi::RawVecOfObjRef; use crate::binding::RubyBinding; use crate::mmtk; use crate::Ruby; @@ -208,11 +209,27 @@ pub extern "C" fn mmtk_last_heap_address() -> Address { } #[no_mangle] -pub extern "C" fn mmtk_register_finalizable(reff: ObjectReference) { +pub extern "C" fn mmtk_add_finalizer(reff: ObjectReference) { memory_manager::add_finalizer(crate::mmtk(), reff) } #[no_mangle] -pub extern "C" fn mmtk_poll_finalizable(_include_live: bool) -> ObjectReference { +pub extern "C" fn mmtk_get_finalized_object() -> ObjectReference { memory_manager::get_finalized_object(crate::mmtk()).unwrap_or(ObjectReference::NULL) } + +#[no_mangle] +pub extern "C" fn mmtk_get_all_finalizers() -> RawVecOfObjRef { + let vec = memory_manager::get_all_finalizers(crate::mmtk()); + + // Note: Vec::into_raw_parts is unstable. We implement it manually. + let mut vec = std::mem::ManuallyDrop::new(vec); + let (ptr, len, capa) = (vec.as_mut_ptr(), vec.len(), vec.capacity()); + + RawVecOfObjRef { ptr, len, capa } +} + +#[no_mangle] +pub extern "C" fn mmtk_free_raw_vec_of_obj_ref(raw_vec: RawVecOfObjRef) { + unsafe { Vec::from_raw_parts(raw_vec.ptr, raw_vec.len, raw_vec.capa) }; +} From 47142e46abcfadd5b9c10a5798d42c2d4e6a4b97 Mon Sep 17 00:00:00 2001 From: Kunshan Wang Date: Thu, 18 Aug 2022 15:23:11 +0800 Subject: [PATCH 5/6] Revert "Expect C to expose obj_free" This reverts commit 2a9711f59a62cc1e84e2ad50e3bb08b14c112497. --- mmtk/src/abi.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/mmtk/src/abi.rs b/mmtk/src/abi.rs index 731982e..ac32c76 100644 --- a/mmtk/src/abi.rs +++ b/mmtk/src/abi.rs @@ -165,7 +165,6 @@ pub struct RubyUpcalls { pub scan_thread_roots: extern "C" fn(), pub scan_thread_root: extern "C" fn(mutator_tls: VMMutatorThread, worker_tls: VMWorkerThread), pub scan_object_ruby_style: extern "C" fn(object: ObjectReference), - pub obj_free: extern "C" fn(object: ObjectReference), } unsafe impl Sync for RubyUpcalls {} From 4811d75c2a34cc8f9cf6a8945b5ae3136f749414 Mon Sep 17 00:00:00 2001 From: Kunshan Wang Date: Thu, 18 Aug 2022 16:33:16 +0800 Subject: [PATCH 6/6] Let RawVecOfObjRef handle conversion to/from Vec --- mmtk/src/abi.rs | 20 ++++++++++++++++++++ mmtk/src/api.rs | 10 ++-------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/mmtk/src/abi.rs b/mmtk/src/abi.rs index ac32c76..35bd24c 100644 --- a/mmtk/src/abi.rs +++ b/mmtk/src/abi.rs @@ -150,6 +150,26 @@ pub struct RawVecOfObjRef { pub capa: usize, } +impl RawVecOfObjRef { + pub fn from_vec(vec: Vec) -> RawVecOfObjRef { + // Note: Vec::into_raw_parts is unstable. We implement it manually. + let mut vec = std::mem::ManuallyDrop::new(vec); + let (ptr, len, capa) = (vec.as_mut_ptr(), vec.len(), vec.capacity()); + + RawVecOfObjRef { ptr, len, capa } + } + + pub unsafe fn into_vec(self) -> Vec { + Vec::from_raw_parts(self.ptr, self.len, self.capa) + } +} + +impl Into for Vec { + fn into(self) -> RawVecOfObjRef { + RawVecOfObjRef::from_vec(self) + } +} + #[repr(C)] #[derive(Clone)] pub struct RubyUpcalls { diff --git a/mmtk/src/api.rs b/mmtk/src/api.rs index 299b744..8ce37ed 100644 --- a/mmtk/src/api.rs +++ b/mmtk/src/api.rs @@ -220,16 +220,10 @@ pub extern "C" fn mmtk_get_finalized_object() -> ObjectReference { #[no_mangle] pub extern "C" fn mmtk_get_all_finalizers() -> RawVecOfObjRef { - let vec = memory_manager::get_all_finalizers(crate::mmtk()); - - // Note: Vec::into_raw_parts is unstable. We implement it manually. - let mut vec = std::mem::ManuallyDrop::new(vec); - let (ptr, len, capa) = (vec.as_mut_ptr(), vec.len(), vec.capacity()); - - RawVecOfObjRef { ptr, len, capa } + memory_manager::get_all_finalizers(crate::mmtk()).into() } #[no_mangle] pub extern "C" fn mmtk_free_raw_vec_of_obj_ref(raw_vec: RawVecOfObjRef) { - unsafe { Vec::from_raw_parts(raw_vec.ptr, raw_vec.len, raw_vec.capa) }; + unsafe { raw_vec.into_vec() }; }