mmtk/plan/marksweep/
mutator.rs

1use crate::plan::marksweep::MarkSweep;
2use crate::plan::mutator_context::create_allocator_mapping;
3use crate::plan::mutator_context::Mutator;
4use crate::plan::mutator_context::MutatorBuilder;
5use crate::plan::mutator_context::MutatorConfig;
6use crate::plan::mutator_context::ReservedAllocators;
7use crate::plan::mutator_context::SpaceMapping;
8use crate::plan::AllocationSemantics;
9use crate::plan::Plan;
10use crate::util::alloc::allocators::AllocatorSelector;
11use crate::util::{VMMutatorThread, VMWorkerThread};
12use crate::vm::VMBinding;
13use crate::MMTK;
14
15use enum_map::EnumMap;
16
17#[cfg(feature = "malloc_mark_sweep")]
18mod malloc_mark_sweep {
19    use crate::plan::mutator_context::{common_prepare_func, common_release_func};
20
21    use super::*;
22
23    // Do nothing for malloc mark sweep (malloc allocator)
24
25    pub fn ms_mutator_prepare<VM: VMBinding>(mutator: &mut Mutator<VM>, tls: VMWorkerThread) {
26        common_prepare_func(mutator, tls);
27    }
28    pub fn ms_mutator_release<VM: VMBinding>(mutator: &mut Mutator<VM>, tls: VMWorkerThread) {
29        common_release_func(mutator, tls);
30    }
31
32    // malloc mark sweep uses 1 malloc allocator
33
34    pub(crate) const RESERVED_ALLOCATORS: ReservedAllocators = ReservedAllocators {
35        n_malloc: 1,
36        ..ReservedAllocators::DEFAULT
37    };
38    lazy_static! {
39        pub static ref ALLOCATOR_MAPPING: EnumMap<AllocationSemantics, AllocatorSelector> = {
40            let mut map = create_allocator_mapping(RESERVED_ALLOCATORS, true);
41            map[AllocationSemantics::Default] = AllocatorSelector::Malloc(0);
42            map
43        };
44    }
45    pub(crate) fn create_space_mapping<VM: VMBinding>(
46        plan: &'static dyn Plan<VM = VM>,
47    ) -> Box<SpaceMapping<VM>> {
48        let ms = plan.downcast_ref::<MarkSweep<VM>>().unwrap();
49        Box::new({
50            let mut vec =
51                crate::plan::mutator_context::create_space_mapping(RESERVED_ALLOCATORS, true, plan);
52            vec.push((AllocatorSelector::Malloc(0), ms.ms_space()));
53            vec
54        })
55    }
56}
57
58#[cfg(not(feature = "malloc_mark_sweep"))]
59mod native_mark_sweep {
60    use super::*;
61    use crate::util::alloc::FreeListAllocator;
62
63    fn get_freelist_allocator_mut<VM: VMBinding>(
64        mutator: &mut Mutator<VM>,
65    ) -> &mut FreeListAllocator<VM> {
66        unsafe {
67            mutator
68                .allocators
69                .get_allocator_mut(mutator.config.allocator_mapping[AllocationSemantics::Default])
70        }
71        .downcast_mut::<FreeListAllocator<VM>>()
72        .unwrap()
73    }
74
75    // We forward calls to the allocator prepare and release
76
77    #[cfg(not(feature = "malloc_mark_sweep"))]
78    pub fn ms_mutator_prepare<VM: VMBinding>(mutator: &mut Mutator<VM>, tls: VMWorkerThread) {
79        use crate::plan::mutator_context::common_prepare_func;
80
81        get_freelist_allocator_mut::<VM>(mutator).prepare();
82        common_prepare_func(mutator, tls);
83    }
84
85    #[cfg(not(feature = "malloc_mark_sweep"))]
86    pub fn ms_mutator_release<VM: VMBinding>(mutator: &mut Mutator<VM>, tls: VMWorkerThread) {
87        use crate::plan::mutator_context::common_release_func;
88
89        get_freelist_allocator_mut::<VM>(mutator).release();
90
91        common_release_func(mutator, tls);
92    }
93
94    // native mark sweep uses 1 free list allocator
95
96    pub(crate) const RESERVED_ALLOCATORS: ReservedAllocators = ReservedAllocators {
97        n_free_list: 1,
98        ..ReservedAllocators::DEFAULT
99    };
100    lazy_static! {
101        pub static ref ALLOCATOR_MAPPING: EnumMap<AllocationSemantics, AllocatorSelector> = {
102            let mut map = create_allocator_mapping(RESERVED_ALLOCATORS, true);
103            map[AllocationSemantics::Default] = AllocatorSelector::FreeList(0);
104            map
105        };
106    }
107    pub(crate) fn create_space_mapping<VM: VMBinding>(
108        plan: &'static dyn Plan<VM = VM>,
109    ) -> Box<SpaceMapping<VM>> {
110        let ms = plan.downcast_ref::<MarkSweep<VM>>().unwrap();
111        Box::new({
112            let mut vec =
113                crate::plan::mutator_context::create_space_mapping(RESERVED_ALLOCATORS, true, plan);
114            vec.push((AllocatorSelector::FreeList(0), ms.ms_space()));
115            vec
116        })
117    }
118}
119
120#[cfg(feature = "malloc_mark_sweep")]
121pub use malloc_mark_sweep::*;
122
123#[cfg(not(feature = "malloc_mark_sweep"))]
124pub use native_mark_sweep::*;
125
126pub fn create_ms_mutator<VM: VMBinding>(
127    mutator_tls: VMMutatorThread,
128    mmtk: &'static MMTK<VM>,
129) -> Mutator<VM> {
130    let config = MutatorConfig {
131        allocator_mapping: &ALLOCATOR_MAPPING,
132        space_mapping: create_space_mapping(mmtk.get_plan()),
133        prepare_func: &ms_mutator_prepare,
134        release_func: &ms_mutator_release,
135    };
136
137    let builder = MutatorBuilder::new(mutator_tls, mmtk, config);
138    builder.build()
139}