More mem sketching.

This commit is contained in:
Jesse Brault 2026-08-06 13:09:16 -05:00
parent 4c744bf2d6
commit 2175d5f20a

View File

@ -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);
}