busy implementing hashcode

This commit is contained in:
Shautvast 2023-12-07 17:20:19 +01:00
parent b714827f24
commit c271881a79
6 changed files with 168 additions and 50 deletions

View file

@ -38,6 +38,7 @@ pub(crate) fn parse_code(opcodes: &[u8]) -> Vec<Opcode> {
IFGE(goto) => IFGE(code2.get(&goto).unwrap().0),
IFLT(goto) => IFLT(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
_ => opcode,
@ -214,8 +215,8 @@ fn get_opcode(opcodes: &[u8], c: &mut usize) -> Opcode {
164 => IF_ICMPLE(offset(opcodes, c)),
165 => IF_ACMPEQ(offset(opcodes, c)),
166 => IF_ACMPNE(offset(opcodes, c)),
167 => GOTO(read_u16(opcodes, c)),
168 => JSR(read_u16(opcodes, c)),
167 => GOTO(offset(opcodes, c)),
168 => JSR(offset(opcodes, c)),
169 => RET(read_u8(opcodes, c)),
170 => TABLESWITCH(read_tableswitch(opcodes, c)),
171 => LOOKUPSWITCH(read_lookupswitch(opcodes, c)),

View file

@ -1,9 +1,6 @@
use java_rs::vm::runtime::Vm;
use std::cmp::Ordering::Equal;
fn main() {
let a = 0.0;
println!("{}", 1.0 / a);
let mut vm = Vm::new();
vm.run(
"/Users/Shautvast/dev/java.rs/tests",

View file

@ -3,12 +3,13 @@ use anyhow::{anyhow, Error};
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> {
if let I32(index) = index {
let index = index as usize;
if let Null = arrayref {
if let Value::Null = arrayref {
return Err(anyhow!("NullpointerException"));
}
if let Ref(objectref) = arrayref {
@ -49,6 +50,9 @@ pub(crate) fn array_load(index: Value, arrayref: Value) -> Result<Value, Error>
Object(_) => {
panic!("should be array")
} //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> {
if let Null = arrayref {
if let Value::Null = arrayref {
return Err(anyhow!("NullpointerException"));
}
@ -135,7 +139,7 @@ pub(crate) fn array_store(value: Value, index: Value, arrayref: Value) -> Result
unreachable!()
}
}
Object(_) | Class(_) => {} //throw error?
Object(_) | Class(_) | ObjectRef::Null => {} //throw error?
}
}
} else {

View file

@ -2,7 +2,6 @@
use std::cell::RefCell;
use std::collections::HashMap;
use std::future::Future;
use std::rc::Rc;
use anyhow::Error;
@ -13,7 +12,7 @@ use crate::classmanager::ClassManager;
use crate::value::Value;
use crate::value::Value::{Utf8, Void, I32};
use crate::vm::object::ObjectRef::Object;
use crate::vm::object::{self, ObjectRef};
use crate::vm::object::{self, Array, ObjectRef};
use crate::vm::runtime::Stackframe;
const primitive_name_classes: Lazy<HashMap<&str, &str>> = Lazy::new(|| {
@ -40,12 +39,13 @@ pub fn invoke_native(
match class_name {
"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),
"jdk/internal/misc/Unsafe" => jdk_internal_misc_Unsafe(method_name),
"jdk/internal/util/SystemProps$Raw" => {
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> {
Ok(match method_name {
_ => Void,
@ -129,7 +148,9 @@ fn vmProperties() -> Result<Value, Error> {
//TODO insert some values
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> {
@ -216,5 +237,7 @@ fn platformProperties() -> Result<Value, Error> {
vec
});
Ok(Value::Ref(ObjectRef::StringArray(props.to_vec())))
Ok(Value::Ref(ObjectRef::StringArray(Array::from_vec(
props.to_vec(),
))))
}

View file

@ -7,37 +7,91 @@ use std::cell::RefCell;
use std::fmt::{Debug, Formatter, Pointer};
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)]
pub enum ObjectRef {
ByteArray(Vec<i8>), //maybe use arrays?
ShortArray(Vec<i16>),
IntArray(Vec<i32>),
LongArray(Vec<i64>),
FloatArray(Vec<f32>),
DoubleArray(Vec<f64>),
BooleanArray(Vec<bool>),
CharArray(Vec<i32>),
StringArray(Vec<String>),
ByteArray(Array<i8>),
//maybe use arrays?
ShortArray(Array<i16>),
IntArray(Array<i32>),
LongArray(Array<i64>),
FloatArray(Array<f32>),
DoubleArray(Array<f64>),
BooleanArray(Array<bool>),
CharArray(Array<i32>),
StringArray(Array<String>),
ObjectArray(ClassId, Vec<ObjectRef>),
Object(Rc<RefCell<Object>>),
Class(Class),
Null,
}
impl Debug for ObjectRef {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let name = match self {
ByteArray(_) => "[B", //length for arrays
ShortArray(_) => "[S",
IntArray(_) => "[I]",
LongArray(_) => "[J",
FloatArray(_) => "[F",
DoubleArray(_) => "[D]",
BooleanArray(_) => "[Z",
CharArray(_) => "[C",
StringArray(_) => "[Ljava/lang/String]",
ObjectArray(_, _) => "[L",
Object(_) => "L",
Class(_) => "Class",
ByteArray(a) => format!("[B;{}", a.len()),
ShortArray(a) => format!("[S;{}", a.len()),
IntArray(a) => format!("[I;{}", a.len()),
LongArray(a) => format!("[J;{}", a.len()),
FloatArray(a) => format!("[F;{}", a.len()),
DoubleArray(a) => format!("[D;{}", a.len()),
BooleanArray(a) => format!("[Z;{}", a.len()),
CharArray(a) => format!("[C;{}", a.len()),
StringArray(a) => format!("[Ljava/lang/String;{}]", a.len()),
ObjectArray(_, a) => format!("[[Lx;{}]", a.len()),
Object(_) => "L".into(),
Class(_) => "Class".into(),
ObjectRef::Null => "null".into(),
};
write!(f, "{}", name)
}
@ -74,29 +128,29 @@ pub enum ArrayType {
impl ObjectRef {
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 {
match arraytype {
8 => ByteArray(vec![0; size]),
9 => ShortArray(vec![0; size]),
10 => IntArray(vec![0; size]),
11 => LongArray(vec![0; size]),
6 => FloatArray(vec![0.0; size]),
7 => DoubleArray(vec![0.0; size]),
4 => BooleanArray(vec![false; size]),
5 => CharArray(vec![0; size]),
8 => ByteArray(Array::new(0, size)),
9 => ShortArray(Array::new(0, size)),
10 => IntArray(Array::new(0, size)),
11 => LongArray(Array::new(0, size)),
6 => FloatArray(Array::new(0_f32, size)),
7 => DoubleArray(Array::new(0_f64, size)),
4 => BooleanArray(Array::new(false, size)),
5 => CharArray(Array::new(0, size)),
_ => unreachable!("impossible array type"),
}
}
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 {
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 {
let instance_data = Object::init_fields(class);
Self {
id: random(),
id: random::<u32>() >> 1,
class_id: class.id,
data: instance_data,
}

View file

@ -514,9 +514,13 @@ impl Stackframe {
let value1 = self.pop();
if_cmp(&mut self.pc, opcode, jmp_to, &value1, &value2);
}
GOTO(jmp_to) => {
self.pc += *jmp_to as usize;
GOTO(jmp_to) | JSR(jmp_to) => {
self.pc = *jmp_to as usize;
}
JSR_W(jmp_to) => {
self.pc = *jmp_to as usize;
}
INVOKEVIRTUAL(c) => {
if let Some(invocation) = get_signature_for_invoke(&constant_pool, *c) {
let mut args = Vec::with_capacity(invocation.method.num_args);
@ -816,7 +820,9 @@ impl Stackframe {
self.push(value.clone());
}
IRETURN | LRETURN | FRETURN | DRETURN | ARETURN => {
return self.pop();
let v = self.pop();
debug!("returning {:?}", v);
return v;
}
RETURN_VOID => {
return Void;
@ -867,9 +873,42 @@ impl Stackframe {
if value1 > 0 {
self.push(I64(value1 >> value2));
} 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")
}