Static object creation
This commit is contained in:
parent
8642dcdd6a
commit
6c0fbd179a
6 changed files with 160 additions and 29 deletions
|
@ -130,9 +130,33 @@ pub enum FieldAccessFlag {
|
|||
Enum = 0x4000, // Declared as an element of an enum class.
|
||||
}
|
||||
|
||||
pub struct FieldAccessFlagMask {
|
||||
pub mask: u16
|
||||
}
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct FieldAccessFlagMask {
|
||||
pub mask: u16
|
||||
}
|
||||
|
||||
impl FieldAccessFlag {
|
||||
pub fn discriminant(&self) -> u16 {
|
||||
return match self {
|
||||
Self::Public => 0x0001,
|
||||
Self::Private => 0x0002,
|
||||
Self::Protected => 0x0004,
|
||||
Self::Static => 0x0008,
|
||||
Self::Final => 0x0010,
|
||||
Self::Volatile => 0x0040,
|
||||
Self::Transient => 0x0080,
|
||||
Self::Synthetic => 0x1000,
|
||||
Self::Enum => 0x4000,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BitAnd<FieldAccessFlag> for FieldAccessFlagMask {
|
||||
type Output=bool;
|
||||
fn bitand(self, f: FieldAccessFlag) -> bool {
|
||||
return (self.mask & f.discriminant()) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for FieldAccessFlagMask {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||
|
|
|
@ -266,10 +266,10 @@ impl JavaClassFile {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct FieldInfo {
|
||||
access_flags: FieldAccessFlagMask,
|
||||
name: String,
|
||||
descriptor: AbstractTypeDescription,
|
||||
attributes: Box<[AttributeInfo]>,
|
||||
pub access_flags: FieldAccessFlagMask,
|
||||
pub name: String,
|
||||
pub descriptor: AbstractTypeDescription,
|
||||
pub attributes: Box<[AttributeInfo]>,
|
||||
}
|
||||
|
||||
impl FieldInfo {
|
||||
|
@ -535,11 +535,15 @@ impl NestMembersAttributeData {
|
|||
pub enum AttributeData {
|
||||
Code(CodeAttributeData),
|
||||
Signature(SignatureAttributeData),
|
||||
Synthetic(),
|
||||
Exceptions(ExceptionAttributeData),
|
||||
NestMembers(NestMembersAttributeData),
|
||||
SourceFile(SourceFileAttributeData),
|
||||
InnerClasses(InnerClassesAttributeData),
|
||||
ConstantValue(ConstantValueAttributeData),
|
||||
DebugExtension(DebugExtensionAttributeData),
|
||||
LineNumberTable(LineNumberTableAttributeData),
|
||||
EnclosingMethod(EnclosingMethodAttributeData),
|
||||
Unknown(UnknownAttributeData),
|
||||
}
|
||||
|
||||
|
@ -564,7 +568,7 @@ impl AttributeInfo {
|
|||
|
||||
fn from_reader(reader: &mut dyn Read, pool: &Box<[ConstantPoolInfo]>, allow_code_attr: bool) -> Result<Self, Error> {
|
||||
let attribute_name_index: u16 = read_u16(reader)? - 1;
|
||||
let _attribute_byte_size: usize = read_u32(reader)?.try_into()?;
|
||||
let attribute_byte_size: usize = read_u32(reader)?.try_into()?;
|
||||
|
||||
let data = {
|
||||
let name_entry = &pool[attribute_name_index as usize];
|
||||
|
@ -574,35 +578,47 @@ impl AttributeInfo {
|
|||
};
|
||||
|
||||
match &utf8[..] {
|
||||
"ConstantValue" => AttributeData::ConstantValue(
|
||||
"ConstantValue" => AttributeData::ConstantValue(
|
||||
ConstantValueAttributeData {
|
||||
constant_value_index: read_u16(reader)?,
|
||||
}
|
||||
),
|
||||
),
|
||||
|
||||
"LineNumberTable" => AttributeData::LineNumberTable(
|
||||
"LineNumberTable" => AttributeData::LineNumberTable(
|
||||
LineNumberTableAttributeData::from_reader(reader)?
|
||||
),
|
||||
),
|
||||
|
||||
"Code" => if allow_code_attr {
|
||||
"Code" => if allow_code_attr {
|
||||
AttributeData::Code(
|
||||
CodeAttributeData::from_reader(reader, pool)?
|
||||
)
|
||||
} else {
|
||||
} else {
|
||||
return Err(Error::BadFileError("Nested Code attributes are forbidden.".to_string()));
|
||||
},
|
||||
},
|
||||
|
||||
"SourceFile" => AttributeData::SourceFile(SourceFileAttributeData::from_reader(reader)?),
|
||||
"SourceFile" => AttributeData::SourceFile(SourceFileAttributeData::from_reader(reader)?),
|
||||
|
||||
"Signature" => AttributeData::Signature(SignatureAttributeData::from_reader(reader)?),
|
||||
"Signature" => AttributeData::Signature(SignatureAttributeData::from_reader(reader)?),
|
||||
|
||||
"InnerClasses" => AttributeData::InnerClasses(InnerClassesAttributeData::from_reader(reader)?),
|
||||
"InnerClasses" => AttributeData::InnerClasses(InnerClassesAttributeData::from_reader(reader)?),
|
||||
|
||||
"NestMembers" => AttributeData::NestMembers(NestMembersAttributeData::from_reader(reader)?),
|
||||
"NestMembers" => AttributeData::NestMembers(NestMembersAttributeData::from_reader(reader)?),
|
||||
|
||||
"Exceptions" => AttributeData::Exceptions(ExceptionAttributeData::from_reader(reader)?),
|
||||
|
||||
"EnclosingMethod" => AttributeData::EnclosingMethod(EnclosingMethodAttributeData {class_index: read_u16(reader)?, method_index: read_u16(reader)?}),
|
||||
|
||||
"Synthetic" => AttributeData::Synthetic(),
|
||||
|
||||
"DebugExtension" => AttributeData::DebugExtension(
|
||||
DebugExtensionAttributeData {
|
||||
utf8: std::str::from_utf8(&(read_buffer(reader, attribute_byte_size)?))?.to_string(),
|
||||
}
|
||||
),
|
||||
|
||||
&_ => AttributeData::Unknown(
|
||||
UnknownAttributeData {
|
||||
info: read_buffer(reader, _attribute_byte_size)?,
|
||||
info: read_buffer(reader, attribute_byte_size)?,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -617,8 +633,42 @@ impl AttributeInfo {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DebugExtensionAttributeData {
|
||||
utf8: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct EnclosingMethodAttributeData {
|
||||
class_index: u16,
|
||||
method_index: u16,
|
||||
}
|
||||
|
||||
// for use on methods, what exception can be thrown by this
|
||||
#[derive(Debug)]
|
||||
pub struct ExceptionAttributeData {
|
||||
exception_indices: Box<[u16]>,
|
||||
}
|
||||
|
||||
impl ExceptionAttributeData {
|
||||
fn from_reader(reader: &mut dyn Read) -> Result<Self, Error> {
|
||||
let length = read_u16(reader)?;
|
||||
let mut exception_vector = Vec::with_capacity(length as usize);
|
||||
|
||||
for _ in 0..length {
|
||||
exception_vector.push(read_u16(reader)?);
|
||||
}
|
||||
|
||||
Ok(
|
||||
ExceptionAttributeData {
|
||||
exception_indices: exception_vector.into_boxed_slice()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||
pub enum AbstractTypeKind {
|
||||
Void() = b'V', // void
|
||||
Byte() = b'B', // signed byte
|
||||
|
@ -649,7 +699,7 @@ impl Into<String> for &AbstractTypeKind {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||
pub struct AbstractTypeDescription {
|
||||
pub array_level: u8,
|
||||
pub kind: AbstractTypeKind,
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use crate::accessmasks::FieldAccessFlag;
|
||||
use crate::stackframe::Value;
|
||||
use crate::classfile::{ AbstractTypeDescription, MethodInfo };
|
||||
use crate::classfile::{ JavaClassFile, AbstractTypeDescription, MethodInfo };
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct HeapArea {
|
||||
|
@ -54,13 +55,46 @@ pub struct StaticArea {
|
|||
static_objects: HashMap<String, StaticObject>,
|
||||
}
|
||||
|
||||
impl StaticArea {
|
||||
pub fn make(&mut self, class: &JavaClassFile, class_index: usize) {
|
||||
let mut fields = Vec::new();
|
||||
|
||||
for field in &class.fields {
|
||||
if field.access_flags & FieldAccessFlag::Static {
|
||||
fields.push(
|
||||
StaticField {
|
||||
name: field.name.clone(),
|
||||
type_description: field.descriptor.clone(),
|
||||
value: Value::default_for(field.descriptor),
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
let new_object = StaticObject {
|
||||
class_index,
|
||||
fields: fields.into_boxed_slice(),
|
||||
methods: Box::new([]),
|
||||
};
|
||||
|
||||
let _ = self.static_objects.insert(class.get_classname().unwrap(), new_object);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct StaticObject {
|
||||
pub class_index: usize,
|
||||
pub fields: Box<[ObjectField]>,
|
||||
pub fields: Box<[StaticField]>,
|
||||
pub methods: Box<[MethodInfo]>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct StaticField {
|
||||
pub name: String,
|
||||
pub type_description: AbstractTypeDescription,
|
||||
pub value: Value,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ObjectField {
|
||||
pub type_description: AbstractTypeDescription,
|
||||
|
|
11
src/jvm.rs
11
src/jvm.rs
|
@ -161,7 +161,7 @@ impl JVM {
|
|||
},
|
||||
|
||||
JVMCallbackOperation::InitClass(name) => {
|
||||
self.init_class(*self.class_store.class_idx_from_name(&name).unwrap());
|
||||
self.init_class(*self.class_store.class_idx_from_name(&name).unwrap())?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -169,14 +169,19 @@ impl JVM {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn init_class(&mut self, class_idx: usize) {
|
||||
pub fn init_class(&mut self, class_idx: usize) -> Result<(), Error> {
|
||||
let class_file = self.class_store.class_file_from_idx(class_idx).unwrap();
|
||||
let clinit_idx = class_file.find_method_index(&"<clinit>".to_string());
|
||||
|
||||
// TODO: ConstantValue Attributes (final)
|
||||
// TODO: Static Stuff
|
||||
self.heap_area.static_area.make(class_file, class_idx);
|
||||
|
||||
// TODO: ConstantValue Attributes (final)
|
||||
// TODO: Push clinit function
|
||||
|
||||
self.class_store.set_init(class_idx, true);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn prepare_invoke_static(&mut self, class_index: usize, method_name: &String, arguments: &[Value]) -> Result<(), Error> {
|
||||
|
|
|
@ -26,5 +26,6 @@ fn main() {
|
|||
Err(e) => println!("{:#?}", e),
|
||||
};
|
||||
|
||||
println!("{:#?}", jvm.stack_frames);
|
||||
println!("{:#?}", jvm);
|
||||
//println!("{:#?}", JavaClassFile::new(&mut File::open("java/Class.class").unwrap()));
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::classfile::{ JavaClassFile, AttributeData };
|
||||
use crate::classfile::{ JavaClassFile, AttributeData, AbstractTypeDescription };
|
||||
use crate::heap_area::ObjectReference;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
@ -18,6 +18,23 @@ pub enum Value {
|
|||
Empty(),
|
||||
}
|
||||
|
||||
impl Value {
|
||||
fn default_for(t: AbstractTypeDescription) -> Self {
|
||||
match t {
|
||||
AbstractTypeDescription::Void() => unreachable!(),
|
||||
AbstractTypeDescription::Byte() => Value::Byte(0),
|
||||
AbstractTypeDescription::Char() => Value::Char(0),
|
||||
AbstractTypeDescription::Double() => Value::Double(0),
|
||||
AbstractTypeDescription::Float() => ,
|
||||
AbstractTypeDescription::Int() => ,
|
||||
AbstractTypeDescription::Long() => ,
|
||||
AbstractTypeDescription::Classname(String) => ,
|
||||
AbstractTypeDescription::Short() => ,
|
||||
AbstractTypeDescription::Boolean() => ,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct OperandStack {
|
||||
stack: Box<[Value]>,
|
||||
|
|
Loading…
Reference in a new issue