diff --git a/src/class.rs b/src/class.rs index 41207b6..3c67d89 100644 --- a/src/class.rs +++ b/src/class.rs @@ -1,16 +1,19 @@ -use std::cell::{RefCell, UnsafeCell}; -use crate::classloader::CpEntry; -use crate::heap::{Object, ObjectRef}; -use anyhow::{anyhow, Error}; +use std::cell::UnsafeCell; use std::collections::HashMap; use std::fmt; use std::hash::Hash; use std::rc::Rc; use std::sync::Arc; +use anyhow::{anyhow, Error}; + +use crate::classloader::CpEntry; +use crate::heap::ObjectRef; use crate::io::read_u16; -// the class definition as read from the class file + derived values +/// the class definition as read from the class file + derived values +// TODO implement call to static initializers +// TODO implement storage for static fields #[derive(Debug)] pub struct Class { pub minor_version: u16, @@ -25,7 +28,7 @@ pub struct Class { pub fields: HashMap, pub methods: HashMap, pub attributes: HashMap, - pub(crate) field_mapping: Option>>, // first key: this/super/supersuper-name(etc), second key: fieldname, value (type, index) + pub(crate) field_mapping: Option>>, // first key: this/super/supersuper-name(etc), second key: fieldname, value (type, index). See below } impl Class { diff --git a/src/heap.rs b/src/heap.rs index 7b37629..9baefb6 100644 --- a/src/heap.rs +++ b/src/heap.rs @@ -12,7 +12,7 @@ pub struct Object { // locked: bool, // hashcode: i32, pub class: Rc, - pub data: Option>>>, + pub data: Vec>>, }//arrays // can contain object or array @@ -37,14 +37,15 @@ unsafe impl Sync for Object {} // object, not array impl Object { pub fn new(class: Rc) -> Self { - Self { class, data: None } + let instance_data = Object::init_fields(&class); + Self { class, data: instance_data} } // initializes all non-static fields to their default values - pub(crate) fn init_fields(&mut self) { - let mut field_data = Vec::with_capacity(self.class.n_fields()); + pub(crate) fn init_fields(class: &Class) -> Vec>>{ + let mut field_data = Vec::with_capacity(class.n_fields()); - for (_, fields) in self.class.field_mapping.as_ref().unwrap() { + for (_, fields) in class.field_mapping.as_ref().unwrap() { for (_, (fieldtype, _)) in fields { let value = match fieldtype.as_str() { "Z" => Value::BOOL(false), @@ -61,19 +62,17 @@ impl Object { } } - self.data = Some(field_data); + field_data } pub fn set(&mut self, class_name: &String, field_name: &String, value: Arc>) { - let p = self.class.field_mapping.as_ref().unwrap(); - let p2 = p.get(class_name).unwrap(); - let (_type, index) = p2.get(field_name).unwrap(); - self.data.as_mut().unwrap()[*index] = value; + let (_type, index) = self.class.field_mapping.as_ref().unwrap().get(class_name).unwrap().get(field_name).unwrap(); + self.data[*index] = value; } pub fn get(&mut self, class_name: &String, field_name: &String) -> &Arc> { - let (_type, index) = &self.class.field_mapping.as_ref().unwrap().get(class_name).unwrap().get(field_name).unwrap(); // (index, type) - &self.data.as_ref().unwrap()[*index] + let (_type, index) = &self.class.field_mapping.as_ref().unwrap().get(class_name).unwrap().get(field_name).unwrap(); + &self.data[*index] } fn get_field_name(&self, cp_index: &u16) -> &str { diff --git a/src/vm.rs b/src/vm.rs index 0c9883c..b759c7d 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -100,11 +100,7 @@ impl Vm { pub fn new_instance(class: Rc) -> Object { let mut class = class; - // let mut outer = HashMap::new(); - //TODO - let mut instance = Object::new(class.clone()); - instance.init_fields(); instance } @@ -317,24 +313,9 @@ impl Vm { } } } - INVOKEVIRTUAL => unsafe { + INVOKEVIRTUAL | INVOKESPECIAL => unsafe { let cp_index = read_u16(&code.opcodes, pc); - if let Some(invocation) = get_signature_for_invoke(Rc::clone(&method.constant_pool), cp_index) { - let mut args = Vec::with_capacity(invocation.method.num_args); - for _ in 0..invocation.method.num_args { - args.insert(0, self.local_stack().pop()?); - } - args.insert(0, self.local_stack().pop()?); - let mut returnvalue = self.execute(&invocation.class_name, &invocation.method.name, args)?; - match *returnvalue.get() { - Void => {} - _ => { self.local_stack().push_arc(returnvalue.clone()); } - } - } - } - INVOKESPECIAL => unsafe { - let cp_index = read_u16(&code.opcodes, pc); - if let Some(invocation) = get_signature_for_invoke(Rc::clone(&method.constant_pool), cp_index) { + if let Some(invocation) = get_signature_for_invoke(&method.constant_pool, cp_index) { let mut args = Vec::with_capacity(invocation.method.num_args); for _ in 0..invocation.method.num_args { args.insert(0, self.local_stack().pop()?); @@ -348,22 +329,16 @@ impl Vm { } } NEW => { - let class_index = read_u16(&code.opcodes, pc); - println!("cp_index {}", class_index); - if let CpEntry::ClassRef(class_name_index) = - method.constant_pool.get(&class_index).unwrap() - { - if let CpEntry::Utf8(new_class) = - method.constant_pool.get(class_name_index).unwrap() - { - println!("new {}", new_class); - let class = self.get_class(new_class)?; - let object = Arc::new(UnsafeCell::new(ObjectRef::Object(Box::new(Vm::new_instance(class))))); - self.local_stack().push(Value::Ref(Arc::clone(&object))); - self.heap.new_object(object); - } - } + let class_index = &read_u16(&code.opcodes, pc); + let class_name_index = class.get_class_ref(class_index).unwrap(); + let class_name = class.get_utf8(class_name_index).unwrap(); + let class = self.get_class(class_name)?; + + let object = Arc::new(UnsafeCell::new(ObjectRef::Object(Box::new(Vm::new_instance(class))))); + self.local_stack().push(Value::Ref(Arc::clone(&object))); + self.heap.new_object(object); } + //TODO implement all opcodes _ => { panic!("opcode not implemented {:?}", self.stack) @@ -503,7 +478,7 @@ struct MethodSignature { num_args: usize, } -fn get_signature_for_invoke(cp: Rc>, index: u16) -> Option { +fn get_signature_for_invoke(cp: &Rc>, index: u16) -> Option { if let CpEntry::MethodRef(class_index, name_and_type_index) = cp.get(&index).unwrap() { if let Some(method_signature) = get_name_and_type(Rc::clone(&cp), *name_and_type_index) { if let CpEntry::ClassRef(class_name_index) = cp.get(class_index).unwrap() {