fixed segv

This commit is contained in:
Shautvast 2023-10-17 14:34:34 +02:00
parent 7219893978
commit 3ce9ce10b4
5 changed files with 106 additions and 40 deletions

View file

@ -28,7 +28,8 @@ pub fn get_class(vm: &mut Vm, calling_class_name: Option<&str>, class_name: &str
// not pretty...sorry // not pretty...sorry
if let Some(calling_class_name) = calling_class_name { 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 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 panic!();
// return Ok(CLASSDEFS.get(class_name.into()).unwrap().clone()); // in that case the class is guaranteed to be here
} }
} }
@ -42,6 +43,8 @@ pub fn get_class(vm: &mut Vm, calling_class_name: Option<&str>, class_name: &str
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, Some(class_name), &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);
} else {
unreachable!()
} }
} }
@ -57,11 +60,16 @@ pub fn get_class(vm: &mut Vm, calling_class_name: Option<&str>, class_name: &str
// the problem is pretty fundamental: method (clinit) should be called before the class is returned, // 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! // 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>) // 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") { //update: this is probably not needed anymore because of the check in PUTSTATIC
//somehow this clone needs to be there before clinit is called, even though the newclass ref remains in scope
let clone = new_class.clone();
if new_class.clone().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();
} }
Ok(new_class.clone()) Ok(clone)
} }
} }
@ -194,7 +202,6 @@ impl Class {
); //name => (type,index) ); //name => (type,index)
*object_field_map_index += 1; *object_field_map_index += 1;
} }
} }
(this_fields, static_fields) (this_fields, static_fields)
} }
@ -540,7 +547,7 @@ pub enum Value {
BOOL(bool), BOOL(bool),
CHAR(char), CHAR(char),
Ref(Arc<UnsafeCell<ObjectRef>>), Ref(Arc<UnsafeCell<ObjectRef>>),
Utf8(String) Utf8(String),
} }
impl Value { impl Value {

View file

@ -1,12 +1,12 @@
use std::cell::{RefCell, UnsafeCell}; use std::cell::{RefCell, UnsafeCell};
use std::fmt; use std::fmt;
use std::fmt::{Debug, Formatter};
use std::sync::Arc; use std::sync::Arc;
use crate::class::{Class, Type, UnsafeValue, Value}; use crate::class::{Class, Type, UnsafeValue, Value};
use crate::heap::ObjectRef::{IntArray, ObjectArray}; use crate::heap::ObjectRef::{IntArray, ObjectArray};
// can contain object or array // can contain object or array
#[derive(Debug)]
pub enum ObjectRef { pub enum ObjectRef {
ByteArray(Vec<i8>), ByteArray(Vec<i8>),
ShortArray(Vec<i16>), ShortArray(Vec<i16>),
@ -30,6 +30,23 @@ impl ObjectRef {
} }
} }
impl Debug for ObjectRef{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
ObjectRef::BooleanArray(d) => write!(f, "[Z;{}]", d.len()),
ObjectRef::ByteArray(d) => write!(f, "[B;{}]", d.len()),
ObjectRef::CharArray(d) => write!(f, "[C;{}]", d.len()),
ObjectRef::DoubleArray(d) => write!(f, "[D;{}]", d.len()),
ObjectRef::FloatArray(d) => write!(f, "[F;{}]", d.len()),
ObjectRef::IntArray(d) => write!(f, "[I;{}]", d.len()),
ObjectRef::LongArray(d) => write!(f, "[J;{}]", d.len()),
ObjectRef::ObjectArray(t, d) => write!(f,"[L{};{}]", t.borrow().name,d.len()),
ObjectRef::ShortArray( d) => write!(f, "[S;{}]", d.len()),
ObjectRef::Object( r) => write!(f,"{}{{ {:?} }}", r.class.borrow().name, r.data),
}
}
}
// trying to implement efficient object instance storage // trying to implement efficient object instance storage
pub struct Object { pub struct Object {
// locked: bool, // locked: bool,

View file

@ -15,7 +15,7 @@ use crate::native::invoke_native;
use crate::opcodes::*; use crate::opcodes::*;
#[derive(Debug)] #[derive(Debug)]
struct StackFrame { pub(crate) struct StackFrame {
at: String, at: String,
data: Vec<UnsafeValue>, data: Vec<UnsafeValue>,
} }
@ -50,7 +50,7 @@ impl StackFrame {
pub struct Vm { pub struct Vm {
pub classpath: Vec<String>, pub classpath: Vec<String>,
heap: Heap, heap: Heap,
stackframes: Vec<StackFrame>, pub(crate) stackframes: Vec<StackFrame>,
} }
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
@ -133,6 +133,7 @@ impl Vm {
self.current_frame().push(Value::I32(0)); self.current_frame().push(Value::I32(0));
} }
ICONST_1 => { ICONST_1 => {
println!("ICONST_1");
self.current_frame().push(Value::I32(1)); self.current_frame().push(Value::I32(1));
} }
ICONST_2 => { ICONST_2 => {
@ -218,7 +219,7 @@ impl Vm {
self.current_frame().push(Value::F32(*f)); self.current_frame().push(Value::F32(*f));
} }
_ => { _ => {
panic!("unexpected") unreachable!()
} }
} }
} }
@ -233,7 +234,7 @@ impl Vm {
self.current_frame().push(Value::I64(*l)); self.current_frame().push(Value::I64(*l));
} }
_ => { _ => {
panic!("unexpected") unreachable!()
} }
} }
} }
@ -342,6 +343,16 @@ impl Vm {
let value = self.current_frame().pop()?; let value = self.current_frame().pop()?;
borrow.static_data[*val_index] = Some(value); borrow.static_data[*val_index] = Some(value);
} }
unsafe {
for v in &borrow.static_data {
let v = &*v.as_ref().unwrap().get();
if let Value::Ref(vv) = v {
println!("{:?}", &*vv.get())
} else {
println!("{:?}", *v);
}
}
}
} }
GETFIELD => unsafe { GETFIELD => unsafe {
let borrow = this_class.borrow(); let borrow = this_class.borrow();
@ -359,7 +370,11 @@ impl Vm {
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_arc(Arc::clone(value)); self.current_frame().push_arc(Arc::clone(value));
} else {
unreachable!()
} }
} else {
unreachable!()
} }
}, },
PUTFIELD => unsafe { PUTFIELD => unsafe {
@ -379,6 +394,8 @@ impl Vm {
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);
} }
} else {
unreachable!()
} }
}, },
INVOKEVIRTUAL | INVOKESPECIAL => unsafe { INVOKEVIRTUAL | INVOKESPECIAL => unsafe {
@ -406,6 +423,8 @@ impl Vm {
} }
} }
println!("stack {} at {}", self.current_frame().len(), self.current_frame().at) println!("stack {} at {}", self.current_frame().len(), self.current_frame().at)
} else {
unreachable!()
} }
}, },
INVOKESTATIC => unsafe { INVOKESTATIC => unsafe {
@ -429,6 +448,8 @@ impl Vm {
self.current_frame().push_arc(returnvalue.clone()); self.current_frame().push_arc(returnvalue.clone());
} }
} }
} else {
unreachable!()
} }
}, },
NEW => { NEW => {
@ -463,7 +484,6 @@ impl Vm {
} else { } else {
panic!(); panic!();
} }
} }
//TODO implement all opcodes //TODO implement all opcodes
@ -478,43 +498,45 @@ impl Vm {
} }
unsafe fn array_load(&mut self) -> Result<(), Error> { unsafe fn array_load(&mut self) -> Result<(), Error> {
if let Value::I32(index) = &*self.current_frame().pop()?.get() { let value = self.current_frame().pop()?;
if let Value::I32(index) = &*value.get() {
let index = *index as usize; let index = *index as usize;
let arrayref = &*self.current_frame().pop()?.get(); let arrayref = self.current_frame().pop()?;
if let Value::Null = arrayref { if let Value::Null = &*arrayref.get() {
return Err(anyhow!("NullpointerException")); return Err(anyhow!("NullpointerException"));
} }
if let Value::Ref(ref objectref) = arrayref { if let Value::Ref(objectref) = &*arrayref.get() {
match &*objectref.get() { match &*objectref.get() {
ObjectRef::ByteArray(ref array) => { ObjectRef::ByteArray(array) => {
self.current_frame().push(Value::I32(array[index] as i32)); self.current_frame().push(Value::I32(array[index] as i32));
} }
ObjectRef::ShortArray(ref array) => { ObjectRef::ShortArray(array) => {
self.current_frame().push(Value::I32(array[index] as i32)); self.current_frame().push(Value::I32(array[index] as i32));
} }
ObjectRef::IntArray(ref array) => { ObjectRef::IntArray(array) => {
self.current_frame().push(Value::I32(array[index])); self.current_frame().push(Value::I32(array[index]));
} }
ObjectRef::BooleanArray(ref array) => { ObjectRef::BooleanArray(array) => {
self.current_frame().push(Value::I32(array[index] as i32)); self.current_frame().push(Value::I32(array[index] as i32));
} }
ObjectRef::CharArray(ref array) => { ObjectRef::CharArray(array) => {
self.current_frame().push(Value::CHAR(array[index])); self.current_frame().push(Value::CHAR(array[index]));
} }
ObjectRef::LongArray(ref array) => { ObjectRef::LongArray(array) => {
self.current_frame().push(Value::I64(array[index])); self.current_frame().push(Value::I64(array[index]));
} }
ObjectRef::FloatArray(ref array) => { ObjectRef::FloatArray(array) => {
self.current_frame().push(Value::F32(array[index])); self.current_frame().push(Value::F32(array[index]));
} }
ObjectRef::DoubleArray(ref array) => { ObjectRef::DoubleArray(array) => {
self.current_frame().push(Value::F64(array[index])); self.current_frame().push(Value::F64(array[index]));
} }
ObjectRef::ObjectArray(_arraytype, ref data) => { ObjectRef::ObjectArray(_arraytype, data) => {
self.current_frame() self.current_frame()
.push(Value::Ref(data[index].clone())); .push(Value::Ref(data[index].clone()));
} }
ObjectRef::Object(_) => {} //throw error? ObjectRef::Object(_) => { panic!("should be array") } //throw error?
} }
} }
} }
@ -523,66 +545,86 @@ 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 = &mut *self.current_frame().pop()?.get(); let index = &*self.current_frame().pop()?;
let mut arrayref = &mut *self.current_frame().pop()?.get(); let mut arrayref = &mut self.current_frame().pop()?;
if let Value::Null = arrayref { if let Value::Null = &*arrayref.get() {
return Err(anyhow!("NullpointerException")); return Err(anyhow!("NullpointerException"));
} }
if let Value::I32(index) = index { if let Value::I32(index) = &*index.get() {
if let Value::Ref(ref mut objectref) = arrayref { if let Value::Ref(ref mut objectref) = &mut *arrayref.get() {
match &mut *objectref.get() { match &mut *objectref.get() {
ObjectRef::ByteArray(ref mut array) => { ObjectRef::ByteArray(ref mut array) => {
if let Value::I32(value) = *value.get() { if let Value::I32(value) = *value.get() {
// is i32 correct? // is i32 correct?
array[*index as usize] = value as i8; array[*index as usize] = value as i8;
} else {
unreachable!()
} }
} }
ObjectRef::ShortArray(ref mut array) => { ObjectRef::ShortArray(ref mut array) => {
if let Value::I32(value) = *value.get() { if let Value::I32(value) = *value.get() {
// is i32 correct? // is i32 correct?
array[*index as usize] = value as i16; array[*index as usize] = value as i16;
} else {
unreachable!()
} }
} }
ObjectRef::IntArray(ref mut array) => { ObjectRef::IntArray(ref mut array) => {
if let Value::I32(value) = *value.get() { if let Value::I32(value) = *value.get() {
array[*index as usize] = value; array[*index as usize] = value;
} else {
unreachable!()
} }
} }
ObjectRef::BooleanArray(ref mut array) => { ObjectRef::BooleanArray(ref mut array) => {
if let Value::I32(value) = *value.get() { if let Value::I32(value) = *value.get() {
array[*index as usize] = value > 0; array[*index as usize] = value > 0;
} else {
unreachable!()
} }
} }
ObjectRef::CharArray(ref mut array) => { ObjectRef::CharArray(ref mut array) => {
if let Value::I32(value) = *value.get() { if let Value::I32(value) = *value.get() {
array[*index as usize] = char::from_u32_unchecked(value as u32); array[*index as usize] = char::from_u32_unchecked(value as u32);
} else {
unreachable!()
} }
} }
ObjectRef::LongArray(ref mut array) => { ObjectRef::LongArray(ref mut array) => {
if let Value::I64(value) = *value.get() { if let Value::I64(value) = *value.get() {
array[*index as usize] = value; array[*index as usize] = value;
} else {
unreachable!()
} }
} }
ObjectRef::FloatArray(ref mut array) => { ObjectRef::FloatArray(ref mut array) => {
if let Value::F32(value) = *value.get() { if let Value::F32(value) = *value.get() {
array[*index as usize] = value array[*index as usize] = value
} else {
unreachable!()
} }
} }
ObjectRef::DoubleArray(ref mut array) => { ObjectRef::DoubleArray(ref mut array) => {
if let Value::F64(value) = *value.get() { if let Value::F64(value) = *value.get() {
array[*index as usize] = value array[*index as usize] = value
} else {
unreachable!()
} }
} }
ObjectRef::ObjectArray(arraytype, ref mut array) => { ObjectRef::ObjectArray(arraytype, ref mut array) => {
if let Value::Ref(ref value) = *value.get() { if let Value::Ref(ref value) = *value.get() {
array[*index as usize] = value.clone(); array[*index as usize] = value.clone();
} else {
unreachable!()
} }
} }
ObjectRef::Object(_) => {} //throw error? ObjectRef::Object(_) => {} //throw error?
} }
} }
} else {
unreachable!()
} }
Ok(()) Ok(())
} }

Binary file not shown.

View file

@ -1,14 +1,14 @@
public class Main { public class Main {
final static int a; final static String a;
static{ static{
a=1; a="";
} }
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(a);
} }
} }