Preload java/lang/ref/Reference

This commit is contained in:
VegOwOtenks 2024-11-15 11:14:35 +01:00
parent 5cf17d5ca3
commit c4da80f23c
4 changed files with 173 additions and 9 deletions

View file

@ -246,6 +246,7 @@ impl Bytecode {
}
0xAC => (Instruction::ReturnInt(), 1),
0xAD => (Instruction::ReturnLong(), 1),
0xAE => (Instruction::ReturnFloat(), 1),
0xAF => (Instruction::ReturnDouble(), 1),
0xB0 => (Instruction::ReturnReference(), 1),
@ -454,6 +455,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
ReturnFloat() = 0xAE, // return float from function
ReturnDouble() = 0xAF, // return double from function
ReturnReference() = 0xB0, // return top-ref from current function

View file

@ -141,10 +141,14 @@ impl ClassStore {
}
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()
if my_index == self.class_idx_from_name(&other_name.to_string()).unwrap() {
true
} else {
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 {

View file

@ -211,7 +211,8 @@ impl JVM {
attributes: Box::new([]),
};
self.class_store.add_class(array_class_file, true).unwrap();
let class_index = self.class_store.add_class(array_class_file, true).unwrap();
self.class_store.set_class_objectref_by_index(class_index, array_class_object);
self.class_store.put_array_class_ref(
array_type_description,
@ -509,6 +510,7 @@ impl JVM {
JVMCallbackOperation::ThrowException(exception) => {
let mut is_handler_found = false;
let exception_type_index = self.heap_area.object_area.get_object_class_index(exception);
while ! is_handler_found {
is_handler_found = {
let frame = {
@ -520,7 +522,6 @@ impl JVM {
if method.is_native() {
false
} else {
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)?
}
};
@ -2279,6 +2280,17 @@ impl JVM {
return Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Double(double)));
}
Instruction::ReturnFloat() => {
match (method.descriptor.return_type.array_level, &method.descriptor.return_type.kind) {
(0, AbstractTypeKind::Float()) => (),
_ => return Err(Error::OpcodeError(format!("Found opcode '{:?}' on method returning '{:?}'", instruction, method.descriptor.return_type)))
}
let float = wrap_stackframe_error(class, method, frame.operand_stack.pop_float(0))?;
return Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Float(float)));
}
Instruction::ReturnInt() => {
match (method.descriptor.return_type.array_level, &method.descriptor.return_type.kind) {
(_, AbstractTypeKind::Byte() | AbstractTypeKind::Boolean()| AbstractTypeKind::Int() | AbstractTypeKind::Char() | AbstractTypeKind::Short()) => (),

View file

@ -455,6 +455,22 @@ impl JavaLangRuntime {
}
}
struct JavaLangSignal {}
impl JavaLangSignal {
fn find_signal_0(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
let frame = {
let frame_index = jvm.stack_frames.len() - 1;
&mut jvm.stack_frames[frame_index]
};
let string_ref = frame.load_local_reference(0).unwrap();
let rust_string = jvm.heap_area.decode_java_string(string_ref, &jvm.class_store);
// TODO: Actually 'find' signals, HUP, INT and TERM
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Int(-1)))
}
}
struct JavaLangStringUTF16 {}
impl JavaLangStringUTF16 {
@ -466,6 +482,64 @@ impl JavaLangStringUTF16 {
struct JavaLangSystem {}
impl JavaLangSystem {
fn register_natives(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
// Load class because it won't be loaded otherwise
let frame = {
let frame_index = jvm.stack_frames.len() - 1;
&mut jvm.stack_frames[frame_index]
};
let r#return = match frame.instruction_pointer {
0 => {
Ok(JVMCallbackOperation::LoadClass("java/lang/ref/Reference".to_string()))
}
1 => {
Ok(JVMCallbackOperation::InitClass("java/lang/ref/Reference".to_string()))
}
_ => {
Ok(JVMCallbackOperation::PopFrame())
}
};
frame.instruction_pointer += 1;
return r#return;
}
fn set_err_0(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
let frame = {
let frame_index = jvm.stack_frames.len() - 1;
&mut jvm.stack_frames[frame_index]
};
let input_stream = frame.load_local_reference(0).unwrap();
// TODO: Bypass final
jvm.heap_area.static_area.set(
&String::from("java/lang/System"),
&String::from("err"),
FieldValue::Reference(input_stream)
)?;
Ok(JVMCallbackOperation::PopFrame())
}
fn set_out_0(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
let frame = {
let frame_index = jvm.stack_frames.len() - 1;
&mut jvm.stack_frames[frame_index]
};
let input_stream = frame.load_local_reference(0).unwrap();
// TODO: Bypass final
jvm.heap_area.static_area.set(
&String::from("java/lang/System"),
&String::from("out"),
FieldValue::Reference(input_stream)
)?;
Ok(JVMCallbackOperation::PopFrame())
}
fn set_in_0(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
let frame = {
let frame_index = jvm.stack_frames.len() - 1;
@ -1604,7 +1678,7 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
]),
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void()},
},
ignore_call
JavaLangSystem::register_natives
),
(
@ -1628,7 +1702,7 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
]),
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void()},
},
todo_call
JavaLangSystem::set_out_0
),
(
@ -1640,7 +1714,7 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
]),
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void()},
},
todo_call
JavaLangSystem::set_err_0
),
(
@ -3846,6 +3920,78 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
},
ignore_call
),
(
"jdk/internal/misc/ScopedMemoryAccess",
"registerNatives",
MethodDescriptor {
argument_types: Box::new([
]),
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void() },
},
ignore_call
),
(
"jdk/internal/misc/ScopedMemoryAccess",
"closeScope0",
MethodDescriptor {
argument_types: Box::new([
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("jdk/internal/foreign/MemorySessionImpl".to_string())},
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("jdk/internal/misc/ScopedMemoryAccess$ScopedAccessError".to_string())},
]),
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void() },
},
todo_call
),
(
"java/lang/NullPointerException",
"getExtendedNPEMessage",
MethodDescriptor {
argument_types: Box::new([
]),
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/String".to_string()) },
},
todo_call
),
(
"jdk/internal/misc/Signal",
"findSignal0",
MethodDescriptor {
argument_types: Box::new([
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/String".to_string())},
]),
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Int() },
},
JavaLangSignal::find_signal_0
),
(
"jdk/internal/misc/Signal",
"handle0",
MethodDescriptor {
argument_types: Box::new([
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Int() },
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Long() },
]),
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Long() },
},
todo_call
),
(
"jdk/internal/misc/Signal",
"raise0",
MethodDescriptor {
argument_types: Box::new([
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Int() },
]),
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void() },
},
todo_call
),
];
for (classname, methodname, methoddescriptor, binding) in native_mappings {