Skip to content

Commit 8ee23f2

Browse files
authored
Trace ptr_or_offset in jl_genericmemoryref_t (#252)
See #249 (comment).
1 parent 0010046 commit 8ee23f2

File tree

7 files changed

+130
-48
lines changed

7 files changed

+130
-48
lines changed

.github/scripts/ci-test-other.sh

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,14 @@ moving_feature=${is_moving,,}
1919

2020
declare -a tests_to_skip=(
2121
# see https://github.com/mmtk/mmtk-julia/issues/259
22-
"atomics"
2322
"abstractarray"
24-
"Artifacts"
2523
"cmdlineargs"
2624
"Downloads"
2725
"read"
2826
"threads"
2927
"LibCURL"
30-
"subarray"
3128
"rounding"
3229
"loading"
33-
"compileall"
3430
"misc"
3531
)
3632

.github/scripts/ci-test-stdlib.sh

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,11 @@ declare -a tests_to_skip=(
3232

3333
# Skipping tests that fail for max moving Immix
3434
# see https://github.com/mmtk/mmtk-julia/issues/259
35-
"Artifacts"
3635
"Downloads"
3736
"REPL"
3837
"TOML"
3938
"Random"
4039
"LibCURL"
41-
"Mmap"
42-
"SharedArrays"
4340
"LazyArtifacts"
4441
)
4542
# These tests need multiple workers.

mmtk/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name = "mmtk-julia"
33
version = "0.30.3"
44
authors = ["Eduardo Souza <[email protected]>", "Yi Lin <[email protected]>"]
55
build = "build.rs"
6-
edition = "2018"
6+
edition = "2021"
77

88
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
99

mmtk/src/julia_scanning.rs

Lines changed: 84 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,17 @@ pub unsafe fn mmtk_jl_to_typeof(t: Address) -> *const jl_datatype_t {
6262
t.to_ptr::<jl_datatype_t>()
6363
}
6464

65+
fn trace_internal_pointer(slot: Address, closure: &mut impl SlotVisitor<JuliaVMSlot>) {
66+
let internal_pointer = unsafe { slot.load::<Address>() };
67+
// find the beginning of the object and trace it since the object may have moved
68+
if let Some(object) =
69+
memory_manager::find_object_from_internal_pointer(internal_pointer, usize::MAX)
70+
{
71+
let offset = internal_pointer - object.to_raw_address();
72+
process_offset_slot(closure, slot, offset);
73+
}
74+
}
75+
6576
const PRINT_OBJ_TYPE: bool = false;
6677

6778
trait ValidOffset: Copy {
@@ -102,6 +113,27 @@ unsafe fn scan_julia_obj_n<T>(
102113
}
103114
}
104115

116+
unsafe fn scan_julia_hidden_ptr_n<T>(
117+
obj: Address,
118+
begin: Address,
119+
end: Address,
120+
closure: &mut impl SlotVisitor<JuliaVMSlot>,
121+
) where
122+
T: ValidOffset,
123+
{
124+
let mut ptr = begin;
125+
while ptr < end {
126+
let offset = ptr.load::<T>();
127+
let slot = obj.shift::<Address>(offset.to_isize());
128+
let hidden_ptr = slot.load::<Address>();
129+
// hidden pointers are internal pointers, or just integers. We must check if it is a real pointer, then trace it.
130+
if mmtk_object_is_managed_by_mmtk(hidden_ptr.as_usize()) {
131+
trace_internal_pointer(slot, closure);
132+
}
133+
ptr = ptr.shift::<T>(1);
134+
}
135+
}
136+
105137
// This function is a rewrite of `gc_mark_outrefs()` in `gc.c`
106138
// INFO: *_custom() functions are acessors to bitfields that do not use bindgen generated code.
107139
#[inline(always)]
@@ -233,26 +265,6 @@ pub unsafe fn scan_julia_object<SV: SlotVisitor<JuliaVMSlot>>(obj: Address, clos
233265
crate::object_model::assert_generic_datatype(obj);
234266
}
235267
let vt = vtag.to_ptr::<jl_datatype_t>();
236-
if (*vt).name == jl_array_typename {
237-
let a = obj.to_ptr::<jl_array_t>();
238-
let memref = (*a).ref_;
239-
240-
let ptr_or_offset = memref.ptr_or_offset;
241-
// if the object moves its pointer inside the array object (void* ptr_or_offset) needs to be updated as well
242-
if mmtk_object_is_managed_by_mmtk(ptr_or_offset as usize) {
243-
let ptr_or_ref_slot = Address::from_ptr(::std::ptr::addr_of!((*a).ref_.ptr_or_offset));
244-
let mem_addr_as_usize = memref.mem as usize;
245-
let ptr_or_offset_as_usize = ptr_or_offset as usize;
246-
if ptr_or_offset_as_usize > mem_addr_as_usize {
247-
let offset = ptr_or_offset_as_usize - mem_addr_as_usize;
248-
249-
// Only update the offset pointer if the offset is valid (> 0)
250-
if offset > 0 {
251-
process_offset_slot(closure, ptr_or_ref_slot, offset);
252-
}
253-
}
254-
}
255-
}
256268
if (*vt).name == jl_genericmemory_typename {
257269
if PRINT_OBJ_TYPE {
258270
println!("scan_julia_obj {}: genericmemory\n", obj);
@@ -403,7 +415,37 @@ pub unsafe fn scan_julia_object<SV: SlotVisitor<JuliaVMSlot>>(obj: Address, clos
403415
}
404416
_ => {
405417
debug_assert!((*layout).fielddesc_type_custom() == 3);
406-
unimplemented!();
418+
panic!(
419+
"Unexpected field desc type custom: {}",
420+
(*layout).fielddesc_type_custom()
421+
);
422+
}
423+
}
424+
}
425+
426+
let nhidden_pointers = (*layout).nhidden_pointers;
427+
if nhidden_pointers != 0 {
428+
let obj_begin = mmtk_jl_dt_layout_hidden_ptrs(layout);
429+
let obj_end;
430+
match (*layout).fielddesc_type_custom() {
431+
0 => {
432+
obj_end = obj_begin.shift::<u8>(nhidden_pointers as isize);
433+
scan_julia_hidden_ptr_n::<u8>(obj, obj_begin, obj_end, closure);
434+
}
435+
1 => {
436+
obj_end = obj_begin.shift::<u16>(nhidden_pointers as isize);
437+
scan_julia_hidden_ptr_n::<u16>(obj, obj_begin, obj_end, closure);
438+
}
439+
2 => {
440+
obj_end = obj_begin.shift::<u32>(nhidden_pointers as isize);
441+
scan_julia_hidden_ptr_n::<u32>(obj, obj_begin, obj_end, closure);
442+
}
443+
_ => {
444+
debug_assert!((*layout).fielddesc_type_custom() == 3);
445+
panic!(
446+
"Unexpected field desc type custom: {}",
447+
(*layout).fielddesc_type_custom()
448+
);
407449
}
408450
}
409451
}
@@ -740,15 +782,26 @@ pub unsafe fn mmtk_jl_svecref(vt: *mut jl_svec_t, i: usize) -> *const jl_datatyp
740782
result as *const _jl_datatype_t
741783
}
742784

785+
#[inline(always)]
786+
pub unsafe fn mmtk_jl_dt_layout_fields(l: *const jl_datatype_layout_t) -> Address {
787+
Address::from_ptr(l) + std::mem::size_of::<jl_datatype_layout_t>()
788+
}
789+
743790
#[inline(always)]
744791
pub unsafe fn mmtk_jl_dt_layout_ptrs(l: *const jl_datatype_layout_t) -> Address {
745792
mmtk_jl_dt_layout_fields(l)
746793
+ (mmtk_jl_fielddesc_size((*l).fielddesc_type_custom()) * (*l).nfields) as usize
747794
}
748795

749796
#[inline(always)]
750-
pub unsafe fn mmtk_jl_dt_layout_fields(l: *const jl_datatype_layout_t) -> Address {
751-
Address::from_ptr(l) + std::mem::size_of::<jl_datatype_layout_t>()
797+
pub unsafe fn mmtk_jl_dt_layout_hidden_ptrs(l: *const jl_datatype_layout_t) -> Address {
798+
let ptrs = mmtk_jl_dt_layout_ptrs(l);
799+
let direct_ptrs_size = if (*l).npointers == 0 {
800+
0
801+
} else {
802+
((*l).npointers as usize) << ((*l).fielddesc_type_custom())
803+
};
804+
ptrs + direct_ptrs_size
752805
}
753806

754807
#[inline(always)]
@@ -789,6 +842,12 @@ pub unsafe fn mmtk_jl_bt_entry_jlvalue(
789842
i: usize,
790843
) -> ObjectReference {
791844
let entry = unsafe { (*bt_entry.add(2 + i)).__bindgen_anon_1.jlvalue };
792-
debug_assert!(!entry.is_null());
793-
unsafe { ObjectReference::from_raw_address_unchecked(Address::from_mut_ptr(entry)) }
845+
debug_assert!(!entry.ptr.is_null());
846+
unsafe { ObjectReference::from_raw_address_unchecked(Address::from_mut_ptr(entry.ptr)) }
847+
}
848+
849+
pub unsafe fn mmtk_jl_is_datatype(vt: *const jl_datatype_t) -> bool {
850+
let type_tag = mmtk_jl_typetagof(Address::from_ptr(vt));
851+
852+
type_tag.as_usize() == ((jl_small_typeof_tags_jl_datatype_tag as usize) << 4)
794853
}

mmtk/src/julia_types.rs

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,10 +1081,11 @@ const _: () = {
10811081
[::std::mem::offset_of!(_jl_genericmemory_t, ptr) - 8usize];
10821082
};
10831083
pub type jl_genericmemory_t = _jl_genericmemory_t;
1084+
pub type jl_hidden_ptr_ptr_or_offset_t = *mut ::std::os::raw::c_void;
10841085
#[repr(C)]
10851086
#[derive(Debug, Copy, Clone)]
10861087
pub struct jl_genericmemoryref_t {
1087-
pub ptr_or_offset: *mut ::std::os::raw::c_void,
1088+
pub ptr_or_offset: jl_hidden_ptr_ptr_or_offset_t,
10881089
pub mem: *mut jl_genericmemory_t,
10891090
}
10901091
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
@@ -1883,10 +1884,11 @@ pub struct jl_typename_t {
18831884
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>,
18841885
pub max_methods: u8,
18851886
pub constprop_heustic: u8,
1887+
pub hiddenptrfields: *const u32,
18861888
}
18871889
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
18881890
const _: () = {
1889-
["Size of jl_typename_t"][::std::mem::size_of::<jl_typename_t>() - 104usize];
1891+
["Size of jl_typename_t"][::std::mem::size_of::<jl_typename_t>() - 112usize];
18901892
["Alignment of jl_typename_t"][::std::mem::align_of::<jl_typename_t>() - 8usize];
18911893
["Offset of field: jl_typename_t::name"][::std::mem::offset_of!(jl_typename_t, name) - 0usize];
18921894
["Offset of field: jl_typename_t::module"]
@@ -1915,6 +1917,8 @@ const _: () = {
19151917
[::std::mem::offset_of!(jl_typename_t, max_methods) - 101usize];
19161918
["Offset of field: jl_typename_t::constprop_heustic"]
19171919
[::std::mem::offset_of!(jl_typename_t, constprop_heustic) - 102usize];
1920+
["Offset of field: jl_typename_t::hiddenptrfields"]
1921+
[::std::mem::offset_of!(jl_typename_t, hiddenptrfields) - 104usize];
19181922
};
19191923
impl jl_typename_t {
19201924
#[inline]
@@ -2082,7 +2086,9 @@ pub struct jl_datatype_layout_t {
20822086
pub size: u32,
20832087
pub nfields: u32,
20842088
pub npointers: u32,
2089+
pub nhidden_pointers: u32,
20852090
pub first_ptr: i32,
2091+
pub first_hidden_ptr: i32,
20862092
pub alignment: u16,
20872093
pub flags: jl_datatype_layout_t__bindgen_ty_1,
20882094
}
@@ -2337,20 +2343,24 @@ impl jl_datatype_layout_t__bindgen_ty_1 {
23372343
}
23382344
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
23392345
const _: () = {
2340-
["Size of jl_datatype_layout_t"][::std::mem::size_of::<jl_datatype_layout_t>() - 20usize];
2346+
["Size of jl_datatype_layout_t"][::std::mem::size_of::<jl_datatype_layout_t>() - 28usize];
23412347
["Alignment of jl_datatype_layout_t"][::std::mem::align_of::<jl_datatype_layout_t>() - 4usize];
23422348
["Offset of field: jl_datatype_layout_t::size"]
23432349
[::std::mem::offset_of!(jl_datatype_layout_t, size) - 0usize];
23442350
["Offset of field: jl_datatype_layout_t::nfields"]
23452351
[::std::mem::offset_of!(jl_datatype_layout_t, nfields) - 4usize];
23462352
["Offset of field: jl_datatype_layout_t::npointers"]
23472353
[::std::mem::offset_of!(jl_datatype_layout_t, npointers) - 8usize];
2354+
["Offset of field: jl_datatype_layout_t::nhidden_pointers"]
2355+
[::std::mem::offset_of!(jl_datatype_layout_t, nhidden_pointers) - 12usize];
23482356
["Offset of field: jl_datatype_layout_t::first_ptr"]
2349-
[::std::mem::offset_of!(jl_datatype_layout_t, first_ptr) - 12usize];
2357+
[::std::mem::offset_of!(jl_datatype_layout_t, first_ptr) - 16usize];
2358+
["Offset of field: jl_datatype_layout_t::first_hidden_ptr"]
2359+
[::std::mem::offset_of!(jl_datatype_layout_t, first_hidden_ptr) - 20usize];
23502360
["Offset of field: jl_datatype_layout_t::alignment"]
2351-
[::std::mem::offset_of!(jl_datatype_layout_t, alignment) - 16usize];
2361+
[::std::mem::offset_of!(jl_datatype_layout_t, alignment) - 24usize];
23522362
["Offset of field: jl_datatype_layout_t::flags"]
2353-
[::std::mem::offset_of!(jl_datatype_layout_t, flags) - 18usize];
2363+
[::std::mem::offset_of!(jl_datatype_layout_t, flags) - 26usize];
23542364
};
23552365
#[repr(C)]
23562366
#[derive(Debug, Copy, Clone)]
@@ -3013,6 +3023,12 @@ const _: () = {
30133023
};
30143024
#[repr(C)]
30153025
#[derive(Debug, Copy, Clone)]
3026+
pub struct pinned_ref<T> {
3027+
pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>>,
3028+
pub ptr: *mut T,
3029+
}
3030+
#[repr(C)]
3031+
#[derive(Debug, Copy, Clone)]
30163032
pub struct _jl_handler_t {
30173033
pub eh_ctx: sigjmp_buf,
30183034
pub gcstack: *mut jl_gcframe_t,
@@ -3056,7 +3072,7 @@ pub struct _jl_bt_element_t {
30563072
#[derive(Copy, Clone)]
30573073
pub union _jl_bt_element_t__bindgen_ty_1 {
30583074
pub uintptr: usize,
3059-
pub jlvalue: *mut jl_value_t,
3075+
pub jlvalue: pinned_ref<jl_value_t>,
30603076
}
30613077
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
30623078
const _: () = {
@@ -3425,3 +3441,10 @@ const _: () = {
34253441
["Align of template specialization: std_atomic_open0_intptr_t_close0"]
34263442
[::std::mem::align_of::<std_atomic<isize>>() - 8usize];
34273443
};
3444+
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
3445+
const _: () = {
3446+
["Size of template specialization: pinned_ref_open0_jl_value_t_close0"]
3447+
[::std::mem::size_of::<pinned_ref<jl_value_t>>() - 8usize];
3448+
["Align of template specialization: pinned_ref_open0_jl_value_t_close0"]
3449+
[::std::mem::align_of::<pinned_ref<jl_value_t>>() - 8usize];
3450+
};

mmtk/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ extern "C" {
134134
pub fn jl_log_pinning_event(pinned_object: Address, filename: *const i8, lineno: i32);
135135
pub fn jl_gc_log();
136136
pub static jl_true: *mut crate::julia_types::jl_value_t;
137+
pub fn jl_symbol(name: *const i8) -> *mut crate::julia_types::jl_sym_t;
137138
}
138139

139140
#[macro_export]

mmtk/src/object_model.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,9 @@ pub(crate) const LOS_METADATA_SPEC: VMLocalLOSMarkNurserySpec =
5454

5555
impl ObjectModel<JuliaVM> for VMObjectModel {
5656
const GLOBAL_LOG_BIT_SPEC: VMGlobalLogBitSpec = LOGGING_SIDE_METADATA_SPEC;
57+
// See https://github.com/mmtk/mmtk-core/issues/1331
5758
const LOCAL_FORWARDING_POINTER_SPEC: VMLocalForwardingPointerSpec =
58-
VMLocalForwardingPointerSpec::in_header(-64);
59+
VMLocalForwardingPointerSpec::in_header(0);
5960

6061
const LOCAL_PINNING_BIT_SPEC: VMLocalPinningBitSpec = LOCAL_PINNING_METADATA_BITS_SPEC;
6162
const LOCAL_FORWARDING_BITS_SPEC: VMLocalForwardingBitsSpec =
@@ -66,6 +67,8 @@ impl ObjectModel<JuliaVM> for VMObjectModel {
6667
const UNIFIED_OBJECT_REFERENCE_ADDRESS: bool = false;
6768
const OBJECT_REF_OFFSET_LOWER_BOUND: isize = 0;
6869

70+
const NEED_VO_BITS_DURING_TRACING: bool = true;
71+
6972
fn copy(
7073
from: ObjectReference,
7174
semantics: CopySemantics,
@@ -126,7 +129,7 @@ impl ObjectModel<JuliaVM> for VMObjectModel {
126129
debug_assert!(test_hash_state(to_obj, UNHASHED));
127130
to_obj
128131
} else if test_hash_state(from, HASHED) {
129-
info!(
132+
debug!(
130133
"Moving a hashed object {} with size = {}. New size = {}",
131134
from, cur_bytes, new_bytes
132135
);
@@ -141,7 +144,7 @@ impl ObjectModel<JuliaVM> for VMObjectModel {
141144
unsafe {
142145
dst.store::<usize>(hash);
143146
}
144-
info!("Store hash {:x} into {}", hash, dst);
147+
debug!("Store hash {:x} into {}", hash, dst);
145148
dst += STORED_HASH_BYTES;
146149

147150
// Copy the object
@@ -153,13 +156,13 @@ impl ObjectModel<JuliaVM> for VMObjectModel {
153156
unsafe { ObjectReference::from_raw_address_unchecked(dst + header_offset) };
154157
copy_context.post_copy(to_obj, new_bytes, semantics);
155158

156-
info!("old object {}, new objectt {}", from, to_obj);
159+
debug!("old object {}, new objectt {}", from, to_obj);
157160

158161
// set_hash_state(from, UNHASHED);
159162
set_hash_state(to_obj, HASHED_AND_MOVED);
160163
to_obj
161164
} else if test_hash_state(from, HASHED_AND_MOVED) {
162-
info!("Moving a hashed+moved object {}", from);
165+
debug!("Moving a hashed+moved object {}", from);
163166
debug_assert_eq!(cur_bytes, new_bytes);
164167
debug_assert_eq!(from.to_raw_address(), from_start + 16usize);
165168
debug_assert_eq!(header_offset, 16);
@@ -203,12 +206,15 @@ impl ObjectModel<JuliaVM> for VMObjectModel {
203206
}
204207

205208
// zero from_obj (for debugging purposes)
209+
// We cannot zero from_obj. We use find_object_from_internal_pointer during trace.
210+
// So we will need to access from_obj after it is being moved to calculate its size.
211+
// We cannot zero from_obj. See https://github.com/mmtk/mmtk-core/issues/1331
206212
#[cfg(debug_assertions)]
207213
{
208214
use atomic::Ordering;
209-
unsafe {
210-
libc::memset(from_start.to_mut_ptr(), 0, cur_bytes);
211-
}
215+
// unsafe {
216+
// libc::memset(from_start.to_mut_ptr(), 0, cur_bytes);
217+
// }
212218

213219
Self::LOCAL_FORWARDING_BITS_SPEC.store_atomic::<JuliaVM, u8>(
214220
from,

0 commit comments

Comments
 (0)