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::collections::HashMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::os::macos::raw::stat;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
|
@ -84,7 +83,7 @@ pub struct Class {
|
||||||
pub access_flags: u16,
|
pub access_flags: u16,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub super_class_name: Option<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 interface_indices: Vec<u16>,
|
||||||
pub interfaces: Vec<Class>,
|
pub interfaces: Vec<Class>,
|
||||||
pub fields: HashMap<String, Field>,
|
pub fields: HashMap<String, Field>,
|
||||||
|
|
@ -546,7 +545,7 @@ pub enum Value {
|
||||||
F64(f64),
|
F64(f64),
|
||||||
BOOL(bool),
|
BOOL(bool),
|
||||||
CHAR(char),
|
CHAR(char),
|
||||||
Ref(Arc<UnsafeCell<ObjectRef>>),
|
Ref(UnsafeRef),
|
||||||
Utf8(String),
|
Utf8(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -563,6 +562,19 @@ impl Into<UnsafeValue> for Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type UnsafeValue = Arc<UnsafeCell<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>>;
|
pub type Type = Arc<RefCell<Class>>;
|
||||||
|
|
||||||
unsafe impl Send for Value {}
|
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 std::sync::Arc;
|
||||||
|
|
||||||
use crate::class::{Class, Type, UnsafeValue, Value};
|
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
|
// can contain object or array
|
||||||
pub enum ObjectRef {
|
pub enum ObjectRef {
|
||||||
|
|
@ -20,6 +20,23 @@ pub enum ObjectRef {
|
||||||
Object(Box<Object>),
|
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 {
|
impl ObjectRef {
|
||||||
pub fn new_object_array(class: Type, size: usize) -> Self {
|
pub fn new_object_array(class: Type, size: usize) -> Self {
|
||||||
ObjectArray(class, Vec::with_capacity(size))
|
ObjectArray(class, Vec::with_capacity(size))
|
||||||
|
|
@ -28,6 +45,10 @@ impl ObjectRef {
|
||||||
pub fn new_int_array(size: usize) -> Self {
|
pub fn new_int_array(size: usize) -> Self {
|
||||||
IntArray(Vec::with_capacity(size))
|
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{
|
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::collections::HashMap;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::string;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use anyhow::{anyhow, Error};
|
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::class::Value::Void;
|
||||||
use crate::classloader::CpEntry;
|
use crate::classloader::CpEntry;
|
||||||
use crate::heap::{Heap, Object, ObjectRef};
|
use crate::heap::{Heap, Object, ObjectRef};
|
||||||
|
|
@ -30,10 +31,10 @@ impl StackFrame {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push(&mut self, val: Value) {
|
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);
|
self.data.push(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -195,12 +196,15 @@ impl Vm {
|
||||||
CpEntry::StringRef(utf8) => {
|
CpEntry::StringRef(utf8) => {
|
||||||
//TODO
|
//TODO
|
||||||
let stringclass = get_class(self, Some(&this_class.borrow().name), "java/lang/String").unwrap();
|
let stringclass = get_class(self, Some(&this_class.borrow().name), "java/lang/String").unwrap();
|
||||||
let stringinstance = Arc::new(UnsafeCell::new(ObjectRef::Object(Box::new(
|
let stringinstance = unsafe_val(
|
||||||
Vm::new_instance(stringclass.clone()),
|
Value::Ref(unsafe_ref(ObjectRef::Object(Box::new(
|
||||||
))));
|
Vm::new_instance(stringclass.clone()))))));
|
||||||
let string = this_class.borrow().cp_utf8(utf8).unwrap().to_owned();
|
let string: Vec<u8> = this_class.borrow().cp_utf8(utf8).unwrap().to_owned().as_bytes().into();
|
||||||
let s = self.execute_class(stringclass, "<init>", vec![Arc::new(UnsafeCell::new(Value::Utf8(string)))])?;
|
|
||||||
self.current_frame().push(Value::Ref(stringinstance));
|
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) => {
|
CpEntry::Long(l) => {
|
||||||
self.current_frame().push(Value::I64(*l));
|
self.current_frame().push(Value::I64(*l));
|
||||||
|
|
@ -242,24 +246,24 @@ impl Vm {
|
||||||
// omitting the type checks so far
|
// omitting the type checks so far
|
||||||
let n = read_u8(&code.opcodes, pc) as usize;
|
let n = read_u8(&code.opcodes, pc) as usize;
|
||||||
self.current_frame()
|
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 => {
|
ILOAD_0 | LLOAD_0 | FLOAD_0 | DLOAD_0 | ALOAD_0 => {
|
||||||
println!("LOAD");
|
println!("LOAD");
|
||||||
self.current_frame()
|
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 => {
|
ILOAD_1 | LLOAD_1 | FLOAD_1 | DLOAD_1 | ALOAD_1 => {
|
||||||
self.current_frame()
|
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 => {
|
ILOAD_2 | LLOAD_2 | FLOAD_2 | DLOAD_2 | ALOAD_2 => {
|
||||||
self.current_frame()
|
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 => {
|
ILOAD_3 | LLOAD_3 | FLOAD_3 | DLOAD_3 | ALOAD_3 => {
|
||||||
self.current_frame()
|
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 {
|
IALOAD | LALOAD | FALOAD | DALOAD | AALOAD | BALOAD | CALOAD | SALOAD => unsafe {
|
||||||
self.array_load()?;
|
self.array_load()?;
|
||||||
|
|
@ -289,8 +293,8 @@ impl Vm {
|
||||||
DUP => {
|
DUP => {
|
||||||
let value = self.current_frame().pop()?;
|
let value = self.current_frame().pop()?;
|
||||||
println!("{:?}", value);
|
println!("{:?}", value);
|
||||||
self.current_frame().push_arc(value.clone());
|
self.current_frame().push_ref(value.clone());
|
||||||
self.current_frame().push_arc(value);
|
self.current_frame().push_ref(value);
|
||||||
}
|
}
|
||||||
IRETURN | FRETURN | DRETURN => {
|
IRETURN | FRETURN | DRETURN => {
|
||||||
println!("RETURN");
|
println!("RETURN");
|
||||||
|
|
@ -317,7 +321,7 @@ impl Vm {
|
||||||
let that_borrow = that.borrow();
|
let that_borrow = that.borrow();
|
||||||
let (_, val_index) = that_borrow.static_field_mapping.get(that_class_name).unwrap().get(name).unwrap();
|
let (_, val_index) = that_borrow.static_field_mapping.get(that_class_name).unwrap().get(name).unwrap();
|
||||||
println!("get static field {}", name);
|
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 => {
|
PUTSTATIC => {
|
||||||
println!("PUTSTATIC");
|
println!("PUTSTATIC");
|
||||||
|
|
@ -369,7 +373,7 @@ impl Vm {
|
||||||
if let Value::Ref(instance) = &mut *objectref.get() {
|
if let Value::Ref(instance) = &mut *objectref.get() {
|
||||||
if let ObjectRef::Object(ref mut object) = &mut *instance.get() {
|
if let ObjectRef::Object(ref mut object) = &mut *instance.get() {
|
||||||
let value = object.get(class_name, field_name);
|
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 {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
|
@ -419,7 +423,7 @@ impl Vm {
|
||||||
match *return_value.get() {
|
match *return_value.get() {
|
||||||
Void => {}
|
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)
|
println!("stack {} at {}", self.current_frame().len(), self.current_frame().at)
|
||||||
|
|
@ -445,7 +449,7 @@ impl Vm {
|
||||||
match *returnvalue.get() {
|
match *returnvalue.get() {
|
||||||
Void => {}
|
Void => {}
|
||||||
_ => {
|
_ => {
|
||||||
self.current_frame().push_arc(returnvalue.clone());
|
self.current_frame().push_ref(returnvalue.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -460,9 +464,9 @@ impl Vm {
|
||||||
let class_name = borrow.cp_utf8(class_name_index).unwrap();
|
let class_name = borrow.cp_utf8(class_name_index).unwrap();
|
||||||
let class_to_instantiate = get_class(self, Some(&borrow.name), class_name)?;
|
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),
|
Vm::new_instance(class_to_instantiate),
|
||||||
))));
|
)));
|
||||||
self.current_frame().push(Value::Ref(Arc::clone(&object)));
|
self.current_frame().push(Value::Ref(Arc::clone(&object)));
|
||||||
self.heap.new_object(object);
|
self.heap.new_object(object);
|
||||||
}
|
}
|
||||||
|
|
@ -476,7 +480,7 @@ impl Vm {
|
||||||
let count = self.current_frame().pop()?;
|
let count = self.current_frame().pop()?;
|
||||||
if let Value::I32(count) = *count.get() { // why does pop()?.get() give weird results?
|
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 = 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)));
|
self.current_frame().push(Value::Ref(Arc::clone(&array)));
|
||||||
println!("{}", self.current_frame().len());
|
println!("{}", self.current_frame().len());
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue