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::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::rc::Rc;
|
||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
|
|
||||||
@ -31,8 +35,24 @@ impl<T: Trace + ?Sized + 'static> Gc<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GcMut<T: Trace> {
|
impl<T: Trace + ?Sized> Clone for Gc<T> {
|
||||||
inner: *mut GcInner<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> {
|
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 {
|
struct GcAny {
|
||||||
inner_ptr: *mut (), // like void* in C
|
inner_ptr: *mut (), // like void* in C
|
||||||
inner_ptr_metadata: *const (), // type-erased metadata
|
inner_ptr_metadata: *const (), // type-erased metadata
|
||||||
@ -112,6 +180,7 @@ struct GcAnyVTable {
|
|||||||
trace: fn(*const (), *const ()) -> Vec<GcAny>,
|
trace: fn(*const (), *const ()) -> Vec<GcAny>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
enum Value {
|
enum Value {
|
||||||
Object(Gc<Object>),
|
Object(Gc<Object>),
|
||||||
Int(i32),
|
Int(i32),
|
||||||
@ -121,6 +190,7 @@ enum Value {
|
|||||||
|
|
||||||
struct Class {
|
struct Class {
|
||||||
name: Rc<str>,
|
name: Rc<str>,
|
||||||
|
field_count: usize, // just a place-holder
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -141,8 +211,108 @@ impl Trace for str {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&str> for Gc<str> {
|
impl<T: Trace + Clone> From<&[T]> for Gc<[T]> {
|
||||||
fn from(value: &str) -> Self {
|
fn from(value: &[T]) -> Self {
|
||||||
|
Gc::from_inner(GcInner::from_slice(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Trace> Trace for [T] {
|
||||||
|
fn grays(&self) -> Vec<GcAny> {
|
||||||
todo!()
|
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