Triplespace backup instructions
This is one possible implementation of the Triplespace collector, provided in case you are stuck on the exercise.
Attempt the exercise yourself before reading this.
First, rename all instances of mygc
to triplespace
, and add it as a
module by following the instructions in Create MyGC.
In triplespace/global.rs
:
-
Add a
youngspace
field topub struct TripleSpace
:#![allow(unused)] fn main() { pub struct TripleSpace<VM: VMBinding> { pub hi: AtomicBool, pub copyspace0: CopySpace<VM>, pub copyspace1: CopySpace<VM>, pub youngspace: CopySpace<VM>, // Add this! pub common: CommonPlan<VM>, } }
-
Define the parameters for the youngspace in
new()
inPlan for TripleSpace
:#![allow(unused)] fn main() { fn new( vm_map: &'static VMMap, mmapper: &'static Mmapper, options: Arc<UnsafeOptionsWrapper>, _scheduler: &'static MMTkScheduler<Self::VM>, ) -> Self { //change - again, completely changed. let mut heap = HeapMeta::new(HEAP_START, HEAP_END); TripleSpace { hi: AtomicBool::new(false), copyspace0: CopySpace::new( "copyspace0", false, true, VMRequest::discontiguous(), vm_map, mmapper, &mut heap, ), copyspace1: CopySpace::new( "copyspace1", true, true, VMRequest::discontiguous(), vm_map, mmapper, &mut heap, ), // Add this! youngspace: CopySpace::new( "youngspace", true, true, VMRequest::discontiguous(), vm_map, mmapper, &mut heap, ), common: CommonPlan::new(vm_map, mmapper, options, heap, &TRIPLESPACE_CONSTRAINTS, &[]), } } }
-
Initialise the youngspace in
gc_init()
:#![allow(unused)] fn main() { fn gc_init( &mut self, heap_size: usize, vm_map: &'static VMMap, scheduler: &Arc<MMTkScheduler<VM>>, ) { self.common.gc_init(heap_size, vm_map, scheduler); self.copyspace0.init(&vm_map); self.copyspace1.init(&vm_map); self.youngspace.init(&vm_map); // Add this! } }
-
Prepare the youngspace (as a fromspace) in
prepare()
:#![allow(unused)] fn main() { fn prepare(&self, tls: OpaquePointer) { self.common.prepare(tls, true); self.hi .store(!self.hi.load(Ordering::SeqCst), Ordering::SeqCst); let hi = self.hi.load(Ordering::SeqCst); self.copyspace0.prepare(hi); self.copyspace1.prepare(!hi); self.youngspace.prepare(true); // Add this! } }
-
Release the youngspace in
release()
:#![allow(unused)] fn main() { fn release(&self, tls: OpaquePointer) { self.common.release(tls, true); self.fromspace().release(); self.youngspace().release(); // Add this! } }
-
Under the reference functions
tospace()
andfromspace()
, add a similar reference functionyoungspace()
:#![allow(unused)] fn main() { pub fn youngspace(&self) -> &CopySpace<VM> { &self.youngspace } }
In mutator.rs
:
- Map a bump pointer to the youngspace (replacing the one mapped to the
tospace) in
space_mapping
increate_triplespace_mutator()
:#![allow(unused)] fn main() { space_mapping: box vec![ (AllocatorSelector::BumpPointer(0), plan.youngspace()), // Change this! ( AllocatorSelector::BumpPointer(1), plan.common.get_immortal(), ), (AllocatorSelector::LargeObject(0), plan.common.get_los()), ], }
- Rebind the bump pointer to youngspace (rather than the tospace) in
triplespace_mutator_release()
:#![allow(unused)] fn main() { pub fn triplespace_mutator_release<VM: VMBinding> ( mutator: &mut Mutator<VM>, _tls: OpaquePointer ) { let bump_allocator = unsafe { mutator .allocators . get_allocator_mut( mutator.config.allocator_mapping[AllocationType::Default] ) } .downcast_mut::<BumpAllocator<VM>>() .unwrap(); bump_allocator.rebind(Some(mutator.plan.youngspace())); // Change this! } }
In gc_work.rs
:
- Add the youngspace to trace_object, following the same format as
the tospace and fromspace:
#![allow(unused)] fn main() { fn trace_object(&mut self, object: ObjectReference) -> ObjectReference { // Add this! else if self.plan().youngspace().in_space(object) { self.plan().youngspace.trace_object::<Self, TripleSpaceCopyContext<VM>>( self, object, super::global::ALLOC_TripleSpace, unsafe { self.worker().local::<TripleSpaceCopyContext<VM>>() }, ) } else if self.plan().tospace().in_space(object) { self.plan().tospace().trace_object::<Self, TripleSpaceCopyContext<VM>>( self, object, super::global::ALLOC_TripleSpace, unsafe { self.worker().local::<MyGCCopyContext<VM>>() }, ) } else if self.plan().fromspace().in_space(object) { self.plan().fromspace().trace_object::<Self, MyGCCopyContext<VM>>( self, object, super::global::ALLOC_TripleSpace, unsafe { self.worker().local::<TripleSpaceCopyContext<VM>>() }, ) } else { self.plan().common.trace_object::<Self, TripleSpaceCopyContext<VM>>(self, object) } } } }