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.
|
Enum = 0x4000, // Declared as an element of an enum class.
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FieldAccessFlagMask {
|
#[derive(Clone, Copy)]
|
||||||
pub mask: u16
|
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 {
|
impl Debug for FieldAccessFlagMask {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
|
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||||
|
|
|
@ -266,10 +266,10 @@ impl JavaClassFile {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct FieldInfo {
|
pub struct FieldInfo {
|
||||||
access_flags: FieldAccessFlagMask,
|
pub access_flags: FieldAccessFlagMask,
|
||||||
name: String,
|
pub name: String,
|
||||||
descriptor: AbstractTypeDescription,
|
pub descriptor: AbstractTypeDescription,
|
||||||
attributes: Box<[AttributeInfo]>,
|
pub attributes: Box<[AttributeInfo]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FieldInfo {
|
impl FieldInfo {
|
||||||
|
@ -535,11 +535,15 @@ impl NestMembersAttributeData {
|
||||||
pub enum AttributeData {
|
pub enum AttributeData {
|
||||||
Code(CodeAttributeData),
|
Code(CodeAttributeData),
|
||||||
Signature(SignatureAttributeData),
|
Signature(SignatureAttributeData),
|
||||||
|
Synthetic(),
|
||||||
|
Exceptions(ExceptionAttributeData),
|
||||||
NestMembers(NestMembersAttributeData),
|
NestMembers(NestMembersAttributeData),
|
||||||
SourceFile(SourceFileAttributeData),
|
SourceFile(SourceFileAttributeData),
|
||||||
InnerClasses(InnerClassesAttributeData),
|
InnerClasses(InnerClassesAttributeData),
|
||||||
ConstantValue(ConstantValueAttributeData),
|
ConstantValue(ConstantValueAttributeData),
|
||||||
|
DebugExtension(DebugExtensionAttributeData),
|
||||||
LineNumberTable(LineNumberTableAttributeData),
|
LineNumberTable(LineNumberTableAttributeData),
|
||||||
|
EnclosingMethod(EnclosingMethodAttributeData),
|
||||||
Unknown(UnknownAttributeData),
|
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> {
|
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_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 data = {
|
||||||
let name_entry = &pool[attribute_name_index as usize];
|
let name_entry = &pool[attribute_name_index as usize];
|
||||||
|
@ -574,35 +578,47 @@ impl AttributeInfo {
|
||||||
};
|
};
|
||||||
|
|
||||||
match &utf8[..] {
|
match &utf8[..] {
|
||||||
"ConstantValue" => AttributeData::ConstantValue(
|
"ConstantValue" => AttributeData::ConstantValue(
|
||||||
ConstantValueAttributeData {
|
ConstantValueAttributeData {
|
||||||
constant_value_index: read_u16(reader)?,
|
constant_value_index: read_u16(reader)?,
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
|
||||||
"LineNumberTable" => AttributeData::LineNumberTable(
|
"LineNumberTable" => AttributeData::LineNumberTable(
|
||||||
LineNumberTableAttributeData::from_reader(reader)?
|
LineNumberTableAttributeData::from_reader(reader)?
|
||||||
),
|
),
|
||||||
|
|
||||||
"Code" => if allow_code_attr {
|
"Code" => if allow_code_attr {
|
||||||
AttributeData::Code(
|
AttributeData::Code(
|
||||||
CodeAttributeData::from_reader(reader, pool)?
|
CodeAttributeData::from_reader(reader, pool)?
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::BadFileError("Nested Code attributes are forbidden.".to_string()));
|
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(
|
&_ => AttributeData::Unknown(
|
||||||
UnknownAttributeData {
|
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)]
|
#[repr(u8)]
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||||
pub enum AbstractTypeKind {
|
pub enum AbstractTypeKind {
|
||||||
Void() = b'V', // void
|
Void() = b'V', // void
|
||||||
Byte() = b'B', // signed byte
|
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 struct AbstractTypeDescription {
|
||||||
pub array_level: u8,
|
pub array_level: u8,
|
||||||
pub kind: AbstractTypeKind,
|
pub kind: AbstractTypeKind,
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::accessmasks::FieldAccessFlag;
|
||||||
use crate::stackframe::Value;
|
use crate::stackframe::Value;
|
||||||
use crate::classfile::{ AbstractTypeDescription, MethodInfo };
|
use crate::classfile::{ JavaClassFile, AbstractTypeDescription, MethodInfo };
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct HeapArea {
|
pub struct HeapArea {
|
||||||
|
@ -54,13 +55,46 @@ pub struct StaticArea {
|
||||||
static_objects: HashMap<String, StaticObject>,
|
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)]
|
#[derive(Debug)]
|
||||||
pub struct StaticObject {
|
pub struct StaticObject {
|
||||||
pub class_index: usize,
|
pub class_index: usize,
|
||||||
pub fields: Box<[ObjectField]>,
|
pub fields: Box<[StaticField]>,
|
||||||
pub methods: Box<[MethodInfo]>,
|
pub methods: Box<[MethodInfo]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct StaticField {
|
||||||
|
pub name: String,
|
||||||
|
pub type_description: AbstractTypeDescription,
|
||||||
|
pub value: Value,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ObjectField {
|
pub struct ObjectField {
|
||||||
pub type_description: AbstractTypeDescription,
|
pub type_description: AbstractTypeDescription,
|
||||||
|
|
11
src/jvm.rs
11
src/jvm.rs
|
@ -161,7 +161,7 @@ impl JVM {
|
||||||
},
|
},
|
||||||
|
|
||||||
JVMCallbackOperation::InitClass(name) => {
|
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(())
|
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 class_file = self.class_store.class_file_from_idx(class_idx).unwrap();
|
||||||
let clinit_idx = class_file.find_method_index(&"<clinit>".to_string());
|
let clinit_idx = class_file.find_method_index(&"<clinit>".to_string());
|
||||||
|
|
||||||
// TODO: ConstantValue Attributes (final)
|
|
||||||
// TODO: Static Stuff
|
// 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);
|
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> {
|
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),
|
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;
|
use crate::heap_area::ObjectReference;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
@ -18,6 +18,23 @@ pub enum Value {
|
||||||
Empty(),
|
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)]
|
#[derive(Debug)]
|
||||||
pub struct OperandStack {
|
pub struct OperandStack {
|
||||||
stack: Box<[Value]>,
|
stack: Box<[Value]>,
|
||||||
|
|
Loading…
Reference in a new issue