Class loading, object creation
This commit is contained in:
parent
25d3509ccf
commit
4dabd6c3a8
5 changed files with 235 additions and 39 deletions
134
src/heap_area.rs
134
src/heap_area.rs
|
@ -1,7 +1,10 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use core::fmt::Debug as DebugTrait;
|
||||
|
||||
use crate::accessmasks::FieldAccessFlag;
|
||||
use crate::classfile::{ JavaClassFile, AbstractTypeDescription, MethodInfo, AbstractTypeKind };
|
||||
use crate::classstore::ClassStore;
|
||||
use crate::jvm::Error;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -22,6 +25,13 @@ impl HeapArea {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn make_object(&mut self, class_store: &ClassStore, class_index: usize) -> ObjectReference {
|
||||
let (object_ref, object_size) = self.object_area.make(class_store, class_index);
|
||||
self.memory_used += object_size;
|
||||
|
||||
return object_ref;
|
||||
}
|
||||
|
||||
pub fn make_static(&mut self, class: &JavaClassFile, class_index: usize) {
|
||||
self.memory_used += self.static_area.make(class, class_index);
|
||||
}
|
||||
|
@ -30,27 +40,144 @@ impl HeapArea {
|
|||
pub type ObjectReference=u32;
|
||||
|
||||
const DEFAULT_COMPARTMENT_CAPACITY: usize = u16::MAX as usize;
|
||||
const INVALID_FIRST_OBJECT: usize = u16::MAX as usize;
|
||||
const INVALID_NEXT_COMPARTMENT: usize = 0;
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct ObjectArea {
|
||||
compartments: Vec<ObjectCompartment>,
|
||||
first_free_compartment: usize,
|
||||
}
|
||||
|
||||
impl ObjectArea {
|
||||
pub fn make(&mut self, class_store: &ClassStore, target_class_index: usize) -> (ObjectReference, usize) {
|
||||
let mut fields = Vec::new();
|
||||
let mut current_class_index;
|
||||
let mut next_class_index = target_class_index;
|
||||
|
||||
let mut object_size = 0;
|
||||
|
||||
while next_class_index != class_store.class_count() {
|
||||
current_class_index = next_class_index;
|
||||
|
||||
let class = class_store.class_file_from_idx(current_class_index).unwrap();
|
||||
|
||||
for field in &class.fields {
|
||||
let new_field = ObjectField {
|
||||
value: FieldValue::default_for(&field.descriptor)
|
||||
};
|
||||
object_size += std::mem::size_of_val(&new_field);
|
||||
|
||||
fields.push(new_field);
|
||||
}
|
||||
|
||||
if class.has_super_class() {
|
||||
next_class_index = class_store.class_idx_from_name(class.get_super_class_name().unwrap()).unwrap();
|
||||
} else {
|
||||
next_class_index = class_store.class_count();
|
||||
}
|
||||
}
|
||||
|
||||
let new_object = HeapObject {
|
||||
class_index: target_class_index,
|
||||
fields: fields.into_boxed_slice(),
|
||||
};
|
||||
|
||||
object_size += std::mem::size_of_val(&new_object);
|
||||
object_size += std::mem::size_of_val(&new_object.fields);
|
||||
|
||||
let object_ref = self.store_object(new_object);
|
||||
|
||||
return (object_ref, object_size);
|
||||
}
|
||||
|
||||
fn store_object(&mut self, object: HeapObject) -> ObjectReference {
|
||||
if self.first_free_compartment == 0 {
|
||||
self.compartments.push(ObjectCompartment::new(INVALID_NEXT_COMPARTMENT));
|
||||
self.first_free_compartment = self.compartments.len();
|
||||
}
|
||||
|
||||
let compartment_index = self.first_free_compartment - 1;
|
||||
let object_index = self.compartments.get_mut(compartment_index).unwrap().store(object);
|
||||
if self.compartments[compartment_index].first_free == INVALID_FIRST_OBJECT {
|
||||
self.first_free_compartment = self.compartments[compartment_index].next_free_compartment;
|
||||
}
|
||||
|
||||
return object_index + (DEFAULT_COMPARTMENT_CAPACITY as u32 * (compartment_index+1) as u32);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ObjectCompartment {
|
||||
objects: Box<[ObjectCompartmentEntry]>,
|
||||
first_free: usize,
|
||||
reserved_count: usize,
|
||||
next_free_compartment: usize,
|
||||
}
|
||||
|
||||
impl ObjectCompartment {
|
||||
fn new(next_free: usize) -> Self {
|
||||
let mut os = Vec::with_capacity(DEFAULT_COMPARTMENT_CAPACITY);
|
||||
for i in 0..DEFAULT_COMPARTMENT_CAPACITY-1 {
|
||||
os.push(ObjectCompartmentEntry::EmptyNext(i+1));
|
||||
}
|
||||
os.push(ObjectCompartmentEntry::EmptyTail());
|
||||
|
||||
ObjectCompartment {
|
||||
objects: os.into_boxed_slice(),
|
||||
first_free: 0,
|
||||
reserved_count: 0,
|
||||
next_free_compartment: next_free,
|
||||
}
|
||||
}
|
||||
|
||||
fn store(&mut self, object: HeapObject) -> ObjectReference {
|
||||
let store_slot = self.objects.get(self.first_free).unwrap();
|
||||
let compartment_index = self.first_free;
|
||||
|
||||
match store_slot {
|
||||
ObjectCompartmentEntry::Valid(_) => unreachable!(),
|
||||
ObjectCompartmentEntry::EmptyNext(next) => {
|
||||
self.first_free = *next;
|
||||
},
|
||||
ObjectCompartmentEntry::EmptyTail() => {
|
||||
// TODO: Maybe change to something else
|
||||
self.first_free = INVALID_FIRST_OBJECT;
|
||||
},
|
||||
}
|
||||
|
||||
*self.objects.get_mut(compartment_index).unwrap() = ObjectCompartmentEntry::Valid(object);
|
||||
self.reserved_count += 1;
|
||||
|
||||
return compartment_index as u32;
|
||||
}
|
||||
}
|
||||
|
||||
impl DebugTrait for ObjectCompartment {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||
f.debug_struct("ObjectCompartment")
|
||||
.field("first_free", &self.first_free)
|
||||
.field("reserved_count", &self.reserved_count)
|
||||
.field("next_free_compartment", &self.next_free_compartment)
|
||||
.field("objects", &self.objects
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|e| match e { (_, ObjectCompartmentEntry::Valid(_)) => true, _ => false})
|
||||
.map(|e| match e { (i, ObjectCompartmentEntry::Valid(o)) => (i, o), _ => unreachable!()})
|
||||
.collect::<Vec<(usize, &HeapObject)>>()
|
||||
).finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ObjectCompartmentEntry {
|
||||
Valid(HeapObject),
|
||||
Empty(usize), // next empty value
|
||||
EmptyNext(usize),
|
||||
EmptyTail(), // next empty value
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct HeapObject {
|
||||
class_index: usize,
|
||||
fields: Box<[ObjectField]>,
|
||||
}
|
||||
|
||||
|
@ -105,7 +232,7 @@ impl StaticArea {
|
|||
let field_array_size = std::mem::size_of_val(&new_object.fields);
|
||||
let method_array_size = std::mem::size_of_val(&new_object.methods);
|
||||
|
||||
let _ = self.static_objects.insert(class.get_classname().unwrap(), new_object);
|
||||
let _ = self.static_objects.insert(class.get_classname().unwrap().to_string(), new_object);
|
||||
|
||||
return object_memory_size + field_array_size + fields_cumulative_size + method_array_size;
|
||||
}
|
||||
|
@ -138,7 +265,6 @@ pub struct StaticField {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct ObjectField {
|
||||
pub type_description: AbstractTypeDescription,
|
||||
pub value: FieldValue,
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue