diff --git a/src/bytecode.rs b/src/bytecode.rs index dba6b3d..7573b21 100644 --- a/src/bytecode.rs +++ b/src/bytecode.rs @@ -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), diff --git a/src/classfile.rs b/src/classfile.rs index 0027c80..014ddc5 100644 --- a/src/classfile.rs +++ b/src/classfile.rs @@ -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); } diff --git a/src/heap_area.rs b/src/heap_area.rs index 03f18e4..57969a2 100644 --- a/src/heap_area.rs +++ b/src/heap_area.rs @@ -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::() + std::mem::size_of::(); + + 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::() + std::mem::size_of::() * array_object.content.len(); + let array_size = std::mem::size_of::() + std::mem::size_of::() * 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]>, } diff --git a/src/jvm.rs b/src/jvm.rs index 4b582f7..6bb2eeb 100644 --- a/src/jvm.rs +++ b/src/jvm.rs @@ -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> {