Experimenting with garbage collection algorithm.

This commit is contained in:
Jesse Brault 2025-10-14 21:18:06 -05:00
parent 34fae6ccca
commit d09d945323
2 changed files with 206 additions and 0 deletions

205
src/vm/mem/mod.rs Normal file
View File

@ -0,0 +1,205 @@
use std::cell::RefCell;
use std::marker::PhantomData;
use std::ops::Mul;
#[derive(Debug)]
pub struct Gc<T> {
inner: *mut GcInner,
data: *const T,
_phantom: PhantomData<T>,
}
#[derive(Debug)]
pub struct GcInner {
color: GcColor,
size: usize,
}
impl GcInner {
pub fn new(size: usize) -> Self {
Self {
color: GcColor::White,
size,
}
}
}
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub enum GcColor {
White,
Black,
}
impl<T> Gc<T> {
pub fn new(data: T) -> Self {
let inner = Box::into_raw(Box::new(GcInner::new(size_of::<T>())));
let boxed_data = Box::into_raw(Box::new(data)) as *const T;
Self {
inner,
data: boxed_data,
_phantom: PhantomData,
}
}
pub fn set_color(&mut self, color: GcColor) {
unsafe {
(*self.inner).color = color;
}
}
pub fn color(&self) -> GcColor {
unsafe { (*self.inner).color }
}
pub fn size(&self) -> usize {
unsafe { (*self.inner).size }
}
pub fn data(&self) -> &T {
unsafe { &*self.data }
}
pub fn dealloc(&mut self) {
unsafe {
drop(Box::from_raw(self.inner));
drop(Box::from_raw(self.data as *mut T));
}
}
}
impl<T> Clone for Gc<T> {
fn clone(&self) -> Self {
Self {
inner: self.inner,
data: self.data,
_phantom: PhantomData,
}
}
}
#[derive(Debug)]
enum DvmValue {
Primitive(usize),
Object(Gc<RefCell<DvmObject>>),
Nil,
}
#[derive(Debug)]
struct DvmObject {
fields: Vec<DvmValue>,
}
impl DvmObject {
pub fn new() -> Self {
Self { fields: vec![] }
}
pub fn fields(&self) -> &[DvmValue] {
&self.fields
}
pub fn fields_mut(&mut self) -> &mut Vec<DvmValue> {
&mut self.fields
}
}
fn collect_garbage(
next_gc: &mut usize,
current_size: &mut usize,
stack: &Vec<DvmValue>,
gcs: &mut Vec<Gc<RefCell<DvmObject>>>,
) {
let mut gray_stack: Vec<Gc<RefCell<DvmObject>>> = vec![];
for stack_value in stack {
match stack_value {
DvmValue::Object(gc) => {
if gc.color() == GcColor::White {
gray_stack.push(gc.clone());
}
}
_ => {}
}
}
while let Some(mut current) = gray_stack.pop() {
for field in current.data().borrow().fields() {
match field {
DvmValue::Object(object) => {
gray_stack.push(object.clone());
}
_ => {}
}
}
current.set_color(GcColor::Black);
}
let mut collected_size: usize = 0;
for i in (0..gcs.len()).rev() {
if gcs[i].color() == GcColor::White {
let mut gc = gcs.remove(i);
let size = gc.size();
*current_size -= size;
collected_size += size;
gc.dealloc();
} else {
gcs[i].set_color(GcColor::White);
}
}
*next_gc = std::cmp::max(1024 * 1024, current_size.mul(2));
println!(
"collected_size: {}, current_size: {}, next_gc: {}",
collected_size, current_size, next_gc
);
}
fn maybe_collect_garbage(
next_gc: &mut usize,
current_size: &mut usize,
stack: &Vec<DvmValue>,
gcs: &mut Vec<Gc<RefCell<DvmObject>>>,
) {
if current_size > next_gc {
collect_garbage(next_gc, current_size, stack, gcs);
}
}
fn alloc_dvm_object(
next_gc: &mut usize,
current_size: &mut usize,
stack: &Vec<DvmValue>,
gcs: &mut Vec<Gc<RefCell<DvmObject>>>,
) -> Gc<RefCell<DvmObject>> {
maybe_collect_garbage(next_gc, current_size, stack, gcs);
let mut object = DvmObject::new();
object.fields_mut().push(DvmValue::Nil);
let gc = Gc::new(RefCell::new(object));
*current_size += gc.size();
gcs.push(gc.clone());
gc
}
fn set_field(obj: &mut Gc<RefCell<DvmObject>>, field_index: usize, value: DvmValue) {
let mut binding = obj.data().borrow_mut();
binding.fields_mut()[field_index] = value;
}
#[cfg(test)]
mod tests {
use crate::vm::mem::{alloc_dvm_object, collect_garbage, DvmObject, DvmValue, Gc};
use std::cell::RefCell;
#[test]
fn test() {
let mut stack: Vec<DvmValue> = vec![];
let mut heap: Vec<Gc<RefCell<DvmObject>>> = vec![];
let mut next_gc: usize = 1024 * 1024;
let mut current_size: usize = 0;
for i in 0..100_000_000 {
let mut o = alloc_dvm_object(&mut next_gc, &mut current_size, &stack, &mut heap);
}
collect_garbage(&mut next_gc, &mut current_size, &stack, &mut heap);
}
}

View File

@ -6,6 +6,7 @@ pub mod implementation;
pub mod instruction; pub mod instruction;
pub mod interface; pub mod interface;
pub mod lib; pub mod lib;
mod mem;
pub mod method; pub mod method;
pub mod object; pub mod object;
pub mod op_codes; pub mod op_codes;