rmoved UnsafeValue
This commit is contained in:
parent
c5d573c698
commit
90361c4a35
5 changed files with 118 additions and 142 deletions
32
src/class.rs
32
src/class.rs
|
|
@ -16,7 +16,7 @@ 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
|
//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
|
||||||
pub static mut CLASSDEFS: Lazy<HashMap<String, Arc<RefCell<Class>>>> = Lazy::new(|| HashMap::new());
|
pub static mut CLASSDEFS: Lazy<HashMap<String, Arc<RefCell<Class>>>> = Lazy::new(|| HashMap::new());
|
||||||
//TODO add mutex..
|
//TODO add mutex..
|
||||||
pub static mut CLASSES: Lazy<HashMap<String, UnsafeValue>> = Lazy::new(|| HashMap::new()); //TODO add mutex..
|
pub static mut CLASSES: Lazy<HashMap<String, Value>> = Lazy::new(|| HashMap::new()); //TODO add mutex..
|
||||||
|
|
||||||
// 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
|
||||||
|
|
@ -48,8 +48,8 @@ pub fn get_class(
|
||||||
if class_name != "java/lang/Class" {
|
if class_name != "java/lang/Class" {
|
||||||
let klazz = get_class(vm, "java/lang/Class")?;
|
let klazz = get_class(vm, "java/lang/Class")?;
|
||||||
let mut class_instance = Vm::new_instance(klazz);
|
let mut class_instance = Vm::new_instance(klazz);
|
||||||
class_instance.set(&"java/lang/Class".to_owned(), &"name".to_owned(), unsafe_val(Value::Utf8(class_name.into())));
|
class_instance.set(&"java/lang/Class".to_owned(), &"name".to_owned(), Value::Utf8(class_name.into()));
|
||||||
CLASSES.insert(class_name.into(), unsafe_val(Value::Ref(unsafe_ref(ObjectRef::Object(Box::new(class_instance))))));
|
CLASSES.insert(class_name.into(), Value::Ref(unsafe_ref(ObjectRef::Object(Box::new(class_instance)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
// must not enter here twice!
|
// must not enter here twice!
|
||||||
|
|
@ -112,7 +112,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<Option<UnsafeValue>>,
|
pub(crate) static_data: Vec<Option<Value>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Class {
|
impl Class {
|
||||||
|
|
@ -281,7 +281,7 @@ impl Class {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn set_field_data(class: Arc<RefCell<Class>>) -> Vec<Option<UnsafeValue>> {
|
pub(crate) fn set_field_data(class: Arc<RefCell<Class>>) -> Vec<Option<Value>> {
|
||||||
let mut field_data = vec![None; class.borrow().n_static_fields()];
|
let mut field_data = vec![None; class.borrow().n_static_fields()];
|
||||||
|
|
||||||
for (_, this_class) in &class.borrow().static_field_mapping {
|
for (_, this_class) in &class.borrow().static_field_mapping {
|
||||||
|
|
@ -581,7 +581,7 @@ impl MethodCode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
Void,
|
Void,
|
||||||
// variant returned for void methods
|
// variant returned for void methods
|
||||||
|
|
@ -597,29 +597,15 @@ pub enum Value {
|
||||||
Utf8(String),
|
Utf8(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Value {
|
|
||||||
pub fn void() -> UnsafeValue {
|
|
||||||
Arc::new(UnsafeCell::new(Value::Void))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Into<UnsafeValue> for Value {
|
|
||||||
fn into(self) -> UnsafeValue {
|
|
||||||
Arc::new(UnsafeCell::new(self))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type UnsafeValue = Arc<UnsafeCell<Value>>;
|
|
||||||
|
|
||||||
pub type UnsafeRef = Arc<UnsafeCell<ObjectRef>>;
|
pub type UnsafeRef = Arc<UnsafeCell<ObjectRef>>;
|
||||||
|
|
||||||
pub fn unsafe_ref(object: ObjectRef) -> UnsafeRef {
|
pub fn unsafe_ref(object: ObjectRef) -> UnsafeRef {
|
||||||
return Arc::new(UnsafeCell::new(object));
|
return Arc::new(UnsafeCell::new(object));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unsafe_val(val: Value) -> UnsafeValue {
|
// pub fn unsafe_val(val: Value) -> UnsafeValue {
|
||||||
return Arc::new(UnsafeCell::new(val));
|
// return Arc::new(UnsafeCell::new(val));
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn type_ref(class: Class) -> Type {
|
pub fn type_ref(class: Class) -> Type {
|
||||||
return Arc::new(RefCell::new(class));
|
return Arc::new(RefCell::new(class));
|
||||||
|
|
|
||||||
19
src/heap.rs
19
src/heap.rs
|
|
@ -1,10 +1,10 @@
|
||||||
use std::cell::{RefCell, UnsafeCell};
|
use std::cell::{RefCell, UnsafeCell};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fmt::{Debug, Formatter, write};
|
use std::fmt::{Debug, Formatter};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use ObjectRef::{BooleanArray, CharArray, DoubleArray, FloatArray, LongArray, ShortArray};
|
use ObjectRef::{BooleanArray, CharArray, DoubleArray, FloatArray, LongArray, ShortArray};
|
||||||
|
|
||||||
use crate::class::{Class, Type, UnsafeValue, Value};
|
use crate::class::{Class, Type, Value};
|
||||||
use crate::heap::ObjectRef::{ByteArray, IntArray, ObjectArray, StringArray};
|
use crate::heap::ObjectRef::{ByteArray, IntArray, ObjectArray, StringArray};
|
||||||
|
|
||||||
// can contain object or array
|
// can contain object or array
|
||||||
|
|
@ -19,7 +19,7 @@ pub enum ObjectRef {
|
||||||
CharArray(Vec<char>),
|
CharArray(Vec<char>),
|
||||||
StringArray(Vec<String>),
|
StringArray(Vec<String>),
|
||||||
ObjectArray(Type, Vec<Arc<UnsafeCell<ObjectRef>>>),
|
ObjectArray(Type, Vec<Arc<UnsafeCell<ObjectRef>>>),
|
||||||
Object(Box<Object>),
|
Object(Box<Object>),//Box necessary??
|
||||||
Class(Arc<RefCell<Class>>),
|
Class(Arc<RefCell<Class>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -42,11 +42,6 @@ impl ObjectRef {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_vec_i8(v: Vec<u8>) -> Vec<i8> {
|
fn into_vec_i8(v: Vec<u8>) -> Vec<i8> {
|
||||||
// ideally we'd use Vec::into_raw_parts, but it's unstable,
|
|
||||||
// so we have to do it manually:
|
|
||||||
|
|
||||||
// first, make sure v's destructor doesn't free the data
|
|
||||||
// it thinks it owns when it goes out of scope
|
|
||||||
let mut v = std::mem::ManuallyDrop::new(v);
|
let mut v = std::mem::ManuallyDrop::new(v);
|
||||||
|
|
||||||
// then, pick apart the existing Vec
|
// then, pick apart the existing Vec
|
||||||
|
|
@ -96,7 +91,7 @@ pub struct Object {
|
||||||
// locked: bool,
|
// locked: bool,
|
||||||
// hashcode: i32,
|
// hashcode: i32,
|
||||||
pub class: Arc<RefCell<Class>>,
|
pub class: Arc<RefCell<Class>>,
|
||||||
pub data: Vec<UnsafeValue>,
|
pub data: Vec<Value>,
|
||||||
} //arrays
|
} //arrays
|
||||||
|
|
||||||
unsafe impl Send for Object {}
|
unsafe impl Send for Object {}
|
||||||
|
|
@ -114,7 +109,7 @@ 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: Arc<RefCell<Class>>) -> Vec<UnsafeValue> {
|
pub(crate) fn init_fields(class: Arc<RefCell<Class>>) -> Vec<Value> {
|
||||||
let mut field_data = Vec::with_capacity(class.borrow().n_object_fields());
|
let mut field_data = Vec::with_capacity(class.borrow().n_object_fields());
|
||||||
|
|
||||||
for (_, fields) in &class.borrow().object_field_mapping {
|
for (_, fields) in &class.borrow().object_field_mapping {
|
||||||
|
|
@ -136,7 +131,7 @@ impl Object {
|
||||||
field_data
|
field_data
|
||||||
}
|
}
|
||||||
|
|
||||||
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: Value) {
|
||||||
let borrow = self.class.borrow();
|
let borrow = self.class.borrow();
|
||||||
let (_type, index) = borrow
|
let (_type, index) = borrow
|
||||||
.object_field_mapping
|
.object_field_mapping
|
||||||
|
|
@ -147,7 +142,7 @@ impl Object {
|
||||||
self.data[*index] = value;
|
self.data[*index] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&mut self, class_name: &String, field_name: &String) -> &UnsafeValue {
|
pub fn get(&mut self, class_name: &String, field_name: &String) -> &Value {
|
||||||
let borrow = self.class.borrow();
|
let borrow = self.class.borrow();
|
||||||
let (_type, index) = borrow
|
let (_type, index) = borrow
|
||||||
.object_field_mapping
|
.object_field_mapping
|
||||||
|
|
|
||||||
|
|
@ -2,20 +2,19 @@
|
||||||
|
|
||||||
use log::info;
|
use log::info;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use whoami::platform;
|
|
||||||
|
|
||||||
use crate::class::{unsafe_ref, unsafe_val, UnsafeValue, Value};
|
use crate::class::{unsafe_ref, Value};
|
||||||
use crate::class::Value::Void;
|
use crate::class::Value::Void;
|
||||||
use crate::heap::ObjectRef;
|
use crate::heap::ObjectRef;
|
||||||
|
|
||||||
pub fn invoke_native(class_name: &String, method_name: &String, _args: Vec<UnsafeValue>) -> UnsafeValue {
|
pub fn invoke_native(class_name: &String, method_name: &String, _args: Vec<Value>) -> Value {
|
||||||
info!("native {}.{}", class_name, method_name);
|
info!("native {}.{}", class_name, method_name);
|
||||||
|
|
||||||
unsafe_val(match class_name.as_str() {
|
match class_name.as_str() {
|
||||||
"java/lang/Class" => java_lang_class(method_name),
|
"java/lang/Class" => java_lang_class(method_name),
|
||||||
"jdk/internal/util/SystemProps$Raw" => jdk_internal_util_SystemProps_Raw(method_name),
|
"jdk/internal/util/SystemProps$Raw" => jdk_internal_util_SystemProps_Raw(method_name),
|
||||||
_ => Void
|
_ => Void
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn java_lang_class(method_name: &String) -> Value {
|
fn java_lang_class(method_name: &String) -> Value {
|
||||||
|
|
|
||||||
|
|
@ -199,7 +199,7 @@ pub const _DSUB: u8 = 103;
|
||||||
pub const _FMUL: u8 = 106;
|
pub const _FMUL: u8 = 106;
|
||||||
// (0x6a) Multiply float
|
// (0x6a) Multiply float
|
||||||
pub const _DMUL: u8 = 107; // (0x6b) Multiply double
|
pub const _DMUL: u8 = 107; // (0x6b) Multiply double
|
||||||
|
pub const IDIV:u8 = 108;
|
||||||
pub const _FDIV: u8 = 110;
|
pub const _FDIV: u8 = 110;
|
||||||
// (0x6e) Divide float
|
// (0x6e) Divide float
|
||||||
pub const _DDIV: u8 = 111;
|
pub const _DDIV: u8 = 111;
|
||||||
|
|
|
||||||
198
src/vm.rs
198
src/vm.rs
|
|
@ -9,7 +9,7 @@ use log::{debug, info};
|
||||||
use Value::*;
|
use Value::*;
|
||||||
|
|
||||||
use crate::class::Value::{Null, Void};
|
use crate::class::Value::{Null, Void};
|
||||||
use crate::class::{get_class, unsafe_ref, unsafe_val, AttributeType, Class, Modifier, UnsafeValue, Value, Method, CLASSES};
|
use crate::class::{get_class, unsafe_ref, AttributeType, Class, Modifier, Value, Method, CLASSES};
|
||||||
use crate::classloader::CpEntry;
|
use crate::classloader::CpEntry;
|
||||||
use crate::heap::{Heap, Object, ObjectRef};
|
use crate::heap::{Heap, Object, ObjectRef};
|
||||||
use crate::io::*;
|
use crate::io::*;
|
||||||
|
|
@ -20,7 +20,7 @@ use crate::opcodes::*;
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct StackFrame {
|
pub(crate) struct StackFrame {
|
||||||
at: String,
|
at: String,
|
||||||
data: Vec<UnsafeValue>,
|
data: Vec<Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// maybe just call frame
|
// maybe just call frame
|
||||||
|
|
@ -33,16 +33,13 @@ impl StackFrame {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push(&mut self, val: Value) {
|
fn push(&mut self, val: Value) {
|
||||||
self.data.push(unsafe_val(val));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn push_ref(&mut self, val: UnsafeValue) {
|
|
||||||
self.data.push(val);
|
self.data.push(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn len(&self) -> usize {
|
fn len(&self) -> usize {
|
||||||
self.data.len()
|
self.data.len()
|
||||||
}
|
}
|
||||||
fn pop(&mut self) -> Result<UnsafeValue, Error> {
|
fn pop(&mut self) -> Result<Value, Error> {
|
||||||
Ok(self.data.pop().unwrap())
|
Ok(self.data.pop().unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -108,23 +105,22 @@ impl Vm {
|
||||||
&mut self,
|
&mut self,
|
||||||
class_name: &str,
|
class_name: &str,
|
||||||
method_name: &str,
|
method_name: &str,
|
||||||
args: Vec<UnsafeValue>,
|
args: Vec<Value>,
|
||||||
) -> Result<UnsafeValue, Error> {
|
) -> Result<Value, Error> {
|
||||||
unsafe {
|
unsafe {
|
||||||
for a in &args {
|
for arg in &args {
|
||||||
let v = &*a.get();
|
if let Ref(r) = arg {
|
||||||
if let Ref(r) = v {
|
|
||||||
info!("arg {:?}",&*r.get());
|
info!("arg {:?}",&*r.get());
|
||||||
} else {
|
} else {
|
||||||
info!("arg {:?}",&*a.get());
|
info!("arg {:?}",arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if let Null = &*args[0].get() {
|
if let Null = args[0] {
|
||||||
panic!("NPE");
|
panic!("NPE");
|
||||||
}
|
}
|
||||||
if let Ref(this) = &*args[0].get() {
|
if let Ref(this) = &args[0] {
|
||||||
if let ObjectRef::Object(this) = &*this.get() {
|
if let ObjectRef::Object(this) = &*this.get() {
|
||||||
let class = &this.class;
|
let class = &this.class;
|
||||||
let borrow = class.borrow();
|
let borrow = class.borrow();
|
||||||
|
|
@ -159,8 +155,8 @@ impl Vm {
|
||||||
&mut self,
|
&mut self,
|
||||||
class_name: &str,
|
class_name: &str,
|
||||||
method_name: &str,
|
method_name: &str,
|
||||||
args: Vec<UnsafeValue>,
|
args: Vec<Value>,
|
||||||
) -> Result<UnsafeValue, Error> {
|
) -> Result<Value, Error> {
|
||||||
let class = get_class(self, class_name)?;
|
let class = get_class(self, class_name)?;
|
||||||
let method = class.clone().borrow().get_method(method_name).expect("execute special needs invoked method on the class").clone();
|
let method = class.clone().borrow().get_method(method_name).expect("execute special needs invoked method on the class").clone();
|
||||||
self.execute_class(class.clone(), method.clone(), args)
|
self.execute_class(class.clone(), method.clone(), args)
|
||||||
|
|
@ -170,8 +166,8 @@ impl Vm {
|
||||||
&mut self,
|
&mut self,
|
||||||
class_name: &str,
|
class_name: &str,
|
||||||
method_name: &str,
|
method_name: &str,
|
||||||
args: Vec<UnsafeValue>,
|
args: Vec<Value>,
|
||||||
) -> Result<UnsafeValue, Error> {
|
) -> Result<Value, Error> {
|
||||||
let class = get_class(self, class_name)?;
|
let class = get_class(self, class_name)?;
|
||||||
let method = class.clone().borrow().get_method(method_name).expect("execute static needs this method").clone();
|
let method = class.clone().borrow().get_method(method_name).expect("execute static needs this method").clone();
|
||||||
self.execute_class(class, method, args)
|
self.execute_class(class, method, args)
|
||||||
|
|
@ -181,14 +177,14 @@ impl Vm {
|
||||||
&mut self,
|
&mut self,
|
||||||
class: Arc<RefCell<Class>>,
|
class: Arc<RefCell<Class>>,
|
||||||
method: Rc<Method>,
|
method: Rc<Method>,
|
||||||
args: Vec<UnsafeValue>,
|
args: Vec<Value>,
|
||||||
) -> Result<UnsafeValue, Error> {
|
) -> Result<Value, Error> {
|
||||||
let this_class = class;
|
let this_class = class;
|
||||||
info!("execute {}.{}", this_class.borrow().name, method.name());
|
info!("execute {}.{}", this_class.borrow().name, method.name());
|
||||||
|
|
||||||
//TODO implement dynamic dispatch -> get method from instance
|
//TODO implement dynamic dispatch -> get method from instance
|
||||||
|
|
||||||
let mut local_params: Vec<Option<UnsafeValue>> =
|
let mut local_params: Vec<Option<Value>> =
|
||||||
args.clone().iter().map(|e| Some(e.clone())).collect();
|
args.clone().iter().map(|e| Some(e.clone())).collect();
|
||||||
if method.is(Modifier::Native) {
|
if method.is(Modifier::Native) {
|
||||||
return Ok(invoke_native(&this_class.borrow().name, &method.name(), args));
|
return Ok(invoke_native(&this_class.borrow().name, &method.name(), args));
|
||||||
|
|
@ -277,9 +273,9 @@ impl Vm {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let stringinstance =
|
let stringinstance =
|
||||||
unsafe_val(Value::Ref(unsafe_ref(ObjectRef::Object(
|
Ref(unsafe_ref(ObjectRef::Object(
|
||||||
Box::new(Vm::new_instance(stringclass.clone())),
|
Box::new(Vm::new_instance(stringclass.clone())),
|
||||||
))));
|
)));
|
||||||
let string: Vec<u8> = this_class
|
let string: Vec<u8> = this_class
|
||||||
.borrow()
|
.borrow()
|
||||||
.cp_utf8(utf8)
|
.cp_utf8(utf8)
|
||||||
|
|
@ -293,10 +289,10 @@ impl Vm {
|
||||||
"<init>([B)V",
|
"<init>([B)V",
|
||||||
vec![
|
vec![
|
||||||
stringinstance.clone(),
|
stringinstance.clone(),
|
||||||
unsafe_val(Value::Ref(ObjectRef::new_byte_array(string))),
|
Ref(ObjectRef::new_byte_array(string)),
|
||||||
],
|
],
|
||||||
)?;
|
)?;
|
||||||
self.current_frame().push_ref(stringinstance);
|
self.current_frame().push(stringinstance);
|
||||||
}
|
}
|
||||||
CpEntry::Long(l) => {
|
CpEntry::Long(l) => {
|
||||||
self.current_frame().push(Value::I64(*l));
|
self.current_frame().push(Value::I64(*l));
|
||||||
|
|
@ -305,7 +301,7 @@ impl Vm {
|
||||||
let class_name = this_class.borrow().cp_utf8(utf8).unwrap().to_owned();
|
let class_name = this_class.borrow().cp_utf8(utf8).unwrap().to_owned();
|
||||||
unsafe {
|
unsafe {
|
||||||
if let Some(class) = CLASSES.get(&class_name) {
|
if let Some(class) = CLASSES.get(&class_name) {
|
||||||
self.current_frame().push_ref(class.clone());
|
self.current_frame().push(class.clone());
|
||||||
} else {
|
} else {
|
||||||
unreachable!("should not be here");
|
unreachable!("should not be here");
|
||||||
}
|
}
|
||||||
|
|
@ -355,23 +351,23 @@ impl Vm {
|
||||||
// omitting the type checks so far
|
// omitting the type checks so far
|
||||||
let n = read_u8(&code.opcodes, pc) as usize;
|
let n = read_u8(&code.opcodes, pc) as usize;
|
||||||
self.current_frame()
|
self.current_frame()
|
||||||
.push_ref(local_params[n].as_ref().unwrap().clone());
|
.push(local_params[n].as_ref().unwrap().clone());
|
||||||
}
|
}
|
||||||
ILOAD_0 | LLOAD_0 | FLOAD_0 | DLOAD_0 | ALOAD_0 => {
|
ILOAD_0 | LLOAD_0 | FLOAD_0 | DLOAD_0 | ALOAD_0 => {
|
||||||
self.current_frame()
|
self.current_frame()
|
||||||
.push_ref(local_params[0].as_ref().unwrap().clone());
|
.push(local_params[0].as_ref().unwrap().clone());
|
||||||
}
|
}
|
||||||
ILOAD_1 | LLOAD_1 | FLOAD_1 | DLOAD_1 | ALOAD_1 => {
|
ILOAD_1 | LLOAD_1 | FLOAD_1 | DLOAD_1 | ALOAD_1 => {
|
||||||
self.current_frame()
|
self.current_frame()
|
||||||
.push_ref(local_params[1].as_ref().unwrap().clone());
|
.push(local_params[1].as_ref().unwrap().clone());
|
||||||
}
|
}
|
||||||
ILOAD_2 | LLOAD_2 | FLOAD_2 | DLOAD_2 | ALOAD_2 => {
|
ILOAD_2 | LLOAD_2 | FLOAD_2 | DLOAD_2 | ALOAD_2 => {
|
||||||
self.current_frame()
|
self.current_frame()
|
||||||
.push_ref(local_params[2].as_ref().unwrap().clone());
|
.push(local_params[2].as_ref().unwrap().clone());
|
||||||
}
|
}
|
||||||
ILOAD_3 | LLOAD_3 | FLOAD_3 | DLOAD_3 | ALOAD_3 => {
|
ILOAD_3 | LLOAD_3 | FLOAD_3 | DLOAD_3 | ALOAD_3 => {
|
||||||
self.current_frame()
|
self.current_frame()
|
||||||
.push_ref(local_params[3].as_ref().unwrap().clone());
|
.push(local_params[3].as_ref().unwrap().clone());
|
||||||
}
|
}
|
||||||
IALOAD | LALOAD | FALOAD | DALOAD | AALOAD | BALOAD | CALOAD | SALOAD => unsafe {
|
IALOAD | LALOAD | FALOAD | DALOAD | AALOAD | BALOAD | CALOAD | SALOAD => unsafe {
|
||||||
self.array_load()?;
|
self.array_load()?;
|
||||||
|
|
@ -401,14 +397,14 @@ impl Vm {
|
||||||
}
|
}
|
||||||
DUP => {
|
DUP => {
|
||||||
let value = self.current_frame().pop()?;
|
let value = self.current_frame().pop()?;
|
||||||
self.current_frame().push_ref(value.clone());
|
self.current_frame().push(value.clone());
|
||||||
self.current_frame().push_ref(value);
|
self.current_frame().push(value);
|
||||||
}
|
}
|
||||||
IFEQ | IFNE | IFLT | IFGE | IFGT | IFLE => {
|
IFEQ | IFNE | IFLT | IFGE | IFGT | IFLE => {
|
||||||
let jmp_to = read_u16(&code.opcodes, pc) - 3; // -3 so that offset = location of Cmp opcode
|
let jmp_to = read_u16(&code.opcodes, pc) - 3; // -3 so that offset = location of Cmp opcode
|
||||||
let value = self.current_frame().pop()?;
|
let value = self.current_frame().pop()?;
|
||||||
unsafe {
|
unsafe {
|
||||||
Self::if_cmp(pc, opcode, jmp_to, &*value.get(), &I32(0));
|
Self::if_cmp(pc, opcode, jmp_to, &value, &I32(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -417,7 +413,7 @@ impl Vm {
|
||||||
let value1 = self.current_frame().pop()?;
|
let value1 = self.current_frame().pop()?;
|
||||||
let value2 = self.current_frame().pop()?;
|
let value2 = self.current_frame().pop()?;
|
||||||
unsafe {
|
unsafe {
|
||||||
Self::if_cmp(pc, opcode, jmp_to, &*value1.get(), &*value2.get());
|
Self::if_cmp(pc, opcode, jmp_to, &value1, &value2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GOTO => {
|
GOTO => {
|
||||||
|
|
@ -431,7 +427,7 @@ impl Vm {
|
||||||
}
|
}
|
||||||
RETURN_VOID => {
|
RETURN_VOID => {
|
||||||
self.stackframes.pop();
|
self.stackframes.pop();
|
||||||
return Ok(Value::void());
|
return Ok(Void);
|
||||||
}
|
}
|
||||||
GETSTATIC => {
|
GETSTATIC => {
|
||||||
let borrow = this_class.borrow();
|
let borrow = this_class.borrow();
|
||||||
|
|
@ -452,7 +448,7 @@ impl Vm {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.get(name)
|
.get(name)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
self.current_frame().push_ref(
|
self.current_frame().push(
|
||||||
that_borrow
|
that_borrow
|
||||||
.static_data
|
.static_data
|
||||||
.get(*val_index)
|
.get(*val_index)
|
||||||
|
|
@ -509,10 +505,10 @@ impl Vm {
|
||||||
let field_name = borrow.cp_utf8(field_name_index).unwrap();
|
let field_name = borrow.cp_utf8(field_name_index).unwrap();
|
||||||
|
|
||||||
let objectref = self.current_frame().pop()?;
|
let objectref = self.current_frame().pop()?;
|
||||||
if let Value::Ref(instance) = &mut *objectref.get() {
|
if let Ref(instance) = objectref {
|
||||||
if let ObjectRef::Object(ref mut object) = &mut *instance.get() {
|
if let ObjectRef::Object(ref mut object) = &mut *instance.get() {
|
||||||
let value = object.get(class_name, field_name);
|
let value = object.get(class_name, field_name);
|
||||||
self.current_frame().push_ref(Arc::clone(value));
|
self.current_frame().push(value.clone());
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
|
@ -533,7 +529,7 @@ impl Vm {
|
||||||
|
|
||||||
let value = self.current_frame().pop()?;
|
let value = self.current_frame().pop()?;
|
||||||
let objectref = self.current_frame().pop()?;
|
let objectref = self.current_frame().pop()?;
|
||||||
if let Value::Ref(instance) = &mut *objectref.get() {
|
if let Ref(instance) = objectref {
|
||||||
if let ObjectRef::Object(ref mut object) = &mut *instance.get() {
|
if let ObjectRef::Object(ref mut object) = &mut *instance.get() {
|
||||||
object.set(class_name, field_name, value);
|
object.set(class_name, field_name, value);
|
||||||
}
|
}
|
||||||
|
|
@ -549,7 +545,7 @@ impl Vm {
|
||||||
{
|
{
|
||||||
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, copy(self.current_frame().pop()?));
|
args.insert(0, self.current_frame().pop()?.clone());
|
||||||
}
|
}
|
||||||
args.insert(0, self.current_frame().pop()?);
|
args.insert(0, self.current_frame().pop()?);
|
||||||
let return_value = self.execute_special(
|
let return_value = self.execute_special(
|
||||||
|
|
@ -557,17 +553,17 @@ impl Vm {
|
||||||
&invocation.method.name,
|
&invocation.method.name,
|
||||||
args,
|
args,
|
||||||
)?;
|
)?;
|
||||||
if let Ref(r) = &*return_value.get() {
|
if let Ref(r) = &return_value {
|
||||||
if let ObjectRef::Object(p) = &*r.get() {
|
if let ObjectRef::Object(p) = &*r.get() {
|
||||||
info!("return {:?}", p);
|
info!("return {:?}", p);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
info!("return {:?}", &*return_value.get());
|
info!("return {:?}", return_value);
|
||||||
}
|
}
|
||||||
match *return_value.get() {
|
match return_value {
|
||||||
Void => {}
|
Void => {}
|
||||||
_ => {
|
_ => {
|
||||||
self.current_frame().push_ref(return_value.clone());
|
self.current_frame().push(return_value.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// println!("stack {} at {}", self.current_frame().len(), self.current_frame().at)
|
// println!("stack {} at {}", self.current_frame().len(), self.current_frame().at)
|
||||||
|
|
@ -583,7 +579,7 @@ impl Vm {
|
||||||
{
|
{
|
||||||
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, copy(self.current_frame().pop()?));
|
args.insert(0, self.current_frame().pop()?.clone());
|
||||||
}
|
}
|
||||||
args.insert(0, self.current_frame().pop()?);
|
args.insert(0, self.current_frame().pop()?);
|
||||||
let return_value = self.execute_virtual(
|
let return_value = self.execute_virtual(
|
||||||
|
|
@ -591,17 +587,17 @@ impl Vm {
|
||||||
&invocation.method.name,
|
&invocation.method.name,
|
||||||
args,
|
args,
|
||||||
)?;
|
)?;
|
||||||
if let Ref(r) = &*return_value.get() {
|
if let Ref(r) = &return_value {
|
||||||
if let ObjectRef::Object(p) = &*r.get() {
|
if let ObjectRef::Object(p) = &*r.get() {
|
||||||
info!("return {:?}", p);
|
info!("return {:?}", p);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
info!("return {:?}", &*return_value.get());
|
info!("return {:?}", return_value);
|
||||||
}
|
}
|
||||||
match *return_value.get() {
|
match return_value {
|
||||||
Void => {}
|
Void => {}
|
||||||
_ => {
|
_ => {
|
||||||
self.current_frame().push_ref(return_value.clone());
|
self.current_frame().push(return_value.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// println!("stack {} at {}", self.current_frame().len(), self.current_frame().at)
|
// println!("stack {} at {}", self.current_frame().len(), self.current_frame().at)
|
||||||
|
|
@ -616,24 +612,24 @@ impl Vm {
|
||||||
{
|
{
|
||||||
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, copy(self.current_frame().pop()?));
|
args.insert(0, self.current_frame().pop()?.clone());
|
||||||
}
|
}
|
||||||
let return_value = self.execute_static(
|
let return_value = self.execute_static(
|
||||||
&invocation.class_name,
|
&invocation.class_name,
|
||||||
&invocation.method.name,
|
&invocation.method.name,
|
||||||
args,
|
args,
|
||||||
)?;
|
)?;
|
||||||
if let Ref(r) = &*return_value.get() {
|
if let Ref(r) = &return_value {
|
||||||
if let ObjectRef::Object(p) = &*r.get() {
|
if let ObjectRef::Object(p) = &*r.get() {
|
||||||
info!("return {:?}", p);
|
info!("return {:?}", p);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
info!("return {:?}", &*return_value.get());
|
info!("return {:?}", return_value);
|
||||||
}
|
}
|
||||||
match *return_value.get() {
|
match return_value {
|
||||||
Void => {}
|
Void => {}
|
||||||
_ => {
|
_ => {
|
||||||
self.current_frame().push_ref(return_value.clone());
|
self.current_frame().push(return_value.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -660,7 +656,7 @@ impl Vm {
|
||||||
let class_name = borrow.cp_utf8(class_name_index).unwrap();
|
let class_name = borrow.cp_utf8(class_name_index).unwrap();
|
||||||
let arraytype = get_class(self, class_name)?;
|
let arraytype = get_class(self, class_name)?;
|
||||||
let count = self.current_frame().pop()?;
|
let count = self.current_frame().pop()?;
|
||||||
if let I32(count) = *count.get() {
|
if let I32(count) = count {
|
||||||
// why does pop()?.get() give weird results?
|
// why does pop()?.get() give weird results?
|
||||||
let array = ObjectRef::new_object_array(arraytype, count as usize);
|
let array = ObjectRef::new_object_array(arraytype, count as usize);
|
||||||
let array = unsafe_ref(array);
|
let array = unsafe_ref(array);
|
||||||
|
|
@ -674,7 +670,7 @@ impl Vm {
|
||||||
ARRAYLENGTH => {
|
ARRAYLENGTH => {
|
||||||
let val = self.current_frame().pop()?;
|
let val = self.current_frame().pop()?;
|
||||||
unsafe {
|
unsafe {
|
||||||
if let Ref(val) = &*val.get() {
|
if let Ref(val) = val {
|
||||||
let o = &*val.get();
|
let o = &*val.get();
|
||||||
self.current_frame().push(I32(o.get_array_length() as i32));
|
self.current_frame().push(I32(o.get_array_length() as i32));
|
||||||
}
|
}
|
||||||
|
|
@ -686,7 +682,7 @@ impl Vm {
|
||||||
IFNULL | IFNONNULL => unsafe {
|
IFNULL | IFNONNULL => unsafe {
|
||||||
let jmp_to = read_u16(&code.opcodes, pc) - 3;
|
let jmp_to = read_u16(&code.opcodes, pc) - 3;
|
||||||
let value = self.current_frame().pop()?;
|
let value = self.current_frame().pop()?;
|
||||||
let its_null = if let Null = *value.get() { true } else { false };
|
let its_null = if let Null = value { true } else { false };
|
||||||
|
|
||||||
if its_null && opcode == IFNULL {
|
if its_null && opcode == IFNULL {
|
||||||
info!("\t\tIF NULL =>{}: JMP {}", its_null, *pc + jmp_to as usize);
|
info!("\t\tIF NULL =>{}: JMP {}", its_null, *pc + jmp_to as usize);
|
||||||
|
|
@ -740,13 +736,13 @@ impl Vm {
|
||||||
unsafe fn array_load(&mut self) -> Result<(), Error> {
|
unsafe fn array_load(&mut self) -> Result<(), Error> {
|
||||||
let value = self.current_frame().pop()?;
|
let value = self.current_frame().pop()?;
|
||||||
|
|
||||||
if let I32(index) = &*value.get() {
|
if let I32(index) = &value {
|
||||||
let index = *index as usize;
|
let index = *index as usize;
|
||||||
let arrayref = self.current_frame().pop()?;
|
let arrayref = self.current_frame().pop()?;
|
||||||
if let Null = &*arrayref.get() {
|
if let Null = arrayref {
|
||||||
return Err(anyhow!("NullpointerException"));
|
return Err(anyhow!("NullpointerException"));
|
||||||
}
|
}
|
||||||
if let Ref(objectref) = &*arrayref.get() {
|
if let Ref(objectref) = arrayref {
|
||||||
match &*objectref.get() {
|
match &*objectref.get() {
|
||||||
ObjectRef::ByteArray(array) => {
|
ObjectRef::ByteArray(array) => {
|
||||||
self.current_frame().push(I32(array[index] as i32));
|
self.current_frame().push(I32(array[index] as i32));
|
||||||
|
|
@ -792,84 +788,84 @@ impl Vm {
|
||||||
|
|
||||||
unsafe fn array_store(&mut self) -> Result<(), Error> {
|
unsafe fn array_store(&mut self) -> Result<(), Error> {
|
||||||
let value = self.current_frame().pop()?;
|
let value = self.current_frame().pop()?;
|
||||||
let index = &*self.current_frame().pop()?;
|
let index = self.current_frame().pop()?;
|
||||||
let arrayref = &mut self.current_frame().pop()?;
|
let arrayref = &mut self.current_frame().pop()?;
|
||||||
|
|
||||||
if let Value::Null = &*arrayref.get() {
|
if let Value::Null = &*arrayref {
|
||||||
return Err(anyhow!("NullpointerException"));
|
return Err(anyhow!("NullpointerException"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let I32(index) = &*index.get() {
|
if let I32(index) = index {
|
||||||
if let Value::Ref(ref mut objectref) = &mut *arrayref.get() {
|
if let Ref(ref mut objectref) = arrayref {
|
||||||
match &mut *objectref.get() {
|
match &mut *objectref.get() {
|
||||||
ObjectRef::ByteArray(ref mut array) => {
|
ObjectRef::ByteArray(ref mut array) => {
|
||||||
if let I32(value) = *value.get() {
|
if let I32(value) = value {
|
||||||
// is i32 correct?
|
// is i32 correct?
|
||||||
array[*index as usize] = value as i8;
|
array[index as usize] = value as i8;
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ObjectRef::ShortArray(ref mut array) => {
|
ObjectRef::ShortArray(ref mut array) => {
|
||||||
if let I32(value) = *value.get() {
|
if let I32(value) = value {
|
||||||
// is i32 correct?
|
// is i32 correct?
|
||||||
array[*index as usize] = value as i16;
|
array[index as usize] = value as i16;
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ObjectRef::IntArray(ref mut array) => {
|
ObjectRef::IntArray(ref mut array) => {
|
||||||
if let I32(value) = *value.get() {
|
if let I32(value) = value{
|
||||||
array[*index as usize] = value;
|
array[index as usize] = value;
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ObjectRef::BooleanArray(ref mut array) => {
|
ObjectRef::BooleanArray(ref mut array) => {
|
||||||
if let I32(value) = *value.get() {
|
if let I32(value) = value {
|
||||||
array[*index as usize] = value > 0;
|
array[index as usize] = value > 0;
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ObjectRef::CharArray(ref mut array) => {
|
ObjectRef::CharArray(ref mut array) => {
|
||||||
if let I32(value) = *value.get() {
|
if let I32(value) = value {
|
||||||
array[*index as usize] = char::from_u32_unchecked(value as u32);
|
array[index as usize] = char::from_u32_unchecked(value as u32);
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ObjectRef::LongArray(ref mut array) => {
|
ObjectRef::LongArray(ref mut array) => {
|
||||||
if let Value::I64(value) = *value.get() {
|
if let I64(value) = value {
|
||||||
array[*index as usize] = value;
|
array[index as usize] = value;
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ObjectRef::FloatArray(ref mut array) => {
|
ObjectRef::FloatArray(ref mut array) => {
|
||||||
if let Value::F32(value) = *value.get() {
|
if let F32(value) = value {
|
||||||
array[*index as usize] = value
|
array[index as usize] = value
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ObjectRef::DoubleArray(ref mut array) => {
|
ObjectRef::DoubleArray(ref mut array) => {
|
||||||
if let Value::F64(value) = *value.get() {
|
if let F64(value) = value {
|
||||||
array[*index as usize] = value
|
array[index as usize] = value
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ObjectRef::ObjectArray(_arraytype, ref mut array) => {
|
ObjectRef::ObjectArray(_arraytype, ref mut array) => {
|
||||||
if let Ref(ref value) = *value.get() {
|
if let Ref(ref value) = value {
|
||||||
array[*index as usize] = value.clone();
|
array[index as usize] = value.clone();
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ObjectRef::StringArray(ref mut array) => {
|
ObjectRef::StringArray(ref mut array) => {
|
||||||
if let Utf8(ref value) = *value.get() {
|
if let Utf8(ref value) = value {
|
||||||
array[*index as usize] = value.clone();
|
array[index as usize] = value.clone();
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
|
@ -885,7 +881,7 @@ impl Vm {
|
||||||
|
|
||||||
fn store(
|
fn store(
|
||||||
&mut self,
|
&mut self,
|
||||||
local_params: &mut Vec<Option<UnsafeValue>>,
|
local_params: &mut Vec<Option<Value>>,
|
||||||
index: usize,
|
index: usize,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let value = self.current_frame().pop()?;
|
let value = self.current_frame().pop()?;
|
||||||
|
|
@ -926,20 +922,20 @@ fn get_signature_for_invoke(cp: &Rc<HashMap<u16, CpEntry>>, index: u16) -> Optio
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn copy(value: UnsafeValue) -> UnsafeValue {
|
// unsafe fn copy(value: Value) -> Value {
|
||||||
unsafe_val(match &*value.get() {
|
// match value {
|
||||||
Void => Void,
|
// Void => Void,
|
||||||
Null => Null,
|
// Null => Null,
|
||||||
BOOL(b) => BOOL(*b),
|
// BOOL(b) => BOOL(b),
|
||||||
CHAR(c) => CHAR(*c),
|
// CHAR(c) => CHAR(c),
|
||||||
I32(i) => I32(*i),
|
// I32(i) => I32(i),
|
||||||
I64(l) => I64(*l),
|
// I64(l) => I64(l),
|
||||||
F32(f) => F32(*f),
|
// F32(f) => F32(f),
|
||||||
F64(d) => F64(*d),
|
// F64(d) => F64(d),
|
||||||
Ref(r) => Ref(r.clone()),
|
// Ref(r) => Ref(r.clone()),
|
||||||
Utf8(s) => Utf8(s.to_owned()),
|
// Utf8(s) => Utf8(s.to_owned()),
|
||||||
})
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
fn get_name_and_type(cp: Rc<HashMap<u16, CpEntry>>, index: u16) -> Option<MethodSignature> {
|
fn get_name_and_type(cp: Rc<HashMap<u16, CpEntry>>, index: u16) -> Option<MethodSignature> {
|
||||||
if let CpEntry::NameAndType(method_name_index, signature_index) = cp.get(&index).unwrap() {
|
if let CpEntry::NameAndType(method_name_index, signature_index) = cp.get(&index).unwrap() {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue