Skip to content

Commit 2bf2cc6

Browse files
committed
Get a new arena when this one is full
1 parent 0ca8cbc commit 2bf2cc6

File tree

3 files changed

+29
-10
lines changed

3 files changed

+29
-10
lines changed

src/arena.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,8 +170,8 @@ const fn header_size<T>() -> usize {
170170
header + ((align - (header % align)) % align)
171171
}
172172

173-
/// Returns `header` and `next`.
174-
fn alloc_arena<T>() -> *mut T {
173+
/// Returns `next`.
174+
pub fn alloc_arena<T>() -> *mut T {
175175
// Get more memory from system allocator
176176
let mem_ptr = unsafe { System.alloc(Layout::new::<Mem>()) };
177177
let mem_addr = mem_ptr as usize;
@@ -180,13 +180,16 @@ fn alloc_arena<T>() -> *mut T {
180180
< unsafe { &std::mem::transmute::<_, &Mem>(mem_ptr)._mem[16383] } as *const _ as usize
181181
);
182182

183+
// FIXME animalizes Header
184+
185+
// FIXME this seems wrong! Make sure it's in sync with ArenaUntyped
183186
let capacity = (16384 - header_size::<T>()) / size_of::<T>();
184187
(mem_addr + (capacity * size_of::<T>())) as *mut T
185188
}
186189

187190
impl<T: Trace> Arena<T> for ArenaInternals<T> {
188191
fn new() -> ArenaInternals<T> {
189-
// if !T::PRE_CONDTION {
192+
// if !T::PRE_CONDITION {
190193

191194
// };
192195
let bus = GC_BUS.with(|tm| {

src/gc_logic.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use std::{
1313

1414
pub(crate) static mut REGISTER: Option<Sender<RegMsg>> = None;
1515

16-
const ARENA_SIZE: usize = 16384;
16+
pub const ARENA_SIZE: usize = 16384;
1717

1818
#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
1919
pub(crate) struct TypeInfo {
@@ -60,7 +60,7 @@ impl Default for Parents {
6060
}
6161

6262
/// Keep in sync with Header<T>
63-
struct HeaderUnTyped {
63+
pub(crate) struct HeaderUnTyped {
6464
// TODO private
6565
pub evacuated: Mutex<HashMap<u16, *const u8>>,
6666
// roots: HashMap<u16, *const Box<UnsafeCell<*const T>>>,
@@ -71,13 +71,13 @@ struct HeaderUnTyped {
7171

7272
impl HeaderUnTyped {
7373
/// last is closest to Header, since we bump down.
74-
fn last_offset(align: u16) -> u16 {
74+
pub(crate) fn last_offset(align: u16) -> u16 {
7575
let header = mem::size_of::<HeaderUnTyped>() as u16;
7676
header + ((align - (header % align)) % align)
7777
}
7878

7979
// TODO is this right?
80-
fn first_offset(align: u16, size: u16) -> u16 {
80+
pub(crate) fn first_offset(align: u16, size: u16) -> u16 {
8181
let cap = (ARENA_SIZE as u16 - HeaderUnTyped::last_offset(align)) / size;
8282
HeaderUnTyped::last_offset(align) + (cap * size)
8383
}

src/mark.rs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
use super::gc::*;
2-
use crate::{auto_traits::HasGc, trace::GcTypeInfo};
2+
use crate::{
3+
arena::alloc_arena,
4+
auto_traits::HasGc,
5+
gc_logic::{HeaderUnTyped, ARENA_SIZE},
6+
trace::GcTypeInfo,
7+
};
38
use smallvec::SmallVec;
49
use std::ops::Range;
5-
use std::{mem, ptr};
10+
use std::{cmp::min, mem, ptr};
611

712
/// This will be sound once GAT or const Eq &str lands.
813
/// The former will allow transmuting only lifetimes.
@@ -21,6 +26,7 @@ pub struct Handlers {
2126
nexts: SmallVec<[*mut u8; 4]>,
2227
/// forward(old, new) -> already evacuated
2328
forward: fn(*const u8, *const u8) -> Option<*const u8>,
29+
filled: SmallVec<[SmallVec<[*mut HeaderUnTyped; 1]>; 4]>,
2430
}
2531

2632
pub unsafe trait Condemned {
@@ -72,6 +78,15 @@ unsafe impl<'r, T> Condemned for Gc<'r, T> {
7278
if region.contains(&addr) {
7379
let i = handlers.translation[OFFSET as usize];
7480
if let Some(next) = handlers.nexts.get_mut(i as usize) {
81+
let next_addr = *next as usize;
82+
let header_addr = next_addr - next_addr % ARENA_SIZE;
83+
84+
// Get a new Arena if this ones full
85+
if HeaderUnTyped::last_offset(mem::align_of::<T>() as u16) as usize > next_addr {
86+
handlers.filled[i as usize].push(header_addr as *mut HeaderUnTyped);
87+
*next = alloc_arena::<T>() as *mut u8;
88+
};
89+
7590
unsafe { ptr::copy_nonoverlapping(ptr, *next as *mut T, 1) }
7691
let forward = handlers.forward;
7792
if let Some(pre_evac) = forward(ptr as *const u8, *next as *const u8) {
@@ -84,7 +99,8 @@ unsafe impl<'r, T> Condemned for Gc<'r, T> {
8499
unsafe {
85100
*r = *next as *const T;
86101
}
87-
*next = (addr + mem::size_of::<T>()) as *mut u8;
102+
// TODO fix overwrite when size_of<T> > size_of<Header> via min in other places
103+
*next = min(addr - mem::size_of::<T>(), header_addr) as *mut u8;
88104
}
89105
}
90106
}

0 commit comments

Comments
 (0)