Fix enumeration issue
This commit is contained in:
parent
3c4921aa54
commit
9243c0b291
4 changed files with 62 additions and 57 deletions
|
@ -91,7 +91,7 @@ impl ClassStore {
|
|||
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);
|
||||
return self.native_class_names.len() - 1;
|
||||
}
|
||||
|
|
|
@ -51,21 +51,37 @@ impl HeapArea {
|
|||
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 {
|
||||
let mut byte_obj_vec = Vec::<ObjectReference>::with_capacity(string.len());
|
||||
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();
|
||||
let byte_obj = self.make_object(&class_store, byte_class_idx);
|
||||
self.object_area.set_object_field(byte_obj, "value", FieldValue::Byte(*byte), byte_class_idx, &class_store).unwrap();
|
||||
|
||||
byte_obj_vec.push(byte_obj);
|
||||
pub fn fill_byte_cache(&mut self, class_store: &ClassStore) {
|
||||
self.memory_used += self.object_area.fill_byte_cache(class_store);
|
||||
}
|
||||
|
||||
let byte_array = self.make_array(&class_store, byte_obj_vec.into_boxed_slice());
|
||||
pub fn make_handmade_string(&mut self, s: &String, class_store: &ClassStore) -> ObjectReference {
|
||||
let utf16_bytes = {
|
||||
let utf16 = s.encode_utf16();
|
||||
let mut byte_buffer = Vec::with_capacity(s.len() * 2);
|
||||
|
||||
byte_array
|
||||
for utf16_point in utf16 {
|
||||
let bytes = utf16_point.to_ne_bytes();
|
||||
byte_buffer.push(bytes[0]);
|
||||
byte_buffer.push(bytes[1]);
|
||||
}
|
||||
|
||||
byte_buffer
|
||||
};
|
||||
|
||||
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_NEXT_COMPARTMENT: usize = 0;
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct ObjectArea {
|
||||
memory_used: usize,
|
||||
byte_object_cache: Vec<ObjectReference>,
|
||||
compartments: Vec<ObjectCompartment>,
|
||||
first_free_compartment: usize,
|
||||
}
|
||||
|
||||
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) {
|
||||
//
|
||||
// make new type desc
|
||||
|
@ -225,8 +261,8 @@ impl ObjectArea {
|
|||
|
||||
let field_option = ClassFieldIterator::new(object.class_index, class_store)
|
||||
.filter(|f| ! (f.access_flags & FieldAccessFlag::Static))
|
||||
.filter(|f| f.name == field_name)
|
||||
.enumerate()
|
||||
.filter(|(_, f)| f.name == field_name)
|
||||
.next();
|
||||
|
||||
match field_option {
|
||||
|
@ -265,8 +301,8 @@ impl ObjectArea {
|
|||
|
||||
let field_option = ClassFieldIterator::new(object.class_index, class_store)
|
||||
.filter(|f| ! (f.access_flags & FieldAccessFlag::Static))
|
||||
.filter(|f| f.name == field_name)
|
||||
.enumerate()
|
||||
.filter(|(_, f)| f.name == field_name)
|
||||
.next();
|
||||
|
||||
match field_option {
|
||||
|
|
51
src/jvm.rs
51
src/jvm.rs
|
@ -112,7 +112,7 @@ impl JVM {
|
|||
self.heap_area.object_area.set_object_field(
|
||||
class_data_object,
|
||||
"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,
|
||||
).unwrap();
|
||||
|
@ -171,7 +171,7 @@ impl JVM {
|
|||
self.heap_area.object_area.set_object_field(
|
||||
array_class_data_object,
|
||||
"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,
|
||||
).unwrap();
|
||||
|
@ -288,7 +288,7 @@ impl JVM {
|
|||
]),
|
||||
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(JVM::class_native_class_data(), true)?; // 1
|
||||
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/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());
|
||||
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.heap_area.fill_byte_cache(&self.class_store);
|
||||
|
||||
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
|
||||
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);
|
||||
|
||||
Ok(())
|
||||
|
@ -481,31 +474,7 @@ impl JVM {
|
|||
if name == "java/lang/String" {
|
||||
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_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)],
|
||||
)
|
||||
);
|
||||
let string_object = self.heap_area.make_handmade_string(string_entry, &self.class_store);
|
||||
|
||||
FieldValue::Reference(string_object)
|
||||
} else {
|
||||
|
|
|
@ -15,7 +15,7 @@ use crate::accessmasks::FieldAccessFlag;
|
|||
use crate::classfile::JavaClassFile;
|
||||
|
||||
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();
|
||||
|
||||
|
|
Loading…
Reference in a new issue