diff --git a/julia/mmtk_julia.c b/julia/mmtk_julia.c index 618100a3..7571ad41 100644 --- a/julia/mmtk_julia.c +++ b/julia/mmtk_julia.c @@ -333,13 +333,13 @@ void scan_vm_specific_roots(RootsWorkClosure* closure) (closure->report_tpinned_nodes_func)(tpinned_buf.ptr, tpinned_len, tpinned_buf.cap, closure->data, false); } -JL_DLLEXPORT void scan_julia_exc_obj(void* obj_raw, void* closure, ProcessEdgeFn process_edge) { +JL_DLLEXPORT void scan_julia_exc_obj(void* obj_raw, void* closure, ProcessSlotFn process_slot) { jl_task_t *ta = (jl_task_t*)obj_raw; if (ta->excstack) { // inlining label `excstack` from mark_loop // if it is not managed by MMTk, nothing needs to be done because the object does not need to be scanned if (mmtk_object_is_managed_by_mmtk(ta->excstack)) { - process_edge(closure, &ta->excstack); + process_slot(closure, &ta->excstack); } jl_excstack_t *excstack = ta->excstack; size_t itr = ta->excstack->top; @@ -355,19 +355,19 @@ JL_DLLEXPORT void scan_julia_exc_obj(void* obj_raw, void* closure, ProcessEdgeFn // GC-managed values inside. size_t njlvals = jl_bt_num_jlvals(bt_entry); while (jlval_index < njlvals) { - jl_value_t** new_obj_edge = &bt_entry[2 + jlval_index].jlvalue; + jl_value_t** new_obj_slot = &bt_entry[2 + jlval_index].jlvalue; jlval_index += 1; - process_edge(closure, new_obj_edge); + process_slot(closure, new_obj_slot); } jlval_index = 0; } jl_bt_element_t *stack_raw = (jl_bt_element_t *)(excstack+1); - jl_value_t** stack_obj_edge = &stack_raw[itr-1].jlvalue; + jl_value_t** stack_obj_slot = &stack_raw[itr-1].jlvalue; itr = jl_excstack_next(excstack, itr); jlval_index = 0; - process_edge(closure, stack_obj_edge); + process_slot(closure, stack_obj_slot); } } } diff --git a/mmtk/Cargo.lock b/mmtk/Cargo.lock index 0f8f0803..16040ee4 100644 --- a/mmtk/Cargo.lock +++ b/mmtk/Cargo.lock @@ -28,47 +28,48 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.13" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" dependencies = [ "windows-sys", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" dependencies = [ "anstyle", "windows-sys", @@ -107,9 +108,9 @@ checksum = "41e67cd8309bbd06cd603a9e693a784ac2e5d1e955f11286e355089fcab3047c" [[package]] name = "autocfg" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "bitflags" @@ -134,9 +135,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15" +checksum = "78834c15cb5d5efe3452d58b1e8ba890dd62d21907f867f383358198e56ebca5" dependencies = [ "bytemuck_derive", ] @@ -149,17 +150,18 @@ checksum = "4da9a32f3fed317401fa3c862968128267c3106685286e15d5aaa3d7389c2f60" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.65", ] [[package]] name = "cc" -version = "1.0.94" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17f6e324229dc011159fcc089755d1e2e216a90d43a7dea6853ca740b84f35e7" +checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" dependencies = [ "jobserver", "libc", + "once_cell", ] [[package]] @@ -184,9 +186,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] name = "core-foundation-sys" @@ -209,9 +211,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.12" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ "crossbeam-utils", ] @@ -246,9 +248,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "delegate" @@ -258,7 +260,7 @@ checksum = "4e018fccbeeb50ff26562ece792ed06659b9c2dae79ece77c4456bb10d9bf79b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.65", ] [[package]] @@ -269,9 +271,9 @@ checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" [[package]] name = "either" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" [[package]] name = "enum-map" @@ -290,7 +292,7 @@ checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.65", ] [[package]] @@ -400,6 +402,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "itertools" version = "0.12.1" @@ -411,9 +419,9 @@ dependencies = [ [[package]] name = "jobserver" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685a7d121ee3f65ae4fddd72b25a04bb36b6af81bc0828f7d5434c0fe60fa3a2" +checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" dependencies = [ "libc", ] @@ -435,9 +443,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libgit2-sys" @@ -465,9 +473,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -496,8 +504,8 @@ dependencies = [ [[package]] name = "mmtk" -version = "0.24.0" -source = "git+https://github.com/mmtk/mmtk-core.git?rev=5a01555b5aee984b634f81e9d137f1ae0410fd39#5a01555b5aee984b634f81e9d137f1ae0410fd39" +version = "0.25.0" +source = "git+https://github.com/mmtk/mmtk-core.git?rev=56b2521d2b99848ee0613a0a5288fe6d81b754ba#56b2521d2b99848ee0613a0a5288fe6d81b754ba" dependencies = [ "atomic 0.6.0", "atomic-traits", @@ -548,13 +556,13 @@ dependencies = [ [[package]] name = "mmtk-macros" -version = "0.24.0" -source = "git+https://github.com/mmtk/mmtk-core.git?rev=5a01555b5aee984b634f81e9d137f1ae0410fd39#5a01555b5aee984b634f81e9d137f1ae0410fd39" +version = "0.25.0" +source = "git+https://github.com/mmtk/mmtk-core.git?rev=56b2521d2b99848ee0613a0a5288fe6d81b754ba#56b2521d2b99848ee0613a0a5288fe6d81b754ba" dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.65", ] [[package]] @@ -568,9 +576,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] @@ -641,9 +649,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.81" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43" dependencies = [ "unicode-ident", ] @@ -717,9 +725,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "scopeguard" @@ -729,9 +737,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "spin" @@ -764,7 +772,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.60", + "syn 2.0.65", ] [[package]] @@ -779,9 +787,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.60" +version = "2.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +checksum = "d2863d96a84c6439701d7a38f9de935ec562c8832cc55d1dde0f513b52fad106" dependencies = [ "proc-macro2", "quote", @@ -790,9 +798,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.30.10" +version = "0.30.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d7c217777061d5a2d652aea771fb9ba98b6dade657204b08c4b9604d11555b" +checksum = "732ffa00f53e6b2af46208fba5718d9662a421049204e156328b66791ffa15ae" dependencies = [ "cfg-if", "core-foundation-sys", @@ -899,7 +907,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.65", "wasm-bindgen-shared", ] @@ -921,7 +929,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.65", "wasm-bindgen-backend", "wasm-bindgen-shared", ] diff --git a/mmtk/Cargo.toml b/mmtk/Cargo.toml index 7479a430..97a569f9 100644 --- a/mmtk/Cargo.toml +++ b/mmtk/Cargo.toml @@ -31,7 +31,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="5a01555b5aee984b634f81e9d137f1ae0410fd39" } +mmtk = { git = "https://github.com/mmtk/mmtk-core.git", rev = "56b2521d2b99848ee0613a0a5288fe6d81b754ba" } # Uncomment the following to build locally # mmtk = { path = "../../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 7ef4dcec..ce629092 100644 --- a/mmtk/api/mmtk.h +++ b/mmtk/api/mmtk.h @@ -11,8 +11,8 @@ extern "C" { typedef void* MMTk_Mutator; typedef void* MMTk_TraceLocal; -typedef void (*ProcessEdgeFn)(void* closure, void* slot); -typedef void (*ProcessOffsetEdgeFn)(void* closure, void* slot, int offset); +typedef void (*ProcessSlotFn)(void* closure, void* slot); +typedef void (*ProcessOffsetSlotFn)(void* closure, void* slot, int offset); typedef struct { void** ptr; @@ -20,7 +20,7 @@ typedef struct { } RootsWorkBuffer; typedef struct { - RootsWorkBuffer (*report_edges_func)(void** buf, size_t size, size_t cap, void* data, bool renew); + RootsWorkBuffer (*report_slots_func)(void** buf, size_t size, size_t cap, void* data, bool renew); RootsWorkBuffer (*report_nodes_func)(void** buf, size_t size, size_t cap, void* data, bool renew); RootsWorkBuffer (*report_tpinned_nodes_func)(void** buf, size_t size, size_t cap, void* data, bool renew); void* data; @@ -71,7 +71,7 @@ extern uintptr_t JULIA_MALLOC_BYTES; // * int is 4 bytes // * size_t is 8 bytes typedef struct { - void (* scan_julia_exc_obj) (void* obj, void* closure, ProcessEdgeFn process_edge); + void (* scan_julia_exc_obj) (void* obj, void* closure, ProcessSlotFn process_slot); void* (* get_stackbase) (int16_t tid); void (* mmtk_jl_run_finalizers) (void* tls); void (* mmtk_jl_throw_out_of_memory_error) (void); diff --git a/mmtk/src/api.rs b/mmtk/src/api.rs index 7898f752..ca8bd07f 100644 --- a/mmtk/src/api.rs +++ b/mmtk/src/api.rs @@ -12,6 +12,7 @@ use libc::c_char; use log::*; use mmtk::memory_manager; use mmtk::scheduler::GCWorker; +use mmtk::util::api_util::NullableObjectReference; use mmtk::util::opaque_pointer::*; use mmtk::util::{Address, ObjectReference, OpaquePointer}; use mmtk::AllocationSemantics; @@ -369,7 +370,7 @@ pub extern "C" fn mmtk_memory_region_copy( dst_addr: Address, count: usize, ) { - use crate::edges::JuliaMemorySlice; + use crate::slots::JuliaMemorySlice; let src = JuliaMemorySlice { owner: src_obj, start: src_addr, @@ -405,16 +406,14 @@ fn set_side_log_bit_for_region(start: Address, size: usize) { pub extern "C" fn mmtk_object_reference_write_post( mutator: *mut Mutator, src: ObjectReference, - target: ObjectReference, + target: NullableObjectReference, ) { let mutator = unsafe { &mut *mutator }; memory_manager::object_reference_write_post( mutator, src, - crate::edges::JuliaVMEdge::Simple(mmtk::vm::edge_shape::SimpleEdge::from_address( - Address::ZERO, - )), - target, + crate::slots::JuliaVMSlot::Simple(mmtk::vm::slot::SimpleSlot::from_address(Address::ZERO)), + target.into(), ) } @@ -422,15 +421,13 @@ pub extern "C" fn mmtk_object_reference_write_post( pub extern "C" fn mmtk_object_reference_write_slow( mutator: &'static mut Mutator, src: ObjectReference, - target: ObjectReference, + target: NullableObjectReference, ) { use mmtk::MutatorContext; mutator.barrier().object_reference_write_slow( src, - crate::edges::JuliaVMEdge::Simple(mmtk::vm::edge_shape::SimpleEdge::from_address( - Address::ZERO, - )), - target, + crate::slots::JuliaVMSlot::Simple(mmtk::vm::slot::SimpleSlot::from_address(Address::ZERO)), + target.into(), ); } diff --git a/mmtk/src/julia_finalizer.rs b/mmtk/src/julia_finalizer.rs index 34289118..3a9855c2 100644 --- a/mmtk/src/julia_finalizer.rs +++ b/mmtk/src/julia_finalizer.rs @@ -112,7 +112,9 @@ impl ArrayListT { } fn gc_ptr_clear_tag(addr: Address, tag: usize) -> ObjectReference { - ObjectReference::from_raw_address(unsafe { Address::from_usize(addr & !tag) }) + let addr = unsafe { Address::from_usize(addr & !tag) }; + debug_assert!(!addr.is_zero()); + unsafe { ObjectReference::from_raw_address_unchecked(addr) } } pub fn gc_ptr_tag(addr: Address, tag: usize) -> bool { @@ -148,12 +150,13 @@ fn sweep_finalizer_list( (true, false) } else { let isfreed = !memory_manager::is_live_object::(v); + debug_assert!(!fin.is_zero()); let isold = finalizer_list_marked.is_some() && !isfreed && (mmtk_object_is_managed_by_mmtk(fin.as_usize()) - && memory_manager::is_live_object::( - ObjectReference::from_raw_address(fin), - ) + && memory_manager::is_live_object::(unsafe { + ObjectReference::from_raw_address_unchecked(fin) + }) || !(mmtk_object_is_managed_by_mmtk(fin.as_usize()))); (isfreed, isold) }; @@ -208,7 +211,8 @@ fn mark_finlist(list: &mut ArrayListT, start: usize, tracer: &m cur_tag = 1; gc_ptr_clear_tag(cur, 1) } else { - ObjectReference::from_raw_address(cur) + // unsafe: We checked `cur.is_zero()` before. + unsafe { ObjectReference::from_raw_address_unchecked(cur) } }; if gc_ptr_tag(cur, 2) { i += 1; diff --git a/mmtk/src/julia_scanning.rs b/mmtk/src/julia_scanning.rs index e4109521..1ec76e7c 100644 --- a/mmtk/src/julia_scanning.rs +++ b/mmtk/src/julia_scanning.rs @@ -1,17 +1,16 @@ #[cfg(not(feature = "non_moving"))] use crate::api::mmtk_is_pinned; use crate::api::mmtk_object_is_managed_by_mmtk; -use crate::edges::JuliaVMEdge; -use crate::edges::OffsetEdge; use crate::julia_types::*; use crate::object_model::mmtk_jl_array_ndims; -use crate::JuliaVM; +use crate::slots::JuliaVMSlot; +use crate::slots::OffsetSlot; use crate::JULIA_BUFF_TAG; use crate::UPCALLS; use memoffset::offset_of; use mmtk::util::{Address, ObjectReference}; -use mmtk::vm::edge_shape::SimpleEdge; -use mmtk::vm::EdgeVisitor; +use mmtk::vm::slot::SimpleSlot; +use mmtk::vm::SlotVisitor; use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering; @@ -47,7 +46,7 @@ const PRINT_OBJ_TYPE: bool = false; // This function is a rewrite of `gc_mark_outrefs()` in `gc.c` // INFO: *_custom() functions are acessors to bitfields that do not use bindgen generated code. #[inline(always)] -pub unsafe fn scan_julia_object>(obj: Address, closure: &mut EV) { +pub unsafe fn scan_julia_object>(obj: Address, closure: &mut SV) { // get Julia object type let vt = mmtk_jl_typeof(obj); @@ -66,9 +65,9 @@ pub unsafe fn scan_julia_object>(obj: Address, clos let globalref = ::std::ptr::addr_of!((*b).globalref); let ty = ::std::ptr::addr_of!((*b).ty); - process_edge(closure, Address::from_usize(value as usize)); - process_edge(closure, Address::from_usize(globalref as usize)); - process_edge(closure, Address::from_usize(ty as usize)); + process_slot(closure, Address::from_usize(value as usize)); + process_slot(closure, Address::from_usize(globalref as usize)); + process_slot(closure, Address::from_usize(ty as usize)); // clearing tag bits Address::from_usize(as_tagged_value).store::(t_header.as_usize() & !3); return; @@ -91,7 +90,7 @@ pub unsafe fn scan_julia_object>(obj: Address, clos let objary_end = objary_begin.shift::
(length as isize); while objary_begin < objary_end { - process_edge(closure, objary_begin); + process_slot(closure, objary_begin); objary_begin = objary_begin.shift::
(1); } } else if (*vt).name == jl_array_typename { @@ -112,7 +111,7 @@ pub unsafe fn scan_julia_object>(obj: Address, clos // julia-allocated buffer that needs to be marked let offset = (*array).offset as usize * (*array).elsize as usize; let data_addr = ::std::ptr::addr_of!((*array).data); - process_offset_edge(closure, Address::from_ptr(data_addr), offset); + process_offset_slot(closure, Address::from_ptr(data_addr), offset); } else if flags.how_custom() == 2 { // malloc-allocated pointer this array object manages // should be processed below if it contains pointers @@ -132,7 +131,7 @@ pub unsafe fn scan_julia_object>(obj: Address, clos mmtk_is_pinned(owner_addr.load()) ); - process_edge(closure, owner_addr); + process_slot(closure, owner_addr); return; } @@ -151,7 +150,7 @@ pub unsafe fn scan_julia_object>(obj: Address, clos let objary_end = objary_begin.shift::
(length as isize); while objary_begin < objary_end { - process_edge(closure, objary_begin); + process_slot(closure, objary_begin); objary_begin = objary_begin.shift::
(1); } } else if flags.hasptr_custom() != 0 { @@ -166,7 +165,7 @@ pub unsafe fn scan_julia_object>(obj: Address, clos if npointers == 1 { objary_begin = objary_begin.shift::
((*layout).first_ptr as isize); while objary_begin < objary_end { - process_edge(closure, objary_begin); + process_slot(closure, objary_begin); objary_begin = objary_begin.shift::
(elsize as isize); } } else if (*layout).fielddesc_type() == 0 { @@ -179,7 +178,7 @@ pub unsafe fn scan_julia_object>(obj: Address, clos while elem_begin < elem_end { let elem_begin_loaded = elem_begin.load::(); let slot = objary_begin.shift::
(elem_begin_loaded as isize); - process_edge(closure, slot); + process_slot(closure, slot); elem_begin = elem_begin.shift::(1); } elem_begin = obj8_begin; @@ -193,7 +192,7 @@ pub unsafe fn scan_julia_object>(obj: Address, clos while obj16_begin < obj16_end { let elem_begin_loaded = obj16_begin.load::(); let slot = objary_begin.shift::
(elem_begin_loaded as isize); - process_edge(closure, slot); + process_slot(closure, slot); obj16_begin = obj16_begin.shift::(1); } obj16_begin = mmtk_jl_dt_layout_ptrs(layout); @@ -229,24 +228,24 @@ pub unsafe fn scan_julia_object>(obj: Address, clos } if (b as usize) != 0 { - process_edge(closure, begin); + process_slot(closure, begin); } let value = ::std::ptr::addr_of!((*b).value); let globalref = ::std::ptr::addr_of!((*b).globalref); let ty = ::std::ptr::addr_of!((*b).ty); - process_edge(closure, Address::from_usize(value as usize)); - process_edge(closure, Address::from_usize(globalref as usize)); - process_edge(closure, Address::from_usize(ty as usize)); + process_slot(closure, Address::from_usize(value as usize)); + process_slot(closure, Address::from_usize(globalref as usize)); + process_slot(closure, Address::from_usize(ty as usize)); begin = begin.shift::
(2); } - let parent_edge = ::std::ptr::addr_of!((*m).parent); + let parent_slot = ::std::ptr::addr_of!((*m).parent); if PRINT_OBJ_TYPE { - println!(" - scan parent: {:?}\n", parent_edge); + println!(" - scan parent: {:?}\n", parent_slot); } - process_edge(closure, Address::from_ptr(parent_edge)); + process_slot(closure, Address::from_ptr(parent_slot)); // m.usings.items may be inlined in the module when the array list size <= AL_N_INLINE (cf. arraylist_new) // In that case it may be an mmtk object and not a malloced address. @@ -255,7 +254,7 @@ pub unsafe fn scan_julia_object>(obj: Address, clos if mmtk_object_is_managed_by_mmtk((*m).usings.items as usize) { let offset = OFFSET_OF_INLINED_SPACE_IN_MODULE; let slot = Address::from_ptr(::std::ptr::addr_of!((*m).usings.items)); - process_offset_edge(closure, slot, offset); + process_offset_slot(closure, slot, offset); } let nusings = (*m).usings.len; @@ -267,7 +266,7 @@ pub unsafe fn scan_julia_object>(obj: Address, clos if PRINT_OBJ_TYPE { println!(" - scan usings: {:?}\n", objary_begin); } - process_edge(closure, objary_begin); + process_slot(closure, objary_begin); objary_begin = objary_begin.shift::
(1); } } @@ -292,7 +291,7 @@ pub unsafe fn scan_julia_object>(obj: Address, clos while obj8_begin < obj8_end { let obj8_begin_loaded = obj8_begin.load::(); let slot = obj.shift::
(obj8_begin_loaded as isize); - process_edge(closure, slot); + process_slot(closure, slot); obj8_begin = obj8_begin.shift::(1); } } else if vt == jl_string_type { @@ -325,7 +324,7 @@ pub unsafe fn scan_julia_object>(obj: Address, clos while obj8_begin < obj8_end { let obj8_begin_loaded = obj8_begin.load::(); let slot = obj.shift::
(obj8_begin_loaded as isize); - process_edge(closure, slot); + process_slot(closure, slot); obj8_begin = obj8_begin.shift::(1); } } else if (*layout).fielddesc_type() == 1 { @@ -335,7 +334,7 @@ pub unsafe fn scan_julia_object>(obj: Address, clos while obj16_begin < obj16_end { let obj16_begin_loaded = obj16_begin.load::(); let slot = obj.shift::
(obj16_begin_loaded as isize); - process_edge(closure, slot); + process_slot(closure, slot); obj16_begin = obj16_begin.shift::(1); } } else if (*layout).fielddesc_type() == 2 { @@ -345,7 +344,7 @@ pub unsafe fn scan_julia_object>(obj: Address, clos while obj32_begin < obj32_end { let obj32_begin_loaded = obj32_begin.load::(); let slot = obj.shift::
(obj32_begin_loaded as isize); - process_edge(closure, slot); + process_slot(closure, slot); obj32_begin = obj32_begin.shift::(1); } } else { @@ -356,7 +355,7 @@ pub unsafe fn scan_julia_object>(obj: Address, clos } } -pub unsafe fn mmtk_scan_gcstack<'a, EV: EdgeVisitor>( +pub unsafe fn mmtk_scan_gcstack<'a, EV: SlotVisitor>( ta: *const mmtk_jl_task_t, mut closure: &'a mut EV, mut pclosure: Option<&'a mut EV>, @@ -366,8 +365,8 @@ pub unsafe fn mmtk_scan_gcstack<'a, EV: EdgeVisitor>( #[cfg(feature = "julia_copy_stack")] if stkbuf != std::ptr::null_mut() && copy_stack != 0 { - let stkbuf_edge = Address::from_ptr(::std::ptr::addr_of!((*ta).stkbuf)); - process_edge(closure, stkbuf_edge); + let stkbuf_slot = Address::from_ptr(::std::ptr::addr_of!((*ta).stkbuf)); + process_slot(closure, stkbuf_slot); } let mut s = (*ta).gcstack; @@ -409,7 +408,7 @@ pub unsafe fn mmtk_scan_gcstack<'a, EV: EdgeVisitor>( if (nroots.as_usize() & 1) != 0 { let slot = read_stack(rts.shift::
(i as isize), offset, lb, ub); let real_addr = get_stack_addr(slot, offset, lb, ub); - process_edge(*closure_to_use, real_addr); + process_slot(*closure_to_use, real_addr); } else { let real_addr = get_stack_addr(rts.shift::
(i as isize), offset, lb, ub); @@ -425,12 +424,12 @@ pub unsafe fn mmtk_scan_gcstack<'a, EV: EdgeVisitor>( // pointer is not malloced but function is native, so skip it if gc_ptr_tag(slot, 1) { - process_offset_edge(*closure_to_use, real_addr, 1); + process_offset_slot(*closure_to_use, real_addr, 1); i += 2; continue; } - process_edge(*closure_to_use, real_addr); + process_slot(*closure_to_use, real_addr); } i += 1; @@ -456,7 +455,7 @@ pub unsafe fn mmtk_scan_gcstack<'a, EV: EdgeVisitor>( ((*UPCALLS).scan_julia_exc_obj)( Address::from_ptr(ta), Address::from_mut_ptr(closure), - process_edge:: as _, + process_slot:: as _, ); } } @@ -477,29 +476,36 @@ pub fn get_stack_addr(addr: Address, offset: isize, lb: u64, ub: u64) -> Address } } -use mmtk::vm::edge_shape::Edge; - #[inline(always)] -pub fn process_edge>(closure: &mut EV, slot: Address) { - let simple_edge = SimpleEdge::from_address(slot); - debug_assert!( - simple_edge.load().is_null() - || mmtk::memory_manager::is_in_mmtk_spaces::(simple_edge.load()), - "Object {:?} in slot {:?} is not mapped address", - simple_edge.load(), - simple_edge - ); +pub fn process_slot>(closure: &mut EV, slot: Address) { + let simple_slot = SimpleSlot::from_address(slot); - // captures wrong edges before creating the work - debug_assert!( - simple_edge.load().to_raw_address().as_usize() % 16 == 0 - || simple_edge.load().to_raw_address().as_usize() % 8 == 0, - "Object {:?} in slot {:?} is not aligned to 8 or 16", - simple_edge.load(), - simple_edge - ); + #[cfg(debug_assertions)] + { + use crate::JuliaVM; + use mmtk::vm::slot::Slot; - closure.visit_edge(JuliaVMEdge::Simple(simple_edge)); + if let Some(objref) = simple_slot.load() { + debug_assert!( + mmtk::memory_manager::is_in_mmtk_spaces::(objref), + "Object {:?} in slot {:?} is not mapped address", + objref, + simple_slot + ); + + let raw_addr_usize = objref.to_raw_address().as_usize(); + + // captures wrong slots before creating the work + debug_assert!( + raw_addr_usize % 16 == 0 || raw_addr_usize % 8 == 0, + "Object {:?} in slot {:?} is not aligned to 8 or 16", + objref, + simple_slot + ); + } + } + + closure.visit_slot(JuliaVMSlot::Simple(simple_slot)); } // #[inline(always)] @@ -540,21 +546,28 @@ pub fn process_edge>(closure: &mut EV, slot: Addres // } #[inline(always)] -pub fn process_offset_edge>( +pub fn process_offset_slot>( closure: &mut EV, slot: Address, offset: usize, ) { - let offset_edge = OffsetEdge::new_with_offset(slot, offset); - debug_assert!( - offset_edge.load().is_null() - || mmtk::memory_manager::is_in_mmtk_spaces::(offset_edge.load()), - "Object {:?} in slot {:?} is not mapped address", - offset_edge.load(), - offset_edge - ); + let offset_slot = OffsetSlot::new_with_offset(slot, offset); + #[cfg(debug_assertions)] + { + use crate::JuliaVM; + use mmtk::vm::slot::Slot; + + if let Some(objref) = offset_slot.load() { + debug_assert!( + mmtk::memory_manager::is_in_mmtk_spaces::(objref), + "Object {:?} in slot {:?} is not mapped address", + objref, + offset_slot + ); + } + } - closure.visit_edge(JuliaVMEdge::Offset(offset_edge)); + closure.visit_slot(JuliaVMSlot::Offset(offset_slot)); } #[inline(always)] @@ -663,5 +676,6 @@ pub fn mmtk_jl_bt_num_uintvals(bt_entry: *mut mmtk_jl_bt_element_t) -> usize { pub fn mmtk_jl_bt_entry_jlvalue(bt_entry: *mut mmtk_jl_bt_element_t, i: usize) -> ObjectReference { let entry = unsafe { (*bt_entry.add(2 + i)).__bindgen_anon_1.jlvalue }; - ObjectReference::from_raw_address(Address::from_mut_ptr(entry)) + debug_assert!(!entry.is_null()); + unsafe { ObjectReference::from_raw_address_unchecked(Address::from_mut_ptr(entry)) } } diff --git a/mmtk/src/lib.rs b/mmtk/src/lib.rs index 14165f49..2811face 100644 --- a/mmtk/src/lib.rs +++ b/mmtk/src/lib.rs @@ -18,11 +18,11 @@ use std::sync::{Arc, Condvar, Mutex, RwLock}; pub mod active_plan; pub mod api; pub mod collection; -pub mod edges; pub mod gc_trigger; pub mod object_model; pub mod reference_glue; pub mod scanning; +pub mod slots; pub mod util; pub mod julia_finalizer; @@ -36,7 +36,7 @@ pub mod julia_types; #[derive(Default)] pub struct JuliaVM; -use crate::edges::JuliaVMEdge; +use crate::slots::JuliaVMSlot; impl VMBinding for JuliaVM { const MAX_ALIGNMENT: usize = 64; @@ -46,8 +46,8 @@ impl VMBinding for JuliaVM { type VMCollection = collection::VMCollection; type VMActivePlan = active_plan::VMActivePlan; type VMReferenceGlue = reference_glue::VMReferenceGlue; - type VMMemorySlice = edges::JuliaMemorySlice; - type VMEdge = JuliaVMEdge; + type VMMemorySlice = slots::JuliaMemorySlice; + type VMSlot = JuliaVMSlot; } /// This is used to ensure we initialize MMTk at a specified timing. @@ -86,12 +86,12 @@ lazy_static! { pub static ref MUTATORS: RwLock> = RwLock::new(HashMap::new()); } -type ProcessEdgeFn = *const extern "C" fn(closure: Address, slot: Address); +type ProcessSlotFn = *const extern "C" fn(closure: Address, slot: Address); #[repr(C)] pub struct Julia_Upcalls { pub scan_julia_exc_obj: - extern "C" fn(obj: Address, closure: Address, process_edge: ProcessEdgeFn), + extern "C" fn(obj: Address, closure: Address, process_slot: ProcessSlotFn), pub get_stackbase: extern "C" fn(tid: u16) -> usize, pub mmtk_jl_run_finalizers: extern "C" fn(tls: OpaquePointer), pub jl_throw_out_of_memory_error: extern "C" fn(), @@ -109,7 +109,7 @@ pub struct Julia_Upcalls { pub get_marked_finalizers_list: extern "C" fn() -> Address, pub arraylist_grow: extern "C" fn(Address, usize), pub get_jl_gc_have_pending_finalizers: extern "C" fn() -> *mut i32, - pub scan_vm_specific_roots: extern "C" fn(closure: *mut crate::edges::RootsWorkClosure), + pub scan_vm_specific_roots: extern "C" fn(closure: *mut crate::slots::RootsWorkClosure), pub update_inlined_array: extern "C" fn(to: Address, from: Address), pub prepare_to_collect: extern "C" fn(), pub check_is_collection_disabled: extern "C" fn() -> bool, diff --git a/mmtk/src/object_model.rs b/mmtk/src/object_model.rs index e99061e5..322dfd8e 100644 --- a/mmtk/src/object_model.rs +++ b/mmtk/src/object_model.rs @@ -62,25 +62,28 @@ impl ObjectModel for VMObjectModel { copy_context: &mut GCWorkerCopyContext, ) -> ObjectReference { let bytes = Self::get_current_size(from); - let from_start_ref = ObjectReference::from_raw_address(Self::ref_to_object_start(from)); - let header_offset = - from.to_raw_address().as_usize() - from_start_ref.to_raw_address().as_usize(); + let from_addr = from.to_raw_address(); + let from_start = Self::ref_to_object_start(from); + let header_offset = from_addr - from_start; let dst = if header_offset == 8 { // regular object - copy_context.alloc_copy(from_start_ref, bytes, 16, 8, semantics) + // Note: The `from` reference is not used by any allocator currently in MMTk core. + copy_context.alloc_copy(from, bytes, 16, 8, semantics) } else if header_offset == 16 { // buffer should not be copied unimplemented!(); } else { unimplemented!() }; + // `alloc_copy` should never return zero. + debug_assert!(!dst.is_zero()); - let src = Self::ref_to_object_start(from); + let src = from_start; unsafe { std::ptr::copy_nonoverlapping::(src.to_ptr(), dst.to_mut_ptr(), bytes); } - let to_obj = ObjectReference::from_raw_address(dst + header_offset); + let to_obj = unsafe { ObjectReference::from_raw_address_unchecked(dst + header_offset) }; trace!("Copying object from {} to {}", from, to_obj); @@ -99,7 +102,7 @@ impl ObjectModel for VMObjectModel { { use atomic::Ordering; unsafe { - libc::memset(from_start_ref.to_raw_address().to_mut_ptr(), 0, bytes); + libc::memset(from_start.to_mut_ptr(), 0, bytes); } Self::LOCAL_FORWARDING_BITS_SPEC.store_atomic::( @@ -160,7 +163,9 @@ impl ObjectModel for VMObjectModel { #[inline(always)] fn address_to_ref(address: Address) -> ObjectReference { - ObjectReference::from_raw_address(address) + // `address` is a result of `ref_to_address(object)`, where `object` cannot be NULL. + debug_assert!(!address.is_zero()); + unsafe { ObjectReference::from_raw_address_unchecked(address) } } #[inline(always)] diff --git a/mmtk/src/reference_glue.rs b/mmtk/src/reference_glue.rs index de8fac5c..c7fc8f6f 100644 --- a/mmtk/src/reference_glue.rs +++ b/mmtk/src/reference_glue.rs @@ -26,40 +26,54 @@ impl Finalizable for JuliaFinalizableObject { self.set_reference(trace.trace_object(self.get_reference())); if !self.2 { // not a void pointer - trace.trace_object(ObjectReference::from_raw_address(self.1)); + debug_assert!(!self.1.is_zero()); + let objref = unsafe { ObjectReference::from_raw_address_unchecked(self.1) }; + trace.trace_object(objref); } } } pub struct VMReferenceGlue {} -impl ReferenceGlue for VMReferenceGlue { - type FinalizableType = JuliaFinalizableObject; - fn set_referent(reference: ObjectReference, referent: ObjectReference) { +impl VMReferenceGlue { + fn load_referent_raw(reference: ObjectReference) -> *mut mmtk_jl_value_t { + let reff = reference.to_raw_address().to_ptr::(); + unsafe { (*reff).value } + } + + fn set_referent_raw(reference: ObjectReference, referent_raw: *mut mmtk_jl_value_t) { + let reff = reference.to_raw_address().to_mut_ptr::(); unsafe { - let reff = reference.to_raw_address().to_mut_ptr::(); - let referent_raw = referent.to_raw_address().to_mut_ptr::(); (*reff).value = referent_raw; } } +} - fn clear_referent(new_reference: ObjectReference) { - Self::set_referent(new_reference, unsafe { - ObjectReference::from_raw_address(Address::from_mut_ptr(jl_nothing)) - }); +impl ReferenceGlue for VMReferenceGlue { + type FinalizableType = JuliaFinalizableObject; + + fn set_referent(reference: ObjectReference, referent: ObjectReference) { + Self::set_referent_raw(reference, referent.to_raw_address().to_mut_ptr()); } - fn get_referent(object: ObjectReference) -> ObjectReference { - let referent; - unsafe { - let reff = object.to_raw_address().to_mut_ptr::(); - referent = ObjectReference::from_raw_address(Address::from_mut_ptr((*reff).value)); - } - referent + fn clear_referent(new_reference: ObjectReference) { + Self::set_referent_raw(new_reference, unsafe { jl_nothing }); } - fn is_referent_cleared(referent: ObjectReference) -> bool { - unsafe { referent.to_raw_address().to_mut_ptr() == jl_nothing } + fn get_referent(object: ObjectReference) -> Option { + let value = Self::load_referent_raw(object); + if value == unsafe { jl_nothing } { + return None; + } else { + debug_assert!( + !value.is_null(), + "A weak reference {} contains null referent pointer", + object + ); + let objref = + unsafe { ObjectReference::from_raw_address_unchecked(Address::from_ptr(value)) }; + Some(objref) + } } fn enqueue_references(_references: &[ObjectReference], _tls: VMWorkerThread) {} diff --git a/mmtk/src/scanning.rs b/mmtk/src/scanning.rs index 10bf7f63..b5515f58 100644 --- a/mmtk/src/scanning.rs +++ b/mmtk/src/scanning.rs @@ -1,14 +1,15 @@ -use crate::edges::JuliaVMEdge; +use crate::slots::JuliaVMSlot; use crate::{SINGLETON, UPCALLS}; use mmtk::memory_manager; use mmtk::scheduler::*; +use mmtk::util::opaque_pointer::*; +use mmtk::util::Address; use mmtk::util::ObjectReference; -use mmtk::util::{opaque_pointer::*, Address}; -use mmtk::vm::edge_shape::Edge; -use mmtk::vm::EdgeVisitor; +use mmtk::vm::slot::Slot; use mmtk::vm::ObjectTracerContext; use mmtk::vm::RootsWorkFactory; use mmtk::vm::Scanning; +use mmtk::vm::SlotVisitor; use mmtk::vm::VMBinding; use mmtk::Mutator; use mmtk::MMTK; @@ -21,26 +22,23 @@ impl Scanning for VMScanning { fn scan_roots_in_mutator_thread( _tls: VMWorkerThread, mutator: &'static mut Mutator, - mut factory: impl RootsWorkFactory, + mut factory: impl RootsWorkFactory, ) { - // This allows us to reuse mmtk_scan_gcstack which expectes an EdgeVisitor + // This allows us to reuse mmtk_scan_gcstack which expectes an SlotVisitor // Push the nodes as they need to be transitively pinned - struct EdgeBuffer { + struct SlotBuffer { pub buffer: Vec, } - impl mmtk::vm::EdgeVisitor for EdgeBuffer { - fn visit_edge(&mut self, edge: JuliaVMEdge) { - match edge { - JuliaVMEdge::Simple(se) => { - let slot = se.as_address(); - let object = unsafe { slot.load::() }; - if !object.is_null() { + impl mmtk::vm::SlotVisitor for SlotBuffer { + fn visit_slot(&mut self, slot: JuliaVMSlot) { + match slot { + JuliaVMSlot::Simple(se) => { + if let Some(object) = se.load() { self.buffer.push(object); } } - JuliaVMEdge::Offset(oe) => { - let object = oe.load(); - if !object.is_null() { + JuliaVMSlot::Offset(oe) => { + if let Some(object) = oe.load() { self.buffer.push(object); } } @@ -52,8 +50,8 @@ impl Scanning for VMScanning { use crate::julia_types::*; let ptls: &mut mmtk__jl_tls_states_t = unsafe { std::mem::transmute(mutator.mutator_tls) }; - let mut tpinning_edge_buffer = EdgeBuffer { buffer: vec![] }; // need to be transitively pinned - let mut pinning_edge_buffer = EdgeBuffer { buffer: vec![] }; // roots from the shadow stack that we know that do not need to be transitively pinned + let mut tpinning_slot_buffer = SlotBuffer { buffer: vec![] }; // need to be transitively pinned + let mut pinning_slot_buffer = SlotBuffer { buffer: vec![] }; // roots from the shadow stack that we know that do not need to be transitively pinned let mut node_buffer = vec![]; // Scan thread local from ptls: See gc_queue_thread_local in gc.c @@ -62,8 +60,8 @@ impl Scanning for VMScanning { unsafe { mmtk_scan_gcstack( task, - &mut tpinning_edge_buffer, - Some(&mut pinning_edge_buffer), + &mut tpinning_slot_buffer, + Some(&mut pinning_slot_buffer), ); } if task_is_root { @@ -75,7 +73,11 @@ impl Scanning for VMScanning { Address::from_ptr(task) ); - node_buffer.push(ObjectReference::from_raw_address(Address::from_ptr(task))); + // unsafe: We checked `!task.is_null()` before. + let objref = unsafe { + ObjectReference::from_raw_address_unchecked(Address::from_ptr(task)) + }; + node_buffer.push(objref); } } }; @@ -96,9 +98,12 @@ impl Scanning for VMScanning { root_scan_task(ptls.next_task, true); root_scan_task(ptls.previous_task, true); if !ptls.previous_exception.is_null() { - node_buffer.push(ObjectReference::from_raw_address(Address::from_mut_ptr( - ptls.previous_exception, - ))); + node_buffer.push(unsafe { + // unsafe: We have just checked `ptls.previous_exception` is not null. + ObjectReference::from_raw_address_unchecked(Address::from_mut_ptr( + ptls.previous_exception, + )) + }); } // Scan backtrace buffer: See gc_queue_bt_buf in gc.c @@ -131,14 +136,14 @@ impl Scanning for VMScanning { // Push work const CAPACITY_PER_PACKET: usize = 4096; - for tpinning_roots in tpinning_edge_buffer + for tpinning_roots in tpinning_slot_buffer .buffer .chunks(CAPACITY_PER_PACKET) .map(|c| c.to_vec()) { factory.create_process_tpinning_roots_work(tpinning_roots); } - for pinning_roots in pinning_edge_buffer + for pinning_roots in pinning_slot_buffer .buffer .chunks(CAPACITY_PER_PACKET) .map(|c| c.to_vec()) @@ -152,21 +157,21 @@ impl Scanning for VMScanning { fn scan_vm_specific_roots( _tls: VMWorkerThread, - mut factory: impl RootsWorkFactory, + mut factory: impl RootsWorkFactory, ) { - use crate::edges::RootsWorkClosure; + use crate::slots::RootsWorkClosure; let mut roots_closure = RootsWorkClosure::from_roots_work_factory(&mut factory); unsafe { ((*UPCALLS).scan_vm_specific_roots)(&mut roots_closure as _); } } - fn scan_object>( + fn scan_object>( _tls: VMWorkerThread, object: ObjectReference, - edge_visitor: &mut EV, + slot_visitor: &mut SV, ) { - process_object(object, edge_visitor); + process_object(object, slot_visitor); } fn notify_initial_thread_scan_complete(_partial_scan: bool, _tls: VMWorkerThread) { let sweep_vm_specific_work = SweepVMSpecific::new(); @@ -200,7 +205,7 @@ impl Scanning for VMScanning { } } -pub fn process_object>(object: ObjectReference, closure: &mut EV) { +pub fn process_object>(object: ObjectReference, closure: &mut EV) { let addr = object.to_raw_address(); unsafe { crate::julia_scanning::scan_julia_object(addr, closure); diff --git a/mmtk/src/edges.rs b/mmtk/src/slots.rs similarity index 80% rename from mmtk/src/edges.rs rename to mmtk/src/slots.rs index 6f7d42af..1bb97d61 100644 --- a/mmtk/src/edges.rs +++ b/mmtk/src/slots.rs @@ -2,37 +2,37 @@ use atomic::Atomic; use mmtk::{ util::{Address, ObjectReference}, vm::{ - edge_shape::{Edge, SimpleEdge}, + slot::{SimpleSlot, Slot}, RootsWorkFactory, }, }; -/// If a VM supports multiple kinds of edges, we can use tagged union to represent all of them. +/// If a VM supports multiple kinds of slots, we can use tagged union to represent all of them. #[derive(Clone, Copy, PartialEq, Eq, Hash)] -pub enum JuliaVMEdge { - Simple(SimpleEdge), - Offset(OffsetEdge), +pub enum JuliaVMSlot { + Simple(SimpleSlot), + Offset(OffsetSlot), } -unsafe impl Send for JuliaVMEdge {} +unsafe impl Send for JuliaVMSlot {} -impl Edge for JuliaVMEdge { - fn load(&self) -> ObjectReference { +impl Slot for JuliaVMSlot { + fn load(&self) -> Option { match self { - JuliaVMEdge::Simple(e) => e.load(), - JuliaVMEdge::Offset(e) => e.load(), + JuliaVMSlot::Simple(e) => e.load(), + JuliaVMSlot::Offset(e) => e.load(), } } fn store(&self, object: ObjectReference) { match self { - JuliaVMEdge::Simple(e) => e.store(object), - JuliaVMEdge::Offset(e) => e.store(object), + JuliaVMSlot::Simple(e) => e.store(object), + JuliaVMSlot::Offset(e) => e.store(object), } } } -impl std::fmt::Debug for JuliaVMEdge { +impl std::fmt::Debug for JuliaVMSlot { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Simple(e) => write!(f, "{}", e.as_address()), @@ -42,14 +42,14 @@ impl std::fmt::Debug for JuliaVMEdge { } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -pub struct OffsetEdge { +pub struct OffsetSlot { slot_addr: *mut Atomic
, offset: usize, } -unsafe impl Send for OffsetEdge {} +unsafe impl Send for OffsetSlot {} -impl OffsetEdge { +impl OffsetSlot { pub fn new_no_offset(address: Address) -> Self { Self { slot_addr: address.to_mut_ptr(), @@ -73,10 +73,11 @@ impl OffsetEdge { } } -impl Edge for OffsetEdge { - fn load(&self) -> ObjectReference { +impl Slot for OffsetSlot { + fn load(&self) -> Option { let middle = unsafe { (*self.slot_addr).load(atomic::Ordering::Relaxed) }; let begin = middle - self.offset; + debug_assert!(!begin.is_zero()); ObjectReference::from_raw_address(begin) } @@ -94,12 +95,12 @@ pub struct JuliaMemorySlice { pub count: usize, } -impl mmtk::vm::edge_shape::MemorySlice for JuliaMemorySlice { - type Edge = JuliaVMEdge; - type EdgeIterator = JuliaMemorySliceEdgeIterator; +impl mmtk::vm::slot::MemorySlice for JuliaMemorySlice { + type SlotType = JuliaVMSlot; + type SlotIterator = JuliaMemorySliceSlotIterator; - fn iter_edges(&self) -> Self::EdgeIterator { - JuliaMemorySliceEdgeIterator { + fn iter_slots(&self) -> Self::SlotIterator { + JuliaMemorySliceSlotIterator { cursor: self.start, limit: self.start.shift::
(self.count as isize), } @@ -155,21 +156,21 @@ impl mmtk::vm::edge_shape::MemorySlice for JuliaMemorySlice { } } -pub struct JuliaMemorySliceEdgeIterator { +pub struct JuliaMemorySliceSlotIterator { cursor: Address, limit: Address, } -impl Iterator for JuliaMemorySliceEdgeIterator { - type Item = JuliaVMEdge; +impl Iterator for JuliaMemorySliceSlotIterator { + type Item = JuliaVMSlot; - fn next(&mut self) -> Option { + fn next(&mut self) -> Option { if self.cursor >= self.limit { None } else { - let edge = self.cursor; + let slot = self.cursor; self.cursor = self.cursor.shift::(1); - Some(JuliaVMEdge::Simple(SimpleEdge::from_address(edge))) + Some(JuliaVMSlot::Simple(SimpleSlot::from_address(slot))) } } } @@ -201,7 +202,7 @@ impl RootsWorkBuffer { #[repr(C)] pub struct RootsWorkClosure { - pub report_edges_func: extern "C" fn( + pub report_slots_func: extern "C" fn( buf: *mut Address, size: usize, cap: usize, @@ -226,7 +227,7 @@ pub struct RootsWorkClosure { } impl RootsWorkClosure { - extern "C" fn report_simple_edges>( + extern "C" fn report_simple_slots>( buf: *mut Address, size: usize, cap: usize, @@ -236,10 +237,10 @@ impl RootsWorkClosure { if !buf.is_null() { let buf = unsafe { Vec::
::from_raw_parts(buf, size, cap) } .into_iter() - .map(|addr| JuliaVMEdge::Simple(SimpleEdge::from_address(addr))) + .map(|addr| JuliaVMSlot::Simple(SimpleSlot::from_address(addr))) .collect(); let factory: &mut F = unsafe { &mut *(factory_ptr as *mut F) }; - factory.create_process_edge_roots_work(buf); + factory.create_process_roots_work(buf); } if renew { @@ -249,7 +250,7 @@ impl RootsWorkClosure { } } - extern "C" fn report_nodes>( + extern "C" fn report_nodes>( buf: *mut ObjectReference, size: usize, cap: usize, @@ -269,7 +270,7 @@ impl RootsWorkClosure { } } - extern "C" fn report_tpinned_nodes>( + extern "C" fn report_tpinned_nodes>( buf: *mut ObjectReference, size: usize, cap: usize, @@ -289,9 +290,9 @@ impl RootsWorkClosure { } } - pub fn from_roots_work_factory>(factory: &mut F) -> Self { + pub fn from_roots_work_factory>(factory: &mut F) -> Self { RootsWorkClosure { - report_edges_func: Self::report_simple_edges::, + report_slots_func: Self::report_simple_slots::, report_nodes_func: Self::report_nodes::, report_tpinned_nodes_func: Self::report_tpinned_nodes::, factory_ptr: factory as *mut F as *mut libc::c_void,