143 lines
5 KiB
Rust
143 lines
5 KiB
Rust
use std::{marker::PhantomData, sync::atomic::{AtomicBool, AtomicUsize}};
|
|
|
|
use mm::{aslr::aslr_vm_layout, traits::SlotExtra, MemoryManager};
|
|
use mmtk::{MMTKBuilder, MMTK};
|
|
use threading::{initialize_threading, ThreadManager};
|
|
|
|
pub mod machine_context;
|
|
pub mod mm;
|
|
pub mod object_model;
|
|
pub mod options;
|
|
pub mod semaphore;
|
|
pub mod sync;
|
|
pub mod threading;
|
|
pub mod platform;
|
|
|
|
#[cfg(feature="uncooperative")]
|
|
pub mod bdwgc_shim;
|
|
|
|
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;
|
|
|
|
const MAX_ALIGNMENT: usize = 16;
|
|
const MIN_ALIGNMENT: usize = 8;
|
|
|
|
/// 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>,
|
|
gc_disabled_depth: AtomicUsize,
|
|
}
|
|
|
|
impl<VM: VirtualMachine> VMKit<VM> {
|
|
pub fn new(builder: &mut MMTKBuilder) -> Self {
|
|
initialize_threading::<VM>();
|
|
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(),
|
|
gc_disabled_depth: AtomicUsize::new(0),
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|
|
}
|