I can't even describe my disappointment at interfaces

This commit is contained in:
vegowotenks 2024-09-11 00:02:48 +02:00
parent d7d159d115
commit 9190d3f7e7
4 changed files with 116 additions and 15 deletions

View file

@ -841,16 +841,22 @@ impl JVM {
Instruction::CheckCast(classref_index) => {
// TODO: Class loading checks
let class_name = class.gather_class(classref_index)?;
let class_index = self.class_store.class_idx_from_name(class_name).unwrap();
let class_object_ref = self.class_store.get_class_objectref_from_index(class_index);
let native_class_description = self.heap_area.object_area.get_class_ref_native_class_name(class_object_ref, &self.class_store);
let class_description = AbstractTypeDescription::parse_full(native_class_description)?;
let object = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?;
let native_class_name = self.heap_area.object_area.get_reference_native_class_name(object, &self.class_store);
let object_description = AbstractTypeDescription::parse_full(native_class_name)?;
if ! self.class_store.are_types_compatible(&object_description, &class_description) {
let instruction_result = if class_name == native_class_name {
1
} else {
let class_index = self.class_store.class_idx_from_name(class_name).unwrap();
let class_object_ref = self.class_store.get_class_objectref_from_index(class_index);
let native_class_description = self.heap_area.object_area.get_class_ref_native_class_name(class_object_ref, &self.class_store);
let class_description = AbstractTypeDescription::parse_full(native_class_description)?;
let object_description = AbstractTypeDescription::parse_full(native_class_name)?;
if self.class_store.are_types_compatible(&object_description, &class_description) { 1 } else { 0 }
};
if instruction_result == 0 {
// TODO: Throw Exception
return Err(Error::RunTimeError(format!("Trying to cast an object of type {native_class_name} to {class_name}")))
}
@ -979,20 +985,81 @@ impl JVM {
Instruction::InstanceOf(classref_index) => {
// TODO: Class loading checks
let class_name = class.gather_class(classref_index)?;
let class_index = self.class_store.class_idx_from_name(class_name).unwrap();
let class_object_ref = self.class_store.get_class_objectref_from_index(class_index);
let native_class_description = self.heap_area.object_area.get_class_ref_native_class_name(class_object_ref, &self.class_store);
let class_description = AbstractTypeDescription::parse_full(native_class_description)?;
let object = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?;
let native_class_name = self.heap_area.object_area.get_reference_native_class_name(object, &self.class_store);
let object_description = AbstractTypeDescription::parse_full(native_class_name)?;
let instruction_result = if self.class_store.are_types_compatible(&object_description, &class_description) { 1 } else { 0 };
let instruction_result = if class_name == native_class_name {
1
} else {
let class_index = self.class_store.class_idx_from_name(class_name).unwrap();
let class_object_ref = self.class_store.get_class_objectref_from_index(class_index);
let native_class_description = self.heap_area.object_area.get_class_ref_native_class_name(class_object_ref, &self.class_store);
let class_description = AbstractTypeDescription::parse_full(native_class_description)?;
let object_description = AbstractTypeDescription::parse_full(native_class_name)?;
if self.class_store.are_types_compatible(&object_description, &class_description) { 1 } else { 0 }
};
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(instruction_result)))?;
}
Instruction::InvokeInterface(methodref_index) => {
let (supplied_interface_name, supplied_method_name, supplied_descriptor_string) = class.gather_interfacemethodref(methodref_index)?;
if ! self.class_store.have_class(supplied_interface_name) {
frame.instruction_pointer -= offset as u32;
return Ok(JVMCallbackOperation::LoadClass(supplied_interface_name.to_string()));
}
if ! self.class_store.was_init(supplied_interface_name).unwrap() {
frame.instruction_pointer -= offset as u32;
return Ok(JVMCallbackOperation::InitClass(supplied_interface_name.to_string()));
}
let target_interface_class_index = self.class_store.class_idx_from_name(supplied_interface_name).unwrap();
let parsed_expected_descriptor: MethodDescriptor = MethodDescriptor::try_from(supplied_descriptor_string)?;
let (class_index, method_index, method_info) = match ClassMethodIterator::new(target_interface_class_index, &self.class_store)
.filter(|(_cid, _mid, minfo)| minfo.name == *supplied_method_name)
.filter(|(_cid, _mid, minfo)| minfo.descriptor == parsed_expected_descriptor)
.next() {
Some(m) => m,
None => {
// TODO: Throw exception
return Err(Error::RunTimeError(format!("InvokeInterface: Failed to find requested method '{}' with descriptor '{}' in the class '{}'", supplied_method_name, supplied_descriptor_string, supplied_interface_name)));
}
};
let mut arguments = VecDeque::new();
fill_arguments(class, method, &mut arguments, &method_info.descriptor.argument_types, &mut frame.operand_stack)?;
let this_object = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?;
arguments.push_front(StackValue::Reference(this_object));
let object_class_index = self.heap_area.object_area.get_object_class_index(this_object);
let object_class_file = self.class_store.class_file_from_idx(object_class_index).unwrap();
let object_class_name = object_class_file.get_classname().unwrap();
if object_class_name != supplied_interface_name {
let object_class_description = AbstractTypeDescription::for_class_name(object_class_name);
let supplied_interface_description = AbstractTypeDescription::for_class_name(supplied_interface_name);
if ! self.class_store.are_types_compatible(&object_class_description, &supplied_interface_description) {
return Err(Error::RunTimeError(format!("Tried to invoke interface method : '{supplied_interface_name}.{supplied_method_name}' on object of type '{object_class_name}'")));
}
}
// TODO: I hate this, now I have to find the 'implementation' of a function
let interface_class_file = self.class_store.class_file_from_idx(target_interface_class_index).unwrap();
let interface_frame = StackFrame::new(
interface_class_file,
target_interface_class_index,
method_index as u16,
arguments.make_contiguous()
);
return Ok(JVMCallbackOperation::PushFrame(interface_frame));
}
Instruction::InvokeSpecial(methodref_index) => {
// No instance-based dispatch
let (supplied_class_name, supplied_method_name, supplied_descriptor_string) = class.gather_methodref(methodref_index)?;