Skip to content

Commit c1ccd57

Browse files
authored
Push pinning roots (#142)
Supporting processing roots in the shadow stack that are not transitively pinned (only the root object is pinned), and therefore should enable moving more objects. NB: Should be merged with mmtk/julia#43.
1 parent c9b1c49 commit c1ccd57

File tree

4 files changed

+44
-16
lines changed

4 files changed

+44
-16
lines changed

.github/scripts/common.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ export MMTK_JULIA_DIR=$BINDING_PATH
1010
# Make sure we have enough heap to build Julia
1111
export MMTK_MIN_HSIZE_G=0.5
1212
export MMTK_MAX_HSIZE_G=4
13+
# Print out a backtrace in case of an error
14+
export RUST_BACKTRACE=1
1315
# Make sure we do not get OOM killed.
1416
total_mem=$(free -m | awk '/^Mem:/ {print $2}')
1517
export JULIA_TEST_MAXRSS_MB=$total_mem

mmtk/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ edition = "2018"
1010
[package.metadata.julia]
1111
# Our CI matches the following line and extract mmtk/julia. If this line is updated, please check ci yaml files and make sure it works.
1212
julia_repo = "https://github.com/mmtk/julia.git"
13-
julia_version = "09e025b25c65e5842b6eeeb3c81ba4cab97f5192"
13+
julia_version = "0ac54e680f9a8b57bb1fd8ef04919ce9898ae77b"
1414

1515
[lib]
1616
crate-type = ["cdylib"]

mmtk/src/julia_scanning.rs

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,9 @@ pub unsafe fn scan_julia_object<EV: EdgeVisitor<JuliaVMEdge>>(obj: Address, clos
278278

279279
let ta = obj.to_ptr::<mmtk_jl_task_t>();
280280

281-
mmtk_scan_gcstack(ta, closure);
281+
// transitively pinnig of stack roots happens during root
282+
// processing so it's fine to have only one closure here
283+
mmtk_scan_gcstack(ta, closure, None);
282284

283285
let layout = (*jl_task_type).layout;
284286
debug_assert!((*layout).fielddesc_type() == 0);
@@ -354,9 +356,10 @@ pub unsafe fn scan_julia_object<EV: EdgeVisitor<JuliaVMEdge>>(obj: Address, clos
354356
}
355357
}
356358

357-
pub unsafe fn mmtk_scan_gcstack<EV: EdgeVisitor<JuliaVMEdge>>(
359+
pub unsafe fn mmtk_scan_gcstack<'a, EV: EdgeVisitor<JuliaVMEdge>>(
358360
ta: *const mmtk_jl_task_t,
359-
closure: &mut EV,
361+
mut closure: &'a mut EV,
362+
mut pclosure: Option<&'a mut EV>,
360363
) {
361364
let stkbuf = (*ta).stkbuf;
362365
let copy_stack = (*ta).copy_stack_custom();
@@ -385,16 +388,28 @@ pub unsafe fn mmtk_scan_gcstack<EV: EdgeVisitor<JuliaVMEdge>>(
385388
let s_nroots_addr = ::std::ptr::addr_of!((*s).nroots);
386389
let mut nroots = read_stack(Address::from_ptr(s_nroots_addr), offset, lb, ub);
387390
debug_assert!(nroots.as_usize() as u32 <= UINT32_MAX);
388-
let mut nr = nroots >> 2;
391+
let mut nr = nroots >> 3;
389392

390393
loop {
394+
// if the 'pin' bit on the root type is not set, must transitively pin
395+
// and therefore use transitive pinning closure
396+
let closure_to_use: &mut &mut EV = if (nroots.as_usize() & 4) == 0 {
397+
&mut closure
398+
} else {
399+
// otherwise, use the pinning closure (if available)
400+
match &mut pclosure {
401+
Some(c) => c,
402+
None => &mut closure,
403+
}
404+
};
405+
391406
let rts = Address::from_mut_ptr(s).shift::<Address>(2);
392407
let mut i = 0;
393408
while i < nr {
394409
if (nroots.as_usize() & 1) != 0 {
395410
let slot = read_stack(rts.shift::<Address>(i as isize), offset, lb, ub);
396411
let real_addr = get_stack_addr(slot, offset, lb, ub);
397-
process_edge(closure, real_addr);
412+
process_edge(*closure_to_use, real_addr);
398413
} else {
399414
let real_addr =
400415
get_stack_addr(rts.shift::<Address>(i as isize), offset, lb, ub);
@@ -410,12 +425,12 @@ pub unsafe fn mmtk_scan_gcstack<EV: EdgeVisitor<JuliaVMEdge>>(
410425

411426
// pointer is not malloced but function is native, so skip it
412427
if gc_ptr_tag(slot, 1) {
413-
process_offset_edge(closure, real_addr, 1);
428+
process_offset_edge(*closure_to_use, real_addr, 1);
414429
i += 2;
415430
continue;
416431
}
417432

418-
process_edge(closure, real_addr);
433+
process_edge(*closure_to_use, real_addr);
419434
}
420435

421436
i += 1;
@@ -431,7 +446,7 @@ pub unsafe fn mmtk_scan_gcstack<EV: EdgeVisitor<JuliaVMEdge>>(
431446
let s_nroots_addr = ::std::ptr::addr_of!((*s).nroots);
432447
let new_nroots = read_stack(Address::from_ptr(s_nroots_addr), offset, lb, ub);
433448
nroots = new_nroots;
434-
nr = nroots >> 2;
449+
nr = nroots >> 3;
435450
continue;
436451
}
437452
}
@@ -447,14 +462,14 @@ pub unsafe fn mmtk_scan_gcstack<EV: EdgeVisitor<JuliaVMEdge>>(
447462
}
448463

449464
#[inline(always)]
450-
unsafe fn read_stack(addr: Address, offset: isize, lb: u64, ub: u64) -> Address {
465+
pub unsafe fn read_stack(addr: Address, offset: isize, lb: u64, ub: u64) -> Address {
451466
let real_addr = get_stack_addr(addr, offset, lb, ub);
452467

453468
real_addr.load::<Address>()
454469
}
455470

456471
#[inline(always)]
457-
fn get_stack_addr(addr: Address, offset: isize, lb: u64, ub: u64) -> Address {
472+
pub fn get_stack_addr(addr: Address, offset: isize, lb: u64, ub: u64) -> Address {
458473
if addr.as_usize() >= lb as usize && addr.as_usize() < ub as usize {
459474
return addr + offset;
460475
} else {

mmtk/src/scanning.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use crate::edges::JuliaVMEdge;
22
use crate::{SINGLETON, UPCALLS};
33
use mmtk::memory_manager;
44
use mmtk::scheduler::*;
5-
use mmtk::util::opaque_pointer::*;
65
use mmtk::util::ObjectReference;
6+
use mmtk::util::{opaque_pointer::*, Address};
77
use mmtk::vm::edge_shape::Edge;
88
use mmtk::vm::EdgeVisitor;
99
use mmtk::vm::ObjectTracerContext;
@@ -50,17 +50,21 @@ impl Scanning<JuliaVM> for VMScanning {
5050

5151
use crate::julia_scanning::*;
5252
use crate::julia_types::*;
53-
use mmtk::util::Address;
5453

5554
let ptls: &mut mmtk__jl_tls_states_t = unsafe { std::mem::transmute(mutator.mutator_tls) };
56-
let mut edge_buffer = EdgeBuffer { buffer: vec![] }; // need to be tpinned as they're all from the shadow stack
55+
let mut tpinning_edge_buffer = EdgeBuffer { buffer: vec![] }; // need to be transitively pinned
56+
let mut pinning_edge_buffer = EdgeBuffer { buffer: vec![] }; // roots from the shadow stack that we know that do not need to be transitively pinned
5757
let mut node_buffer = vec![];
5858

5959
// Scan thread local from ptls: See gc_queue_thread_local in gc.c
6060
let mut root_scan_task = |task: *const mmtk__jl_task_t, task_is_root: bool| {
6161
if !task.is_null() {
6262
unsafe {
63-
crate::julia_scanning::mmtk_scan_gcstack(task, &mut edge_buffer);
63+
mmtk_scan_gcstack(
64+
task,
65+
&mut tpinning_edge_buffer,
66+
Some(&mut pinning_edge_buffer),
67+
);
6468
}
6569
if task_is_root {
6670
// captures wrong root nodes before creating the work
@@ -127,13 +131,20 @@ impl Scanning<JuliaVM> for VMScanning {
127131

128132
// Push work
129133
const CAPACITY_PER_PACKET: usize = 4096;
130-
for tpinning_roots in edge_buffer
134+
for tpinning_roots in tpinning_edge_buffer
131135
.buffer
132136
.chunks(CAPACITY_PER_PACKET)
133137
.map(|c| c.to_vec())
134138
{
135139
factory.create_process_tpinning_roots_work(tpinning_roots);
136140
}
141+
for pinning_roots in pinning_edge_buffer
142+
.buffer
143+
.chunks(CAPACITY_PER_PACKET)
144+
.map(|c| c.to_vec())
145+
{
146+
factory.create_process_pinning_roots_work(pinning_roots);
147+
}
137148
for nodes in node_buffer.chunks(CAPACITY_PER_PACKET).map(|c| c.to_vec()) {
138149
factory.create_process_pinning_roots_work(nodes);
139150
}

0 commit comments

Comments
 (0)