Native Unsafe:: methods, main loading, stuff!
This commit is contained in:
parent
90e244c964
commit
fba596ce5a
8 changed files with 242 additions and 22 deletions
|
@ -119,6 +119,7 @@ impl Bytecode {
|
||||||
|
|
||||||
0x80 => (Instruction::OrInt(), 1),
|
0x80 => (Instruction::OrInt(), 1),
|
||||||
0x82 => (Instruction::XorInt(), 1),
|
0x82 => (Instruction::XorInt(), 1),
|
||||||
|
0x83 => (Instruction::XorLong(), 1),
|
||||||
0x84 => (Instruction::IncrementLocalInt(self.bytes[offset+1], i8::from_be_bytes([self.bytes[offset+2]])), 3),
|
0x84 => (Instruction::IncrementLocalInt(self.bytes[offset+1], i8::from_be_bytes([self.bytes[offset+2]])), 3),
|
||||||
0x85 => (Instruction::ConvertIntToLong(), 1),
|
0x85 => (Instruction::ConvertIntToLong(), 1),
|
||||||
|
|
||||||
|
@ -416,6 +417,7 @@ pub enum Instruction {
|
||||||
|
|
||||||
OrInt() = 0x80, // value, value => or
|
OrInt() = 0x80, // value, value => or
|
||||||
XorInt() = 0x82, // value, value => xor
|
XorInt() = 0x82, // value, value => xor
|
||||||
|
XorLong() = 0x83, // value, value => xor
|
||||||
IncrementLocalInt(u8, i8) = 0x84, // increment local variable by constant i8
|
IncrementLocalInt(u8, i8) = 0x84, // increment local variable by constant i8
|
||||||
ConvertIntToLong() = 0x85, // convert int on stack to long
|
ConvertIntToLong() = 0x85, // convert int on stack to long
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,8 @@ use core::str::Utf8Error;
|
||||||
use crate::accessmasks::*;
|
use crate::accessmasks::*;
|
||||||
use crate::bytecode::Bytecode;
|
use crate::bytecode::Bytecode;
|
||||||
use crate::classstore::ClassStore;
|
use crate::classstore::ClassStore;
|
||||||
use crate::constantpool::{ ConstantFieldRefInfo, ConstantPoolInfo, ConstantUtf8Info, ConstantInterfaceMethodRefInfo, ConstantStringInfo, ConstantMethodRefInfo, ConstantFloatInfo, ConstantClassInfo, ConstantNameAndTypeInfo, ConstantIntegerInfo, ConstantLongInfo };
|
use crate::constantpool::*;
|
||||||
use crate::constantpool::ConstantDoubleInfo;
|
use crate::constantpool::ConstantDoubleInfo;
|
||||||
use crate::heap_area::ObjectReference;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
@ -240,6 +239,17 @@ impl JavaClassFile {
|
||||||
return Ok(methodref_entry);
|
return Ok(methodref_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn pool_methodhandle_entry(&self, index: u16) -> Result<&ConstantMethodHandleInfo, Error> {
|
||||||
|
let pool_entry = self.pool_entry(index)?;
|
||||||
|
|
||||||
|
let methodhandle_entry = match pool_entry {
|
||||||
|
ConstantPoolInfo::MethodHandle(data) => data,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
return Ok(methodhandle_entry);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn pool_fieldref_entry(&self, index: u16) -> Result<&ConstantFieldRefInfo, Error> {
|
pub fn pool_fieldref_entry(&self, index: u16) -> Result<&ConstantFieldRefInfo, Error> {
|
||||||
let pool_entry = self.pool_entry(index)?;
|
let pool_entry = self.pool_entry(index)?;
|
||||||
|
|
||||||
|
@ -429,6 +439,7 @@ impl JavaClassFile {
|
||||||
|
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -702,9 +713,60 @@ impl NestMembersAttributeData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct BootstrapMethodEntry {
|
||||||
|
bootstrap_method_ref: u16,
|
||||||
|
bootstrap_arguments: Box<[u16]>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BootstrapMethodEntry {
|
||||||
|
fn from_reader(reader: &mut dyn Read) -> Result<Self, Error> {
|
||||||
|
Ok(
|
||||||
|
BootstrapMethodEntry {
|
||||||
|
bootstrap_method_ref: read_u16(reader)?,
|
||||||
|
bootstrap_arguments: {
|
||||||
|
let length = read_u16(reader)?;
|
||||||
|
let mut v = Vec::with_capacity(length.into());
|
||||||
|
|
||||||
|
for _i in 0..length {
|
||||||
|
v.push(read_u16(reader)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
v.into_boxed_slice()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct BootstrapMethodsData {
|
||||||
|
bootstrap_methods: Box<[BootstrapMethodEntry]>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BootstrapMethodsData {
|
||||||
|
fn from_reader(reader: &mut dyn Read) -> Result<Self, Error> {
|
||||||
|
Ok(
|
||||||
|
BootstrapMethodsData {
|
||||||
|
bootstrap_methods: {
|
||||||
|
let length = read_u16(reader)?;
|
||||||
|
let mut v = Vec::with_capacity(length.into());
|
||||||
|
|
||||||
|
for _i in 0..length {
|
||||||
|
v.push(BootstrapMethodEntry::from_reader(reader)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
v.into_boxed_slice()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum AttributeData {
|
pub enum AttributeData {
|
||||||
Code(CodeAttributeData),
|
Code(CodeAttributeData),
|
||||||
|
BootstrapMethods(BootstrapMethodsData),
|
||||||
Signature(SignatureAttributeData),
|
Signature(SignatureAttributeData),
|
||||||
Synthetic(),
|
Synthetic(),
|
||||||
Exceptions(ExceptionAttributeData),
|
Exceptions(ExceptionAttributeData),
|
||||||
|
@ -755,6 +817,10 @@ impl AttributeInfo {
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
|
||||||
|
"BootstrapMethods" => AttributeData::BootstrapMethods(
|
||||||
|
BootstrapMethodsData::from_reader(reader)?,
|
||||||
|
),
|
||||||
|
|
||||||
"LineNumberTable" => AttributeData::LineNumberTable(
|
"LineNumberTable" => AttributeData::LineNumberTable(
|
||||||
LineNumberTableAttributeData::from_reader(reader)?
|
LineNumberTableAttributeData::from_reader(reader)?
|
||||||
),
|
),
|
||||||
|
|
|
@ -16,7 +16,7 @@ pub struct ClassStore {
|
||||||
pub array_classes: HashMap<AbstractTypeDescription, ObjectReference>,
|
pub array_classes: HashMap<AbstractTypeDescription, ObjectReference>,
|
||||||
pub classes: Vec<ClassStoreEntry>,
|
pub classes: Vec<ClassStoreEntry>,
|
||||||
pub class_path_fragments: Vec<PathBuf>,
|
pub class_path_fragments: Vec<PathBuf>,
|
||||||
pub native_class_names: Vec<String>,
|
pub native_class_descriptors: Vec<String>,
|
||||||
pub primitive_classes: PrimitiveClassStore,
|
pub primitive_classes: PrimitiveClassStore,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ impl ClassStore {
|
||||||
array_classes: HashMap::new(),
|
array_classes: HashMap::new(),
|
||||||
classes: Vec::new(),
|
classes: Vec::new(),
|
||||||
class_path_fragments: vec![current_dir_path],
|
class_path_fragments: vec![current_dir_path],
|
||||||
native_class_names: Vec::new(),
|
native_class_descriptors: Vec::new(),
|
||||||
primitive_classes: PrimitiveClassStore::default(),
|
primitive_classes: PrimitiveClassStore::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,12 +106,12 @@ impl ClassStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_native_class_descriptor(&mut self, name: String) -> usize {
|
pub fn add_native_class_descriptor(&mut self, name: String) -> usize {
|
||||||
self.native_class_names.push(name);
|
self.native_class_descriptors.push(name);
|
||||||
return self.native_class_names.len() - 1;
|
return self.native_class_descriptors.len() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_native_class_name(&self, index: usize) -> &String {
|
pub fn get_native_class_name(&self, index: usize) -> &String {
|
||||||
return &self.native_class_names[index];
|
return &self.native_class_descriptors[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_class_from_file(&mut self, class_file_path: &PathBuf) -> Result<usize, Error> {
|
pub fn load_class_from_file(&mut self, class_file_path: &PathBuf) -> Result<usize, Error> {
|
||||||
|
|
|
@ -223,7 +223,7 @@ impl ObjectArea {
|
||||||
fn make_array(&mut self, class_store: &ClassStore, elements: Box<[ObjectReference]>) -> (ObjectReference, usize) {
|
fn make_array(&mut self, class_store: &ClassStore, elements: Box<[ObjectReference]>) -> (ObjectReference, usize) {
|
||||||
assert!(elements.len() != 0);
|
assert!(elements.len() != 0);
|
||||||
let array_element_class_name = self.get_reference_native_class_name(elements[0], class_store);
|
let array_element_class_name = self.get_reference_native_class_name(elements[0], class_store);
|
||||||
let array_element_type_desc = AbstractTypeDescription::parse_first(array_element_class_name).unwrap().1;
|
let array_element_type_desc = AbstractTypeDescription::parse_full(array_element_class_name).unwrap();
|
||||||
|
|
||||||
let (array_object_ref, array_size) = self.make_empty_array(class_store, array_element_type_desc, elements.len());
|
let (array_object_ref, array_size) = self.make_empty_array(class_store, array_element_type_desc, elements.len());
|
||||||
|
|
||||||
|
@ -255,6 +255,23 @@ impl ObjectArea {
|
||||||
return (object_ref, object_size);
|
return (object_ref, object_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn class_ref_get_class_index(&self, class_ref: ObjectReference, class_store: &ClassStore) -> usize {
|
||||||
|
let class_data_ref = match self.get_object_field(class_ref, "classData", self.get_object_class_index(class_ref), class_store).unwrap() {
|
||||||
|
FieldValue::Reference(r) => r,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
let native_name_index = match self.get_object_field(class_data_ref, "native_class_descriptor_index", self.get_object_class_index(class_data_ref), class_store).unwrap() {
|
||||||
|
FieldValue::Int(i) => i,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let native_class_name = class_store.get_native_class_name(native_name_index as usize);
|
||||||
|
|
||||||
|
let native_class_index = class_store.class_index_for_type(AbstractTypeDescription::parse_full(native_class_name).unwrap()).unwrap();
|
||||||
|
|
||||||
|
return native_class_index;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_class_ref_native_class_name<'a>(&self, class_ref: ObjectReference, class_store: &'a ClassStore) -> &'a String {
|
pub fn get_class_ref_native_class_name<'a>(&self, class_ref: ObjectReference, class_store: &'a ClassStore) -> &'a String {
|
||||||
let class_data_ref = match self.get_object_field(class_ref, "classData", self.get_object_class_index(class_ref), class_store).unwrap() {
|
let class_data_ref = match self.get_object_field(class_ref, "classData", self.get_object_class_index(class_ref), class_store).unwrap() {
|
||||||
FieldValue::Reference(r) => r,
|
FieldValue::Reference(r) => r,
|
||||||
|
|
11
src/jvm.rs
11
src/jvm.rs
|
@ -1471,6 +1471,10 @@ impl JVM {
|
||||||
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(instruction_result)))?;
|
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(instruction_result)))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Instruction::InvokeDynamic(invokedynamic_index, _zero) => {
|
||||||
|
let methodhandle_reference = class.pool_methodhandle_entry(invokedynamic_index)?;
|
||||||
|
}
|
||||||
|
|
||||||
Instruction::InvokeInterface(methodref_index) => {
|
Instruction::InvokeInterface(methodref_index) => {
|
||||||
let (supplied_interface_name, supplied_method_name, supplied_descriptor_string) = class.gather_interfacemethodref(methodref_index)?;
|
let (supplied_interface_name, supplied_method_name, supplied_descriptor_string) = class.gather_interfacemethodref(methodref_index)?;
|
||||||
|
|
||||||
|
@ -2600,6 +2604,13 @@ impl JVM {
|
||||||
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(value_1 ^ value_2)))?;
|
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(value_1 ^ value_2)))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Instruction::XorLong() => {
|
||||||
|
let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
|
||||||
|
let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
|
||||||
|
|
||||||
|
wrap_stackframe_error(class, method, frame.operand_stack.push_long(value_1 ^ value_2))?;
|
||||||
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::RunTimeError(format!("Opcode not implemented yet: {:?}", instruction)))
|
return Err(Error::RunTimeError(format!("Opcode not implemented yet: {:?}", instruction)))
|
||||||
},
|
},
|
||||||
|
|
|
@ -25,9 +25,9 @@ fn main() {
|
||||||
jvm.class_store.class_path_fragments.push(PathBuf::from("./classpath"));
|
jvm.class_store.class_path_fragments.push(PathBuf::from("./classpath"));
|
||||||
|
|
||||||
match jvm.entrypoint(
|
match jvm.entrypoint(
|
||||||
&"Main".to_string(),
|
&"SiedepunktNamen".to_string(),
|
||||||
&"main".to_string(),
|
&"main".to_string(),
|
||||||
&["Hello World"],
|
&["5"],
|
||||||
) {
|
) {
|
||||||
Ok(()) => (),
|
Ok(()) => (),
|
||||||
Err(e) => println!("{:#?}", e),
|
Err(e) => println!("{:#?}", e),
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
use std::time::SystemTime;
|
||||||
|
use std::time::UNIX_EPOCH;
|
||||||
|
|
||||||
|
use crate::accessmasks::FieldAccessFlag;
|
||||||
use crate::classfile::FieldInfo;
|
use crate::classfile::FieldInfo;
|
||||||
use crate::classstore::ClassStore;
|
use crate::classstore::ClassStore;
|
||||||
use crate::stackframe::StackFrame;
|
use crate::stackframe::StackFrame;
|
||||||
|
@ -58,6 +62,59 @@ impl JavaIOFileDescriptor {
|
||||||
struct JavaLangClass {}
|
struct JavaLangClass {}
|
||||||
|
|
||||||
impl JavaLangClass {
|
impl JavaLangClass {
|
||||||
|
fn get_declared_fields_0(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
|
let frame = {
|
||||||
|
let thread = &mut jvm.threads[jvm.active_thread];
|
||||||
|
let frame_index = thread.stack_frames.len() - 1;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
|
};
|
||||||
|
let this = frame.load_local_reference(0).unwrap();
|
||||||
|
let public_only = frame.load_local_boolean_compatible(1).unwrap();
|
||||||
|
let class_index = jvm.heap_area.object_area.class_ref_get_class_index(this, &jvm.class_store);
|
||||||
|
|
||||||
|
if ! jvm.class_store.have_class(&"java/lang/reflect/Field".to_string()) {
|
||||||
|
return Ok(JVMCallbackOperation::LoadClass("java/lang/reflect/Field".to_string()));
|
||||||
|
}
|
||||||
|
if ! jvm.class_store.was_init(&"java/lang/reflect/Field".to_string()).unwrap() {
|
||||||
|
return Ok(JVMCallbackOperation::InitClass("java/lang/reflect/Field".to_string()));
|
||||||
|
}
|
||||||
|
if ! jvm.class_store.have_class(&"[Ljava/lang/reflect/Field;".to_string()) {
|
||||||
|
let description = AbstractTypeDescription {
|
||||||
|
array_level: 0,
|
||||||
|
kind: AbstractTypeKind::Classname("java/lang/reflect/Field".to_string()),
|
||||||
|
};
|
||||||
|
return Ok(JVMCallbackOperation::MakeArrayClass(this, description));
|
||||||
|
}
|
||||||
|
let field_class_index = jvm.class_store.class_idx_from_name(&"java/lang/reflect/Field".to_string()).unwrap();
|
||||||
|
|
||||||
|
let fields = ClassFieldIterator::new(class_index, &jvm.class_store)
|
||||||
|
.filter(|field_info| if public_only { field_info.access_flags & FieldAccessFlag::Public } else { true } )
|
||||||
|
.map(|field_info| {
|
||||||
|
let field = jvm.heap_area.make_object(&jvm.class_store, field_class_index);
|
||||||
|
let java_string = jvm.heap_area.make_handmade_string(&field_info.name, &jvm.class_store);
|
||||||
|
jvm.heap_area.object_area.set_object_field(
|
||||||
|
field,
|
||||||
|
"name",
|
||||||
|
java_string.into(),
|
||||||
|
field_class_index,
|
||||||
|
&jvm.class_store
|
||||||
|
).unwrap();
|
||||||
|
jvm.heap_area.object_area.set_object_field(
|
||||||
|
field,
|
||||||
|
"clazz",
|
||||||
|
this.into(),
|
||||||
|
field_class_index,
|
||||||
|
&jvm.class_store
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
|
field
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let field_array = jvm.heap_area.make_array(&jvm.class_store, fields);
|
||||||
|
|
||||||
|
Ok(JVMCallbackOperation::ReturnFrame(field_array.into()))
|
||||||
|
}
|
||||||
|
|
||||||
fn is_array(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
fn is_array(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
let frame = {
|
let frame = {
|
||||||
|
@ -500,6 +557,12 @@ impl JavaLangStringUTF16 {
|
||||||
struct JavaLangSystem {}
|
struct JavaLangSystem {}
|
||||||
|
|
||||||
impl JavaLangSystem {
|
impl JavaLangSystem {
|
||||||
|
fn nano_time(_: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
|
let nanos = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_nanos() as i64;
|
||||||
|
|
||||||
|
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Long(nanos)))
|
||||||
|
}
|
||||||
|
|
||||||
fn register_natives(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
fn register_natives(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
// Load class because it won't be loaded otherwise
|
// Load class because it won't be loaded otherwise
|
||||||
let frame = {
|
let frame = {
|
||||||
|
@ -849,7 +912,18 @@ impl JdkInternalMiscUnsafe {
|
||||||
|
|
||||||
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Boolean(success)))
|
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Boolean(success)))
|
||||||
} else {
|
} else {
|
||||||
todo!()
|
let object_class_descriptor = jvm.heap_area.object_area.get_reference_native_class_name(object, &jvm.class_store);
|
||||||
|
let object_class_index = jvm.class_store.class_index_for_type(AbstractTypeDescription::parse_full(object_class_descriptor).unwrap()).unwrap();
|
||||||
|
|
||||||
|
let field = JdkInternalMiscUnsafe::class_field_at_offset(object_class_index, &jvm.class_store, offset)?;
|
||||||
|
|
||||||
|
let current_value = jvm.heap_area.object_area.get_object_field(object, &field.name, object_class_index, &jvm.class_store)?;
|
||||||
|
let function_result = current_value == expected.into();
|
||||||
|
if function_result {
|
||||||
|
jvm.heap_area.object_area.set_object_field(object, &field.name, replacement.into(), object_class_index, &jvm.class_store)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Boolean(function_result)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1003,6 +1077,46 @@ impl JdkInternalMiscUnsafe {
|
||||||
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Boolean(function_result)))
|
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Boolean(function_result)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn object_field_offset_0(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
|
let frame = {
|
||||||
|
let thread = &mut jvm.threads[jvm.active_thread];
|
||||||
|
let frame_index = thread.stack_frames.len() - 1;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
|
};
|
||||||
|
let field_object_reference = frame.load_local_reference(1).unwrap();
|
||||||
|
let field_class_index = jvm.heap_area.object_area.get_reference_class_index(field_object_reference, &jvm.class_store);
|
||||||
|
|
||||||
|
let class = jvm.heap_area.object_area.get_object_field(
|
||||||
|
field_object_reference,
|
||||||
|
"clazz",
|
||||||
|
field_class_index,
|
||||||
|
&jvm.class_store
|
||||||
|
)?.expect_reference();
|
||||||
|
let field_name = jvm.heap_area.object_area.get_object_field(
|
||||||
|
field_object_reference,
|
||||||
|
"name",
|
||||||
|
field_class_index,
|
||||||
|
&jvm.class_store
|
||||||
|
)?.expect_reference();
|
||||||
|
|
||||||
|
let byte_offset = JdkInternalMiscUnsafe::object_field_offset_2(jvm, class, field_name)?;
|
||||||
|
|
||||||
|
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Long(byte_offset)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn object_field_offset_2(jvm: &mut JVM, class_object_reference: ObjectReference, field_name_string_reference: ObjectReference) -> Result<i64, Error> {
|
||||||
|
let class_descriptor = jvm.heap_area.object_area.get_class_ref_native_class_name(class_object_reference, &jvm.class_store);
|
||||||
|
let class_index = jvm.class_store.class_index_for_type(AbstractTypeDescription::parse_full(class_descriptor).unwrap()).unwrap();
|
||||||
|
let rust_field_name_string = jvm.heap_area.decode_java_string(field_name_string_reference, &jvm.class_store);
|
||||||
|
|
||||||
|
let byte_offset: i64 = ClassFieldIterator::new(class_index as usize, &jvm.class_store)
|
||||||
|
.take_while(|f| f.name != rust_field_name_string)
|
||||||
|
.map(|f| f.descriptor.storage_size() as i64)
|
||||||
|
.sum();
|
||||||
|
|
||||||
|
Ok(byte_offset)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn object_field_offset_1(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
pub fn object_field_offset_1(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
// args: Class class, String fieldName
|
// args: Class class, String fieldName
|
||||||
let frame = {
|
let frame = {
|
||||||
|
@ -1012,16 +1126,9 @@ impl JdkInternalMiscUnsafe {
|
||||||
};
|
};
|
||||||
|
|
||||||
let class_object_reference = frame.load_local_reference(1).unwrap();
|
let class_object_reference = frame.load_local_reference(1).unwrap();
|
||||||
let class_descriptor = jvm.heap_area.object_area.get_class_ref_native_class_name(class_object_reference, &jvm.class_store);
|
|
||||||
let class_index = jvm.class_store.class_index_for_type(AbstractTypeDescription::parse_full(class_descriptor).unwrap()).unwrap();
|
|
||||||
let field_name_string_reference = frame.load_local_reference(2).unwrap();
|
let field_name_string_reference = frame.load_local_reference(2).unwrap();
|
||||||
|
|
||||||
let rust_field_name_string = jvm.heap_area.decode_java_string(field_name_string_reference, &jvm.class_store);
|
let byte_offset = JdkInternalMiscUnsafe::object_field_offset_2(jvm, class_object_reference, field_name_string_reference)?;
|
||||||
|
|
||||||
let byte_offset: i64 = ClassFieldIterator::new(class_index as usize, &jvm.class_store)
|
|
||||||
.take_while(|f| f.name != rust_field_name_string)
|
|
||||||
.map(|f| f.descriptor.storage_size() as i64)
|
|
||||||
.sum();
|
|
||||||
|
|
||||||
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Long(byte_offset)))
|
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Long(byte_offset)))
|
||||||
}
|
}
|
||||||
|
@ -1257,7 +1364,7 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
|
||||||
]),
|
]),
|
||||||
return_type: AbstractTypeDescription { array_level: 1, kind: AbstractTypeKind::Classname("java/lang/reflect/Field".to_string()) },
|
return_type: AbstractTypeDescription { array_level: 1, kind: AbstractTypeKind::Classname("java/lang/reflect/Field".to_string()) },
|
||||||
},
|
},
|
||||||
todo_call
|
JavaLangClass::get_declared_fields_0
|
||||||
),
|
),
|
||||||
|
|
||||||
(
|
(
|
||||||
|
@ -1784,7 +1891,7 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
|
||||||
]),
|
]),
|
||||||
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Long()},
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Long()},
|
||||||
},
|
},
|
||||||
todo_call
|
JavaLangSystem::nano_time
|
||||||
),
|
),
|
||||||
|
|
||||||
(
|
(
|
||||||
|
@ -2543,7 +2650,7 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
|
||||||
]),
|
]),
|
||||||
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Long()},
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Long()},
|
||||||
},
|
},
|
||||||
todo_call
|
JdkInternalMiscUnsafe::object_field_offset_0
|
||||||
),
|
),
|
||||||
|
|
||||||
(
|
(
|
||||||
|
|
|
@ -430,6 +430,23 @@ impl StackFrame {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn load_local_boolean_compatible(&self, index: u16) -> Result<bool, Error> {
|
||||||
|
let local = self.locals[index as usize];
|
||||||
|
match local {
|
||||||
|
StackValue::Boolean(b) => Ok(b),
|
||||||
|
StackValue::Int(i) => Ok(i != 0),
|
||||||
|
_ => Err(Error::LocalError(format!("Mismatched type at index {} of the function locals, expected Boolean but found '{:?}'", index, local)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_local_boolean(&self, index: u16) -> Result<bool, Error> {
|
||||||
|
let local = self.locals[index as usize];
|
||||||
|
match local {
|
||||||
|
StackValue::Boolean(b) => Ok(b),
|
||||||
|
_ => Err(Error::LocalError(format!("Mismatched type at index {} of the function locals, expected Boolean but found '{:?}'", index, local)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn load_local_int(&self, index: u16) -> Result<i32, Error> {
|
pub fn load_local_int(&self, index: u16) -> Result<i32, Error> {
|
||||||
let local = self.locals[index as usize];
|
let local = self.locals[index as usize];
|
||||||
match local {
|
match local {
|
||||||
|
|
Loading…
Reference in a new issue