use crate::plan::Plan;
use crate::policy::sft_map::SFTMapType;
use crate::scheduler::GCWorkScheduler;
#[cfg(feature = "extreme_assertions")]
use crate::util::edge_logger::EdgeLogger;
use crate::util::finalizable_processor::FinalizableProcessor;
use crate::util::heap::layout::heap_layout::Mmapper;
use crate::util::heap::layout::heap_layout::VMMap;
use crate::util::heap::layout::map::Map;
use crate::util::opaque_pointer::*;
use crate::util::options::Options;
use crate::util::reference_processor::ReferenceProcessors;
#[cfg(feature = "sanity")]
use crate::util::sanity::sanity_checker::SanityChecker;
use crate::vm::ReferenceGlue;
use crate::vm::VMBinding;
use std::default::Default;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::sync::Mutex;
lazy_static! {
pub static ref VM_MAP: VMMap = VMMap::new();
pub static ref MMAPPER: Mmapper = Mmapper::new();
}
use crate::util::rust_util::InitializeOnce;
pub static SFT_MAP: InitializeOnce<SFTMapType<'static>> = InitializeOnce::new();
pub struct MMTKBuilder {
pub options: Options,
}
impl MMTKBuilder {
pub fn new() -> Self {
MMTKBuilder {
options: Options::default(),
}
}
pub fn set_option(&mut self, name: &str, val: &str) -> bool {
self.options.set_from_command_line(name, val)
}
pub fn set_options_bulk_by_str(&mut self, options: &str) -> bool {
self.options.set_bulk_from_command_line(options)
}
pub fn build<VM: VMBinding>(&self) -> MMTK<VM> {
MMTK::new(Arc::new(self.options.clone()))
}
}
impl Default for MMTKBuilder {
fn default() -> Self {
Self::new()
}
}
pub struct MMTK<VM: VMBinding> {
pub(crate) options: Arc<Options>,
pub(crate) plan: Box<dyn Plan<VM = VM>>,
pub(crate) reference_processors: ReferenceProcessors,
pub(crate) finalizable_processor:
Mutex<FinalizableProcessor<<VM::VMReferenceGlue as ReferenceGlue<VM>>::FinalizableType>>,
pub(crate) scheduler: Arc<GCWorkScheduler<VM>>,
#[cfg(feature = "sanity")]
pub(crate) sanity_checker: Mutex<SanityChecker<VM::VMEdge>>,
#[cfg(feature = "extreme_assertions")]
pub(crate) edge_logger: EdgeLogger<VM::VMEdge>,
inside_harness: AtomicBool,
}
impl<VM: VMBinding> MMTK<VM> {
pub fn new(options: Arc<Options>) -> Self {
SFT_MAP.initialize_once(&SFTMapType::new);
let num_workers = if cfg!(feature = "single_worker") {
1
} else {
*options.threads
};
let scheduler = GCWorkScheduler::new(num_workers, (*options.thread_affinity).clone());
let plan = crate::plan::create_plan(
*options.plan,
&VM_MAP,
&MMAPPER,
options.clone(),
scheduler.clone(),
);
VM_MAP.boot();
VM_MAP.finalize_static_space_map(
plan.base().heap.get_discontig_start(),
plan.base().heap.get_discontig_end(),
);
MMTK {
options,
plan,
reference_processors: ReferenceProcessors::new(),
finalizable_processor: Mutex::new(FinalizableProcessor::<
<VM::VMReferenceGlue as ReferenceGlue<VM>>::FinalizableType,
>::new()),
scheduler,
#[cfg(feature = "sanity")]
sanity_checker: Mutex::new(SanityChecker::new()),
inside_harness: AtomicBool::new(false),
#[cfg(feature = "extreme_assertions")]
edge_logger: EdgeLogger::new(),
}
}
pub fn harness_begin(&self, tls: VMMutatorThread) {
self.plan.handle_user_collection_request(tls, true);
self.inside_harness.store(true, Ordering::SeqCst);
self.plan.base().stats.start_all();
self.scheduler.enable_stat();
}
pub fn harness_end(&'static self) {
self.plan.base().stats.stop_all(self);
self.inside_harness.store(false, Ordering::SeqCst);
}
pub fn get_plan(&self) -> &dyn Plan<VM = VM> {
self.plan.as_ref()
}
#[inline(always)]
pub fn get_options(&self) -> &Options {
&self.options
}
}