hit a wall
This commit is contained in:
parent
24a6bd0812
commit
76304fa616
6 changed files with 161 additions and 85 deletions
139
src/class.rs
139
src/class.rs
|
|
@ -21,6 +21,8 @@ pub static mut CLASSES: Lazy<HashMap<String, Value>> = Lazy::new(|| HashMap::new
|
||||||
// gets the Class from cache, or reads it from classpath,
|
// gets the Class from cache, or reads it from classpath,
|
||||||
// then parses the binary data into a Class struct
|
// then parses the binary data into a Class struct
|
||||||
// Vm keeps ownership of the class and hands out Arc references to it
|
// Vm keeps ownership of the class and hands out Arc references to it
|
||||||
|
|
||||||
|
|
||||||
pub(crate) fn get_class(
|
pub(crate) fn get_class(
|
||||||
vm: &mut Vm,
|
vm: &mut Vm,
|
||||||
class_name: &str,
|
class_name: &str,
|
||||||
|
|
@ -43,6 +45,7 @@ pub(crate) fn get_class(
|
||||||
// not sure why I have to create the clones first
|
// not sure why I have to create the clones first
|
||||||
let clone2 = class.clone();
|
let clone2 = class.clone();
|
||||||
let clone3 = class.clone();
|
let clone3 = class.clone();
|
||||||
|
let clone4 = class.clone();
|
||||||
let mut some_class = class.clone();
|
let mut some_class = class.clone();
|
||||||
|
|
||||||
if class_name != "java/lang/Class" {
|
if class_name != "java/lang/Class" {
|
||||||
|
|
@ -69,7 +72,7 @@ pub(crate) fn get_class(
|
||||||
if let Ok(super_class) = get_class(vm, &super_class_name) {
|
if let Ok(super_class) = get_class(vm, &super_class_name) {
|
||||||
supers.push(super_class.clone());
|
supers.push(super_class.clone());
|
||||||
some_class = super_class.clone();
|
some_class = super_class.clone();
|
||||||
clone2.borrow_mut().super_class = Some(super_class);
|
clone4.borrow_mut().super_class = Some(super_class);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -79,7 +82,8 @@ pub(crate) fn get_class(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Class::initialize_fields(clone3);
|
|
||||||
|
Class::initialize_fields(clone3, supers);
|
||||||
let clinit = clone2.borrow().methods.contains_key("<clinit>()V");
|
let clinit = clone2.borrow().methods.contains_key("<clinit>()V");
|
||||||
let name = &clone2.borrow().name.to_owned();
|
let name = &clone2.borrow().name.to_owned();
|
||||||
if clinit {
|
if clinit {
|
||||||
|
|
@ -108,11 +112,27 @@ pub struct Class {
|
||||||
pub methods: HashMap<String, Rc<Method>>,
|
pub methods: HashMap<String, Rc<Method>>,
|
||||||
pub attributes: HashMap<String, AttributeType>,
|
pub attributes: HashMap<String, AttributeType>,
|
||||||
pub inited: bool,
|
pub inited: bool,
|
||||||
pub(crate) object_field_mapping: HashMap<String, HashMap<String, (String, usize)>>,
|
|
||||||
// first key: this/super/supersuper-name(etc), second key: fieldname, value (type, index)
|
// lookup index and type from the name
|
||||||
pub(crate) static_field_mapping: HashMap<String, HashMap<String, (String, usize)>>,
|
pub(crate) object_field_mapping: HashMap<String, HashMap<String, TypeIndex>>,
|
||||||
// first key: this/super/supersuper-name(etc), second key: fieldname, value (type, index)
|
pub(crate) static_field_mapping: HashMap<String, HashMap<String, TypeIndex>>,
|
||||||
pub(crate) static_data: Vec<Option<Value>>,
|
// static fields
|
||||||
|
pub(crate) static_data: Vec<Value>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub(crate) struct TypeIndex {
|
||||||
|
pub type_name: String,
|
||||||
|
pub index: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypeIndex {
|
||||||
|
pub(crate) fn new(type_name: String, index: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
type_name,
|
||||||
|
index,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Class {
|
impl Class {
|
||||||
|
|
@ -176,7 +196,7 @@ impl Class {
|
||||||
// This way `this.a` can be differentiated from `super.a`.
|
// This way `this.a` can be differentiated from `super.a`.
|
||||||
//
|
//
|
||||||
// this method looks up this and super classes and calls map_fields for each.
|
// this method looks up this and super classes and calls map_fields for each.
|
||||||
pub fn initialize_fields(class: Arc<RefCell<Class>>) {
|
pub fn initialize_fields(class: Arc<RefCell<Class>>, super_classes: Vec<Arc<RefCell<Class>>>) {
|
||||||
let mut this_field_mapping = HashMap::new();
|
let mut this_field_mapping = HashMap::new();
|
||||||
let mut static_field_mapping = HashMap::new();
|
let mut static_field_mapping = HashMap::new();
|
||||||
let mut object_field_map_index: usize = 0;
|
let mut object_field_map_index: usize = 0;
|
||||||
|
|
@ -197,9 +217,13 @@ impl Class {
|
||||||
class.borrow_mut().static_data = static_data;
|
class.borrow_mut().static_data = static_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// for all static and non-static fields on the class compute an index
|
||||||
|
/// the result of this function is that the class object contains mappings
|
||||||
|
/// from the field name to the index. This index will be used to store the
|
||||||
|
/// actual data later in a Vector.
|
||||||
fn add_field_mappings(
|
fn add_field_mappings(
|
||||||
this_field_mapping: &mut HashMap<String, HashMap<String, (String, usize)>>,
|
this_field_mapping: &mut HashMap<String, HashMap<String, TypeIndex>>,
|
||||||
static_field_mapping: &mut HashMap<String, HashMap<String, (String, usize)>>,
|
static_field_mapping: &mut HashMap<String, HashMap<String, TypeIndex>>,
|
||||||
class: Arc<RefCell<Class>>,
|
class: Arc<RefCell<Class>>,
|
||||||
object_field_map_index: &mut usize,
|
object_field_map_index: &mut usize,
|
||||||
static_field_map_index: &mut usize,
|
static_field_map_index: &mut usize,
|
||||||
|
|
@ -214,11 +238,21 @@ impl Class {
|
||||||
this_field_mapping.insert(name.to_owned(), o);
|
this_field_mapping.insert(name.to_owned(), o);
|
||||||
static_field_mapping.insert(name.to_owned(), s);
|
static_field_mapping.insert(name.to_owned(), s);
|
||||||
|
|
||||||
if let Some(super_class) = class.borrow().super_class.as_ref() {
|
// // same for super class
|
||||||
|
// if let Some(super_class) = class.borrow().super_class.as_ref() {
|
||||||
|
// Class::add_field_mappings(
|
||||||
|
// this_field_mapping,
|
||||||
|
// static_field_mapping,
|
||||||
|
// super_class.clone(),
|
||||||
|
// object_field_map_index,
|
||||||
|
// static_field_map_index,
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
for c in &class.borrow().super_classes {
|
||||||
Class::add_field_mappings(
|
Class::add_field_mappings(
|
||||||
this_field_mapping,
|
this_field_mapping,
|
||||||
static_field_mapping,
|
static_field_mapping,
|
||||||
super_class.clone(),
|
c.clone(),
|
||||||
object_field_map_index,
|
object_field_map_index,
|
||||||
static_field_map_index,
|
static_field_map_index,
|
||||||
);
|
);
|
||||||
|
|
@ -226,13 +260,14 @@ impl Class {
|
||||||
}
|
}
|
||||||
|
|
||||||
// part of the initialize procedure
|
// part of the initialize procedure
|
||||||
|
/// here the actual indices are created
|
||||||
fn map_fields(
|
fn map_fields(
|
||||||
class: Arc<RefCell<Class>>,
|
class: Arc<RefCell<Class>>,
|
||||||
object_field_map_index: &mut usize,
|
object_field_map_index: &mut usize,
|
||||||
static_field_map_index: &mut usize,
|
static_field_map_index: &mut usize,
|
||||||
) -> (
|
) -> (
|
||||||
HashMap<String, (String, usize)>,
|
HashMap<String, TypeIndex>,
|
||||||
HashMap<String, (String, usize)>,
|
HashMap<String, TypeIndex>,
|
||||||
) {
|
) {
|
||||||
let mut this_fields = HashMap::new(); //fields in class are stored per class and every superclass.
|
let mut this_fields = HashMap::new(); //fields in class are stored per class and every superclass.
|
||||||
let mut static_fields = HashMap::new(); //fields in class are stored per class and every superclass.
|
let mut static_fields = HashMap::new(); //fields in class are stored per class and every superclass.
|
||||||
|
|
@ -241,13 +276,13 @@ impl Class {
|
||||||
if field.is(Modifier::Static) {
|
if field.is(Modifier::Static) {
|
||||||
static_fields.insert(
|
static_fields.insert(
|
||||||
name.to_owned(),
|
name.to_owned(),
|
||||||
(field.type_of().to_owned(), *static_field_map_index),
|
TypeIndex::new(field.type_of().to_owned(), *static_field_map_index),
|
||||||
);
|
);
|
||||||
*static_field_map_index += 1;
|
*static_field_map_index += 1;
|
||||||
} else {
|
} else {
|
||||||
this_fields.insert(
|
this_fields.insert(
|
||||||
name.to_owned(),
|
name.to_owned(),
|
||||||
(field.type_of().to_owned(), *object_field_map_index),
|
TypeIndex::new(field.type_of().to_owned(), *object_field_map_index),
|
||||||
); //name => (type,index)
|
); //name => (type,index)
|
||||||
*object_field_map_index += 1;
|
*object_field_map_index += 1;
|
||||||
}
|
}
|
||||||
|
|
@ -255,14 +290,17 @@ impl Class {
|
||||||
(this_fields, static_fields)
|
(this_fields, static_fields)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// the bytecode version
|
||||||
pub fn get_version(&self) -> (u16, u16) {
|
pub fn get_version(&self) -> (u16, u16) {
|
||||||
(self.major_version, self.minor_version)
|
(self.major_version, self.minor_version)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// get a method by signature
|
||||||
pub fn get_method(&self, name: &str) -> Option<&Rc<Method>> {
|
pub fn get_method(&self, name: &str) -> Option<&Rc<Method>> {
|
||||||
self.methods.get(name)
|
self.methods.get(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// get the class name
|
||||||
fn class_name(
|
fn class_name(
|
||||||
super_class_index: u16,
|
super_class_index: u16,
|
||||||
constant_pool: Rc<HashMap<u16, CpEntry>>,
|
constant_pool: Rc<HashMap<u16, CpEntry>>,
|
||||||
|
|
@ -281,12 +319,15 @@ impl Class {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn set_field_data(class: Arc<RefCell<Class>>) -> Vec<Option<Value>> {
|
/// creates default values for every field, ie null for objects, 0 for integers etc
|
||||||
let mut field_data = vec![None; class.borrow().n_static_fields()];
|
/// this is the step before the constructor/static initializer can be called to set hardcoded
|
||||||
|
/// or computed values.
|
||||||
|
pub(crate) fn set_field_data(class: Arc<RefCell<Class>>) -> Vec<Value> {
|
||||||
|
let mut field_data = vec![Value::Null; class.borrow().n_static_fields()];
|
||||||
|
|
||||||
for (_, this_class) in &class.borrow().static_field_mapping {
|
for (_, this_class) in &class.borrow().static_field_mapping {
|
||||||
for (_name, (fieldtype, index)) in this_class {
|
for (_name, type_index) in this_class {
|
||||||
let value = match fieldtype.as_str() {
|
let value = match type_index.type_name.as_str() {
|
||||||
"Z" => Value::BOOL(false),
|
"Z" => Value::BOOL(false),
|
||||||
"B" => Value::I32(0),
|
"B" => Value::I32(0),
|
||||||
"S" => Value::I32(0),
|
"S" => Value::I32(0),
|
||||||
|
|
@ -297,7 +338,7 @@ impl Class {
|
||||||
_ => Value::Null,
|
_ => Value::Null,
|
||||||
};
|
};
|
||||||
// println!("{} = {:?}", name, value);
|
// println!("{} = {:?}", name, value);
|
||||||
field_data[*index] = Some(value.into());
|
field_data[type_index.index] = value.into();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -306,51 +347,51 @@ impl Class {
|
||||||
|
|
||||||
// convienence methods for data from the constantpool
|
// convienence methods for data from the constantpool
|
||||||
|
|
||||||
pub fn cp_field_ref(&self, index: &u16) -> Option<(&u16, &u16)> {
|
pub fn cp_field_ref(&self, index: &u16) -> (&u16, &u16) {
|
||||||
if let CpEntry::Fieldref(class_index, name_and_type_index) =
|
if let CpEntry::Fieldref(class_index, name_and_type_index) =
|
||||||
self.constant_pool.get(index).unwrap()
|
self.constant_pool.get(index).unwrap()
|
||||||
{
|
{
|
||||||
Some((class_index, name_and_type_index))
|
(class_index, name_and_type_index)
|
||||||
} else {
|
} else {
|
||||||
None
|
unreachable!("should be field")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// both methodRef and InterfaceMethodRef
|
/// both methodRef and InterfaceMethodRef
|
||||||
/// returns (class_index, name_and_type_index)
|
/// returns (class_index, name_and_type_index)
|
||||||
pub fn cp_method_ref(&self, index: &u16) -> Option<(&u16, &u16)> {
|
pub fn cp_method_ref(&self, index: &u16) -> (&u16, &u16) {
|
||||||
if let CpEntry::MethodRef(class_index, name_and_type_index)
|
if let CpEntry::MethodRef(class_index, name_and_type_index)
|
||||||
| CpEntry::InterfaceMethodref(class_index, name_and_type_index) =
|
| CpEntry::InterfaceMethodref(class_index, name_and_type_index) =
|
||||||
self.constant_pool.get(index).unwrap()
|
self.constant_pool.get(index).unwrap()
|
||||||
{
|
{
|
||||||
Some((class_index, name_and_type_index))
|
(class_index, name_and_type_index)
|
||||||
} else {
|
} else {
|
||||||
None
|
unreachable!("should be method")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cp_class_ref(&self, index: &u16) -> Option<&u16> {
|
pub fn cp_class_ref(&self, index: &u16) -> &u16 {
|
||||||
if let CpEntry::ClassRef(name_index) = self.constant_pool.get(index).unwrap() {
|
if let CpEntry::ClassRef(name_index) = self.constant_pool.get(index).unwrap() {
|
||||||
Some(name_index)
|
name_index
|
||||||
} else {
|
} else {
|
||||||
None
|
unreachable!("should be class entry")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cp_utf8(&self, index: &u16) -> Option<&String> {
|
pub fn cp_utf8(&self, index: &u16) -> &String {
|
||||||
if let CpEntry::Utf8(utf8) = self.constant_pool.get(index).unwrap() {
|
if let CpEntry::Utf8(utf8) = self.constant_pool.get(index).unwrap() {
|
||||||
Some(utf8)
|
utf8
|
||||||
} else {
|
} else {
|
||||||
None
|
unreachable!("should be utf8 entry")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cp_name_and_type(&self, index: &u16) -> Option<(&u16, &u16)> {
|
pub fn cp_name_and_type(&self, index: &u16) -> (&u16, &u16) {
|
||||||
if let CpEntry::NameAndType(name_index, type_index) = self.constant_pool.get(index).unwrap()
|
if let CpEntry::NameAndType(name_index, type_index) = self.constant_pool.get(index).unwrap()
|
||||||
{
|
{
|
||||||
Some((name_index, type_index))
|
(name_index, type_index)
|
||||||
} else {
|
} else {
|
||||||
None
|
unreachable!("should be name_and_type entry")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -583,20 +624,42 @@ impl MethodCode {
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
Void,
|
|
||||||
// variant returned for void methods
|
// variant returned for void methods
|
||||||
Null,
|
Void,
|
||||||
// 'pointer' to nothing
|
// 'pointer' to nothing
|
||||||
|
Null,
|
||||||
|
// primitives
|
||||||
I32(i32),
|
I32(i32),
|
||||||
I64(i64),
|
I64(i64),
|
||||||
F32(f32),
|
F32(f32),
|
||||||
F64(f64),
|
F64(f64),
|
||||||
BOOL(bool),
|
BOOL(bool),
|
||||||
CHAR(char),
|
CHAR(char),
|
||||||
|
// objects and arrays
|
||||||
Ref(UnsafeRef),
|
Ref(UnsafeRef),
|
||||||
|
// special object
|
||||||
Utf8(String),
|
Utf8(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Value {
|
||||||
|
// panics if not correct type
|
||||||
|
pub fn into_i32(self) -> i32 {
|
||||||
|
if let Value::I32(v) = self {
|
||||||
|
v
|
||||||
|
} else {
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_object(self) -> UnsafeRef {
|
||||||
|
if let Value::Ref(v) = self {
|
||||||
|
v
|
||||||
|
} else {
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub type UnsafeRef = Arc<UnsafeCell<ObjectRef>>;
|
pub type UnsafeRef = Arc<UnsafeCell<ObjectRef>>;
|
||||||
|
|
||||||
pub fn unsafe_ref(object: ObjectRef) -> UnsafeRef {
|
pub fn unsafe_ref(object: ObjectRef) -> UnsafeRef {
|
||||||
|
|
|
||||||
12
src/heap.rs
12
src/heap.rs
|
|
@ -113,8 +113,8 @@ impl Object {
|
||||||
let mut field_data = Vec::with_capacity(class.borrow().n_object_fields());
|
let mut field_data = Vec::with_capacity(class.borrow().n_object_fields());
|
||||||
|
|
||||||
for (_, fields) in &class.borrow().object_field_mapping {
|
for (_, fields) in &class.borrow().object_field_mapping {
|
||||||
for (_, (fieldtype, _)) in fields {
|
for (_, type_index) in fields {
|
||||||
let value = match fieldtype.as_str() {
|
let value = match type_index.type_name.as_str() {
|
||||||
"Z" => Value::BOOL(false),
|
"Z" => Value::BOOL(false),
|
||||||
"B" => Value::I32(0),
|
"B" => Value::I32(0),
|
||||||
"S" => Value::I32(0),
|
"S" => Value::I32(0),
|
||||||
|
|
@ -133,24 +133,24 @@ impl Object {
|
||||||
|
|
||||||
pub fn set(&mut self, class_name: &String, field_name: &String, value: Value) {
|
pub fn set(&mut self, class_name: &String, field_name: &String, value: Value) {
|
||||||
let borrow = self.class.borrow();
|
let borrow = self.class.borrow();
|
||||||
let (_type, index) = borrow
|
let type_index = borrow
|
||||||
.object_field_mapping
|
.object_field_mapping
|
||||||
.get(class_name)
|
.get(class_name)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.get(field_name)
|
.get(field_name)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
self.data[*index] = value;
|
self.data[type_index.index] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&mut self, class_name: &String, field_name: &String) -> &Value {
|
pub fn get(&mut self, class_name: &String, field_name: &String) -> &Value {
|
||||||
let borrow = self.class.borrow();
|
let borrow = self.class.borrow();
|
||||||
let (_type, index) = borrow
|
let type_index = borrow
|
||||||
.object_field_mapping
|
.object_field_mapping
|
||||||
.get(class_name)
|
.get(class_name)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.get(field_name)
|
.get(field_name)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
&self.data[*index]
|
&self.data[type_index.index]
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn get_field_name(&self, cp_index: &u16) -> &str {
|
// fn get_field_name(&self, cp_index: &u16) -> &str {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
use std::io::Error;
|
use std::io::Error;
|
||||||
use java_rs::vm::Vm;
|
use java_rs::vm::Vm;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fn main() -> Result<(), Error> {
|
fn main() -> Result<(), Error> {
|
||||||
// TODO cmdline args
|
// TODO cmdline args
|
||||||
// TODO build index for package -> jarfile?
|
// TODO build index for package -> jarfile?
|
||||||
|
|
|
||||||
|
|
@ -1,43 +1,52 @@
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use log::info;
|
use std::ptr::hash;
|
||||||
|
use anyhow::Error;
|
||||||
|
use log::{debug, info};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
use crate::class::{unsafe_ref, Value};
|
use crate::class::{get_class, unsafe_ref, Value};
|
||||||
use crate::class::Value::Void;
|
use crate::class::Value::Void;
|
||||||
use crate::heap::ObjectRef;
|
use crate::heap::ObjectRef;
|
||||||
|
use crate::heap::ObjectRef::Object;
|
||||||
|
use crate::vm::Vm;
|
||||||
|
|
||||||
pub fn invoke_native(class_name: &String, method_name: &String, _args: Vec<Value>) -> Value {
|
pub fn invoke_native(vm: &mut Vm, class_name: &String, method_name: &String, _args: Vec<Value>) -> Result<Value,Error> {
|
||||||
info!("native {}.{}", class_name, method_name);
|
info!("native {}.{}", class_name, method_name);
|
||||||
|
|
||||||
match class_name.as_str() {
|
match class_name.as_str() {
|
||||||
"java/lang/Class" => java_lang_class(method_name),
|
"java/lang/Class" => java_lang_class(vm, method_name),
|
||||||
"jdk/internal/util/SystemProps$Raw" => jdk_internal_util_SystemProps_Raw(method_name),
|
"jdk/internal/util/SystemProps$Raw" => jdk_internal_util_SystemProps_Raw(vm, method_name),
|
||||||
_ => Void
|
_ => Ok(Void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn java_lang_class(method_name: &String) -> Value {
|
fn java_lang_class(_vm: &mut Vm, method_name: &String) -> Result<Value,Error> {
|
||||||
match method_name.as_str() {
|
Ok(match method_name.as_str() {
|
||||||
"desiredAssertionStatus0(Ljava/lang/Class;)Z" => Value::BOOL(false),
|
"desiredAssertionStatus0(Ljava/lang/Class;)Z" => Value::BOOL(false),
|
||||||
_ => Void
|
_ => Void
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn jdk_internal_util_SystemProps_Raw(method_name: &String) -> Value {
|
fn jdk_internal_util_SystemProps_Raw(vm: &mut Vm,method_name: &String) -> Result<Value,Error> {
|
||||||
match method_name.as_str() {
|
match method_name.as_str() {
|
||||||
"platformProperties()[Ljava/lang/String;" => systemProps(),
|
"platformProperties()[Ljava/lang/String;" => systemProps(),
|
||||||
"cmdProperties()Ljava/util/HashMap;" => cmdProps(), //TODO ability to instantiate classes here
|
"cmdProperties()Ljava/util/HashMap;" => cmdProps(vm), //TODO ability to instantiate classes here
|
||||||
"vmProperties()[Ljava/lang/String;" => cmdProps(),
|
"vmProperties()[Ljava/lang/String;" => cmdProps(vm),
|
||||||
_ => Void
|
_ => Ok(Void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cmdProps() -> Value {
|
fn cmdProps(vm: &mut Vm,) -> Result<Value,Error> {
|
||||||
Value::Null
|
let hashmap_class = get_class(vm, "java/util/HashMap")?;
|
||||||
|
let hashmap = Vm::new_instance(hashmap_class);
|
||||||
|
let hashmap = Value::Ref(unsafe_ref(Object(Box::new(hashmap))));
|
||||||
|
vm.execute_special("java/util/HashMap", "<init>()V", vec![hashmap.clone()]);
|
||||||
|
unsafe {debug!("hashmap {:?}", *hashmap.into_object().get());}
|
||||||
|
panic!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn systemProps() -> Value {
|
fn systemProps() -> Result<Value,Error> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let props: Lazy<Vec<String>> = Lazy::new(|| {
|
let props: Lazy<Vec<String>> = Lazy::new(|| {
|
||||||
let mut vec: Vec<String> = Vec::new();
|
let mut vec: Vec<String> = Vec::new();
|
||||||
|
|
@ -122,6 +131,6 @@ fn systemProps() -> Value {
|
||||||
|
|
||||||
vec
|
vec
|
||||||
});
|
});
|
||||||
Value::Ref(unsafe_ref(ObjectRef::StringArray(props.to_vec())))
|
Ok(Value::Ref(unsafe_ref(ObjectRef::StringArray(props.to_vec()))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -397,6 +397,7 @@ pub const OPCODES:Lazy<Vec<&str>> = Lazy::new(|| {
|
||||||
opcodes[_DSUB as usize] = "_DSUB" ;
|
opcodes[_DSUB as usize] = "_DSUB" ;
|
||||||
opcodes[_FMUL as usize] = "_FMUL" ;
|
opcodes[_FMUL as usize] = "_FMUL" ;
|
||||||
opcodes[_DMUL as usize] = "_DMUL" ;
|
opcodes[_DMUL as usize] = "_DMUL" ;
|
||||||
|
opcodes[IDIV as usize] = "IDIV" ;
|
||||||
opcodes[_FDIV as usize] = "_FDIV" ;
|
opcodes[_FDIV as usize] = "_FDIV" ;
|
||||||
opcodes[_DDIV as usize] = "_DDIV" ;
|
opcodes[_DDIV as usize] = "_DDIV" ;
|
||||||
opcodes[_FREM as usize] = "_FREM" ;
|
opcodes[_FREM as usize] = "_FREM" ;
|
||||||
|
|
|
||||||
|
|
@ -2,36 +2,37 @@ use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use anyhow::{anyhow, Error};
|
use anyhow::Error;
|
||||||
use Value::I32;
|
|
||||||
use crate::class::{Class, get_class, Method, Value};
|
use crate::class::{Class, get_class, Value};
|
||||||
use crate::class::Value::{F32, F64, I64, Ref, Utf8};
|
|
||||||
use crate::classloader::CpEntry;
|
use crate::classloader::CpEntry;
|
||||||
use crate::heap::ObjectRef;
|
|
||||||
use crate::vm::Vm;
|
use crate::vm::Vm;
|
||||||
use crate::vm::vm::{Invocation, MethodSignature};
|
use crate::vm::vm::{Invocation, MethodSignature};
|
||||||
|
|
||||||
pub(crate) fn get_static(vm: &mut Vm, this_class: Arc<RefCell<Class>>, field_index: u16) -> Value {
|
/// the place for opcode implementations that are a bit long
|
||||||
let borrow = this_class.borrow();
|
|
||||||
let (class_index, field_name_and_type_index) =
|
|
||||||
borrow.cp_field_ref(&field_index).unwrap(); // all these unwraps are safe as long as the class is valid
|
|
||||||
let (name_index, _) =
|
|
||||||
borrow.cp_name_and_type(field_name_and_type_index).unwrap();
|
|
||||||
let name = borrow.cp_utf8(name_index).unwrap();
|
|
||||||
|
|
||||||
let that_class_name_index = borrow.cp_class_ref(class_index).unwrap();
|
// GET_STATIC opcode
|
||||||
let that_class_name = borrow.cp_utf8(that_class_name_index).unwrap();
|
pub(crate) fn get_static(vm: &mut Vm, this_class: Arc<RefCell<Class>>, field_index: u16) -> Result<Value,Error> {
|
||||||
let that = get_class(vm, that_class_name.as_str()).unwrap();
|
let this_class = this_class.borrow();
|
||||||
let that_borrow = that.borrow();
|
let (class_index, field_name_and_type_index) =
|
||||||
let (_, val_index) = that_borrow
|
this_class.cp_field_ref(&field_index); // all these unwraps are safe as long as the class is valid
|
||||||
|
let (name_index, _) =
|
||||||
|
this_class.cp_name_and_type(field_name_and_type_index);
|
||||||
|
let field_name = this_class.cp_utf8(name_index);
|
||||||
|
|
||||||
|
let that_class_name_index = this_class.cp_class_ref(class_index);
|
||||||
|
let that_class_name = this_class.cp_utf8(that_class_name_index);
|
||||||
|
let that_class = get_class(vm, that_class_name.as_str())?;
|
||||||
|
let that_class = that_class.borrow();
|
||||||
|
|
||||||
|
let type_index = that_class
|
||||||
.static_field_mapping
|
.static_field_mapping
|
||||||
.get(that_class_name)
|
.get(that_class_name)
|
||||||
.unwrap()
|
.unwrap()// safe because class for static field must be there
|
||||||
.get(name)
|
.get(field_name)
|
||||||
.unwrap();
|
.unwrap(); // safe because field must be there
|
||||||
that_borrow
|
|
||||||
.static_data
|
Ok(that_class.static_data[type_index.index].clone())
|
||||||
.get(*val_index).unwrap().as_ref().unwrap().clone()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_name_and_type(cp: Rc<HashMap<u16, CpEntry>>, index: u16) -> Option<MethodSignature> {
|
pub(crate) fn get_name_and_type(cp: Rc<HashMap<u16, CpEntry>>, index: u16) -> Option<MethodSignature> {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue