Skip to content

Commit 4be3884

Browse files
committed
WIP: Generational code cache roots
1 parent e8e415a commit 4be3884

File tree

9 files changed

+94
-48
lines changed

9 files changed

+94
-48
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,6 @@ target/
1515
/*.dylib
1616
/*.so
1717

18-
/repos/mmtk-core
18+
/repos/mmtk-core
19+
20+
__pycache__

mmtk/Cargo.lock

Lines changed: 7 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mmtk/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "mmtk_openjdk"
33
version = "0.27.0"
44
authors = [" <>"]
5-
rust-version = "1.71.1"
5+
rust-version = "1.73.0"
66
build = "build.rs"
77
edition = "2021"
88

@@ -27,14 +27,15 @@ once_cell = "1.10.0"
2727
atomic = "0.6.0"
2828
memoffset = "0.9.0"
2929
cfg-if = "1.0"
30+
probe = "0.5"
3031

3132
# Be very careful to commit any changes to the following mmtk dependency, as our CI scripts (including mmtk-core CI)
3233
# rely on matching these lines to modify them: e.g. comment out the git dependency and use the local path.
3334
# These changes are safe:
3435
# - change branch
3536
# - change repo name
3637
# But other changes including adding/removing whitespaces in commented lines may break the CI.
37-
mmtk = { git = "https://github.com/mmtk/mmtk-core.git", rev = "45cdf31055b1b6a629bdb8032adaa6dd5a8e32b9" }
38+
mmtk = { git = "https://github.com/mmtk/mmtk-core.git", rev = "a025c24104d8d456a865aa0122e6e0fb6d77e8f2" }
3839
# Uncomment the following to build locally
3940
# mmtk = { path = "../repos/mmtk-core" }
4041

mmtk/src/api.rs

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -497,42 +497,31 @@ thread_local! {
497497
/// Report a list of pointers in nmethod to mmtk.
498498
#[no_mangle]
499499
pub extern "C" fn mmtk_add_nmethod_oop(addr: Address) {
500-
NMETHOD_SLOTS.with(|x| x.borrow_mut().push(addr))
500+
NMETHOD_SLOTS.with_borrow_mut(|x| x.push(addr))
501501
}
502502

503503
/// Register a nmethod.
504504
/// The c++ part of the binding should scan the nmethod and report all the pointers to mmtk first, before calling this function.
505505
/// This function will transfer all the locally cached pointers of this nmethod to the global storage.
506506
#[no_mangle]
507507
pub extern "C" fn mmtk_register_nmethod(nm: Address) {
508-
let slots = NMETHOD_SLOTS.with(|x| {
509-
if x.borrow().len() == 0 {
510-
return None;
508+
NMETHOD_SLOTS.with_borrow_mut(|slots| {
509+
if !slots.is_empty() {
510+
let mut roots = crate::NURSERY_CODE_CACHE_ROOTS.lock().unwrap();
511+
roots.insert(nm, std::mem::take(slots));
511512
}
512-
Some(x.replace(vec![]))
513513
});
514-
let slots = match slots {
515-
Some(slots) => slots,
516-
_ => return,
517-
};
518-
let mut roots = crate::CODE_CACHE_ROOTS.lock().unwrap();
519-
// Relaxed add instead of `fetch_add`, since we've already acquired the lock.
520-
crate::CODE_CACHE_ROOTS_SIZE.store(
521-
crate::CODE_CACHE_ROOTS_SIZE.load(Ordering::Relaxed) + slots.len(),
522-
Ordering::Relaxed,
523-
);
524-
roots.insert(nm, slots);
525514
}
526515

527516
/// Unregister a nmethod.
528517
#[no_mangle]
529518
pub extern "C" fn mmtk_unregister_nmethod(nm: Address) {
530-
let mut roots = crate::CODE_CACHE_ROOTS.lock().unwrap();
531-
if let Some(slots) = roots.remove(&nm) {
532-
// Relaxed sub instead of `fetch_sub`, since we've already acquired the lock.
533-
crate::CODE_CACHE_ROOTS_SIZE.store(
534-
crate::CODE_CACHE_ROOTS_SIZE.load(Ordering::Relaxed) - slots.len(),
535-
Ordering::Relaxed,
536-
);
519+
{
520+
let mut roots = crate::NURSERY_CODE_CACHE_ROOTS.lock().unwrap();
521+
roots.remove(&nm);
522+
}
523+
{
524+
let mut roots = crate::MATURE_CODE_CACHE_ROOTS.lock().unwrap();
525+
roots.remove(&nm);
537526
}
538527
}

mmtk/src/gc_work.rs

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
use std::sync::atomic::Ordering;
2-
1+
use crate::scanning;
32
use crate::scanning::to_slots_closure;
43
use crate::OpenJDK;
54
use crate::OpenJDKSlot;
65
use crate::UPCALLS;
76
use mmtk::scheduler::*;
7+
use mmtk::util::Address;
88
use mmtk::vm::RootsWorkFactory;
99
use mmtk::vm::*;
1010
use mmtk::MMTK;
@@ -69,16 +69,51 @@ impl<const COMPRESSED: bool, F: RootsWorkFactory<OpenJDKSlot<COMPRESSED>>>
6969
fn do_work(
7070
&mut self,
7171
_worker: &mut GCWorker<OpenJDK<COMPRESSED>>,
72-
_mmtk: &'static MMTK<OpenJDK<COMPRESSED>>,
72+
mmtk: &'static MMTK<OpenJDK<COMPRESSED>>,
7373
) {
74-
// Collect all the cached roots
75-
let mut slots = Vec::with_capacity(crate::CODE_CACHE_ROOTS_SIZE.load(Ordering::Relaxed));
76-
for roots in (*crate::CODE_CACHE_ROOTS.lock().unwrap()).values() {
77-
for r in roots {
78-
slots.push((*r).into())
74+
let is_current_gc_nursery = mmtk
75+
.get_plan()
76+
.generational()
77+
.is_some_and(|gen| gen.is_current_gc_nursery());
78+
79+
let mut slots = Vec::with_capacity(scanning::WORK_PACKET_CAPACITY);
80+
81+
let mut nursery_slots = 0;
82+
let mut mature_slots = 0;
83+
84+
let mut add_roots = |roots: &[Address]| {
85+
for root in roots {
86+
slots.push(OpenJDKSlot::<COMPRESSED>::from(*root));
87+
if slots.len() >= scanning::WORK_PACKET_CAPACITY {
88+
self.factory
89+
.create_process_roots_work(std::mem::take(&mut slots));
90+
}
91+
}
92+
};
93+
94+
{
95+
let mut mature = crate::MATURE_CODE_CACHE_ROOTS.lock().unwrap();
96+
97+
// Only scan mature roots in full-heap collections.
98+
if !is_current_gc_nursery {
99+
for roots in mature.values() {
100+
mature_slots += roots.len();
101+
add_roots(roots);
102+
}
103+
}
104+
105+
{
106+
let mut nursery = crate::NURSERY_CODE_CACHE_ROOTS.lock().unwrap();
107+
for (key, roots) in nursery.drain() {
108+
nursery_slots += roots.len();
109+
add_roots(&roots);
110+
mature.insert(key, roots);
111+
}
79112
}
80113
}
81-
// Create work packet
114+
115+
probe!(mmtk_openjdk, code_cache_roots, nursery_slots, mature_slots);
116+
82117
if !slots.is_empty() {
83118
self.factory.create_process_roots_work(slots);
84119
}

mmtk/src/lib.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
#[macro_use]
22
extern crate lazy_static;
3+
#[macro_use]
4+
extern crate probe;
35

46
use std::collections::HashMap;
57
use std::ptr::null_mut;
6-
use std::sync::atomic::AtomicUsize;
78
use std::sync::Mutex;
89

910
use libc::{c_char, c_void, uintptr_t};
@@ -202,13 +203,12 @@ pub static MMTK_MARK_COMPACT_HEADER_RESERVED_IN_BYTES: usize =
202203
mmtk::util::alloc::MarkCompactAllocator::<OpenJDK<false>>::HEADER_RESERVED_IN_BYTES;
203204

204205
lazy_static! {
205-
/// A global storage for all the cached CodeCache root pointers
206-
static ref CODE_CACHE_ROOTS: Mutex<HashMap<Address, Vec<Address>>> = Mutex::new(HashMap::new());
206+
/// A global storage for all the cached CodeCache root pointers added since the last GC.
207+
static ref NURSERY_CODE_CACHE_ROOTS: Mutex<HashMap<Address, Vec<Address>>> = Mutex::new(HashMap::new());
208+
/// A global storage for all the cached CodeCache root pointers added before the last GC.
209+
static ref MATURE_CODE_CACHE_ROOTS: Mutex<HashMap<Address, Vec<Address>>> = Mutex::new(HashMap::new());
207210
}
208211

209-
/// A counter tracking the total size of the `CODE_CACHE_ROOTS`.
210-
static CODE_CACHE_ROOTS_SIZE: AtomicUsize = AtomicUsize::new(0);
211-
212212
fn set_compressed_pointer_vm_layout(builder: &mut MMTKBuilder) {
213213
let max_heap_size = builder.options.gc_trigger.max_heap_size();
214214
assert!(

mmtk/src/scanning.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use mmtk::MutatorContext;
1212

1313
pub struct VMScanning {}
1414

15-
const WORK_PACKET_CAPACITY: usize = 4096;
15+
pub(crate) const WORK_PACKET_CAPACITY: usize = 4096;
1616

1717
extern "C" fn report_slots_and_renew_buffer<S: Slot, F: RootsWorkFactory<S>>(
1818
ptr: *mut Address,
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
usdt:$MMTK:mmtk_openjdk:code_cache_roots {
2+
if (@enable_print) {
3+
printf("code_cache_roots,meta,%d,%lu,%lu,%lu\n", tid, nsecs, arg0, arg1);
4+
}
5+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/usr/bin/env python3
2+
3+
def enrich_meta_extra(log_processor, name, tid, ts, gc, wp, args):
4+
if wp is not None:
5+
match name:
6+
case "code_cache_roots":
7+
nursery, mature = int(args[0]), int(args[1])
8+
total = nursery + mature
9+
wp["args"] |= {
10+
"nursery_slots": nursery,
11+
"mature_slots": mature,
12+
"total_slots": total,
13+
}

0 commit comments

Comments
 (0)