More error checking in invokestatic
This commit is contained in:
parent
2042007242
commit
fb29955f7d
3 changed files with 41 additions and 2 deletions
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
29
src/jvm.rs
29
src/jvm.rs
|
@ -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)))
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue