From a0d6ebe93ded9b576f6f394e55b7c2fe350bbb4c Mon Sep 17 00:00:00 2001 From: Yi Lin Date: Thu, 6 Jul 2023 07:10:16 +0000 Subject: [PATCH 1/2] Use simple edge. Use trace_object_immediately --- julia/mmtk_julia.c | 12 +++++-- mmtk/Cargo.lock | 2 -- mmtk/Cargo.toml | 2 +- mmtk/api/mmtk.h | 3 +- mmtk/src/api.rs | 8 ++--- mmtk/src/edges.rs | 74 +++----------------------------------- mmtk/src/julia_scanning.rs | 60 +++++++++++++++++-------------- mmtk/src/lib.rs | 5 ++- mmtk/src/scanning.rs | 8 +++-- 9 files changed, 61 insertions(+), 113 deletions(-) diff --git a/julia/mmtk_julia.c b/julia/mmtk_julia.c index 88399ef7..5bba7cd2 100644 --- a/julia/mmtk_julia.c +++ b/julia/mmtk_julia.c @@ -728,7 +728,7 @@ const bool PRINT_OBJ_TYPE = false; * directly (not an edge), specifying whether to scan the object or not; and only scan the object * (necessary for boot image / non-MMTk objects) **/ -JL_DLLEXPORT void scan_julia_obj(void* obj_raw, closure_pointer closure, ProcessEdgeFn process_edge, ProcessOffsetEdgeFn process_offset_edge) +JL_DLLEXPORT void scan_julia_obj(void* obj_raw, closure_pointer closure, ProcessEdgeFn process_edge, TraceObjectImmediatelyFn trace_object_immediately) { jl_value_t* obj = (jl_value_t*) obj_raw; uintptr_t tag = (uintptr_t)jl_typeof(obj); @@ -756,7 +756,15 @@ JL_DLLEXPORT void scan_julia_obj(void* obj_raw, closure_pointer closure, Process if (flags.how == 1) { // julia-allocated buffer that needs to be marked long offset = a->offset * a->elsize; - process_offset_edge(closure, &a->data, offset); + if (offset == 0) { + process_edge(closure, &a->data); + } else { + // Special case: we need to deal with offset edge. + // We trace object immediately here. + uint8_t* data = (uint8_t*)(a->data); + uint8_t* new_obj = (uint8_t*)trace_object_immediately(closure, data - offset); + a->data = new_obj + offset; + } } if (flags.how == 2) { // malloc-allocated pointer this array object manages // should be processed below if it contains pointers diff --git a/mmtk/Cargo.lock b/mmtk/Cargo.lock index 65492a30..0665a95e 100644 --- a/mmtk/Cargo.lock +++ b/mmtk/Cargo.lock @@ -545,7 +545,6 @@ dependencies = [ [[package]] name = "mmtk" version = "0.18.0" -source = "git+https://github.com/mmtk/mmtk-core.git?rev=f1a0bb7fbec97dd84e35a40e8be01cf5018f2f9e#f1a0bb7fbec97dd84e35a40e8be01cf5018f2f9e" dependencies = [ "atomic 0.5.1", "atomic-traits", @@ -590,7 +589,6 @@ dependencies = [ [[package]] name = "mmtk-macros" version = "0.18.0" -source = "git+https://github.com/mmtk/mmtk-core.git?rev=f1a0bb7fbec97dd84e35a40e8be01cf5018f2f9e#f1a0bb7fbec97dd84e35a40e8be01cf5018f2f9e" dependencies = [ "proc-macro-error", "proc-macro2", diff --git a/mmtk/Cargo.toml b/mmtk/Cargo.toml index 53745c1f..a5a77eee 100644 --- a/mmtk/Cargo.toml +++ b/mmtk/Cargo.toml @@ -29,7 +29,7 @@ lazy_static = "1.1" # - change branch # - change repo name # But other changes including adding/removing whitespaces in commented lines may break the CI -mmtk = { git = "https://github.com/mmtk/mmtk-core.git", rev = "f1a0bb7fbec97dd84e35a40e8be01cf5018f2f9e" } +mmtk = { git = "https://github.com/qinsoon/mmtk-core.git", rev = "28bde92892d699cea0e1e179931d3aeeee25e982" } # Uncomment the following to build locally # mmtk = { path = "../repos/mmtk-core" } log = {version = "0.4", features = ["max_level_trace", "release_max_level_off"] } diff --git a/mmtk/api/mmtk.h b/mmtk/api/mmtk.h index 263d5f70..ac6a7078 100644 --- a/mmtk/api/mmtk.h +++ b/mmtk/api/mmtk.h @@ -18,6 +18,7 @@ typedef void* MMTk_Mutator; typedef void* MMTk_TraceLocal; typedef void (*ProcessEdgeFn)(closure_pointer closure, void* slot); typedef void (*ProcessOffsetEdgeFn)(closure_pointer closure, void* slot, int offset); +typedef void* (*TraceObjectImmediatelyFn)(closure_pointer closure, void* object); /** * Allocation @@ -77,7 +78,7 @@ extern const void* MMTK_SIDE_LOG_BIT_BASE_ADDRESS; // * int is 4 bytes // * size_t is 8 bytes typedef struct { - void (* scan_julia_obj) (void* obj, closure_pointer closure, ProcessEdgeFn process_edge, ProcessOffsetEdgeFn process_offset_edge); + void (* scan_julia_obj) (void* obj, closure_pointer closure, ProcessEdgeFn process_edge, TraceObjectImmediatelyFn trace_object_immediately); void (* scan_julia_exc_obj) (void* obj, closure_pointer closure, ProcessEdgeFn process_edge); void* (* get_stackbase) (int16_t tid); void (* calculate_roots) (void* tls); diff --git a/mmtk/src/api.rs b/mmtk/src/api.rs index 054ba9fb..9d6c67b8 100644 --- a/mmtk/src/api.rs +++ b/mmtk/src/api.rs @@ -545,9 +545,7 @@ pub extern "C" fn mmtk_object_reference_write_post( memory_manager::object_reference_write_post( mutator, src, - crate::edges::JuliaVMEdge::Simple(mmtk::vm::edge_shape::SimpleEdge::from_address( - Address::ZERO, - )), + mmtk::vm::edge_shape::SimpleEdge::from_address(Address::ZERO), target, ) } @@ -561,9 +559,7 @@ pub extern "C" fn mmtk_object_reference_write_slow( use mmtk::MutatorContext; mutator.barrier().object_reference_write_slow( src, - crate::edges::JuliaVMEdge::Simple(mmtk::vm::edge_shape::SimpleEdge::from_address( - Address::ZERO, - )), + mmtk::vm::edge_shape::SimpleEdge::from_address(Address::ZERO), target, ); } diff --git a/mmtk/src/edges.rs b/mmtk/src/edges.rs index 461345ec..3fead6c8 100644 --- a/mmtk/src/edges.rs +++ b/mmtk/src/edges.rs @@ -4,76 +4,10 @@ use mmtk::{ vm::edge_shape::{Edge, SimpleEdge}, }; -/// If a VM supports multiple kinds of edges, we can use tagged union to represent all of them. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -pub enum JuliaVMEdge { - Simple(SimpleEdge), - Offset(OffsetEdge), -} - -unsafe impl Send for JuliaVMEdge {} - -impl Edge for JuliaVMEdge { - fn load(&self) -> ObjectReference { - match self { - JuliaVMEdge::Simple(e) => e.load(), - JuliaVMEdge::Offset(e) => e.load(), - } - } - - fn store(&self, object: ObjectReference) { - match self { - JuliaVMEdge::Simple(e) => e.store(object), - JuliaVMEdge::Offset(e) => e.store(object), - } - } -} - -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -pub struct OffsetEdge { - slot_addr: *mut Atomic
, - offset: usize, -} +use std::sync::atomic::AtomicUsize; +use std::sync::atomic::Ordering; -unsafe impl Send for OffsetEdge {} - -impl OffsetEdge { - pub fn new_no_offset(address: Address) -> Self { - Self { - slot_addr: address.to_mut_ptr(), - offset: 0, - } - } - - pub fn new_with_offset(address: Address, offset: usize) -> Self { - Self { - slot_addr: address.to_mut_ptr(), - offset, - } - } - - pub fn slot_address(&self) -> Address { - Address::from_mut_ptr(self.slot_addr) - } - - pub fn offset(&self) -> usize { - self.offset - } -} - -impl Edge for OffsetEdge { - fn load(&self) -> ObjectReference { - let middle = unsafe { (*self.slot_addr).load(atomic::Ordering::Relaxed) }; - let begin = middle - self.offset; - ObjectReference::from_raw_address(begin) - } - - fn store(&self, object: ObjectReference) { - let begin = object.to_raw_address(); - let middle = begin + self.offset; - unsafe { (*self.slot_addr).store(middle, atomic::Ordering::Relaxed) } - } -} +pub type JuliaVMEdge = SimpleEdge; #[derive(Hash, Clone, PartialEq, Eq, Debug)] pub struct JuliaMemorySlice { @@ -157,7 +91,7 @@ impl Iterator for JuliaMemorySliceEdgeIterator { } else { let edge = self.cursor; self.cursor = self.cursor.shift::(1); - Some(JuliaVMEdge::Simple(SimpleEdge::from_address(edge))) + Some(mmtk::vm::edge_shape::SimpleEdge::from_address(edge)) } } } diff --git a/mmtk/src/julia_scanning.rs b/mmtk/src/julia_scanning.rs index 365bec36..7920837a 100644 --- a/mmtk/src/julia_scanning.rs +++ b/mmtk/src/julia_scanning.rs @@ -59,7 +59,8 @@ pub unsafe fn scan_julia_object(addr: Address, closure: &mut dyn EdgeVisitor()).offset as u16 * (*addr.to_ptr::()).elsize) as usize; - process_offset_edge(closure, addr, offset); + // process_offset_edge(closure, addr, offset); + unimplemented!(); } else if flags.how() == 3 { // has a pointer to the object that owns the data #[allow(deref_nullptr)] @@ -326,43 +327,48 @@ pub fn process_edge(closure: &mut dyn EdgeVisitor, slot: Address) { let simple_edge = SimpleEdge::from_address(slot); if mmtk_object_is_managed_by_mmtk(internal_obj_addr.as_usize()) { - closure.visit_edge(JuliaVMEdge::Simple(simple_edge)); + closure.visit_edge(mmtk::vm::edge_shape::SimpleEdge::from_address(slot)); } else { unsafe { let has_been_scanned = ((*UPCALLS).julia_object_has_been_scanned)(internal_obj_addr); if has_been_scanned == 0 { ((*UPCALLS).mark_julia_object_as_scanned)(internal_obj_addr); - closure.visit_edge(JuliaVMEdge::Simple(simple_edge)); + closure.visit_edge(mmtk::vm::edge_shape::SimpleEdge::from_address(slot)); } } } } -#[inline(always)] -pub fn process_offset_edge( - closure: &mut dyn EdgeVisitor, - slot: Address, - offset: usize, -) { - let internal_obj: ObjectReference = unsafe { slot.load() }; - let internal_obj_addr = internal_obj.to_raw_address(); - if internal_obj_addr.is_zero() { - return; - } - - let offset_edge = OffsetEdge::new_with_offset(slot, offset); +// #[inline(always)] +// pub fn process_offset_edge( +// closure: &mut dyn EdgeVisitor, +// slot: Address, +// offset: usize, +// ) { +// let internal_obj: ObjectReference = unsafe { slot.load() }; +// let internal_obj_addr = internal_obj.to_raw_address(); +// if internal_obj_addr.is_zero() { +// return; +// } + +// let offset_edge = OffsetEdge::new_with_offset(slot, offset); + +// if mmtk_object_is_managed_by_mmtk(internal_obj_addr.as_usize()) { +// closure.visit_edge(offset_edge); +// } else { +// unsafe { +// let has_been_scanned = ((*UPCALLS).julia_object_has_been_scanned)(internal_obj_addr); +// if has_been_scanned == 0 { +// ((*UPCALLS).mark_julia_object_as_scanned)(internal_obj_addr); +// closure.visit_edge(offset_edge); +// } +// } +// } +// } - if mmtk_object_is_managed_by_mmtk(internal_obj_addr.as_usize()) { - closure.visit_edge(JuliaVMEdge::Offset(offset_edge)); - } else { - unsafe { - let has_been_scanned = ((*UPCALLS).julia_object_has_been_scanned)(internal_obj_addr); - if has_been_scanned == 0 { - ((*UPCALLS).mark_julia_object_as_scanned)(internal_obj_addr); - closure.visit_edge(JuliaVMEdge::Offset(offset_edge)); - } - } - } +#[inline(always)] +pub fn trace_object_immediately(closure: &mut dyn EdgeVisitor, object: ObjectReference) -> ObjectReference { + closure.visit_object_immediately(object) } #[inline(always)] diff --git a/mmtk/src/lib.rs b/mmtk/src/lib.rs index 3aef983f..5d8de12d 100644 --- a/mmtk/src/lib.rs +++ b/mmtk/src/lib.rs @@ -125,13 +125,16 @@ type ProcessEdgeFn = type ProcessOffsetEdgeFn = *const extern "C" fn(closure: &mut dyn EdgeVisitor, slot: Address, offset: usize); +type TraceObjectImmediatelyFn = + *const extern "C" fn(closure: &mut dyn EdgeVisitor, object: ObjectReference) -> ObjectReference; + #[repr(C)] pub struct Julia_Upcalls { pub scan_julia_obj: extern "C" fn( obj: Address, closure: &mut dyn EdgeVisitor, process_edge: ProcessEdgeFn, - process_offset_edge: ProcessOffsetEdgeFn, + trace_object_immediately: TraceObjectImmediatelyFn, ), pub scan_julia_exc_obj: extern "C" fn( obj: Address, diff --git a/mmtk/src/scanning.rs b/mmtk/src/scanning.rs index 7640ad87..9a2e124c 100644 --- a/mmtk/src/scanning.rs +++ b/mmtk/src/scanning.rs @@ -1,8 +1,10 @@ use crate::edges::JuliaVMEdge; #[cfg(feature = "scan_obj_c")] use crate::julia_scanning::process_edge; +// #[cfg(feature = "scan_obj_c")] +// use crate::julia_scanning::process_offset_edge; #[cfg(feature = "scan_obj_c")] -use crate::julia_scanning::process_offset_edge; +use crate::julia_scanning::trace_object_immediately; use crate::FINALIZER_ROOTS; use crate::{ROOT_EDGES, ROOT_NODES, SINGLETON, UPCALLS}; use mmtk::memory_manager; @@ -69,7 +71,7 @@ impl Scanning for VMScanning { .lock() .unwrap() .drain() - .map(|e| JuliaVMEdge::Simple(mmtk::vm::edge_shape::SimpleEdge::from_address(e))) + .map(|e| mmtk::vm::edge_shape::SimpleEdge::from_address(e)) .collect(); info!("{} thread root edges", roots.len()); factory.create_process_edge_roots_work(roots); @@ -106,7 +108,7 @@ pub fn process_object(object: ObjectReference, closure: &mut dyn EdgeVisitor Date: Thu, 6 Jul 2023 07:17:55 +0000 Subject: [PATCH 2/2] Fix --- mmtk/Cargo.lock | 2 ++ mmtk/src/edges.rs | 6 +----- mmtk/src/julia_scanning.rs | 43 +++++--------------------------------- mmtk/src/lib.rs | 3 --- 4 files changed, 8 insertions(+), 46 deletions(-) diff --git a/mmtk/Cargo.lock b/mmtk/Cargo.lock index 0665a95e..09e9f18f 100644 --- a/mmtk/Cargo.lock +++ b/mmtk/Cargo.lock @@ -545,6 +545,7 @@ dependencies = [ [[package]] name = "mmtk" version = "0.18.0" +source = "git+https://github.com/qinsoon/mmtk-core.git?rev=28bde92892d699cea0e1e179931d3aeeee25e982#28bde92892d699cea0e1e179931d3aeeee25e982" dependencies = [ "atomic 0.5.1", "atomic-traits", @@ -589,6 +590,7 @@ dependencies = [ [[package]] name = "mmtk-macros" version = "0.18.0" +source = "git+https://github.com/qinsoon/mmtk-core.git?rev=28bde92892d699cea0e1e179931d3aeeee25e982#28bde92892d699cea0e1e179931d3aeeee25e982" dependencies = [ "proc-macro-error", "proc-macro2", diff --git a/mmtk/src/edges.rs b/mmtk/src/edges.rs index 3fead6c8..5fdcceae 100644 --- a/mmtk/src/edges.rs +++ b/mmtk/src/edges.rs @@ -1,12 +1,8 @@ -use atomic::Atomic; use mmtk::{ util::{Address, ObjectReference}, - vm::edge_shape::{Edge, SimpleEdge}, + vm::edge_shape::SimpleEdge, }; -use std::sync::atomic::AtomicUsize; -use std::sync::atomic::Ordering; - pub type JuliaVMEdge = SimpleEdge; #[derive(Hash, Clone, PartialEq, Eq, Debug)] diff --git a/mmtk/src/julia_scanning.rs b/mmtk/src/julia_scanning.rs index 93197502..7b0dce76 100644 --- a/mmtk/src/julia_scanning.rs +++ b/mmtk/src/julia_scanning.rs @@ -1,6 +1,5 @@ use crate::api::*; use crate::edges::JuliaVMEdge; -use crate::edges::OffsetEdge; use crate::julia_types::*; use crate::UPCALLS; use mmtk::util::{Address, ObjectReference}; @@ -57,8 +56,8 @@ pub unsafe fn scan_julia_object(addr: Address, closure: &mut dyn EdgeVisitor()).offset as u16 - * (*addr.to_ptr::()).elsize) as usize; + // let offset = ((*addr.to_ptr::()).offset as u16 + // * (*addr.to_ptr::()).elsize) as usize; // process_offset_edge(closure, addr, offset); unimplemented!(); } else if flags.how() == 3 { @@ -319,44 +318,12 @@ fn read_stack(addr: Address, offset: usize, lb: usize, ub: usize) -> Address { #[inline(always)] pub fn process_edge(closure: &mut dyn EdgeVisitor, slot: Address) { let simple_edge = SimpleEdge::from_address(slot); - closure.visit_edge(JuliaVMEdge::Simple(simple_edge)); + closure.visit_edge(simple_edge); } -// #[inline(always)] -// pub fn process_offset_edge( -// closure: &mut dyn EdgeVisitor, -// slot: Address, -// offset: usize, -// ) { -// let internal_obj: ObjectReference = unsafe { slot.load() }; -// let internal_obj_addr = internal_obj.to_raw_address(); -// if internal_obj_addr.is_zero() { -// return; -// } - -// let offset_edge = OffsetEdge::new_with_offset(slot, offset); - -// if mmtk_object_is_managed_by_mmtk(internal_obj_addr.as_usize()) { -// closure.visit_edge(offset_edge); -// } else { -// unsafe { -// let has_been_scanned = ((*UPCALLS).julia_object_has_been_scanned)(internal_obj_addr); -// if has_been_scanned == 0 { -// ((*UPCALLS).mark_julia_object_as_scanned)(internal_obj_addr); -// closure.visit_edge(offset_edge); -// } -// } -// } -// } - #[inline(always)] -pub fn process_offset_edge( - closure: &mut dyn EdgeVisitor, - slot: Address, - offset: usize, -) { - let offset_edge = OffsetEdge::new_with_offset(slot, offset); - closure.visit_edge(JuliaVMEdge::Offset(offset_edge)); +pub fn trace_object_immediately(closure: &mut dyn EdgeVisitor, object: ObjectReference) -> ObjectReference { + closure.visit_object_immediately(object) } #[inline(always)] diff --git a/mmtk/src/lib.rs b/mmtk/src/lib.rs index 5d8de12d..3932fb8e 100644 --- a/mmtk/src/lib.rs +++ b/mmtk/src/lib.rs @@ -122,9 +122,6 @@ extern "C" { type ProcessEdgeFn = *const extern "C" fn(closure: &mut dyn EdgeVisitor, slot: Address); -type ProcessOffsetEdgeFn = - *const extern "C" fn(closure: &mut dyn EdgeVisitor, slot: Address, offset: usize); - type TraceObjectImmediatelyFn = *const extern "C" fn(closure: &mut dyn EdgeVisitor, object: ObjectReference) -> ObjectReference;