java.rs/src/heap.rs
2023-10-29 18:11:12 +01:00

190 lines
5.7 KiB
Rust

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<i8>),
ShortArray(Vec<i16>),
IntArray(Vec<i32>),
LongArray(Vec<i64>),
FloatArray(Vec<f32>),
DoubleArray(Vec<f64>),
BooleanArray(Vec<bool>),
CharArray(Vec<char>),
StringArray(Vec<String>),
ObjectArray(Type, Vec<Arc<UnsafeCell<ObjectRef>>>),
Object(Box<Object>),//Box necessary??
Class(Arc<RefCell<Class>>),
}
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<u8>) -> Vec<i8> {
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<u8>) -> Arc<UnsafeCell<Self>> {
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<RefCell<Class>>,
pub data: Vec<Value>,
} //arrays
unsafe impl Send for Object {}
unsafe impl Sync for Object {}
// object, not array
impl Object {
pub fn new(class: Arc<RefCell<Class>>) -> 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<RefCell<Class>>) -> Vec<Value> {
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<String> = 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<Arc<UnsafeCell<ObjectRef>>>,
}
impl Heap {
pub fn new() -> Self {
Self { objects: vec![] }
}
pub(crate) fn new_object(&mut self, object: Arc<UnsafeCell<ObjectRef>>) {
self.objects.push(object);
}
}