Skip to main content

shape_gc/
fixup.rs

1//! Pointer fixup after relocation.
2//!
3//! After objects are relocated and the forwarding table is populated,
4//! we must update all pointers (in live objects and root set) to point
5//! to the new locations.
6
7use crate::region::Region;
8use crate::relocator::ForwardingTable;
9
10/// Fix up all pointers in the root set using the forwarding table.
11///
12/// `trace_roots` should iterate all root pointers. For each pointer that
13/// has a forwarding entry, update it to the new address.
14pub fn fixup_roots(
15    forwarding: &ForwardingTable,
16    trace_roots: &mut dyn FnMut(&mut dyn FnMut(*mut u8, &mut *mut u8)),
17) {
18    trace_roots(&mut |old_ptr, slot| {
19        if let Some(new_ptr) = forwarding.lookup(old_ptr) {
20            *slot = new_ptr;
21        }
22    });
23}
24
25/// Fix up pointers within all live objects in a region.
26///
27/// For each live object, trace its inner pointers and update any that
28/// appear in the forwarding table.
29pub fn fixup_region(region: &mut Region, _forwarding: &ForwardingTable) {
30    region.for_each_object_mut(|header, _obj_ptr| {
31        // Only process live objects
32        if header.size == 0 {
33            return;
34        }
35
36        // Walk the object's pointer fields and update forwarded ones.
37        // For now, this is a placeholder — real implementation needs type-specific
38        // tracing via HeapKind to know which fields are pointers.
39        // The actual fixup happens via the Trace trait in the VM integration.
40    });
41}
42
43/// Fix up a single raw pointer if it has a forwarding entry.
44#[inline]
45pub fn fixup_ptr(ptr: *mut u8, forwarding: &ForwardingTable) -> *mut u8 {
46    if let Some(new) = forwarding.lookup(ptr) {
47        new
48    } else {
49        ptr
50    }
51}
52
53/// Fix up a NaN-boxed u64 value in-place if it contains a forwarded heap pointer.
54#[inline]
55pub fn fixup_nanboxed_bits(bits: &mut u64, forwarding: &ForwardingTable) {
56    const TAG_BASE: u64 = 0xFFF8_0000_0000_0000;
57    const PAYLOAD_MASK: u64 = 0x0000_FFFF_FFFF_FFFF;
58    const TAG_MASK: u64 = 0x0007_0000_0000_0000;
59    const TAG_SHIFT: u32 = 48;
60    const TAG_HEAP: u64 = 0b000;
61
62    let is_tagged = (*bits & TAG_BASE) == TAG_BASE;
63    if !is_tagged {
64        return;
65    }
66
67    let tag = (*bits & TAG_MASK) >> TAG_SHIFT;
68    if tag != TAG_HEAP {
69        return;
70    }
71
72    let old_ptr = (*bits & PAYLOAD_MASK) as *mut u8;
73    if old_ptr.is_null() {
74        return;
75    }
76
77    if let Some(new_ptr) = forwarding.lookup(old_ptr) {
78        let new_payload = (new_ptr as u64) & PAYLOAD_MASK;
79        *bits = (*bits & !PAYLOAD_MASK) | new_payload;
80    }
81}