WIP statin initializers
This commit is contained in:
parent
b46145719c
commit
24f03f61f6
9 changed files with 240 additions and 141 deletions
154
src/class.rs
154
src/class.rs
|
|
@ -1,4 +1,4 @@
|
|||
use std::cell::UnsafeCell;
|
||||
use std::cell::{Ref, RefCell, RefMut, UnsafeCell};
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
|
|
@ -6,14 +6,52 @@ use std::rc::Rc;
|
|||
use std::sync::Arc;
|
||||
|
||||
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::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
|
||||
// TODO implement call to static initializers
|
||||
// TODO implement storage for static fields
|
||||
#[derive(Debug)]
|
||||
pub struct Class {
|
||||
pub minor_version: u16,
|
||||
|
|
@ -22,13 +60,17 @@ pub struct Class {
|
|||
pub access_flags: u16,
|
||||
pub name: 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 interfaces: Vec<Class>,
|
||||
pub fields: HashMap<String, Field>,
|
||||
pub methods: HashMap<String, Method>,
|
||||
pub methods: HashMap<String, Rc<Method>>,
|
||||
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 {
|
||||
|
|
@ -41,7 +83,7 @@ impl Class {
|
|||
super_class_index: u16,
|
||||
interface_indices: Vec<u16>,
|
||||
fields: HashMap<String, Field>,
|
||||
methods: HashMap<String, Method>,
|
||||
methods: HashMap<String, Rc<Method>>,
|
||||
attributes: HashMap<String, AttributeType>,
|
||||
) -> Self {
|
||||
let name = Class::class_name(this_class, constant_pool.clone()).unwrap();
|
||||
|
|
@ -60,12 +102,18 @@ impl Class {
|
|||
fields,
|
||||
methods,
|
||||
attributes,
|
||||
field_mapping: None,
|
||||
object_field_mapping: HashMap::new(),
|
||||
static_field_mapping: HashMap::new(),
|
||||
static_data: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn n_fields(&self) -> usize {
|
||||
self.field_mapping.as_ref().map_or(0, |m| m.len())
|
||||
pub(crate) fn n_object_fields(&self) -> usize {
|
||||
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.
|
||||
|
|
@ -76,42 +124,64 @@ impl Class {
|
|||
// This way `this.a` can be differentiated from `super.a`.
|
||||
//
|
||||
// this method looks up this and super classes and calls map_fields for each.
|
||||
pub fn initialize(&mut self) {
|
||||
let mut field_mapping = HashMap::new();
|
||||
pub fn initialize_fields(class: Arc<RefCell<Class>>) {
|
||||
let mut this_field_mapping = HashMap::new();
|
||||
let mut static_field_mapping = HashMap::new();
|
||||
let mut field_map_index: usize = 0;
|
||||
|
||||
Class::map_fields(&mut field_mapping, self, &mut field_map_index);
|
||||
let mut sooper = &self.super_class;
|
||||
while let Some(super_class) = sooper {
|
||||
Class::map_fields(&mut field_mapping, super_class, &mut field_map_index);
|
||||
sooper = &super_class.super_class;
|
||||
Class::add_field_mappings(&mut this_field_mapping, &mut static_field_mapping, class.clone(), &mut field_map_index);
|
||||
|
||||
class.borrow_mut().object_field_mapping = this_field_mapping;
|
||||
class.borrow_mut().static_field_mapping = static_field_mapping;
|
||||
|
||||
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
|
||||
fn map_fields(
|
||||
field_mapping: &mut HashMap<String, HashMap<String, (String, usize)>>,
|
||||
class: &Class,
|
||||
class: Arc<RefCell<Class>>,
|
||||
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.
|
||||
for field in &class.fields {
|
||||
let mut static_fields = HashMap::new(); //fields in class are stored per class and every superclass.
|
||||
|
||||
for (name, field) in &class.borrow().fields {
|
||||
if field.is(Modifier::Static) {
|
||||
static_fields.insert(
|
||||
name.to_owned(),
|
||||
(field.type_of().to_owned(), *field_map_index),
|
||||
);
|
||||
} else {
|
||||
this_fields.insert(
|
||||
field.0.to_owned(),
|
||||
(field.1.type_of().to_owned(), *field_map_index),
|
||||
name.to_owned(),
|
||||
(field.type_of().to_owned(), *field_map_index),
|
||||
); //name => (type,index)
|
||||
}
|
||||
*field_map_index += 1;
|
||||
}
|
||||
let this_name = class.name.to_owned();
|
||||
field_mapping.insert(this_name, this_fields);
|
||||
(this_fields, static_fields)
|
||||
}
|
||||
|
||||
pub fn get_version(&self) -> (u16, u16) {
|
||||
(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
|
||||
.get(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
|
||||
|
||||
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 {
|
||||
if let CpEntry::Utf8(utf8) = &self.constant_pool.get(&self.name_index).unwrap() {
|
||||
return utf8;
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ pub fn load_class(bytecode: Vec<u8>) -> Result<Class, Error> {
|
|||
let mut methods = HashMap::new();
|
||||
for _ in 0..methods_count {
|
||||
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);
|
||||
|
|
|
|||
60
src/heap.rs
60
src/heap.rs
|
|
@ -1,17 +1,9 @@
|
|||
use std::cell::UnsafeCell;
|
||||
use std::cell::{RefCell, UnsafeCell};
|
||||
use std::fmt;
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
|
||||
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
|
||||
#[derive(Debug)]
|
||||
|
|
@ -28,14 +20,22 @@ pub enum ObjectRef {
|
|||
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 Sync for Object {}
|
||||
|
||||
// object, not array
|
||||
impl Object {
|
||||
pub fn new(class: Arc<Class>) -> Self {
|
||||
let instance_data = Object::init_fields(&class);
|
||||
pub fn new(class: Arc<RefCell<Class>>) -> Self {
|
||||
let instance_data = Object::init_fields(class.clone());
|
||||
Self {
|
||||
class,
|
||||
data: instance_data,
|
||||
|
|
@ -43,10 +43,10 @@ impl Object {
|
|||
}
|
||||
|
||||
// initializes all non-static fields to their default values
|
||||
pub(crate) fn init_fields(class: &Class) -> Vec<UnsafeValue> {
|
||||
let mut field_data = Vec::with_capacity(class.n_fields());
|
||||
pub(crate) fn init_fields(class: Arc<RefCell<Class>>) -> Vec<UnsafeValue> {
|
||||
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 {
|
||||
let value = match fieldtype.as_str() {
|
||||
"Z" => Value::BOOL(false),
|
||||
|
|
@ -67,11 +67,9 @@ impl Object {
|
|||
}
|
||||
|
||||
pub fn set(&mut self, class_name: &String, field_name: &String, value: UnsafeValue) {
|
||||
let (_type, index) = self
|
||||
.class
|
||||
.field_mapping
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
let borrow = self.class.borrow();
|
||||
let (_type, index) =borrow
|
||||
.object_field_mapping
|
||||
.get(class_name)
|
||||
.unwrap()
|
||||
.get(field_name)
|
||||
|
|
@ -80,11 +78,9 @@ impl Object {
|
|||
}
|
||||
|
||||
pub fn get(&mut self, class_name: &String, field_name: &String) -> &UnsafeValue {
|
||||
let (_type, index) = &self
|
||||
.class
|
||||
.field_mapping
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
let borrow = self.class.borrow();
|
||||
let (_type, index) =borrow
|
||||
.object_field_mapping
|
||||
.get(class_name)
|
||||
.unwrap()
|
||||
.get(field_name)
|
||||
|
|
@ -92,12 +88,12 @@ impl Object {
|
|||
&self.data[*index]
|
||||
}
|
||||
|
||||
fn get_field_name(&self, cp_index: &u16) -> &str {
|
||||
if let CpEntry::Utf8(name) = self.class.constant_pool.get(cp_index).unwrap() {
|
||||
return name;
|
||||
}
|
||||
panic!()
|
||||
}
|
||||
// fn get_field_name(&self, cp_index: &u16) -> &str {
|
||||
// if let CpEntry::Utf8(name) = self.class.constant_pool.get(cp_index).unwrap() {
|
||||
// return name;
|
||||
// }
|
||||
// panic!()
|
||||
// }
|
||||
}
|
||||
|
||||
impl fmt::Debug for Object {
|
||||
|
|
@ -109,7 +105,7 @@ impl fmt::Debug for Object {
|
|||
// // r
|
||||
// }
|
||||
// ).collect();
|
||||
write!(f, "{}", self.class.name)
|
||||
write!(f, "{}", self.class.borrow().name)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ fn main() -> Result<(), Error> {
|
|||
// TODO build index for package -> jarfile?
|
||||
|
||||
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![])
|
||||
.unwrap();
|
||||
|
|
|
|||
|
|
@ -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(class: Arc<Class>, method: &Method) -> UnsafeValue {
|
||||
println!("invoke native {:?}.{:?}", class.name, method.name());
|
||||
pub fn invoke_native(method: Rc<Method>, args: Vec<UnsafeValue>) -> UnsafeValue {
|
||||
println!("native {}", method.name());
|
||||
Value::void()
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -125,6 +125,7 @@ pub const DRETURN: u8 = 175; // (0xaf) Return double from method
|
|||
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 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 PUTFIELD: u8 = 181; // (0xb5) Set field in object
|
||||
pub const INVOKEVIRTUAL: u8 = 182; // (0xb6) Invoke instance method; dispatch based on class
|
||||
|
|
|
|||
144
src/vm.rs
144
src/vm.rs
|
|
@ -1,14 +1,13 @@
|
|||
use std::cell::UnsafeCell;
|
||||
use std::cell::{RefCell, UnsafeCell};
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
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::{AttributeType, Class, Modifier, UnsafeValue, Value};
|
||||
use crate::classloader::{load_class, CpEntry};
|
||||
use crate::classloader::CpEntry;
|
||||
use crate::heap::{Heap, Object, ObjectRef};
|
||||
use crate::io::*;
|
||||
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 {
|
||||
classpath: Vec<String>,
|
||||
pub classpath: Vec<String>,
|
||||
heap: Heap,
|
||||
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)
|
||||
});
|
||||
Ok(entry.clone())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_instance(class: Arc<Class>) -> Object {
|
||||
let mut class = class;
|
||||
pub fn new_instance(class: Arc<RefCell<Class>>) -> Object {
|
||||
let mut instance = Object::new(class.clone());
|
||||
instance
|
||||
}
|
||||
|
|
@ -118,25 +88,27 @@ impl Vm {
|
|||
method_name: &str,
|
||||
args: Vec<UnsafeValue>,
|
||||
) -> Result<UnsafeValue, Error> {
|
||||
let mut local_params: Vec<Option<UnsafeValue>> =
|
||||
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) {
|
||||
let return_value = invoke_native(class.clone(), method);
|
||||
unsafe {
|
||||
match *return_value.get() {
|
||||
Void => {}
|
||||
_ => {
|
||||
self.local_stack().push_arc(return_value.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
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>> =
|
||||
args.clone().iter().map(|e| Some(e.clone())).collect();
|
||||
if method.is(Modifier::Native) {
|
||||
return Ok(invoke_native(method, args));
|
||||
}
|
||||
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);
|
||||
|
||||
let mut pc = &mut 0;
|
||||
|
|
@ -297,23 +269,45 @@ impl Vm {
|
|||
return Ok(Value::void());
|
||||
}
|
||||
GETSTATIC => {
|
||||
let cp_index = read_u16(&code.opcodes, pc);
|
||||
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 borrow = this_class.borrow();
|
||||
let cp_index = read_u16(&code.opcodes, pc);
|
||||
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, _) =
|
||||
class.cp_name_and_type(field_name_and_type_index).unwrap();
|
||||
let class_name_index = class.cp_class_ref(class_index).unwrap();
|
||||
let class_name = class.cp_utf8(class_name_index).unwrap();
|
||||
let field_name = class.cp_utf8(field_name_index).unwrap();
|
||||
borrow.cp_name_and_type(field_name_and_type_index).unwrap();
|
||||
let class_name_index = borrow.cp_class_ref(class_index).unwrap();
|
||||
let class_name = borrow.cp_utf8(class_name_index).unwrap();
|
||||
let field_name = borrow.cp_utf8(field_name_index).unwrap();
|
||||
|
||||
let mut objectref = self.local_stack().pop()?;
|
||||
if let Value::Ref(instance) = &mut *objectref.get() {
|
||||
|
|
@ -324,14 +318,15 @@ impl Vm {
|
|||
}
|
||||
},
|
||||
PUTFIELD => unsafe {
|
||||
let borrow = this_class.borrow();
|
||||
let cp_index = read_u16(&code.opcodes, pc);
|
||||
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, _) =
|
||||
class.cp_name_and_type(field_name_and_type_index).unwrap();
|
||||
let class_name_index = class.cp_class_ref(class_index).unwrap();
|
||||
let class_name = class.cp_utf8(class_name_index).unwrap();
|
||||
let field_name = class.cp_utf8(field_name_index).unwrap();
|
||||
borrow.cp_name_and_type(field_name_and_type_index).unwrap();
|
||||
let class_name_index = borrow.cp_class_ref(class_index).unwrap();
|
||||
let class_name = borrow.cp_utf8(class_name_index).unwrap();
|
||||
let field_name = borrow.cp_utf8(field_name_index).unwrap();
|
||||
|
||||
let value = self.local_stack().pop()?;
|
||||
let mut objectref = self.local_stack().pop()?;
|
||||
|
|
@ -388,12 +383,13 @@ impl Vm {
|
|||
},
|
||||
NEW => {
|
||||
let class_index = &read_u16(&code.opcodes, pc);
|
||||
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)?;
|
||||
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 class_to_instantiate = get_class(self, class_name)?;
|
||||
|
||||
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.heap.new_object(object);
|
||||
|
|
|
|||
BIN
tests/Main.class
BIN
tests/Main.class
Binary file not shown.
|
|
@ -1,5 +1,11 @@
|
|||
public class Main {
|
||||
|
||||
final static String a;
|
||||
|
||||
static{
|
||||
a="";
|
||||
}
|
||||
|
||||
public static void main(String[] args){
|
||||
FloatBean f = new FloatBean();
|
||||
f.setValue(42F);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue