Skip to content

Commit

Permalink
swiper: start implementing evacuation mode
Browse files Browse the repository at this point in the history
  • Loading branch information
dinfuehr committed Jan 4, 2024
1 parent e256cfe commit 52c7514
Show file tree
Hide file tree
Showing 2 changed files with 168 additions and 68 deletions.
161 changes: 124 additions & 37 deletions dora-runtime/src/gc/swiper/full.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ pub struct FullCollector<'a> {
card_table: &'a CardTable,
crossing_map: &'a CrossingMap,
readonly_space: &'a Space,
use_evacuation: bool,
young_evacuated_pages: Vec<(Page, usize)>,
old_evacuated_pages: Vec<(Page, usize)>,

top: Address,
current_limit: Address,
Expand Down Expand Up @@ -74,6 +77,9 @@ impl<'a> FullCollector<'a> {
card_table,
crossing_map,
readonly_space,
use_evacuation: false,
young_evacuated_pages: Vec::new(),
old_evacuated_pages: Vec::new(),

top: old_total.start(),
current_limit: old_total.start(),
Expand Down Expand Up @@ -130,37 +136,43 @@ impl<'a> FullCollector<'a> {
}
}

self.compute_forward();
if !self.use_evacuation {
self.compute_forward();

if stats {
let duration = timer.stop();
self.phases.compute_forward = duration;
}
if stats {
let duration = timer.stop();
self.phases.compute_forward = duration;
}

if dev_verbose {
println!("Full GC: Phase 2 (compute forward)");
}
if dev_verbose {
println!("Full GC: Phase 2 (compute forward)");
}

self.update_references();
self.update_references();

if stats {
let duration = timer.stop();
self.phases.update_refs = duration;
}
if stats {
let duration = timer.stop();
self.phases.update_refs = duration;
}

if dev_verbose {
println!("Full GC: Phase 3 (update refs)");
}
if dev_verbose {
println!("Full GC: Phase 3 (update refs)");
}

self.relocate();
self.relocate();

if stats {
let duration = timer.stop();
self.phases.relocate = duration;
}
if stats {
let duration = timer.stop();
self.phases.relocate = duration;
}

if dev_verbose {
println!("Full GC: Phase 4 (relocate)");
if dev_verbose {
println!("Full GC: Phase 4 (relocate)");
}
} else {
self.evacuate();
self.update_references();
self.free_pages();
}

self.reset_cards();
Expand All @@ -176,9 +188,11 @@ impl<'a> FullCollector<'a> {

self.young.reset_after_full_gc(self.vm);

let pages = std::mem::replace(&mut self.pages, Vec::new());
self.old_protected
.reset_after_gc(pages, self.top, self.current_limit);
if !self.use_evacuation {
let pages = std::mem::replace(&mut self.pages, Vec::new());
self.old_protected
.reset_after_gc(pages, self.top, self.current_limit);
}
}

fn mark_live(&mut self) {
Expand All @@ -198,6 +212,36 @@ impl<'a> FullCollector<'a> {
Some(object_address)
}
});

for page in self.young.pages() {
let live = self.compute_live_on_page(page);

if live > 0 {
self.young_evacuated_pages.push((page, live));
}
}

let mut old_evacuated_pages = Vec::new();

for page in self.old_protected.pages() {
let live = self.compute_live_on_page(page);
old_evacuated_pages.push((page, live));
}

old_evacuated_pages.sort_by(|a, b| a.1.cmp(&b.1));
old_evacuated_pages.truncate(10);

let _ = std::mem::replace(&mut self.old_evacuated_pages, old_evacuated_pages);
}

fn compute_live_on_page(&self, page: Page) -> usize {
let mut live = 0;
walk_region(self.vm, page.object_area(), |obj, _addr, size| {
if obj.header().is_marked() {
live += size;
}
});
live
}

fn compute_forward(&mut self) {
Expand Down Expand Up @@ -310,28 +354,71 @@ impl<'a> FullCollector<'a> {
self.old.update_crossing(self.top, self.current_limit);
}

fn evacuate(&mut self) {
for (page, _) in self.young_evacuated_pages.clone() {
self.evacuate_page(page);
}

for (page, _) in self.old_evacuated_pages.clone() {
self.evacuate_page(page);
}
}

fn evacuate_page(&mut self, page: Page) {
walk_region(self.vm, page.object_area(), |object, address, size| {
if !object.header().is_marked() {
return;
}

if let Some(new_address) = self.old_protected.allocate(self.vm, self.old, size) {
// determine location after relocated object
let object_end = address.offset(size);

object.header().set_metadata_fwdptr(new_address);
object.copy_to(new_address, size);

// Clear metadata word.
let new_obj = new_address.to_obj();
new_obj.header().set_metadata_raw(INITIAL_METADATA_OLD);

self.old.update_crossing(new_address, object_end);
} else {
panic!("FAIL: Not enough space for objects in old generation.");
}
});
}

fn free_pages(&mut self) {
for (page, _) in self.old_evacuated_pages.clone() {
self.old_protected.free_page(page);
}
}

fn reset_cards(&mut self) {
for page in self.old_protected.pages() {
self.card_table.reset_page(page);
}
}

fn forward_reference(&mut self, slot: Slot) {
let object_addr = slot.get();
let object_address = slot.get();

if object_address.is_null() {
return;
}

if self.heap.contains(object_addr) {
debug_assert!(object_addr.to_obj().header().is_marked());
if self.heap.contains(object_address) {
let object = object_address.to_obj();
debug_assert!(object.header().is_marked());

if self.large_space.contains(object_addr) {
// large objects do not move in memory
return;
}
let fwd_addr = object.header().metadata_fwdptr();

let fwd_addr = object_addr.to_obj().header().metadata_fwdptr();
debug_assert!(self.heap.contains(fwd_addr));
slot.set(fwd_addr);
if fwd_addr.is_non_null() {
debug_assert!(self.heap.contains(fwd_addr));
slot.set(fwd_addr);
}
} else {
debug_assert!(object_addr.is_null() || self.readonly_space.contains(object_addr));
debug_assert!(self.readonly_space.contains(object_address));
}
}

Expand Down
75 changes: 44 additions & 31 deletions dora-runtime/src/gc/swiper/old.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,37 +95,7 @@ impl CommonOldGen for OldGen {
impl GenerationAllocator for OldGen {
fn allocate(&self, vm: &VM, size: usize) -> Option<Address> {
let mut protected = self.protected.lock();

if let Some(address) = protected.raw_alloc(size) {
fill_region_with(vm, protected.top, protected.current_limit, false);
self.update_crossing(protected.top, protected.current_limit);
return Some(address);
}

fill_region_with(vm, protected.top, protected.current_limit, false);
self.update_crossing(protected.top, protected.current_limit);

if !self.can_add_page() {
return None;
}

if let Some(page) = protected.allocate_page(vm) {
protected.pages.push(page);
protected.pages.sort();

protected.top = page.object_area_start();
protected.current_limit = page.object_area_end();
let result = protected.raw_alloc(size);
assert!(result.is_some());

// Make rest of page iterable.
fill_region(vm, protected.top, protected.current_limit);
self.update_crossing(protected.top, protected.current_limit);

result
} else {
None
}
protected.allocate(vm, self, size)
}

fn free(&self, _region: Region) {
Expand Down Expand Up @@ -171,6 +141,39 @@ impl OldGenProtected {
self.total.start <= addr && addr < self.top
}

pub fn allocate(&mut self, vm: &VM, old: &OldGen, size: usize) -> Option<Address> {
if let Some(address) = self.raw_alloc(size) {
fill_region_with(vm, self.top, self.current_limit, false);
old.update_crossing(self.top, self.current_limit);
return Some(address);
}

fill_region_with(vm, self.top, self.current_limit, false);
old.update_crossing(self.top, self.current_limit);

if !old.can_add_page() {
return None;
}

if let Some(page) = self.allocate_page(vm) {
self.pages.push(page);
self.pages.sort();

self.top = page.object_area_start();
self.current_limit = page.object_area_end();
let result = self.raw_alloc(size);
assert!(result.is_some());

// Make rest of page iterable.
fill_region(vm, self.top, self.current_limit);
old.update_crossing(self.top, self.current_limit);

result
} else {
None
}
}

pub fn commit_pages(&mut self, pages: &[Page]) {
let previous_page_set: HashSet<Page> = HashSet::from_iter(self.pages.iter().cloned());

Expand Down Expand Up @@ -204,6 +207,16 @@ impl OldGenProtected {
self.current_limit = current_limit;
}

pub fn free_page(&mut self, page: Page) {
let idx = self
.pages
.iter()
.position(|&p| p == page)
.expect("missing page");
self.pages.swap_remove(idx);
os::discard(page.start(), page.size());
}

pub fn active_size(&self) -> usize {
self.top.offset_from(self.total.start())
}
Expand Down

0 comments on commit 52c7514

Please sign in to comment.