correcter string init

This commit is contained in:
Shautvast 2023-10-17 15:10:15 +02:00
parent 3ce9ce10b4
commit e3f58a7b9f
3 changed files with 65 additions and 28 deletions

View file

@ -1,8 +1,7 @@
use std::cell::{Ref, RefCell, RefMut, UnsafeCell};
use std::cell::{RefCell, UnsafeCell};
use std::collections::HashMap;
use std::fmt;
use std::hash::Hash;
use std::os::macos::raw::stat;
use std::rc::Rc;
use std::sync::Arc;
@ -84,7 +83,7 @@ pub struct Class {
pub access_flags: u16,
pub name: String,
pub super_class_name: Option<String>,
pub super_class: Option<Arc<RefCell<Class>>>,
pub super_class: Option<Type>,
pub interface_indices: Vec<u16>,
pub interfaces: Vec<Class>,
pub fields: HashMap<String, Field>,
@ -546,7 +545,7 @@ pub enum Value {
F64(f64),
BOOL(bool),
CHAR(char),
Ref(Arc<UnsafeCell<ObjectRef>>),
Ref(UnsafeRef),
Utf8(String),
}
@ -563,6 +562,19 @@ impl Into<UnsafeValue> for Value {
}
pub type UnsafeValue = Arc<UnsafeCell<Value>>;
pub type UnsafeRef = Arc<UnsafeCell<ObjectRef>>;
pub fn unsafe_ref(object: ObjectRef) -> UnsafeRef{
return Arc::new(UnsafeCell::new(object))
}
pub fn unsafe_val(val: Value) -> UnsafeValue{
return Arc::new(UnsafeCell::new(val))
}
pub fn type_ref(class: Class) -> Type{
return Arc::new(RefCell::new(class))
}
pub type Type = Arc<RefCell<Class>>;
unsafe impl Send for Value {}

View file

@ -4,7 +4,7 @@ use std::fmt::{Debug, Formatter};
use std::sync::Arc;
use crate::class::{Class, Type, UnsafeValue, Value};
use crate::heap::ObjectRef::{IntArray, ObjectArray};
use crate::heap::ObjectRef::{ByteArray, IntArray, ObjectArray};
// can contain object or array
pub enum ObjectRef {
@ -20,6 +20,23 @@ pub enum 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))
@ -28,6 +45,10 @@ impl ObjectRef {
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{

View file

@ -2,11 +2,12 @@ use std::cell::{RefCell, UnsafeCell};
use std::collections::HashMap;
use std::ops::Deref;
use std::rc::Rc;
use std::string;
use std::sync::Arc;
use anyhow::{anyhow, Error};
use crate::class::{AttributeType, Class, get_class, Modifier, UnsafeValue, Value};
use crate::class::{AttributeType, Class, get_class, Modifier, unsafe_ref, unsafe_val, UnsafeValue, Value};
use crate::class::Value::Void;
use crate::classloader::CpEntry;
use crate::heap::{Heap, Object, ObjectRef};
@ -30,10 +31,10 @@ impl StackFrame {
}
fn push(&mut self, val: Value) {
self.data.push(Arc::new(UnsafeCell::new(val)));
self.data.push(unsafe_val(val));
}
fn push_arc(&mut self, val: UnsafeValue) {
fn push_ref(&mut self, val: UnsafeValue) {
self.data.push(val);
}
@ -195,12 +196,15 @@ impl Vm {
CpEntry::StringRef(utf8) => {
//TODO
let stringclass = get_class(self, Some(&this_class.borrow().name), "java/lang/String").unwrap();
let stringinstance = Arc::new(UnsafeCell::new(ObjectRef::Object(Box::new(
Vm::new_instance(stringclass.clone()),
))));
let string = this_class.borrow().cp_utf8(utf8).unwrap().to_owned();
let s = self.execute_class(stringclass, "<init>", vec![Arc::new(UnsafeCell::new(Value::Utf8(string)))])?;
self.current_frame().push(Value::Ref(stringinstance));
let stringinstance = unsafe_val(
Value::Ref(unsafe_ref(ObjectRef::Object(Box::new(
Vm::new_instance(stringclass.clone()))))));
let string: Vec<u8> = this_class.borrow().cp_utf8(utf8).unwrap().to_owned().as_bytes().into();
self.execute_class(stringclass, "<init>([B)V",
vec![stringinstance.clone(),
unsafe_val(Value::Ref(ObjectRef::new_byte_array(string)))])?;
self.current_frame().push_ref(stringinstance);
}
CpEntry::Long(l) => {
self.current_frame().push(Value::I64(*l));
@ -242,24 +246,24 @@ impl Vm {
// omitting the type checks so far
let n = read_u8(&code.opcodes, pc) as usize;
self.current_frame()
.push_arc(local_params[n].as_ref().unwrap().clone());
.push_ref(local_params[n].as_ref().unwrap().clone());
}
ILOAD_0 | LLOAD_0 | FLOAD_0 | DLOAD_0 | ALOAD_0 => {
println!("LOAD");
self.current_frame()
.push_arc(local_params[0].as_ref().unwrap().clone());
.push_ref(local_params[0].as_ref().unwrap().clone());
}
ILOAD_1 | LLOAD_1 | FLOAD_1 | DLOAD_1 | ALOAD_1 => {
self.current_frame()
.push_arc(local_params[1].as_ref().unwrap().clone());
.push_ref(local_params[1].as_ref().unwrap().clone());
}
ILOAD_2 | LLOAD_2 | FLOAD_2 | DLOAD_2 | ALOAD_2 => {
self.current_frame()
.push_arc(local_params[2].as_ref().unwrap().clone());
.push_ref(local_params[2].as_ref().unwrap().clone());
}
ILOAD_3 | LLOAD_3 | FLOAD_3 | DLOAD_3 | ALOAD_3 => {
self.current_frame()
.push_arc(local_params[3].as_ref().unwrap().clone());
.push_ref(local_params[3].as_ref().unwrap().clone());
}
IALOAD | LALOAD | FALOAD | DALOAD | AALOAD | BALOAD | CALOAD | SALOAD => unsafe {
self.array_load()?;
@ -289,8 +293,8 @@ impl Vm {
DUP => {
let value = self.current_frame().pop()?;
println!("{:?}", value);
self.current_frame().push_arc(value.clone());
self.current_frame().push_arc(value);
self.current_frame().push_ref(value.clone());
self.current_frame().push_ref(value);
}
IRETURN | FRETURN | DRETURN => {
println!("RETURN");
@ -317,7 +321,7 @@ impl Vm {
let that_borrow = that.borrow();
let (_, val_index) = that_borrow.static_field_mapping.get(that_class_name).unwrap().get(name).unwrap();
println!("get static field {}", name);
self.current_frame().push_arc(borrow.static_data.get(*val_index).unwrap().as_ref().unwrap().clone());
self.current_frame().push_ref(borrow.static_data.get(*val_index).unwrap().as_ref().unwrap().clone());
}
PUTSTATIC => {
println!("PUTSTATIC");
@ -369,7 +373,7 @@ impl Vm {
if let Value::Ref(instance) = &mut *objectref.get() {
if let ObjectRef::Object(ref mut object) = &mut *instance.get() {
let value = object.get(class_name, field_name);
self.current_frame().push_arc(Arc::clone(value));
self.current_frame().push_ref(Arc::clone(value));
} else {
unreachable!()
}
@ -419,7 +423,7 @@ impl Vm {
match *return_value.get() {
Void => {}
_ => {
self.current_frame().push_arc(return_value.clone());
self.current_frame().push_ref(return_value.clone());
}
}
println!("stack {} at {}", self.current_frame().len(), self.current_frame().at)
@ -445,7 +449,7 @@ impl Vm {
match *returnvalue.get() {
Void => {}
_ => {
self.current_frame().push_arc(returnvalue.clone());
self.current_frame().push_ref(returnvalue.clone());
}
}
} else {
@ -460,9 +464,9 @@ impl Vm {
let class_name = borrow.cp_utf8(class_name_index).unwrap();
let class_to_instantiate = get_class(self, Some(&borrow.name), class_name)?;
let object = Arc::new(UnsafeCell::new(ObjectRef::Object(Box::new(
let object = unsafe_ref(ObjectRef::Object(Box::new(
Vm::new_instance(class_to_instantiate),
))));
)));
self.current_frame().push(Value::Ref(Arc::clone(&object)));
self.heap.new_object(object);
}
@ -476,7 +480,7 @@ impl Vm {
let count = self.current_frame().pop()?;
if let Value::I32(count) = *count.get() { // why does pop()?.get() give weird results?
let array = ObjectRef::new_object_array(arraytype, count as usize);
let array = Arc::new(UnsafeCell::new(array));
let array = unsafe_ref(array);
self.current_frame().push(Value::Ref(Arc::clone(&array)));
println!("{}", self.current_frame().len());