Implemented a lot of opcodes and some native methods

This commit is contained in:
vegowotenks 2024-11-03 17:42:04 +01:00
parent 4c43e9290f
commit 272a34b7cd
5 changed files with 394 additions and 101 deletions

View file

@ -87,7 +87,7 @@ impl JavaLangClass {
1 => {
if wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))? == 1 {
let boolean_class_ref = jvm.class_store.primitive_classes.boolean_class;
Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(boolean_class_ref)))
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Reference(boolean_class_ref)))
} else {
let byte_class_ref = jvm.class_store.primitive_classes.byte_class;
let byte_class_name_ref = match jvm.heap_area.object_area.get_object_field(
@ -114,7 +114,7 @@ impl JavaLangClass {
2 => {
if wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))? == 1 {
let char_class_ref = jvm.class_store.primitive_classes.char_class;
Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(char_class_ref)))
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Reference(char_class_ref)))
} else {
let char_class_ref = jvm.class_store.primitive_classes.char_class;
let char_class_name_ref = match jvm.heap_area.object_area.get_object_field(
@ -141,7 +141,7 @@ impl JavaLangClass {
3 => {
if wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))? == 1 {
let short_class_ref = jvm.class_store.primitive_classes.short_class;
Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(short_class_ref)))
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Reference(short_class_ref)))
} else {
let short_class_ref = jvm.class_store.primitive_classes.short_class;
let short_class_name_ref = match jvm.heap_area.object_area.get_object_field(
@ -168,7 +168,7 @@ impl JavaLangClass {
4 => {
if wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))? == 1 {
let int_class_ref = jvm.class_store.primitive_classes.int_class;
Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(int_class_ref)))
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Reference(int_class_ref)))
} else {
let int_class_ref = jvm.class_store.primitive_classes.int_class;
let int_class_name_ref = match jvm.heap_area.object_area.get_object_field(
@ -195,7 +195,7 @@ impl JavaLangClass {
5 => {
if wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))? == 1 {
let float_class_ref = jvm.class_store.primitive_classes.float_class;
Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(float_class_ref)))
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Reference(float_class_ref)))
} else {
let float_class_ref = jvm.class_store.primitive_classes.float_class;
let float_class_name_ref = match jvm.heap_area.object_area.get_object_field(
@ -222,7 +222,7 @@ impl JavaLangClass {
6 => {
if wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))? == 1 {
let double_class_ref = jvm.class_store.primitive_classes.double_class;
Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(double_class_ref)))
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Reference(double_class_ref)))
} else {
let double_class_ref = jvm.class_store.primitive_classes.double_class;
let double_class_name_ref = match jvm.heap_area.object_area.get_object_field(
@ -249,7 +249,7 @@ impl JavaLangClass {
7 => {
if wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))? == 1 {
let long_class_ref = jvm.class_store.primitive_classes.long_class;
Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(long_class_ref)))
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Reference(long_class_ref)))
} else {
let long_class_ref = jvm.class_store.primitive_classes.long_class;
let long_class_name_ref = match jvm.heap_area.object_area.get_object_field(
@ -276,17 +276,55 @@ impl JavaLangClass {
8 => {
if wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))? == 1 {
let long_class_ref = jvm.class_store.primitive_classes.long_class;
Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(long_class_ref)))
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Reference(long_class_ref)))
} else {
Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(ObjectReference::NULL)))
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Reference(ObjectReference::NULL)))
}
}
_ => Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(ObjectReference::NULL)))
_ => Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Reference(ObjectReference::NULL)))
}
}
pub fn desired_assertion_status_0(_: &mut JVM) -> Result<JVMCallbackOperation, Error> {
Ok(JVMCallbackOperation::ReturnFrame(StackValue::Int(1)))
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Int(1)))
}
}
struct JavaLangFloat {}
impl JavaLangFloat {
pub fn float_to_raw_int_bits(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
let frame = {
let frame_index = jvm.stack_frames.len() - 1;
&mut jvm.stack_frames[frame_index]
};
let class = jvm.class_store.class_file_from_idx(frame.class_index).unwrap();
let method = & class.methods[frame.method_index as usize];
let float_value = wrap_stackframe_error(class, method, frame.load_local_float(0))?;
let ubits = float_value.to_bits();
let ibits = i32::from_ne_bytes(ubits.to_ne_bytes());
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Int(ibits)))
}
}
struct JavaLangDouble {}
impl JavaLangDouble {
pub fn double_to_raw_long_bits(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
let frame = {
let frame_index = jvm.stack_frames.len() - 1;
&mut jvm.stack_frames[frame_index]
};
let class = jvm.class_store.class_file_from_idx(frame.class_index).unwrap();
let method = & class.methods[frame.method_index as usize];
let double_value = wrap_stackframe_error(class, method, frame.load_local_double(0))?;
let ubits = double_value.to_bits();
let ibits = i64::from_ne_bytes(ubits.to_ne_bytes());
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Long(ibits)))
}
}
@ -294,7 +332,7 @@ struct JavaLangStringUTF16 {}
impl JavaLangStringUTF16 {
pub fn is_big_endian(_jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
Ok(JVMCallbackOperation::ReturnFrame(StackValue::Int(if cfg!(target_endian = "big") {1} else {0})))
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Int(if cfg!(target_endian = "big") {1} else {0})))
}
}
@ -336,12 +374,12 @@ impl JdkInternalMiscUnsafe {
std::mem::size_of::<usize>() as i32
};
Ok(JVMCallbackOperation::ReturnFrame(StackValue::Int(index_scale)))
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Int(index_scale)))
}
pub fn array_base_offset_0(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
// TODO: Check passed class
Ok(JVMCallbackOperation::ReturnFrame(StackValue::Int(0)))
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Int(0)))
}
}
@ -390,7 +428,7 @@ impl JdkInternalUtilSystemPropsRaw {
}
Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(array_reference)))
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Reference(array_reference)))
}
// command-line configured properties, should return at least java.home
@ -404,6 +442,7 @@ impl JdkInternalUtilSystemPropsRaw {
("user.country", "US"),
("user.variant", ""),
("sun.nio.MaxDirectMemorySize", "9223372036854775807"),
("sun.nio.PageAlignDirectMemory", "false"),
];
// TODO: Cross-Platform tmpdir
// TODO: locale detection
@ -420,7 +459,7 @@ impl JdkInternalUtilSystemPropsRaw {
jvm.heap_area.object_area.set_array_element(array_reference, index * 2 + 1, value_reference.into());
}
Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(array_reference)))
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Reference(array_reference)))
}
}
@ -921,6 +960,36 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
Ok(todo_call)
}
("java/lang/Double", "doubleToRawLongBits") => {
let expected_descriptor = MethodDescriptor {
argument_types: Box::new([
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Double() }
]),
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Long() },
};
if m.descriptor != expected_descriptor {
return Err(Error::RunTimeError(format!("Native descriptor mismatch for method '{class_name}.{method_name}': found '{}' but expected '{}'", m.descriptor.source_string(), expected_descriptor.source_string())));
}
Ok(JavaLangDouble::double_to_raw_long_bits)
}
("java/lang/Double", "longBitsToDouble") => {
let expected_descriptor = MethodDescriptor {
argument_types: Box::new([
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Long() }
]),
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Double() },
};
if m.descriptor != expected_descriptor {
return Err(Error::RunTimeError(format!("Native descriptor mismatch for method '{class_name}.{method_name}': found '{}' but expected '{}'", m.descriptor.source_string(), expected_descriptor.source_string())));
}
Ok(JavaLangDouble::double_to_raw_long_bits)
}
("java/lang/Float", "intBitsToFloat") => {
let expected_descriptor = MethodDescriptor {
argument_types: Box::new([
@ -948,7 +1017,7 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
return Err(Error::RunTimeError(format!("Native descriptor mismatch for method '{class_name}.{method_name}': found '{}' but expected '{}'", m.descriptor.source_string(), expected_descriptor.source_string())));
}
Ok(todo_call)
Ok(JavaLangFloat::float_to_raw_int_bits)
}
("java/lang/String", "intern") => {