busy implementing hashcode
This commit is contained in:
parent
b714827f24
commit
c271881a79
6 changed files with 168 additions and 50 deletions
|
|
@ -38,6 +38,7 @@ pub(crate) fn parse_code(opcodes: &[u8]) -> Vec<Opcode> {
|
||||||
IFGE(goto) => IFGE(code2.get(&goto).unwrap().0),
|
IFGE(goto) => IFGE(code2.get(&goto).unwrap().0),
|
||||||
IFLT(goto) => IFLT(code2.get(&goto).unwrap().0),
|
IFLT(goto) => IFLT(code2.get(&goto).unwrap().0),
|
||||||
IFLE(goto) => IFLE(code2.get(&goto).unwrap().0),
|
IFLE(goto) => IFLE(code2.get(&goto).unwrap().0),
|
||||||
|
GOTO(goto) => GOTO(code2.get(&goto).unwrap().0),
|
||||||
|
|
||||||
//TODO more jump instructions
|
//TODO more jump instructions
|
||||||
_ => opcode,
|
_ => opcode,
|
||||||
|
|
@ -214,8 +215,8 @@ fn get_opcode(opcodes: &[u8], c: &mut usize) -> Opcode {
|
||||||
164 => IF_ICMPLE(offset(opcodes, c)),
|
164 => IF_ICMPLE(offset(opcodes, c)),
|
||||||
165 => IF_ACMPEQ(offset(opcodes, c)),
|
165 => IF_ACMPEQ(offset(opcodes, c)),
|
||||||
166 => IF_ACMPNE(offset(opcodes, c)),
|
166 => IF_ACMPNE(offset(opcodes, c)),
|
||||||
167 => GOTO(read_u16(opcodes, c)),
|
167 => GOTO(offset(opcodes, c)),
|
||||||
168 => JSR(read_u16(opcodes, c)),
|
168 => JSR(offset(opcodes, c)),
|
||||||
169 => RET(read_u8(opcodes, c)),
|
169 => RET(read_u8(opcodes, c)),
|
||||||
170 => TABLESWITCH(read_tableswitch(opcodes, c)),
|
170 => TABLESWITCH(read_tableswitch(opcodes, c)),
|
||||||
171 => LOOKUPSWITCH(read_lookupswitch(opcodes, c)),
|
171 => LOOKUPSWITCH(read_lookupswitch(opcodes, c)),
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,6 @@
|
||||||
use java_rs::vm::runtime::Vm;
|
use java_rs::vm::runtime::Vm;
|
||||||
use std::cmp::Ordering::Equal;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let a = 0.0;
|
|
||||||
println!("{}", 1.0 / a);
|
|
||||||
let mut vm = Vm::new();
|
let mut vm = Vm::new();
|
||||||
vm.run(
|
vm.run(
|
||||||
"/Users/Shautvast/dev/java.rs/tests",
|
"/Users/Shautvast/dev/java.rs/tests",
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,13 @@ use anyhow::{anyhow, Error};
|
||||||
|
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
use crate::value::Value::*;
|
use crate::value::Value::*;
|
||||||
|
use crate::vm::object::ObjectRef;
|
||||||
|
|
||||||
pub(crate) fn array_load(index: Value, arrayref: Value) -> Result<Value, Error> {
|
pub(crate) fn array_load(index: Value, arrayref: Value) -> Result<Value, Error> {
|
||||||
if let I32(index) = index {
|
if let I32(index) = index {
|
||||||
let index = index as usize;
|
let index = index as usize;
|
||||||
|
|
||||||
if let Null = arrayref {
|
if let Value::Null = arrayref {
|
||||||
return Err(anyhow!("NullpointerException"));
|
return Err(anyhow!("NullpointerException"));
|
||||||
}
|
}
|
||||||
if let Ref(objectref) = arrayref {
|
if let Ref(objectref) = arrayref {
|
||||||
|
|
@ -49,6 +50,9 @@ pub(crate) fn array_load(index: Value, arrayref: Value) -> Result<Value, Error>
|
||||||
Object(_) => {
|
Object(_) => {
|
||||||
panic!("should be array")
|
panic!("should be array")
|
||||||
} //throw error?
|
} //throw error?
|
||||||
|
ObjectRef::Null => {
|
||||||
|
return Ok(Value::Null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -56,7 +60,7 @@ pub(crate) fn array_load(index: Value, arrayref: Value) -> Result<Value, Error>
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn array_store(value: Value, index: Value, arrayref: Value) -> Result<(), Error> {
|
pub(crate) fn array_store(value: Value, index: Value, arrayref: Value) -> Result<(), Error> {
|
||||||
if let Null = arrayref {
|
if let Value::Null = arrayref {
|
||||||
return Err(anyhow!("NullpointerException"));
|
return Err(anyhow!("NullpointerException"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -135,7 +139,7 @@ pub(crate) fn array_store(value: Value, index: Value, arrayref: Value) -> Result
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Object(_) | Class(_) => {} //throw error?
|
Object(_) | Class(_) | ObjectRef::Null => {} //throw error?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::future::Future;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
|
|
@ -13,7 +12,7 @@ use crate::classmanager::ClassManager;
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
use crate::value::Value::{Utf8, Void, I32};
|
use crate::value::Value::{Utf8, Void, I32};
|
||||||
use crate::vm::object::ObjectRef::Object;
|
use crate::vm::object::ObjectRef::Object;
|
||||||
use crate::vm::object::{self, ObjectRef};
|
use crate::vm::object::{self, Array, ObjectRef};
|
||||||
use crate::vm::runtime::Stackframe;
|
use crate::vm::runtime::Stackframe;
|
||||||
|
|
||||||
const primitive_name_classes: Lazy<HashMap<&str, &str>> = Lazy::new(|| {
|
const primitive_name_classes: Lazy<HashMap<&str, &str>> = Lazy::new(|| {
|
||||||
|
|
@ -40,12 +39,13 @@ pub fn invoke_native(
|
||||||
|
|
||||||
match class_name {
|
match class_name {
|
||||||
"java/lang/Class" => java_lang_Class(class_manager, method_name, args),
|
"java/lang/Class" => java_lang_Class(class_manager, method_name, args),
|
||||||
|
"java/lang/Object" => java_lang_Object(method_name, args),
|
||||||
"java/lang/System" => java_lang_System(method_name),
|
"java/lang/System" => java_lang_System(method_name),
|
||||||
"jdk/internal/misc/Unsafe" => jdk_internal_misc_Unsafe(method_name),
|
"jdk/internal/misc/Unsafe" => jdk_internal_misc_Unsafe(method_name),
|
||||||
"jdk/internal/util/SystemProps$Raw" => {
|
"jdk/internal/util/SystemProps$Raw" => {
|
||||||
jdk_internal_util_SystemProps_Raw(class_manager, method_name)
|
jdk_internal_util_SystemProps_Raw(class_manager, method_name)
|
||||||
}
|
}
|
||||||
_ => unimplemented!(""),
|
_ => unimplemented!("{}", class_name),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -63,6 +63,25 @@ fn java_lang_Class(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn java_lang_Object(method_name: &str, args: Vec<Value>) -> Result<Value, Error> {
|
||||||
|
Ok(match method_name {
|
||||||
|
"hashCode()I" => {
|
||||||
|
if let Value::Ref(object_ref) = args.get(0).unwrap() {
|
||||||
|
if let Object(p) = object_ref {
|
||||||
|
I32(p.borrow().id as i32) // system hashcode
|
||||||
|
} else {
|
||||||
|
I32(0) //todo implement for arrays
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unimplemented!("{}", method_name);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn java_lang_System(method_name: &str) -> Result<Value, Error> {
|
fn java_lang_System(method_name: &str) -> Result<Value, Error> {
|
||||||
Ok(match method_name {
|
Ok(match method_name {
|
||||||
_ => Void,
|
_ => Void,
|
||||||
|
|
@ -129,7 +148,9 @@ fn vmProperties() -> Result<Value, Error> {
|
||||||
//TODO insert some values
|
//TODO insert some values
|
||||||
vec
|
vec
|
||||||
});
|
});
|
||||||
Ok(Value::Ref(ObjectRef::StringArray(props.to_vec())))
|
Ok(Value::Ref(ObjectRef::StringArray(Array::from_vec(
|
||||||
|
props.to_vec(),
|
||||||
|
))))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn platformProperties() -> Result<Value, Error> {
|
fn platformProperties() -> Result<Value, Error> {
|
||||||
|
|
@ -216,5 +237,7 @@ fn platformProperties() -> Result<Value, Error> {
|
||||||
|
|
||||||
vec
|
vec
|
||||||
});
|
});
|
||||||
Ok(Value::Ref(ObjectRef::StringArray(props.to_vec())))
|
Ok(Value::Ref(ObjectRef::StringArray(Array::from_vec(
|
||||||
|
props.to_vec(),
|
||||||
|
))))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
120
src/vm/object.rs
120
src/vm/object.rs
|
|
@ -7,37 +7,91 @@ use std::cell::RefCell;
|
||||||
use std::fmt::{Debug, Formatter, Pointer};
|
use std::fmt::{Debug, Formatter, Pointer};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Array<T>
|
||||||
|
where
|
||||||
|
T: Clone,
|
||||||
|
{
|
||||||
|
id: u32,
|
||||||
|
data: Vec<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Array<T>
|
||||||
|
where
|
||||||
|
T: Clone,
|
||||||
|
{
|
||||||
|
pub fn new(init: T, size: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
id: random::<u32>() >> 1,
|
||||||
|
data: vec![init; size],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_vec(vec: Vec<T>) -> Self {
|
||||||
|
Self {
|
||||||
|
id: random::<u32>() >> 1,
|
||||||
|
data: vec,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.data.len()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> std::ops::Index<usize> for Array<T>
|
||||||
|
where
|
||||||
|
T: Clone,
|
||||||
|
{
|
||||||
|
type Output = T;
|
||||||
|
|
||||||
|
fn index(&self, index: usize) -> &Self::Output {
|
||||||
|
&self.data[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> std::ops::IndexMut<usize> for Array<T>
|
||||||
|
where
|
||||||
|
T: Clone,
|
||||||
|
{
|
||||||
|
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
||||||
|
&mut self.data[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum ObjectRef {
|
pub enum ObjectRef {
|
||||||
ByteArray(Vec<i8>), //maybe use arrays?
|
ByteArray(Array<i8>),
|
||||||
ShortArray(Vec<i16>),
|
//maybe use arrays?
|
||||||
IntArray(Vec<i32>),
|
ShortArray(Array<i16>),
|
||||||
LongArray(Vec<i64>),
|
IntArray(Array<i32>),
|
||||||
FloatArray(Vec<f32>),
|
LongArray(Array<i64>),
|
||||||
DoubleArray(Vec<f64>),
|
FloatArray(Array<f32>),
|
||||||
BooleanArray(Vec<bool>),
|
DoubleArray(Array<f64>),
|
||||||
CharArray(Vec<i32>),
|
BooleanArray(Array<bool>),
|
||||||
StringArray(Vec<String>),
|
CharArray(Array<i32>),
|
||||||
|
StringArray(Array<String>),
|
||||||
ObjectArray(ClassId, Vec<ObjectRef>),
|
ObjectArray(ClassId, Vec<ObjectRef>),
|
||||||
Object(Rc<RefCell<Object>>),
|
Object(Rc<RefCell<Object>>),
|
||||||
Class(Class),
|
Class(Class),
|
||||||
|
Null,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for ObjectRef {
|
impl Debug for ObjectRef {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
let name = match self {
|
let name = match self {
|
||||||
ByteArray(_) => "[B", //length for arrays
|
ByteArray(a) => format!("[B;{}", a.len()),
|
||||||
ShortArray(_) => "[S",
|
ShortArray(a) => format!("[S;{}", a.len()),
|
||||||
IntArray(_) => "[I]",
|
IntArray(a) => format!("[I;{}", a.len()),
|
||||||
LongArray(_) => "[J",
|
LongArray(a) => format!("[J;{}", a.len()),
|
||||||
FloatArray(_) => "[F",
|
FloatArray(a) => format!("[F;{}", a.len()),
|
||||||
DoubleArray(_) => "[D]",
|
DoubleArray(a) => format!("[D;{}", a.len()),
|
||||||
BooleanArray(_) => "[Z",
|
BooleanArray(a) => format!("[Z;{}", a.len()),
|
||||||
CharArray(_) => "[C",
|
CharArray(a) => format!("[C;{}", a.len()),
|
||||||
StringArray(_) => "[Ljava/lang/String]",
|
StringArray(a) => format!("[Ljava/lang/String;{}]", a.len()),
|
||||||
ObjectArray(_, _) => "[L",
|
ObjectArray(_, a) => format!("[[Lx;{}]", a.len()),
|
||||||
Object(_) => "L",
|
Object(_) => "L".into(),
|
||||||
Class(_) => "Class",
|
Class(_) => "Class".into(),
|
||||||
|
ObjectRef::Null => "null".into(),
|
||||||
};
|
};
|
||||||
write!(f, "{}", name)
|
write!(f, "{}", name)
|
||||||
}
|
}
|
||||||
|
|
@ -74,29 +128,29 @@ pub enum ArrayType {
|
||||||
|
|
||||||
impl ObjectRef {
|
impl ObjectRef {
|
||||||
pub fn new_object_array(class: &Class, size: usize) -> Self {
|
pub fn new_object_array(class: &Class, size: usize) -> Self {
|
||||||
ObjectArray(class.id, Vec::with_capacity(size))
|
ObjectArray(class.id, vec![ObjectRef::Null; size])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_array(arraytype: u8, size: usize) -> Self {
|
pub fn new_array(arraytype: u8, size: usize) -> Self {
|
||||||
match arraytype {
|
match arraytype {
|
||||||
8 => ByteArray(vec![0; size]),
|
8 => ByteArray(Array::new(0, size)),
|
||||||
9 => ShortArray(vec![0; size]),
|
9 => ShortArray(Array::new(0, size)),
|
||||||
10 => IntArray(vec![0; size]),
|
10 => IntArray(Array::new(0, size)),
|
||||||
11 => LongArray(vec![0; size]),
|
11 => LongArray(Array::new(0, size)),
|
||||||
6 => FloatArray(vec![0.0; size]),
|
6 => FloatArray(Array::new(0_f32, size)),
|
||||||
7 => DoubleArray(vec![0.0; size]),
|
7 => DoubleArray(Array::new(0_f64, size)),
|
||||||
4 => BooleanArray(vec![false; size]),
|
4 => BooleanArray(Array::new(false, size)),
|
||||||
5 => CharArray(vec![0; size]),
|
5 => CharArray(Array::new(0, size)),
|
||||||
_ => unreachable!("impossible array type"),
|
_ => unreachable!("impossible array type"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_int_array(size: usize) -> Self {
|
pub fn new_int_array(size: usize) -> Self {
|
||||||
IntArray(Vec::with_capacity(size))
|
IntArray(Array::new(0, size))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_byte_array(d: Vec<u8>) -> Self {
|
pub fn new_byte_array(d: Vec<u8>) -> Self {
|
||||||
ByteArray(into_vec_i8(d))
|
ByteArray(Array::from_vec(into_vec_i8(d)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,7 +181,7 @@ impl Object {
|
||||||
pub fn new(class: &Class) -> Self {
|
pub fn new(class: &Class) -> Self {
|
||||||
let instance_data = Object::init_fields(class);
|
let instance_data = Object::init_fields(class);
|
||||||
Self {
|
Self {
|
||||||
id: random(),
|
id: random::<u32>() >> 1,
|
||||||
class_id: class.id,
|
class_id: class.id,
|
||||||
data: instance_data,
|
data: instance_data,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -514,9 +514,13 @@ impl Stackframe {
|
||||||
let value1 = self.pop();
|
let value1 = self.pop();
|
||||||
if_cmp(&mut self.pc, opcode, jmp_to, &value1, &value2);
|
if_cmp(&mut self.pc, opcode, jmp_to, &value1, &value2);
|
||||||
}
|
}
|
||||||
GOTO(jmp_to) => {
|
GOTO(jmp_to) | JSR(jmp_to) => {
|
||||||
self.pc += *jmp_to as usize;
|
self.pc = *jmp_to as usize;
|
||||||
}
|
}
|
||||||
|
JSR_W(jmp_to) => {
|
||||||
|
self.pc = *jmp_to as usize;
|
||||||
|
}
|
||||||
|
|
||||||
INVOKEVIRTUAL(c) => {
|
INVOKEVIRTUAL(c) => {
|
||||||
if let Some(invocation) = get_signature_for_invoke(&constant_pool, *c) {
|
if let Some(invocation) = get_signature_for_invoke(&constant_pool, *c) {
|
||||||
let mut args = Vec::with_capacity(invocation.method.num_args);
|
let mut args = Vec::with_capacity(invocation.method.num_args);
|
||||||
|
|
@ -816,7 +820,9 @@ impl Stackframe {
|
||||||
self.push(value.clone());
|
self.push(value.clone());
|
||||||
}
|
}
|
||||||
IRETURN | LRETURN | FRETURN | DRETURN | ARETURN => {
|
IRETURN | LRETURN | FRETURN | DRETURN | ARETURN => {
|
||||||
return self.pop();
|
let v = self.pop();
|
||||||
|
debug!("returning {:?}", v);
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
RETURN_VOID => {
|
RETURN_VOID => {
|
||||||
return Void;
|
return Void;
|
||||||
|
|
@ -867,9 +873,42 @@ impl Stackframe {
|
||||||
if value1 > 0 {
|
if value1 > 0 {
|
||||||
self.push(I64(value1 >> value2));
|
self.push(I64(value1 >> value2));
|
||||||
} else {
|
} else {
|
||||||
self.push(Value::I64(((value1 as u64) >> value2) as i64));
|
self.push(I64(((value1 as u64) >> value2) as i64));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
IAND => {
|
||||||
|
let value2 = self.pop().into_i32();
|
||||||
|
let value1 = self.pop().into_i32();
|
||||||
|
self.push(I32(value1 & value2));
|
||||||
|
}
|
||||||
|
|
||||||
|
LAND => {
|
||||||
|
let value2 = self.pop().into_i64();
|
||||||
|
let value1 = self.pop().into_i64();
|
||||||
|
self.push(I64(value1 & value2));
|
||||||
|
}
|
||||||
|
IOR => {
|
||||||
|
let value2 = self.pop().into_i32();
|
||||||
|
let value1 = self.pop().into_i32();
|
||||||
|
self.push(I32(value1 | value2));
|
||||||
|
}
|
||||||
|
LOR => {
|
||||||
|
let value2 = self.pop().into_i64();
|
||||||
|
let value1 = self.pop().into_i64();
|
||||||
|
self.push(I64(value1 | value2));
|
||||||
|
}
|
||||||
|
IXOR => {
|
||||||
|
let value2 = self.pop().into_i32();
|
||||||
|
let value1 = self.pop().into_i32();
|
||||||
|
self.push(I32(value1 ^ value2));
|
||||||
|
}
|
||||||
|
LXOR => {
|
||||||
|
let value2 = self.pop().into_i64();
|
||||||
|
let value1 = self.pop().into_i64();
|
||||||
|
self.push(I64(value1 ^ value2));
|
||||||
|
}
|
||||||
|
|
||||||
|
CHECKCAST(_) => {}
|
||||||
_ => {
|
_ => {
|
||||||
panic!("opcode not implemented")
|
panic!("opcode not implemented")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue