Preload java/lang/ref/Reference
This commit is contained in:
parent
5cf17d5ca3
commit
c4da80f23c
4 changed files with 173 additions and 9 deletions
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
16
src/jvm.rs
16
src/jvm.rs
|
@ -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()) => (),
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue