use std::cell::{RefCell, UnsafeCell}; use std::fmt; use std::fmt::{Debug, Formatter}; use std::sync::Arc; use ObjectRef::{BooleanArray, CharArray, DoubleArray, FloatArray, LongArray, ShortArray}; use crate::class::{Class, Type, Value}; use crate::heap::ObjectRef::{ByteArray, IntArray, ObjectArray, StringArray}; // can contain object or array pub enum ObjectRef { ByteArray(Vec), ShortArray(Vec), IntArray(Vec), LongArray(Vec), FloatArray(Vec), DoubleArray(Vec), BooleanArray(Vec), CharArray(Vec), StringArray(Vec), ObjectArray(Type, Vec>>), Object(Box),//Box necessary?? Class(Arc>), } impl ObjectRef { pub fn get_array_length(&self) -> usize { match self { ByteArray(d) => d.len(), ShortArray(d) => d.len(), IntArray(d) => d.len(), LongArray(d) => d.len(), FloatArray(d) => d.len(), DoubleArray(d) => d.len(), BooleanArray(d) => d.len(), CharArray(d) => d.len(), StringArray(d) => d.len(), ObjectArray(_, d) => d.len(), _ => unreachable!("not an array") } } } fn into_vec_i8(v: Vec) -> Vec { let mut v = std::mem::ManuallyDrop::new(v); // then, pick apart the existing Vec let p = v.as_mut_ptr(); let len = v.len(); let cap = v.capacity(); // finally, adopt the data into a new Vec unsafe { Vec::from_raw_parts(p as *mut i8, len, cap) } } impl ObjectRef { pub fn new_object_array(class: Type, size: usize) -> Self { ObjectArray(class, Vec::with_capacity(size)) } pub fn new_int_array(size: usize) -> Self { IntArray(Vec::with_capacity(size)) } pub fn new_byte_array(d: Vec) -> Arc> { Arc::new(UnsafeCell::new(ByteArray(into_vec_i8(d)))) } } impl Debug for ObjectRef { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { BooleanArray(d) => write!(f, "[Z;{}]", d.len()), ByteArray(d) => write!(f, "[B;{}]", d.len()), CharArray(d) => write!(f, "[C;{}]", d.len()), DoubleArray(d) => write!(f, "[D;{}]", d.len()), FloatArray(d) => write!(f, "[F;{}]", d.len()), IntArray(d) => write!(f, "[I;{}]", d.len()), LongArray(d) => write!(f, "[J;{}]", d.len()), ObjectArray(t, d) => write!(f, "[L{};{}]", t.borrow().name, d.len()), ShortArray(d) => write!(f, "[S;{}]", d.len()), StringArray(d) => write!(f, "[S;{}]", d.len()), ObjectRef::Object(r) => write!(f, "{}{{ {:?} }}", r.class.borrow().name, r.data), ObjectRef::Class(s) => write!(f, "Class {:?}", s.borrow().name), } } } // trying to implement efficient object instance storage pub struct Object { // locked: bool, // hashcode: i32, pub class: Arc>, pub data: Vec, } //arrays unsafe impl Send for Object {} unsafe impl Sync for Object {} // object, not array impl Object { pub fn new(class: Arc>) -> Self { let instance_data = Object::init_fields(class.clone()); Self { class, data: instance_data, } } // initializes all non-static fields to their default values pub(crate) fn init_fields(class: Arc>) -> Vec { let mut field_data = Vec::with_capacity(class.borrow().n_object_fields()); for (_, fields) in &class.borrow().object_field_mapping { for (_, type_index) in fields { let value = match type_index.type_name.as_str() { "Z" => Value::BOOL(false), "B" => Value::I32(0), "S" => Value::I32(0), "I" => Value::I32(0), "J" => Value::I64(0), "F" => Value::F32(0.0), "D" => Value::F64(0.0), _ => Value::Null, }; field_data.push(value.into()); } } field_data } pub fn set(&mut self, class_name: &String, field_name: &String, value: Value) { let borrow = self.class.borrow(); let type_index = borrow .object_field_mapping .get(class_name) .unwrap() .get(field_name) .unwrap(); self.data[type_index.index] = value; } pub fn get(&mut self, class_name: &String, field_name: &String) -> &Value { let borrow = self.class.borrow(); let type_index = borrow .object_field_mapping .get(class_name) .unwrap() .get(field_name) .unwrap(); &self.data[type_index.index] } // fn get_field_name(&self, cp_index: &u16) -> &str { // if let CpEntry::Utf8(name) = self.class.constant_pool.get(cp_index).unwrap() { // return name; // } // panic!() // } } impl fmt::Debug for Object { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // let fields: Vec = self.data.unwrap().iter().map(|(k)| { // // let mut r: String = self.get_field_name(k).into(); // // r.push(':'); // // r.push_str(format!("{:?}").as_str()); // // r // } // ).collect(); write!(f, "{}", self.class.borrow().name) } } // will using Arc's enable a GC-less heap???? pub(crate) struct Heap { objects: Vec>>, } impl Heap { pub fn new() -> Self { Self { objects: vec![] } } pub(crate) fn new_object(&mut self, object: Arc>) { self.objects.push(object); } }