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

@ -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))?;