pub type TraceCallback = dyn FnMut(*mut u8);
pub trait Trace {
fn trace(&self, visitor: &mut dyn FnMut(*mut u8));
}
#[inline]
pub fn trace_nanboxed_bits(bits: u64, visitor: &mut dyn FnMut(*mut u8)) {
const TAG_BASE: u64 = 0xFFF8_0000_0000_0000;
const PAYLOAD_MASK: u64 = 0x0000_FFFF_FFFF_FFFF;
const TAG_SHIFT: u32 = 48;
const TAG_MASK: u64 = 0x0007_0000_0000_0000;
const TAG_HEAP: u64 = 0b000;
let is_tagged = (bits & TAG_BASE) == TAG_BASE;
if is_tagged {
let tag = (bits & TAG_MASK) >> TAG_SHIFT;
if tag == TAG_HEAP {
const HEAP_PTR_MASK: u64 = !1;
let ptr = (bits & PAYLOAD_MASK & HEAP_PTR_MASK) as *mut u8;
if !ptr.is_null() {
visitor(ptr);
}
}
}
}
#[inline]
pub fn trace_heap_slot(bits: u64, visitor: &mut dyn FnMut(*mut u8)) {
let ptr = bits as *mut u8;
if !ptr.is_null() {
visitor(ptr);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_trace_non_heap_is_noop() {
let i48_bits: u64 = 0xFFF8_0000_0000_0001 | (0b001 << 48); let mut found = false;
trace_nanboxed_bits(i48_bits, &mut |_| found = true);
assert!(!found);
}
#[test]
fn test_trace_f64_is_noop() {
let f64_bits = 3.14_f64.to_bits();
let mut found = false;
trace_nanboxed_bits(f64_bits, &mut |_| found = true);
assert!(!found);
}
}