WIP statin initializers

This commit is contained in:
Shautvast 2023-10-16 09:10:55 +02:00
parent b46145719c
commit 24f03f61f6
9 changed files with 240 additions and 141 deletions

View file

@ -1,4 +1,4 @@
use std::cell::UnsafeCell; use std::cell::{Ref, RefCell, RefMut, UnsafeCell};
use std::collections::HashMap; use std::collections::HashMap;
use std::fmt; use std::fmt;
use std::hash::Hash; use std::hash::Hash;
@ -6,14 +6,52 @@ use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
use anyhow::{anyhow, Error}; use anyhow::{anyhow, Error};
use once_cell::sync::Lazy;
use crate::classloader::CpEntry; use crate::classloader::{CpEntry, load_class};
use crate::heap::ObjectRef; use crate::heap::ObjectRef;
use crate::io::read_u16; use crate::io::{find_class, read_bytecode, read_u16};
use crate::vm::Vm;
//trying to be ready for multithreaded as much as possible, using Arc's and all, but it will still require (a lot of) extra work
static mut CLASSDEFS: Lazy<HashMap<String, Arc<RefCell<Class>>>> = Lazy::new(|| HashMap::new()); //TODO add mutex..
// gets the Class from cache, or reads it from classpath,
// then parses the binary data into a Class struct
// Vm keeps ownership of the class and hands out Arc references to it
pub fn get_class(vm: &mut Vm, class_name: &str) -> Result<Arc<RefCell<Class>>, Error> {
println!("get_class {}", class_name);
unsafe {
let new_class = CLASSDEFS.entry(class_name.into()).or_insert_with(|| {
println!("read class {} ", class_name);
let resolved_path = find_class(&vm.classpath, class_name).unwrap();
// println!("full path {}", resolved_path);
let bytecode = read_bytecode(resolved_path).unwrap();
let mut class = load_class(bytecode).unwrap();
let super_class_name = class.super_class_name.as_ref();
if let Some(super_class_name) = super_class_name {
if let Ok(super_class) = get_class(vm, &super_class_name) {
class.super_class = Some(super_class);
}
}
Arc::new(RefCell::new(class))
});
Class::initialize_fields(new_class.clone());
let exec = new_class.borrow().methods.contains_key("<clinit>()V");
if exec {
vm.execute_class(new_class.clone(), "<clinit>()V", vec![]).unwrap();
}
Ok(new_class.clone())
}
}
/// 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 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,
@ -22,13 +60,17 @@ 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<Class>>, pub super_class: Option<Arc<RefCell<Class>>>,
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>,
pub methods: HashMap<String, Method>, pub methods: HashMap<String, Rc<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) object_field_mapping: HashMap<String, HashMap<String, (String, usize)>>,
// first key: this/super/supersuper-name(etc), second key: fieldname, value (type, index)
pub(crate) static_field_mapping: HashMap<String, HashMap<String, (String, usize)>>,
// first key: this/super/supersuper-name(etc), second key: fieldname, value (type, index)
pub(crate) static_data: Vec<UnsafeValue>,
} }
impl Class { impl Class {
@ -41,7 +83,7 @@ impl Class {
super_class_index: u16, super_class_index: u16,
interface_indices: Vec<u16>, interface_indices: Vec<u16>,
fields: HashMap<String, Field>, fields: HashMap<String, Field>,
methods: HashMap<String, Method>, methods: HashMap<String, Rc<Method>>,
attributes: HashMap<String, AttributeType>, attributes: HashMap<String, AttributeType>,
) -> Self { ) -> Self {
let name = Class::class_name(this_class, constant_pool.clone()).unwrap(); let name = Class::class_name(this_class, constant_pool.clone()).unwrap();
@ -60,12 +102,18 @@ impl Class {
fields, fields,
methods, methods,
attributes, attributes,
field_mapping: None, object_field_mapping: HashMap::new(),
static_field_mapping: HashMap::new(),
static_data: vec![],
} }
} }
pub(crate) fn n_fields(&self) -> usize { pub(crate) fn n_object_fields(&self) -> usize {
self.field_mapping.as_ref().map_or(0, |m| m.len()) self.object_field_mapping.len()
}
pub(crate) fn n_static_fields(&self) -> usize {
self.object_field_mapping.len()
} }
// Create a mapping per field(name) to an index in the storage vector that contains the instance data. // Create a mapping per field(name) to an index in the storage vector that contains the instance data.
@ -76,42 +124,64 @@ impl Class {
// This way `this.a` can be differentiated from `super.a`. // This way `this.a` can be differentiated from `super.a`.
// //
// this method looks up this and super classes and calls map_fields for each. // this method looks up this and super classes and calls map_fields for each.
pub fn initialize(&mut self) { pub fn initialize_fields(class: Arc<RefCell<Class>>) {
let mut field_mapping = HashMap::new(); let mut this_field_mapping = HashMap::new();
let mut static_field_mapping = HashMap::new();
let mut field_map_index: usize = 0; let mut field_map_index: usize = 0;
Class::map_fields(&mut field_mapping, self, &mut field_map_index); Class::add_field_mappings(&mut this_field_mapping, &mut static_field_mapping, class.clone(), &mut field_map_index);
let mut sooper = &self.super_class;
while let Some(super_class) = sooper { class.borrow_mut().object_field_mapping = this_field_mapping;
Class::map_fields(&mut field_mapping, super_class, &mut field_map_index); class.borrow_mut().static_field_mapping = static_field_mapping;
sooper = &super_class.super_class;
let static_data = Class::set_field_data(class.clone());
class.borrow_mut().static_data = static_data;
}
fn add_field_mappings(this_field_mapping: &mut HashMap<String, HashMap<String, (String, usize)>>,
static_field_mapping: &mut HashMap<String, HashMap<String, (String, usize)>>,
class: Arc<RefCell<Class>>, field_map_index: &mut usize) {
let (o, s) = Class::map_fields(class.clone(), field_map_index);
let borrow = class.borrow();
let name = &borrow.name;
this_field_mapping.insert(name.to_owned(), o);
static_field_mapping.insert(name.to_owned(), s);
if let Some(super_class) = class.borrow().super_class.as_ref() {
Class::add_field_mappings(this_field_mapping, static_field_mapping, super_class.clone(), field_map_index);
} }
self.field_mapping = Some(field_mapping);
} }
// part of the initialize procedure // part of the initialize procedure
fn map_fields( fn map_fields(
field_mapping: &mut HashMap<String, HashMap<String, (String, usize)>>, class: Arc<RefCell<Class>>,
class: &Class,
field_map_index: &mut usize, field_map_index: &mut usize,
) { ) -> (HashMap<String, (String, usize)>, HashMap<String, (String, usize)>) {
let mut this_fields = HashMap::new(); //fields in class are stored per class and every superclass. let mut this_fields = HashMap::new(); //fields in class are stored per class and every superclass.
for field in &class.fields { let mut static_fields = HashMap::new(); //fields in class are stored per class and every superclass.
this_fields.insert(
field.0.to_owned(), for (name, field) in &class.borrow().fields {
(field.1.type_of().to_owned(), *field_map_index), if field.is(Modifier::Static) {
); //name => (type,index) static_fields.insert(
name.to_owned(),
(field.type_of().to_owned(), *field_map_index),
);
} else {
this_fields.insert(
name.to_owned(),
(field.type_of().to_owned(), *field_map_index),
); //name => (type,index)
}
*field_map_index += 1; *field_map_index += 1;
} }
let this_name = class.name.to_owned(); (this_fields, static_fields)
field_mapping.insert(this_name, this_fields);
} }
pub fn get_version(&self) -> (u16, u16) { pub fn get_version(&self) -> (u16, u16) {
(self.major_version, self.minor_version) (self.major_version, self.minor_version)
} }
pub fn get_method(&self, name: &str) -> Result<&Method, Error> { pub fn get_method(&self, name: &str) -> Result<&Rc<Method>, Error> {
self.methods self.methods
.get(name) .get(name)
.ok_or(anyhow!("Method {} not found", name)) .ok_or(anyhow!("Method {} not found", name))
@ -135,6 +205,29 @@ impl Class {
} }
} }
pub(crate) fn set_field_data(class: Arc<RefCell<Class>>) -> Vec<UnsafeValue> {
let mut field_data = Vec::with_capacity(class.borrow().n_object_fields());
for (_, fields) in &class.borrow().static_field_mapping {
for (_, (fieldtype, _)) in fields {
let value = match fieldtype.as_str() {
"Z" => Value::BOOL(false),
"B" => Value::I32(0),
"S" => Value::I32(0),
"I" => Value::I32(0),
"J" => Value::I64(0),
"F" => Value::F32(0.0),
"D" => Value::F64(0.0),
"L" => Value::Null,
_ => Value::Void,
};
field_data.push(value.into());
}
}
field_data
}
// convienence methods for data from the constantpool // convienence methods for data from the constantpool
pub fn cp_field_ref(&self, index: &u16) -> Option<(&u16, &u16)> { pub fn cp_field_ref(&self, index: &u16) -> Option<(&u16, &u16)> {
@ -281,6 +374,11 @@ impl Field {
} }
} }
pub fn is(&self, modifier: Modifier) -> bool {
let modifier = modifier as u16;
self.access_flags & modifier == modifier
}
pub fn name(&self) -> &String { pub fn name(&self) -> &String {
if let CpEntry::Utf8(utf8) = &self.constant_pool.get(&self.name_index).unwrap() { if let CpEntry::Utf8(utf8) = &self.constant_pool.get(&self.name_index).unwrap() {
return utf8; return utf8;

View file

@ -48,7 +48,7 @@ pub fn load_class(bytecode: Vec<u8>) -> Result<Class, Error> {
let mut methods = HashMap::new(); let mut methods = HashMap::new();
for _ in 0..methods_count { for _ in 0..methods_count {
let m = read_method(constant_pool.clone(), pos, &bytecode); let m = read_method(constant_pool.clone(), pos, &bytecode);
methods.insert(m.name(), m); methods.insert(m.name(), Rc::new(m));
} }
let attributes_count = read_u16(&bytecode, pos); let attributes_count = read_u16(&bytecode, pos);

View file

@ -1,17 +1,9 @@
use std::cell::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, UnsafeValue, Value};
use crate::classloader::CpEntry;
// trying to implement efficient object instance storage
pub struct Object {
// locked: bool,
// hashcode: i32,
pub class: Arc<Class>,
pub data: Vec<UnsafeValue>,
} //arrays
// can contain object or array // can contain object or array
#[derive(Debug)] #[derive(Debug)]
@ -28,14 +20,22 @@ pub enum ObjectRef {
Object(Box<Object>), Object(Box<Object>),
} }
// trying to implement efficient object instance storage
pub struct Object {
// locked: bool,
// hashcode: i32,
pub class: Arc<RefCell<Class>>,
pub data: Vec<UnsafeValue>,
} //arrays
unsafe impl Send for Object {} unsafe impl Send for Object {}
unsafe impl Sync for Object {} unsafe impl Sync for Object {}
// object, not array // object, not array
impl Object { impl Object {
pub fn new(class: Arc<Class>) -> Self { pub fn new(class: Arc<RefCell<Class>>) -> Self {
let instance_data = Object::init_fields(&class); let instance_data = Object::init_fields(class.clone());
Self { Self {
class, class,
data: instance_data, data: instance_data,
@ -43,10 +43,10 @@ impl Object {
} }
// initializes all non-static fields to their default values // initializes all non-static fields to their default values
pub(crate) fn init_fields(class: &Class) -> Vec<UnsafeValue> { pub(crate) fn init_fields(class: Arc<RefCell<Class>>) -> Vec<UnsafeValue> {
let mut field_data = Vec::with_capacity(class.n_fields()); let mut field_data = Vec::with_capacity(class.borrow().n_object_fields());
for (_, fields) in class.field_mapping.as_ref().unwrap() { for (_, fields) in &class.borrow().object_field_mapping {
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),
@ -67,11 +67,9 @@ 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 (_type, index) = self let borrow = self.class.borrow();
.class let (_type, index) =borrow
.field_mapping .object_field_mapping
.as_ref()
.unwrap()
.get(class_name) .get(class_name)
.unwrap() .unwrap()
.get(field_name) .get(field_name)
@ -80,11 +78,9 @@ 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 (_type, index) = &self let borrow = self.class.borrow();
.class let (_type, index) =borrow
.field_mapping .object_field_mapping
.as_ref()
.unwrap()
.get(class_name) .get(class_name)
.unwrap() .unwrap()
.get(field_name) .get(field_name)
@ -92,12 +88,12 @@ impl Object {
&self.data[*index] &self.data[*index]
} }
fn get_field_name(&self, cp_index: &u16) -> &str { // fn get_field_name(&self, cp_index: &u16) -> &str {
if let CpEntry::Utf8(name) = self.class.constant_pool.get(cp_index).unwrap() { // if let CpEntry::Utf8(name) = self.class.constant_pool.get(cp_index).unwrap() {
return name; // return name;
} // }
panic!() // panic!()
} // }
} }
impl fmt::Debug for Object { impl fmt::Debug for Object {
@ -109,7 +105,7 @@ impl fmt::Debug for Object {
// // r // // r
// } // }
// ).collect(); // ).collect();
write!(f, "{}", self.class.name) write!(f, "{}", self.class.borrow().name)
} }
} }

View file

@ -6,7 +6,8 @@ fn main() -> Result<(), Error> {
// TODO build index for package -> jarfile? // TODO build index for package -> jarfile?
let mut vm = Vm::new("tests"); let mut vm = Vm::new("tests");
let main_class = "Inheritance"; // let main_class = "Inheritance";
let main_class = "Main";
vm.execute(main_class, "main([Ljava/lang/String;)V", vec![]) vm.execute(main_class, "main([Ljava/lang/String;)V", vec![])
.unwrap(); .unwrap();

View file

@ -1,8 +1,9 @@
use std::sync::Arc; use std::rc::Rc;
use crate::class::{Method, UnsafeValue, Value};
use crate::class::{Class, Method, UnsafeValue, Value}; pub fn invoke_native(method: Rc<Method>, args: Vec<UnsafeValue>) -> UnsafeValue {
println!("native {}", method.name());
pub fn invoke_native(class: Arc<Class>, method: &Method) -> UnsafeValue {
println!("invoke native {:?}.{:?}", class.name, method.name());
Value::void() Value::void()
} }

View file

@ -125,6 +125,7 @@ pub const DRETURN: u8 = 175; // (0xaf) Return double from method
pub const areturn: u8 = 176; //(0xb0) return reference pub const areturn: u8 = 176; //(0xb0) return reference
pub const RETURN_VOID: u8 = 177; // (0xb1) Return void from method (actually 'return' but that's a keyword) pub const RETURN_VOID: u8 = 177; // (0xb1) Return void from method (actually 'return' but that's a keyword)
pub const GETSTATIC: u8 = 178; // (0xb2) Get static field from class pub const GETSTATIC: u8 = 178; // (0xb2) Get static field from class
pub const PUTSTATIC: u8 = 179; // (0xb3) Set static field in class
pub const GETFIELD: u8 = 180; // (0xb4) Fetch field from object3 pub const GETFIELD: u8 = 180; // (0xb4) Fetch field from object3
pub const PUTFIELD: u8 = 181; // (0xb5) Set field in object pub const PUTFIELD: u8 = 181; // (0xb5) Set field in object
pub const INVOKEVIRTUAL: u8 = 182; // (0xb6) Invoke instance method; dispatch based on class pub const INVOKEVIRTUAL: u8 = 182; // (0xb6) Invoke instance method; dispatch based on class

140
src/vm.rs
View file

@ -1,14 +1,13 @@
use std::cell::UnsafeCell; use std::cell::{RefCell, UnsafeCell};
use std::collections::HashMap; use std::collections::HashMap;
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
use anyhow::{anyhow, Error}; use anyhow::{anyhow, Error};
use once_cell::unsync::Lazy;
use crate::class::{AttributeType, Class, get_class, Modifier, UnsafeValue, Value};
use crate::class::Value::Void; use crate::class::Value::Void;
use crate::class::{AttributeType, Class, Modifier, UnsafeValue, Value}; use crate::classloader::CpEntry;
use crate::classloader::{load_class, CpEntry};
use crate::heap::{Heap, Object, ObjectRef}; use crate::heap::{Heap, Object, ObjectRef};
use crate::io::*; use crate::io::*;
use crate::native::invoke_native; use crate::native::invoke_native;
@ -42,11 +41,9 @@ impl StackFrame {
} }
} }
//trying to be ready for multithreaded as much as possible, using Arc's and all, but it will still require (a lot of) extra work
static mut CLASSDEFS: Lazy<HashMap<String, Arc<Class>>> = Lazy::new(|| HashMap::new()); //TODO add mutex..
pub struct Vm { pub struct Vm {
classpath: Vec<String>, pub classpath: Vec<String>,
heap: Heap, heap: Heap,
stack: Vec<StackFrame>, stack: Vec<StackFrame>,
} }
@ -77,35 +74,8 @@ impl Vm {
} }
} }
// gets the Class from cache, or reads it from classpath,
// then parses the binary data into a Class struct
// Vm keeps ownership of the class and hands out Arc references to it
pub fn get_class(&self, class_name: &str) -> Result<Arc<Class>, Error> {
println!("get_class {}", class_name);
unsafe {
let entry = CLASSDEFS.entry(class_name.into());
let entry = entry.or_insert_with(|| {
println!("read class {} ", class_name);
let resolved_path = find_class(&self.classpath, class_name).unwrap();
// println!("full path {}", resolved_path);
let bytecode = read_bytecode(resolved_path).unwrap();
let mut class = load_class(bytecode).unwrap();
let super_class_name = class.super_class_name.as_ref();
if let Some(super_class_name) = super_class_name {
if let Ok(super_class) = self.get_class(&super_class_name) {
class.super_class = Some(super_class.clone());
}
}
class.initialize();
Arc::new(class) pub fn new_instance(class: Arc<RefCell<Class>>) -> Object {
});
Ok(entry.clone())
}
}
pub fn new_instance(class: Arc<Class>) -> Object {
let mut class = class;
let mut instance = Object::new(class.clone()); let mut instance = Object::new(class.clone());
instance instance
} }
@ -118,25 +88,27 @@ impl Vm {
method_name: &str, method_name: &str,
args: Vec<UnsafeValue>, args: Vec<UnsafeValue>,
) -> Result<UnsafeValue, Error> { ) -> Result<UnsafeValue, Error> {
let class = get_class(self, class_name)?;
self.execute_class(class, method_name, args)
}
pub fn execute_class(
&mut self,
class: Arc<RefCell<Class>>,
method_name: &str,
args: Vec<UnsafeValue>,
) -> Result<UnsafeValue, Error> {
let this_class = class;
println!("execute {}.{}", this_class.borrow().name, method_name);
let method = this_class.clone().borrow().get_method(method_name)?.clone();
let mut local_params: Vec<Option<UnsafeValue>> = let mut local_params: Vec<Option<UnsafeValue>> =
args.clone().iter().map(|e| Some(e.clone())).collect(); args.clone().iter().map(|e| Some(e.clone())).collect();
println!("execute {}.{}", class_name, method_name);
let class = self.get_class(class_name)?;
let method = class.get_method(method_name)?;
if method.is(Modifier::Native) { if method.is(Modifier::Native) {
let return_value = invoke_native(class.clone(), method); return Ok(invoke_native(method, args));
unsafe {
match *return_value.get() {
Void => {}
_ => {
self.local_stack().push_arc(return_value.clone());
}
}
}
} }
if let AttributeType::Code(code) = method.attributes.get("Code").unwrap() { if let AttributeType::Code(code) = method.attributes.get("Code").unwrap() {
let stackframe = StackFrame::new(class_name, method_name); let stackframe = StackFrame::new(&this_class.borrow().name, &method.name());
self.stack.push(stackframe); self.stack.push(stackframe);
let mut pc = &mut 0; let mut pc = &mut 0;
@ -297,23 +269,45 @@ impl Vm {
return Ok(Value::void()); return Ok(Value::void());
} }
GETSTATIC => { GETSTATIC => {
let cp_index = read_u16(&code.opcodes, pc); let borrow = this_class.borrow();
let (class_index, _field_name_and_type_index) =
class.cp_field_ref(&cp_index).unwrap(); // all these unwraps are safe as long as the class is valid
let class_name_index = class.cp_class_ref(class_index).unwrap();
let class_name = class.cp_utf8(class_name_index).unwrap();
let class = self.get_class(class_name.as_str())?;
// println!("{:?}", class); //TODO
}
GETFIELD => unsafe {
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) =
class.cp_field_ref(&cp_index).unwrap(); borrow.cp_field_ref(&cp_index).unwrap(); // all these unwraps are safe as long as the class is valid
let (name_index, _) = borrow.cp_name_and_type(field_name_and_type_index).unwrap();
let (name) = borrow.cp_utf8(name_index).unwrap();
let class_name_index = borrow.cp_class_ref(class_index).unwrap();
let class_name = borrow.cp_utf8(class_name_index).unwrap();
let that = get_class(self, class_name.as_str())?;
let borrow = that.borrow();
let (_, val_index) = borrow.static_field_mapping.get(class_name).unwrap().get(name).unwrap();
self.local_stack().push_arc(this_class.borrow().static_data.get(*val_index).unwrap().clone());
}
PUTSTATIC => {
println!("putstatic");
let mut borrow = this_class.borrow_mut();
let cp_index = read_u16(&code.opcodes, pc);
let (class_index, field_name_and_type_index) =
borrow.cp_field_ref(&cp_index).unwrap(); // all these unwraps are safe as long as the class is valid
let (name_index, _) = borrow.cp_name_and_type(field_name_and_type_index).unwrap();
let (name) = borrow.cp_utf8(name_index).unwrap();
let class_name_index = borrow.cp_class_ref(class_index).unwrap();
let class_name = borrow.cp_utf8(class_name_index).unwrap();
let that = get_class(self, class_name.as_str())?;
let that_borrow = that.borrow();
let (_, val_index) = that_borrow.static_field_mapping.get(class_name).unwrap().get(name).unwrap();
let value = self.local_stack().pop()?;
borrow.static_data[*val_index] = value;
}
GETFIELD => unsafe {
let borrow = this_class.borrow();
let cp_index = read_u16(&code.opcodes, pc);
let (class_index, field_name_and_type_index) =
borrow.cp_field_ref(&cp_index).unwrap();
let (field_name_index, _) = let (field_name_index, _) =
class.cp_name_and_type(field_name_and_type_index).unwrap(); borrow.cp_name_and_type(field_name_and_type_index).unwrap();
let class_name_index = class.cp_class_ref(class_index).unwrap(); let class_name_index = borrow.cp_class_ref(class_index).unwrap();
let class_name = class.cp_utf8(class_name_index).unwrap(); let class_name = borrow.cp_utf8(class_name_index).unwrap();
let field_name = class.cp_utf8(field_name_index).unwrap(); let field_name = borrow.cp_utf8(field_name_index).unwrap();
let mut objectref = self.local_stack().pop()?; let mut objectref = self.local_stack().pop()?;
if let Value::Ref(instance) = &mut *objectref.get() { if let Value::Ref(instance) = &mut *objectref.get() {
@ -324,14 +318,15 @@ impl Vm {
} }
}, },
PUTFIELD => unsafe { PUTFIELD => unsafe {
let borrow = this_class.borrow();
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) =
class.cp_field_ref(&cp_index).unwrap(); borrow.cp_field_ref(&cp_index).unwrap();
let (field_name_index, _) = let (field_name_index, _) =
class.cp_name_and_type(field_name_and_type_index).unwrap(); borrow.cp_name_and_type(field_name_and_type_index).unwrap();
let class_name_index = class.cp_class_ref(class_index).unwrap(); let class_name_index = borrow.cp_class_ref(class_index).unwrap();
let class_name = class.cp_utf8(class_name_index).unwrap(); let class_name = borrow.cp_utf8(class_name_index).unwrap();
let field_name = class.cp_utf8(field_name_index).unwrap(); let field_name = borrow.cp_utf8(field_name_index).unwrap();
let value = self.local_stack().pop()?; let value = self.local_stack().pop()?;
let mut objectref = self.local_stack().pop()?; let mut objectref = self.local_stack().pop()?;
@ -388,12 +383,13 @@ impl Vm {
}, },
NEW => { NEW => {
let class_index = &read_u16(&code.opcodes, pc); let class_index = &read_u16(&code.opcodes, pc);
let class_name_index = class.cp_class_ref(class_index).unwrap(); let borrow = this_class.borrow();
let class_name = class.cp_utf8(class_name_index).unwrap(); let class_name_index = borrow.cp_class_ref(class_index).unwrap();
let class = self.get_class(class_name)?; let class_name = borrow.cp_utf8(class_name_index).unwrap();
let class_to_instantiate = get_class(self, class_name)?;
let object = Arc::new(UnsafeCell::new(ObjectRef::Object(Box::new( let object = Arc::new(UnsafeCell::new(ObjectRef::Object(Box::new(
Vm::new_instance(class), Vm::new_instance(class_to_instantiate),
)))); ))));
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);

Binary file not shown.

View file

@ -1,5 +1,11 @@
public class Main { public class Main {
final static String a;
static{
a="";
}
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);