small improvements
This commit is contained in:
parent
6cf0365dd0
commit
1e6f7956e8
3 changed files with 32 additions and 55 deletions
15
src/class.rs
15
src/class.rs
|
|
@ -1,16 +1,19 @@
|
||||||
use std::cell::{RefCell, UnsafeCell};
|
use std::cell::UnsafeCell;
|
||||||
use crate::classloader::CpEntry;
|
|
||||||
use crate::heap::{Object, ObjectRef};
|
|
||||||
use anyhow::{anyhow, Error};
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use anyhow::{anyhow, Error};
|
||||||
|
|
||||||
|
use crate::classloader::CpEntry;
|
||||||
|
use crate::heap::ObjectRef;
|
||||||
use crate::io::read_u16;
|
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)]
|
#[derive(Debug)]
|
||||||
pub struct Class {
|
pub struct Class {
|
||||||
pub minor_version: u16,
|
pub minor_version: u16,
|
||||||
|
|
@ -25,7 +28,7 @@ pub struct Class {
|
||||||
pub fields: HashMap<String, Field>,
|
pub fields: HashMap<String, Field>,
|
||||||
pub methods: HashMap<String, Method>,
|
pub methods: HashMap<String, Method>,
|
||||||
pub attributes: HashMap<String, AttributeType>,
|
pub attributes: HashMap<String, AttributeType>,
|
||||||
pub(crate) field_mapping: Option<HashMap<String, HashMap<String, (String, usize)>>>, // first key: this/super/supersuper-name(etc), second key: fieldname, value (type, index)
|
pub(crate) field_mapping: Option<HashMap<String, HashMap<String, (String, usize)>>>, // first key: this/super/supersuper-name(etc), second key: fieldname, value (type, index). See below
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Class {
|
impl Class {
|
||||||
|
|
|
||||||
23
src/heap.rs
23
src/heap.rs
|
|
@ -12,7 +12,7 @@ pub struct Object {
|
||||||
// locked: bool,
|
// locked: bool,
|
||||||
// hashcode: i32,
|
// hashcode: i32,
|
||||||
pub class: Rc<Class>,
|
pub class: Rc<Class>,
|
||||||
pub data: Option<Vec<Arc<UnsafeCell<Value>>>>,
|
pub data: Vec<Arc<UnsafeCell<Value>>>,
|
||||||
}//arrays
|
}//arrays
|
||||||
|
|
||||||
// can contain object or array
|
// can contain object or array
|
||||||
|
|
@ -37,14 +37,15 @@ unsafe impl Sync for Object {}
|
||||||
// object, not array
|
// object, not array
|
||||||
impl Object {
|
impl Object {
|
||||||
pub fn new(class: Rc<Class>) -> Self {
|
pub fn new(class: Rc<Class>) -> 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
|
// initializes all non-static fields to their default values
|
||||||
pub(crate) fn init_fields(&mut self) {
|
pub(crate) fn init_fields(class: &Class) -> Vec<Arc<UnsafeCell<Value>>>{
|
||||||
let mut field_data = Vec::with_capacity(self.class.n_fields());
|
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 {
|
for (_, (fieldtype, _)) in fields {
|
||||||
let value = match fieldtype.as_str() {
|
let value = match fieldtype.as_str() {
|
||||||
"Z" => Value::BOOL(false),
|
"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<UnsafeCell<Value>>) {
|
pub fn set(&mut self, class_name: &String, field_name: &String, value: Arc<UnsafeCell<Value>>) {
|
||||||
let p = self.class.field_mapping.as_ref().unwrap();
|
let (_type, index) = self.class.field_mapping.as_ref().unwrap().get(class_name).unwrap().get(field_name).unwrap();
|
||||||
let p2 = p.get(class_name).unwrap();
|
self.data[*index] = value;
|
||||||
let (_type, index) = p2.get(field_name).unwrap();
|
|
||||||
self.data.as_mut().unwrap()[*index] = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&mut self, class_name: &String, field_name: &String) -> &Arc<UnsafeCell<Value>> {
|
pub fn get(&mut self, class_name: &String, field_name: &String) -> &Arc<UnsafeCell<Value>> {
|
||||||
let (_type, index) = &self.class.field_mapping.as_ref().unwrap().get(class_name).unwrap().get(field_name).unwrap(); // (index, type)
|
let (_type, index) = &self.class.field_mapping.as_ref().unwrap().get(class_name).unwrap().get(field_name).unwrap();
|
||||||
&self.data.as_ref().unwrap()[*index]
|
&self.data[*index]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_field_name(&self, cp_index: &u16) -> &str {
|
fn get_field_name(&self, cp_index: &u16) -> &str {
|
||||||
|
|
|
||||||
49
src/vm.rs
49
src/vm.rs
|
|
@ -100,11 +100,7 @@ impl Vm {
|
||||||
|
|
||||||
pub fn new_instance(class: Rc<Class>) -> Object {
|
pub fn new_instance(class: Rc<Class>) -> Object {
|
||||||
let mut class = class;
|
let mut class = class;
|
||||||
// let mut outer = HashMap::new();
|
|
||||||
//TODO
|
|
||||||
|
|
||||||
let mut instance = Object::new(class.clone());
|
let mut instance = Object::new(class.clone());
|
||||||
instance.init_fields();
|
|
||||||
instance
|
instance
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -317,24 +313,9 @@ impl Vm {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
INVOKEVIRTUAL => unsafe {
|
INVOKEVIRTUAL | INVOKESPECIAL => unsafe {
|
||||||
let cp_index = read_u16(&code.opcodes, pc);
|
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()?);
|
|
||||||
}
|
|
||||||
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) {
|
|
||||||
let mut args = Vec::with_capacity(invocation.method.num_args);
|
let mut args = Vec::with_capacity(invocation.method.num_args);
|
||||||
for _ in 0..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()?);
|
||||||
|
|
@ -348,22 +329,16 @@ impl Vm {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NEW => {
|
NEW => {
|
||||||
let class_index = read_u16(&code.opcodes, pc);
|
let class_index = &read_u16(&code.opcodes, pc);
|
||||||
println!("cp_index {}", class_index);
|
let class_name_index = class.get_class_ref(class_index).unwrap();
|
||||||
if let CpEntry::ClassRef(class_name_index) =
|
let class_name = class.get_utf8(class_name_index).unwrap();
|
||||||
method.constant_pool.get(&class_index).unwrap()
|
let class = self.get_class(class_name)?;
|
||||||
{
|
|
||||||
if let CpEntry::Utf8(new_class) =
|
let object = Arc::new(UnsafeCell::new(ObjectRef::Object(Box::new(Vm::new_instance(class)))));
|
||||||
method.constant_pool.get(class_name_index).unwrap()
|
self.local_stack().push(Value::Ref(Arc::clone(&object)));
|
||||||
{
|
self.heap.new_object(object);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO implement all opcodes
|
//TODO implement all opcodes
|
||||||
_ => {
|
_ => {
|
||||||
panic!("opcode not implemented {:?}", self.stack)
|
panic!("opcode not implemented {:?}", self.stack)
|
||||||
|
|
@ -503,7 +478,7 @@ struct MethodSignature {
|
||||||
num_args: usize,
|
num_args: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_signature_for_invoke(cp: Rc<HashMap<u16, CpEntry>>, index: u16) -> Option<Invocation> {
|
fn get_signature_for_invoke(cp: &Rc<HashMap<u16, CpEntry>>, index: u16) -> Option<Invocation> {
|
||||||
if let CpEntry::MethodRef(class_index, name_and_type_index) = cp.get(&index).unwrap() {
|
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 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() {
|
if let CpEntry::ClassRef(class_name_index) = cp.get(class_index).unwrap() {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue