fixed lot of issues. static initializers are working
This commit is contained in:
parent
24f03f61f6
commit
d132502771
8 changed files with 100 additions and 47 deletions
72
src/class.rs
72
src/class.rs
|
|
@ -2,6 +2,7 @@ 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;
|
||||||
|
use std::os::macos::raw::stat;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
|
@ -20,9 +21,17 @@ static mut CLASSDEFS: Lazy<HashMap<String, Arc<RefCell<Class>>>> = Lazy::new(||
|
||||||
// gets the Class from cache, or reads it from classpath,
|
// gets the Class from cache, or reads it from classpath,
|
||||||
// then parses the binary data into a Class struct
|
// then parses the binary data into a Class struct
|
||||||
// Vm keeps ownership of the class and hands out Arc references to it
|
// 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> {
|
pub fn get_class(vm: &mut Vm, calling_class_name: Option<&str>, class_name: &str) -> Result<Arc<RefCell<Class>>, Error> {
|
||||||
println!("get_class {}", class_name);
|
println!("get_class {}", class_name);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
// not pretty...sorry
|
||||||
|
if let Some(calling_class_name) = calling_class_name {
|
||||||
|
if class_name == calling_class_name { // works around the situation that static initializer needs a ref to the class it's in
|
||||||
|
return Ok(CLASSDEFS.get(class_name.into()).unwrap().clone()); // in that case the class is guaranteed to be here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let new_class = CLASSDEFS.entry(class_name.into()).or_insert_with(|| {
|
let new_class = CLASSDEFS.entry(class_name.into()).or_insert_with(|| {
|
||||||
println!("read class {} ", class_name);
|
println!("read class {} ", class_name);
|
||||||
let resolved_path = find_class(&vm.classpath, class_name).unwrap();
|
let resolved_path = find_class(&vm.classpath, class_name).unwrap();
|
||||||
|
|
@ -31,17 +40,24 @@ pub fn get_class(vm: &mut Vm, class_name: &str) -> Result<Arc<RefCell<Class>>, E
|
||||||
let mut class = load_class(bytecode).unwrap();
|
let mut class = load_class(bytecode).unwrap();
|
||||||
let super_class_name = class.super_class_name.as_ref();
|
let super_class_name = class.super_class_name.as_ref();
|
||||||
if let Some(super_class_name) = super_class_name {
|
if let Some(super_class_name) = super_class_name {
|
||||||
if let Ok(super_class) = get_class(vm, &super_class_name) {
|
if let Ok(super_class) = get_class(vm, Some(class_name), &super_class_name) {
|
||||||
class.super_class = Some(super_class);
|
class.super_class = Some(super_class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Arc::new(RefCell::new(class))
|
|
||||||
|
let class = Arc::new(RefCell::new(class));
|
||||||
|
Class::initialize_fields(class.clone());
|
||||||
|
class
|
||||||
});
|
});
|
||||||
|
|
||||||
Class::initialize_fields(new_class.clone());
|
|
||||||
|
|
||||||
let exec = new_class.borrow().methods.contains_key("<clinit>()V");
|
// calling clinit before the end of this function has been a PITA
|
||||||
if exec {
|
// 1. infinite recursion
|
||||||
|
// panic after second borrow.
|
||||||
|
// the problem is pretty fundamental: method (clinit) should be called before the class is returned,
|
||||||
|
// but the executing code needs a reference to itself. So get_class is called recursively, but clinit must be called exactly once!
|
||||||
|
// putting the call to clinit in the closure above is way nicer, but the signature change (wrap it in Arc<RefCell>)
|
||||||
|
if new_class.borrow().methods.contains_key("<clinit>()V") {
|
||||||
vm.execute_class(new_class.clone(), "<clinit>()V", vec![]).unwrap();
|
vm.execute_class(new_class.clone(), "<clinit>()V", vec![]).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -70,7 +86,7 @@ pub struct Class {
|
||||||
// first key: this/super/supersuper-name(etc), second key: fieldname, value (type, index)
|
// first key: this/super/supersuper-name(etc), second key: fieldname, value (type, index)
|
||||||
pub(crate) static_field_mapping: HashMap<String, HashMap<String, (String, usize)>>,
|
pub(crate) static_field_mapping: HashMap<String, HashMap<String, (String, usize)>>,
|
||||||
// first key: this/super/supersuper-name(etc), second key: fieldname, value (type, index)
|
// first key: this/super/supersuper-name(etc), second key: fieldname, value (type, index)
|
||||||
pub(crate) static_data: Vec<UnsafeValue>,
|
pub(crate) static_data: Vec<Option<UnsafeValue>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Class {
|
impl Class {
|
||||||
|
|
@ -109,11 +125,11 @@ impl Class {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn n_object_fields(&self) -> usize {
|
pub(crate) fn n_object_fields(&self) -> usize {
|
||||||
self.object_field_mapping.len()
|
self.object_field_mapping.iter().map(|(_,v)|v.len()).reduce(|acc, e| acc + e).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn n_static_fields(&self) -> usize {
|
pub(crate) fn n_static_fields(&self) -> usize {
|
||||||
self.object_field_mapping.len()
|
self.static_field_mapping.iter().map(|(_,v)|v.len()).reduce(|acc, e| acc + e).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
||||||
|
|
@ -127,9 +143,10 @@ impl Class {
|
||||||
pub fn initialize_fields(class: Arc<RefCell<Class>>) {
|
pub fn initialize_fields(class: Arc<RefCell<Class>>) {
|
||||||
let mut this_field_mapping = HashMap::new();
|
let mut this_field_mapping = HashMap::new();
|
||||||
let mut static_field_mapping = HashMap::new();
|
let mut static_field_mapping = HashMap::new();
|
||||||
let mut field_map_index: usize = 0;
|
let mut object_field_map_index: usize = 0;
|
||||||
|
let mut static_field_map_index: usize = 0;
|
||||||
|
|
||||||
Class::add_field_mappings(&mut this_field_mapping, &mut static_field_mapping, class.clone(), &mut field_map_index);
|
Class::add_field_mappings(&mut this_field_mapping, &mut static_field_mapping, class.clone(), &mut object_field_map_index, &mut static_field_map_index);
|
||||||
|
|
||||||
class.borrow_mut().object_field_mapping = this_field_mapping;
|
class.borrow_mut().object_field_mapping = this_field_mapping;
|
||||||
class.borrow_mut().static_field_mapping = static_field_mapping;
|
class.borrow_mut().static_field_mapping = static_field_mapping;
|
||||||
|
|
@ -140,22 +157,25 @@ impl Class {
|
||||||
|
|
||||||
fn add_field_mappings(this_field_mapping: &mut HashMap<String, HashMap<String, (String, usize)>>,
|
fn add_field_mappings(this_field_mapping: &mut HashMap<String, HashMap<String, (String, usize)>>,
|
||||||
static_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) {
|
class: Arc<RefCell<Class>>,
|
||||||
let (o, s) = Class::map_fields(class.clone(), field_map_index);
|
object_field_map_index: &mut usize,
|
||||||
|
static_field_map_index: &mut usize) {
|
||||||
|
let (o, s) = Class::map_fields(class.clone(), object_field_map_index, static_field_map_index);
|
||||||
let borrow = class.borrow();
|
let borrow = class.borrow();
|
||||||
let name = &borrow.name;
|
let name = &borrow.name;
|
||||||
this_field_mapping.insert(name.to_owned(), o);
|
this_field_mapping.insert(name.to_owned(), o);
|
||||||
static_field_mapping.insert(name.to_owned(), s);
|
static_field_mapping.insert(name.to_owned(), s);
|
||||||
|
|
||||||
if let Some(super_class) = class.borrow().super_class.as_ref() {
|
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);
|
Class::add_field_mappings(this_field_mapping, static_field_mapping, super_class.clone(), object_field_map_index, static_field_map_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// part of the initialize procedure
|
// part of the initialize procedure
|
||||||
fn map_fields(
|
fn map_fields(
|
||||||
class: Arc<RefCell<Class>>,
|
class: Arc<RefCell<Class>>,
|
||||||
field_map_index: &mut usize,
|
object_field_map_index: &mut usize,
|
||||||
|
static_field_map_index: &mut usize,
|
||||||
) -> (HashMap<String, (String, usize)>, HashMap<String, (String, 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.
|
||||||
let mut static_fields = HashMap::new(); //fields in class are stored per class and every superclass.
|
let mut static_fields = HashMap::new(); //fields in class are stored per class and every superclass.
|
||||||
|
|
@ -164,15 +184,17 @@ impl Class {
|
||||||
if field.is(Modifier::Static) {
|
if field.is(Modifier::Static) {
|
||||||
static_fields.insert(
|
static_fields.insert(
|
||||||
name.to_owned(),
|
name.to_owned(),
|
||||||
(field.type_of().to_owned(), *field_map_index),
|
(field.type_of().to_owned(), *static_field_map_index),
|
||||||
);
|
);
|
||||||
|
*static_field_map_index += 1;
|
||||||
} else {
|
} else {
|
||||||
this_fields.insert(
|
this_fields.insert(
|
||||||
name.to_owned(),
|
name.to_owned(),
|
||||||
(field.type_of().to_owned(), *field_map_index),
|
(field.type_of().to_owned(), *object_field_map_index),
|
||||||
); //name => (type,index)
|
); //name => (type,index)
|
||||||
|
*object_field_map_index += 1;
|
||||||
}
|
}
|
||||||
*field_map_index += 1;
|
|
||||||
}
|
}
|
||||||
(this_fields, static_fields)
|
(this_fields, static_fields)
|
||||||
}
|
}
|
||||||
|
|
@ -205,11 +227,11 @@ impl Class {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn set_field_data(class: Arc<RefCell<Class>>) -> Vec<UnsafeValue> {
|
pub(crate) fn set_field_data(class: Arc<RefCell<Class>>) -> Vec<Option<UnsafeValue>> {
|
||||||
let mut field_data = Vec::with_capacity(class.borrow().n_object_fields());
|
let mut field_data = vec![None; class.borrow().n_static_fields()];
|
||||||
|
|
||||||
for (_, fields) in &class.borrow().static_field_mapping {
|
for (_, this_class) in &class.borrow().static_field_mapping {
|
||||||
for (_, (fieldtype, _)) in fields {
|
for (name, (fieldtype, index)) in this_class {
|
||||||
let value = match fieldtype.as_str() {
|
let value = match fieldtype.as_str() {
|
||||||
"Z" => Value::BOOL(false),
|
"Z" => Value::BOOL(false),
|
||||||
"B" => Value::I32(0),
|
"B" => Value::I32(0),
|
||||||
|
|
@ -218,10 +240,10 @@ impl Class {
|
||||||
"J" => Value::I64(0),
|
"J" => Value::I64(0),
|
||||||
"F" => Value::F32(0.0),
|
"F" => Value::F32(0.0),
|
||||||
"D" => Value::F64(0.0),
|
"D" => Value::F64(0.0),
|
||||||
"L" => Value::Null,
|
_ => Value::Null,
|
||||||
_ => Value::Void,
|
|
||||||
};
|
};
|
||||||
field_data.push(value.into());
|
println!("{} = {:?}", name, value );
|
||||||
|
field_data[*index] = Some(value.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
@ -273,6 +273,7 @@ fn read_attribute(
|
||||||
"NestMembers" => Some(("".into(), AttributeType::NestMembers)), //stub
|
"NestMembers" => Some(("".into(), AttributeType::NestMembers)), //stub
|
||||||
"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
|
||||||
//TODO more actual attribute implementations
|
//TODO more actual attribute implementations
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -56,8 +56,7 @@ impl Object {
|
||||||
"J" => Value::I64(0),
|
"J" => Value::I64(0),
|
||||||
"F" => Value::F32(0.0),
|
"F" => Value::F32(0.0),
|
||||||
"D" => Value::F64(0.0),
|
"D" => Value::F64(0.0),
|
||||||
"L" => Value::Null,
|
_ => Value::Null,
|
||||||
_ => Value::Void,
|
|
||||||
};
|
};
|
||||||
field_data.push(value.into());
|
field_data.push(value.into());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ fn main() -> Result<(), Error> {
|
||||||
// let main_class = "Inheritance";
|
// let main_class = "Inheritance";
|
||||||
let main_class = "Main";
|
let main_class = "Main";
|
||||||
|
|
||||||
vm.execute(main_class, "main([Ljava/lang/String;)V", vec![])
|
vm.execute(None,main_class, "main([Ljava/lang/String;)V", vec![])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,7 @@ pub const INVOKEVIRTUAL: u8 = 182; // (0xb6) Invoke instance method; dispatch ba
|
||||||
pub const INVOKESPECIAL: u8 = 183; // (0xb7) // nvoke instance method; direct invocation of instance initialization methods and methods of the current class and its supertypes
|
pub const INVOKESPECIAL: u8 = 183; // (0xb7) // nvoke instance method; direct invocation of instance initialization methods and methods of the current class and its supertypes
|
||||||
pub const INVOKESTATIC: u8 = 184; // (0xb8) Invoke a class (static) method
|
pub const INVOKESTATIC: u8 = 184; // (0xb8) Invoke a class (static) method
|
||||||
pub const NEW: u8 = 187; // (0xbb) Create new object
|
pub const NEW: u8 = 187; // (0xbb) Create new object
|
||||||
pub const anewarray: u8 = 189; // (0xbd)
|
pub const ANEWARRAY: u8 = 189; // (0xbd)
|
||||||
pub const arraylength: u8 = 190; // (0xbe)
|
pub const arraylength: u8 = 190; // (0xbe)
|
||||||
pub const athrow: u8 = 191; // (0xbf)
|
pub const athrow: u8 = 191; // (0xbf)
|
||||||
pub const checkcast: u8 = 192; // (0xc0)
|
pub const checkcast: u8 = 192; // (0xc0)
|
||||||
|
|
|
||||||
61
src/vm.rs
61
src/vm.rs
|
|
@ -1,5 +1,6 @@
|
||||||
use std::cell::{RefCell, UnsafeCell};
|
use std::cell::{RefCell, UnsafeCell};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::ops::Deref;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
|
@ -39,6 +40,10 @@ impl StackFrame {
|
||||||
fn pop(&mut self) -> Result<UnsafeValue, Error> {
|
fn pop(&mut self) -> Result<UnsafeValue, Error> {
|
||||||
Ok(self.data.pop().unwrap())
|
Ok(self.data.pop().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn len(&self) -> usize {
|
||||||
|
self.data.len()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -84,11 +89,12 @@ impl Vm {
|
||||||
/// contains unsafe, as I think that mimics not-synchronized memory access in the original JVM
|
/// contains unsafe, as I think that mimics not-synchronized memory access in the original JVM
|
||||||
pub fn execute(
|
pub fn execute(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
calling_class_name: Option<&str>,
|
||||||
class_name: &str,
|
class_name: &str,
|
||||||
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)?;
|
let class = get_class(self, calling_class_name, class_name)?;
|
||||||
self.execute_class(class, method_name, args)
|
self.execute_class(class, method_name, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -114,7 +120,7 @@ impl Vm {
|
||||||
let mut pc = &mut 0;
|
let mut pc = &mut 0;
|
||||||
while *pc < code.opcodes.len() {
|
while *pc < code.opcodes.len() {
|
||||||
let opcode = read_u8(&code.opcodes, pc);
|
let opcode = read_u8(&code.opcodes, pc);
|
||||||
println!("opcode {} ", opcode);
|
println!("stack {} opcode {} ", self.local_stack().len(), opcode);
|
||||||
match opcode {
|
match opcode {
|
||||||
ACONST_NULL => {
|
ACONST_NULL => {
|
||||||
self.local_stack().push(Value::Null);
|
self.local_stack().push(Value::Null);
|
||||||
|
|
@ -171,13 +177,25 @@ impl Vm {
|
||||||
}
|
}
|
||||||
LDC => {
|
LDC => {
|
||||||
let cp_index = read_u8(&code.opcodes, pc) as u16;
|
let cp_index = read_u8(&code.opcodes, pc) as u16;
|
||||||
match method.constant_pool.get(&cp_index).unwrap() {
|
let c = method.constant_pool.get(&cp_index).unwrap();
|
||||||
|
println!("{:?}", c);
|
||||||
|
match c {
|
||||||
CpEntry::Integer(i) => {
|
CpEntry::Integer(i) => {
|
||||||
self.local_stack().push(Value::I32(*i));
|
self.local_stack().push(Value::I32(*i));
|
||||||
}
|
}
|
||||||
CpEntry::Float(f) => {
|
CpEntry::Float(f) => {
|
||||||
self.local_stack().push(Value::F32(*f));
|
self.local_stack().push(Value::F32(*f));
|
||||||
}
|
}
|
||||||
|
CpEntry::Double(d) => {
|
||||||
|
self.local_stack().push(Value::F64(*d));
|
||||||
|
}
|
||||||
|
CpEntry::StringRef(utf8) => {
|
||||||
|
let string = get_class(self, Some(&this_class.borrow().name), "java/lang/String").unwrap();
|
||||||
|
self.local_stack().push(Value::Ref(Arc::new(UnsafeCell::new(ObjectRef::Object(Box::new(Object::new(string)))))))
|
||||||
|
}
|
||||||
|
CpEntry::Long(l) => {
|
||||||
|
self.local_stack().push(Value::I64(*l));
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -275,12 +293,14 @@ impl Vm {
|
||||||
borrow.cp_field_ref(&cp_index).unwrap(); // all these unwraps are safe as long as the class is valid
|
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_index, _) = borrow.cp_name_and_type(field_name_and_type_index).unwrap();
|
||||||
let (name) = borrow.cp_utf8(name_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_class_name_index = borrow.cp_class_ref(class_index).unwrap();
|
||||||
let that = get_class(self, class_name.as_str())?;
|
let that_class_name = borrow.cp_utf8(that_class_name_index).unwrap();
|
||||||
let borrow = that.borrow();
|
let that = get_class(self, Some(&borrow.name), that_class_name.as_str())?;
|
||||||
let (_, val_index) = borrow.static_field_mapping.get(class_name).unwrap().get(name).unwrap();
|
let that_borrow = that.borrow();
|
||||||
self.local_stack().push_arc(this_class.borrow().static_data.get(*val_index).unwrap().clone());
|
let (_, val_index) = that_borrow.static_field_mapping.get(that_class_name).unwrap().get(name).unwrap();
|
||||||
|
println!("get static field {}", name);
|
||||||
|
self.local_stack().push_arc(borrow.static_data.get(*val_index).unwrap().as_ref().unwrap().clone());
|
||||||
}
|
}
|
||||||
PUTSTATIC => {
|
PUTSTATIC => {
|
||||||
println!("putstatic");
|
println!("putstatic");
|
||||||
|
|
@ -291,12 +311,21 @@ impl Vm {
|
||||||
let (name_index, _) = borrow.cp_name_and_type(field_name_and_type_index).unwrap();
|
let (name_index, _) = borrow.cp_name_and_type(field_name_and_type_index).unwrap();
|
||||||
let (name) = borrow.cp_utf8(name_index).unwrap();
|
let (name) = borrow.cp_utf8(name_index).unwrap();
|
||||||
let class_name_index = borrow.cp_class_ref(class_index).unwrap();
|
let class_name_index = borrow.cp_class_ref(class_index).unwrap();
|
||||||
let class_name = borrow.cp_utf8(class_name_index).unwrap();
|
println!("field {}", name);
|
||||||
let that = get_class(self, class_name.as_str())?;
|
let that_class_name = borrow.cp_utf8(class_name_index).unwrap();
|
||||||
let that_borrow = that.borrow();
|
|
||||||
let (_, val_index) = that_borrow.static_field_mapping.get(class_name).unwrap().get(name).unwrap();
|
if &borrow.name == that_class_name {
|
||||||
|
let (_, val_index) = borrow.static_field_mapping.get(that_class_name).unwrap().get(name).as_ref().unwrap();
|
||||||
|
let val_index = *val_index;
|
||||||
let value = self.local_stack().pop()?;
|
let value = self.local_stack().pop()?;
|
||||||
borrow.static_data[*val_index] = value;
|
borrow.static_data[val_index] = Some(value);
|
||||||
|
} else {
|
||||||
|
let that = get_class(self, Some(&borrow.name), that_class_name.as_str())?;
|
||||||
|
let that_borrow = that.borrow(); // if already borrowed, then that_class == this_class
|
||||||
|
let (_, val_index) = that_borrow.static_field_mapping.get(that_class_name).unwrap().get(name).unwrap();
|
||||||
|
let value = self.local_stack().pop()?;
|
||||||
|
borrow.static_data[*val_index] = Some(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
GETFIELD => unsafe {
|
GETFIELD => unsafe {
|
||||||
let borrow = this_class.borrow();
|
let borrow = this_class.borrow();
|
||||||
|
|
@ -347,6 +376,7 @@ impl Vm {
|
||||||
}
|
}
|
||||||
args.insert(0, self.local_stack().pop()?);
|
args.insert(0, self.local_stack().pop()?);
|
||||||
let mut return_value = self.execute(
|
let mut return_value = self.execute(
|
||||||
|
Some(this_class.borrow().name.as_str()),
|
||||||
&invocation.class_name,
|
&invocation.class_name,
|
||||||
&invocation.method.name,
|
&invocation.method.name,
|
||||||
args,
|
args,
|
||||||
|
|
@ -369,6 +399,7 @@ impl Vm {
|
||||||
args.insert(0, self.local_stack().pop()?);
|
args.insert(0, self.local_stack().pop()?);
|
||||||
}
|
}
|
||||||
let mut returnvalue = self.execute(
|
let mut returnvalue = self.execute(
|
||||||
|
Some(this_class.borrow().name.as_str()),
|
||||||
&invocation.class_name,
|
&invocation.class_name,
|
||||||
&invocation.method.name,
|
&invocation.method.name,
|
||||||
args,
|
args,
|
||||||
|
|
@ -386,7 +417,7 @@ impl Vm {
|
||||||
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();
|
||||||
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, 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 = Arc::new(UnsafeCell::new(ObjectRef::Object(Box::new(
|
||||||
Vm::new_instance(class_to_instantiate),
|
Vm::new_instance(class_to_instantiate),
|
||||||
|
|
|
||||||
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());
|
System.out.println(f.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue