Implemented opcodes, natives, fixed iterators

This commit is contained in:
vegowotenks 2024-11-06 23:39:26 +01:00
parent 49916f5564
commit dfb6060df9
6 changed files with 1485 additions and 1585 deletions

View file

@ -157,7 +157,7 @@ impl JVM {
fn make_array_class(&mut self, element_class_ref: ObjectReference, element_descriptor: AbstractTypeDescription) {
let class_class_index = self.class_store.class_idx_from_name(&"java/lang/Class".to_string()).unwrap();
let array_class_object = self.heap_area.make_object(&self.class_store, 6);
let array_class_object = self.heap_area.make_object(&self.class_store, class_class_index);
let array_class_data_object = self.heap_area.make_object(&self.class_store, 1);
let array_type_description = AbstractTypeDescription {
array_level: 1 + element_descriptor.array_level,
@ -341,12 +341,12 @@ impl JVM {
self.class_store.add_class(entry_class, true)?; // 0
self.class_store.add_class(JVM::class_native_class_data(), true)?; // 1
self.load_class(&"java/lang/Object".to_string())?; // 2
self.load_class(&"java/lang/Number".to_string())?; // 3
let byte_class_index = self.load_class(&"java/lang/Byte".to_string())?; // 4
let string_class_index = self.load_class(&"java/lang/String".to_string())?; // 5
let class_class_index = self.load_class(&"java/lang/Class".to_string())?; // 6
let system_class_index = self.load_class(&"java/lang/System".to_string())?; // 7
self.load_class_hierarchy(&"java/lang/Object".to_string())?; // 2
self.load_class_hierarchy(&"java/lang/Number".to_string())?; // 3
let byte_class_index = self.load_class_hierarchy(&"java/lang/Byte".to_string())?; // 4
let string_class_index = self.load_class_hierarchy(&"java/lang/String".to_string())?; // 5
let class_class_index = self.load_class_hierarchy(&"java/lang/Class".to_string())?; // 6
let system_class_index = self.load_class_hierarchy(&"java/lang/System".to_string())?; // 7
self.make_class_class("Ljava/lang/Byte;");
self.make_class_class("Ljava/lang/String;");
@ -466,15 +466,21 @@ impl JVM {
Ok(())
}
fn load_class_hierarchy(&mut self, name: &String) -> Result<(), Error> {
fn load_class_hierarchy(&mut self, name: &String) -> Result<usize, Error> {
let mut waiting_queue = VecDeque::new();
waiting_queue.push_back(name.clone());
let mut return_class_index = usize::MAX;
while waiting_queue.len() != 0 {
let class_name = waiting_queue.pop_front().unwrap();
if ! self.class_store.have_class(&class_name) {
let new_class_index = self.load_class(&class_name)?;
if class_name == *name {
return_class_index = new_class_index;
}
let (file, _) = self.class_store.get_class(&class_name).unwrap();
if file.has_super_class() {
waiting_queue.push_back(file.get_super_class_name()?.to_string());
@ -488,7 +494,7 @@ impl JVM {
}
}
Ok(())
Ok(return_class_index)
}
fn init_class_hierarchy(&mut self, name: &String) -> Result<(), Error> {
@ -678,6 +684,13 @@ impl JVM {
match instruction {
Instruction::AddDouble() => {
let value_0 = wrap_stackframe_error(class, method, frame.operand_stack.pop_double(0))?;
let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_double(0))?;
wrap_stackframe_error(class, method, frame.operand_stack.push_double(value_0 + value_1))?;
}
Instruction::AddInt() => {
let value_0 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
@ -685,6 +698,13 @@ impl JVM {
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(value_0 + value_1)))?;
}
Instruction::AddLong() => {
let value_0 = 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_0 + value_1))?;
}
Instruction::ArithmeticShiftIntLeft() => {
let shift = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))? as u8 & 0b00011111;
let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
@ -700,6 +720,14 @@ impl JVM {
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(int >> shift)))?;
}
Instruction::ArithmeticShiftLongLeft() => {
let shift = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))? as u8 % 64;
let long = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
// rust does arithmetic shift on signed values
wrap_stackframe_error(class, method, frame.operand_stack.push_long(long << shift))?;
}
Instruction::ArrayLength() => {
let array_reference = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?;
@ -884,6 +912,19 @@ impl JVM {
Instruction::CheckCast(classref_index) => {
// TODO: Class loading checks
let class_name = class.gather_class(classref_index)?;
if ! class_name.starts_with("[") { // don't load array classes
if ! self.class_store.have_class(class_name) {
// rewind the bytecode offset, I'll need to execute this instruction again
frame.instruction_pointer -= offset as u32;
return Ok(JVMCallbackOperation::LoadClass(class_name.to_string()));
}
if ! self.class_store.was_init(class_name).unwrap() {
// rewind the bytecode offset, I'll need to execute this instruction again
frame.instruction_pointer -= offset as u32;
return Ok(JVMCallbackOperation::InitClass(class_name.to_string()));
}
}
let object = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?;
if object != ObjectReference::NULL {
let native_class_name = self.heap_area.object_area.get_reference_native_class_name(object, &self.class_store);
@ -957,6 +998,13 @@ impl JVM {
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(comparison_result)))?;
}
Instruction::ConvertFloatToDouble() => {
let float = wrap_stackframe_error(class, method, frame.operand_stack.pop_float(0))?;
let double = float as f64;
wrap_stackframe_error(class, method, frame.operand_stack.push_double(double))?;
}
Instruction::ConvertFloatToInt() => {
let float = wrap_stackframe_error(class, method, frame.operand_stack.pop_float(0))?;
let int_value = match float {
@ -965,7 +1013,18 @@ impl JVM {
v @ _ => if v.is_nan() { 0 } else { v as i32 } ,
};
frame.operand_stack.push(StackValue::Int(int_value)).unwrap();
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(int_value)))?;
}
Instruction::ConvertDoubleToLong() => {
let double = wrap_stackframe_error(class, method, frame.operand_stack.pop_double(0))?;
let long = match double {
f64::INFINITY => i64::MAX,
f64::NEG_INFINITY => i64::MIN,
v @ _ => if v.is_nan() { 0 } else { v as i64 }
};
wrap_stackframe_error(class, method, frame.operand_stack.push_long(long))?;
}
Instruction::ConvertIntToByte() => {
@ -1003,6 +1062,21 @@ impl JVM {
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(int_value)))?;
}
Instruction::ConvertLongToFloat() => {
let long_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
let float_value = long_value as f32;
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Float(float_value)))?;
}
Instruction::DivideFloat() => {
// TODO: Obey all the rules
let quotient = wrap_stackframe_error(class, method, frame.operand_stack.pop_float(0))?;
let divident = wrap_stackframe_error(class, method, frame.operand_stack.pop_float(0))?;
frame.operand_stack.push(StackValue::Float(divident / quotient)).unwrap();
}
Instruction::DivideInt() => {
// TODO: Obey all the rules
let quotient = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
@ -1051,10 +1125,10 @@ impl JVM {
// TODO: Are there any methods callable on arrays?
let this_object_class_index = self.heap_area.object_area.get_object_class_index(this_object);
let this_object_class_name = self.class_store.class_name_from_index(this_object_class_index).unwrap().to_string();
let this_object_class_name = self.class_store.class_name_from_index(this_object_class_index).unwrap();
let this_object_descriptor = AbstractTypeDescription {
array_level: 0,
kind: AbstractTypeKind::Classname(this_object_class_name.clone())
kind: AbstractTypeKind::Classname(this_object_class_name.to_string())
};
let object_descriptor = AbstractTypeDescription {
array_level: 0,
@ -1815,6 +1889,9 @@ impl JVM {
wrap_stackframe_error(class, method, frame.operand_stack.pop_computational_1(0))?;
}
Instruction::PushConstDouble1() => {
wrap_stackframe_error(class, method, frame.operand_stack.push_double(1.0))?;
}
Instruction::PushConstFloat0() => {
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Float(0.0)))?;
}