Real classes for arrays, initialization order
This commit is contained in:
parent
70a11283db
commit
5cf17d5ca3
4 changed files with 160 additions and 35 deletions
85
src/jvm.rs
85
src/jvm.rs
|
@ -12,7 +12,7 @@ use crate::classstore;
|
|||
use crate::classstore::ClassStore;
|
||||
use crate::constantpool::{ ConstantClassInfo, ConstantInterfaceMethodRefInfo, ConstantMethodRefInfo, ConstantNameAndTypeInfo, ConstantPoolInfo, ConstantUtf8Info};
|
||||
use crate::heap_area::{ HeapArea, FieldValue, ObjectReference, CompartmentEntry };
|
||||
use crate::iterators::{ ClassMethodIterator, ClassFieldIterator };
|
||||
use crate::iterators::{ ClassFieldIterator, ClassMethodIterator, CompatibleTypesIterator };
|
||||
use crate::native_methods;
|
||||
use crate::native_methods::EntryPoint;
|
||||
use crate::native_registry::NativeRegistry;
|
||||
|
@ -188,6 +188,31 @@ impl JVM {
|
|||
self.class_store.class_idx_from_name(&"::NativeClassData".to_string()).unwrap(),
|
||||
&self.class_store,
|
||||
).unwrap();
|
||||
|
||||
let array_class_file = JavaClassFile {
|
||||
minor_version: 0,
|
||||
major_version: 63,
|
||||
constant_pool: Box::new(
|
||||
[
|
||||
ConstantPoolInfo::Class(ConstantClassInfo { name_index: 2 }),
|
||||
ConstantPoolInfo::Utf8(ConstantUtf8Info { utf8: (&array_type_description).into() }),
|
||||
ConstantPoolInfo::Class(ConstantClassInfo { name_index: 4 }),
|
||||
ConstantPoolInfo::Utf8(ConstantUtf8Info { utf8: "java/lang/Object".to_string() }),
|
||||
]
|
||||
),
|
||||
access_flags: ClassAccessFlagMask {
|
||||
mask: ClassAccessFlag::Public.discriminant() | ClassAccessFlag::Synthetic.discriminant()
|
||||
},
|
||||
this_class: 1,
|
||||
super_class: 3,
|
||||
interfaces: Box::new([]),
|
||||
fields: Box::new([]),
|
||||
methods: Box::new([]),
|
||||
attributes: Box::new([]),
|
||||
};
|
||||
|
||||
self.class_store.add_class(array_class_file, true).unwrap();
|
||||
|
||||
self.class_store.put_array_class_ref(
|
||||
array_type_description,
|
||||
array_class_object,
|
||||
|
@ -557,30 +582,18 @@ impl JVM {
|
|||
}
|
||||
|
||||
fn init_class_hierarchy(&mut self, name: &String) -> Result<(), Error> {
|
||||
let mut class_stack = vec![name.to_string()];
|
||||
// TODO: Work around the clones
|
||||
|
||||
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()
|
||||
}
|
||||
};
|
||||
let mut current_name = name.clone();
|
||||
|
||||
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());
|
||||
while ! self.class_store.was_init(¤t_name).unwrap() {
|
||||
let class_index = self.class_store.class_idx_from_name(¤t_name).unwrap();
|
||||
self.init_class(class_index)?;
|
||||
|
||||
let class_file = self.class_store.class_file_from_idx(class_index).unwrap();
|
||||
|
||||
if class_file.has_super_class() {
|
||||
current_name = class_file.get_super_class_name().unwrap().clone();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1310,11 +1323,31 @@ impl JVM {
|
|||
return Ok(JVMCallbackOperation::InitClass(class_name.to_string()));
|
||||
}
|
||||
|
||||
let class_index = self.class_store.class_idx_from_name(class_name).unwrap();
|
||||
let owning_class = CompatibleTypesIterator::new(class_index, &self.class_store)
|
||||
.filter(|name| {
|
||||
let index = self.class_store.class_idx_from_name(name).unwrap();
|
||||
let class_file = self.class_store.class_file_from_idx(index).unwrap();
|
||||
class_file.fields.iter()
|
||||
.filter(|finfo| finfo.access_flags & FieldAccessFlag::Static)
|
||||
.filter(|finfo| finfo.name == *field_name)
|
||||
.next()
|
||||
.is_some()
|
||||
})
|
||||
.next()
|
||||
.unwrap_or_else(|| class_name);
|
||||
|
||||
if ! self.class_store.was_init(owning_class).unwrap() {
|
||||
// rewind the bytecode offset, I'll need to execute this instruction again
|
||||
frame.instruction_pointer -= offset as u32;
|
||||
return Ok(JVMCallbackOperation::InitClass(owning_class.to_string()));
|
||||
}
|
||||
|
||||
// TODO: Throw error
|
||||
let parsed_field_descriptor = AbstractTypeDescription::parse_full(field_descriptor).unwrap();
|
||||
|
||||
// TODO: Throw error
|
||||
let fetched_value = self.heap_area.static_area.get(class_name, field_name, parsed_field_descriptor).unwrap();
|
||||
let fetched_value = self.heap_area.static_area.get(owning_class, field_name, parsed_field_descriptor).unwrap();
|
||||
|
||||
wrap_stackframe_error(class, method, frame.operand_stack.push_field_value(fetched_value))?;
|
||||
}
|
||||
|
@ -1569,8 +1602,8 @@ impl JVM {
|
|||
let this_object = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?;
|
||||
arguments.push_front(StackValue::Reference(this_object));
|
||||
|
||||
// TODO: Are there any methods callable on arrays?
|
||||
let this_object_class_index = self.heap_area.object_area.get_object_class_index(this_object);
|
||||
// Are there any methods callable on arrays?, turns out there are
|
||||
let this_object_class_index = self.heap_area.object_area.get_reference_class_index(this_object, &self.class_store);
|
||||
let this_object_class_name = self.class_store.class_name_from_index(this_object_class_index).unwrap().to_string();
|
||||
let this_object_descriptor = AbstractTypeDescription {
|
||||
array_level: 0,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue