Skip to content

Commit

Permalink
swiper: ensure large objects are properly page aligned
Browse files Browse the repository at this point in the history
  • Loading branch information
dinfuehr committed Dec 29, 2023
1 parent 00c1593 commit 50aab6f
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 29 deletions.
2 changes: 1 addition & 1 deletion dora-runtime/src/gc/code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ impl CodeSpace {
CodeSpace {
total: Region::new(space_start, space_end),
mutex: Mutex::new(alloc_data),
chunk_size: mem::page_align(CHUNK_SIZE),
chunk_size: mem::os_page_align_up(CHUNK_SIZE),
reservation,
}
}
Expand Down
4 changes: 2 additions & 2 deletions dora-runtime/src/gc/space.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ pub struct SpaceConfig {
fn adapt_to_page_size(config: SpaceConfig) -> SpaceConfig {
SpaceConfig {
executable: config.executable,
chunk: mem::page_align(config.chunk),
limit: mem::page_align(config.limit),
chunk: mem::os_page_align_up(config.chunk),
limit: mem::os_page_align_up(config.limit),
object_alignment: config.object_alignment,
}
}
Expand Down
4 changes: 2 additions & 2 deletions dora-runtime/src/gc/swiper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,10 @@ impl Swiper {
controller::init(&mut config, args);

// Determine size for card table.
let card_size = mem::page_align((4 * max_heap_size) >> CARD_SIZE_BITS);
let card_size = mem::os_page_align_up((4 * max_heap_size) >> CARD_SIZE_BITS);

// Determine size for crossing map.
let crossing_size = mem::page_align(max_heap_size >> CARD_SIZE_BITS);
let crossing_size = mem::os_page_align_up(max_heap_size >> CARD_SIZE_BITS);

// Determine full reservation size.
let reserve_size = max_heap_size * 4 + card_size + crossing_size;
Expand Down
44 changes: 26 additions & 18 deletions dora-runtime/src/gc/swiper/large.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::mem::size_of;

use crate::gc::swiper::controller::SharedHeapConfig;
use crate::gc::swiper::LARGE_OBJECT_SIZE;
use crate::gc::{Address, Region};
use crate::gc::{align_page_up, is_page_aligned, Address, Region};
use crate::mem;
use crate::os::{self, MemoryPermission};

Expand All @@ -15,25 +15,30 @@ pub struct LargeSpace {

impl LargeSpace {
pub fn new(start: Address, end: Address, config: SharedHeapConfig) -> LargeSpace {
let total = Region::new(start, end);
assert!(is_page_aligned(total.size()));
assert!(start.is_page_aligned());
assert!(end.is_page_aligned());

LargeSpace {
total: Region::new(start, end),
total,
space: Mutex::new(LargeSpaceProtected::new(start, end)),
config,
}
}

pub fn alloc(&self, size: usize) -> Address {
debug_assert!(size >= LARGE_OBJECT_SIZE);
let size = mem::page_align(size_of::<LargeAlloc>() + size);
let committed_size = mem::os_page_align_up(size_of::<LargeAlloc>() + size);

let mut space = self.space.lock();
let mut config = self.config.lock();

if !config.grow_old(size) {
if !config.grow_old(committed_size) {
return Address::null();
}

space.alloc(size)
space.alloc(committed_size)
}

pub fn total(&self) -> Region {
Expand Down Expand Up @@ -146,24 +151,26 @@ impl LargeSpaceProtected {
self.committed_size
}

fn alloc(&mut self, size: usize) -> Address {
debug_assert!(mem::is_os_page_aligned(size));
fn alloc(&mut self, committed_size: usize) -> Address {
assert!(mem::is_os_page_aligned(committed_size));
let reserved_size = align_page_up(committed_size);
let len = self.elements.len();

for i in 0..len {
if self.elements[i].size() >= size {
if self.elements[i].size() >= reserved_size {
let range = self.elements[i];
let addr = range.start;

if range.size() == size {
if range.size() == reserved_size {
self.elements.remove(i);
} else {
self.elements[i] = Region::new(range.start.offset(size), range.end);
self.elements[i] = Region::new(range.start.offset(reserved_size), range.end);
}

os::commit_at(addr, size, MemoryPermission::ReadWrite);
self.append_large_alloc(addr, size);
self.committed_size += size;
os::commit_at(addr, committed_size, MemoryPermission::ReadWrite);
self.append_large_alloc(addr, committed_size);
self.committed_size += committed_size;
assert!(addr.is_page_aligned());

return addr.offset(size_of::<LargeAlloc>());
}
Expand All @@ -172,11 +179,12 @@ impl LargeSpaceProtected {
Address::null()
}

fn free(&mut self, ptr: Address, size: usize) {
debug_assert!(mem::is_os_page_aligned(size));
os::discard(ptr, size);
self.elements.push(ptr.region_start(size));
self.committed_size -= size;
fn free(&mut self, ptr: Address, committed_size: usize) {
assert!(mem::is_os_page_aligned(committed_size));
let reserved_size = align_page_up(committed_size);
os::discard(ptr, committed_size);
self.elements.push(ptr.region_start(reserved_size));
self.committed_size -= committed_size;
}

fn merge(&mut self) {
Expand Down
10 changes: 5 additions & 5 deletions dora-runtime/src/mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ fn test_is_os_page_aligned() {
}

/// round the given value up to the nearest multiple of a page
pub fn page_align(val: usize) -> usize {
pub fn os_page_align_up(val: usize) -> usize {
let align = os::page_size_bits();

// we know that page size is power of 2, hence
Expand All @@ -50,10 +50,10 @@ pub fn page_align(val: usize) -> usize {
fn test_page_align() {
let p = os::page_size();

assert_eq!(p, page_align(1));
assert_eq!(p, page_align(p - 1));
assert_eq!(p, page_align(p));
assert_eq!(2 * p, page_align(p + 1));
assert_eq!(p, os_page_align_up(1));
assert_eq!(p, os_page_align_up(p - 1));
assert_eq!(p, os_page_align_up(p));
assert_eq!(2 * p, os_page_align_up(p + 1));
}

/// rounds the given value `val` up to the nearest multiple
Expand Down
2 changes: 1 addition & 1 deletion dora-runtime/src/vm/globals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pub fn init_global_addresses(vm: &mut VM) {
backing_memory_size = value_offset + ty_size as usize;
}

let size = mem::page_align(backing_memory_size);
let size = mem::os_page_align_up(backing_memory_size);
let start = if backing_memory_size > 0 {
os::commit(size, false)
} else {
Expand Down

0 comments on commit 50aab6f

Please sign in to comment.