Implemented Exception Throwing
This commit is contained in:
parent
f5428c79b2
commit
8e5b6bb2b8
5 changed files with 224 additions and 9 deletions
|
@ -102,6 +102,7 @@ impl Bytecode {
|
|||
0x6D => (Instruction::DivideLong(), 1),
|
||||
0x6E => (Instruction::DivideFloat(), 1),
|
||||
|
||||
0x70 => (Instruction::ModuloInt(), 1),
|
||||
0x74 => (Instruction::NegateInt(), 1),
|
||||
0x75 => (Instruction::NegateLong(), 1),
|
||||
0x78 => (Instruction::ArithmeticShiftIntLeft(), 1),
|
||||
|
@ -386,6 +387,7 @@ pub enum Instruction {
|
|||
DivideLong() = 0x6D, // long division
|
||||
DivideFloat() = 0x6E, // float division
|
||||
|
||||
ModuloInt() = 0x70, // modulo
|
||||
NegateInt() = 0x74, // arithmetic negation
|
||||
NegateLong() = 0x75, // arithmetic negation
|
||||
ArithmeticShiftIntLeft() = 0x78, // shift int left, preserve sign
|
||||
|
|
|
@ -375,6 +375,15 @@ impl JavaClassFile {
|
|||
|
||||
return Ok((class_name, method_name, method_descriptor));
|
||||
}
|
||||
|
||||
pub fn gather_methodref_compatible(&self, methodref_index: u16) -> Result<(&String, &String, &String), Error> {
|
||||
return match self.pool_entry(methodref_index) {
|
||||
Ok(ConstantPoolInfo::MethodRef(_)) => self.gather_methodref(methodref_index),
|
||||
Ok(ConstantPoolInfo::InterfaceMethodRef(_)) => self.gather_interfacemethodref(methodref_index),
|
||||
Err(i) => Err(i),
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sourcefile(&self) -> Result<Option<&String>, Error> {
|
||||
match (&self.attributes).into_iter()
|
||||
|
|
18
src/jvm.rs
18
src/jvm.rs
|
@ -1403,7 +1403,7 @@ impl JVM {
|
|||
},
|
||||
|
||||
Instruction::InvokeStatic(methodref_index) => {
|
||||
let (supplied_class_name, supplied_method_name, supplied_descriptor_string) = class.gather_methodref(methodref_index)?;
|
||||
let (supplied_class_name, supplied_method_name, supplied_descriptor_string) = class.gather_methodref_compatible(methodref_index)?;
|
||||
|
||||
if ! self.class_store.have_class(supplied_class_name) {
|
||||
// rewind the bytecode offset, I'll need to execute this instruction again
|
||||
|
@ -1842,6 +1842,15 @@ impl JVM {
|
|||
wrap_stackframe_error(class, method, frame.operand_stack.push_long(result))?;
|
||||
}
|
||||
|
||||
Instruction::ModuloInt() => {
|
||||
let int_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
|
||||
let int_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
|
||||
|
||||
let modulo = int_2.wrapping_rem(int_1);
|
||||
|
||||
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(modulo)))?;
|
||||
}
|
||||
|
||||
Instruction::NegateInt() => {
|
||||
let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
|
||||
let negated = -int;
|
||||
|
@ -2020,6 +2029,7 @@ impl JVM {
|
|||
match expected_field_descriptor.as_str() {
|
||||
"Z" => FieldValue::Boolean(i != 0),
|
||||
"B" => FieldValue::Byte(i as i8),
|
||||
"C" => FieldValue::Char(i as u16),
|
||||
_ => FieldValue::Int(i)
|
||||
}
|
||||
}
|
||||
|
@ -2126,7 +2136,7 @@ impl JVM {
|
|||
_ => return Err(Error::OpcodeError(format!("Found opcode '{:?}' on method returning '{:?}'", instruction, method.descriptor.return_type)))
|
||||
}
|
||||
|
||||
let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
|
||||
let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int_compatible(0))?;
|
||||
|
||||
return Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Int(int)));
|
||||
}
|
||||
|
@ -2429,8 +2439,8 @@ fn fill_arguments(class: &JavaClassFile, method: &MethodInfo, arguments: &mut Ve
|
|||
wrap_stackframe_error(
|
||||
class,
|
||||
method,
|
||||
stack.pop_char(0)
|
||||
)? as i32
|
||||
stack.pop_int_compatible(0)
|
||||
)?
|
||||
)
|
||||
)
|
||||
},
|
||||
|
|
|
@ -461,6 +461,14 @@ impl JavaLangThrowable {
|
|||
}
|
||||
}
|
||||
|
||||
struct JdkInternalMiscCDS {}
|
||||
|
||||
impl JdkInternalMiscCDS {
|
||||
fn get_cds_config_status(_jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||
return Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Int(0)));
|
||||
}
|
||||
}
|
||||
|
||||
struct JdkInternalMiscUnsafe {}
|
||||
|
||||
impl JdkInternalMiscUnsafe {
|
||||
|
@ -2949,6 +2957,185 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
|
|||
},
|
||||
JavaLangThrowable::fill_in_stacktrace
|
||||
),
|
||||
|
||||
(
|
||||
"java/lang/invoke/MethodHandle",
|
||||
"invokeExact",
|
||||
MethodDescriptor {
|
||||
argument_types: Box::new([
|
||||
AbstractTypeDescription { array_level: 1, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||
]),
|
||||
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||
},
|
||||
todo_call
|
||||
),
|
||||
|
||||
(
|
||||
"java/lang/invoke/MethodHandle",
|
||||
"invoke",
|
||||
MethodDescriptor {
|
||||
argument_types: Box::new([
|
||||
AbstractTypeDescription { array_level: 1, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||
]),
|
||||
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||
},
|
||||
todo_call
|
||||
),
|
||||
|
||||
(
|
||||
"java/lang/invoke/MethodHandle",
|
||||
"invokeBasic",
|
||||
MethodDescriptor {
|
||||
argument_types: Box::new([
|
||||
AbstractTypeDescription { array_level: 1, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||
]),
|
||||
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||
},
|
||||
todo_call
|
||||
),
|
||||
|
||||
(
|
||||
"java/lang/invoke/MethodHandle",
|
||||
"linkToVirtual",
|
||||
MethodDescriptor {
|
||||
argument_types: Box::new([
|
||||
AbstractTypeDescription { array_level: 1, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||
]),
|
||||
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||
},
|
||||
todo_call
|
||||
),
|
||||
|
||||
(
|
||||
"java/lang/invoke/MethodHandle",
|
||||
"linkToStatic",
|
||||
MethodDescriptor {
|
||||
argument_types: Box::new([
|
||||
AbstractTypeDescription { array_level: 1, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||
]),
|
||||
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||
},
|
||||
todo_call
|
||||
),
|
||||
|
||||
(
|
||||
"java/lang/invoke/MethodHandle",
|
||||
"linkToSpecial",
|
||||
MethodDescriptor {
|
||||
argument_types: Box::new([
|
||||
AbstractTypeDescription { array_level: 1, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||
]),
|
||||
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||
},
|
||||
todo_call
|
||||
),
|
||||
|
||||
(
|
||||
"java/lang/invoke/MethodHandle",
|
||||
"linkToInterface",
|
||||
MethodDescriptor {
|
||||
argument_types: Box::new([
|
||||
AbstractTypeDescription { array_level: 1, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||
]),
|
||||
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||
},
|
||||
todo_call
|
||||
),
|
||||
|
||||
(
|
||||
"java/lang/invoke/MethodHandle",
|
||||
"linkToNative",
|
||||
MethodDescriptor {
|
||||
argument_types: Box::new([
|
||||
AbstractTypeDescription { array_level: 1, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||
]),
|
||||
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||
},
|
||||
todo_call
|
||||
),
|
||||
|
||||
(
|
||||
"jdk/internal/misc/CDS",
|
||||
"getCDSConfigStatus",
|
||||
MethodDescriptor {
|
||||
argument_types: Box::new([
|
||||
]),
|
||||
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Int() },
|
||||
},
|
||||
JdkInternalMiscCDS::get_cds_config_status
|
||||
),
|
||||
|
||||
(
|
||||
"jdk/internal/misc/CDS",
|
||||
"logLambdaFormInvoker",
|
||||
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::Void() },
|
||||
},
|
||||
todo_call
|
||||
),
|
||||
|
||||
(
|
||||
"jdk/internal/misc/CDS",
|
||||
"initializeFromArchive",
|
||||
MethodDescriptor {
|
||||
argument_types: Box::new([
|
||||
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Class".to_string())},
|
||||
]),
|
||||
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void() },
|
||||
},
|
||||
ignore_call // TODO: idk
|
||||
),
|
||||
|
||||
(
|
||||
"jdk/internal/misc/CDS",
|
||||
"defineArchivedModules",
|
||||
MethodDescriptor {
|
||||
argument_types: Box::new([
|
||||
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/ClassLoader".to_string())},
|
||||
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/ClassLoader".to_string())},
|
||||
]),
|
||||
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void() },
|
||||
},
|
||||
todo_call
|
||||
),
|
||||
|
||||
(
|
||||
"jdk/internal/misc/CDS",
|
||||
"getRandomSeedForDumping",
|
||||
MethodDescriptor {
|
||||
argument_types: Box::new([
|
||||
]),
|
||||
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Long() },
|
||||
},
|
||||
todo_call
|
||||
),
|
||||
|
||||
(
|
||||
"jdk/internal/misc/CDS",
|
||||
"dumpClassList",
|
||||
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::Void() },
|
||||
},
|
||||
todo_call
|
||||
),
|
||||
|
||||
(
|
||||
"jdk/internal/misc/CDS",
|
||||
"dumpDynamicArchive",
|
||||
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::Void() },
|
||||
},
|
||||
todo_call
|
||||
),
|
||||
];
|
||||
|
||||
for (classname, methodname, methoddescriptor, binding) in native_mappings {
|
||||
|
|
|
@ -8,7 +8,7 @@ pub enum StackValue {
|
|||
Boolean(bool),
|
||||
Byte(i8),
|
||||
Char(u16),
|
||||
Short(u16),
|
||||
Short(i16),
|
||||
Int(i32),
|
||||
Float(f32),
|
||||
Reference(ObjectReference),
|
||||
|
@ -102,9 +102,15 @@ impl OperandStack {
|
|||
self.push_long(l)
|
||||
}
|
||||
|
||||
_ => {
|
||||
println!("{value:?}");
|
||||
todo!();
|
||||
FieldValue::Char(c) => {
|
||||
self.push(StackValue::Char(c))
|
||||
}
|
||||
|
||||
FieldValue::Short(s) => {
|
||||
self.push(StackValue::Short(s))
|
||||
}
|
||||
FieldValue::Double(d) => {
|
||||
self.push_double(d)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -191,7 +197,7 @@ impl OperandStack {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn pop_short(&mut self, index: usize) -> Result<u16, Error> {
|
||||
pub fn pop_short(&mut self, index: usize) -> Result<i16, Error> {
|
||||
let absolute_index = self.depth as usize - 1 - index;
|
||||
let value = self.stack[absolute_index];
|
||||
self.depth -= 1;
|
||||
|
@ -218,6 +224,7 @@ impl OperandStack {
|
|||
match value {
|
||||
StackValue::Int(i) => Ok(i),
|
||||
StackValue::Byte(b) => Ok(b as i32),
|
||||
StackValue::Char(c) => Ok(c as i32),
|
||||
_ => Err(Error::LocalError(format!("Mismatched type at index {} of the function operand stack, expected Int-compatible but found '{:?}'", index, value)))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue