Class loading, object creation

This commit is contained in:
VegOwOtenks 2024-09-03 00:49:28 +02:00
parent 25d3509ccf
commit 4dabd6c3a8
5 changed files with 235 additions and 39 deletions

View file

@ -10,7 +10,7 @@ use crate::classfile::{ JavaClassFile, MethodInfo, MethodDescriptor, AbstractTyp
use crate::classstore;
use crate::classstore::ClassStore;
use crate::constantpool::{ ConstantPoolInfo, ConstantClassInfo, ConstantUtf8Info, ConstantMethodRefInfo, ConstantNameAndTypeInfo};
use crate::heap_area::{ HeapArea, FieldValue };
use crate::heap_area::{ HeapArea, FieldValue, ObjectReference };
use crate::stackframe;
use crate::stackframe::{ StackFrame, StackValue, OperandStack };
@ -128,6 +128,10 @@ impl JVM {
);
self.class_store.add_class(entry_class, true);
self.class_store.load_class(&"java/lang/Class".to_string())?;
self.class_store.load_class(&"java/lang/Object".to_string())?;
self.new_object(&"java/lang/Class".to_string())?;
Ok(())
}
@ -156,12 +160,13 @@ impl JVM {
JVMCallbackOperation::PushFrame(frame) => self.stack_frames.push(frame),
JVMCallbackOperation::LoadClass(name) => {
self.class_store.load_class(&name)?;
()
// TODO: throw exception
self.load_class_hierarchy(&name)?;
},
JVMCallbackOperation::InitClass(name) => {
self.init_class(*self.class_store.class_idx_from_name(&name).unwrap())?;
// TODO: throw exception
self.init_class_hierarchy(&name)?;
}
}
}
@ -169,13 +174,82 @@ impl JVM {
Ok(())
}
pub fn init_class(&mut self, class_idx: usize) -> Result<(), Error> {
fn new_object(&mut self, class_name: &String) -> Result<ObjectReference, Error> {
let (_, class_idx) = self.class_store.get_class(class_name)?;
Ok(self.heap_area.make_object(&mut self.class_store, class_idx))
}
fn load_class_hierarchy(&mut self, name: &String) -> Result<(), Error> {
self.class_store.load_class(&name)?;
let super_class_name = {
let (file, _) = self.class_store.get_class(&name)?;
file.get_super_class_name()?.clone()
};
let mut super_classes = vec![super_class_name];
while super_classes.len() != 0 {
let current_super = super_classes.pop().unwrap();
let have_super_super = {
let (super_file, _) = self.class_store.get_class(&current_super)?;
super_file.has_super_class()
};
if have_super_super {
let super_super_name = {
let (super_file, _) = self.class_store.get_class(&current_super)?;
super_file.get_super_class_name()?
};
if self.class_store.have_class(super_super_name) {
self.class_store.load_class(&current_super)?;
} else {
super_classes.push(current_super);
super_classes.push(super_super_name.to_string());
}
} else {
self.class_store.load_class(&current_super)?;
}
}
Ok(())
}
fn init_class_hierarchy(&mut self, name: &String) -> Result<(), Error> {
let mut class_stack = vec![name.to_string()];
while class_stack.len() != 0 {
let current_name = class_stack.pop().unwrap();
let was_super_init = {
let (file, _) = self.class_store.get_class(&current_name)?;
if ! file.has_super_class() {
true
} else {
let super_name = file.get_super_class_name()?;
self.class_store.was_init(super_name).unwrap()
}
};
if was_super_init {
let class_idx = self.class_store.class_idx_from_name(&current_name).unwrap();
self.init_class(class_idx)?;
} else {
let super_name = {
let (file, _) = self.class_store.get_class(&current_name)?;
file.get_super_class_name()?
};
class_stack.push(current_name);
class_stack.push(super_name.to_string());
}
}
Ok(())
}
fn init_class(&mut self, class_idx: usize) -> Result<(), Error> {
let class_file = self.class_store.class_file_from_idx(class_idx).unwrap();
let clinit_idx = class_file.find_method_index(&"<clinit>".to_string());
self.heap_area.make_static(class_file, class_idx);
// TODO: ConstantValue Attributes (final)
for field in &class_file.fields {
if field.access_flags & FieldAccessFlag::Static {
let cvalue_attrs: Vec<&ConstantValueAttributeData> = (&field.attributes).iter()
@ -211,7 +285,7 @@ impl JVM {
_ => todo!()
};
self.heap_area.static_area.set(&class_file.get_classname()?, &field.name, field_value)?;
self.heap_area.static_area.set(class_file.get_classname()?, &field.name, field_value)?;
}
}
}
@ -223,25 +297,6 @@ impl JVM {
Ok(())
}
fn prepare_invoke_static(&mut self, class_index: usize, method_name: &String, arguments: &[StackValue]) -> Result<(), Error> {
let class_file = self.class_store.class_file_from_idx(class_index).unwrap();
let method_index = class_file.find_method_index(method_name)
.ok_or(Error::BadNameError(format!("Could not find method '{}' in class '{}'", method_name, class_file.get_classname()?)))?;
let new_frame = StackFrame::new(
class_file,
class_index,
method_index.try_into().expect(&format!("Bad method index: {}", method_index)),
arguments
);
self.stack_frames.push(new_frame);
return Ok(());
}
fn bytecode_loop(&mut self) -> Result<JVMCallbackOperation, Error> {
let frame = {