Skip to content

Commit

Permalink
runtime: let each GC provide the read only space
Browse files Browse the repository at this point in the history
  • Loading branch information
dinfuehr committed Jan 11, 2024
1 parent 33e84cb commit d01f0db
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 42 deletions.
18 changes: 5 additions & 13 deletions dora-runtime/src/gc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::gc::allocator::GenerationAllocator;
use crate::gc::code::CodeSpace;
use crate::gc::compact::MarkCompactCollector;
use crate::gc::copy::CopyCollector;
use crate::gc::space::{Space, SpaceConfig};
use crate::gc::space::{default_readonly_space_config, Space};
use crate::gc::sweep::SweepCollector;
use crate::gc::swiper::{Swiper, CARD_SIZE};
use crate::gc::tlab::MAX_TLAB_OBJECT_SIZE;
Expand Down Expand Up @@ -45,28 +45,20 @@ pub const M: usize = K * K;

const CHUNK_SIZE: usize = 8 * K;
pub const DEFAULT_CODE_SPACE_LIMIT: usize = 2 * M;
pub const DEFAULT_READONLY_SPACE_LIMIT: usize = PAGE_SIZE;
pub const DEFAULT_READONLY_SPACE_LIMIT: usize = PAGE_SIZE * 4;

pub struct Gc {
collector: Box<dyn Collector + Sync>,
supports_tlab: bool,

code_space: CodeSpace,
readonly_space: Space,
epoch: AtomicUsize,

finalizers: Mutex<Vec<(Address, Arc<DoraThread>)>>,
}

impl Gc {
pub fn new(args: &Flags) -> Gc {
let readonly_config = SpaceConfig {
executable: false,
chunk: PAGE_SIZE,
limit: args.readonly_size(),
object_alignment: mem::ptr_width_usize(),
};

let collector_name = args.gc.unwrap_or(CollectorName::Swiper);

let collector: Box<dyn Collector + Sync> = match collector_name {
Expand All @@ -86,7 +78,6 @@ impl Gc {
supports_tlab,

code_space: CodeSpace::new(code_size),
readonly_space: Space::new(readonly_config, "perm"),
epoch: AtomicUsize::new(0),

finalizers: Mutex::new(Vec::new()),
Expand Down Expand Up @@ -114,8 +105,8 @@ impl Gc {
self.code_space.alloc(size)
}

pub fn alloc_readonly(&self, size: usize) -> Address {
self.readonly_space.alloc(size)
pub fn alloc_readonly(&self, vm: &VM, size: usize) -> Address {
self.collector.alloc_readonly(vm, size)
}

pub fn alloc(&self, vm: &VM, size: usize) -> Address {
Expand Down Expand Up @@ -189,6 +180,7 @@ trait Collector {
// allocate object of given size
fn alloc_tlab_area(&self, vm: &VM, size: usize) -> Option<Region>;
fn alloc(&self, vm: &VM, size: usize) -> Address;
fn alloc_readonly(&self, vm: &VM, size: usize) -> Address;

// collect garbage
fn collect(&self, vm: &VM, reason: GcReason);
Expand Down
16 changes: 10 additions & 6 deletions dora-runtime/src/gc/compact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ use parking_lot::Mutex;
use crate::gc::bump::BumpAllocator;
use crate::gc::marking;
use crate::gc::root::{determine_strong_roots, Slot};
use crate::gc::space::Space;
use crate::gc::tlab;
use crate::gc::{
formatted_size, iterate_weak_roots, Address, CollectionStats, Collector, GcReason, Region,
default_readonly_space_config, iterate_weak_roots, Address, CollectionStats, Collector,
GcReason, Region, Space,
};
use crate::object::Obj;
use crate::os;
Expand All @@ -18,6 +18,7 @@ pub struct MarkCompactCollector {
heap: Region,
alloc: BumpAllocator,
stats: Mutex<CollectionStats>,
readonly: Space,
}

impl MarkCompactCollector {
Expand All @@ -32,14 +33,13 @@ impl MarkCompactCollector {
let heap_end = heap_start.offset(heap_size);
let heap = Region::new(heap_start, heap_end);

if args.gc_verbose {
println!("GC: {} {}", heap, formatted_size(heap_size));
}
let readonly_space = Space::new(default_readonly_space_config(args), "perm");

MarkCompactCollector {
heap,
alloc: BumpAllocator::new(heap_start, heap_end),
stats: Mutex::new(CollectionStats::new()),
readonly: readonly_space,
}
}
}
Expand Down Expand Up @@ -78,6 +78,10 @@ impl Collector for MarkCompactCollector {
self.alloc.bump_alloc(size)
}

fn alloc_readonly(&self, _vm: &VM, size: usize) -> Address {
self.readonly.alloc(size)
}

fn collect(&self, vm: &VM, reason: GcReason) {
let mut timer = Timer::new(vm.flags.gc_stats);

Expand Down Expand Up @@ -133,7 +137,7 @@ impl MarkCompactCollector {
let mut mark_compact = MarkCompact {
vm,
heap: self.heap,
readonly_space: &vm.gc.readonly_space,
readonly_space: &self.readonly,

init_top: self.alloc.top(),
top: self.heap.start,
Expand Down
14 changes: 9 additions & 5 deletions dora-runtime/src/gc/copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use std::sync::Arc;
use crate::gc::bump::BumpAllocator;
use crate::gc::tlab;
use crate::gc::{
formatted_size, iterate_strong_roots, iterate_weak_roots, Address, CollectionStats, Collector,
GcReason, Region,
default_readonly_space_config, formatted_size, iterate_strong_roots, iterate_weak_roots,
Address, CollectionStats, Collector, GcReason, Region, Space,
};
use crate::mem;
use crate::object::{Obj, VtblptrWordKind};
Expand All @@ -22,6 +22,7 @@ pub struct CopyCollector {

alloc: BumpAllocator,
stats: Mutex<CollectionStats>,
readonly: Space,
}

impl CopyCollector {
Expand All @@ -39,15 +40,14 @@ impl CopyCollector {
let semi_size = heap_size / 2;
let separator = heap_start.offset(semi_size);

if args.gc_verbose {
println!("GC: {}; semi size: {}", heap, formatted_size(semi_size),);
}
let readonly_space = Space::new(default_readonly_space_config(args), "perm");

CopyCollector {
total: heap,
separator,
alloc: BumpAllocator::new(heap_start, separator),
stats: Mutex::new(CollectionStats::new()),
readonly: readonly_space,
}
}
}
Expand Down Expand Up @@ -86,6 +86,10 @@ impl Collector for CopyCollector {
self.alloc.bump_alloc(size)
}

fn alloc_readonly(&self, _vm: &VM, size: usize) -> Address {
self.readonly.alloc(size)
}

fn collect(&self, vm: &VM, reason: GcReason) {
let mut timer = Timer::new(vm.flags.gc_stats);

Expand Down
12 changes: 11 additions & 1 deletion dora-runtime/src/gc/space.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use parking_lot::Mutex;
use std::sync::atomic::{AtomicUsize, Ordering};

use crate::gc::{Address, Region};
use crate::gc::{Address, Region, PAGE_SIZE};
use crate::mem;
use crate::os::{self, MemoryPermission, Reservation};
use crate::vm::Flags;

/// Configuration for a space.
/// This makes it possible to use `Space` both for the
Expand All @@ -15,6 +16,15 @@ pub struct SpaceConfig {
pub object_alignment: usize,
}

pub fn default_readonly_space_config(flags: &Flags) -> SpaceConfig {
SpaceConfig {
executable: false,
chunk: PAGE_SIZE,
limit: flags.readonly_size(),
object_alignment: mem::ptr_width_usize(),
}
}

fn adapt_to_page_size(config: SpaceConfig) -> SpaceConfig {
SpaceConfig {
executable: config.executable,
Expand Down
15 changes: 11 additions & 4 deletions dora-runtime/src/gc/sweep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@ use parking_lot::Mutex;
use crate::gc::freelist::FreeList;
use crate::gc::marking;
use crate::gc::root::{determine_strong_roots, Slot};
use crate::gc::space::Space;
use crate::gc::tlab;
use crate::gc::{
fill_region_with_free, formatted_size, iterate_weak_roots, Address, CollectionStats, Collector,
GcReason, Region,
default_readonly_space_config, fill_region_with_free, formatted_size, iterate_weak_roots,
Address, CollectionStats, Collector, GcReason, Region, Space,
};
use crate::os;
use crate::safepoint;
Expand All @@ -18,6 +17,7 @@ pub struct SweepCollector {
heap: Region,
alloc: Mutex<SweepAllocator>,
stats: Mutex<CollectionStats>,
readonly: Space,
}

impl SweepCollector {
Expand All @@ -36,10 +36,13 @@ impl SweepCollector {
println!("GC: {} {}", heap, formatted_size(heap_size));
}

let readonly_space = Space::new(default_readonly_space_config(args), "perm");

SweepCollector {
heap,
alloc: Mutex::new(SweepAllocator::new(heap)),
stats: Mutex::new(CollectionStats::new()),
readonly: readonly_space,
}
}
}
Expand Down Expand Up @@ -78,6 +81,10 @@ impl Collector for SweepCollector {
self.inner_alloc(vm, size)
}

fn alloc_readonly(&self, _vm: &VM, size: usize) -> Address {
self.readonly.alloc(size)
}

fn collect(&self, vm: &VM, reason: GcReason) {
let mut timer = Timer::new(vm.flags.gc_stats);

Expand Down Expand Up @@ -141,7 +148,7 @@ impl SweepCollector {
let mut collector = MarkSweep {
vm,
heap: Region::new(start, top),
readonly_space: &vm.gc.readonly_space,
readonly_space: &self.readonly,

rootset,
reason,
Expand Down
32 changes: 21 additions & 11 deletions dora-runtime/src/gc/swiper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ use crate::gc::swiper::minor::MinorCollector;
use crate::gc::swiper::old::OldGen;
use crate::gc::swiper::verify::{Verifier, VerifierPhase};
use crate::gc::swiper::young::YoungGen;
use crate::gc::tlab;
use crate::gc::Collector;
use crate::gc::GcReason;
use crate::gc::{align_page_up, Address, Region, K};
use crate::gc::{
align_page_up, default_readonly_space_config, tlab, Address, Collector, GcReason, Region,
Space, K,
};
use crate::mem;
use crate::object::{Obj, OLD_BIT, REMEMBERED_BIT};
use crate::os::{self, MemoryPermission, Reservation};
Expand Down Expand Up @@ -69,6 +69,7 @@ pub struct Swiper {
young: YoungGen,
old: OldGen,
large: LargeSpace,
readonly: Space,

card_table: CardTable,
crossing_map: CrossingMap,
Expand Down Expand Up @@ -168,6 +169,8 @@ impl Swiper {

let threadpool = Mutex::new(Pool::new(nworkers as u32));

let readonly = Space::new(default_readonly_space_config(args), "perm");

Swiper {
heap: Region::new(heap_start, heap_end),
reserved_area,
Expand All @@ -176,6 +179,7 @@ impl Swiper {
young,
old,
large,
readonly,

card_table,
crossing_map,
Expand Down Expand Up @@ -296,7 +300,7 @@ impl Swiper {
&self.large,
&self.card_table,
&self.crossing_map,
&vm.gc.readonly_space,
&self.readonly,
rootset,
threads,
reason,
Expand All @@ -316,8 +320,6 @@ impl Swiper {

fn verify(&self, vm: &VM, phase: VerifierPhase, _kind: CollectionKind, rootset: &[Slot]) {
if vm.flags.gc_verify {
let readonly_space = &vm.gc.readonly_space;

let mut verifier = Verifier::new(
vm,
self.heap,
Expand All @@ -327,7 +329,7 @@ impl Swiper {
&self.crossing_map,
rootset,
&self.large,
&*readonly_space,
&self.readonly,
phase,
);
verifier.verify();
Expand Down Expand Up @@ -391,6 +393,10 @@ impl Collector for Swiper {
}
}

fn alloc_readonly(&self, _vm: &VM, size: usize) -> Address {
self.readonly.alloc(size)
}

fn collect(&self, vm: &VM, reason: GcReason) {
self.perform_collection(vm, CollectionKind::Full, reason);
}
Expand Down Expand Up @@ -658,6 +664,10 @@ impl RegularPage {
self.base_page_header().is_large()
}

pub fn is_survivor(&self) -> bool {
self.base_page_header().is_large()
}

fn raw_flags(&self) -> usize {
self.base_page_header().raw_flags()
}
Expand All @@ -669,7 +679,7 @@ impl RegularPage {

const YOUNG_BIT: usize = 1;
const LARGE_BIT: usize = 1 << 1;
const SURVIVED_BIT: usize = 1 << 2;
const SURVIVOR_BIT: usize = 1 << 2;

#[repr(C)]
struct BasePageHeader {
Expand All @@ -685,8 +695,8 @@ impl BasePageHeader {
(self.raw_flags() & LARGE_BIT) != 0
}

fn is_survived(&self) -> bool {
(self.raw_flags() & SURVIVED_BIT) != 0
fn is_survivor(&self) -> bool {
(self.raw_flags() & SURVIVOR_BIT) != 0
}

fn add_flag(&self, flag: usize) {
Expand Down
8 changes: 8 additions & 0 deletions dora-runtime/src/gc/swiper/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,14 @@ impl<'a> Verifier<'a> {

fn verify_heap(&mut self) {
assert!(!self.in_old);
self.young.unprotect_from();
for page in self.young.from_pages() {
assert!(page.is_young());
assert!(!page.is_large());
assert!(!page.is_survivor());
}
self.young.protect_from();

for page in self.young.to_pages() {
self.verify_page(page);
}
Expand Down
Loading

0 comments on commit d01f0db

Please sign in to comment.