Working up until registerNatives()

This commit is contained in:
VegOwOtenks 2024-09-06 23:51:35 +02:00
parent 5bc0d813e5
commit 3282694b32
4 changed files with 268 additions and 58 deletions

View file

@ -25,6 +25,7 @@ impl Bytecode {
0x10 => (Instruction::LoadByteImmediate(self.bytes[offset+1]), 2),
0x11 => (Instruction::LoadShortImmediate((self.bytes[offset+1] as u16) << 8 | self.bytes[offset+2] as u16), 3),
0x12 => (Instruction::LoadConstant(self.bytes[offset+1]), 2),
0x13 => (Instruction::LoadWideConstant((self.bytes[offset+1] as u16) << 8 | self.bytes[offset+2] as u16), 3),
0x14 => (Instruction::LoadConstant64((self.bytes[offset+1] as u16) << 8 | self.bytes[offset+2] as u16), 3),
0x1A => (Instruction::LoadLocalInt0(), 1),
@ -41,6 +42,7 @@ impl Bytecode {
0x2D => (Instruction::LoadLocalReference3(), 1),
0x32 => (Instruction::ArrayElement(), 1),
0x36 => (Instruction::StoreLocalInt(self.bytes[offset+1]), 2),
0x3B => (Instruction::StoreLocalInt0(), 1),
0x3C => (Instruction::StoreLocalInt1(), 1),
0x3D => (Instruction::StoreLocalInt2(), 1),
@ -50,6 +52,9 @@ impl Bytecode {
0x4D => (Instruction::StoreReference2(), 1),
0x4E => (Instruction::StoreReference3(), 1),
0x53 => (Instruction::StoreIntoRArray(), 1),
0x54 => (Instruction::StoreIntoBArray(), 1),
0x57 => (Instruction::Pop(), 1),
0x59 => (Instruction::Duplicate(), 1),
@ -85,6 +90,31 @@ impl Bytecode {
(Instruction::BranchNonNegative(i16::from_be_bytes(bytes)), 3)
}
0x9F => {
let bytes = [self.bytes[offset+1], self.bytes[offset+2]];
(Instruction::BranchIntEquality(i16::from_be_bytes(bytes)), 3)
}
0xA0 => {
let bytes = [self.bytes[offset+1], self.bytes[offset+2]];
(Instruction::BranchIntInequality(i16::from_be_bytes(bytes)), 3)
}
0xA1 => {
let bytes = [self.bytes[offset+1], self.bytes[offset+2]];
(Instruction::BranchIntLessThan(i16::from_be_bytes(bytes)), 3)
}
0xA2 => {
let bytes = [self.bytes[offset+1], self.bytes[offset+2]];
(Instruction::BranchIntGreaterEquals(i16::from_be_bytes(bytes)), 3)
}
0xA3 => {
let bytes = [self.bytes[offset+1], self.bytes[offset+2]];
(Instruction::BranchIntGreaterThan(i16::from_be_bytes(bytes)), 3)
}
0xA4 => {
let bytes = [self.bytes[offset+1], self.bytes[offset+2]];
(Instruction::BranchIntLessEquals(i16::from_be_bytes(bytes)), 3)
}
0xAC => (Instruction::ReturnInt(), 1),
0xA7 => {
let bytes = [self.bytes[offset+1], self.bytes[offset+2]];
@ -102,6 +132,7 @@ impl Bytecode {
0xB8 => (Instruction::InvokeStatic((self.bytes[offset+1] as u16) << 8 | self.bytes[offset+2] as u16), 3),
0xBA => (Instruction::InvokeDynamic((self.bytes[offset+1] as u16) << 8 | self.bytes[offset+2] as u16, (self.bytes[offset+3] as u16) << 8 | self.bytes[offset+4] as u16), 5),
0xBB => (Instruction::NewObject((self.bytes[offset+1] as u16) << 8 | self.bytes[offset+2] as u16), 3),
0xBC => (Instruction::NewPrimitiveArray(self.bytes[offset+1]), 2),
0xBD => (Instruction::NewArray((self.bytes[offset+1] as u16) << 8 | self.bytes[offset+2] as u16), 3),
0xBE => (Instruction::ArrayLength(), 1),
_ => (Instruction::Unknown(opcode), 1)
@ -150,6 +181,8 @@ pub enum Instruction {
LoadByteImmediate(u8) = 0x10, // push immediate short
LoadShortImmediate(u16) = 0x11, // push immediate short
LoadConstant(u8) = 0x12, // Push from constant pool
LoadWideConstant(u16) = 0x13, // Push from constant pool with wide index, don't load
// double or long or whatever
LoadConstant64(u16) = 0x14, // Push Long or Double from constant pool
LoadLocalInt0() = 0x1A, // Load int from local variable
LoadLocalInt1() = 0x1B, // Load int from local variable
@ -166,6 +199,7 @@ pub enum Instruction {
LoadLocalReference3() = 0x2D, // Load local reference variable reference onto stack
ArrayElement() = 0x32, // load element from array
StoreLocalInt(u8) = 0x36, // store into indexed local variable
StoreLocalInt0() = 0x3B, // store int into local variable
StoreLocalInt1() = 0x3C, // store int into local variable
StoreLocalInt2() = 0x3D, // store int into local variable
@ -175,6 +209,8 @@ pub enum Instruction {
StoreReference2() = 0x4D, // store reference into local variable
StoreReference3() = 0x4E, // store reference into local variable
StoreIntoRArray() = 0x53, // store value into reference array
StoreIntoBArray() = 0x54, // store value into byte or boolean array
Pop() = 0x57, // Pop top stack value
Duplicate() = 0x59, // duplicate top stack value
@ -197,6 +233,7 @@ pub enum Instruction {
BranchIntLessThan(i16) = 0xA1,
BranchIntGreaterEquals(i16) = 0xA2,
BranchIntGreaterThan(i16) = 0xA3,
BranchIntLessEquals(i16) = 0xA4,
BranchAlways(i16) = 0xA7, // branch if true
ReturnInt() = 0xAC, // return integer from function
@ -212,6 +249,7 @@ pub enum Instruction {
InvokeStatic(u16) = 0xB8, // invoke static function
InvokeDynamic(u16, u16) = 0xBA, // invoke dynamic function
NewObject(u16) = 0xBB, // Create a new object from a constant-pool class reference
NewPrimitiveArray(u8) = 0xBC, // make a primitive array
NewArray(u16) = 0xBD, // Create a new array from a constant-pool component class reference
ArrayLength() = 0xBE, // Get length from array reference
Unknown(u8),

View file

@ -202,7 +202,7 @@ impl JavaClassFile {
return None;
}
fn pool_entry(&self, index: u16) -> Result<&ConstantPoolInfo, Error> {
pub fn pool_entry(&self, index: u16) -> Result<&ConstantPoolInfo, Error> {
return pool_entry(&self.constant_pool, index);
}

View file

@ -55,6 +55,13 @@ impl HeapArea {
self.memory_used += self.object_area.fill_byte_cache(class_store);
}
pub fn make_primitive_byte_array(&mut self, capacity: usize, class_store: &ClassStore) -> ObjectReference {
let (array_ref, size) = self.object_area.make_primitive_byte_array(capacity, class_store);
self.memory_used += size;
array_ref
}
pub fn make_handmade_string(&mut self, s: &String, class_store: &ClassStore) -> ObjectReference {
let utf16_bytes = {
let utf16 = s.encode_utf16();
@ -127,8 +134,29 @@ impl ObjectArea {
self.byte_object_cache[byte as usize]
}
fn make_primitive_byte_array(&mut self, capacity: usize, class_store: &ClassStore) -> (ObjectReference, usize) {
// make new type desc
let array_type_desc = AbstractTypeDescription {
array_level: 1,
kind: AbstractTypeKind::Byte(),
};
let array_class_ref = class_store.get_array_class_ref(&array_type_desc).unwrap();
let array_size = capacity * std::mem::size_of::<u8>() + std::mem::size_of::<ByteArray>();
let array_object = ByteArray {
class_ref: array_class_ref,
content: vec![0_u8; capacity].into(),
};
let array_ref = self.store_entry(CompartmentEntry::ByteArray(array_object));
(array_ref, array_size)
}
fn make_empty_array(&mut self, class_store: &ClassStore, element_type_desc: AbstractTypeDescription, capacity: usize) -> (ObjectReference, usize) {
//
// make new type desc
let array_type_desc = AbstractTypeDescription {
array_level: 1 + element_type_desc.array_level,
@ -137,14 +165,14 @@ impl ObjectArea {
let array_class_ref = class_store.get_array_class_ref(&array_type_desc).unwrap();
let array_object = HeapArray {
let array_object = ReferenceArray {
class_ref: array_class_ref,
content: vec![ObjectReference::NULL; capacity].into_boxed_slice(),
};
let array_size = std::mem::size_of::<HeapArray>() + std::mem::size_of::<ObjectReference>() * array_object.content.len();
let array_size = std::mem::size_of::<ReferenceArray>() + std::mem::size_of::<ObjectReference>() * array_object.content.len();
let array_object_ref = self.store_entry(CompartmentEntry::Array(array_object));
let array_object_ref = self.store_entry(CompartmentEntry::ReferenceArray(array_object));
self.memory_used += array_size;
@ -159,13 +187,13 @@ impl ObjectArea {
let (array_object_ref, array_size) = self.make_empty_array(class_store, array_element_type_desc, elements.len());
for (index, element) in elements.iter().enumerate() {
self.set_array_element(array_object_ref, index, *element);
self.set_array_element(array_object_ref, index, FieldValue::Reference(*element));
}
return (array_object_ref, array_size);
}
pub fn make(&mut self, class_store: &ClassStore, target_class_index: usize) -> (ObjectReference, usize) {
fn make(&mut self, class_store: &ClassStore, target_class_index: usize) -> (ObjectReference, usize) {
let fields: Vec<_> = ClassFieldIterator::new(target_class_index, class_store)
.filter(|f| ! (f.access_flags & FieldAccessFlag::Static))
.map(|f| ObjectField { value: FieldValue::default_for(&f.descriptor) })
@ -210,7 +238,7 @@ impl ObjectArea {
fn get_reference_class_ref(&self, reference: ObjectReference, class_store: &ClassStore) -> ObjectReference {
match self.get_entry(reference) {
CompartmentEntry::Object(o) => class_store.get_class_objectref_from_index(o.class_index),
CompartmentEntry::Array(a) => a.class_ref,
CompartmentEntry::ReferenceArray(a) => a.class_ref,
_ => unreachable!(),
}
}
@ -230,7 +258,7 @@ impl ObjectArea {
return ObjectReference(object_index + (DEFAULT_COMPARTMENT_CAPACITY * (compartment_index as u32 + 1)));
}
fn get_entry(&self, reference: ObjectReference) -> &CompartmentEntry {
pub fn get_entry(&self, reference: ObjectReference) -> &CompartmentEntry {
let index = reference.0;
let compartment_index: u32 = (index / DEFAULT_COMPARTMENT_CAPACITY) - 1;
let object_index: u32 = index % DEFAULT_COMPARTMENT_CAPACITY;
@ -255,7 +283,7 @@ impl ObjectArea {
pub fn get_array_length(&self, reference: ObjectReference) -> usize {
// TODO: Throw errors
let array = match self.get_entry(reference) {
CompartmentEntry::Array(a) => a,
CompartmentEntry::ReferenceArray(a) => a,
_ => unreachable!(),
};
@ -265,7 +293,7 @@ impl ObjectArea {
pub fn get_array_element(&self, array_ref: ObjectReference, element_index: i32) -> ObjectReference {
// TODO: Throw errors
let array = match self.get_entry(array_ref) {
CompartmentEntry::Array(a) => a,
CompartmentEntry::ReferenceArray(a) => a,
_ => unreachable!(),
};
@ -301,15 +329,21 @@ impl ObjectArea {
}
}
pub fn set_array_element(&mut self, array_reference: ObjectReference, index: usize, element: ObjectReference) {
let array = match self.get_entry_mut(array_reference) {
CompartmentEntry::Array(a) => a,
pub fn set_array_element(&mut self, array_reference: ObjectReference, index: usize, element: FieldValue) {
match self.get_entry_mut(array_reference) {
CompartmentEntry::ReferenceArray(array) => {
let array_element = array.content.get_mut(index).unwrap();
*array_element = match element { FieldValue::Reference(r) => r, _ => unreachable!() } ;
},
CompartmentEntry::ByteArray(array) => {
let array_element = array.content.get_mut(index).unwrap();
*array_element = match element { FieldValue::Byte(b) => b, _ => unreachable!() } ;
},
_ => unreachable!(),
};
let array_element = array.content.get_mut(index).unwrap();
*array_element = element;
}
pub fn set_object_field(&mut self, reference: ObjectReference, field_name: &str, value: FieldValue, accessing_class_idx: usize, class_store: &ClassStore) -> Result<(), Error> {
@ -392,7 +426,8 @@ impl ObjectCompartment {
},
CompartmentEntry::Object(_) => unreachable!(),
CompartmentEntry::Array(_) => unreachable!(),
CompartmentEntry::ReferenceArray(_) => unreachable!(),
CompartmentEntry::ByteArray(_) => unreachable!(),
}
*self.objects.get_mut(compartment_index).unwrap() = object;
@ -420,13 +455,20 @@ impl DebugTrait for ObjectCompartment {
#[derive(Debug)]
pub enum CompartmentEntry {
Object(HeapObject),
Array(HeapArray),
ReferenceArray(ReferenceArray),
ByteArray(ByteArray),
EmptyNext(usize),
EmptyTail(), // last empty value
}
#[derive(Debug)]
pub struct HeapArray {
pub struct ByteArray {
class_ref: ObjectReference,
content: Box<[u8]>,
}
#[derive(Debug)]
pub struct ReferenceArray {
class_ref: ObjectReference,
content: Box<[ObjectReference]>,
}

View file

@ -10,8 +10,8 @@ use crate::classfile::{ JavaClassFile, FieldInfo, MethodInfo, MethodDescriptor,
use crate::classstore;
use crate::classstore::ClassStore;
use crate::constantpool::{ ConstantPoolInfo, ConstantClassInfo, ConstantUtf8Info, ConstantMethodRefInfo, ConstantNameAndTypeInfo};
use crate::heap_area::{ HeapArea, FieldValue, ObjectReference };
use crate::iterators::{ ClassMethodIterator, ClassFieldIterator, CompatibleTypesIterator };
use crate::heap_area::{ HeapArea, FieldValue, ObjectReference, CompartmentEntry };
use crate::iterators::{ ClassMethodIterator, ClassFieldIterator };
use crate::stackframe;
use crate::stackframe::{ StackFrame, StackValue, OperandStack };
@ -129,21 +129,8 @@ impl JVM {
self.class_store.set_class_objectref_by_index(self.class_store.class_idx_from_name(&parsed_class_name).unwrap(), class_object);
}
fn make_array_class(&mut self, element_descriptor_string: &str) {
let (chars_consumed, element_descriptor) = AbstractTypeDescription::parse_first(element_descriptor_string).unwrap();
assert!(chars_consumed == element_descriptor_string.len());
let element_class_ref = if element_descriptor.array_level == 0 {
match element_descriptor.kind {
AbstractTypeKind::Classname(ref name) => {
self.class_store.get_class_objectref_from_index(
self.class_store.class_idx_from_name(&name).unwrap()
)
}
_ => unreachable!(),
}
} else {
self.class_store.get_array_class_ref(&element_descriptor).unwrap()
};
fn make_array_class(&mut self, element_class_ref: ObjectReference, element_descriptor: AbstractTypeDescription) {
let class_class_index = self.class_store.class_idx_from_name(&"java/lang/Class".to_string()).unwrap();
let array_class_object = self.heap_area.make_object(&self.class_store, 6);
let array_class_data_object = self.heap_area.make_object(&self.class_store, 1);
@ -156,7 +143,7 @@ impl JVM {
array_class_object,
"componentType",
FieldValue::Reference(element_class_ref),
self.class_store.class_idx_from_name(&"java/lang/Class".to_string()).unwrap(),
class_class_index,
&self.class_store,
).unwrap();
// set classdata object
@ -164,7 +151,7 @@ impl JVM {
array_class_object,
"classData",
FieldValue::Reference(array_class_data_object),
self.class_store.class_idx_from_name(&"java/lang/Class".to_string()).unwrap(),
class_class_index,
&self.class_store,
).unwrap();
// set native name index on class data
@ -181,6 +168,46 @@ impl JVM {
);
}
fn make_primitive_class(&mut self, class_name: &str, class_descriptor: &str) -> ObjectReference {
let class_class_index = self.class_store.class_idx_from_name(&String::from("java/lang/Class")).unwrap();
let data_class_index = self.class_store.class_idx_from_name(&String::from("::NativeClassData")).unwrap();
let primitive_class_object = self.heap_area.make_object(&self.class_store, class_class_index);
let primitive_class_data_object = self.heap_area.make_object(&self.class_store, data_class_index);
// set classdata object
self.heap_area.object_area.set_object_field(
primitive_class_object,
"classData",
FieldValue::Reference(primitive_class_data_object),
class_class_index,
&self.class_store,
).unwrap();
let name_string_ref = self.heap_area.make_handmade_string(&class_name.into(), &self.class_store);
// set name string object
self.heap_area.object_area.set_object_field(
primitive_class_object,
"name",
FieldValue::Reference(name_string_ref),
class_class_index,
&self.class_store,
).unwrap();
// set native name index on class data
self.heap_area.object_area.set_object_field(
primitive_class_data_object,
"native_class_descriptor_index",
FieldValue::Int(self.class_store.add_native_class_descriptor(class_descriptor.into()) as i32),
self.class_store.class_idx_from_name(&"::NativeClassData".to_string()).unwrap(),
&self.class_store,
).unwrap();
// TODO: Set Static
primitive_class_object
}
pub fn entrypoint(&mut self, class_name: &String, method_name: &String, arguments: &[&str]) -> Result<(), Error> {
let entry_class = JavaClassFile {
minor_version: 0,
@ -259,11 +286,42 @@ impl JVM {
self.make_class_class("Ljava/lang/Byte;");
self.make_class_class("Ljava/lang/String;");
self.make_array_class("Ljava/lang/Byte;");
self.make_array_class("Ljava/lang/String;");
self.make_array_class(
self.class_store.get_class_objectref_from_index(4),
AbstractTypeDescription {
array_level: 0,
kind: AbstractTypeKind::Classname("java/lang/Byte".into()),
}
);
self.make_array_class(
self.class_store.get_class_objectref_from_index(5),
AbstractTypeDescription {
array_level: 0,
kind: AbstractTypeKind::Classname("java/lang/String".into()),
}
);
self.heap_area.fill_byte_cache(&self.class_store);
let int_class_ref = self.make_primitive_class("int", "I");
let byte_class_ref = self.make_primitive_class("byte", "B");
self.make_array_class(
int_class_ref,
AbstractTypeDescription {
array_level: 0,
kind: AbstractTypeKind::Int(),
}
);
self.make_array_class(
byte_class_ref,
AbstractTypeDescription {
array_level: 0,
kind: AbstractTypeKind::Byte(),
}
);
let string_refs = arguments.iter()
.map(|s| self.heap_area.make_handmade_string(&s.to_string(), &self.class_store))
.collect();
@ -312,8 +370,8 @@ impl JVM {
self.init_class_hierarchy(&name)?;
},
JVMCallbackOperation::MakeArrayClass(component_descriptor_string) => {
self.make_array_class(&component_descriptor_string);
JVMCallbackOperation::MakeArrayClass(component_class_ref, component_descriptor) => {
self.make_array_class(component_class_ref, component_descriptor);
}
}
}
@ -519,6 +577,16 @@ impl JVM {
frame.instruction_pointer = if branch_offset < 0 { frame.instruction_pointer - branch_offset.abs() as u32} else { frame.instruction_pointer + branch_offset.abs() as u32};
}
Instruction::BranchIntInequality(branch_offset) => {
let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
if value_1 != value_2 {
frame.instruction_pointer -= offset as u32;
frame.instruction_pointer = if branch_offset < 0 { frame.instruction_pointer - branch_offset.abs() as u32} else { frame.instruction_pointer + branch_offset.abs() as u32};
}
}
Instruction::BranchZero(branch_offset) => {
let test_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
@ -783,6 +851,21 @@ impl JVM {
}
},
Instruction::LoadWideConstant(wide_index) => {
// TODO: Handle error instead of unwrap
match class.pool_entry(wide_index).unwrap() {
ConstantPoolInfo::String(_) => {
// TODO: Handle error instead of unwrap
let string_constant = class.gather_string(wide_index).unwrap();
let string_obj_ref = self.heap_area.make_handmade_string(string_constant, &self.class_store);
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Reference(string_obj_ref)))?;
},
_ => todo!(),
}
},
Instruction::LoadLocalInt0() => {
load_local_int(class, method, frame, 0)?;
}
@ -815,44 +898,61 @@ impl JVM {
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(factor_1 * factor_2)))?;
}
Instruction::NewArray(class_index) => {
Instruction::NewArray(component_class_index) => {
// construct single level array
let class_name = class.gather_class(class_index)?;
let component_class_name = class.gather_class(component_class_index)?;
if ! self.class_store.have_class(class_name) {
if ! self.class_store.have_class(component_class_name) {
// rewind the bytecode offset, I'll need to execute this instruction again
frame.instruction_pointer -= offset as u32;
return Ok(JVMCallbackOperation::LoadClass(class_name.to_string()));
return Ok(JVMCallbackOperation::LoadClass(component_class_name.to_string()));
}
if ! self.class_store.was_init(class_name).unwrap() {
if ! self.class_store.was_init(component_class_name).unwrap() {
// rewind the bytecode offset, I'll need to execute this instruction again
frame.instruction_pointer -= offset as u32;
return Ok(JVMCallbackOperation::InitClass(class_name.to_string()));
return Ok(JVMCallbackOperation::InitClass(component_class_name.to_string()));
}
let class_descriptor = AbstractTypeDescription {
let component_class_descriptor = AbstractTypeDescription {
array_level: 0,
kind: match class_name {
_ => AbstractTypeKind::Classname(class_name.to_string())
kind: match component_class_name {
_ => AbstractTypeKind::Classname(component_class_name.to_string())
}
};
let array_descriptor = AbstractTypeDescription {
array_level: 1,
kind: class_descriptor.kind.clone(),
kind: component_class_descriptor.kind.clone(),
};
if let None = self.class_store.get_array_class_ref(&array_descriptor) {
let complete_type_descriptor = format!("L{};", class_name);
// rewind the bytecode offset, I'll need to execute this instruction again
frame.instruction_pointer -= offset as u32;
return Ok(JVMCallbackOperation::MakeArrayClass(complete_type_descriptor));
let component_class_index = self.class_store.class_idx_from_name(component_class_name).unwrap();
let component_class_class_ref = self.class_store.get_class_objectref_from_index(component_class_index);
return Ok(JVMCallbackOperation::MakeArrayClass(component_class_class_ref, component_class_descriptor));
}
let array_capacity = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
let array_ref = self.heap_area.make_empty_array(&self.class_store, class_descriptor, array_capacity as usize);
let array_ref = self.heap_area.make_empty_array(&self.class_store, component_class_descriptor, array_capacity as usize);
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Reference(array_ref)))?;
}
Instruction::NewPrimitiveArray(array_type) => {
let array_capacity = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
const BYTE: u8 = 8;
let array_ref = match array_type {
BYTE => {
let array_ref = self.heap_area.make_primitive_byte_array(array_capacity as usize, &self.class_store);
array_ref
}
_ => todo!()
};
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Reference(array_ref)))?;
}
@ -990,6 +1090,36 @@ impl JVM {
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(int >> shift)))?;
},
Instruction::StoreIntoRArray() => {
let value = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?;
let index = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
let array_ref = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?;
// TODO: Type checking
self.heap_area.object_area.set_array_element(array_ref, index as usize, FieldValue::Reference(value));
}
Instruction::StoreIntoBArray() => {
let value = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
let index = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
let array_ref = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?;
match self.heap_area.object_area.get_entry(array_ref) {
CompartmentEntry::ByteArray(_) => {
let byte_value = value.to_ne_bytes()[3];
self.heap_area.object_area.set_array_element(array_ref, index as usize, FieldValue::Byte(byte_value));
}
_ => todo!(), // TODO: Handle as error, Boolean arrays also
}
}
Instruction::StoreLocalInt(index) => {
let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
wrap_stackframe_error(class, method, frame.store_local(index as u16, StackValue::Int(int)))?;
},
Instruction::StoreLocalInt0() => {
let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
@ -1051,7 +1181,7 @@ enum JVMCallbackOperation {
PushFrame(StackFrame),
LoadClass(String),
InitClass(String),
MakeArrayClass(String),
MakeArrayClass(ObjectReference, AbstractTypeDescription),
}
fn load_local_reference(class: &JavaClassFile, method: &MethodInfo, frame: &mut StackFrame, index: usize) -> Result<(), Error> {