diff --git a/dvm-lib/src/vm/mem.rs b/dvm-lib/src/vm/mem.rs index 4c7431e..c2236ee 100644 --- a/dvm-lib/src/vm/mem.rs +++ b/dvm-lib/src/vm/mem.rs @@ -1,5 +1,9 @@ +use std::alloc::{Layout, alloc}; use std::any::TypeId; -use std::ptr::Pointee; +use std::borrow::Borrow; +use std::collections::HashSet; +use std::hash::{Hash, Hasher}; +use std::ptr::{Pointee, slice_from_raw_parts_mut}; use std::rc::Rc; use std::sync::OnceLock; @@ -31,8 +35,24 @@ impl Gc { } } -struct GcMut { - inner: *mut GcInner, +impl Clone for Gc { + fn clone(&self) -> Self { + Gc::from_inner(self.inner) + } +} + +impl PartialEq for Gc { + fn eq(&self, other: &Self) -> bool { + self.data().eq(other.data()) + } +} + +impl Eq for Gc {} + +impl Hash for Gc { + fn hash(&self, state: &mut H) { + self.data().hash(state) + } } struct GcInner { @@ -55,6 +75,54 @@ impl GcInner { } } +impl GcInner { + fn from_slice(slice: &[T]) -> *mut GcInner<[T]> { + let data_layout = Layout::array::(slice.len()).expect(&format!( + "Unable to create Layout for array size {}", + slice.len() + )); + let (gc_inner_layout, _) = Layout::new::>() + .extend(data_layout) + .expect("Unable to create and extend Layout for GcInner<()>"); + let gc_inner_layout = gc_inner_layout.pad_to_align(); + + // alloc + let ptr = unsafe { alloc(gc_inner_layout) }; + if ptr.is_null() { + panic!("Unable to allocate memory for GcInner<()>"); + } + + // get wide pointer + let gc_inner = slice_from_raw_parts_mut(ptr, slice.len()) as *mut GcInner<[T]>; + + // init + unsafe { + (&raw mut (*gc_inner).borrow_count).write(0); + (&raw mut (*gc_inner).borrow_mut_count).write(false); + (&raw mut (*gc_inner).color).write(false); + (&raw mut (*gc_inner).next).write(None); + + for (i, item) in slice.iter().enumerate() { + (&raw mut (*gc_inner).data[i]).write(item.clone()); + } + } + + gc_inner + } +} + +impl GcInner { + fn from_dst(data_ptr: *mut T) -> *mut GcInner { + todo!() + } +} + +impl Trace for () { + fn grays(&self) -> Vec { + vec![] + } +} + struct GcAny { inner_ptr: *mut (), // like void* in C inner_ptr_metadata: *const (), // type-erased metadata @@ -112,6 +180,7 @@ struct GcAnyVTable { trace: fn(*const (), *const ()) -> Vec, } +#[derive(Clone)] enum Value { Object(Gc), Int(i32), @@ -121,6 +190,7 @@ enum Value { struct Class { name: Rc, + field_count: usize, // just a place-holder } #[repr(C)] @@ -141,8 +211,108 @@ impl Trace for str { } } -impl From<&str> for Gc { - fn from(value: &str) -> Self { +impl From<&[T]> for Gc<[T]> { + fn from(value: &[T]) -> Self { + Gc::from_inner(GcInner::from_slice(value)) + } +} + +impl Trace for [T] { + fn grays(&self) -> Vec { todo!() } } + +impl Trace for u8 { + fn grays(&self) -> Vec { + vec![] + } +} + +impl From<&str> for Gc { + fn from(value: &str) -> Self { + let gc_inner = GcInner::from_slice(value.as_bytes()) as *mut GcInner; + Gc::from_inner(gc_inner) + } +} + +struct DvmHeap { + first: Option, + last: Option, +} + +impl DvmHeap { + fn new() -> Self { + Self { + first: None, + last: None, + } + } + + fn new_object(&mut self, class: &Class) -> Gc { + let mut fields = Vec::with_capacity(class.field_count); + for _ in 0..class.field_count { + fields.push(Value::Null); + } + + let fields_layout = Layout::array::(class.field_count).unwrap(); + let object_layout = Layout::new::<*const Class>() + .extend(fields_layout) + .unwrap() + .0 + .pad_to_align(); + + let ptr = unsafe { alloc(object_layout) }; + if ptr.is_null() { + panic!("Unable to allocate memory for new Object on DvmHeap"); + } + + let wide_ptr = slice_from_raw_parts_mut(ptr, class.field_count) as *mut Object; + + unsafe { + (&raw mut (*wide_ptr).class).write(class); + for (i, value) in fields.iter().enumerate() { + (&raw mut (*wide_ptr).fields[i]).write(value.clone()); + } + } + + let gc = Gc::from_inner(GcInner::from_dst(wide_ptr)); + // some logic for adjusting first and last pointers, etc., bookkeeping on the heap, ex: + self.first = Some(gc.erase()); + self.last = Some(gc.erase()); + gc + } + + fn push(&mut self, data: T) -> Gc { + let inner = GcInner::new(data); + let inner_ptr = Box::into_raw(Box::new(inner)); + Gc::from_inner(inner_ptr) + } +} + +impl Borrow for Gc { + fn borrow(&self) -> &str { + self.data() + } +} + +fn borrow_test() { + let s = Gc::from("hello"); + let mut interned = HashSet::>::new(); + interned.insert(s.clone()); + if interned.contains("hello") { + println!("yay") + } +} + +impl Trace for i32 { + fn grays(&self) -> Vec { + vec![] + } +} + +fn push_test() { + let num = 42_i32; + let mut heap = DvmHeap::new(); + let gc_num = heap.push(num); +}