Working up until registerNatives()

This commit is contained in:
vegowotenks 2024-09-06 23:51:35 +02:00
parent 5bc0d813e5
commit 3282694b32
4 changed files with 268 additions and 58 deletions

View file

@ -10,8 +10,8 @@ use crate::classfile::{ JavaClassFile, FieldInfo, MethodInfo, MethodDescriptor,
use crate::classstore;
use crate::classstore::ClassStore;
use crate::constantpool::{ ConstantPoolInfo, ConstantClassInfo, ConstantUtf8Info, ConstantMethodRefInfo, ConstantNameAndTypeInfo};
use crate::heap_area::{ HeapArea, FieldValue, ObjectReference };
use crate::iterators::{ ClassMethodIterator, ClassFieldIterator, CompatibleTypesIterator };
use crate::heap_area::{ HeapArea, FieldValue, ObjectReference, CompartmentEntry };
use crate::iterators::{ ClassMethodIterator, ClassFieldIterator };
use crate::stackframe;
use crate::stackframe::{ StackFrame, StackValue, OperandStack };
@ -129,21 +129,8 @@ impl JVM {
self.class_store.set_class_objectref_by_index(self.class_store.class_idx_from_name(&parsed_class_name).unwrap(), class_object);
}
fn make_array_class(&mut self, element_descriptor_string: &str) {
let (chars_consumed, element_descriptor) = AbstractTypeDescription::parse_first(element_descriptor_string).unwrap();
assert!(chars_consumed == element_descriptor_string.len());
let element_class_ref = if element_descriptor.array_level == 0 {
match element_descriptor.kind {
AbstractTypeKind::Classname(ref name) => {
self.class_store.get_class_objectref_from_index(
self.class_store.class_idx_from_name(&name).unwrap()
)
}
_ => unreachable!(),
}
} else {
self.class_store.get_array_class_ref(&element_descriptor).unwrap()
};
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_data_object = self.heap_area.make_object(&self.class_store, 1);
@ -156,7 +143,7 @@ impl JVM {
array_class_object,
"componentType",
FieldValue::Reference(element_class_ref),
self.class_store.class_idx_from_name(&"java/lang/Class".to_string()).unwrap(),
class_class_index,
&self.class_store,
).unwrap();
// set classdata object
@ -164,7 +151,7 @@ impl JVM {
array_class_object,
"classData",
FieldValue::Reference(array_class_data_object),
self.class_store.class_idx_from_name(&"java/lang/Class".to_string()).unwrap(),
class_class_index,
&self.class_store,
).unwrap();
// set native name index on class data
@ -181,6 +168,46 @@ impl JVM {
);
}
fn make_primitive_class(&mut self, class_name: &str, class_descriptor: &str) -> ObjectReference {
let class_class_index = self.class_store.class_idx_from_name(&String::from("java/lang/Class")).unwrap();
let data_class_index = self.class_store.class_idx_from_name(&String::from("::NativeClassData")).unwrap();
let primitive_class_object = self.heap_area.make_object(&self.class_store, class_class_index);
let primitive_class_data_object = self.heap_area.make_object(&self.class_store, data_class_index);
// set classdata object
self.heap_area.object_area.set_object_field(
primitive_class_object,
"classData",
FieldValue::Reference(primitive_class_data_object),
class_class_index,
&self.class_store,
).unwrap();
let name_string_ref = self.heap_area.make_handmade_string(&class_name.into(), &self.class_store);
// set name string object
self.heap_area.object_area.set_object_field(
primitive_class_object,
"name",
FieldValue::Reference(name_string_ref),
class_class_index,
&self.class_store,
).unwrap();
// set native name index on class data
self.heap_area.object_area.set_object_field(
primitive_class_data_object,
"native_class_descriptor_index",
FieldValue::Int(self.class_store.add_native_class_descriptor(class_descriptor.into()) as i32),
self.class_store.class_idx_from_name(&"::NativeClassData".to_string()).unwrap(),
&self.class_store,
).unwrap();
// TODO: Set Static
primitive_class_object
}
pub fn entrypoint(&mut self, class_name: &String, method_name: &String, arguments: &[&str]) -> Result<(), Error> {
let entry_class = JavaClassFile {
minor_version: 0,
@ -259,11 +286,42 @@ impl JVM {
self.make_class_class("Ljava/lang/Byte;");
self.make_class_class("Ljava/lang/String;");
self.make_array_class("Ljava/lang/Byte;");
self.make_array_class("Ljava/lang/String;");
self.make_array_class(
self.class_store.get_class_objectref_from_index(4),
AbstractTypeDescription {
array_level: 0,
kind: AbstractTypeKind::Classname("java/lang/Byte".into()),
}
);
self.make_array_class(
self.class_store.get_class_objectref_from_index(5),
AbstractTypeDescription {
array_level: 0,
kind: AbstractTypeKind::Classname("java/lang/String".into()),
}
);
self.heap_area.fill_byte_cache(&self.class_store);
let int_class_ref = self.make_primitive_class("int", "I");
let byte_class_ref = self.make_primitive_class("byte", "B");
self.make_array_class(
int_class_ref,
AbstractTypeDescription {
array_level: 0,
kind: AbstractTypeKind::Int(),
}
);
self.make_array_class(
byte_class_ref,
AbstractTypeDescription {
array_level: 0,
kind: AbstractTypeKind::Byte(),
}
);
let string_refs = arguments.iter()
.map(|s| self.heap_area.make_handmade_string(&s.to_string(), &self.class_store))
.collect();
@ -312,8 +370,8 @@ impl JVM {
self.init_class_hierarchy(&name)?;
},
JVMCallbackOperation::MakeArrayClass(component_descriptor_string) => {
self.make_array_class(&component_descriptor_string);
JVMCallbackOperation::MakeArrayClass(component_class_ref, component_descriptor) => {
self.make_array_class(component_class_ref, component_descriptor);
}
}
}
@ -519,6 +577,16 @@ impl JVM {
frame.instruction_pointer = if branch_offset < 0 { frame.instruction_pointer - branch_offset.abs() as u32} else { frame.instruction_pointer + branch_offset.abs() as u32};
}
Instruction::BranchIntInequality(branch_offset) => {
let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
if value_1 != value_2 {
frame.instruction_pointer -= offset as u32;
frame.instruction_pointer = if branch_offset < 0 { frame.instruction_pointer - branch_offset.abs() as u32} else { frame.instruction_pointer + branch_offset.abs() as u32};
}
}
Instruction::BranchZero(branch_offset) => {
let test_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
@ -783,6 +851,21 @@ impl JVM {
}
},
Instruction::LoadWideConstant(wide_index) => {
// TODO: Handle error instead of unwrap
match class.pool_entry(wide_index).unwrap() {
ConstantPoolInfo::String(_) => {
// TODO: Handle error instead of unwrap
let string_constant = class.gather_string(wide_index).unwrap();
let string_obj_ref = self.heap_area.make_handmade_string(string_constant, &self.class_store);
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Reference(string_obj_ref)))?;
},
_ => todo!(),
}
},
Instruction::LoadLocalInt0() => {
load_local_int(class, method, frame, 0)?;
}
@ -815,44 +898,61 @@ impl JVM {
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(factor_1 * factor_2)))?;
}
Instruction::NewArray(class_index) => {
Instruction::NewArray(component_class_index) => {
// construct single level array
let class_name = class.gather_class(class_index)?;
let component_class_name = class.gather_class(component_class_index)?;
if ! self.class_store.have_class(class_name) {
if ! self.class_store.have_class(component_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()));
return Ok(JVMCallbackOperation::LoadClass(component_class_name.to_string()));
}
if ! self.class_store.was_init(class_name).unwrap() {
if ! self.class_store.was_init(component_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()));
return Ok(JVMCallbackOperation::InitClass(component_class_name.to_string()));
}
let class_descriptor = AbstractTypeDescription {
let component_class_descriptor = AbstractTypeDescription {
array_level: 0,
kind: match class_name {
_ => AbstractTypeKind::Classname(class_name.to_string())
kind: match component_class_name {
_ => AbstractTypeKind::Classname(component_class_name.to_string())
}
};
let array_descriptor = AbstractTypeDescription {
array_level: 1,
kind: class_descriptor.kind.clone(),
kind: component_class_descriptor.kind.clone(),
};
if let None = self.class_store.get_array_class_ref(&array_descriptor) {
let complete_type_descriptor = format!("L{};", class_name);
// rewind the bytecode offset, I'll need to execute this instruction again
frame.instruction_pointer -= offset as u32;
return Ok(JVMCallbackOperation::MakeArrayClass(complete_type_descriptor));
let component_class_index = self.class_store.class_idx_from_name(component_class_name).unwrap();
let component_class_class_ref = self.class_store.get_class_objectref_from_index(component_class_index);
return Ok(JVMCallbackOperation::MakeArrayClass(component_class_class_ref, component_class_descriptor));
}
let array_capacity = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
let array_ref = self.heap_area.make_empty_array(&self.class_store, class_descriptor, array_capacity as usize);
let array_ref = self.heap_area.make_empty_array(&self.class_store, component_class_descriptor, array_capacity as usize);
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Reference(array_ref)))?;
}
Instruction::NewPrimitiveArray(array_type) => {
let array_capacity = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
const BYTE: u8 = 8;
let array_ref = match array_type {
BYTE => {
let array_ref = self.heap_area.make_primitive_byte_array(array_capacity as usize, &self.class_store);
array_ref
}
_ => todo!()
};
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Reference(array_ref)))?;
}
@ -990,6 +1090,36 @@ impl JVM {
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(int >> shift)))?;
},
Instruction::StoreIntoRArray() => {
let value = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?;
let index = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
let array_ref = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?;
// TODO: Type checking
self.heap_area.object_area.set_array_element(array_ref, index as usize, FieldValue::Reference(value));
}
Instruction::StoreIntoBArray() => {
let value = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
let index = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
let array_ref = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?;
match self.heap_area.object_area.get_entry(array_ref) {
CompartmentEntry::ByteArray(_) => {
let byte_value = value.to_ne_bytes()[3];
self.heap_area.object_area.set_array_element(array_ref, index as usize, FieldValue::Byte(byte_value));
}
_ => todo!(), // TODO: Handle as error, Boolean arrays also
}
}
Instruction::StoreLocalInt(index) => {
let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
wrap_stackframe_error(class, method, frame.store_local(index as u16, StackValue::Int(int)))?;
},
Instruction::StoreLocalInt0() => {
let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
@ -1051,7 +1181,7 @@ enum JVMCallbackOperation {
PushFrame(StackFrame),
LoadClass(String),
InitClass(String),
MakeArrayClass(String),
MakeArrayClass(ObjectReference, AbstractTypeDescription),
}
fn load_local_reference(class: &JavaClassFile, method: &MethodInfo, frame: &mut StackFrame, index: usize) -> Result<(), Error> {