vmkit-core/vmkit/src/mm/scanning.rs

156 lines
4.9 KiB
Rust
Raw Normal View History

2025-02-09 09:21:48 +07:00
use std::marker::PhantomData;
use crate::{
mm::MemoryManager,
object_model::{
2025-02-09 21:05:13 +07:00
metadata::{Metadata, TraceCallback},
2025-02-09 09:21:48 +07:00
object::VMKitObject,
},
options::OPTIONS,
threading::{Thread, ThreadContext},
VirtualMachine,
};
use mmtk::{
vm::{slot::Slot, ObjectTracer, Scanning, SlotVisitor},
MutatorContext,
};
use super::{conservative_roots::ConservativeRoots, traits::ToSlot};
pub struct VMKitScanning<VM: VirtualMachine>(PhantomData<VM>);
impl<VM: VirtualMachine> Scanning<MemoryManager<VM>> for VMKitScanning<VM> {
fn forward_weak_refs(
_worker: &mut mmtk::scheduler::GCWorker<MemoryManager<VM>>,
_tracer_context: impl mmtk::vm::ObjectTracerContext<MemoryManager<VM>>,
) {
VM::forward_weak_refs(_worker, _tracer_context);
}
fn notify_initial_thread_scan_complete(partial_scan: bool, tls: mmtk::util::VMWorkerThread) {
VM::notify_initial_thread_scan_complete(partial_scan, tls);
}
fn prepare_for_roots_re_scanning() {
VM::prepare_for_roots_re_scanning();
}
fn process_weak_refs(
_worker: &mut mmtk::scheduler::GCWorker<MemoryManager<VM>>,
_tracer_context: impl mmtk::vm::ObjectTracerContext<MemoryManager<VM>>,
) -> bool {
VM::process_weak_refs(_worker, _tracer_context)
}
fn scan_object<
SV: mmtk::vm::SlotVisitor<<MemoryManager<VM> as mmtk::vm::VMBinding>::VMSlot>,
>(
_tls: mmtk::util::VMWorkerThread,
object: mmtk::util::ObjectReference,
slot_visitor: &mut SV,
) {
let object = VMKitObject::from(object);
let metadata = object.header::<VM>().metadata();
if metadata.is_object() {
slot_visitor.visit_slot(metadata.to_slot().expect("Object is not a slot"));
}
let gc_metadata = metadata.gc_metadata();
let trace = &gc_metadata.trace;
match trace {
2025-02-09 21:05:13 +07:00
TraceCallback::ScanSlots(fun) => {
2025-02-09 09:21:48 +07:00
fun(object, slot_visitor);
}
2025-02-09 21:05:13 +07:00
TraceCallback::None => (),
TraceCallback::TraceObject(_) => {
2025-02-09 09:21:48 +07:00
unreachable!("TraceObject is not supported for scanning");
}
}
}
fn scan_object_and_trace_edges<OT: mmtk::vm::ObjectTracer>(
_tls: mmtk::util::VMWorkerThread,
object: mmtk::util::ObjectReference,
object_tracer: &mut OT,
) {
let object = VMKitObject::from(object);
let metadata = object.header::<VM>().metadata();
let gc_metadata = metadata.gc_metadata();
let trace = &gc_metadata.trace;
match trace {
2025-02-09 21:05:13 +07:00
TraceCallback::ScanSlots(fun) => {
2025-02-09 09:21:48 +07:00
// wrap object tracer in a trait that implements SlotVisitor
// but actually traces the object directly.
let mut visitor = TraceSlotVisitor::<VM, OT> {
ot: object_tracer,
marker: PhantomData,
};
fun(object, &mut visitor);
}
2025-02-09 21:05:13 +07:00
TraceCallback::None => (),
TraceCallback::TraceObject(fun) => {
2025-02-09 09:21:48 +07:00
fun(object, object_tracer);
}
}
}
fn scan_roots_in_mutator_thread(
_tls: mmtk::util::VMWorkerThread,
mutator: &'static mut mmtk::Mutator<MemoryManager<VM>>,
mut factory: impl mmtk::vm::RootsWorkFactory<VM::Slot>,
) {
let tls = Thread::<VM>::from_vm_mutator_thread(mutator.get_tls());
tls.context.scan_roots(factory.clone());
if OPTIONS.conservative_stacks {
let mut croots = ConservativeRoots::new();
let bounds = *tls.stack_bounds();
2025-02-12 20:42:03 +07:00
unsafe { croots.add_span(bounds.origin(), tls.stack_pointer()) };
2025-02-09 09:21:48 +07:00
tls.context.scan_conservative_roots(&mut croots);
croots.add_to_factory(&mut factory);
}
}
fn scan_vm_specific_roots(
tls: mmtk::util::VMWorkerThread,
factory: impl mmtk::vm::RootsWorkFactory<VM::Slot>,
) {
VM::scan_vm_specific_roots(tls, factory);
}
2025-02-10 14:31:00 +07:00
#[inline(always)]
2025-02-09 09:21:48 +07:00
fn support_slot_enqueuing(
_tls: mmtk::util::VMWorkerThread,
object: mmtk::util::ObjectReference,
) -> bool {
let object = VMKitObject::from(object);
let metadata = object.header::<VM>().metadata();
2025-02-09 21:05:13 +07:00
matches!(metadata.gc_metadata().trace, TraceCallback::ScanSlots(_))
2025-02-09 09:21:48 +07:00
&& (!metadata.is_object() || metadata.to_slot().is_some())
}
fn supports_return_barrier() -> bool {
false
}
}
struct TraceSlotVisitor<'a, VM: VirtualMachine, OT: ObjectTracer> {
ot: &'a mut OT,
marker: PhantomData<VM>,
}
impl<'a, VM: VirtualMachine, OT: ObjectTracer> SlotVisitor<VM::Slot>
for TraceSlotVisitor<'a, VM, OT>
{
fn visit_slot(&mut self, slot: VM::Slot) {
let value = slot.load();
match value {
Some(object) => {
let object = self.ot.trace_object(object);
slot.store(object);
}
None => (),
}
}
}