Class loading, object creation
This commit is contained in:
parent
25d3509ccf
commit
4dabd6c3a8
5 changed files with 235 additions and 39 deletions
107
src/jvm.rs
107
src/jvm.rs
|
@ -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(¤t_super)?;
|
||||
super_file.has_super_class()
|
||||
};
|
||||
|
||||
if have_super_super {
|
||||
let super_super_name = {
|
||||
let (super_file, _) = self.class_store.get_class(¤t_super)?;
|
||||
super_file.get_super_class_name()?
|
||||
};
|
||||
if self.class_store.have_class(super_super_name) {
|
||||
self.class_store.load_class(¤t_super)?;
|
||||
} else {
|
||||
super_classes.push(current_super);
|
||||
super_classes.push(super_super_name.to_string());
|
||||
}
|
||||
} else {
|
||||
self.class_store.load_class(¤t_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(¤t_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(¤t_name).unwrap();
|
||||
self.init_class(class_idx)?;
|
||||
} else {
|
||||
let super_name = {
|
||||
let (file, _) = self.class_store.get_class(¤t_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 = {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue