Skip to content

Trace ptr_or_offset in jl_genericmemoryref_t #252

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: mmtk-support-moving-upstream
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 28 additions & 18 deletions mmtk/src/julia_scanning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,27 @@ pub unsafe fn mmtk_jl_to_typeof(t: Address) -> *const jl_datatype_t {
t.to_ptr::<jl_datatype_t>()
}

// The type jl_genericmemoryref_t potentially has two pointers (ptr_or_offset, and mem).
// But Julia only identifies it with one single pointer (mem). We need to make sure ptr_or_offset is also traced.
// This function only traces ptr_or_offset, and still leaves mem to the generic trace for data types.
fn trace_ptr_or_offset_in_genericmemoryref<SV: SlotVisitor<JuliaVMSlot>>(closure: &mut SV, r: *mut jl_genericmemoryref_t) {
unsafe {
if mmtk_object_is_managed_by_mmtk((*r).ptr_or_offset as usize) {
let ptr_or_ref_slot = Address::from_ptr(::std::ptr::addr_of!((*r).ptr_or_offset));
let mem_addr_as_usize = (*r).mem as usize;
let ptr_or_offset_as_usize = (*r).ptr_or_offset as usize;
if ptr_or_offset_as_usize > mem_addr_as_usize {
let offset = ptr_or_offset_as_usize - mem_addr_as_usize;

// Only update the offset pointer if the offset is valid (> 0)
if offset > 0 {
process_offset_slot(closure, ptr_or_ref_slot, offset);
}
}
}
}
}

const PRINT_OBJ_TYPE: bool = false;

// This function is a rewrite of `gc_mark_outrefs()` in `gc.c`
Expand Down Expand Up @@ -214,24 +235,8 @@ pub unsafe fn scan_julia_object<SV: SlotVisitor<JuliaVMSlot>>(obj: Address, clos
}
let vt = vtag.to_ptr::<jl_datatype_t>();
if (*vt).name == jl_array_typename {
let a = obj.to_ptr::<jl_array_t>();
let memref = (*a).ref_;

let ptr_or_offset = memref.ptr_or_offset;
// if the object moves its pointer inside the array object (void* ptr_or_offset) needs to be updated as well
if mmtk_object_is_managed_by_mmtk(ptr_or_offset as usize) {
let ptr_or_ref_slot = Address::from_ptr(::std::ptr::addr_of!((*a).ref_.ptr_or_offset));
let mem_addr_as_usize = memref.mem as usize;
let ptr_or_offset_as_usize = ptr_or_offset as usize;
if ptr_or_offset_as_usize > mem_addr_as_usize {
let offset = ptr_or_offset_as_usize - mem_addr_as_usize;

// Only update the offset pointer if the offset is valid (> 0)
if offset > 0 {
process_offset_slot(closure, ptr_or_ref_slot, offset);
}
}
}
let a = obj.to_mut_ptr::<jl_array_t>();
trace_ptr_or_offset_in_genericmemoryref(closure, &mut (*a).ref_);
}
if (*vt).name == jl_genericmemory_typename {
if PRINT_OBJ_TYPE {
Expand Down Expand Up @@ -363,6 +368,11 @@ pub unsafe fn scan_julia_object<SV: SlotVisitor<JuliaVMSlot>>(obj: Address, clos
return;
}

if (*vt).name == jl_genericmemoryref_typename {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@d-netto Is it possible that we're not tracing all jl_genericmemoryref_t objects with that check? I remember I had some code to simply print out if those objects were scanned when running the atomics test but for some reason nothing was being printed out.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just more info for the discussion. In the runtime code, we can see that jl_genericmemoryref_t may be used as a value (rather than as a pointer to heap objects) -- the ref in jl_array_t is an example, there are a few functions that return jl_genericmemoryref_t as a value -- so objects of this type may be stored outside the heap, like stacks, global memory, native heap, etc. We should be fine with stacks. But if it appears in global memory, or native heap, or anywhere else, we would have an issue -- though I don't know if that happens or not.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry about the delay. Will take a look soon.

let gmr = obj.to_mut_ptr::<jl_genericmemoryref_t>();
trace_ptr_or_offset_in_genericmemoryref(closure, gmr);
}

if PRINT_OBJ_TYPE {
println!("scan_julia_obj {}: datatype\n", obj);
}
Expand Down