Skip to content

Commit 0790db6

Browse files
authored
Add a function to print object info from the space for debugging (#1269)
This PR adds a non-mangled function to print object information for debugging. I also added a section in the doc about the function.
1 parent c5ead72 commit 0790db6

File tree

12 files changed

+145
-0
lines changed

12 files changed

+145
-0
lines changed

docs/userguide/src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
- [Next Steps](portingguide/howto/next_steps.md)
3636
- [Debugging Tips](portingguide/debugging/prefix.md)
3737
- [Enabling Debug Assertions](portingguide/debugging/assertions.md)
38+
- [Print Object Info](portingguide/debugging/print_obj_info.md)
3839
- [Performance Tuning](portingguide/perf_tuning/prefix.md)
3940
- [Link Time Optimization](portingguide/perf_tuning/lto.md)
4041
- [Optimizing Allocation](portingguide/perf_tuning/alloc.md)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Print MMTk Object Information
2+
3+
MMTk provides a utility function to print object information for debugging, `crate::mmtk::mmtk_debug_print_object`.
4+
The function is marked as `#[no_mangle]`, making it suitable to be used in a debugger.
5+
6+
The following example shows how to use the function to print MMTk's object metadata before and after a single GC in `rr`.
7+
8+
Set up break points before and after a GC.
9+
10+
```console
11+
(rr) b stop_all_mutators
12+
Breakpoint 1 at 0x767cba8f74e8 (14 locations)
13+
(rr) b resume_mutators
14+
Breakpoint 2 at 0x767cba8f8908
15+
```
16+
17+
When the program stops, call `mmtk_debug_print_object`. We might need to
18+
set the language context in the debugger to `C` when we stop in a Rust frame.
19+
Then call `mmtk_debug_print_object` with the interested object.
20+
21+
```console
22+
(rr) set language c
23+
(rr) call mmtk_debug_print_object_info(0x200fffed9f0)
24+
In immix:
25+
marked = false
26+
line marked = false
27+
block state = Unmarked
28+
forwarding bits = 0, forwarding pointer = None
29+
vo bit = true
30+
```

src/mmtk.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,3 +597,32 @@ impl<VM: VMBinding> MMTK<VM> {
597597
.initialize_object_metadata(object, false)
598598
}
599599
}
600+
601+
/// A non-mangled function to print object information for debugging purposes. This function can be directly
602+
/// called from a debugger.
603+
#[no_mangle]
604+
pub fn mmtk_debug_print_object(object: crate::util::ObjectReference) {
605+
// If the address is unmapped, we cannot access its metadata. Just quit.
606+
if !object.to_raw_address().is_mapped() {
607+
println!("{} is not mapped in MMTk", object);
608+
return;
609+
}
610+
611+
// If the address is not aligned to the object reference size, it is not an object reference.
612+
if !object
613+
.to_raw_address()
614+
.is_aligned_to(crate::util::ObjectReference::ALIGNMENT)
615+
{
616+
println!(
617+
"{} is not properly aligned. It is not an object reference.",
618+
object
619+
);
620+
}
621+
622+
// Forward to the space
623+
let sft = SFT_MAP.get_checked(object.to_raw_address());
624+
// Print the space name
625+
println!("In {}:", sft.name());
626+
// Print object information
627+
sft.debug_print_object_info(object);
628+
}

src/policy/copyspace.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@ impl<VM: VMBinding> SFT for CopySpace<VM> {
100100
let worker = worker.into_mut::<VM>();
101101
self.trace_object(queue, object, self.common.copy, worker)
102102
}
103+
104+
fn debug_print_object_info(&self, object: ObjectReference) {
105+
object_forwarding::debug_print_object_forwarding_info::<VM>(object);
106+
self.common.debug_print_object_global_info(object);
107+
}
103108
}
104109

105110
impl<VM: VMBinding> Space<VM> for CopySpace<VM> {

src/policy/immix/immixspace.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,20 @@ impl<VM: VMBinding> SFT for ImmixSpace<VM> {
158158
) -> ObjectReference {
159159
panic!("We do not use SFT to trace objects for Immix. sft_trace_object() cannot be used.")
160160
}
161+
162+
fn debug_print_object_info(&self, object: ObjectReference) {
163+
println!("marked = {}", self.is_marked(object));
164+
println!(
165+
"line marked = {}",
166+
Line::from_unaligned_address(object.to_raw_address()).is_marked(self.mark_state)
167+
);
168+
println!(
169+
"block state = {:?}",
170+
Block::from_unaligned_address(object.to_raw_address()).get_state()
171+
);
172+
object_forwarding::debug_print_object_forwarding_info::<VM>(object);
173+
self.common.debug_print_object_global_info(object);
174+
}
161175
}
162176

163177
impl<VM: VMBinding> Space<VM> for ImmixSpace<VM> {

src/policy/largeobjectspace.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,12 @@ impl<VM: VMBinding> SFT for LargeObjectSpace<VM> {
145145
) -> ObjectReference {
146146
self.trace_object(queue, object)
147147
}
148+
149+
fn debug_print_object_info(&self, object: ObjectReference) {
150+
println!("marked = {}", self.test_mark_bit(object, self.mark_state));
151+
println!("nursery = {}", self.is_in_nursery(object));
152+
self.common.debug_print_object_global_info(object);
153+
}
148154
}
149155

150156
impl<VM: VMBinding> Space<VM> for LargeObjectSpace<VM> {

src/policy/markcompactspace.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,15 @@ impl<VM: VMBinding> SFT for MarkCompactSpace<VM> {
102102
// Depending on which trace it is, we should manually call either trace_mark or trace_forward.
103103
panic!("sft_trace_object() cannot be used with mark compact space")
104104
}
105+
106+
fn debug_print_object_info(&self, object: ObjectReference) {
107+
println!("marked = {}", MarkCompactSpace::<VM>::is_marked(object));
108+
println!(
109+
"head forwarding pointer = {:?}",
110+
MarkCompactSpace::<VM>::get_header_forwarding_pointer(object)
111+
);
112+
self.common.debug_print_object_global_info(object);
113+
}
105114
}
106115

107116
impl<VM: VMBinding> Space<VM> for MarkCompactSpace<VM> {

src/policy/sft.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,12 @@ pub trait SFT {
101101
object: ObjectReference,
102102
worker: GCWorkerMutRef,
103103
) -> ObjectReference;
104+
105+
/// Print debug info for the object. The implementer should print one line at a time so in case of an unexpected error,
106+
/// we still print something.
107+
fn debug_print_object_info(&self, _object: ObjectReference) {
108+
println!("This policy does not implement debug_print_object_info.");
109+
}
104110
}
105111

106112
// Create erased VM refs for these types that will be used in `sft_trace_object()`.

src/policy/space.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,22 @@ impl<VM: VMBinding> CommonSpace<VM> {
723723
},
724724
}
725725
}
726+
727+
pub(crate) fn debug_print_object_global_info(&self, object: ObjectReference) {
728+
#[cfg(feature = "vo_bit")]
729+
println!(
730+
"vo bit = {}",
731+
crate::util::metadata::vo_bit::is_vo_bit_set(object)
732+
);
733+
if self.needs_log_bit {
734+
use crate::vm::object_model::ObjectModel;
735+
use std::sync::atomic::Ordering;
736+
println!(
737+
"log bit = {}",
738+
VM::VMObjectModel::GLOBAL_LOG_BIT_SPEC.is_unlogged::<VM>(object, Ordering::Relaxed),
739+
);
740+
}
741+
}
726742
}
727743

728744
fn get_frac_available(frac: f32) -> usize {

src/util/object_forwarding.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,3 +233,16 @@ pub(super) fn forwarding_bits_offset_in_forwarding_pointer<VM: VMBinding>() -> O
233233
pub(super) fn forwarding_bits_offset_in_forwarding_pointer<VM: VMBinding>() -> Option<isize> {
234234
unimplemented!()
235235
}
236+
237+
pub(crate) fn debug_print_object_forwarding_info<VM: VMBinding>(object: ObjectReference) {
238+
let forwarding_bits = get_forwarding_status::<VM>(object);
239+
println!(
240+
"forwarding bits = {:?}, forwarding pointer = {:?}",
241+
forwarding_bits,
242+
if state_is_forwarded_or_being_forwarded(forwarding_bits) {
243+
Some(read_forwarding_pointer::<VM>(object))
244+
} else {
245+
None
246+
}
247+
)
248+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// GITHUB-CI: MMTK_PLAN=all
2+
3+
use super::mock_test_prelude::*;
4+
5+
#[test]
6+
pub fn debug_print_object_info() {
7+
with_mockvm(
8+
default_setup,
9+
|| {
10+
let fixture = SingleObject::create();
11+
crate::mmtk::mmtk_debug_print_object(fixture.objref);
12+
},
13+
no_cleanup,
14+
)
15+
}

src/vm/tests/mock_tests/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ mod mock_test_allocator_info;
3535
mod mock_test_barrier_slow_path_assertion;
3636
#[cfg(feature = "is_mmtk_object")]
3737
mod mock_test_conservatism;
38+
mod mock_test_debug_get_object_info;
3839
#[cfg(target_os = "linux")]
3940
mod mock_test_handle_mmap_conflict;
4041
mod mock_test_handle_mmap_oom;

0 commit comments

Comments
 (0)