Skip to content

Commit

Permalink
Merge pull request #1 from notJoon/add-gc-algorithms
Browse files Browse the repository at this point in the history
Add TriColorGC and MarkAndSweep garbage collectors
  • Loading branch information
notJoon committed Nov 24, 2023
2 parents d775c4f + 5165d9e commit 82320e8
Show file tree
Hide file tree
Showing 9 changed files with 244 additions and 153 deletions.
47 changes: 47 additions & 0 deletions src/gc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use std::fmt;

use crate::{controller::PIController, vm::VirtualMachine};

pub trait GarbageCollector {
fn collect(&self, vm: &mut VirtualMachine);
fn ty(&self) -> GCType;
fn new_instance(&self) -> Box<dyn GarbageCollector>;
fn adjust_confidence(&mut self, vm: &mut VirtualMachine);
fn trigger_gc(&mut self, vm: &mut VirtualMachine);
}

pub struct TriColorGC {
pub color: TriColor,
}

#[derive(Debug, PartialEq, Clone)]
pub enum GCType {
MarkAndSweep,
}

#[derive(Debug, PartialEq, Clone)]
pub enum TriColor {
White,
Gray,
Black,
}

impl fmt::Display for TriColor {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
TriColor::White => write!(f, "White: Not visited"),
TriColor::Gray => write!(f, "Gray: Visiting"),
TriColor::Black => write!(f, "Black: Visited"),
}
}
}

pub struct MarkAndSweep {
pub pi: PIController,
}

// impl GarbageCollector for MarkAndSweep {
// fn collect(&self, vm: &mut VM) {

// }
// }
6 changes: 6 additions & 0 deletions src/heap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use std::collections::BTreeSet;

// #[derive(Debug, PartialEq, Clone, Default)]
// pub struct Heap {
// pub roots: BTreeSet<>
// }
3 changes: 2 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub mod controller;
pub mod mem;
pub mod object;
pub mod types;
pub mod vm;
pub mod gc;
pub mod heap;
14 changes: 6 additions & 8 deletions src/object.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use core::fmt;
use std::cell::RefCell;
use std::default;
use std::rc::Rc;

use crate::types::TriColor;
use crate::gc::TriColor;

#[derive(Debug, PartialEq, Clone)]
pub enum TypeValue {
Expand All @@ -22,14 +20,14 @@ impl fmt::Display for TypeValue {
pub struct Object {
pub ident: String,
pub value: Option<TypeValue>,
pub reference: Vec<Rc<RefCell<Object>>>,
pub reference: Vec<Object>,
pub marked: TriColor,
}

pub trait ObjectTrait {
fn new(ident: String, value: TypeValue) -> Self;
fn add_reference(&mut self, object: Object) -> usize;
fn delete_reference(&mut self, object: Rc<RefCell<Object>>) -> usize;
fn delete_reference(&mut self, object: Object) -> usize;
fn len(&self) -> usize;
fn is_empty(&self) -> bool;
fn to_string(&self) -> String;
Expand All @@ -47,12 +45,12 @@ impl ObjectTrait for Object {
}

fn add_reference(&mut self, object: Object) -> usize {
self.reference.push(Rc::new(RefCell::new(object)));
self.reference.push(object);
self.reference.len()
}

fn delete_reference(&mut self, object: Rc<RefCell<Object>>) -> usize {
self.reference.retain(|x| !Rc::ptr_eq(x, &object));
fn delete_reference(&mut self, object: Object) -> usize {
self.reference.retain(|x| x != &object);
self.reference.len()
}

Expand Down
Empty file added src/stack.rs
Empty file.
18 changes: 0 additions & 18 deletions src/types.rs

This file was deleted.

129 changes: 90 additions & 39 deletions src/vm.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use core::fmt;

use crate::{
controller::PIController,
object::{Object, ObjectTrait, TypeValue},
gc::TriColor,
object::{Object, TypeValue},
};

#[derive(Debug, PartialEq, Default)]
#[derive(Debug, PartialEq, Default, Clone)]
pub enum GCStatus {
#[default]
Idle,
Expand All @@ -20,16 +20,26 @@ pub enum VMError {
InvalidRangeOfThreshold,
}

#[derive(Debug, PartialEq, Default)]
pub struct VM {
pub stack: Vec<*mut Object>,
#[derive(Debug, PartialEq, Clone, Default)]
pub enum OpCode {
#[default]
Halt,
Pop,
Push(TypeValue),
Mark,
Sweep,
}

#[derive(Debug, PartialEq, Default, Clone)]
pub struct VirtualMachine {
pub stack: Vec<Object>,
pub op_codes: Vec<OpCode>,
pub max_stack_size: usize,

pub threshold: usize,
pub num_objects: usize,
pub first_object: Option<*mut Object>,
pub first_object: Option<Object>,

pi: PIController,
pub gc_confidence: f64,
pub trigger_gc: bool,
pub gc_status: GCStatus,
Expand All @@ -39,16 +49,16 @@ pub trait VMTrait {
fn new(max_stack_size: usize, threshold: f64) -> Result<Self, VMError>
where
Self: Sized;
fn push(&mut self, obj: *mut Object) -> Result<usize, VMError>;
fn pop(&mut self) -> Result<*mut Object, VMError>;
fn new_object(&mut self, ident: String, value: TypeValue) -> *mut Object;
fn push_int(&mut self, value: i32) -> Result<i32, VMError>;
fn push(&mut self, obj: Object) -> Result<usize, VMError>;
fn pop(&mut self) -> Result<Object, VMError>;
fn len(&self) -> usize;
fn is_empty(&self) -> bool;
fn update_gc_confidence(&mut self) -> f64;
fn to_string(&self) -> String;

fn mark(&mut self);
}

impl VMTrait for VM {
impl VMTrait for VirtualMachine {
fn new(max_stack_size: usize, threshold: f64) -> Result<Self, VMError> {
if threshold <= 0.0 || threshold >= 100.0 {
return Err(VMError::InvalidRangeOfThreshold);
Expand All @@ -61,38 +71,28 @@ impl VMTrait for VM {
})
}

fn push(&mut self, obj: *mut Object) -> Result<usize, VMError> {
fn push(&mut self, obj: Object) -> Result<usize, VMError> {
if self.len() >= self.max_stack_size {
self.op_codes.push(OpCode::Halt);
return Err(VMError::StackOverflow);
}

self.stack.push(obj);
self.stack.push(obj.to_owned());
self.op_codes.push(OpCode::Push(obj.value.unwrap()));

Ok(self.len())
}

fn pop(&mut self) -> Result<*mut Object, VMError> {
fn pop(&mut self) -> Result<Object, VMError> {
if self.is_empty() {
self.op_codes.push(OpCode::Halt);
return Err(VMError::StackUnderflow);
}

let obj = self.stack.pop().unwrap();
Ok(obj)
}

fn new_object(&mut self, ident: String, value: TypeValue) -> *mut Object {
let obj = Box::new(Object::new(ident, value));
let obj_ptr = Box::into_raw(obj);
self.op_codes.push(OpCode::Pop);

self.first_object = Some(obj_ptr);
self.num_objects += 1;

obj_ptr
}

fn push_int(&mut self, value: i32) -> Result<i32, VMError> {
let obj = self.new_object(String::from("int"), TypeValue::Int(value));
self.push(obj)?;
Ok(value)
Ok(obj)
}

fn len(&self) -> usize {
Expand All @@ -103,15 +103,54 @@ impl VMTrait for VM {
self.stack.is_empty()
}

fn update_gc_confidence(&mut self) -> f64 {
let current_metric = self.stack.len() as f64 / self.max_stack_size as f64 * 100.0;
let set_point = self.threshold as f64;
fn to_string(&self) -> String {
format!(
"VM: {{\nstack: {:?},\nop_codes: {:?},\nmax_stack_size: {},\nthreshold: {},\nnum_objects: {},\nfirst_object: {:?},\ngc_confidence: {},\ntrigger_gc: {},\ngc_status: {}\n}}",
self.stack,
self.op_codes,
self.max_stack_size,
self.threshold,
self.num_objects,
self.first_object,
self.gc_confidence,
self.trigger_gc,
self.gc_status
)
}

if let Ok(output) = self.pi.update(current_metric, set_point, 0.0, 0.0) {
self.gc_confidence = output;
fn mark(&mut self) {
self.op_codes.push(OpCode::Mark);
let mut mark_stack = Vec::new();

while let Some(mut obj) = self.stack.pop() {
if obj.marked == TriColor::White {
obj.marked = TriColor::Gray;
mark_stack.push(obj.clone());
}

if obj.reference.len() > 0 {
let mut ref_obj = obj.reference.pop().unwrap();
if ref_obj.marked == TriColor::White {
ref_obj.marked = TriColor::Gray;
mark_stack.push(ref_obj.clone());
}
obj.reference.push(ref_obj);
}
}

self.gc_confidence
while let Some(mut obj) = mark_stack.pop() {
if obj.marked == TriColor::Gray {
obj.marked = TriColor::Black;
}

if obj.reference.len() > 0 {
let mut ref_obj = obj.reference.pop().unwrap();
if ref_obj.marked == TriColor::Gray {
ref_obj.marked = TriColor::Black;
}
obj.reference.push(ref_obj);
}
}
}
}

Expand All @@ -137,3 +176,15 @@ impl fmt::Display for GCStatus {
}
}
}

impl fmt::Display for OpCode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
OpCode::Push(ref i) => write!(f, "Push: {}", i),
OpCode::Pop => write!(f, "Pop"),
OpCode::Halt => write!(f, "Halt"),
OpCode::Mark => write!(f, "Mark"),
OpCode::Sweep => write!(f, "Sweep"),
}
}
}
3 changes: 1 addition & 2 deletions tests/object_test.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#[cfg(test)]
mod object_tests {
use gc_simulator::object::{Object, ObjectTrait, TypeValue};
use gc_simulator::types::TriColor;
use gc_simulator::{object::{Object, ObjectTrait, TypeValue}, gc::TriColor};

#[test]
fn test_new() {
Expand Down
Loading

0 comments on commit 82320e8

Please sign in to comment.