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

@ -442,7 +442,7 @@ impl JVM {
};
let class = self.class_store.class_file_from_idx(frame.class_index).unwrap();
let method = & class.methods[frame.method_index as usize];
wrap_stackframe_error(class, method, self.stack_frames.last_mut().unwrap().operand_stack.push(value))?;
wrap_stackframe_error(class, method, self.stack_frames.last_mut().unwrap().operand_stack.push_field_value(value))?;
}
JVMCallbackOperation::PushFrame(frame) => self.stack_frames.push(frame),
@ -580,6 +580,11 @@ impl JVM {
FieldValue::Float(float_entry.value)
},
AbstractTypeKind::Double() => {
let double_entry = class_file.pool_double_entry(constant_value_info.constant_value_index)?;
FieldValue::Double(double_entry.value)
}
AbstractTypeKind::Classname(ref name) => {
if name == "java/lang/String" {
let string_entry = class_file.gather_string(constant_value_info.constant_value_index)?;
@ -880,26 +885,28 @@ impl JVM {
// TODO: Class loading checks
let class_name = class.gather_class(classref_index)?;
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);
if object != ObjectReference::NULL {
let native_class_name = self.heap_area.object_area.get_reference_native_class_name(object, &self.class_store);
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 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 }
};
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}")))
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}")))
}
}
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Reference(object)))?;
}
Instruction::CompareFloatG() => {
@ -936,6 +943,20 @@ impl JVM {
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(comparison_result)))?;
}
Instruction::CompareLong() => {
let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
let comparison_result = if value_1 > value_2 {
1
} else if value_1 < value_2 {
-1
} else {
0
};
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(comparison_result)))?;
}
Instruction::ConvertFloatToInt() => {
let float = wrap_stackframe_error(class, method, frame.operand_stack.pop_float(0))?;
let int_value = match float {
@ -947,6 +968,13 @@ impl JVM {
frame.operand_stack.push(StackValue::Int(int_value)).unwrap();
}
Instruction::ConvertIntToByte() => {
let int_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
let byte_value = int_value & 0x000000FF;
frame.operand_stack.push(StackValue::Int(byte_value)).unwrap();
}
Instruction::ConvertIntToChar() => {
let int_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
let char_value = int_value & 0x0000FFFF;
@ -961,6 +989,20 @@ impl JVM {
frame.operand_stack.push(StackValue::Float(float_value)).unwrap();
}
Instruction::ConvertIntToLong() => {
let int_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
let long_value = int_value as i64;
wrap_stackframe_error(class, method, frame.operand_stack.push_long(long_value))?;
}
Instruction::ConvertLongToInt() => {
let long_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
let int_value = long_value as i32;
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(int_value)))?;
}
Instruction::DivideInt() => {
// TODO: Obey all the rules
let quotient = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
@ -969,6 +1011,15 @@ impl JVM {
frame.operand_stack.push(StackValue::Int(divident / quotient)).unwrap();
}
Instruction::DivideLong() => {
// TODO: Obey all the rules
let quotient = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
let divident = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
let result = divident / quotient;
wrap_stackframe_error(class, method, frame.operand_stack.push_long(result))?;
}
Instruction::Duplicate() => {
let popped_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_computational_1(0))?;
wrap_stackframe_error(class, method, frame.operand_stack.push(popped_value))?;
@ -1474,6 +1525,11 @@ impl JVM {
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(int_value)))?;
}
ConstantPoolInfo::Float(float_data) => {
let float_value = float_data.value;
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Float(float_value)))?;
}
_ => {
println!("{:?}", class.pool_entry(wide_index).unwrap());
todo!()
@ -1488,6 +1544,11 @@ impl JVM {
wrap_stackframe_error(class, method, frame.operand_stack.push_long(long_value))?;
}
ConstantPoolInfo::Double(double_data) => {
let double = double_data.value;
wrap_stackframe_error(class, method, frame.operand_stack.push_double(double))?;
}
_ => {
println!("{:?}", class.pool_entry(wide_index).unwrap());
todo!()
@ -1527,6 +1588,28 @@ impl JVM {
load_local_int(class, method, frame, 3)?;
}
Instruction::LoadLocalLong(index) => {
let long_value = wrap_stackframe_error(class, method, frame.load_local_long(index as u16))?;
wrap_stackframe_error(class, method, frame.operand_stack.push_long(long_value))?;
}
Instruction::LoadLocalLong0() => {
let long_value = wrap_stackframe_error(class, method, frame.load_local_long(0))?;
wrap_stackframe_error(class, method, frame.operand_stack.push_long(long_value))?;
}
Instruction::LoadLocalLong1() => {
let long_value = wrap_stackframe_error(class, method, frame.load_local_long(1))?;
wrap_stackframe_error(class, method, frame.operand_stack.push_long(long_value))?;
}
Instruction::LoadLocalLong2() => {
let long_value = wrap_stackframe_error(class, method, frame.load_local_long(2))?;
wrap_stackframe_error(class, method, frame.operand_stack.push_long(long_value))?;
}
Instruction::LoadLocalLong3() => {
let long_value = wrap_stackframe_error(class, method, frame.load_local_long(3))?;
wrap_stackframe_error(class, method, frame.operand_stack.push_long(long_value))?;
}
Instruction::LoadLocalReference(index) => {
load_local_reference(class, method, frame, index as usize)?;
}
@ -1588,6 +1671,27 @@ impl JVM {
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(java_result)))?;
}
Instruction::MultiplyLong() => {
let factor_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
let factor_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
let result = factor_1 * factor_2;
wrap_stackframe_error(class, method, frame.operand_stack.push_long(result))?;
}
Instruction::NegateInt() => {
let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
let negated = -int;
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(negated)))?;
}
Instruction::NegateLong() => {
let long = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
let negated = -long;
wrap_stackframe_error(class, method, frame.operand_stack.push_long(negated))?;
}
Instruction::NewArray(component_class_index) => {
// construct single level array
let component_class_name = class.gather_class(component_class_index)?;
@ -1743,6 +1847,7 @@ impl JVM {
StackValue::Int(i) => FieldValue::Int(i),
StackValue::Reference(r) => FieldValue::Reference(r),
StackValue::Float(f) => FieldValue::Float(f),
StackValue::Byte(b) => FieldValue::Byte(b),
stack_value @ _ => {
println!("{stack_value:?}");
todo!()
@ -1845,17 +1950,28 @@ impl JVM {
let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
return Ok(JVMCallbackOperation::ReturnFrame(StackValue::Int(int)));
return Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Int(int)));
}
Instruction::ReturnLong() => {
match (method.descriptor.return_type.array_level, &method.descriptor.return_type.kind) {
(0, AbstractTypeKind::Long()) => (),
_ => return Err(Error::OpcodeError(format!("Found opcode '{:?}' on method returning '{:?}'", instruction, method.descriptor.return_type)))
}
let long = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
return Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Long(long)));
}
Instruction::ReturnReference() => {
match (method.descriptor.return_type.array_level, &method.descriptor.return_type.kind) {
(1..=u8::MAX, _) => (),
(_, AbstractTypeKind::Classname(_)) => (),
_ => return Err(Error::OpcodeError(format!("Found opcode '{:?}' on method returning '{:?}'", instruction, method.descriptor.return_type)))
}
let ref_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?;
return Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(ref_value)));
return Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Reference(ref_value)));
}
Instruction::ReturnVoid() => {
let expected_type = AbstractTypeDescription {
@ -1928,6 +2044,13 @@ impl JVM {
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(value_1 - value_2)))?;
}
Instruction::SubtractLong() => {
let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
wrap_stackframe_error(class, method, frame.operand_stack.push_long(value_1 - value_2))?;
}
Instruction::StoreLocalFloat(index) => {
let float = wrap_stackframe_error(class, method, frame.operand_stack.pop_float(0))?;
@ -1961,11 +2084,39 @@ impl JVM {
}
Instruction::StoreLocalLong(index) => {
let long1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_long1(0))?;
let _ = wrap_stackframe_error(class, method, frame.operand_stack.pop_long1(0))?;
let long0 = wrap_stackframe_error(class, method, frame.operand_stack.pop_long0(0))?;
wrap_stackframe_error(class, method, frame.store_local(index as u16, StackValue::Long0(long0)))?;
wrap_stackframe_error(class, method, frame.store_local(index as u16 + 1, StackValue::Long1(long1)))?;
wrap_stackframe_error(class, method, frame.store_local(index as u16 + 1, StackValue::Long1()))?;
}
Instruction::StoreLocalLong0() => {
let _ = wrap_stackframe_error(class, method, frame.operand_stack.pop_long1(0))?;
let long0 = wrap_stackframe_error(class, method, frame.operand_stack.pop_long0(0))?;
wrap_stackframe_error(class, method, frame.store_local(1, StackValue::Long0(long0)))?;
wrap_stackframe_error(class, method, frame.store_local(2, StackValue::Long1()))?;
}
Instruction::StoreLocalLong1() => {
let _ = wrap_stackframe_error(class, method, frame.operand_stack.pop_long1(0))?;
let long0 = wrap_stackframe_error(class, method, frame.operand_stack.pop_long0(0))?;
wrap_stackframe_error(class, method, frame.store_local(1, StackValue::Long0(long0)))?;
wrap_stackframe_error(class, method, frame.store_local(2, StackValue::Long1()))?;
}
Instruction::StoreLocalLong2() => {
let _ = wrap_stackframe_error(class, method, frame.operand_stack.pop_long1(0))?;
let long0 = wrap_stackframe_error(class, method, frame.operand_stack.pop_long0(0))?;
wrap_stackframe_error(class, method, frame.store_local(2, StackValue::Long0(long0)))?;
wrap_stackframe_error(class, method, frame.store_local(3, StackValue::Long1()))?;
}
Instruction::StoreLocalLong3() => {
let _ = wrap_stackframe_error(class, method, frame.operand_stack.pop_long1(0))?;
let long0 = wrap_stackframe_error(class, method, frame.operand_stack.pop_long0(0))?;
wrap_stackframe_error(class, method, frame.store_local(3, StackValue::Long0(long0)))?;
wrap_stackframe_error(class, method, frame.store_local(4, StackValue::Long1()))?;
}
Instruction::StoreLocalReference(index) => {
@ -2029,7 +2180,7 @@ impl JVM {
pub enum JVMCallbackOperation {
PopFrame(),
ReturnFrame(StackValue),
ReturnFrame(FieldValue),
PushFrame(StackFrame),
LoadClass(String),
InitClass(String),
@ -2053,9 +2204,9 @@ fn load_local_float(class: &JavaClassFile, method: &MethodInfo, frame: &mut Stac
}
fn load_local_int(class: &JavaClassFile, method: &MethodInfo, frame: &mut StackFrame, index: usize) -> Result<(), Error> {
let loaded_value = wrap_stackframe_error(class, method, frame.load_local_int(index as u16))?;
let int_compatible_stackvalue = wrap_stackframe_error(class, method, frame.load_local_int_compatible(index as u16))?;
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(loaded_value)))?;
wrap_stackframe_error(class, method, frame.operand_stack.push(int_compatible_stackvalue))?;
Ok(())
}
@ -2095,15 +2246,12 @@ fn fill_arguments(class: &JavaClassFile, method: &MethodInfo, arguments: &mut Ve
)
},
AbstractTypeKind::Double() => {
arguments.push_front(
StackValue::Double1(
wrap_stackframe_error(
class,
method,
stack.pop_double1(0)
)?
)
);
wrap_stackframe_error(
class,
method,
stack.pop_double1(0)
)?;
arguments.push_front(StackValue::Double1());
arguments.push_front(
StackValue::Double0(
wrap_stackframe_error(
@ -2137,13 +2285,13 @@ fn fill_arguments(class: &JavaClassFile, method: &MethodInfo, arguments: &mut Ve
)
},
AbstractTypeKind::Long() => {
wrap_stackframe_error(
class,
method,
stack.pop_long1(0)
)?;
arguments.push_front(
StackValue::Long1(
wrap_stackframe_error(
class,
method,
stack.pop_long1(0)
)?
)
);
arguments.push_front(