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);
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
51
src/jvm.rs
51
src/jvm.rs
|
@ -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 {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue