Implemented Exception Throwing fith specific catchers
This commit is contained in:
parent
796e52241d
commit
fc0d11c1e1
8 changed files with 351 additions and 12 deletions
106
src/jvm.rs
106
src/jvm.rs
|
@ -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))?;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue