Skip to content

Commit 309a6ae

Browse files
wksmmtkgc-bot
andauthored
Remove NULL ObjectReference (#146)
Parent PR: mmtk/mmtk-core#1064 --------- Co-authored-by: mmtkgc-bot <[email protected]>
1 parent 063f8fc commit 309a6ae

8 files changed

+119
-75
lines changed

mmtk/Cargo.lock

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

mmtk/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ lazy_static = "1.1"
3131
# - change branch
3232
# - change repo name
3333
# But other changes including adding/removing whitespaces in commented lines may break the CI
34-
mmtk = { git = "https://github.com/mmtk/mmtk-core.git", rev="e79e94e744660c486d5471f252ff05c4248bcea9" }
34+
mmtk = { git = "https://github.com/mmtk/mmtk-core.git", rev="a02803b4104519ff2289234101a2dd8ceedd1bc7" }
3535
# Uncomment the following to build locally
3636
# mmtk = { path = "../repos/mmtk-core" }
3737
log = {version = "0.4", features = ["max_level_trace", "release_max_level_off"] }

mmtk/src/edges.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub enum JuliaVMEdge {
1717
unsafe impl Send for JuliaVMEdge {}
1818

1919
impl Edge for JuliaVMEdge {
20-
fn load(&self) -> ObjectReference {
20+
fn load(&self) -> Option<ObjectReference> {
2121
match self {
2222
JuliaVMEdge::Simple(e) => e.load(),
2323
JuliaVMEdge::Offset(e) => e.load(),
@@ -74,9 +74,10 @@ impl OffsetEdge {
7474
}
7575

7676
impl Edge for OffsetEdge {
77-
fn load(&self) -> ObjectReference {
77+
fn load(&self) -> Option<ObjectReference> {
7878
let middle = unsafe { (*self.slot_addr).load(atomic::Ordering::Relaxed) };
7979
let begin = middle - self.offset;
80+
debug_assert!(!begin.is_zero());
8081
ObjectReference::from_raw_address(begin)
8182
}
8283

mmtk/src/julia_finalizer.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,9 @@ impl ArrayListT {
111111
}
112112

113113
fn gc_ptr_clear_tag(addr: Address, tag: usize) -> ObjectReference {
114-
ObjectReference::from_raw_address(unsafe { Address::from_usize(addr & !tag) })
114+
let addr = unsafe { Address::from_usize(addr & !tag) };
115+
debug_assert!(!addr.is_zero());
116+
unsafe { ObjectReference::from_raw_address_unchecked(addr) }
115117
}
116118

117119
fn gc_ptr_tag(addr: Address, tag: usize) -> bool {
@@ -201,7 +203,8 @@ fn mark_finlist<T: ObjectTracer>(list: &mut ArrayListT, start: usize, tracer: &m
201203
cur_tag = 1;
202204
gc_ptr_clear_tag(cur, 1)
203205
} else {
204-
ObjectReference::from_raw_address(cur)
206+
// unsafe: We checked `cur.is_zero()` before.
207+
unsafe { ObjectReference::from_raw_address_unchecked(cur) }
205208
};
206209
if gc_ptr_tag(cur, 2) {
207210
i += 1;

mmtk/src/julia_scanning.rs

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use crate::edges::JuliaVMEdge;
44
use crate::edges::OffsetEdge;
55
use crate::julia_types::*;
66
use crate::object_model::mmtk_jl_array_ndims;
7-
use crate::JuliaVM;
87
use crate::JULIA_BUFF_TAG;
98
use crate::UPCALLS;
109
use memoffset::offset_of;
@@ -416,27 +415,34 @@ fn get_stack_addr(addr: Address, offset: isize, lb: u64, ub: u64) -> Address {
416415
}
417416
}
418417

419-
use mmtk::vm::edge_shape::Edge;
420-
421418
#[inline(always)]
422419
pub fn process_edge<EV: EdgeVisitor<JuliaVMEdge>>(closure: &mut EV, slot: Address) {
423420
let simple_edge = SimpleEdge::from_address(slot);
424-
debug_assert!(
425-
simple_edge.load().is_null()
426-
|| mmtk::memory_manager::is_in_mmtk_spaces::<JuliaVM>(simple_edge.load()),
427-
"Object {:?} in slot {:?} is not mapped address",
428-
simple_edge.load(),
429-
simple_edge
430-
);
431421

432-
// captures wrong edges before creating the work
433-
debug_assert!(
434-
simple_edge.load().to_raw_address().as_usize() % 16 == 0
435-
|| simple_edge.load().to_raw_address().as_usize() % 8 == 0,
436-
"Object {:?} in slot {:?} is not aligned to 8 or 16",
437-
simple_edge.load(),
438-
simple_edge
439-
);
422+
#[cfg(debug_assertions)]
423+
{
424+
use crate::JuliaVM;
425+
use mmtk::vm::edge_shape::Edge;
426+
427+
if let Some(objref) = simple_edge.load() {
428+
debug_assert!(
429+
mmtk::memory_manager::is_in_mmtk_spaces::<JuliaVM>(objref),
430+
"Object {:?} in slot {:?} is not mapped address",
431+
objref,
432+
simple_edge
433+
);
434+
435+
let raw_addr_usize = objref.to_raw_address().as_usize();
436+
437+
// captures wrong edges before creating the work
438+
debug_assert!(
439+
raw_addr_usize % 16 == 0 || raw_addr_usize % 8 == 0,
440+
"Object {:?} in slot {:?} is not aligned to 8 or 16",
441+
objref,
442+
simple_edge
443+
);
444+
}
445+
}
440446

441447
closure.visit_edge(JuliaVMEdge::Simple(simple_edge));
442448
}
@@ -485,13 +491,20 @@ pub fn process_offset_edge<EV: EdgeVisitor<JuliaVMEdge>>(
485491
offset: usize,
486492
) {
487493
let offset_edge = OffsetEdge::new_with_offset(slot, offset);
488-
debug_assert!(
489-
offset_edge.load().is_null()
490-
|| mmtk::memory_manager::is_in_mmtk_spaces::<JuliaVM>(offset_edge.load()),
491-
"Object {:?} in slot {:?} is not mapped address",
492-
offset_edge.load(),
493-
offset_edge
494-
);
494+
#[cfg(debug_assertions)]
495+
{
496+
use crate::JuliaVM;
497+
use mmtk::vm::edge_shape::Edge;
498+
499+
if let Some(objref) = offset_edge.load() {
500+
debug_assert!(
501+
mmtk::memory_manager::is_in_mmtk_spaces::<JuliaVM>(objref),
502+
"Object {:?} in slot {:?} is not mapped address",
503+
objref,
504+
offset_edge
505+
);
506+
}
507+
}
495508

496509
closure.visit_edge(JuliaVMEdge::Offset(offset_edge));
497510
}
@@ -603,5 +616,6 @@ pub fn mmtk_jl_bt_num_uintvals(bt_entry: *mut mmtk_jl_bt_element_t) -> usize {
603616

604617
pub fn mmtk_jl_bt_entry_jlvalue(bt_entry: *mut mmtk_jl_bt_element_t, i: usize) -> ObjectReference {
605618
let entry = unsafe { (*bt_entry.add(2 + i)).__bindgen_anon_1.jlvalue };
606-
ObjectReference::from_raw_address(Address::from_mut_ptr(entry))
619+
debug_assert!(!entry.is_null());
620+
unsafe { ObjectReference::from_raw_address_unchecked(Address::from_mut_ptr(entry)) }
607621
}

mmtk/src/object_model.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,25 +62,28 @@ impl ObjectModel<JuliaVM> for VMObjectModel {
6262
copy_context: &mut GCWorkerCopyContext<JuliaVM>,
6363
) -> ObjectReference {
6464
let bytes = Self::get_current_size(from);
65-
let from_start_ref = ObjectReference::from_raw_address(Self::ref_to_object_start(from));
66-
let header_offset =
67-
from.to_raw_address().as_usize() - from_start_ref.to_raw_address().as_usize();
65+
let from_addr = from.to_raw_address();
66+
let from_start = Self::ref_to_object_start(from);
67+
let header_offset = from_addr - from_start;
6868

6969
let dst = if header_offset == 8 {
7070
// regular object
71-
copy_context.alloc_copy(from_start_ref, bytes, 16, 8, semantics)
71+
// Note: The `from` reference is not used by any allocator currently in MMTk core.
72+
copy_context.alloc_copy(from, bytes, 16, 8, semantics)
7273
} else if header_offset == 16 {
7374
// buffer should not be copied
7475
unimplemented!();
7576
} else {
7677
unimplemented!()
7778
};
79+
// `alloc_copy` should never return zero.
80+
debug_assert!(!dst.is_zero());
7881

79-
let src = Self::ref_to_object_start(from);
82+
let src = from_start;
8083
unsafe {
8184
std::ptr::copy_nonoverlapping::<u8>(src.to_ptr(), dst.to_mut_ptr(), bytes);
8285
}
83-
let to_obj = ObjectReference::from_raw_address(dst + header_offset);
86+
let to_obj = unsafe { ObjectReference::from_raw_address_unchecked(dst + header_offset) };
8487

8588
trace!("Copying object from {} to {}", from, to_obj);
8689

@@ -99,7 +102,7 @@ impl ObjectModel<JuliaVM> for VMObjectModel {
99102
{
100103
use atomic::Ordering;
101104
unsafe {
102-
libc::memset(from_start_ref.to_raw_address().to_mut_ptr(), 0, bytes);
105+
libc::memset(from_start.to_mut_ptr(), 0, bytes);
103106
}
104107

105108
Self::LOCAL_FORWARDING_BITS_SPEC.store_atomic::<JuliaVM, u8>(
@@ -160,7 +163,9 @@ impl ObjectModel<JuliaVM> for VMObjectModel {
160163

161164
#[inline(always)]
162165
fn address_to_ref(address: Address) -> ObjectReference {
163-
ObjectReference::from_raw_address(address)
166+
// `address` is a result of `ref_to_address(object)`, where `object` cannot be NULL.
167+
debug_assert!(!address.is_zero());
168+
unsafe { ObjectReference::from_raw_address_unchecked(address) }
164169
}
165170

166171
#[inline(always)]

mmtk/src/reference_glue.rs

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,40 +26,54 @@ impl Finalizable for JuliaFinalizableObject {
2626
self.set_reference(trace.trace_object(self.get_reference()));
2727
if !self.2 {
2828
// not a void pointer
29-
trace.trace_object(ObjectReference::from_raw_address(self.1));
29+
debug_assert!(!self.1.is_zero());
30+
let objref = unsafe { ObjectReference::from_raw_address_unchecked(self.1) };
31+
trace.trace_object(objref);
3032
}
3133
}
3234
}
3335

3436
pub struct VMReferenceGlue {}
3537

36-
impl ReferenceGlue<JuliaVM> for VMReferenceGlue {
37-
type FinalizableType = JuliaFinalizableObject;
38-
fn set_referent(reference: ObjectReference, referent: ObjectReference) {
38+
impl VMReferenceGlue {
39+
fn load_referent_raw(reference: ObjectReference) -> *mut mmtk_jl_value_t {
40+
let reff = reference.to_raw_address().to_ptr::<mmtk_jl_weakref_t>();
41+
unsafe { (*reff).value }
42+
}
43+
44+
fn set_referent_raw(reference: ObjectReference, referent_raw: *mut mmtk_jl_value_t) {
45+
let reff = reference.to_raw_address().to_mut_ptr::<mmtk_jl_weakref_t>();
3946
unsafe {
40-
let reff = reference.to_raw_address().to_mut_ptr::<mmtk_jl_weakref_t>();
41-
let referent_raw = referent.to_raw_address().to_mut_ptr::<mmtk_jl_value_t>();
4247
(*reff).value = referent_raw;
4348
}
4449
}
50+
}
4551

46-
fn clear_referent(new_reference: ObjectReference) {
47-
Self::set_referent(new_reference, unsafe {
48-
ObjectReference::from_raw_address(Address::from_mut_ptr(jl_nothing))
49-
});
52+
impl ReferenceGlue<JuliaVM> for VMReferenceGlue {
53+
type FinalizableType = JuliaFinalizableObject;
54+
55+
fn set_referent(reference: ObjectReference, referent: ObjectReference) {
56+
Self::set_referent_raw(reference, referent.to_raw_address().to_mut_ptr());
5057
}
5158

52-
fn get_referent(object: ObjectReference) -> ObjectReference {
53-
let referent;
54-
unsafe {
55-
let reff = object.to_raw_address().to_mut_ptr::<mmtk_jl_weakref_t>();
56-
referent = ObjectReference::from_raw_address(Address::from_mut_ptr((*reff).value));
57-
}
58-
referent
59+
fn clear_referent(new_reference: ObjectReference) {
60+
Self::set_referent_raw(new_reference, unsafe { jl_nothing });
5961
}
6062

61-
fn is_referent_cleared(referent: ObjectReference) -> bool {
62-
unsafe { referent.to_raw_address().to_mut_ptr() == jl_nothing }
63+
fn get_referent(object: ObjectReference) -> Option<ObjectReference> {
64+
let value = Self::load_referent_raw(object);
65+
if value == unsafe { jl_nothing } {
66+
return None;
67+
} else {
68+
debug_assert!(
69+
!value.is_null(),
70+
"A weak reference {} contains null referent pointer",
71+
object
72+
);
73+
let objref =
74+
unsafe { ObjectReference::from_raw_address_unchecked(Address::from_ptr(value)) };
75+
Some(objref)
76+
}
6377
}
6478

6579
fn enqueue_references(_references: &[ObjectReference], _tls: VMWorkerThread) {}

mmtk/src/scanning.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use mmtk::memory_manager;
44
use mmtk::scheduler::*;
55
use mmtk::util::opaque_pointer::*;
66
use mmtk::util::ObjectReference;
7+
use mmtk::vm::edge_shape::Edge;
78
use mmtk::vm::EdgeVisitor;
89
use mmtk::vm::ObjectTracerContext;
910
use mmtk::vm::RootsWorkFactory;
@@ -31,9 +32,7 @@ impl Scanning<JuliaVM> for VMScanning {
3132
fn visit_edge(&mut self, edge: JuliaVMEdge) {
3233
match edge {
3334
JuliaVMEdge::Simple(se) => {
34-
let slot = se.as_address();
35-
let object = unsafe { slot.load::<ObjectReference>() };
36-
if !object.is_null() {
35+
if let Some(object) = se.load() {
3736
self.buffer.push(object);
3837
}
3938
}
@@ -67,7 +66,11 @@ impl Scanning<JuliaVM> for VMScanning {
6766
Address::from_ptr(task)
6867
);
6968

70-
node_buffer.push(ObjectReference::from_raw_address(Address::from_ptr(task)));
69+
// unsafe: We checked `!task.is_null()` before.
70+
let objref = unsafe {
71+
ObjectReference::from_raw_address_unchecked(Address::from_ptr(task))
72+
};
73+
node_buffer.push(objref);
7174
}
7275
}
7376
};
@@ -88,9 +91,12 @@ impl Scanning<JuliaVM> for VMScanning {
8891
root_scan_task(ptls.next_task, true);
8992
root_scan_task(ptls.previous_task, true);
9093
if !ptls.previous_exception.is_null() {
91-
node_buffer.push(ObjectReference::from_raw_address(Address::from_mut_ptr(
92-
ptls.previous_exception,
93-
)));
94+
node_buffer.push(unsafe {
95+
// unsafe: We have just checked `ptls.previous_exception` is not null.
96+
ObjectReference::from_raw_address_unchecked(Address::from_mut_ptr(
97+
ptls.previous_exception,
98+
))
99+
});
94100
}
95101

96102
// Scan backtrace buffer: See gc_queue_bt_buf in gc.c

0 commit comments

Comments
 (0)