2025-02-13 17:24:08 +07:00
use std ::{
marker ::PhantomData ,
sync ::atomic ::{ AtomicBool , AtomicUsize } ,
} ;
2025-02-09 09:21:48 +07:00
use mm ::{ aslr ::aslr_vm_layout , traits ::SlotExtra , MemoryManager } ;
2025-02-13 22:32:44 +07:00
use mmtk ::{ vm ::slot ::MemorySlice , MMTKBuilder , MMTK } ;
use object_model ::object ::VMKitObject ;
use threading ::{ initialize_threading , Thread , ThreadManager } ;
2025-02-09 09:21:48 +07:00
2025-02-12 20:42:03 +07:00
pub mod machine_context ;
2025-02-09 09:21:48 +07:00
pub mod mm ;
pub mod object_model ;
pub mod options ;
2025-02-13 17:24:08 +07:00
pub mod platform ;
2025-02-12 20:42:03 +07:00
pub mod semaphore ;
2025-02-09 09:21:48 +07:00
pub mod sync ;
pub mod threading ;
2025-02-13 17:24:08 +07:00
#[ cfg(feature = " uncooperative " ) ]
2025-02-12 20:42:03 +07:00
pub mod bdwgc_shim ;
2025-02-09 09:21:48 +07:00
pub trait VirtualMachine : Sized + 'static + Send + Sync {
type ThreadContext : threading ::ThreadContext < Self > ;
type BlockAdapterList : threading ::BlockAdapterList < Self > ;
type Metadata : object_model ::metadata ::Metadata < Self > ;
type Slot : SlotExtra ;
2025-02-13 22:32:44 +07:00
type MemorySlice : MemorySlice < SlotType = Self ::Slot > ;
2025-02-13 17:24:08 +07:00
const ALIGNMENT_VALUE : u32 = 0xdead_beef ;
const MAX_ALIGNMENT : usize = 32 ;
2025-02-09 21:05:13 +07:00
const MIN_ALIGNMENT : usize = 8 ;
2025-02-09 09:21:48 +07:00
/// Does this VM use conservative tracing? If `true` then VM can
/// query VO-bit (valid-object bit) to check if an object is live
/// during tracing work.
///
/// Note that this is distinct from conservative stack scanning. When
/// collecting roots VO-bits are always available.
///
/// Read more: [ObjectModel::NEED_VO_BITS_DURING_TRACING](mmtk::vm::ObjectModel::NEED_VO_BITS_DURING_TRACING).
///
/// # Note
///
/// - [`InternalPointer`](mm::conservative_roots::InternalPointer) can only be used when this is `true`.
#[ cfg(feature = " cooperative " ) ]
const CONSERVATIVE_TRACING : bool = false ;
/// Get currently active VM instance.
///
/// # Notes
///
/// At the moment we assume only one active VM per process. This can be changed in the future once MMTk supports
/// instances. In that case this function can return active VM for current thread instead of one global instance.
fn get ( ) -> & 'static Self ;
fn vmkit ( & self ) -> & VMKit < Self > ;
/// Prepare for another round of root scanning in the same GC.
///
/// For details: [Scanning::prepare_for_roots_re_scanning](mmtk::vm::Scanning::prepare_for_roots_re_scanning)
fn prepare_for_roots_re_scanning ( ) ;
/// MMTk calls this method at the first time during a collection that thread's stacks have been scanned. This can be used (for example) to clean up obsolete compiled methods that are no longer being executed.
fn notify_initial_thread_scan_complete ( partial_scan : bool , tls : mmtk ::util ::VMWorkerThread ) ;
/// Process weak references.
///
/// This function is called after a transitive closure is completed.
///
/// For details: [Scanning::process_weak_refs](mmtk::vm::Scanning::process_weak_refs)
fn process_weak_refs (
_worker : & mut mmtk ::scheduler ::GCWorker < MemoryManager < Self > > ,
_tracer_context : impl mmtk ::vm ::ObjectTracerContext < MemoryManager < Self > > ,
) -> bool {
false
}
fn forward_weak_refs (
_worker : & mut mmtk ::scheduler ::GCWorker < MemoryManager < Self > > ,
_tracer_context : impl mmtk ::vm ::ObjectTracerContext < MemoryManager < Self > > ,
) ;
/// Scan one mutator for stack roots.
///
/// For details: [Scanning::scan_roots_in_mutator_thread](mmtk::vm::Scanning::scan_roots_in_mutator_thread)
fn scan_roots_in_mutator_thread (
tls : mmtk ::util ::VMWorkerThread ,
mutator : & 'static mut mmtk ::Mutator < MemoryManager < Self > > ,
factory : impl mmtk ::vm ::RootsWorkFactory < < MemoryManager < Self > as mmtk ::vm ::VMBinding > ::VMSlot > ,
) ;
/// Scan VM-specific roots.
///
/// For details: [Scanning::scan_vm_specific_roots](mmtk::vm::Scanning::scan_vm_specific_roots)
fn scan_vm_specific_roots (
tls : mmtk ::util ::VMWorkerThread ,
factory : impl mmtk ::vm ::RootsWorkFactory < < MemoryManager < Self > as mmtk ::vm ::VMBinding > ::VMSlot > ,
) ;
/// A hook for the VM to do work after forwarding objects.
fn post_forwarding ( tls : mmtk ::util ::VMWorkerThread ) {
let _ = tls ;
}
fn schedule_finalization ( tls : mmtk ::util ::VMWorkerThread ) {
let _ = tls ;
}
fn vm_live_bytes ( ) -> usize {
0
}
fn out_of_memory ( tls : mmtk ::util ::VMThread , err_kind : mmtk ::util ::alloc ::AllocationError ) {
let _ = tls ;
let _ = err_kind ;
eprintln! ( " Out of memory: {:?} " , err_kind ) ;
std ::process ::exit ( 1 ) ;
}
2025-02-13 22:32:44 +07:00
/// Weak and soft references always clear the referent before enqueueing.
fn clear_referent ( new_reference : VMKitObject ) {
let _ = new_reference ;
unimplemented! ( )
}
/// Get the referent from a weak reference object.
fn get_referent ( object : VMKitObject ) -> VMKitObject {
let _ = object ;
unimplemented! ( )
}
/// Set the referent in a weak reference object.
fn set_referent ( reff : VMKitObject , referent : VMKitObject ) {
let _ = reff ;
let _ = referent ;
unimplemented! ( )
}
/// For weak reference types, if the referent is cleared during GC, the reference
/// will be added to a queue, and MMTk will call this method to inform
/// the VM about the changes for those references. This method is used
/// to implement Java's ReferenceQueue.
/// Note that this method is called for each type of weak references during GC, and
/// the references slice will be cleared after this call is returned. That means
/// MMTk will no longer keep these references alive once this method is returned.
fn enqueue_references ( references : impl Iterator < Item = VMKitObject > , tls : & Thread < Self > ) {
let _ = references ;
let _ = tls ;
unimplemented! ( )
}
2025-02-09 09:21:48 +07:00
}
pub struct VMKit < VM : VirtualMachine > {
thread_manager : ThreadManager < VM > ,
pub mmtk : MMTK < MemoryManager < VM > > ,
pub ( crate ) collector_started : AtomicBool ,
marker : PhantomData < VM > ,
2025-02-13 16:45:30 +07:00
gc_disabled_depth : AtomicUsize ,
2025-02-09 09:21:48 +07:00
}
impl < VM : VirtualMachine > VMKit < VM > {
2025-02-12 20:42:03 +07:00
pub fn new ( builder : & mut MMTKBuilder ) -> Self {
initialize_threading ::< VM > ( ) ;
2025-02-09 09:21:48 +07:00
let vm_layout = aslr_vm_layout ( & mut builder . options ) ;
builder . set_vm_layout ( vm_layout ) ;
VMKit {
mmtk : builder . build ( ) ,
marker : PhantomData ,
collector_started : AtomicBool ::new ( false ) ,
thread_manager : ThreadManager ::new ( ) ,
2025-02-13 16:45:30 +07:00
gc_disabled_depth : AtomicUsize ::new ( 0 ) ,
2025-02-09 09:21:48 +07:00
}
}
pub ( crate ) fn are_collector_threads_spawned ( & self ) -> bool {
self . collector_started . load ( atomic ::Ordering ::Relaxed )
}
pub fn thread_manager ( & self ) -> & ThreadManager < VM > {
& self . thread_manager
}
}