mmtk/util/analysis/
mod.rs

1use crate::scheduler::*;
2use crate::util::statistics::stats::Stats;
3use crate::vm::VMBinding;
4use crate::MMTK;
5use std::sync::{Arc, Mutex};
6
7pub mod gc_count;
8pub mod obj_num;
9pub mod obj_size;
10
11use self::gc_count::GcCounter;
12use self::obj_num::ObjectCounter;
13use self::obj_size::PerSizeClassObjectCounter;
14
15///
16/// This trait exposes hooks for developers to implement their own analysis routines.
17///
18/// Most traits would want to hook into the `Stats` and counters provided by the MMTk
19/// framework that are exposed to the Harness.
20///
21/// The arguments for the hooks should be sufficient, however, if one wishes to add
22/// other arguments, then they can create an analysis routine specific function and
23/// invoke it in its respective place.
24///
25pub trait RtAnalysis<VM: VMBinding> {
26    fn alloc_hook(&mut self, _size: usize, _align: usize, _offset: usize) {}
27    fn gc_hook(&mut self, _mmtk: &'static MMTK<VM>) {}
28    fn set_running(&mut self, running: bool);
29}
30
31#[derive(Default)]
32pub struct GcHookWork;
33
34impl<VM: VMBinding> GCWork<VM> for GcHookWork {
35    fn do_work(&mut self, _worker: &mut GCWorker<VM>, mmtk: &'static MMTK<VM>) {
36        mmtk.analysis_manager.gc_hook(mmtk);
37    }
38}
39
40// The AnalysisManager essentially acts as a proxy for all analysis routines made.
41// The framwework uses the AnalysisManager to call hooks for analysis routines.
42#[derive(Default)]
43pub struct AnalysisManager<VM: VMBinding> {
44    routines: Mutex<Vec<Arc<Mutex<dyn RtAnalysis<VM> + Send>>>>,
45}
46
47impl<VM: VMBinding> AnalysisManager<VM> {
48    pub fn new(stats: Arc<Stats>) -> Self {
49        let mut manager = AnalysisManager {
50            routines: Mutex::new(vec![]),
51        };
52        manager.initialize_routines(stats);
53        manager
54    }
55
56    // Initializing all routines. If you want to add a new routine, here is the place
57    // to do so
58    fn initialize_routines(&mut self, stats: Arc<Stats>) {
59        let ctr = stats.new_event_counter("obj.num", true, true);
60        let gc_ctr = stats.new_event_counter("gc.num", true, true);
61        let obj_num = Arc::new(Mutex::new(ObjectCounter::new(true, ctr)));
62        let gc_count = Arc::new(Mutex::new(GcCounter::new(true, gc_ctr)));
63        let obj_size = Arc::new(Mutex::new(PerSizeClassObjectCounter::new(true, stats)));
64        self.add_analysis_routine(obj_num);
65        self.add_analysis_routine(gc_count);
66        self.add_analysis_routine(obj_size);
67    }
68
69    pub fn add_analysis_routine(&mut self, routine: Arc<Mutex<dyn RtAnalysis<VM> + Send>>) {
70        let mut routines = self.routines.lock().unwrap();
71        routines.push(routine.clone());
72    }
73
74    pub fn alloc_hook(&self, size: usize, align: usize, offset: usize) {
75        let routines = self.routines.lock().unwrap();
76        for r in &*routines {
77            r.lock().unwrap().alloc_hook(size, align, offset);
78        }
79    }
80
81    pub fn gc_hook(&self, mmtk: &'static MMTK<VM>) {
82        let routines = self.routines.lock().unwrap();
83        for r in &*routines {
84            r.lock().unwrap().gc_hook(mmtk);
85        }
86    }
87}