Fix enumeration issue

This commit is contained in:
VegOwOtenks 2024-09-06 15:04:21 +02:00
parent 3c4921aa54
commit 9243c0b291
4 changed files with 62 additions and 57 deletions

View file

@ -91,7 +91,7 @@ impl ClassStore {
return Ok(self.classes.len() - 1); return Ok(self.classes.len() - 1);
} }
pub fn add_native_class_name(&mut self, name: String) -> usize { pub fn add_native_class_descriptor(&mut self, name: String) -> usize {
self.native_class_names.push(name); self.native_class_names.push(name);
return self.native_class_names.len() - 1; return self.native_class_names.len() - 1;
} }

View file

@ -51,21 +51,37 @@ impl HeapArea {
self.memory_used += self.static_area.make(class, class_index); self.memory_used += self.static_area.make(class, class_index);
} }
pub fn byte_array_from_rust_string(&mut self, string: &str, class_store: &ClassStore) -> ObjectReference { pub fn fill_byte_cache(&mut self, class_store: &ClassStore) {
let mut byte_obj_vec = Vec::<ObjectReference>::with_capacity(string.len()); self.memory_used += self.object_area.fill_byte_cache(class_store);
for byte in string.as_bytes() { }
// TODO: Take bytes from ByteCache
let byte_class_idx = class_store.class_idx_from_name(&"java/lang/Byte".to_string()).unwrap(); pub fn make_handmade_string(&mut self, s: &String, class_store: &ClassStore) -> ObjectReference {
let byte_obj = self.make_object(&class_store, byte_class_idx); let utf16_bytes = {
self.object_area.set_object_field(byte_obj, "value", FieldValue::Byte(*byte), byte_class_idx, &class_store).unwrap(); let utf16 = s.encode_utf16();
let mut byte_buffer = Vec::with_capacity(s.len() * 2);
byte_obj_vec.push(byte_obj); for utf16_point in utf16 {
} let bytes = utf16_point.to_ne_bytes();
byte_buffer.push(bytes[0]);
byte_buffer.push(bytes[1]);
}
let byte_array = self.make_array(&class_store, byte_obj_vec.into_boxed_slice()); byte_buffer
};
byte_array let byte_object_refs = utf16_bytes.iter().map(|byte| self.object_area.cached_byte_object(*byte)).collect();
let byte_array_ref = self.make_array(class_store, byte_object_refs);
let string_class_index = class_store.class_idx_from_name(&String::from("java/lang/String")).unwrap();
let string_ref = self.make_object(class_store, string_class_index);
self.object_area.set_object_field(string_ref, "value", FieldValue::Reference(byte_array_ref), string_class_index, class_store).unwrap();
const UTF16_CODER: u8 = 1; // TODO: I don't like this
self.object_area.set_object_field(string_ref, "coder", FieldValue::Byte(UTF16_CODER), string_class_index, class_store).unwrap();
string_ref
} }
} }
@ -83,14 +99,34 @@ const DEFAULT_COMPARTMENT_CAPACITY: u32 = u16::MAX as u32;
const INVALID_FIRST_OBJECT: usize = u16::MAX as usize; const INVALID_FIRST_OBJECT: usize = u16::MAX as usize;
const INVALID_NEXT_COMPARTMENT: usize = 0; const INVALID_NEXT_COMPARTMENT: usize = 0;
#[derive(Default, Debug)] #[derive(Debug, Default)]
pub struct ObjectArea { pub struct ObjectArea {
memory_used: usize, memory_used: usize,
byte_object_cache: Vec<ObjectReference>,
compartments: Vec<ObjectCompartment>, compartments: Vec<ObjectCompartment>,
first_free_compartment: usize, first_free_compartment: usize,
} }
impl ObjectArea { impl ObjectArea {
fn fill_byte_cache(&mut self, class_store: &ClassStore) -> usize {
let byte_class_index = class_store.class_idx_from_name(&String::from("java/lang/Byte")).unwrap();
let mut total_memory_usage = 0;
for byte in 0..=u8::MAX {
let (byte_object_ref, object_memory) = self.make(class_store, byte_class_index);
self.set_object_field(byte_object_ref, "value", FieldValue::Byte(byte), byte_class_index, class_store).unwrap();
self.byte_object_cache.push(byte_object_ref);
total_memory_usage += object_memory;
}
total_memory_usage
}
pub fn cached_byte_object(&mut self, byte: u8) -> ObjectReference {
self.byte_object_cache[byte as usize]
}
fn make_empty_array(&mut self, class_store: &ClassStore, element_type_desc: AbstractTypeDescription, capacity: usize) -> (ObjectReference, usize) { fn make_empty_array(&mut self, class_store: &ClassStore, element_type_desc: AbstractTypeDescription, capacity: usize) -> (ObjectReference, usize) {
// //
// make new type desc // make new type desc
@ -225,8 +261,8 @@ impl ObjectArea {
let field_option = ClassFieldIterator::new(object.class_index, class_store) let field_option = ClassFieldIterator::new(object.class_index, class_store)
.filter(|f| ! (f.access_flags & FieldAccessFlag::Static)) .filter(|f| ! (f.access_flags & FieldAccessFlag::Static))
.filter(|f| f.name == field_name)
.enumerate() .enumerate()
.filter(|(_, f)| f.name == field_name)
.next(); .next();
match field_option { match field_option {
@ -265,8 +301,8 @@ impl ObjectArea {
let field_option = ClassFieldIterator::new(object.class_index, class_store) let field_option = ClassFieldIterator::new(object.class_index, class_store)
.filter(|f| ! (f.access_flags & FieldAccessFlag::Static)) .filter(|f| ! (f.access_flags & FieldAccessFlag::Static))
.filter(|f| f.name == field_name)
.enumerate() .enumerate()
.filter(|(_, f)| f.name == field_name)
.next(); .next();
match field_option { match field_option {

View file

@ -112,7 +112,7 @@ impl JVM {
self.heap_area.object_area.set_object_field( self.heap_area.object_area.set_object_field(
class_data_object, class_data_object,
"native_class_descriptor_index", "native_class_descriptor_index",
FieldValue::Int(self.class_store.add_native_class_name(class_name.to_string()) as i32), FieldValue::Int(self.class_store.add_native_class_descriptor(class_name.to_string()) as i32),
self.class_store.class_idx_from_name(&"::NativeClassData".to_string()).unwrap(), self.class_store.class_idx_from_name(&"::NativeClassData".to_string()).unwrap(),
&self.class_store, &self.class_store,
).unwrap(); ).unwrap();
@ -171,7 +171,7 @@ impl JVM {
self.heap_area.object_area.set_object_field( self.heap_area.object_area.set_object_field(
array_class_data_object, array_class_data_object,
"native_class_descriptor_index", "native_class_descriptor_index",
FieldValue::Int(self.class_store.add_native_class_name((&array_type_description).into()) as i32), FieldValue::Int(self.class_store.add_native_class_descriptor((&array_type_description).into()) as i32),
self.class_store.class_idx_from_name(&"::NativeClassData".to_string()).unwrap(), self.class_store.class_idx_from_name(&"::NativeClassData".to_string()).unwrap(),
&self.class_store, &self.class_store,
).unwrap(); ).unwrap();
@ -288,7 +288,7 @@ impl JVM {
]), ]),
attributes: Box::new([]), attributes: Box::new([]),
}; };
let entry_frame = StackFrame::new(&entry_class, 0, 0, &[]);
self.class_store.add_class(entry_class, true)?; // 0 self.class_store.add_class(entry_class, true)?; // 0
self.class_store.add_class(JVM::class_native_class_data(), true)?; // 1 self.class_store.add_class(JVM::class_native_class_data(), true)?; // 1
self.class_store.load_class(&"java/lang/Object".to_string())?; // 2 self.class_store.load_class(&"java/lang/Object".to_string())?; // 2
@ -302,23 +302,16 @@ impl JVM {
self.make_array_class("Ljava/lang/Byte;"); self.make_array_class("Ljava/lang/Byte;");
self.make_array_class("Ljava/lang/String;"); self.make_array_class("Ljava/lang/String;");
let argument_array = self.heap_area.make_empty_array(&self.class_store, AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/String".into()) }, arguments.len()); self.heap_area.fill_byte_cache(&self.class_store);
for (arg_index, argument) in arguments.iter().enumerate() {
let byte_array = self.heap_area.byte_array_from_rust_string(argument, &self.class_store);
self.stack_frames.push(
StackFrame::new(
self.class_store.get_class(&"::EntryPoint".to_string()).unwrap().0,
self.class_store.class_idx_from_name(&"::EntryPoint".to_string()).unwrap(),
1, // method index
&[StackValue::Reference(byte_array), StackValue::Reference(argument_array), StackValue::Int(arg_index as i32)],
)
);
self.run()?; let string_refs = arguments.iter()
} .map(|s| self.heap_area.make_handmade_string(&s.to_string(), &self.class_store))
.collect();
let argument_array_ref = self.heap_area.make_array(&self.class_store, string_refs);
// push the entry frame which will call main // push the entry frame which will call main
let entry_frame = StackFrame::new(self.class_store.get_class(&String::from("::EntryPoint")).unwrap().0, 0, 0, &[StackValue::Reference(argument_array_ref)]);
self.stack_frames.push(entry_frame); self.stack_frames.push(entry_frame);
Ok(()) Ok(())
@ -481,31 +474,7 @@ impl JVM {
if name == "java/lang/String" { if name == "java/lang/String" {
let string_entry = class_file.gather_string(constant_value_info.constant_value_index)?; let string_entry = class_file.gather_string(constant_value_info.constant_value_index)?;
let (string_class_file, string_class_index) = self.class_store.get_class(name).unwrap(); let string_object = self.heap_area.make_handmade_string(string_entry, &self.class_store);
let string_object = self.heap_area.make_object(&self.class_store, string_class_index);
// TODO: Review this if it looks like there will be stack
// overflows in initialization
let string_init_function_index = match ClassMethodIterator::new(string_class_index, &self.class_store)
.filter(|( cid, _mid, _minfo)| *cid == string_class_index)
.filter(|(_cid, _mid, minfo)| minfo.name == "<init>")
.filter(|(_cid, _mid, minfo)| minfo.descriptor.argument_types.len() == 1)
.filter(|(_cid, _mid, minfo)| minfo.descriptor.argument_types[0] == AbstractTypeDescription { array_level: 1, kind: AbstractTypeKind::Byte() })
.next() {
Some((_, method_index, _)) => method_index,
None => unreachable!(),
};
let byte_array = self.heap_area.byte_array_from_rust_string(string_entry, &self.class_store);
self.stack_frames.push(
StackFrame::new(
string_class_file,
string_class_index,
string_init_function_index as u16,
&[StackValue::Reference(byte_array)],
)
);
FieldValue::Reference(string_object) FieldValue::Reference(string_object)
} else { } else {

View file

@ -15,7 +15,7 @@ use crate::accessmasks::FieldAccessFlag;
use crate::classfile::JavaClassFile; use crate::classfile::JavaClassFile;
fn main() { fn main() {
//println!("{:#?}", JavaClassFile::new(&mut File::open("java/Main.class").unwrap()).unwrap()); //println!("{:#?}", JavaClassFile::new(&mut File::open("java/lang/String.class").unwrap()).unwrap().fields.iter().filter(|f| ! (f.access_flags & FieldAccessFlag::Static)).collect::<Vec<_>>());
let mut jvm = jvm::JVM::new(); let mut jvm = jvm::JVM::new();