diff --git a/mmtk/Cargo.lock b/mmtk/Cargo.lock index b95913e7..dd3fb1df 100644 --- a/mmtk/Cargo.lock +++ b/mmtk/Cargo.lock @@ -162,6 +162,17 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "delegate" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d358e0ec5c59a5e1603b933def447096886121660fc680dc1e64a0753981fe3c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "downcast-rs" version = "1.2.0" @@ -419,7 +430,7 @@ dependencies = [ [[package]] name = "mmtk" version = "0.18.0" -source = "git+https://github.com/mmtk/mmtk-core.git?rev=df146b7af6cf41cc7d6996e1ca538fd2b32950f5#df146b7af6cf41cc7d6996e1ca538fd2b32950f5" +source = "git+https://github.com/ArberSephirotheca/mmtk-core.git?rev=1bd9b39053f5596204c196746f50a2dd51128c7c#1bd9b39053f5596204c196746f50a2dd51128c7c" dependencies = [ "atomic", "atomic-traits", @@ -427,6 +438,7 @@ dependencies = [ "built 0.6.0", "cfg-if", "crossbeam", + "delegate", "downcast-rs", "enum-map", "env_logger", @@ -448,7 +460,7 @@ dependencies = [ [[package]] name = "mmtk-macros" version = "0.18.0" -source = "git+https://github.com/mmtk/mmtk-core.git?rev=df146b7af6cf41cc7d6996e1ca538fd2b32950f5#df146b7af6cf41cc7d6996e1ca538fd2b32950f5" +source = "git+https://github.com/ArberSephirotheca/mmtk-core.git?rev=1bd9b39053f5596204c196746f50a2dd51128c7c#1bd9b39053f5596204c196746f50a2dd51128c7c" dependencies = [ "proc-macro-error", "proc-macro2", diff --git a/mmtk/Cargo.toml b/mmtk/Cargo.toml index cae04d45..a0f3ae39 100644 --- a/mmtk/Cargo.toml +++ b/mmtk/Cargo.toml @@ -30,7 +30,7 @@ once_cell = "1.10.0" # - 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 = "df146b7af6cf41cc7d6996e1ca538fd2b32950f5" } +mmtk = { git = "https://github.com/ArberSephirotheca/mmtk-core.git", rev = "1bd9b39053f5596204c196746f50a2dd51128c7c" } # Uncomment the following to build locally # mmtk = { path = "../repos/mmtk-core" } diff --git a/mmtk/src/abi.rs b/mmtk/src/abi.rs index 0bd27a20..1986c1d3 100644 --- a/mmtk/src/abi.rs +++ b/mmtk/src/abi.rs @@ -404,6 +404,43 @@ pub fn validate_memory_layouts() { ^ mem::size_of::() ^ mem::size_of::() ^ mem::size_of::() + ^ mem::size_of::() }; assert_eq!(vm_checksum, binding_checksum); } + +// hotspot/share/runtime/threadSMR.hpp +#[repr(C)] +pub struct SafeThreadsListPtr { + _previous: *mut libc::c_void, + _thread: *mut libc::c_void, + _list: *mut libc::c_void, + _has_ref_count: bool, + _needs_release: bool, +} + +#[repr(C)] +pub struct ElapsedTimer { + _counter: i64, + _start_counter: i64, + _active: bool, +} + +#[repr(C)] +pub struct ThreadsListHandle { + // This is speculative: + // SafeThreadsListPtr is 32 bytes, and ElapsedTimer is 24 bytes. + // But ThreadsListHandle in C++ has a size of 64 bytes in debug builds, but 56 bytes in release builds. + // I am guessing the compiler includes a vtable pointer in debug builds, and optimize it away in release builds. + #[cfg(debug_assertions)] + vtable: *mut libc::c_void, + _list_ptr: SafeThreadsListPtr, + _timer: ElapsedTimer, +} + +#[repr(C)] +pub struct JavaThreadIteratorWithHandle { + vtable: *mut libc::c_void, + _tlh: ThreadsListHandle, + _index: u32, +} diff --git a/mmtk/src/active_plan.rs b/mmtk/src/active_plan.rs index 88d12958..55e43b28 100644 --- a/mmtk/src/active_plan.rs +++ b/mmtk/src/active_plan.rs @@ -1,3 +1,4 @@ +use crate::abi::JavaThreadIteratorWithHandle; use crate::OpenJDK; use crate::SINGLETON; use crate::UPCALLS; @@ -5,7 +6,40 @@ use mmtk::util::opaque_pointer::*; use mmtk::vm::ActivePlan; use mmtk::Mutator; use mmtk::Plan; -use std::sync::Mutex; +use std::marker::PhantomData; +use std::mem::MaybeUninit; + +struct OpenJDKMutatorIterator<'a> { + handle: MaybeUninit, + _p: PhantomData<&'a ()>, +} + +impl<'a> OpenJDKMutatorIterator<'a> { + fn new() -> Self { + let mut iter = Self { + handle: MaybeUninit::uninit(), + _p: PhantomData, + }; + // Create JavaThreadIteratorWithHandle + unsafe { + ((*UPCALLS).new_java_thread_iterator)(iter.handle.as_mut_ptr()); + } + iter + } +} + +impl<'a> Iterator for OpenJDKMutatorIterator<'a> { + type Item = &'a mut Mutator; + + fn next(&mut self) -> Option { + let next = unsafe { ((*UPCALLS).java_thread_iterator_next)(self.handle.as_mut_ptr()) }; + if next.is_null() { + None + } else { + Some(unsafe { &mut *next }) + } + } +} pub struct VMActivePlan {} @@ -25,29 +59,11 @@ impl ActivePlan for VMActivePlan { } } - fn reset_mutator_iterator() { - unsafe { - ((*UPCALLS).reset_mutator_iterator)(); - } - } - - fn get_next_mutator() -> Option<&'static mut Mutator> { - let _guard = MUTATOR_ITERATOR_LOCK.lock().unwrap(); - unsafe { - let m = ((*UPCALLS).get_next_mutator)(); - if m.is_null() { - None - } else { - Some(&mut *m) - } - } + fn mutators<'a>() -> Box> + 'a> { + Box::new(OpenJDKMutatorIterator::new()) } fn number_of_mutators() -> usize { unsafe { ((*UPCALLS).number_of_mutators)() } } } - -lazy_static! { - pub static ref MUTATOR_ITERATOR_LOCK: Mutex<()> = Mutex::new(()); -} diff --git a/mmtk/src/lib.rs b/mmtk/src/lib.rs index 7bca0753..5df19c06 100644 --- a/mmtk/src/lib.rs +++ b/mmtk/src/lib.rs @@ -62,8 +62,6 @@ pub struct OpenJDK_Upcalls { pub spawn_gc_thread: extern "C" fn(tls: VMThread, kind: libc::c_int, ctx: *mut libc::c_void), pub block_for_gc: extern "C" fn(), pub out_of_memory: extern "C" fn(tls: VMThread, err_kind: AllocationError), - pub get_next_mutator: extern "C" fn() -> *mut Mutator, - pub reset_mutator_iterator: extern "C" fn(), pub scan_object: extern "C" fn(trace: *mut c_void, object: ObjectReference, tls: OpaquePointer), pub dump_object: extern "C" fn(object: ObjectReference), pub get_object_size: extern "C" fn(object: ObjectReference) -> usize, @@ -95,6 +93,9 @@ pub struct OpenJDK_Upcalls { pub schedule_finalizer: extern "C" fn(), pub prepare_for_roots_re_scanning: extern "C" fn(), pub enqueue_references: extern "C" fn(objects: *const ObjectReference, len: usize), + pub new_java_thread_iterator: extern "C" fn(iter: *mut abi::JavaThreadIteratorWithHandle), + pub java_thread_iterator_next: + extern "C" fn(iter: *mut abi::JavaThreadIteratorWithHandle) -> *mut Mutator, } pub static mut UPCALLS: *const OpenJDK_Upcalls = null_mut(); diff --git a/openjdk/mmtk.h b/openjdk/mmtk.h index a2c3d9c9..29d9e666 100644 --- a/openjdk/mmtk.h +++ b/openjdk/mmtk.h @@ -149,8 +149,6 @@ typedef struct { void (*spawn_gc_thread) (void *tls, int kind, void *ctx); void (*block_for_gc) (); void (*out_of_memory) (void *tls, MMTkAllocationError err_kind); - void* (*get_next_mutator) (); - void (*reset_mutator_iterator) (); void (*scan_object) (void* trace, void* object, void* tls); void (*dump_object) (void* object); size_t (*get_object_size) (void* object); @@ -182,6 +180,8 @@ typedef struct { void (*schedule_finalizer)(); void (*prepare_for_roots_re_scanning)(); void (*enqueue_references)(void** objects, size_t len); + void (*new_java_thread_iterator)(void*); + void* (*java_thread_iterator_next)(void*); } OpenJDK_Upcalls; extern void openjdk_gc_init(OpenJDK_Upcalls *calls); diff --git a/openjdk/mmtkUpcalls.cpp b/openjdk/mmtkUpcalls.cpp index 3b983bcb..e7187c8a 100644 --- a/openjdk/mmtkUpcalls.cpp +++ b/openjdk/mmtkUpcalls.cpp @@ -190,27 +190,18 @@ struct MaybeUninit { char _data[sizeof(T)]; }; -static MaybeUninit jtiwh; -static bool mutator_iteration_start = true; +static void mmtk_new_java_thread_iterator(void* iter) { + *(JavaThreadIteratorWithHandle*)iter = JavaThreadIteratorWithHandle(); +} -static void* mmtk_get_next_mutator() { - if (mutator_iteration_start) { - *jtiwh = JavaThreadIteratorWithHandle(); - mutator_iteration_start = false; - } - JavaThread *thr = jtiwh->next(); +static void* mmtk_java_thread_iterator_next(void* iter) { + JavaThread *thr = ((JavaThreadIteratorWithHandle*)iter)->next(); if (thr == NULL) { - mutator_iteration_start = true; return NULL; } return (void*) &thr->third_party_heap_mutator; } -static void mmtk_reset_mutator_iterator() { - mutator_iteration_start = true; -} - - static void mmtk_scan_all_thread_roots(EdgesClosure closure) { MMTkRootsClosure2 cl(closure); MMTkHeap::heap()->scan_thread_roots(cl); @@ -276,7 +267,8 @@ static size_t compute_klass_mem_layout_checksum() { ^ sizeof(InstanceMirrorKlass) ^ sizeof(InstanceClassLoaderKlass) ^ sizeof(TypeArrayKlass) - ^ sizeof(ObjArrayKlass); + ^ sizeof(ObjArrayKlass) + ^ sizeof(JavaThreadIteratorWithHandle); } static int referent_offset() { @@ -347,8 +339,6 @@ OpenJDK_Upcalls mmtk_upcalls = { mmtk_spawn_gc_thread, mmtk_block_for_gc, mmtk_out_of_memory, - mmtk_get_next_mutator, - mmtk_reset_mutator_iterator, mmtk_scan_object, mmtk_dump_object, mmtk_get_object_size, @@ -379,5 +369,7 @@ OpenJDK_Upcalls mmtk_upcalls = { mmtk_number_of_mutators, mmtk_schedule_finalizer, mmtk_prepare_for_roots_re_scanning, - mmtk_enqueue_references + mmtk_enqueue_references, + mmtk_new_java_thread_iterator, + mmtk_java_thread_iterator_next, };