Skip to content

Commit ebf6e74

Browse files
authored
No ProcessEdgesWork in API functions (#163)
* No ProcessEdgesWork in API functions Because of a change in mmtk-core, API functions no longer pass type parameters for the work packet type. - For stop_all_mutators, we call back to mmtk-core when a mutator is stopped. - For scan_xxx_roots, mmtk-openjdk no longer creates work packets for scanning roots, but simply report edges via callback so that the mmtk-core can create the right work packets. * Remove "ScopedDynamicXxxInvoker" Following upstream change, we use impl instead of dyn. When passing to native, pass function pointer + plain object pointer. Use macro to generate ScanXxxxxRoots work packet types.
1 parent de468c2 commit ebf6e74

File tree

10 files changed

+191
-315
lines changed

10 files changed

+191
-315
lines changed

mmtk/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ once_cell = "1.10.0"
2828
# - change branch
2929
# - change repo name
3030
# But other changes including adding/removing whitespaces in commented lines may break the CI.
31-
mmtk = { git = "https://github.com/mmtk/mmtk-core.git", rev = "571a857b75e648ca4c711d56fbf400d99173398f" }
31+
mmtk = { git = "https://github.com/mmtk/mmtk-core.git", rev = "f0fed5fc01438162115120c7551d4eb96e888bc2" }
3232
# Uncomment the following to build locally
3333
# mmtk = { path = "../repos/mmtk-core" }
3434

mmtk/src/collection.rs

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,29 @@
1-
use mmtk::scheduler::WorkBucketStage;
2-
use mmtk::scheduler::{ProcessEdgesWork, ScanStackRoot};
31
use mmtk::util::alloc::AllocationError;
42
use mmtk::util::opaque_pointer::*;
53
use mmtk::vm::{Collection, GCThreadContext, Scanning, VMBinding};
64
use mmtk::{Mutator, MutatorContext};
75

8-
use crate::OpenJDK;
9-
use crate::{SINGLETON, UPCALLS};
6+
use crate::UPCALLS;
7+
use crate::{MutatorClosure, OpenJDK};
108

119
pub struct VMCollection {}
1210

13-
extern "C" fn create_mutator_scan_work<E: ProcessEdgesWork<VM = OpenJDK>>(
14-
mutator: &'static mut Mutator<OpenJDK>,
15-
) {
16-
mmtk::memory_manager::add_work_packet(
17-
&SINGLETON,
18-
WorkBucketStage::Prepare,
19-
ScanStackRoot::<E>(mutator),
20-
);
11+
extern "C" fn report_mutator_stop<F>(mutator: *mut Mutator<OpenJDK>, callback: *mut F)
12+
where
13+
F: FnMut(&'static mut Mutator<OpenJDK>),
14+
{
15+
let callback: &mut F = unsafe { &mut *callback };
16+
callback(unsafe { &mut *mutator });
17+
}
18+
19+
fn to_mutator_closure<F>(callback: &mut F) -> MutatorClosure
20+
where
21+
F: FnMut(&'static mut Mutator<OpenJDK>),
22+
{
23+
MutatorClosure {
24+
func: report_mutator_stop::<F> as *const _,
25+
data: callback as *mut F as *mut libc::c_void,
26+
}
2127
}
2228

2329
const GC_THREAD_KIND_CONTROLLER: libc::c_int = 0;
@@ -28,16 +34,19 @@ impl Collection<OpenJDK> for VMCollection {
2834
/// the OpenJDK binding allows any MMTk GC thread to stop/start the world.
2935
const COORDINATOR_ONLY_STW: bool = false;
3036

31-
fn stop_all_mutators<E: ProcessEdgesWork<VM = OpenJDK>>(tls: VMWorkerThread) {
32-
let f = {
33-
if <OpenJDK as VMBinding>::VMScanning::SCAN_MUTATORS_IN_SAFEPOINT {
34-
0usize as _
35-
} else {
36-
create_mutator_scan_work::<E> as *const extern "C" fn(&'static mut Mutator<OpenJDK>)
37-
}
38-
};
37+
fn stop_all_mutators<F>(tls: VMWorkerThread, mut mutator_visitor: F)
38+
where
39+
F: FnMut(&'static mut Mutator<OpenJDK>),
40+
{
41+
let scan_mutators_in_safepoint =
42+
<OpenJDK as VMBinding>::VMScanning::SCAN_MUTATORS_IN_SAFEPOINT;
43+
3944
unsafe {
40-
((*UPCALLS).stop_all_mutators)(tls, f);
45+
((*UPCALLS).stop_all_mutators)(
46+
tls,
47+
scan_mutators_in_safepoint,
48+
to_mutator_closure(&mut mutator_visitor),
49+
);
4150
}
4251
}
4352

mmtk/src/gc_work.rs

Lines changed: 40 additions & 194 deletions
Original file line numberDiff line numberDiff line change
@@ -1,197 +1,43 @@
11
use super::{OpenJDK, UPCALLS};
2-
use crate::scanning::create_process_edges_work;
32
use mmtk::scheduler::*;
3+
use mmtk::vm::RootsWorkFactory;
44
use mmtk::MMTK;
5-
use std::marker::PhantomData;
6-
7-
pub struct ScanUniverseRoots<E: ProcessEdgesWork<VM = OpenJDK>>(PhantomData<E>);
8-
9-
impl<E: ProcessEdgesWork<VM = OpenJDK>> ScanUniverseRoots<E> {
10-
pub fn new() -> Self {
11-
Self(PhantomData)
12-
}
13-
}
14-
15-
impl<E: ProcessEdgesWork<VM = OpenJDK>> GCWork<OpenJDK> for ScanUniverseRoots<E> {
16-
fn do_work(&mut self, _worker: &mut GCWorker<OpenJDK>, _mmtk: &'static MMTK<OpenJDK>) {
17-
unsafe {
18-
((*UPCALLS).scan_universe_roots)(create_process_edges_work::<E> as _);
19-
}
20-
}
21-
}
22-
23-
pub struct ScanJNIHandlesRoots<E: ProcessEdgesWork<VM = OpenJDK>>(PhantomData<E>);
24-
25-
impl<E: ProcessEdgesWork<VM = OpenJDK>> ScanJNIHandlesRoots<E> {
26-
pub fn new() -> Self {
27-
Self(PhantomData)
28-
}
29-
}
30-
31-
impl<E: ProcessEdgesWork<VM = OpenJDK>> GCWork<OpenJDK> for ScanJNIHandlesRoots<E> {
32-
fn do_work(&mut self, _worker: &mut GCWorker<OpenJDK>, _mmtk: &'static MMTK<OpenJDK>) {
33-
unsafe {
34-
((*UPCALLS).scan_jni_handle_roots)(create_process_edges_work::<E> as _);
35-
}
36-
}
37-
}
38-
39-
pub struct ScanObjectSynchronizerRoots<E: ProcessEdgesWork<VM = OpenJDK>>(PhantomData<E>);
40-
41-
impl<E: ProcessEdgesWork<VM = OpenJDK>> ScanObjectSynchronizerRoots<E> {
42-
pub fn new() -> Self {
43-
Self(PhantomData)
44-
}
45-
}
46-
47-
impl<E: ProcessEdgesWork<VM = OpenJDK>> GCWork<OpenJDK> for ScanObjectSynchronizerRoots<E> {
48-
fn do_work(&mut self, _worker: &mut GCWorker<OpenJDK>, _mmtk: &'static MMTK<OpenJDK>) {
49-
unsafe {
50-
((*UPCALLS).scan_object_synchronizer_roots)(create_process_edges_work::<E> as _);
51-
}
52-
}
53-
}
54-
55-
pub struct ScanManagementRoots<E: ProcessEdgesWork<VM = OpenJDK>>(PhantomData<E>);
56-
57-
impl<E: ProcessEdgesWork<VM = OpenJDK>> ScanManagementRoots<E> {
58-
pub fn new() -> Self {
59-
Self(PhantomData)
60-
}
61-
}
62-
63-
impl<E: ProcessEdgesWork<VM = OpenJDK>> GCWork<OpenJDK> for ScanManagementRoots<E> {
64-
fn do_work(&mut self, _worker: &mut GCWorker<OpenJDK>, _mmtk: &'static MMTK<OpenJDK>) {
65-
unsafe {
66-
((*UPCALLS).scan_management_roots)(create_process_edges_work::<E> as _);
67-
}
68-
}
69-
}
70-
71-
pub struct ScanJvmtiExportRoots<E: ProcessEdgesWork<VM = OpenJDK>>(PhantomData<E>);
72-
73-
impl<E: ProcessEdgesWork<VM = OpenJDK>> ScanJvmtiExportRoots<E> {
74-
pub fn new() -> Self {
75-
Self(PhantomData)
76-
}
77-
}
78-
79-
impl<E: ProcessEdgesWork<VM = OpenJDK>> GCWork<OpenJDK> for ScanJvmtiExportRoots<E> {
80-
fn do_work(&mut self, _worker: &mut GCWorker<OpenJDK>, _mmtk: &'static MMTK<OpenJDK>) {
81-
unsafe {
82-
((*UPCALLS).scan_jvmti_export_roots)(create_process_edges_work::<E> as _);
83-
}
84-
}
85-
}
86-
87-
pub struct ScanAOTLoaderRoots<E: ProcessEdgesWork<VM = OpenJDK>>(PhantomData<E>);
88-
89-
impl<E: ProcessEdgesWork<VM = OpenJDK>> ScanAOTLoaderRoots<E> {
90-
pub fn new() -> Self {
91-
Self(PhantomData)
92-
}
93-
}
94-
95-
impl<E: ProcessEdgesWork<VM = OpenJDK>> GCWork<OpenJDK> for ScanAOTLoaderRoots<E> {
96-
fn do_work(&mut self, _worker: &mut GCWorker<OpenJDK>, _mmtk: &'static MMTK<OpenJDK>) {
97-
unsafe {
98-
((*UPCALLS).scan_aot_loader_roots)(create_process_edges_work::<E> as _);
99-
}
100-
}
101-
}
102-
103-
pub struct ScanSystemDictionaryRoots<E: ProcessEdgesWork<VM = OpenJDK>>(PhantomData<E>);
104-
105-
impl<E: ProcessEdgesWork<VM = OpenJDK>> ScanSystemDictionaryRoots<E> {
106-
pub fn new() -> Self {
107-
Self(PhantomData)
108-
}
109-
}
110-
111-
impl<E: ProcessEdgesWork<VM = OpenJDK>> GCWork<OpenJDK> for ScanSystemDictionaryRoots<E> {
112-
fn do_work(&mut self, _worker: &mut GCWorker<OpenJDK>, _mmtk: &'static MMTK<OpenJDK>) {
113-
unsafe {
114-
((*UPCALLS).scan_system_dictionary_roots)(create_process_edges_work::<E> as _);
115-
}
116-
}
117-
}
118-
119-
pub struct ScanCodeCacheRoots<E: ProcessEdgesWork<VM = OpenJDK>>(PhantomData<E>);
120-
121-
impl<E: ProcessEdgesWork<VM = OpenJDK>> ScanCodeCacheRoots<E> {
122-
pub fn new() -> Self {
123-
Self(PhantomData)
124-
}
125-
}
126-
127-
impl<E: ProcessEdgesWork<VM = OpenJDK>> GCWork<OpenJDK> for ScanCodeCacheRoots<E> {
128-
fn do_work(&mut self, _worker: &mut GCWorker<OpenJDK>, _mmtk: &'static MMTK<OpenJDK>) {
129-
unsafe {
130-
((*UPCALLS).scan_code_cache_roots)(create_process_edges_work::<E> as _);
131-
}
132-
}
133-
}
134-
135-
pub struct ScanStringTableRoots<E: ProcessEdgesWork<VM = OpenJDK>>(PhantomData<E>);
136-
137-
impl<E: ProcessEdgesWork<VM = OpenJDK>> ScanStringTableRoots<E> {
138-
pub fn new() -> Self {
139-
Self(PhantomData)
140-
}
141-
}
142-
143-
impl<E: ProcessEdgesWork<VM = OpenJDK>> GCWork<OpenJDK> for ScanStringTableRoots<E> {
144-
fn do_work(&mut self, _worker: &mut GCWorker<OpenJDK>, _mmtk: &'static MMTK<OpenJDK>) {
145-
unsafe {
146-
((*UPCALLS).scan_string_table_roots)(create_process_edges_work::<E> as _);
147-
}
148-
}
149-
}
150-
151-
pub struct ScanClassLoaderDataGraphRoots<E: ProcessEdgesWork<VM = OpenJDK>>(PhantomData<E>);
152-
153-
impl<E: ProcessEdgesWork<VM = OpenJDK>> ScanClassLoaderDataGraphRoots<E> {
154-
pub fn new() -> Self {
155-
Self(PhantomData)
156-
}
157-
}
158-
159-
impl<E: ProcessEdgesWork<VM = OpenJDK>> GCWork<OpenJDK> for ScanClassLoaderDataGraphRoots<E> {
160-
fn do_work(&mut self, _worker: &mut GCWorker<OpenJDK>, _mmtk: &'static MMTK<OpenJDK>) {
161-
unsafe {
162-
((*UPCALLS).scan_class_loader_data_graph_roots)(create_process_edges_work::<E> as _);
163-
}
164-
}
165-
}
166-
167-
pub struct ScanWeakProcessorRoots<E: ProcessEdgesWork<VM = OpenJDK>>(PhantomData<E>);
168-
169-
impl<E: ProcessEdgesWork<VM = OpenJDK>> ScanWeakProcessorRoots<E> {
170-
pub fn new() -> Self {
171-
Self(PhantomData)
172-
}
173-
}
174-
175-
impl<E: ProcessEdgesWork<VM = OpenJDK>> GCWork<OpenJDK> for ScanWeakProcessorRoots<E> {
176-
fn do_work(&mut self, _worker: &mut GCWorker<OpenJDK>, _mmtk: &'static MMTK<OpenJDK>) {
177-
unsafe {
178-
((*UPCALLS).scan_weak_processor_roots)(create_process_edges_work::<E> as _);
179-
}
180-
}
181-
}
182-
183-
pub struct ScanVMThreadRoots<E: ProcessEdgesWork<VM = OpenJDK>>(PhantomData<E>);
184-
185-
impl<E: ProcessEdgesWork<VM = OpenJDK>> ScanVMThreadRoots<E> {
186-
pub fn new() -> Self {
187-
Self(PhantomData)
188-
}
189-
}
190-
191-
impl<E: ProcessEdgesWork<VM = OpenJDK>> GCWork<OpenJDK> for ScanVMThreadRoots<E> {
192-
fn do_work(&mut self, _worker: &mut GCWorker<OpenJDK>, _mmtk: &'static MMTK<OpenJDK>) {
193-
unsafe {
194-
((*UPCALLS).scan_vm_thread_roots)(create_process_edges_work::<E> as _);
195-
}
196-
}
197-
}
5+
use scanning::to_edges_closure;
6+
7+
macro_rules! scan_roots_work {
8+
($struct_name: ident, $func_name: ident) => {
9+
pub struct $struct_name<F: RootsWorkFactory> {
10+
factory: F,
11+
}
12+
13+
impl<F: RootsWorkFactory> $struct_name<F> {
14+
pub fn new(factory: F) -> Self {
15+
Self { factory }
16+
}
17+
}
18+
19+
impl<F: RootsWorkFactory> GCWork<OpenJDK> for $struct_name<F> {
20+
fn do_work(&mut self, _worker: &mut GCWorker<OpenJDK>, _mmtk: &'static MMTK<OpenJDK>) {
21+
unsafe {
22+
((*UPCALLS).$func_name)(to_edges_closure(&mut self.factory));
23+
}
24+
}
25+
}
26+
};
27+
}
28+
29+
scan_roots_work!(ScanUniverseRoots, scan_universe_roots);
30+
scan_roots_work!(ScanJNIHandlesRoots, scan_jni_handle_roots);
31+
scan_roots_work!(ScanObjectSynchronizerRoots, scan_object_synchronizer_roots);
32+
scan_roots_work!(ScanManagementRoots, scan_management_roots);
33+
scan_roots_work!(ScanJvmtiExportRoots, scan_jvmti_export_roots);
34+
scan_roots_work!(ScanAOTLoaderRoots, scan_aot_loader_roots);
35+
scan_roots_work!(ScanSystemDictionaryRoots, scan_system_dictionary_roots);
36+
scan_roots_work!(ScanCodeCacheRoots, scan_code_cache_roots);
37+
scan_roots_work!(ScanStringTableRoots, scan_string_table_roots);
38+
scan_roots_work!(
39+
ScanClassLoaderDataGraphRoots,
40+
scan_class_loader_data_graph_roots
41+
);
42+
scan_roots_work!(ScanWeakProcessorRoots, scan_weak_processor_roots);
43+
scan_roots_work!(ScanVMThreadRoots, scan_vm_thread_roots);

mmtk/src/lib.rs

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,27 @@ pub struct NewBuffer {
3030
pub capacity: usize,
3131
}
3232

33-
type ProcessEdgesFn = *const extern "C" fn(buf: *mut Address, size: usize, cap: usize) -> NewBuffer;
33+
/// A closure for reporting mutators. The C++ code should pass `data` back as the last argument.
34+
#[repr(C)]
35+
pub struct MutatorClosure {
36+
pub func: *const extern "C" fn(mutator: *mut Mutator<OpenJDK>, data: *mut libc::c_void),
37+
pub data: *mut libc::c_void,
38+
}
39+
40+
/// A closure for reporting root edges. The C++ code should pass `data` back as the last argument.
41+
#[repr(C)]
42+
pub struct EdgesClosure {
43+
pub func:
44+
*const extern "C" fn(buf: *mut Address, size: usize, cap: usize, data: *const libc::c_void),
45+
pub data: *const libc::c_void,
46+
}
3447

3548
#[repr(C)]
3649
pub struct OpenJDK_Upcalls {
3750
pub stop_all_mutators: extern "C" fn(
3851
tls: VMWorkerThread,
39-
create_stack_scan_work: *const extern "C" fn(&'static mut Mutator<OpenJDK>),
52+
scan_mutators_in_safepoint: bool,
53+
closure: MutatorClosure,
4054
),
4155
pub resume_mutators: extern "C" fn(tls: VMWorkerThread),
4256
pub spawn_gc_thread: extern "C" fn(tls: VMThread, kind: libc::c_int, ctx: *mut libc::c_void),
@@ -60,20 +74,20 @@ pub struct OpenJDK_Upcalls {
6074
pub referent_offset: extern "C" fn() -> i32,
6175
pub discovered_offset: extern "C" fn() -> i32,
6276
pub dump_object_string: extern "C" fn(object: ObjectReference) -> *const c_char,
63-
pub scan_thread_roots: extern "C" fn(process_edges: ProcessEdgesFn),
64-
pub scan_thread_root: extern "C" fn(process_edges: ProcessEdgesFn, tls: VMMutatorThread),
65-
pub scan_universe_roots: extern "C" fn(process_edges: ProcessEdgesFn),
66-
pub scan_jni_handle_roots: extern "C" fn(process_edges: ProcessEdgesFn),
67-
pub scan_object_synchronizer_roots: extern "C" fn(process_edges: ProcessEdgesFn),
68-
pub scan_management_roots: extern "C" fn(process_edges: ProcessEdgesFn),
69-
pub scan_jvmti_export_roots: extern "C" fn(process_edges: ProcessEdgesFn),
70-
pub scan_aot_loader_roots: extern "C" fn(process_edges: ProcessEdgesFn),
71-
pub scan_system_dictionary_roots: extern "C" fn(process_edges: ProcessEdgesFn),
72-
pub scan_code_cache_roots: extern "C" fn(process_edges: ProcessEdgesFn),
73-
pub scan_string_table_roots: extern "C" fn(process_edges: ProcessEdgesFn),
74-
pub scan_class_loader_data_graph_roots: extern "C" fn(process_edges: ProcessEdgesFn),
75-
pub scan_weak_processor_roots: extern "C" fn(process_edges: ProcessEdgesFn),
76-
pub scan_vm_thread_roots: extern "C" fn(process_edges: ProcessEdgesFn),
77+
pub scan_thread_roots: extern "C" fn(closure: EdgesClosure),
78+
pub scan_thread_root: extern "C" fn(closure: EdgesClosure, tls: VMMutatorThread),
79+
pub scan_universe_roots: extern "C" fn(closure: EdgesClosure),
80+
pub scan_jni_handle_roots: extern "C" fn(closure: EdgesClosure),
81+
pub scan_object_synchronizer_roots: extern "C" fn(closure: EdgesClosure),
82+
pub scan_management_roots: extern "C" fn(closure: EdgesClosure),
83+
pub scan_jvmti_export_roots: extern "C" fn(closure: EdgesClosure),
84+
pub scan_aot_loader_roots: extern "C" fn(closure: EdgesClosure),
85+
pub scan_system_dictionary_roots: extern "C" fn(closure: EdgesClosure),
86+
pub scan_code_cache_roots: extern "C" fn(closure: EdgesClosure),
87+
pub scan_string_table_roots: extern "C" fn(closure: EdgesClosure),
88+
pub scan_class_loader_data_graph_roots: extern "C" fn(closure: EdgesClosure),
89+
pub scan_weak_processor_roots: extern "C" fn(closure: EdgesClosure),
90+
pub scan_vm_thread_roots: extern "C" fn(closure: EdgesClosure),
7791
pub number_of_mutators: extern "C" fn() -> usize,
7892
pub schedule_finalizer: extern "C" fn(),
7993
pub prepare_for_roots_re_scanning: extern "C" fn(),

0 commit comments

Comments
 (0)