Implemented a lot of opcodes and some native methods
This commit is contained in:
parent
4c43e9290f
commit
272a34b7cd
5 changed files with 394 additions and 101 deletions
222
src/jvm.rs
222
src/jvm.rs
|
@ -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(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue