vmkit-core/vmkit/src/lib.rs

148 lines
5.1 KiB
Rust
Raw Normal View History

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-12 20:42:03 +07:00
use mmtk::{MMTKBuilder, MMTK};
use threading::{initialize_threading, 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 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);
}
}
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
}
}