mmtk/plan/concurrent/immix/
mutator.rs

1use crate::plan::barriers::SATBBarrier;
2use crate::plan::concurrent::barrier::SATBBarrierSemantics;
3use crate::plan::concurrent::immix::ConcurrentImmix;
4use crate::plan::concurrent::Pause;
5use crate::plan::mutator_context::create_allocator_mapping;
6use crate::plan::mutator_context::create_space_mapping;
7
8use crate::plan::mutator_context::Mutator;
9use crate::plan::mutator_context::MutatorBuilder;
10use crate::plan::mutator_context::MutatorConfig;
11use crate::plan::mutator_context::ReservedAllocators;
12use crate::plan::AllocationSemantics;
13use crate::util::alloc::allocators::AllocatorSelector;
14use crate::util::alloc::ImmixAllocator;
15use crate::util::opaque_pointer::{VMMutatorThread, VMWorkerThread};
16use crate::vm::VMBinding;
17use crate::MMTK;
18use enum_map::EnumMap;
19
20type BarrierSemanticsType<VM> =
21    SATBBarrierSemantics<VM, ConcurrentImmix<VM>, { crate::policy::immix::TRACE_KIND_FAST }>;
22
23type BarrierType<VM> = SATBBarrier<BarrierSemanticsType<VM>>;
24
25pub fn concurrent_immix_mutator_release<VM: VMBinding>(
26    mutator: &mut Mutator<VM>,
27    _tls: VMWorkerThread,
28) {
29    // Release is not scheduled for initial mark pause
30    let current_pause = mutator.plan.concurrent().unwrap().current_pause().unwrap();
31    debug_assert_ne!(current_pause, Pause::InitialMark);
32
33    let immix_allocator = unsafe {
34        mutator
35            .allocators
36            .get_allocator_mut(mutator.config.allocator_mapping[AllocationSemantics::Default])
37    }
38    .downcast_mut::<ImmixAllocator<VM>>()
39    .unwrap();
40    immix_allocator.reset();
41
42    // NonMoving space also should give up its bump region at every pause, or it keeps allocating
43    // into lines that were not marked live for the current marking phase.
44    mutator.reset_nonmoving_allocator();
45
46    // Deactivate SATB
47    if current_pause == Pause::Full || current_pause == Pause::FinalMark {
48        debug!("Deactivate SATB barrier active for {:?}", mutator as *mut _);
49        mutator
50            .barrier
51            .downcast_mut::<BarrierType<VM>>()
52            .unwrap()
53            .set_weak_ref_barrier_enabled(false);
54    }
55}
56
57pub fn concurent_immix_mutator_prepare<VM: VMBinding>(
58    mutator: &mut Mutator<VM>,
59    _tls: VMWorkerThread,
60) {
61    // Prepare is not scheduled for final mark pause
62    let current_pause = mutator.plan.concurrent().unwrap().current_pause().unwrap();
63    debug_assert_ne!(current_pause, Pause::FinalMark);
64
65    let immix_allocator = unsafe {
66        mutator
67            .allocators
68            .get_allocator_mut(mutator.config.allocator_mapping[AllocationSemantics::Default])
69    }
70    .downcast_mut::<ImmixAllocator<VM>>()
71    .unwrap();
72    immix_allocator.reset();
73
74    // NonMoving space also should give up its bump region at every pause, or it keeps allocating
75    // into lines that were not marked live for the current marking phase.
76    mutator.reset_nonmoving_allocator();
77
78    // Activate SATB
79    if current_pause == Pause::InitialMark {
80        debug!("Activate SATB barrier active for {:?}", mutator as *mut _);
81        mutator
82            .barrier
83            .downcast_mut::<BarrierType<VM>>()
84            .unwrap()
85            .set_weak_ref_barrier_enabled(true);
86    }
87}
88
89pub(in crate::plan) const RESERVED_ALLOCATORS: ReservedAllocators = ReservedAllocators {
90    n_immix: 1,
91    ..ReservedAllocators::DEFAULT
92};
93
94lazy_static! {
95    pub static ref ALLOCATOR_MAPPING: EnumMap<AllocationSemantics, AllocatorSelector> = {
96        let mut map = create_allocator_mapping(RESERVED_ALLOCATORS, true);
97        map[AllocationSemantics::Default] = AllocatorSelector::Immix(0);
98        map
99    };
100}
101
102pub fn create_concurrent_immix_mutator<VM: VMBinding>(
103    mutator_tls: VMMutatorThread,
104    mmtk: &'static MMTK<VM>,
105) -> Mutator<VM> {
106    let immix = mmtk
107        .get_plan()
108        .downcast_ref::<ConcurrentImmix<VM>>()
109        .unwrap();
110    let config = MutatorConfig {
111        allocator_mapping: &ALLOCATOR_MAPPING,
112        space_mapping: Box::new({
113            let mut vec = create_space_mapping(RESERVED_ALLOCATORS, true, immix);
114            vec.push((AllocatorSelector::Immix(0), &immix.immix_space));
115            vec
116        }),
117
118        prepare_func: &concurent_immix_mutator_prepare,
119        release_func: &concurrent_immix_mutator_release,
120    };
121
122    let builder = MutatorBuilder::new(mutator_tls, mmtk, config);
123    let mut mutator = builder
124        .barrier(Box::new(SATBBarrier::new(BarrierSemanticsType::<VM>::new(
125            mmtk,
126            mutator_tls,
127        ))))
128        .build();
129
130    // Set barrier active, based on whether concurrent marking is in progress
131    mutator
132        .barrier
133        .downcast_mut::<BarrierType<VM>>()
134        .unwrap()
135        .set_weak_ref_barrier_enabled(immix.is_concurrent_marking_active());
136
137    mutator
138}