WIP Strings
This commit is contained in:
parent
d132502771
commit
8f6651e303
6 changed files with 60 additions and 17 deletions
|
|
@ -540,6 +540,7 @@ pub enum Value {
|
||||||
BOOL(bool),
|
BOOL(bool),
|
||||||
CHAR(char),
|
CHAR(char),
|
||||||
Ref(Arc<UnsafeCell<ObjectRef>>),
|
Ref(Arc<UnsafeCell<ObjectRef>>),
|
||||||
|
Utf8(String)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Value {
|
impl Value {
|
||||||
|
|
@ -555,6 +556,7 @@ impl Into<UnsafeValue> for Value {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type UnsafeValue = Arc<UnsafeCell<Value>>;
|
pub type UnsafeValue = Arc<UnsafeCell<Value>>;
|
||||||
|
pub type Type = Arc<RefCell<Class>>;
|
||||||
|
|
||||||
unsafe impl Send for Value {}
|
unsafe impl Send for Value {}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -226,7 +226,7 @@ fn read_attribute(
|
||||||
*index += attribute_length;
|
*index += attribute_length;
|
||||||
|
|
||||||
if let CpEntry::Utf8(s) = &constant_pool.get(&attribute_name_index).unwrap() {
|
if let CpEntry::Utf8(s) = &constant_pool.get(&attribute_name_index).unwrap() {
|
||||||
println!("Att [{}]", s);
|
// println!("Att [{}]", s);
|
||||||
return match s.as_str() {
|
return match s.as_str() {
|
||||||
"ConstantValue" => {
|
"ConstantValue" => {
|
||||||
assert_eq!(info.len(), 2);
|
assert_eq!(info.len(), 2);
|
||||||
|
|
@ -274,6 +274,7 @@ fn read_attribute(
|
||||||
"BootstrapMethods" => Some(("".into(), AttributeType::BootstrapMethods)), //stub
|
"BootstrapMethods" => Some(("".into(), AttributeType::BootstrapMethods)), //stub
|
||||||
"InnerClasses" => Some(("".into(), AttributeType::InnerClasses)), //stub
|
"InnerClasses" => Some(("".into(), AttributeType::InnerClasses)), //stub
|
||||||
"Signature" => Some(("".into(), AttributeType::Signature)), //stub
|
"Signature" => Some(("".into(), AttributeType::Signature)), //stub
|
||||||
|
"NestHost" => Some(("".into(), AttributeType::NestHost)), //stub
|
||||||
//TODO more actual attribute implementations
|
//TODO more actual attribute implementations
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
20
src/heap.rs
20
src/heap.rs
|
|
@ -1,9 +1,9 @@
|
||||||
use std::cell::{RefCell, UnsafeCell};
|
use std::cell::{RefCell, UnsafeCell};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops::Deref;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::class::{Class, UnsafeValue, Value};
|
use crate::class::{Class, Type, UnsafeValue, Value};
|
||||||
|
use crate::heap::ObjectRef::{IntArray, ObjectArray};
|
||||||
|
|
||||||
// can contain object or array
|
// can contain object or array
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -16,10 +16,20 @@ pub enum ObjectRef {
|
||||||
DoubleArray(Vec<f64>),
|
DoubleArray(Vec<f64>),
|
||||||
BooleanArray(Vec<bool>),
|
BooleanArray(Vec<bool>),
|
||||||
CharArray(Vec<char>),
|
CharArray(Vec<char>),
|
||||||
ObjectArray(Vec<Arc<UnsafeCell<ObjectRef>>>),
|
ObjectArray(Type, Vec<Arc<UnsafeCell<ObjectRef>>>),
|
||||||
Object(Box<Object>),
|
Object(Box<Object>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// trying to implement efficient object instance storage
|
// trying to implement efficient object instance storage
|
||||||
pub struct Object {
|
pub struct Object {
|
||||||
// locked: bool,
|
// locked: bool,
|
||||||
|
|
@ -67,7 +77,7 @@ impl Object {
|
||||||
|
|
||||||
pub fn set(&mut self, class_name: &String, field_name: &String, value: UnsafeValue) {
|
pub fn set(&mut self, class_name: &String, field_name: &String, value: UnsafeValue) {
|
||||||
let borrow = self.class.borrow();
|
let borrow = self.class.borrow();
|
||||||
let (_type, index) =borrow
|
let (_type, index) = borrow
|
||||||
.object_field_mapping
|
.object_field_mapping
|
||||||
.get(class_name)
|
.get(class_name)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|
@ -78,7 +88,7 @@ impl Object {
|
||||||
|
|
||||||
pub fn get(&mut self, class_name: &String, field_name: &String) -> &UnsafeValue {
|
pub fn get(&mut self, class_name: &String, field_name: &String) -> &UnsafeValue {
|
||||||
let borrow = self.class.borrow();
|
let borrow = self.class.borrow();
|
||||||
let (_type, index) =borrow
|
let (_type, index) = borrow
|
||||||
.object_field_mapping
|
.object_field_mapping
|
||||||
.get(class_name)
|
.get(class_name)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|
|
||||||
46
src/vm.rs
46
src/vm.rs
|
|
@ -129,6 +129,7 @@ impl Vm {
|
||||||
self.local_stack().push(Value::I32(-1));
|
self.local_stack().push(Value::I32(-1));
|
||||||
}
|
}
|
||||||
ICONST_0 => {
|
ICONST_0 => {
|
||||||
|
println!("ICONST_0");
|
||||||
self.local_stack().push(Value::I32(0));
|
self.local_stack().push(Value::I32(0));
|
||||||
}
|
}
|
||||||
ICONST_1 => {
|
ICONST_1 => {
|
||||||
|
|
@ -190,8 +191,14 @@ impl Vm {
|
||||||
self.local_stack().push(Value::F64(*d));
|
self.local_stack().push(Value::F64(*d));
|
||||||
}
|
}
|
||||||
CpEntry::StringRef(utf8) => {
|
CpEntry::StringRef(utf8) => {
|
||||||
let string = get_class(self, Some(&this_class.borrow().name), "java/lang/String").unwrap();
|
//TODO
|
||||||
self.local_stack().push(Value::Ref(Arc::new(UnsafeCell::new(ObjectRef::Object(Box::new(Object::new(string)))))))
|
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.local_stack().push(Value::Ref(stringinstance));
|
||||||
}
|
}
|
||||||
CpEntry::Long(l) => {
|
CpEntry::Long(l) => {
|
||||||
self.local_stack().push(Value::I64(*l));
|
self.local_stack().push(Value::I64(*l));
|
||||||
|
|
@ -283,7 +290,7 @@ impl Vm {
|
||||||
return self.local_stack().pop();
|
return self.local_stack().pop();
|
||||||
}
|
}
|
||||||
RETURN_VOID => {
|
RETURN_VOID => {
|
||||||
self.stack.pop(); // Void is also returned as a value
|
println!("RETURN");
|
||||||
return Ok(Value::void());
|
return Ok(Value::void());
|
||||||
}
|
}
|
||||||
GETSTATIC => {
|
GETSTATIC => {
|
||||||
|
|
@ -303,7 +310,7 @@ impl Vm {
|
||||||
self.local_stack().push_arc(borrow.static_data.get(*val_index).unwrap().as_ref().unwrap().clone());
|
self.local_stack().push_arc(borrow.static_data.get(*val_index).unwrap().as_ref().unwrap().clone());
|
||||||
}
|
}
|
||||||
PUTSTATIC => {
|
PUTSTATIC => {
|
||||||
println!("putstatic");
|
println!("PUTSTATIC");
|
||||||
let mut borrow = this_class.borrow_mut();
|
let mut borrow = this_class.borrow_mut();
|
||||||
let cp_index = read_u16(&code.opcodes, pc);
|
let cp_index = read_u16(&code.opcodes, pc);
|
||||||
let (class_index, field_name_and_type_index) =
|
let (class_index, field_name_and_type_index) =
|
||||||
|
|
@ -314,7 +321,7 @@ impl Vm {
|
||||||
println!("field {}", name);
|
println!("field {}", name);
|
||||||
let that_class_name = borrow.cp_utf8(class_name_index).unwrap();
|
let that_class_name = borrow.cp_utf8(class_name_index).unwrap();
|
||||||
|
|
||||||
if &borrow.name == that_class_name {
|
if &borrow.name == that_class_name {// may have to apply this in GETSTATIC too
|
||||||
let (_, val_index) = borrow.static_field_mapping.get(that_class_name).unwrap().get(name).as_ref().unwrap();
|
let (_, val_index) = borrow.static_field_mapping.get(that_class_name).unwrap().get(name).as_ref().unwrap();
|
||||||
let val_index = *val_index;
|
let val_index = *val_index;
|
||||||
let value = self.local_stack().pop()?;
|
let value = self.local_stack().pop()?;
|
||||||
|
|
@ -366,6 +373,8 @@ impl Vm {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
INVOKEVIRTUAL | INVOKESPECIAL => unsafe {
|
INVOKEVIRTUAL | INVOKESPECIAL => unsafe {
|
||||||
|
println!("INVOKE");
|
||||||
|
// TODO differentiate these opcodes
|
||||||
let cp_index = read_u16(&code.opcodes, pc);
|
let cp_index = read_u16(&code.opcodes, pc);
|
||||||
if let Some(invocation) =
|
if let Some(invocation) =
|
||||||
get_signature_for_invoke(&method.constant_pool, cp_index)
|
get_signature_for_invoke(&method.constant_pool, cp_index)
|
||||||
|
|
@ -413,6 +422,7 @@ impl Vm {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
NEW => {
|
NEW => {
|
||||||
|
println!("NEW");
|
||||||
let class_index = &read_u16(&code.opcodes, pc);
|
let class_index = &read_u16(&code.opcodes, pc);
|
||||||
let borrow = this_class.borrow();
|
let borrow = this_class.borrow();
|
||||||
let class_name_index = borrow.cp_class_ref(class_index).unwrap();
|
let class_name_index = borrow.cp_class_ref(class_index).unwrap();
|
||||||
|
|
@ -425,6 +435,26 @@ impl Vm {
|
||||||
self.local_stack().push(Value::Ref(Arc::clone(&object)));
|
self.local_stack().push(Value::Ref(Arc::clone(&object)));
|
||||||
self.heap.new_object(object);
|
self.heap.new_object(object);
|
||||||
}
|
}
|
||||||
|
ANEWARRAY => unsafe{
|
||||||
|
println!("ANEWARRAY");
|
||||||
|
let class_index = &read_u16(&code.opcodes, pc);
|
||||||
|
let borrow = this_class.borrow();
|
||||||
|
let class_name_index = borrow.cp_class_ref(class_index).unwrap();
|
||||||
|
let class_name = borrow.cp_utf8(class_name_index).unwrap();
|
||||||
|
let arraytype = get_class(self, Some(&borrow.name), class_name)?;
|
||||||
|
let count = self.local_stack().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));
|
||||||
|
|
||||||
|
self.local_stack().push(Value::Ref(Arc::clone(&array)));
|
||||||
|
println!("{}",self.local_stack().len());
|
||||||
|
self.heap.new_object(array);
|
||||||
|
} else {
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
//TODO implement all opcodes
|
//TODO implement all opcodes
|
||||||
_ => {
|
_ => {
|
||||||
|
|
@ -470,9 +500,9 @@ impl Vm {
|
||||||
ObjectRef::DoubleArray(ref array) => {
|
ObjectRef::DoubleArray(ref array) => {
|
||||||
self.local_stack().push(Value::F64(array[index]));
|
self.local_stack().push(Value::F64(array[index]));
|
||||||
}
|
}
|
||||||
ObjectRef::ObjectArray(ref array) => {
|
ObjectRef::ObjectArray(_arraytype, ref data) => {
|
||||||
self.local_stack()
|
self.local_stack()
|
||||||
.push(Value::Ref(array.get(index).unwrap().clone()));
|
.push(Value::Ref(data[index].clone()));
|
||||||
}
|
}
|
||||||
ObjectRef::Object(_) => {} //throw error?
|
ObjectRef::Object(_) => {} //throw error?
|
||||||
}
|
}
|
||||||
|
|
@ -535,7 +565,7 @@ impl Vm {
|
||||||
array[*index as usize] = value
|
array[*index as usize] = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ObjectRef::ObjectArray(ref mut array) => {
|
ObjectRef::ObjectArray(arraytype, ref mut array) => {
|
||||||
if let Value::Ref(ref value) = *value.get() {
|
if let Value::Ref(ref value) = *value.get() {
|
||||||
array[*index as usize] = value.clone();
|
array[*index as usize] = value.clone();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
BIN
tests/Main.class
BIN
tests/Main.class
Binary file not shown.
|
|
@ -9,6 +9,6 @@ public class Main {
|
||||||
public static void main(String[] args){
|
public static void main(String[] args){
|
||||||
FloatBean f = new FloatBean();
|
FloatBean f = new FloatBean();
|
||||||
f.setValue(42F);
|
f.setValue(42F);
|
||||||
System.out.println(f.getValue());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue