ConstantValue initialization
This commit is contained in:
parent
4ee673d5ff
commit
25d3509ccf
4 changed files with 167 additions and 69 deletions
110
src/heap_area.rs
110
src/heap_area.rs
|
@ -1,8 +1,8 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use crate::accessmasks::FieldAccessFlag;
|
||||
use crate::stackframe::StackValue;
|
||||
use crate::classfile::{ JavaClassFile, AbstractTypeDescription, MethodInfo };
|
||||
use crate::classfile::{ JavaClassFile, AbstractTypeDescription, MethodInfo, AbstractTypeKind };
|
||||
use crate::jvm::Error;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct HeapArea {
|
||||
|
@ -21,6 +21,10 @@ impl HeapArea {
|
|||
static_area: StaticArea::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_static(&mut self, class: &JavaClassFile, class_index: usize) {
|
||||
self.memory_used += self.static_area.make(class, class_index);
|
||||
}
|
||||
}
|
||||
|
||||
pub type ObjectReference=u32;
|
||||
|
@ -56,18 +60,38 @@ pub struct StaticArea {
|
|||
}
|
||||
|
||||
impl StaticArea {
|
||||
pub fn make(&mut self, class: &JavaClassFile, class_index: usize) {
|
||||
|
||||
pub fn set(&mut self, class_name: &String, field_name: &String, field_value: FieldValue) -> Result<(), Error> {
|
||||
let static_object = match self.static_objects.get_mut(class_name) {
|
||||
Some(o) => o,
|
||||
None => return Err(Error::RunTimeError(format!("Trying to set '{}.{}={:?}' but there is no such static object.", class_name, field_name, field_value))),
|
||||
};
|
||||
|
||||
let field_index = match static_object.field_index_from_name(&field_name) {
|
||||
Some(i) => i,
|
||||
None => return Err(Error::RunTimeError(format!("Trying to set '{}.{}={:?}' but there is no such static field on this object.", class_name, field_name, field_value))),
|
||||
};
|
||||
|
||||
field_value.check_type(&static_object.fields[field_index].descriptor, class_name)?;
|
||||
|
||||
static_object.fields[field_index].value = field_value;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn make(&mut self, class: &JavaClassFile, class_index: usize) -> usize {
|
||||
let mut fields = Vec::new();
|
||||
|
||||
let mut fields_cumulative_size = 0;
|
||||
for field in &class.fields {
|
||||
if field.access_flags & FieldAccessFlag::Static {
|
||||
fields.push(
|
||||
StaticField {
|
||||
name: field.name.clone(),
|
||||
type_description: field.descriptor.clone(),
|
||||
value: StackValue::default_for(field.descriptor),
|
||||
}
|
||||
)
|
||||
let new_field = StaticField {
|
||||
name: field.name.clone(),
|
||||
descriptor: field.descriptor.clone(),
|
||||
value: FieldValue::default_for(&field.descriptor),
|
||||
};
|
||||
fields_cumulative_size += std::mem::size_of_val(&new_field);
|
||||
fields.push(new_field);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,7 +101,13 @@ impl StaticArea {
|
|||
methods: Box::new([]),
|
||||
};
|
||||
|
||||
let object_memory_size = std::mem::size_of_val(&new_object);
|
||||
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);
|
||||
|
||||
return object_memory_size + field_array_size + fields_cumulative_size + method_array_size;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,15 +118,69 @@ pub struct StaticObject {
|
|||
pub methods: Box<[MethodInfo]>,
|
||||
}
|
||||
|
||||
impl StaticObject {
|
||||
fn field_index_from_name(&self, name: &String) -> Option<usize> {
|
||||
for (index, field) in self.fields.iter().enumerate() {
|
||||
if field.name == *name {
|
||||
return Some(index)
|
||||
}
|
||||
}
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct StaticField {
|
||||
pub name: String,
|
||||
pub type_description: AbstractTypeDescription,
|
||||
pub value: StackValue,
|
||||
pub descriptor: AbstractTypeDescription,
|
||||
pub value: FieldValue,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ObjectField {
|
||||
pub type_description: AbstractTypeDescription,
|
||||
pub value: StackValue,
|
||||
pub value: FieldValue,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum FieldValue {
|
||||
Boolean(bool),
|
||||
Byte(u8),
|
||||
Char(u16),
|
||||
Short(i16),
|
||||
Int(i32),
|
||||
Float(f32),
|
||||
Reference(ObjectReference),
|
||||
Double(f64),
|
||||
Long(i64),
|
||||
}
|
||||
|
||||
impl FieldValue {
|
||||
fn check_type(&self, t: &AbstractTypeDescription, class_name: &String) -> Result<(), Error> {
|
||||
let default_val = FieldValue::default_for(t);
|
||||
|
||||
return if std::mem::discriminant(&default_val) != std::mem::discriminant(self) {
|
||||
Err(Error::RunTimeError(format!("Type Mismatch: trying to set {:?} on a field of type {:?} in class {}", self, default_val, class_name)))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn default_for(t: &AbstractTypeDescription) -> Self {
|
||||
if t.array_level != 0 {
|
||||
return Self::Reference(0);
|
||||
}
|
||||
match &t.kind {
|
||||
AbstractTypeKind::Void() => unreachable!(),
|
||||
AbstractTypeKind::Byte() => Self::Byte(0),
|
||||
AbstractTypeKind::Char() => Self::Char(0),
|
||||
AbstractTypeKind::Double() => Self::Double(0.0),
|
||||
AbstractTypeKind::Float() => Self::Float(0.0),
|
||||
AbstractTypeKind::Int() => Self::Int(0),
|
||||
AbstractTypeKind::Long() => Self::Long(0),
|
||||
AbstractTypeKind::Classname(_) => Self::Reference(0),
|
||||
AbstractTypeKind::Short() => Self::Short(0),
|
||||
AbstractTypeKind::Boolean() => Self::Boolean(true),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue