More error checking in invokestatic

This commit is contained in:
VegOwOtenks 2024-09-02 12:02:19 +02:00
parent 2042007242
commit fb29955f7d
3 changed files with 41 additions and 2 deletions

View file

@ -1,4 +1,5 @@
use core::fmt::{Formatter, Debug}; use core::fmt::{Formatter, Debug};
use core::ops::BitAnd;
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
#[repr(u16)] #[repr(u16)]
@ -36,10 +37,18 @@ impl MethodAccessFlag {
} }
} }
#[derive(Copy, Clone)]
pub struct MethodAccessFlagMask { pub struct MethodAccessFlagMask {
pub mask: u16, pub mask: u16,
} }
impl BitAnd<MethodAccessFlag> for MethodAccessFlagMask {
type Output=bool;
fn bitand(self, f: MethodAccessFlag) -> bool {
return (self.mask & f.discriminant()) != 0;
}
}
impl Debug for MethodAccessFlagMask { impl Debug for MethodAccessFlagMask {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
let mut flag_vec = Vec::new(); let mut flag_vec = Vec::new();

View file

@ -130,6 +130,11 @@ impl ClassStore {
return Some(was_init); return Some(was_init);
} }
pub fn set_init(&mut self, class_idx: usize, was_init: bool) {
let pair = self.classes.get_mut(class_idx).unwrap();
pair.0 = was_init;
}
} }

View file

@ -17,6 +17,7 @@ pub enum Error {
ClassFileError(classfile::Error), ClassFileError(classfile::Error),
BadNameError(String), BadNameError(String),
RunTimeError(String), RunTimeError(String),
OpcodeError(String),
} }
impl From<classfile::Error> for Error { impl From<classfile::Error> for Error {
@ -151,6 +152,7 @@ impl JVM {
// TODO: ConstantValue Attributes (final) // TODO: ConstantValue Attributes (final)
// TODO: Static Stuff // TODO: Static Stuff
self.class_store.set_init(class_idx, true);
} }
fn prepare_invoke_static(&mut self, class_index: usize, method_name: &String, arguments: &[Value]) -> Result<(), Error> { fn prepare_invoke_static(&mut self, class_index: usize, method_name: &String, arguments: &[Value]) -> Result<(), Error> {
@ -210,6 +212,17 @@ impl JVM {
// TODO: Throw exception on fail // TODO: Throw exception on fail
let callee_method_info = &callee_class_file.methods[callee_method_index]; let callee_method_info = &callee_class_file.methods[callee_method_index];
if ! (callee_method_info.access_flags & MethodAccessFlag::Static) {
// TODO: Throw IncompatibleClassChangeError
return Err(Error::RunTimeError(format!(
"Invoked method '{}' in class '{}' does not have Access::Static (from invokestatic from '{}' in class '{}')",
method.name,
class.get_classname().unwrap(),
supplied_method_name,
supplied_class_name,
)));
}
let supplied_descriptor: MethodDescriptor = supplied_descriptor_string.try_into()?; let supplied_descriptor: MethodDescriptor = supplied_descriptor_string.try_into()?;
// TODO: Throw exception on fail // TODO: Throw exception on fail
@ -225,6 +238,7 @@ impl JVM {
} }
let arguments = Vec::new(); let arguments = Vec::new();
// TODO: Pass arguments
let new_frame = StackFrame::new( let new_frame = StackFrame::new(
callee_class_file, callee_class_file,
@ -233,11 +247,22 @@ impl JVM {
&arguments.into_boxed_slice(), &arguments.into_boxed_slice(),
); );
//println!("{} {} {}", class_name, method_name, method_descriptor);
return Ok(JVMCallbackOperation::PushFrame(new_frame)); return Ok(JVMCallbackOperation::PushFrame(new_frame));
}, },
Instruction::ReturnVoid() => {
let expected_type = AbstractTypeDescription {
array_level: 0,
kind: AbstractTypeKind::Void(),
};
if method.descriptor.return_type != expected_type {
return Err(Error::OpcodeError(format!("Found opcode '{:?}' on method returning '{:?}'", instruction, method.descriptor.return_type)))
}
return Ok(JVMCallbackOperation::PopFrame());
},
_ => { _ => {
return Err(Error::RunTimeError(format!("Opcode not implemented yet: {:?}", instruction))) return Err(Error::RunTimeError(format!("Opcode not implemented yet: {:?}", instruction)))
}, },