Skip to content

Commit 3f242b5

Browse files
committed
Process pinning roots - port PR #142 (#192)
Port #142 to `dev`. Process both transitively pinning roots, and non transitively pinning roots.
1 parent c9e046b commit 3f242b5

File tree

3 files changed

+39
-12
lines changed

3 files changed

+39
-12
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
.idea/
22
julia/*.o
33
julia/*.dbj.obj
4-
.vscode
4+
.vscode
5+
mmtk/src/julia_types.rs
6+

mmtk/src/julia_scanning.rs

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ pub unsafe fn scan_julia_object<SV: SlotVisitor<JuliaVMSlot>>(obj: Address, clos
162162

163163
let ta = obj.to_ptr::<jl_task_t>();
164164

165-
mmtk_scan_gcstack(ta, closure);
165+
mmtk_scan_gcstack(ta, closure, None);
166166

167167
let layout = (*jl_task_type).layout;
168168
debug_assert!((*layout).fielddesc_type_custom() == 0);
@@ -373,9 +373,10 @@ unsafe fn mmtk_jl_genericmemory_data_owner_field_address(m: *const jl_genericmem
373373
// mmtk_jl_genericmemory_data_owner_field_address(m).load::<*const mmtk_jl_value_t>()
374374
// }
375375

376-
pub unsafe fn mmtk_scan_gcstack<EV: SlotVisitor<JuliaVMSlot>>(
376+
pub unsafe fn mmtk_scan_gcstack<'a, EV: SlotVisitor<JuliaVMSlot>>(
377377
ta: *const jl_task_t,
378-
closure: &mut EV,
378+
mut closure: &'a mut EV,
379+
mut pclosure: Option<&'a mut EV>,
379380
) {
380381
let stkbuf = (*ta).ctx.stkbuf;
381382
let copy_stack = (*ta).ctx.copy_stack_custom();
@@ -404,16 +405,28 @@ pub unsafe fn mmtk_scan_gcstack<EV: SlotVisitor<JuliaVMSlot>>(
404405
let s_nroots_addr = ::std::ptr::addr_of!((*s).nroots);
405406
let mut nroots = read_stack(Address::from_ptr(s_nroots_addr), offset, lb, ub);
406407
debug_assert!(nroots.as_usize() as u32 <= u32::MAX);
407-
let mut nr = nroots >> 2;
408+
let mut nr = nroots >> 3;
408409

409410
loop {
411+
// if the 'pin' bit on the root type is not set, must transitively pin
412+
// and therefore use transitive pinning closure
413+
let closure_to_use: &mut &mut EV = if (nroots.as_usize() & 4) == 0 {
414+
&mut closure
415+
} else {
416+
// otherwise, use the pinning closure (if available)
417+
match &mut pclosure {
418+
Some(c) => c,
419+
None => &mut closure,
420+
}
421+
};
422+
410423
let rts = Address::from_mut_ptr(s).shift::<Address>(2);
411424
let mut i = 0;
412425
while i < nr {
413426
if (nroots.as_usize() & 1) != 0 {
414427
let slot = read_stack(rts.shift::<Address>(i as isize), offset, lb, ub);
415428
let real_addr = get_stack_addr(slot, offset, lb, ub);
416-
process_slot(closure, real_addr);
429+
process_slot(*closure_to_use, real_addr);
417430
} else {
418431
let real_addr =
419432
get_stack_addr(rts.shift::<Address>(i as isize), offset, lb, ub);
@@ -429,12 +442,12 @@ pub unsafe fn mmtk_scan_gcstack<EV: SlotVisitor<JuliaVMSlot>>(
429442

430443
// pointer is not malloced but function is native, so skip it
431444
if gc_ptr_tag(slot, 1) {
432-
process_offset_slot(closure, real_addr, 1);
445+
process_offset_slot(*closure_to_use, real_addr, 1);
433446
i += 2;
434447
continue;
435448
}
436449

437-
process_slot(closure, real_addr);
450+
process_slot(*closure_to_use, real_addr);
438451
}
439452

440453
i += 1;
@@ -450,7 +463,7 @@ pub unsafe fn mmtk_scan_gcstack<EV: SlotVisitor<JuliaVMSlot>>(
450463
let s_nroots_addr = ::std::ptr::addr_of!((*s).nroots);
451464
let new_nroots = read_stack(Address::from_ptr(s_nroots_addr), offset, lb, ub);
452465
nroots = new_nroots;
453-
nr = nroots >> 2;
466+
nr = nroots >> 3;
454467
continue;
455468
}
456469
}

mmtk/src/scanning.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,19 @@ impl Scanning<JuliaVM> for VMScanning {
5353
use mmtk::util::Address;
5454

5555
let ptls: &mut _jl_tls_states_t = unsafe { std::mem::transmute(mutator.mutator_tls) };
56-
let mut slot_buffer = SlotBuffer { buffer: vec![] }; // need to be tpinned as they're all from the shadow stack
56+
let mut tpinning_slot_buffer = SlotBuffer { buffer: vec![] }; // need to be transitively pinned
57+
let mut pinning_slot_buffer = SlotBuffer { buffer: vec![] }; // roots from the shadow stack that we know that do not need to be transitively pinned
5758
let mut node_buffer = vec![];
5859

5960
// Scan thread local from ptls: See gc_queue_thread_local in gc.c
6061
let mut root_scan_task = |task: *const _jl_task_t, task_is_root: bool| {
6162
if !task.is_null() {
6263
unsafe {
63-
crate::julia_scanning::mmtk_scan_gcstack(task, &mut slot_buffer);
64+
crate::julia_scanning::mmtk_scan_gcstack(
65+
task,
66+
&mut tpinning_slot_buffer,
67+
Some(&mut pinning_slot_buffer),
68+
);
6469
}
6570
if task_is_root {
6671
// captures wrong root nodes before creating the work
@@ -136,13 +141,20 @@ impl Scanning<JuliaVM> for VMScanning {
136141

137142
// Push work
138143
const CAPACITY_PER_PACKET: usize = 4096;
139-
for tpinning_roots in slot_buffer
144+
for tpinning_roots in tpinning_slot_buffer
140145
.buffer
141146
.chunks(CAPACITY_PER_PACKET)
142147
.map(|c| c.to_vec())
143148
{
144149
factory.create_process_tpinning_roots_work(tpinning_roots);
145150
}
151+
for pinning_roots in pinning_slot_buffer
152+
.buffer
153+
.chunks(CAPACITY_PER_PACKET)
154+
.map(|c| c.to_vec())
155+
{
156+
factory.create_process_pinning_roots_work(pinning_roots);
157+
}
146158
for nodes in node_buffer.chunks(CAPACITY_PER_PACKET).map(|c| c.to_vec()) {
147159
factory.create_process_pinning_roots_work(nodes);
148160
}

0 commit comments

Comments
 (0)