correcter string init
This commit is contained in:
parent
3ce9ce10b4
commit
e3f58a7b9f
3 changed files with 65 additions and 28 deletions
20
src/class.rs
20
src/class.rs
|
|
@ -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 {}
|
||||
|
|
|
|||
23
src/heap.rs
23
src/heap.rs
|
|
@ -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{
|
||||
|
|
|
|||
50
src/vm.rs
50
src/vm.rs
|
|
@ -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());
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue