WIP virtual methods

This commit is contained in:
Shautvast 2023-10-22 15:54:37 +02:00
parent ff5c41fc8d
commit c47b7e9f50
3 changed files with 79 additions and 7 deletions

View file

@ -63,7 +63,7 @@ pub fn get_class(
let clinit = clone2.borrow().methods.contains_key("<clinit>()V"); let clinit = clone2.borrow().methods.contains_key("<clinit>()V");
let name = &clone2.borrow().name.to_owned(); let name = &clone2.borrow().name.to_owned();
if clinit { if clinit {
vm.execute(name, "<clinit>()V", vec![]).unwrap(); vm.execute_special(name, "<clinit>()V", vec![]).unwrap();
} }
} }
Ok(clone) Ok(clone)

View file

@ -93,10 +93,55 @@ impl Vm {
class_name: &str, class_name: &str,
method_name: &str, method_name: &str,
args: Vec<UnsafeValue>, args: Vec<UnsafeValue>,
) -> Result<UnsafeValue, Error> {
let class = get_class(self, class_name)?;
// let method = class.clone().borrow().get_method(method_name)?.clone();
let classb = class.borrow();
let method = Self::get_method(&classb, method_name, &args).unwrap();
// let mut superclass = class.super_class.as_ref();
// while let Some(s) = superclass {
// if let Ok(m) = s.borrow().get_method(method_name) {
// return m;
// }
// superclass = s.borrow().super_class.as_ref();
// }
self.execute_class(class.clone(), method.clone(), args)
}
pub fn execute_special(
&mut self,
class_name: &str,
method_name: &str,
args: Vec<UnsafeValue>,
) -> Result<UnsafeValue, Error> {
let class = get_class(self, class_name)?;
let method = class.clone().borrow().get_method(method_name)?.clone();
self.execute_class(class.clone(), method.clone(), args)
}
fn get_method<'a>(class: &'a std::cell::Ref<Class>, method_name: &str, args: &Vec<UnsafeValue>) -> Option<&'a Rc<Method>> {
unsafe {
if let Ref(this) = &*args[0].get() {
if let ObjectRef::Object(this) = &*this.get() {
if let Ok(m) = class.get_method(method_name) {
return Some(m);
}
}
}
}
None
}
pub fn execute_static(
&mut self,
class_name: &str,
method_name: &str,
args: Vec<UnsafeValue>,
) -> Result<UnsafeValue, Error> { ) -> Result<UnsafeValue, Error> {
let class = get_class(self, class_name)?; let class = get_class(self, class_name)?;
let method = class.clone().borrow().get_method(method_name)?.clone(); let method = class.clone().borrow().get_method(method_name)?.clone();
//TODO implement dynamic dispatch -> get method from instance
self.execute_class(class, method, args) self.execute_class(class, method, args)
} }
@ -211,7 +256,7 @@ impl Vm {
.as_bytes() .as_bytes()
.into(); .into();
self.execute( self.execute_special(
"java/lang/String", "java/lang/String",
"<init>([B)V", "<init>([B)V",
vec![ vec![
@ -451,7 +496,34 @@ impl Vm {
unreachable!() unreachable!()
} }
}, },
INVOKEVIRTUAL | INVOKESPECIAL => unsafe { INVOKESPECIAL => unsafe {
// TODO differentiate these opcodes
let cp_index = read_u16(&code.opcodes, pc);
if let Some(invocation) =
get_signature_for_invoke(&method.constant_pool, cp_index)
{
let mut args = Vec::with_capacity(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()?);
let return_value = self.execute_special(
&invocation.class_name,
&invocation.method.name,
args,
)?;
match *return_value.get() {
Void => {}
_ => {
self.current_frame().push_ref(return_value.clone());
}
}
// println!("stack {} at {}", self.current_frame().len(), self.current_frame().at)
} else {
unreachable!()
}
},
INVOKEVIRTUAL => unsafe {
// TODO differentiate these opcodes // TODO differentiate these opcodes
let cp_index = read_u16(&code.opcodes, pc); let cp_index = read_u16(&code.opcodes, pc);
if let Some(invocation) = if let Some(invocation) =
@ -487,7 +559,7 @@ impl Vm {
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, copy(self.current_frame().pop()?));
} }
let returnvalue = self.execute( let returnvalue = self.execute_static(
&invocation.class_name, &invocation.class_name,
&invocation.method.name, &invocation.method.name,
args, args,

View file

@ -21,7 +21,7 @@ mod test {
fn consts() { fn consts() {
let mut vm = Vm::new("tests"); let mut vm = Vm::new("tests");
let ret = vm let ret = vm
.execute("testclasses.Const", "hello()Ljava/lang/String;", vec![]) .execute_static("testclasses.Const", "hello()Ljava/lang/String;", vec![])
.unwrap(); .unwrap();
unsafe { unsafe {
if let Value::Ref(s) = &*ret.get() { if let Value::Ref(s) = &*ret.get() {