More mem sketching.
This commit is contained in:
parent
4c744bf2d6
commit
2175d5f20a
@ -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<T: Trace + ?Sized + 'static> Gc<T> {
|
||||
}
|
||||
}
|
||||
|
||||
struct GcMut<T: Trace> {
|
||||
inner: *mut GcInner<T>,
|
||||
impl<T: Trace + ?Sized> Clone for Gc<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Gc::from_inner(self.inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trace + ?Sized + PartialEq> PartialEq for Gc<T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.data().eq(other.data())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trace + ?Sized + Eq> Eq for Gc<T> {}
|
||||
|
||||
impl<T: Trace + ?Sized + Hash> Hash for Gc<T> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.data().hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
struct GcInner<T: Trace + ?Sized> {
|
||||
@ -55,6 +75,54 @@ impl<T: Trace> GcInner<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trace + Clone> GcInner<T> {
|
||||
fn from_slice(slice: &[T]) -> *mut GcInner<[T]> {
|
||||
let data_layout = Layout::array::<T>(slice.len()).expect(&format!(
|
||||
"Unable to create Layout for array size {}",
|
||||
slice.len()
|
||||
));
|
||||
let (gc_inner_layout, _) = Layout::new::<GcInner<()>>()
|
||||
.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<T: Trace + ?Sized> GcInner<T> {
|
||||
fn from_dst(data_ptr: *mut T) -> *mut GcInner<T> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Trace for () {
|
||||
fn grays(&self) -> Vec<GcAny> {
|
||||
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<GcAny>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
enum Value {
|
||||
Object(Gc<Object>),
|
||||
Int(i32),
|
||||
@ -121,6 +190,7 @@ enum Value {
|
||||
|
||||
struct Class {
|
||||
name: Rc<str>,
|
||||
field_count: usize, // just a place-holder
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
@ -141,8 +211,108 @@ impl Trace for str {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Gc<str> {
|
||||
fn from(value: &str) -> Self {
|
||||
impl<T: Trace + Clone> From<&[T]> for Gc<[T]> {
|
||||
fn from(value: &[T]) -> Self {
|
||||
Gc::from_inner(GcInner::from_slice(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Trace> Trace for [T] {
|
||||
fn grays(&self) -> Vec<GcAny> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Trace for u8 {
|
||||
fn grays(&self) -> Vec<GcAny> {
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Gc<str> {
|
||||
fn from(value: &str) -> Self {
|
||||
let gc_inner = GcInner::from_slice(value.as_bytes()) as *mut GcInner<str>;
|
||||
Gc::from_inner(gc_inner)
|
||||
}
|
||||
}
|
||||
|
||||
struct DvmHeap {
|
||||
first: Option<GcAny>,
|
||||
last: Option<GcAny>,
|
||||
}
|
||||
|
||||
impl DvmHeap {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
first: None,
|
||||
last: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn new_object(&mut self, class: &Class) -> Gc<Object> {
|
||||
let mut fields = Vec::with_capacity(class.field_count);
|
||||
for _ in 0..class.field_count {
|
||||
fields.push(Value::Null);
|
||||
}
|
||||
|
||||
let fields_layout = Layout::array::<Value>(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<T: Trace>(&mut self, data: T) -> Gc<T> {
|
||||
let inner = GcInner::new(data);
|
||||
let inner_ptr = Box::into_raw(Box::new(inner));
|
||||
Gc::from_inner(inner_ptr)
|
||||
}
|
||||
}
|
||||
|
||||
impl Borrow<str> for Gc<str> {
|
||||
fn borrow(&self) -> &str {
|
||||
self.data()
|
||||
}
|
||||
}
|
||||
|
||||
fn borrow_test() {
|
||||
let s = Gc::from("hello");
|
||||
let mut interned = HashSet::<Gc<str>>::new();
|
||||
interned.insert(s.clone());
|
||||
if interned.contains("hello") {
|
||||
println!("yay")
|
||||
}
|
||||
}
|
||||
|
||||
impl Trace for i32 {
|
||||
fn grays(&self) -> Vec<GcAny> {
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
|
||||
fn push_test() {
|
||||
let num = 42_i32;
|
||||
let mut heap = DvmHeap::new();
|
||||
let gc_num = heap.push(num);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user