Skip to content

Commit 12c3664

Browse files
committed
Optimization: Zero-copy work creation
1 parent 59868a3 commit 12c3664

File tree

7 files changed

+96
-57
lines changed

7 files changed

+96
-57
lines changed

mmtk/src/api.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ use crate::UPCALLS;
1717
use crate::OpenJDK_Upcalls;
1818
use crate::SINGLETON;
1919

20+
#[no_mangle]
21+
pub extern "C" fn release_buffer(ptr: *mut Address, length: usize, capacity: usize) {
22+
let _vec = unsafe { Vec::<Address>::from_raw_parts(ptr, length, capacity) };
23+
}
24+
2025
#[no_mangle]
2126
pub extern "C" fn openjdk_gc_init(calls: *const OpenJDK_Upcalls, heap_size: usize) {
2227
unsafe { UPCALLS = calls };

mmtk/src/lib.rs

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![feature(specialization)]
22
#![feature(const_fn)]
33
#![feature(box_syntax)]
4+
#![feature(vec_into_raw_parts)]
45

56
extern crate mmtk;
67
extern crate libc;
@@ -26,6 +27,14 @@ mod abi;
2627
mod object_scanning;
2728
mod gc_works;
2829

30+
#[repr(C)]
31+
pub struct NewBuffer {
32+
pub ptr: *mut Address,
33+
pub capacity: usize
34+
}
35+
36+
type ProcessEdgesFn = *const extern "C" fn(buf: *mut Address, size: usize, cap: usize) -> NewBuffer;
37+
2938
#[repr(C)]
3039
pub struct OpenJDK_Upcalls {
3140
pub stop_all_mutators: extern "C" fn(tls: OpaquePointer, create_stack_scan_work: *const extern "C" fn(&'static mut Mutator<SelectedPlan<OpenJDK>>)),
@@ -51,20 +60,20 @@ pub struct OpenJDK_Upcalls {
5160
pub referent_offset: extern "C" fn() -> i32,
5261
pub discovered_offset: extern "C" fn() -> i32,
5362
pub dump_object_string: extern "C" fn(object: ObjectReference) -> *const c_char,
54-
pub scan_thread_roots: extern "C" fn(process_edges: *const extern "C" fn(buf: *const Address, size: usize), tls: OpaquePointer),
55-
pub scan_thread_root: extern "C" fn(process_edges: *const extern "C" fn(buf: *const Address, size: usize), tls: OpaquePointer),
56-
pub scan_universe_roots: extern "C" fn(process_edges: *const extern "C" fn (buf: *const Address, size: usize)),
57-
pub scan_jni_handle_roots: extern "C" fn(process_edges: *const extern "C" fn (buf: *const Address, size: usize)),
58-
pub scan_object_synchronizer_roots: extern "C" fn(process_edges: *const extern "C" fn (buf: *const Address, size: usize)),
59-
pub scan_management_roots: extern "C" fn(process_edges: *const extern "C" fn (buf: *const Address, size: usize)),
60-
pub scan_jvmti_export_roots: extern "C" fn(process_edges: *const extern "C" fn (buf: *const Address, size: usize)),
61-
pub scan_aot_loader_roots: extern "C" fn(process_edges: *const extern "C" fn (buf: *const Address, size: usize)),
62-
pub scan_system_dictionary_roots: extern "C" fn(process_edges: *const extern "C" fn (buf: *const Address, size: usize)),
63-
pub scan_code_cache_roots: extern "C" fn(process_edges: *const extern "C" fn (buf: *const Address, size: usize)),
64-
pub scan_string_table_roots: extern "C" fn(process_edges: *const extern "C" fn (buf: *const Address, size: usize)),
65-
pub scan_class_loader_data_graph_roots: extern "C" fn(process_edges: *const extern "C" fn (buf: *const Address, size: usize)),
66-
pub scan_weak_processor_roots: extern "C" fn(process_edges: *const extern "C" fn (buf: *const Address, size: usize)),
67-
pub scan_vm_thread_roots: extern "C" fn(process_edges: *const extern "C" fn (buf: *const Address, size: usize)),
63+
pub scan_thread_roots: extern "C" fn(process_edges: ProcessEdgesFn, tls: OpaquePointer),
64+
pub scan_thread_root: extern "C" fn(process_edges: ProcessEdgesFn, tls: OpaquePointer),
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),
6877
pub number_of_mutators: extern "C" fn() -> usize,
6978
}
7079

mmtk/src/object_model.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ impl ObjectModel<OpenJDK> for VMObjectModel {
2020
&*(o.to_address() + Self::GC_BYTE_OFFSET / 8).to_ptr::<AtomicU8>()
2121
}
2222
}
23+
#[inline]
2324
fn copy(from: ObjectReference, allocator: Allocator, copy_context: &mut impl CopyContext) -> ObjectReference {
2425
let bytes = unsafe { ((*UPCALLS).get_object_size)(from) };
2526
let dst = copy_context.alloc_copy(from, bytes, ::std::mem::size_of::<usize>(), 0, allocator);

mmtk/src/scanning.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use mmtk::util::{Address, ObjectReference, SynchronizedCounter};
55
use mmtk::util::OpaquePointer;
66
use mmtk::scheduler::gc_works::ProcessEdgesWork;
77
use crate::OpenJDK;
8-
use super::{UPCALLS, SINGLETON};
8+
use super::{UPCALLS, SINGLETON, NewBuffer};
99
use std::mem;
1010
use super::gc_works::*;
1111
use mmtk::MutatorContext;
@@ -15,12 +15,15 @@ static COUNTER: SynchronizedCounter = SynchronizedCounter::new(0);
1515

1616
pub struct VMScanning {}
1717

18-
pub extern fn create_process_edges_work<W: ProcessEdgesWork<VM=OpenJDK>>(ptr: *const Address, len: usize) {
19-
let mut buf = Vec::with_capacity(len);
20-
for i in 0..len {
21-
buf.push(unsafe { *ptr.add(i) });
18+
pub extern fn create_process_edges_work<W: ProcessEdgesWork<VM=OpenJDK>>(ptr: *mut Address, length: usize, capacity: usize) -> NewBuffer {
19+
if !ptr.is_null() {
20+
let mut buf = unsafe { Vec::<Address>::from_raw_parts(ptr, length, capacity) };
21+
SINGLETON.scheduler.closure_stage.add(W::new(buf, false));
22+
}
23+
let (ptr, _, capacity) = Vec::with_capacity(W::CAPACITY).into_raw_parts();
24+
NewBuffer {
25+
ptr, capacity
2226
}
23-
SINGLETON.scheduler.closure_stage.add(W::new(buf, false));
2427
}
2528

2629
impl Scanning<OpenJDK> for VMScanning {

openjdk/mmtk.h

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ extern void post_alloc(MMTk_Mutator mutator, void* refer, void* type_refer,
4747
extern void record_modified_node(MMTk_Mutator mutator, void* obj);
4848
extern void record_modified_edge(MMTk_Mutator mutator, void* slot);
4949

50+
extern void release_buffer(void** buffer, size_t len, size_t cap);
51+
5052
extern bool is_mapped_object(void* ref);
5153
extern bool is_mapped_address(void* addr);
5254
extern void modify_check(void* ref);
@@ -80,6 +82,13 @@ extern void start_worker(void *tls, void* worker);
8082
extern size_t free_bytes();
8183
extern size_t total_bytes();
8284

85+
typedef struct {
86+
void** buf;
87+
size_t cap;
88+
} NewBuffer;
89+
90+
typedef NewBuffer (*ProcessEdgesFn)(void** buf, size_t len, size_t cap);
91+
8392
/**
8493
* OpenJDK-specific
8594
*/
@@ -107,20 +116,20 @@ typedef struct {
107116
int (*referent_offset) ();
108117
int (*discovered_offset) ();
109118
char* (*dump_object_string) (void* object);
110-
void (*scan_thread_roots)(void (*process_edges)(void** buf, size_t len), void* tls);
111-
void (*scan_thread_root)(void (*process_edges)(void** buf, size_t len), void* tls);
112-
void (*scan_universe_roots) (void (*process_edges)(void** buf, size_t len));
113-
void (*scan_jni_handle_roots) (void (*process_edges)(void** buf, size_t len));
114-
void (*scan_object_synchronizer_roots) (void (*process_edges)(void** buf, size_t len));
115-
void (*scan_management_roots) (void (*process_edges)(void** buf, size_t len));
116-
void (*scan_jvmti_export_roots) (void (*process_edges)(void** buf, size_t len));
117-
void (*scan_aot_loader_roots) (void (*process_edges)(void** buf, size_t len));
118-
void (*scan_system_dictionary_roots) (void (*process_edges)(void** buf, size_t len));
119-
void (*scan_code_cache_roots) (void (*process_edges)(void** buf, size_t len));
120-
void (*scan_string_table_roots) (void (*process_edges)(void** buf, size_t len));
121-
void (*scan_class_loader_data_graph_roots) (void (*process_edges)(void** buf, size_t len));
122-
void (*scan_weak_processor_roots) (void (*process_edges)(void** buf, size_t len));
123-
void (*scan_vm_thread_roots) (void (*process_edges)(void** buf, size_t len));
119+
void (*scan_thread_roots)(ProcessEdgesFn process_edges, void* tls);
120+
void (*scan_thread_root)(ProcessEdgesFn process_edges, void* tls);
121+
void (*scan_universe_roots) (ProcessEdgesFn process_edges);
122+
void (*scan_jni_handle_roots) (ProcessEdgesFn process_edges);
123+
void (*scan_object_synchronizer_roots) (ProcessEdgesFn process_edges);
124+
void (*scan_management_roots) (ProcessEdgesFn process_edges);
125+
void (*scan_jvmti_export_roots) (ProcessEdgesFn process_edges);
126+
void (*scan_aot_loader_roots) (ProcessEdgesFn process_edges);
127+
void (*scan_system_dictionary_roots) (ProcessEdgesFn process_edges);
128+
void (*scan_code_cache_roots) (ProcessEdgesFn process_edges);
129+
void (*scan_string_table_roots) (ProcessEdgesFn process_edges);
130+
void (*scan_class_loader_data_graph_roots) (ProcessEdgesFn process_edges);
131+
void (*scan_weak_processor_roots) (ProcessEdgesFn process_edges);
132+
void (*scan_vm_thread_roots) (ProcessEdgesFn process_edges);
124133
size_t (*number_of_mutators)();
125134
} OpenJDK_Upcalls;
126135

openjdk/mmtkRootsClosure.hpp

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,9 @@ class MMTkRootsClosure : public OopClosure {
4545
};
4646

4747
class MMTkRootsClosure2 : public OopClosure {
48-
void (*_process_edges)(void** buf, size_t len);
49-
void* _buffer[ROOTS_BUFFER_SIZE];
48+
ProcessEdgesFn _process_edges;
49+
void** _buffer;
50+
size_t _cap;
5051
size_t _cursor;
5152

5253
template <class T>
@@ -58,21 +59,32 @@ class MMTkRootsClosure2 : public OopClosure {
5859
// RawAccess<>::oop_store(p, fwd);
5960
// }
6061
_buffer[_cursor++] = (void*) p;
61-
if (_cursor >= ROOTS_BUFFER_SIZE) {
62+
if (_cursor >= _cap) {
6263
flush();
6364
}
6465
}
6566

66-
NOINLINE void flush() {
67-
_process_edges(_buffer, _cursor);
68-
_cursor = 0;
67+
void flush() {
68+
if (_cursor > 0) {
69+
NewBuffer buf = _process_edges(_buffer, _cursor, _cap);
70+
_buffer = buf.buf;
71+
_cap = buf.cap;
72+
_cursor = 0;
73+
}
6974
}
7075

7176
public:
72-
MMTkRootsClosure2(void (*process_edges)(void** buf, size_t len)): _process_edges(process_edges), _cursor(0) {}
77+
MMTkRootsClosure2(ProcessEdgesFn process_edges): _process_edges(process_edges), _cursor(0) {
78+
NewBuffer buf = process_edges(NULL, 0, 0);
79+
_buffer = buf.buf;
80+
_cap = buf.cap;
81+
}
7382

7483
~MMTkRootsClosure2() {
7584
if (_cursor > 0) flush();
85+
if (_buffer != NULL) {
86+
release_buffer(_buffer, _cursor, _cap);
87+
}
7688
}
7789

7890
virtual void do_oop(oop* p) { do_oop_work(p); }

openjdk/mmtkUpcalls.cpp

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -155,25 +155,25 @@ static void mmtk_compute_thread_roots(void* trace, void* tls) {
155155
MMTkHeap::heap()->scan_thread_roots(cl);
156156
}
157157

158-
static void mmtk_scan_thread_roots(void (*process_edges)(void** buf, size_t len), void* tls) {
158+
static void mmtk_scan_thread_roots(ProcessEdgesFn process_edges, void* tls) {
159159
MMTkRootsClosure2 cl(process_edges);
160160
MMTkHeap::heap()->scan_thread_roots(cl);
161161
}
162162

163-
static void mmtk_scan_thread_root(void (*process_edges)(void** buf, size_t len), void* tls) {
163+
static void mmtk_scan_thread_root(ProcessEdgesFn process_edges, void* tls) {
164164
ResourceMark rm;
165165
JavaThread* thread = (JavaThread*) tls;
166166
MMTkRootsClosure2 cl(process_edges);
167167
CodeBlobToOopClosure cb_cl(&cl, false);
168168
thread->oops_do(&cl, &cb_cl);
169169
}
170170

171-
static void mmtk_scan_static_roots(void (*process_edges)(void** buf, size_t len), void* tls) {
171+
static void mmtk_scan_static_roots(ProcessEdgesFn process_edges, void* tls) {
172172
MMTkRootsClosure2 cl(process_edges);
173173
MMTkHeap::heap()->scan_static_roots(cl);
174174
}
175175

176-
static void mmtk_scan_global_roots(void (*process_edges)(void** buf, size_t len), void* tls) {
176+
static void mmtk_scan_global_roots(ProcessEdgesFn process_edges, void* tls) {
177177
MMTkRootsClosure2 cl(process_edges);
178178
MMTkHeap::heap()->scan_global_roots(cl);
179179
}
@@ -258,18 +258,18 @@ static char* dump_object_string(void* object) {
258258
return o->print_value_string();
259259
}
260260

261-
static void mmtk_scan_universe_roots(void (*process_edges)(void** buf, size_t len)) { MMTkRootsClosure2 cl(process_edges); MMTkHeap::heap()->scan_universe_roots(cl); }
262-
static void mmtk_scan_jni_handle_roots(void (*process_edges)(void** buf, size_t len)) { MMTkRootsClosure2 cl(process_edges); MMTkHeap::heap()->scan_jni_handle_roots(cl); }
263-
static void mmtk_scan_object_synchronizer_roots(void (*process_edges)(void** buf, size_t len)) { MMTkRootsClosure2 cl(process_edges); MMTkHeap::heap()->scan_object_synchronizer_roots(cl); }
264-
static void mmtk_scan_management_roots(void (*process_edges)(void** buf, size_t len)) { MMTkRootsClosure2 cl(process_edges); MMTkHeap::heap()->scan_management_roots(cl); }
265-
static void mmtk_scan_jvmti_export_roots(void (*process_edges)(void** buf, size_t len)) { MMTkRootsClosure2 cl(process_edges); MMTkHeap::heap()->scan_jvmti_export_roots(cl); }
266-
static void mmtk_scan_aot_loader_roots(void (*process_edges)(void** buf, size_t len)) { MMTkRootsClosure2 cl(process_edges); MMTkHeap::heap()->scan_aot_loader_roots(cl); }
267-
static void mmtk_scan_system_dictionary_roots(void (*process_edges)(void** buf, size_t len)) { MMTkRootsClosure2 cl(process_edges); MMTkHeap::heap()->scan_system_dictionary_roots(cl); }
268-
static void mmtk_scan_code_cache_roots(void (*process_edges)(void** buf, size_t len)) { MMTkRootsClosure2 cl(process_edges); MMTkHeap::heap()->scan_code_cache_roots(cl); }
269-
static void mmtk_scan_string_table_roots(void (*process_edges)(void** buf, size_t len)) { MMTkRootsClosure2 cl(process_edges); MMTkHeap::heap()->scan_string_table_roots(cl); }
270-
static void mmtk_scan_class_loader_data_graph_roots(void (*process_edges)(void** buf, size_t len)) { MMTkRootsClosure2 cl(process_edges); MMTkHeap::heap()->scan_class_loader_data_graph_roots(cl); }
271-
static void mmtk_scan_weak_processor_roots(void (*process_edges)(void** buf, size_t len)) { MMTkRootsClosure2 cl(process_edges); MMTkHeap::heap()->scan_weak_processor_roots(cl); }
272-
static void mmtk_scan_vm_thread_roots(void (*process_edges)(void** buf, size_t len)) { MMTkRootsClosure2 cl(process_edges); MMTkHeap::heap()->scan_vm_thread_roots(cl); }
261+
static void mmtk_scan_universe_roots(ProcessEdgesFn process_edges) { MMTkRootsClosure2 cl(process_edges); MMTkHeap::heap()->scan_universe_roots(cl); }
262+
static void mmtk_scan_jni_handle_roots(ProcessEdgesFn process_edges) { MMTkRootsClosure2 cl(process_edges); MMTkHeap::heap()->scan_jni_handle_roots(cl); }
263+
static void mmtk_scan_object_synchronizer_roots(ProcessEdgesFn process_edges) { MMTkRootsClosure2 cl(process_edges); MMTkHeap::heap()->scan_object_synchronizer_roots(cl); }
264+
static void mmtk_scan_management_roots(ProcessEdgesFn process_edges) { MMTkRootsClosure2 cl(process_edges); MMTkHeap::heap()->scan_management_roots(cl); }
265+
static void mmtk_scan_jvmti_export_roots(ProcessEdgesFn process_edges) { MMTkRootsClosure2 cl(process_edges); MMTkHeap::heap()->scan_jvmti_export_roots(cl); }
266+
static void mmtk_scan_aot_loader_roots(ProcessEdgesFn process_edges) { MMTkRootsClosure2 cl(process_edges); MMTkHeap::heap()->scan_aot_loader_roots(cl); }
267+
static void mmtk_scan_system_dictionary_roots(ProcessEdgesFn process_edges) { MMTkRootsClosure2 cl(process_edges); MMTkHeap::heap()->scan_system_dictionary_roots(cl); }
268+
static void mmtk_scan_code_cache_roots(ProcessEdgesFn process_edges) { MMTkRootsClosure2 cl(process_edges); MMTkHeap::heap()->scan_code_cache_roots(cl); }
269+
static void mmtk_scan_string_table_roots(ProcessEdgesFn process_edges) { MMTkRootsClosure2 cl(process_edges); MMTkHeap::heap()->scan_string_table_roots(cl); }
270+
static void mmtk_scan_class_loader_data_graph_roots(ProcessEdgesFn process_edges) { MMTkRootsClosure2 cl(process_edges); MMTkHeap::heap()->scan_class_loader_data_graph_roots(cl); }
271+
static void mmtk_scan_weak_processor_roots(ProcessEdgesFn process_edges) { MMTkRootsClosure2 cl(process_edges); MMTkHeap::heap()->scan_weak_processor_roots(cl); }
272+
static void mmtk_scan_vm_thread_roots(ProcessEdgesFn process_edges) { MMTkRootsClosure2 cl(process_edges); MMTkHeap::heap()->scan_vm_thread_roots(cl); }
273273

274274
static size_t mmtk_number_of_mutators() {
275275
return Threads::number_of_threads();

0 commit comments

Comments
 (0)