Implemented Exception Throwing fith specific catchers

This commit is contained in:
VegOwOtenks 2024-11-13 12:14:42 +01:00
parent 796e52241d
commit fc0d11c1e1
8 changed files with 351 additions and 12 deletions

View file

@ -39,6 +39,7 @@ impl Bytecode {
0x15 => (Instruction::LoadLocalInt(self.bytes[offset+1]), 2),
0x16 => (Instruction::LoadLocalLong(self.bytes[offset+1]), 2),
0x17 => (Instruction::LoadLocalFloat(self.bytes[offset+1]), 2),
0x18 => (Instruction::LoadLocalDouble(self.bytes[offset+1]), 2),
0x19 => (Instruction::LoadLocalReference(self.bytes[offset+1]), 2),
0x1A => (Instruction::LoadLocalInt0(), 1),
0x1B => (Instruction::LoadLocalInt1(), 1),
@ -66,6 +67,7 @@ impl Bytecode {
0x36 => (Instruction::StoreLocalInt(self.bytes[offset+1]), 2),
0x37 => (Instruction::StoreLocalLong(self.bytes[offset+1]), 2),
0x38 => (Instruction::StoreLocalFloat(self.bytes[offset+1]), 2),
0x39 => (Instruction::StoreLocalDouble(self.bytes[offset+1]), 2),
0x3A => (Instruction::StoreLocalReference(self.bytes[offset+1]), 2),
0x3B => (Instruction::StoreLocalInt0(), 1),
0x3C => (Instruction::StoreLocalInt1(), 1),
@ -101,6 +103,7 @@ impl Bytecode {
0x6C => (Instruction::DivideInt(), 1),
0x6D => (Instruction::DivideLong(), 1),
0x6E => (Instruction::DivideFloat(), 1),
0x6F => (Instruction::DivideDouble(), 1),
0x70 => (Instruction::ModuloInt(), 1),
0x74 => (Instruction::NegateInt(), 1),
@ -110,6 +113,7 @@ impl Bytecode {
0x7A => (Instruction::ArithmeticShiftIntRight(), 1),
0x7B => (Instruction::ArithmeticShiftLongRight(), 1),
0x7C => (Instruction::LogicalShiftIntRight(), 1),
0x7D => (Instruction::LogicalShiftLongRight(), 1),
0x7E => (Instruction::AndInt(), 1),
0x7F => (Instruction::AndLong(), 1),
@ -119,16 +123,20 @@ impl Bytecode {
0x85 => (Instruction::ConvertIntToLong(), 1),
0x86 => (Instruction::ConvertIntToFloat(), 1),
0x87 => (Instruction::ConvertIntToDouble(), 1),
0x88 => (Instruction::ConvertLongToInt(), 1),
0x89 => (Instruction::ConvertLongToFloat(), 1),
0x8B => (Instruction::ConvertFloatToInt(), 1),
0x8D => (Instruction::ConvertFloatToDouble(), 1),
0x8E => (Instruction::ConvertDoubleToInt(), 1),
0x8F => (Instruction::ConvertDoubleToLong(), 1),
0x91 => (Instruction::ConvertIntToByte(), 1),
0x92 => (Instruction::ConvertIntToChar(), 1),
0x94 => (Instruction::CompareLong(), 1),
0x95 => (Instruction::CompareFloatL(), 1),
0x96 => (Instruction::CompareFloatG(), 1),
0x97 => (Instruction::CompareDoubleL(), 1),
0x98 => (Instruction::CompareDoubleG(), 1),
0x99 => {
let bytes = [self.bytes[offset+1], self.bytes[offset+2]];
(Instruction::BranchZero(i16::from_be_bytes(bytes)), 3)
@ -238,6 +246,7 @@ impl Bytecode {
}
0xAC => (Instruction::ReturnInt(), 1),
0xAD => (Instruction::ReturnLong(), 1),
0xAF => (Instruction::ReturnDouble(), 1),
0xB0 => (Instruction::ReturnReference(), 1),
0xB1 => (Instruction::ReturnVoid(), 1),
@ -326,6 +335,7 @@ pub enum Instruction {
LoadLocalInt(u8) = 0x15, // Load int from indexed local variable
LoadLocalLong(u8) = 0x16, // Load long from indexed local variable
LoadLocalFloat(u8) = 0x17, // Load float from indexed local variable
LoadLocalDouble(u8) = 0x18, // Load double from indexed local variable
LoadLocalReference(u8) = 0x19, // Load reference from indexed local variable
LoadLocalInt0() = 0x1A, // Load int from local variable
LoadLocalInt1() = 0x1B, // Load int from local variable
@ -354,6 +364,7 @@ pub enum Instruction {
StoreLocalInt(u8) = 0x36, // store into indexed local variable
StoreLocalLong(u8) = 0x37, // store into indexed local variable
StoreLocalFloat(u8) = 0x38, // store into indexed local variable
StoreLocalDouble(u8) = 0x39, // store into indexed local variable
StoreLocalReference(u8) = 0x3A, // store into indexed local variable
StoreLocalInt0() = 0x3B, // store int into local variable
StoreLocalInt1() = 0x3C, // store int into local variable
@ -388,6 +399,7 @@ pub enum Instruction {
DivideInt() = 0x6C, // integer division, round toward zero and more rules
DivideLong() = 0x6D, // long division
DivideFloat() = 0x6E, // float division
DivideDouble() = 0x6F, // double division
ModuloInt() = 0x70, // modulo
NegateInt() = 0x74, // arithmetic negation
@ -397,6 +409,7 @@ pub enum Instruction {
ArithmeticShiftIntRight() = 0x7A, // shift int right, preserve sign
ArithmeticShiftLongRight() = 0x7B, // shift long right, preserve sign
LogicalShiftIntRight() = 0x7C, // shift int right with zero extension
LogicalShiftLongRight() = 0x7D, // shift long right with zero extension
AndInt() = 0x7E, // bitwise and
AndLong() = 0x7F, // bitwise and
@ -406,16 +419,20 @@ pub enum Instruction {
ConvertIntToLong() = 0x85, // convert int on stack to long
ConvertIntToFloat() = 0x86, // change data type
ConvertIntToDouble() = 0x87, // change data type
ConvertLongToInt() = 0x88, // change data type
ConvertLongToFloat() = 0x89, // change data type
ConvertFloatToInt() = 0x8B, // change data type
ConvertFloatToDouble() = 0x8D, // change data type
ConvertDoubleToInt() = 0x8E, // change data type
ConvertDoubleToLong() = 0x8F, // change data type
ConvertIntToByte() = 0x91, // truncate int to 8 bits
ConvertIntToChar() = 0x92, // truncate int to 16 bits
CompareLong() = 0x94, // compare long
CompareFloatL() = 0x95, // compare float, push -1 if one is NaN
CompareFloatG() = 0x96, // compare float, push 1 if one is NaN
CompareDoubleL() = 0x97, // compare float, push -1 if one is NaN
CompareDoubleG() = 0x98, // compare float, push 1 if one is NaN
BranchZero(i16) = 0x99, // branch if value == 0
BranchNonZero(i16) = 0x9A, // branch if value != 0
BranchNegative(i16) = 0x9B, // branch if value < 0
@ -437,6 +454,7 @@ pub enum Instruction {
LookupSwitch(i32, Box<[(i32, i32)]>) = 0xAB, // jump based on switch value
ReturnInt() = 0xAC, // return integer from function
ReturnLong() = 0xAD, // return long from function
ReturnDouble() = 0xAF, // return double from function
ReturnReference() = 0xB0, // return top-ref from current function
ReturnVoid() = 0xB1, // return void from function

View file

@ -5,8 +5,10 @@ use core::str::Utf8Error;
use crate::accessmasks::*;
use crate::bytecode::Bytecode;
use crate::classstore::ClassStore;
use crate::constantpool::{ ConstantFieldRefInfo, ConstantPoolInfo, ConstantUtf8Info, ConstantInterfaceMethodRefInfo, ConstantStringInfo, ConstantMethodRefInfo, ConstantFloatInfo, ConstantClassInfo, ConstantNameAndTypeInfo, ConstantIntegerInfo, ConstantLongInfo };
use crate::constantpool::ConstantDoubleInfo;
use crate::heap_area::ObjectReference;
#[derive(Debug)]
pub enum Error {
@ -191,6 +193,15 @@ impl JavaClassFile {
return Ok(&name_entry.utf8);
}
pub fn resolve_method_index(&self, name: &str, descriptor: &str) -> Option<u16> {
for (index, method_info) in (&self.methods).into_iter().enumerate() {
if method_info.name == *name && method_info.descriptor == (&descriptor.to_string()).try_into().unwrap() {
return Some(index as u16);
}
}
return None;
}
pub fn find_method_index(&self, name: &String) -> Option<usize> {
@ -401,21 +412,22 @@ impl JavaClassFile {
}
}
pub fn is_method_bytecode_protected(&self, method: &MethodInfo, instruction_pointer: u16, exception: crate::heap_area::ObjectReference) -> bool {
pub fn is_method_bytecode_protected(&self, method: &MethodInfo, instruction_pointer: u16, exception_class_index: usize, class_store: &ClassStore) -> Result<bool, Error> {
let code_attribute = method.get_code_attribute().unwrap();
for exception_entry in &code_attribute.exception_table {
if exception_entry.start_pc <= instruction_pointer && exception_entry.end_pc > instruction_pointer {
if exception_entry.catch_type == 0 {
return true;
return Ok(true);
} else {
// Check catch-type
todo!()
let catch_type_name = self.gather_class(exception_entry.catch_type);
return Ok(class_store.are_types_compatible_0(exception_class_index, catch_type_name?));
}
}
}
false
Ok(false)
}
}

View file

@ -140,6 +140,13 @@ impl ClassStore {
return Err(Error::ClassNotFoundError(format!("Could not find class '{classname}' in classpath")));
}
pub fn are_types_compatible_0(&self, my_index: usize, other_name: &str) -> bool {
CompatibleTypesIterator::new(my_index, self)
.filter(|type_name| *type_name == other_name)
.next()
.is_some()
}
pub fn are_types_compatible(&self, my_type: &AbstractTypeDescription, other_type: &AbstractTypeDescription) -> bool {
if my_type == other_type { return true; }
if my_type.array_level != other_type.array_level { return false; }

View file

@ -280,6 +280,20 @@ impl ObjectArea {
}
}
pub fn get_object_field_count(&self, reference: ObjectReference) -> usize {
match self.get_entry(reference) {
CompartmentEntry::Object(o) => o.fields.len(),
_ => unreachable!(),
}
}
pub fn get_object_field_at(&self, reference: ObjectReference, index: usize) -> ObjectField {
match self.get_entry(reference) {
CompartmentEntry::Object(o) => o.fields[index],
_ => unreachable!(),
}
}
pub fn get_reference_class_ref(&self, reference: ObjectReference, class_store: &ClassStore) -> ObjectReference {
match self.get_entry(reference) {
CompartmentEntry::Object(o) => class_store.get_class_objectref_from_index(o.class_index),
@ -336,8 +350,8 @@ impl ObjectArea {
CompartmentEntry::ByteArray(_) => true,
CompartmentEntry::CharArray(_) => true,
CompartmentEntry::IntArray(_) => true,
CompartmentEntry::EmptyNext(_) => true,
CompartmentEntry::EmptyTail() => true,
CompartmentEntry::EmptyNext(_) => unreachable!(),
CompartmentEntry::EmptyTail() => unreachable!(),
}
}
@ -720,7 +734,7 @@ pub struct StaticField {
pub value: FieldValue,
}
#[derive(Debug)]
#[derive(Debug, Copy, Clone)]
pub struct ObjectField {
pub value: FieldValue,
}

View file

@ -58,7 +58,7 @@ impl <'i>CompatibleTypesIterator<'i> {
}
impl <'i> Iterator for CompatibleTypesIterator<'i>{
type Item = &'i String; // class index, method index, method info
type Item = &'i String;
fn next(&mut self) -> Option<Self::Item> {
let (class_index, interface_index) = match self.class_stack.pop() {

View file

@ -495,7 +495,8 @@ impl JVM {
if method.is_native() {
false
} else {
class.is_method_bytecode_protected(method, frame.instruction_pointer as u16, exception)
let exception_type_index = self.heap_area.object_area.get_object_class_index(exception);
class.is_method_bytecode_protected(method, frame.instruction_pointer as u16, exception_type_index, &self.class_store)?
}
};
@ -1023,6 +1024,40 @@ impl JVM {
}
Instruction::CompareDoubleG() => {
let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_double(0))?;
let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_double(0))?;
let comparison_result = if value_1.is_nan() || value_2.is_nan() {
1
} else if value_1 == value_2 {
0
} else if value_1 < value_2 {
-1
} else {
1
};
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(comparison_result)))?;
}
Instruction::CompareDoubleL() => {
let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_double(0))?;
let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_double(0))?;
let comparison_result = if value_1.is_nan() || value_2.is_nan() {
-1
} else if value_1 == value_2 {
0
} else if value_1 < value_2 {
-1
} else {
1
};
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(comparison_result)))?;
}
Instruction::CompareFloatG() => {
let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_float(0))?;
let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_float(0))?;
@ -1089,6 +1124,17 @@ impl JVM {
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(int_value)))?;
}
Instruction::ConvertDoubleToInt() => {
let double = wrap_stackframe_error(class, method, frame.operand_stack.pop_double(0))?;
let int_value = match double {
f64::INFINITY => i32::MAX,
f64::NEG_INFINITY => i32::MIN,
v @ _ => if v.is_nan() { 0 } else { v as i32 } ,
};
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(int_value)))?;
}
Instruction::ConvertDoubleToLong() => {
let double = wrap_stackframe_error(class, method, frame.operand_stack.pop_double(0))?;
let long = match double {
@ -1114,6 +1160,13 @@ impl JVM {
frame.operand_stack.push(StackValue::Int(char_value)).unwrap();
}
Instruction::ConvertIntToDouble() => {
let int_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
let double_value = int_value as f64;
frame.operand_stack.push_double(double_value).unwrap();
}
Instruction::ConvertIntToFloat() => {
let int_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
let float_value = int_value as f32;
@ -1142,6 +1195,14 @@ impl JVM {
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Float(float_value)))?;
}
Instruction::DivideDouble() => {
// TODO: Obey all the rules
let quotient = wrap_stackframe_error(class, method, frame.operand_stack.pop_double(0))?;
let divident = wrap_stackframe_error(class, method, frame.operand_stack.pop_double(0))?;
frame.operand_stack.push_double(divident / quotient).unwrap();
}
Instruction::DivideFloat() => {
// TODO: Obey all the rules
let quotient = wrap_stackframe_error(class, method, frame.operand_stack.pop_float(0))?;
@ -1733,6 +1794,14 @@ impl JVM {
}
}
Instruction::LoadLocalDouble(index) => {
load_local_double(class, method, frame, index as usize)?;
}
Instruction::LoadLocalDouble0() => {
load_local_double(class, method, frame, 0)?;
}
Instruction::LoadLocalFloat(index) => {
load_local_float(class, method, frame, index as usize)?;
}
@ -1813,6 +1882,16 @@ impl JVM {
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(i_result)))?;
}
Instruction::LogicalShiftLongRight() => {
let shift = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))? as u8 & 0b00111111;
let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
let uint = u64::from_ne_bytes(int.to_ne_bytes());
let u_result = uint >> shift;
let i_result = i64::from_ne_bytes(u_result.to_ne_bytes());
wrap_stackframe_error(class, method, frame.operand_stack.push_long(i_result))?;
}
Instruction::LookupSwitch(default_offset, pairs) => {
let key = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
let jump_offset = match pairs.binary_search_by(|(match_key, _offset)| match_key.cmp(&key)) {
@ -2156,6 +2235,17 @@ impl JVM {
self.heap_area.static_area.set(target_class_name, target_field_name, set_value)?;
}
Instruction::ReturnDouble() => {
match (method.descriptor.return_type.array_level, &method.descriptor.return_type.kind) {
(0, AbstractTypeKind::Double()) => (),
_ => return Err(Error::OpcodeError(format!("Found opcode '{:?}' on method returning '{:?}'", instruction, method.descriptor.return_type)))
}
let double = wrap_stackframe_error(class, method, frame.operand_stack.pop_double(0))?;
return Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Double(double)));
}
Instruction::ReturnInt() => {
match (method.descriptor.return_type.array_level, &method.descriptor.return_type.kind) {
(_, AbstractTypeKind::Byte() | AbstractTypeKind::Boolean()| AbstractTypeKind::Int() | AbstractTypeKind::Char() | AbstractTypeKind::Short()) => (),
@ -2265,6 +2355,12 @@ impl JVM {
wrap_stackframe_error(class, method, frame.operand_stack.push_long(value_1 - value_2))?;
}
Instruction::StoreLocalDouble(index) => {
let double = wrap_stackframe_error(class, method, frame.operand_stack.pop_double(0))?;
wrap_stackframe_error(class, method, frame.store_local_double(index as u16, double))?;
}
Instruction::StoreLocalFloat(index) => {
let float = wrap_stackframe_error(class, method, frame.operand_stack.pop_float(0))?;
@ -2420,6 +2516,14 @@ fn load_local_reference(class: &JavaClassFile, method: &MethodInfo, frame: &mut
Ok(())
}
fn load_local_double(class: &JavaClassFile, method: &MethodInfo, frame: &mut StackFrame, index: usize) -> Result<(), Error> {
let loaded_value = wrap_stackframe_error(class, method, frame.load_local_double(index as u16))?;
wrap_stackframe_error(class, method, frame.operand_stack.push_double(loaded_value))?;
Ok(())
}
fn load_local_float(class: &JavaClassFile, method: &MethodInfo, frame: &mut StackFrame, index: usize) -> Result<(), Error> {
let loaded_value = wrap_stackframe_error(class, method, frame.load_local_float(index as u16))?;

View file

@ -44,6 +44,24 @@ impl EntryPoint {
struct JavaLangClass {}
impl JavaLangClass {
fn is_array(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
let frame = {
let frame_index = jvm.stack_frames.len() - 1;
&mut jvm.stack_frames[frame_index]
};
let this = frame.load_local_reference(0).unwrap();
let class_class_index = jvm.heap_area.object_area.get_object_class_index(this);
let component_type = jvm.heap_area.object_area.get_object_field(
this,
"componentType",
class_class_index,
&jvm.class_store,
)?;
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Boolean(component_type.expect_reference() == ObjectReference::NULL)))
}
pub fn get_primitive_class(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
let frame = {
let frame_index = jvm.stack_frames.len() - 1;
@ -330,6 +348,81 @@ impl JavaLangDouble {
}
}
struct JavaLangObject {}
impl JavaLangObject {
fn get_class(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
let frame = {
let frame_index = jvm.stack_frames.len() - 1;
&mut jvm.stack_frames[frame_index]
};
let this = frame.load_local_reference(0).unwrap();
let class_reference = jvm.heap_area.object_area.get_reference_class_ref(this, &jvm.class_store);
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Reference(class_reference)))
}
fn hashcode(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
let frame = {
let frame_index = jvm.stack_frames.len() - 1;
&mut jvm.stack_frames[frame_index]
};
if frame.operand_stack.capacity() == 1 {
frame.operand_stack.grow(2);
frame.operand_stack.push(StackValue::Int(91)).unwrap();
} else {
let new_hashcode_part = frame.operand_stack.pop_int(0).unwrap();
let old_hashcode_part = frame.operand_stack.pop_int(0).unwrap();
let combined_hashcode = old_hashcode_part.wrapping_mul(37).wrapping_add(new_hashcode_part);
frame.operand_stack.push(StackValue::Int(combined_hashcode)).unwrap();
}
let this = frame.load_local_reference(0).unwrap();
let this_pointer = &this as *const _;
return Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Int(this_pointer as i32)))
//let this_field_count = jvm.heap_area.object_area.get_object_field_count(this);
//Ok(if this_field_count > frame.instruction_pointer as usize {
// let current_field = jvm.heap_area.object_area.get_object_field_at(this, frame.instruction_pointer as usize);
// let caller_frame = match current_field.value {
// FieldValue::Boolean(b) => {
// // TODO: Maybe load the class
// let (boolean_class_file, boolean_class_index) = jvm.class_store.get_class(&String::from("java/lang/Boolean")).unwrap();
// StackFrame::new(
// boolean_class_file,
// boolean_class_index,
// boolean_class_file.resolve_method_index("hashCode", "(Z)I").unwrap(),
// &[StackValue::Boolean(b)]
// )
// },
// FieldValue::Byte(_) => todo!(),
// FieldValue::Char(_) => todo!(),
// FieldValue::Short(_) => todo!(),
// FieldValue::Int(_) => todo!(),
// FieldValue::Float(_) => todo!(),
// FieldValue::Reference(r) => {
// if jvm.heap_area.object_area.is_array_reference(r) {
// } else {
// }
// },
// FieldValue::Double(_) => todo!(),
// FieldValue::Long(_) => todo!(),
// };
// JVMCallbackOperation::PushFrame(caller_frame)
//} else {
// let hashcode = frame.operand_stack.pop_int(0).unwrap();
// JVMCallbackOperation::ReturnFrame(FieldValue::Int(hashcode))
//})
}
}
struct JavaLangRuntime {}
impl JavaLangRuntime {
@ -1136,7 +1229,7 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
argument_types: Box::new([]),
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Boolean()},
},
todo_call
JavaLangClass::is_array
),
(
@ -1299,7 +1392,7 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
argument_types: Box::new([]),
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname(String::from("java/lang/Class"))},
},
todo_call
JavaLangObject::get_class
),
(
@ -1309,7 +1402,7 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
argument_types: Box::new([]),
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Int()},
},
todo_call
JavaLangObject::hashcode
),
(
@ -3435,6 +3528,75 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
},
todo_call
),
(
"java/lang/Module",
"defineModule0",
MethodDescriptor {
argument_types: Box::new([
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Module".to_string())},
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Boolean()},
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/String".to_string())},
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/String".to_string())},
AbstractTypeDescription { array_level: 1, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
]),
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void() },
},
todo_call
),
(
"java/lang/Module",
"addReads0",
MethodDescriptor {
argument_types: Box::new([
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Module".to_string())},
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Module".to_string())},
]),
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void() },
},
todo_call
),
(
"java/lang/Module",
"addExports0",
MethodDescriptor {
argument_types: Box::new([
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Module".to_string())},
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/String".to_string())},
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Module".to_string())},
]),
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void() },
},
todo_call
),
(
"java/lang/Module",
"addExportsToAll0",
MethodDescriptor {
argument_types: Box::new([
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Module".to_string())},
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/String".to_string())},
]),
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void() },
},
todo_call
),
(
"java/lang/Module",
"addExportsToAllUnnamed0",
MethodDescriptor {
argument_types: Box::new([
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Module".to_string())},
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/String".to_string())},
]),
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void() },
},
todo_call
),
];
for (classname, methodname, methoddescriptor, binding) in native_mappings {

View file

@ -47,6 +47,14 @@ impl OperandStack {
}
}
pub fn capacity(&self) -> usize {
self.stack.len()
}
pub fn grow(&mut self, new_size: usize) {
self.stack = vec![StackValue::Empty(); new_size].into_boxed_slice()
}
pub fn clear(&mut self) -> () {
self.depth = 0
}
@ -408,6 +416,20 @@ impl StackFrame {
}
}
pub fn store_local_double(&mut self, index: u16, double: f64) -> Result<(), Error> {
let field0 = self.locals.get(index as usize);
let field1 = self.locals.get((index + 1) as usize);
match (field0, field1) {
(Some(_), Some(_)) => {
self.locals[index as usize] = StackValue::Double0(double);
self.locals[(index + 1) as usize] = StackValue::Double1();
Ok(())
},
_ => Err(Error::LocalError(format!("Tried to set local at indices {} and {} when max_locals is {}.", index, index+1, self.locals.len())))
}
}
pub fn load_local_int(&self, index: u16) -> Result<i32, Error> {
let local = self.locals[index as usize];
match local {