java.rs/src/heap.rs
2023-10-17 15:10:15 +02:00

172 lines
5.2 KiB
Rust

use std::cell::{RefCell, UnsafeCell};
use std::fmt;
use std::fmt::{Debug, Formatter};
use std::sync::Arc;
use crate::class::{Class, Type, UnsafeValue, Value};
use crate::heap::ObjectRef::{ByteArray, IntArray, ObjectArray};
// 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>),
ObjectArray(Type, Vec<Arc<UnsafeCell<ObjectRef>>>),
Object(Box<Object>),
}
fn into_vec_i8(v: Vec<u8>) -> Vec<i8> {
// ideally we'd use Vec::into_raw_parts, but it's unstable,
// so we have to do it manually:
// first, make sure v's destructor doesn't free the data
// it thinks it owns when it goes out of scope
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 {
ObjectRef::BooleanArray(d) => write!(f, "[Z;{}]", d.len()),
ObjectRef::ByteArray(d) => write!(f, "[B;{}]", d.len()),
ObjectRef::CharArray(d) => write!(f, "[C;{}]", d.len()),
ObjectRef::DoubleArray(d) => write!(f, "[D;{}]", d.len()),
ObjectRef::FloatArray(d) => write!(f, "[F;{}]", d.len()),
ObjectRef::IntArray(d) => write!(f, "[I;{}]", d.len()),
ObjectRef::LongArray(d) => write!(f, "[J;{}]", d.len()),
ObjectRef::ObjectArray(t, d) => write!(f,"[L{};{}]", t.borrow().name,d.len()),
ObjectRef::ShortArray( d) => write!(f, "[S;{}]", d.len()),
ObjectRef::Object( r) => write!(f,"{}{{ {:?} }}", r.class.borrow().name, r.data),
}
}
}
// trying to implement efficient object instance storage
pub struct Object {
// locked: bool,
// hashcode: i32,
pub class: Arc<RefCell<Class>>,
pub data: Vec<UnsafeValue>,
} //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<UnsafeValue> {
let mut field_data = Vec::with_capacity(class.borrow().n_object_fields());
for (_, fields) in &class.borrow().object_field_mapping {
for (_, (fieldtype, _)) in fields {
let value = match fieldtype.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: UnsafeValue) {
let borrow = self.class.borrow();
let (_type, index) = borrow
.object_field_mapping
.get(class_name)
.unwrap()
.get(field_name)
.unwrap();
self.data[*index] = value;
}
pub fn get(&mut self, class_name: &String, field_name: &String) -> &UnsafeValue {
let borrow = self.class.borrow();
let (_type, index) = borrow
.object_field_mapping
.get(class_name)
.unwrap()
.get(field_name)
.unwrap();
&self.data[*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);
}
}