diff --git a/src/bytecode.rs b/src/bytecode.rs index c720810..cf271cb 100644 --- a/src/bytecode.rs +++ b/src/bytecode.rs @@ -25,16 +25,12 @@ impl Bytecode { 0x0E => (Instruction::PushConstDouble0(), 1), 0x0F => (Instruction::PushConstDouble1(), 1), - 0x10 => (Instruction::LoadByteImmediate(i8::from_be_bytes([self.bytes[offset+1]])), 2), - 0x11 => { - let bytes = [self.bytes[offset+1], self.bytes[offset+2]]; - (Instruction::LoadShortImmediate(i16::from_be_bytes(bytes)), 3) - } + 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::LoadCostantWide((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), - 0x19 => (Instruction::LoadLocalReference(self.bytes[offset+1]), 2), 0x1A => (Instruction::LoadLocalInt0(), 1), 0x1B => (Instruction::LoadLocalInt1(), 1), 0x1C => (Instruction::LoadLocalInt2(), 1), @@ -53,36 +49,30 @@ impl Bytecode { 0x2D => (Instruction::LoadLocalReference3(), 1), 0x32 => (Instruction::ArrayElement(), 1), - 0x33 => (Instruction::LoadFromBArray(), 1), 0x36 => (Instruction::StoreLocalInt(self.bytes[offset+1]), 2), - 0x3A => (Instruction::StoreLocalReference(self.bytes[offset+1]), 2), 0x3B => (Instruction::StoreLocalInt0(), 1), 0x3C => (Instruction::StoreLocalInt1(), 1), 0x3D => (Instruction::StoreLocalInt2(), 1), 0x3E => (Instruction::StoreLocalInt3(), 1), - 0x4B => (Instruction::StoreLocalReference0(), 1), - 0x4C => (Instruction::StoreLocalReference1(), 1), - 0x4D => (Instruction::StoreLocalReference2(), 1), - 0x4E => (Instruction::StoreLocalReference3(), 1), + 0x4B => (Instruction::StoreReference0(), 1), + 0x4C => (Instruction::StoreReference1(), 1), + 0x4D => (Instruction::StoreReference2(), 1), + 0x4E => (Instruction::StoreReference3(), 1), 0x53 => (Instruction::StoreIntoRArray(), 1), 0x54 => (Instruction::StoreIntoBArray(), 1), - 0x55 => (Instruction::StoreIntoCArray(), 1), 0x57 => (Instruction::Pop(), 1), 0x59 => (Instruction::Duplicate(), 1), 0x60 => (Instruction::AddInt(), 1), - 0x64 => (Instruction::SubtractInt(), 1), 0x68 => (Instruction::MultiplyInt(), 1), 0x6C => (Instruction::DivideInt(), 1), 0x6D => (Instruction::DivideLong(), 1), - 0x7A => (Instruction::ArithmeticShiftIntRight(), 1), - 0x7C => (Instruction::LogicalShiftIntRight(), 1), + 0x7A => (Instruction::ShiftIntRight(), 1), 0x80 => (Instruction::OrInt(), 1), - 0x84 => (Instruction::IncrementLocalInt(self.bytes[offset+1], i8::from_be_bytes([self.bytes[offset+2]])), 3), 0x95 => (Instruction::CompareFloatL(), 1), 0x96 => (Instruction::CompareFloatG(), 1), @@ -143,31 +133,13 @@ impl Bytecode { let bytes = [self.bytes[offset+1], self.bytes[offset+2]]; (Instruction::BranchReferenceInequality(i16::from_be_bytes(bytes)), 3) } + + 0xAC => (Instruction::ReturnInt(), 1), 0xA7 => { let bytes = [self.bytes[offset+1], self.bytes[offset+2]]; (Instruction::BranchAlways(i16::from_be_bytes(bytes)), 3) } - 0xAB => { - let padding = 4 - (offset % 4) - 1; - let default_bytes = [self.bytes[offset+padding+1], self.bytes[offset+padding+2], self.bytes[offset+padding+3], self.bytes[offset+padding+4]]; - let default = i32::from_be_bytes(default_bytes); - - let npairs_bytes = [self.bytes[offset+padding+5], self.bytes[offset+padding+6], self.bytes[offset+padding+7], self.bytes[offset+padding+8]]; - let npairs = i32::from_be_bytes(npairs_bytes); - - let mut pairs_vec = Vec::with_capacity(npairs as usize); - for i in 0..npairs as usize { - let match_bytes = [self.bytes[offset+padding+8*(1+i)+1], self.bytes[offset+padding+8*(1+i)+2], self.bytes[offset+padding+8*(1+i)+3], self.bytes[offset+padding+8*(1+i)+4]]; - let offset_bytes = [self.bytes[offset+padding+8*(1+i)+5], self.bytes[offset+padding+8*(1+i)+6], self.bytes[offset+padding+8*(1+i)+7], self.bytes[offset+padding+8*(1+i)+8]]; - - pairs_vec.push((i32::from_be_bytes(match_bytes), i32::from_be_bytes(offset_bytes))); - } - - (Instruction::LookupSwitch(default, pairs_vec.into()), 1 + padding + 4 + 4 + npairs as usize * 8) - } - 0xAC => (Instruction::ReturnInt(), 1), - 0xB0 => (Instruction::ReturnReference(), 1), 0xB1 => (Instruction::ReturnVoid(), 1), 0xB2 => (Instruction::GetStatic((self.bytes[offset+1] as u16) << 8 | self.bytes[offset+2] as u16), 3), @@ -183,7 +155,6 @@ impl Bytecode { 0xBD => (Instruction::NewArray((self.bytes[offset+1] as u16) << 8 | self.bytes[offset+2] as u16), 3), 0xBE => (Instruction::ArrayLength(), 1), - 0xC0 => (Instruction::CheckCast((self.bytes[offset+1] as u16) << 8 | self.bytes[offset+2] as u16), 3), 0xC1 => (Instruction::InstanceOf((self.bytes[offset+1] as u16) << 8 | self.bytes[offset+2] as u16), 3), 0xC2 => (Instruction::EnterMonitor(), 1), 0xC3 => (Instruction::ExitMonitor(), 1), @@ -227,120 +198,111 @@ impl Debug for Bytecode { #[derive(Debug)] #[repr(u8)] pub enum Instruction { - NoOperation() = 0x00, // No-Operation - PushNull() = 0x01, // ..., arrayref, index, value - PushConstIntM1() = 0x02, // Push -1 - PushConstInt0() = 0x03, // Push 0 - PushConstInt1() = 0x04, // Push 1 - PushConstInt2() = 0x05, // Push 2 - PushConstInt3() = 0x06, // Push 3 - PushConstInt4() = 0x07, // Push 4 - PushConstInt5() = 0x08, // Push 5 - PushConstFloat0() = 0x0B, // Push 0.0f - PushConstFloat1() = 0x0C, // Push 1.0f - PushConstFloat2() = 0x0D, // Push 2.0f - PushConstDouble0() = 0x0E, // Push 0.0 - PushConstDouble1() = 0x0F, // Push 1.0 + NoOperation() = 0x00, // No-Operation + PushNull() = 0x01, // ..., arrayref, index, value + PushConstIntM1() = 0x02, // Push -1 + PushConstInt0() = 0x03, // Push 0 + PushConstInt1() = 0x04, // Push 1 + PushConstInt2() = 0x05, // Push 2 + PushConstInt3() = 0x06, // Push 3 + PushConstInt4() = 0x07, // Push 4 + PushConstInt5() = 0x08, // Push 5 + PushConstFloat0() = 0x0B, // Push 0.0f + PushConstFloat1() = 0x0C, // Push 1.0f + PushConstFloat2() = 0x0D, // Push 2.0f + PushConstDouble0() = 0x0E, // Push 0.0 + PushConstDouble1() = 0x0F, // Push 1.0 - LoadByteImmediate(i8) = 0x10, // push immediate short - LoadShortImmediate(i16) = 0x11, // push immediate short - LoadConstant(u8) = 0x12, // Push from constant pool - LoadCostantWide(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 - LoadLocalReference(u8) = 0x19, // Load reference from indexed local variable - LoadLocalInt0() = 0x1A, // Load int from local variable - LoadLocalInt1() = 0x1B, // Load int from local variable - LoadLocalInt2() = 0x1C, // Load int from local variable - LoadLocalInt3() = 0x1D, // Load int from local variable + LoadByteImmediate(u8) = 0x10, // push immediate short + LoadShortImmediate(u16) = 0x11, // push immediate short + LoadConstant(u8) = 0x12, // Push from constant pool + LoadCostantWide(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 + LoadLocalInt2() = 0x1C, // Load int from local variable + LoadLocalInt3() = 0x1D, // Load int from local variable - LoadLocalFloat0() = 0x22, // Load local double variable reference onto stack - LoadLocalFloat1() = 0x23, // Load local double variable reference onto stack - LoadLocalFloat2() = 0x24, // Load local double variable reference onto stack - LoadLocalFloat3() = 0x25, // Load local double variable reference onto stack - LoadLocalDouble0() = 0x26, // Load local double variable reference onto stack - LoadLocalDouble1() = 0x27, // Load local double variable reference onto stack - LoadLocalDouble2() = 0x28, // Load local double variable reference onto stack - LoadLocalDouble3() = 0x29, // Load local double variable reference onto stack - LoadLocalReference0() = 0x2A, // Load local reference variable reference onto stack - LoadLocalReference1() = 0x2B, // Load local reference variable reference onto stack - LoadLocalReference2() = 0x2C, // Load local reference variable reference onto stack - LoadLocalReference3() = 0x2D, // Load local reference variable reference onto stack + LoadLocalFloat0() = 0x22, // Load local double variable reference onto stack + LoadLocalFloat1() = 0x23, // Load local double variable reference onto stack + LoadLocalFloat2() = 0x24, // Load local double variable reference onto stack + LoadLocalFloat3() = 0x25, // Load local double variable reference onto stack + LoadLocalDouble0() = 0x26, // Load local double variable reference onto stack + LoadLocalDouble1() = 0x27, // Load local double variable reference onto stack + LoadLocalDouble2() = 0x28, // Load local double variable reference onto stack + LoadLocalDouble3() = 0x29, // Load local double variable reference onto stack + LoadLocalReference0() = 0x2A, // Load local reference variable reference onto stack + LoadLocalReference1() = 0x2B, // Load local reference variable reference onto stack + LoadLocalReference2() = 0x2C, // Load local reference variable reference onto stack + LoadLocalReference3() = 0x2D, // Load local reference variable reference onto stack - ArrayElement() = 0x32, // load element from array - LoadFromBArray() = 0x33, // store into byte array - StoreLocalInt(u8) = 0x36, // store into indexed local variable - StoreLocalReference(u8) = 0x3A, // 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 - StoreLocalInt3() = 0x3E, // store int into local variable - StoreLocalReference0() = 0x4B, // store reference into local variable - StoreLocalReference1() = 0x4C, // store reference into local variable - StoreLocalReference2() = 0x4D, // store reference into local variable - StoreLocalReference3() = 0x4E, // store reference into local variable + 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 + StoreLocalInt3() = 0x3E, // store int into local variable + StoreReference0() = 0x4B, // store reference into local variable + StoreReference1() = 0x4C, // store reference into local variable + 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 - StoreIntoCArray() = 0x55, // store value into char array - Pop() = 0x57, // Pop top stack value - Duplicate() = 0x59, // duplicate top stack value + 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 - AddInt() = 0x60, // int addition - SubtractInt() = 0x64, // int subtraction - MultiplyInt() = 0x68, // int multiplication - DivideInt() = 0x6C, // integer division, round toward zero and more rules - DivideLong() = 0x6D, // long division + AddInt() = 0x60, // int addition + MultiplyInt() = 0x68, // int multiplication + DivideInt() = 0x6C, // integer division, round toward zero and more rules + DivideLong() = 0x6D, // long division - ArithmeticShiftIntRight() = 0x7A, // shift int - LogicalShiftIntRight() = 0x7C, // shift int right with zero extension + ShiftIntRight() = 0x7a, // shift int - OrInt() = 0x80, // value, value => or - IncrementLocalInt(u8, i8) = 0x84, // increment local variable by constant i8 + OrInt() = 0x80, // value, value => or - CompareFloatL() = 0x95, // compare float, push -1 if one is NaN - CompareFloatG() = 0x96, // compare float, push 1 if one is NaN - BranchZero(i16) = 0x99, // branch if value == 0 - BranchNonZero(i16) = 0x9A, // branch if value != 0 - BranchNegative(i16) = 0x9B, // branch if value < 0 - BranchNonNegative(i16) = 0x9C, // branch if value <= 0 - BranchPositive(i16) = 0x9D, // branch if value > 0 - BranchNonPositive(i16) = 0x9E, // branch if value >= 0 + CompareFloatL() = 0x95, // compare float, push -1 if one is NaN + CompareFloatG() = 0x96, // compare float, push 1 if one is NaN + BranchZero(i16) = 0x99, // branch if value == 0 + BranchNonZero(i16) = 0x9A, // branch if value != 0 + BranchNegative(i16) = 0x9B, // branch if value < 0 + BranchNonNegative(i16) = 0x9C, // branch if value <= 0 + BranchPositive(i16) = 0x9D, // branch if value > 0 + BranchNonPositive(i16) = 0x9E, // branch if value >= 0 - BranchIntEquality(i16) = 0x9F, - BranchIntInequality(i16) = 0xA0, - BranchIntLessThan(i16) = 0xA1, - BranchIntGreaterEquals(i16) = 0xA2, - BranchIntGreaterThan(i16) = 0xA3, - BranchIntLessEquals(i16) = 0xA4, - BranchReferenceEquality(i16) = 0xA5, - BranchReferenceInequality(i16) = 0xA6, + BranchIntEquality(i16) = 0x9F, + BranchIntInequality(i16) = 0xA0, + BranchIntLessThan(i16) = 0xA1, + BranchIntGreaterEquals(i16) = 0xA2, + BranchIntGreaterThan(i16) = 0xA3, + BranchIntLessEquals(i16) = 0xA4, + BranchReferenceEquality(i16) = 0xA5, + BranchReferenceInequality(i16) = 0xA6, - BranchAlways(i16) = 0xA7, // branch if true - LookupSwitch(i32, Box<[(i32, i32)]>) = 0xAB, // offset based on switch value - ReturnInt() = 0xAC, // return integer from function + BranchAlways(i16) = 0xA7, // branch if true + ReturnInt() = 0xAC, // return integer from function - ReturnReference() = 0xB0, // return top-ref from current function - ReturnVoid() = 0xB1, // return void from function - GetStatic(u16) = 0xB2, // get static field from class - PutStatic(u16) = 0xB3, // set static field on class - GetField(u16) = 0xB4, // get field from class - PutField(u16) = 0xB5, // set field to a value - InvokeVirtual(u16) = 0xB6, // invoke function on a class - InvokeSpecial(u16) = 0xB7, // invoke instance method - 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 + ReturnReference() = 0xB0, // return top-ref from current function + ReturnVoid() = 0xB1, // return void from function + GetStatic(u16) = 0xB2, // get static field from class + PutStatic(u16) = 0xB3, // set static field on class + GetField(u16) = 0xB4, // get field from class + PutField(u16) = 0xB5, // set field to a value + InvokeVirtual(u16) = 0xB6, // invoke function on a class + InvokeSpecial(u16) = 0xB7, // invoke instance method + 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 - CheckCast(u16) = 0xC0, // throw exception on fail - InstanceOf(u16) = 0xC1, // push integer result for success - EnterMonitor() = 0xC2, // enter the synchronization monitor of an object - ExitMonitor() = 0xC3, // exit the synchronization monitor of an object - BranchNull(i16) = 0xC6, // branch if Null - BranchNonNull(i16) = 0xC7, // branch if Null + InstanceOf(u16) = 0xC1, // branch if Null + EnterMonitor() = 0xC2, // enter the synchronization monitor of an object + ExitMonitor() = 0xC3, // exit the synchronization monitor of an object + BranchNull(i16) = 0xC6, // branch if Null + BranchNonNull(i16) = 0xC7, // branch if Null Unknown(u8), } diff --git a/src/classstore.rs b/src/classstore.rs index b37e7e2..083d788 100644 --- a/src/classstore.rs +++ b/src/classstore.rs @@ -33,7 +33,7 @@ pub struct PrimitiveClassStore { } #[derive(Debug)] -pub struct ClassStoreEntry { +struct ClassStoreEntry { was_init: bool, class_object: ObjectReference, class_file: JavaClassFile, @@ -133,8 +133,6 @@ impl ClassStore { if path_buf.is_file() { return self.load_class_from_file(&path_buf); } - - path_buf.clear(); }; return Err(Error::ClassNotFoundError(format!("Could not find class '{classname}' in classpath"))); @@ -156,12 +154,10 @@ impl ClassStore { }; let compatible_count = CompatibleTypesIterator::new(my_type_index, self) - .filter(|type_name| - *type_name == other_type_name - ) + .filter(|type_name| *type_name == other_type_name) .count(); - compatible_count != 0 + compatible_count == 0 } pub fn have_class(&self, classname: &String) -> bool { diff --git a/src/heap_area.rs b/src/heap_area.rs index f8da3a7..56abcfa 100644 --- a/src/heap_area.rs +++ b/src/heap_area.rs @@ -76,40 +76,27 @@ impl HeapArea { byte_buffer }; - let byte_array_ref = self.make_primitive_byte_array(utf16_bytes.len(), class_store); + let byte_object_refs = utf16_bytes.iter().map(|byte| self.object_area.cached_byte_object(*byte)).collect(); + + let byte_array_ref = self.make_array(class_store, byte_object_refs); - for (index, byte) in utf16_bytes.iter().enumerate() { - self.object_area.set_array_element(byte_array_ref, index, FieldValue::Byte(i8::from_ne_bytes([*byte]))); - } let string_class_index = class_store.class_idx_from_name(&String::from("java/lang/String")).unwrap(); let string_ref = self.make_object(class_store, string_class_index); self.object_area.set_object_field(string_ref, "value", FieldValue::Reference(byte_array_ref), string_class_index, class_store).unwrap(); - const UTF16_CODER: i8 = 1; // TODO: I don't like this + const UTF16_CODER: u8 = 1; // TODO: I don't like this self.object_area.set_object_field(string_ref, "coder", FieldValue::Byte(UTF16_CODER), string_class_index, class_store).unwrap(); - string_ref + string_ref } - pub fn make_primitive_char_array(&mut self, array_capacity: usize, class_store: &ClassStore) -> ObjectReference { - let (array_ref, size) = self.object_area.make_primitive_char_array(array_capacity, class_store); - self.memory_used += size; - - array_ref - } } #[derive(Clone, Copy, Debug, Default, PartialEq)] pub struct ObjectReference(u32); -impl Into for ObjectReference { - fn into(self) -> FieldValue { - FieldValue::Reference(self) - } -} - impl ObjectReference { pub const NULL: ObjectReference = ObjectReference(0); } @@ -131,7 +118,7 @@ impl ObjectArea { fn fill_byte_cache(&mut self, class_store: &ClassStore) -> usize { let byte_class_index = class_store.class_idx_from_name(&String::from("java/lang/Byte")).unwrap(); let mut total_memory_usage = 0; - for byte in i8::MIN..=i8::MAX { + for byte in 0..=u8::MAX { let (byte_object_ref, object_memory) = self.make(class_store, byte_class_index); self.set_object_field(byte_object_ref, "value", FieldValue::Byte(byte), byte_class_index, class_store).unwrap(); @@ -160,7 +147,7 @@ impl ObjectArea { let array_object = ByteArray { class_ref: array_class_ref, - content: vec![0_i8; capacity].into(), + content: vec![0_u8; capacity].into(), }; let array_ref = self.store_entry(CompartmentEntry::ByteArray(array_object)); @@ -227,7 +214,8 @@ impl ObjectArea { return (object_ref, object_size); } - pub fn get_class_ref_native_class_name<'a>(&self, class_ref: ObjectReference, class_store: &'a ClassStore) -> &'a String { + pub fn get_reference_native_class_name<'a>(&self, reference: ObjectReference, class_store: &'a ClassStore) -> &'a String { + let class_ref = self.get_reference_class_ref(reference, class_store); 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!(), @@ -240,11 +228,6 @@ impl ObjectArea { return class_store.get_native_class_name(native_name_index as usize); } - pub fn get_reference_native_class_name<'a>(&self, reference: ObjectReference, class_store: &'a ClassStore) -> &'a String { - let class_ref = self.get_reference_class_ref(reference, class_store); - self.get_class_ref_native_class_name(class_ref, class_store) - } - pub fn get_object_class_index(&self, reference: ObjectReference) -> usize { match self.get_entry(reference) { CompartmentEntry::Object(o) => o.class_index, @@ -299,26 +282,22 @@ impl ObjectArea { pub fn get_array_length(&self, reference: ObjectReference) -> usize { // TODO: Throw errors - match self.get_entry(reference) { - CompartmentEntry::ReferenceArray(a) => a.content.len(), - CompartmentEntry::ByteArray(b) => b.content.len(), + let array = match self.get_entry(reference) { + CompartmentEntry::ReferenceArray(a) => a, _ => unreachable!(), - } + }; + + array.content.len() } - pub fn get_array_element(&self, array_ref: ObjectReference, element_index: i32) -> FieldValue { + pub fn get_array_element(&self, array_ref: ObjectReference, element_index: i32) -> ObjectReference { // TODO: Throw errors - match self.get_entry(array_ref) { - CompartmentEntry::ReferenceArray(array) => { - let element = array.content[element_index as usize]; - FieldValue::Reference(element) - } - CompartmentEntry::ByteArray(array) => { - let element = array.content[element_index as usize]; - FieldValue::Byte(element) - } + let array = match self.get_entry(array_ref) { + CompartmentEntry::ReferenceArray(a) => a, _ => unreachable!(), - } + }; + + array.content[element_index as usize] } pub fn get_object_field(&self, reference: ObjectReference, field_name: &str, accessing_class_idx: usize, class_store: &ClassStore) -> Result { @@ -356,17 +335,12 @@ impl ObjectArea { 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!() } ; - } - CompartmentEntry::CharArray(array) => { - let array_element = array.content.get_mut(index).unwrap(); - - *array_element = match element { FieldValue::Char(c) => c, _ => unreachable!() } ; - } + }, _ => unreachable!(), }; @@ -413,27 +387,6 @@ impl ObjectArea { ))) } } - - fn make_primitive_char_array(&mut self, array_capacity: usize, class_store: &ClassStore) -> (ObjectReference, usize) { - // make new type desc - let array_type_desc = AbstractTypeDescription { - array_level: 1, - kind: AbstractTypeKind::Char(), - }; - - let array_class_ref = class_store.get_array_class_ref(&array_type_desc).unwrap(); - - let array_size = array_capacity * std::mem::size_of::() + std::mem::size_of::(); - - let array_object = CharArray { - class_ref: array_class_ref, - content: vec![0; array_capacity].into(), - }; - - let array_ref = self.store_entry(CompartmentEntry::CharArray(array_object)); - - (array_ref, array_size) - } } pub struct ObjectCompartment { @@ -475,7 +428,6 @@ impl ObjectCompartment { CompartmentEntry::Object(_) => unreachable!(), CompartmentEntry::ReferenceArray(_) => unreachable!(), CompartmentEntry::ByteArray(_) => unreachable!(), - CompartmentEntry::CharArray(_) => unreachable!(), } *self.objects.get_mut(compartment_index).unwrap() = object; @@ -505,21 +457,14 @@ pub enum CompartmentEntry { Object(HeapObject), ReferenceArray(ReferenceArray), ByteArray(ByteArray), - CharArray(CharArray), EmptyNext(usize), EmptyTail(), // last empty value } -#[derive(Debug)] -pub struct CharArray { - class_ref: ObjectReference, - content: Box<[u16]>, -} - #[derive(Debug)] pub struct ByteArray { class_ref: ObjectReference, - content: Box<[i8]>, + content: Box<[u8]>, } #[derive(Debug)] @@ -650,7 +595,7 @@ pub struct ObjectField { #[derive(Debug, Clone, Copy)] pub enum FieldValue { Boolean(bool), - Byte(i8), + Byte(u8), Char(u16), Short(i16), Int(i32), @@ -685,7 +630,7 @@ impl FieldValue { AbstractTypeKind::Long() => Self::Long(0), AbstractTypeKind::Classname(_) => Self::Reference(ObjectReference::NULL), AbstractTypeKind::Short() => Self::Short(0), - AbstractTypeKind::Boolean() => Self::Boolean(false), + AbstractTypeKind::Boolean() => Self::Boolean(true), } } } diff --git a/src/jvm.rs b/src/jvm.rs index dc6ee7b..9a2b773 100644 --- a/src/jvm.rs +++ b/src/jvm.rs @@ -193,7 +193,7 @@ impl JVM { ); } - fn make_primitive_class(&mut self, class_name: &str, class_descriptor: &str, string_names: bool) -> ObjectReference { + 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(); @@ -209,17 +209,15 @@ impl JVM { &self.class_store, ).unwrap(); - if string_names { - 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(); - } + 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( @@ -367,40 +365,15 @@ impl JVM { self.heap_area.fill_byte_cache(&self.class_store); - self.class_store.primitive_classes.byte_class = self.make_primitive_class("byte", "B", false); - self.make_array_class( - self.class_store.primitive_classes.byte_class, - AbstractTypeDescription { - array_level: 0, - kind: AbstractTypeKind::Byte(), - } - ); - { - // we can only make a byte class name after the byte array is loaded - let string_ref = self.heap_area.make_handmade_string(&String::from("byte"), &self.class_store); - self.heap_area.object_area.set_object_field( - self.class_store.primitive_classes.byte_class, - "name", - FieldValue::Reference(string_ref), - class_class_index, - &self.class_store - ).unwrap(); - } - self.class_store.primitive_classes.int_class = self.make_primitive_class("int", "I", true); - self.class_store.primitive_classes.char_class = self.make_primitive_class("char", "C", true); - self.class_store.primitive_classes.long_class = self.make_primitive_class("long", "J", true); - self.class_store.primitive_classes.float_class = self.make_primitive_class("float", "F", true); - self.class_store.primitive_classes.short_class = self.make_primitive_class("short", "S", true); - self.class_store.primitive_classes.double_class = self.make_primitive_class("double", "D", true); - self.class_store.primitive_classes.boolean_class = self.make_primitive_class("boolean", "Z", true); + self.class_store.primitive_classes.int_class = self.make_primitive_class("int", "I"); + self.class_store.primitive_classes.byte_class = self.make_primitive_class("byte", "B"); + self.class_store.primitive_classes.char_class = self.make_primitive_class("char", "C"); + self.class_store.primitive_classes.long_class = self.make_primitive_class("long", "J"); + self.class_store.primitive_classes.float_class = self.make_primitive_class("float", "F"); + self.class_store.primitive_classes.short_class = self.make_primitive_class("short", "S"); + self.class_store.primitive_classes.double_class = self.make_primitive_class("double", "D"); + self.class_store.primitive_classes.boolean_class = self.make_primitive_class("boolean", "Z"); - self.make_array_class( - self.class_store.primitive_classes.char_class, - AbstractTypeDescription { - array_level: 0, - kind: AbstractTypeKind::Char(), - } - ); self.make_array_class( self.class_store.primitive_classes.int_class, AbstractTypeDescription { @@ -408,6 +381,13 @@ impl JVM { kind: AbstractTypeKind::Int(), } ); + self.make_array_class( + self.class_store.primitive_classes.byte_class, + AbstractTypeDescription { + array_level: 0, + kind: AbstractTypeKind::Byte(), + } + ); let string_refs = arguments.iter() @@ -553,7 +533,7 @@ impl JVM { AbstractTypeKind::Byte() => { let int_entry = class_file.pool_int_entry(constant_value_info.constant_value_index)?; - FieldValue::Byte(int_entry.value as i8) + FieldValue::Byte(int_entry.value as u8) }, AbstractTypeKind::Char() => { let int_entry = class_file.pool_int_entry(constant_value_info.constant_value_index)?; @@ -678,14 +658,6 @@ impl JVM { wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(value_0 + value_1)))?; } - Instruction::ArithmeticShiftIntRight() => { - let shift = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))? as u8 & 0b00011111; - let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?; - - // rust does arithmetic shift on singed values - wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(int >> shift)))?; - }, - Instruction::ArrayLength() => { let array_reference = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?; @@ -700,7 +672,7 @@ impl JVM { let element = self.heap_area.object_area.get_array_element(array_reference, element_index); - wrap_stackframe_error(class, method, frame.operand_stack.push_field_value(element))?; + wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Reference(element)))?; }, Instruction::BranchAlways(branch_offset) => { @@ -718,16 +690,6 @@ impl JVM { } } - Instruction::BranchIntGreaterEquals(branch_offset) => { - let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?; - let value_1 = 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::BranchIntInequality(branch_offset) => { let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?; let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?; @@ -748,16 +710,6 @@ impl JVM { } } - Instruction::BranchIntLessThan(branch_offset) => { - let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?; - let value_1 = 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::BranchNonNull(branch_offset) => { let test_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?; @@ -803,10 +755,10 @@ impl JVM { } } - Instruction::BranchPositive(branch_offset) => { + Instruction::BranchZero(branch_offset) => { let test_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?; - if test_value > 0 { + if test_value == 0 { 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}; } @@ -822,35 +774,6 @@ impl JVM { } } - Instruction::BranchZero(branch_offset) => { - let test_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?; - - if test_value == 0 { - 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::CheckCast(classref_index) => { - // TODO: Class loading checks - let class_name = class.gather_class(classref_index)?; - let class_index = self.class_store.class_idx_from_name(class_name).unwrap(); - let class_object_ref = self.class_store.get_class_objectref_from_index(class_index); - let native_class_description = self.heap_area.object_area.get_class_ref_native_class_name(class_object_ref, &self.class_store); - let class_description = AbstractTypeDescription::parse_full(native_class_description)?; - - let object = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?; - let native_class_name = self.heap_area.object_area.get_reference_native_class_name(object, &self.class_store); - let object_description = AbstractTypeDescription::parse_full(native_class_name)?; - - if ! self.class_store.are_types_compatible(&object_description, &class_description) { - // TODO: Throw Exception - return Err(Error::RunTimeError(format!("Trying to cast an object of type {native_class_name} to {class_name}"))) - } - - wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Reference(object)))?; - } - Instruction::CompareFloatG() => { let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_float(0))?; let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_float(0))?; @@ -963,27 +886,8 @@ impl JVM { wrap_stackframe_error(class, method, frame.operand_stack.push_field_value(fetched_value))?; } - Instruction::IncrementLocalInt(index, constant) => { - let int = wrap_stackframe_error(class, method, frame.load_local_int(index as u16))?; - - wrap_stackframe_error(class, method, frame.store_local(index as u16, StackValue::Int(int + constant as i32)))?; - } - Instruction::InstanceOf(classref_index) => { - // TODO: Class loading checks let class_name = class.gather_class(classref_index)?; - let class_index = self.class_store.class_idx_from_name(class_name).unwrap(); - let class_object_ref = self.class_store.get_class_objectref_from_index(class_index); - let native_class_description = self.heap_area.object_area.get_class_ref_native_class_name(class_object_ref, &self.class_store); - let class_description = AbstractTypeDescription::parse_full(native_class_description)?; - - let object = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?; - let native_class_name = self.heap_area.object_area.get_reference_native_class_name(object, &self.class_store); - let object_description = AbstractTypeDescription::parse_full(native_class_name)?; - - let instruction_result = if self.class_store.are_types_compatible(&object_description, &class_description) { 1 } else { 0 }; - - wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(instruction_result)))?; } Instruction::InvokeSpecial(methodref_index) => { @@ -1137,7 +1041,10 @@ impl JVM { // TODO: Throw error if ! self.class_store.are_types_compatible(&this_object_descriptor, &base_object_descriptor) { - return Err(Error::RunTimeError(format!("InvokeVirtual: Cannot call '{base_method_name}' from class '{base_class_name}' on instance from class '{this_object_class_name}: Types are incompatible'"))) + return Err(Error::RunTimeError(format!( + "InvokeVirtual: Cannot call '{base_method_name}' from class '{base_class_name}' on instance from class '{}: Types are incompatible'", + this_object_class_name + ))) } let (invoked_class_index, invoked_method_index, _invoked_method_info) = match ClassMethodIterator::new(this_object_class_index, &self.class_store) @@ -1169,33 +1076,15 @@ impl JVM { Instruction::LoadByteImmediate(byte) => { // sign extend into int + let i8_int = i8::from_be_bytes([byte]); - let frame_result = frame.operand_stack.push(StackValue::Int(byte as i32)); + let frame_result = frame.operand_stack.push(StackValue::Int(i8_int as i32)); match frame_result { Ok(_) => (), Err(err) => return Err(Error::StackFrameError(err, format!("in '{}', in class '{}'", method.name, class.get_classname().unwrap()))), } } - Instruction::LoadShortImmediate(short) => { - // sign extend into int - - let frame_result = frame.operand_stack.push(StackValue::Int(short as i32)); - match frame_result { - Ok(_) => (), - Err(err) => return Err(Error::StackFrameError(err, format!("in '{}', in class '{}'", method.name, class.get_classname().unwrap()))), - } - } - - Instruction::LoadFromBArray() => { - let index = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?; - let array = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?; - - let element = self.heap_area.object_area.get_array_element(array, index); - - wrap_stackframe_error(class, method, frame.operand_stack.push_field_value(element))?; - } - Instruction::LoadConstant(index) => { // TODO: Handle error instead of unwrap match class.pool_entry(index as u16).unwrap() { @@ -1296,19 +1185,13 @@ impl JVM { 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)))?; - } - - ConstantPoolInfo::Integer(int_data) => { - let int_value = int_data.value; - - wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(int_value)))?; - } + }, _ => { println!("{:?}", class.pool_entry(wide_index).unwrap()); todo!() } } - } + }, Instruction::LoadLocalFloat0() => { load_local_float(class, method, frame, 0)?; @@ -1336,9 +1219,6 @@ impl JVM { load_local_int(class, method, frame, 3)?; } - Instruction::LoadLocalReference(index) => { - load_local_reference(class, method, frame, index as usize)?; - } Instruction::LoadLocalReference0() => { load_local_reference(class, method, frame, 0)?; } @@ -1352,27 +1232,6 @@ impl JVM { load_local_reference(class, method, frame, 3)?; } - Instruction::LogicalShiftIntRight() => { - let shift = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))? as u8 & 0b00011111; - let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?; - let uint = u32::from_ne_bytes(int.to_ne_bytes()); - let u_result = uint >> shift; - let i_result = i32::from_ne_bytes(u_result.to_ne_bytes()); - - wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(i_result)))?; - } - - Instruction::LookupSwitch(default_offset, pairs) => { - let key = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?; - let jump_offset = match pairs.binary_search_by(|(match_key, _offset)| match_key.cmp(&key)) { - Ok(offset) => pairs[offset].1, - Err(_) => default_offset, - }; - - frame.instruction_pointer -= offset as u32; - frame.instruction_pointer = if jump_offset < 0 { frame.instruction_pointer - jump_offset.abs() as u32} else { frame.instruction_pointer + jump_offset.abs() as u32}; - } - Instruction::MultiplyInt() => { let factor_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?; let factor_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?; @@ -1424,7 +1283,6 @@ impl JVM { Instruction::NewPrimitiveArray(array_type) => { let array_capacity = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?; - const CHAR: u8 = 5; const BYTE: u8 = 8; let array_ref = match array_type { BYTE => { @@ -1433,12 +1291,6 @@ impl JVM { array_ref } - CHAR => { - let array_ref = self.heap_area.make_primitive_char_array(array_capacity as usize, &self.class_store); - - array_ref - } - _ => todo!() }; @@ -1481,9 +1333,6 @@ impl JVM { wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Float(2.0)))?; } - Instruction::PushConstIntM1() => { - wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(-1)))?; - } Instruction::PushConstInt0() => { wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(0)))?; } @@ -1515,7 +1364,6 @@ impl JVM { _ => match wrap_stackframe_error(class, method, frame.operand_stack.pop_computational_1(0))? { StackValue::Int(i) => FieldValue::Int(i), StackValue::Reference(r) => FieldValue::Reference(r), - StackValue::Float(f) => FieldValue::Float(f), stack_value @ _ => { println!("{stack_value:?}"); todo!() @@ -1579,26 +1427,20 @@ impl JVM { let ref_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?; if ref_value != ObjectReference::NULL { - let value_native_name = self.heap_area.object_area.get_reference_native_class_name(ref_value, &self.class_store); + let value_native_name = self.heap_area.object_area.get_reference_native_class_name(ref_value, &self.class_store); let parsed_native_name = AbstractTypeDescription::parse_first(value_native_name).unwrap().1; - if ! self.class_store.are_types_compatible(&parsed_native_name, &matched_field.descriptor) { + if ! self.class_store.are_types_compatible(&matched_field.descriptor, &parsed_native_name) { return Err(Error::RunTimeError(format!("PutStatic: Trying to set a value with type '{parsed_native_name:?}' on a field with type '{:?}'", matched_field.descriptor))); } } FieldValue::Reference(ref_value) } - - (1..=255, _) => { - let ref_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?; - FieldValue::Reference(ref_value) - } - _ => { println!("{:?}", matched_field); todo!() - } + }, }; self.heap_area.static_area.set(target_class_name, target_field_name, set_value)?; @@ -1637,6 +1479,13 @@ impl JVM { return Ok(JVMCallbackOperation::PopFrame()); }, + Instruction::ShiftIntRight() => { + let shift = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))? as u8 & 0b00011111; + let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?; + + wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(int >> shift)))?; + }, + 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))?; @@ -1644,7 +1493,7 @@ impl JVM { match self.heap_area.object_area.get_entry(array_ref) { CompartmentEntry::ByteArray(_) => { - let byte_value = value as i8; + 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)); } @@ -1652,22 +1501,6 @@ impl JVM { } } - Instruction::StoreIntoCArray() => { - 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::CharArray(_) => { - let int_bytes = value.to_ne_bytes(); - let char_value = u16::from_ne_bytes([int_bytes[2], int_bytes[3]]); - - self.heap_area.object_area.set_array_element(array_ref, index as usize, FieldValue::Char(char_value)); - } - _ => todo!(), // TODO: Handle as error - } - } - 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))?; @@ -1678,64 +1511,52 @@ impl JVM { self.heap_area.object_area.set_array_element(array_ref, index as usize, FieldValue::Reference(value)); } - Instruction::SubtractInt() => { - let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?; - let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?; - - wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(value_1 - value_2)))?; - } - 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))?; wrap_stackframe_error(class, method, frame.store_local(0, StackValue::Int(int)))?; - } + }, Instruction::StoreLocalInt1() => { let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?; wrap_stackframe_error(class, method, frame.store_local(1, StackValue::Int(int)))?; - } + }, Instruction::StoreLocalInt2() => { let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?; wrap_stackframe_error(class, method, frame.store_local(2, StackValue::Int(int)))?; - } + }, Instruction::StoreLocalInt3() => { let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?; wrap_stackframe_error(class, method, frame.store_local(3, StackValue::Int(int)))?; - } + }, - Instruction::StoreLocalReference(index) => { - let reference = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?; - - wrap_stackframe_error(class, method, frame.store_local(index as u16, StackValue::Reference(reference)))?; - } - Instruction::StoreLocalReference0() => { + Instruction::StoreReference0() => { let reference = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?; wrap_stackframe_error(class, method, frame.store_local(0, StackValue::Reference(reference)))?; - } - Instruction::StoreLocalReference1() => { + }, + Instruction::StoreReference1() => { let reference = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?; wrap_stackframe_error(class, method, frame.store_local(1, StackValue::Reference(reference)))?; - } - Instruction::StoreLocalReference2() => { + }, + Instruction::StoreReference2() => { let reference = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?; wrap_stackframe_error(class, method, frame.store_local(2, StackValue::Reference(reference)))?; - } - Instruction::StoreLocalReference3() => { + }, + Instruction::StoreReference3() => { let reference = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?; wrap_stackframe_error(class, method, frame.store_local(3, StackValue::Reference(reference)))?; - } + }, _ => { return Err(Error::RunTimeError(format!("Opcode not implemented yet: {:?}", instruction))) diff --git a/src/main.rs b/src/main.rs index e8d5b95..24a5a86 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,13 +15,11 @@ mod native_methods; //use crate::accessmasks::FieldAccessFlag; //use crate::stackframe::StackValue; //use crate::classfile::JavaClassFile; -use std::path::PathBuf; fn main() { //println!("{:#?}", JavaClassFile::new(&mut File::open("java/lang/System.class").unwrap()).unwrap()); let mut jvm = jvm::JVM::new(); - jvm.class_store.class_path_fragments.push(PathBuf::from("./classpath")); match jvm.entrypoint( &"Main".to_string(), diff --git a/src/native_methods.rs b/src/native_methods.rs index ee76b03..6b3b2b9 100644 --- a/src/native_methods.rs +++ b/src/native_methods.rs @@ -49,8 +49,6 @@ impl JavaLangClass { }; // max_locals: 1 // max_stack: 1 - let class = jvm.class_store.class_file_from_idx(frame.class_index).unwrap(); - let method = &class.methods[frame.method_index as usize]; let class_class_index = jvm.class_store.class_idx_from_name(&String::from("java/lang/Class")).unwrap(); let (string_class_file, string_class_index) = jvm.class_store.get_class(&String::from("java/lang/String")).unwrap(); let string_equals_index = string_class_file.find_method_index(&String::from("equals")).unwrap(); @@ -59,9 +57,7 @@ impl JavaLangClass { _ => unreachable!(), }; - frame.instruction_pointer += 1; - - match frame.instruction_pointer - 1 { + match frame.instruction_pointer { 0 => { let boolean_class_ref = jvm.class_store.primitive_classes.boolean_class; let boolean_class_name_ref = match jvm.heap_area.object_area.get_object_field( @@ -81,206 +77,10 @@ impl JavaLangClass { &[StackValue::Reference(boolean_class_name_ref), StackValue::Reference(passed_wanted_string)], ); + frame.instruction_pointer += 1; + Ok(JVMCallbackOperation::PushFrame(string_compare_frame)) - } - - 1 => { - if wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))? == 1 { - let boolean_class_ref = jvm.class_store.primitive_classes.boolean_class; - Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(boolean_class_ref))) - } else { - let byte_class_ref = jvm.class_store.primitive_classes.byte_class; - let byte_class_name_ref = match jvm.heap_area.object_area.get_object_field( - byte_class_ref, - "name", - class_class_index, - &jvm.class_store - ).unwrap() { - FieldValue::Reference(r) => r, - _ => unreachable!(), - }; - - let string_compare_frame = StackFrame::new( - string_class_file, - string_class_index, - string_equals_index as u16, - &[StackValue::Reference(byte_class_name_ref), StackValue::Reference(passed_wanted_string)], - ); - - Ok(JVMCallbackOperation::PushFrame(string_compare_frame)) - } - } - - 2 => { - if wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))? == 1 { - let char_class_ref = jvm.class_store.primitive_classes.char_class; - Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(char_class_ref))) - } else { - let char_class_ref = jvm.class_store.primitive_classes.char_class; - let char_class_name_ref = match jvm.heap_area.object_area.get_object_field( - char_class_ref, - "name", - class_class_index, - &jvm.class_store - ).unwrap() { - FieldValue::Reference(r) => r, - _ => unreachable!(), - }; - - let string_compare_frame = StackFrame::new( - string_class_file, - string_class_index, - string_equals_index as u16, - &[StackValue::Reference(char_class_name_ref), StackValue::Reference(passed_wanted_string)], - ); - - Ok(JVMCallbackOperation::PushFrame(string_compare_frame)) - } - } - - 3 => { - if wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))? == 1 { - let short_class_ref = jvm.class_store.primitive_classes.short_class; - Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(short_class_ref))) - } else { - let short_class_ref = jvm.class_store.primitive_classes.short_class; - let short_class_name_ref = match jvm.heap_area.object_area.get_object_field( - short_class_ref, - "name", - class_class_index, - &jvm.class_store - ).unwrap() { - FieldValue::Reference(r) => r, - _ => unreachable!(), - }; - - let string_compare_frame = StackFrame::new( - string_class_file, - string_class_index, - string_equals_index as u16, - &[StackValue::Reference(short_class_name_ref), StackValue::Reference(passed_wanted_string)], - ); - - Ok(JVMCallbackOperation::PushFrame(string_compare_frame)) - } - } - - 4 => { - if wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))? == 1 { - let int_class_ref = jvm.class_store.primitive_classes.int_class; - Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(int_class_ref))) - } else { - let int_class_ref = jvm.class_store.primitive_classes.int_class; - let int_class_name_ref = match jvm.heap_area.object_area.get_object_field( - int_class_ref, - "name", - class_class_index, - &jvm.class_store - ).unwrap() { - FieldValue::Reference(r) => r, - _ => unreachable!(), - }; - - let string_compare_frame = StackFrame::new( - string_class_file, - string_class_index, - string_equals_index as u16, - &[StackValue::Reference(int_class_name_ref), StackValue::Reference(passed_wanted_string)], - ); - - Ok(JVMCallbackOperation::PushFrame(string_compare_frame)) - } - } - - 5 => { - if wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))? == 1 { - let float_class_ref = jvm.class_store.primitive_classes.float_class; - Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(float_class_ref))) - } else { - let float_class_ref = jvm.class_store.primitive_classes.float_class; - let float_class_name_ref = match jvm.heap_area.object_area.get_object_field( - float_class_ref, - "name", - class_class_index, - &jvm.class_store - ).unwrap() { - FieldValue::Reference(r) => r, - _ => unreachable!(), - }; - - let string_compare_frame = StackFrame::new( - string_class_file, - string_class_index, - string_equals_index as u16, - &[StackValue::Reference(float_class_name_ref), StackValue::Reference(passed_wanted_string)], - ); - - Ok(JVMCallbackOperation::PushFrame(string_compare_frame)) - } - } - - 6 => { - if wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))? == 1 { - let double_class_ref = jvm.class_store.primitive_classes.double_class; - Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(double_class_ref))) - } else { - let double_class_ref = jvm.class_store.primitive_classes.double_class; - let double_class_name_ref = match jvm.heap_area.object_area.get_object_field( - double_class_ref, - "name", - class_class_index, - &jvm.class_store - ).unwrap() { - FieldValue::Reference(r) => r, - _ => unreachable!(), - }; - - let string_compare_frame = StackFrame::new( - string_class_file, - string_class_index, - string_equals_index as u16, - &[StackValue::Reference(double_class_name_ref), StackValue::Reference(passed_wanted_string)], - ); - - Ok(JVMCallbackOperation::PushFrame(string_compare_frame)) - } - } - - 7 => { - if wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))? == 1 { - let long_class_ref = jvm.class_store.primitive_classes.long_class; - Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(long_class_ref))) - } else { - let long_class_ref = jvm.class_store.primitive_classes.long_class; - let long_class_name_ref = match jvm.heap_area.object_area.get_object_field( - long_class_ref, - "name", - class_class_index, - &jvm.class_store - ).unwrap() { - FieldValue::Reference(r) => r, - _ => unreachable!(), - }; - - let string_compare_frame = StackFrame::new( - string_class_file, - string_class_index, - string_equals_index as u16, - &[StackValue::Reference(long_class_name_ref), StackValue::Reference(passed_wanted_string)], - ); - - Ok(JVMCallbackOperation::PushFrame(string_compare_frame)) - } - } - - 8 => { - if wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))? == 1 { - let long_class_ref = jvm.class_store.primitive_classes.long_class; - Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(long_class_ref))) - } else { - Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(ObjectReference::NULL))) - } - } + }, _ => Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(ObjectReference::NULL))) } } @@ -290,14 +90,6 @@ impl JavaLangClass { } } -struct JavaLangStringUTF16 {} - -impl JavaLangStringUTF16 { - pub fn is_big_endian(_jvm: &mut JVM) -> Result { - Ok(JVMCallbackOperation::ReturnFrame(StackValue::Int(if cfg!(target_endian = "big") {1} else {0}))) - } -} - struct JdkInternalMiscUnsafe {} impl JdkInternalMiscUnsafe { @@ -365,19 +157,8 @@ impl JdkInternalUtilSystemPropsRaw { Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(array_reference))) } - // command-line configured properties, should return at least java.home pub fn vm_properties(jvm: &mut JVM) -> Result { - let array_length = 4; - let array_reference = jvm.heap_area.make_empty_array(&jvm.class_store, AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/String".into()) }, array_length); - - { - // TODO: Actual java home path - let java_home_key_reference = jvm.heap_area.make_handmade_string(&String::from("java.home"), &jvm.class_store); - let java_home_value_reference = jvm.heap_area.make_handmade_string(&String::from("./"), &jvm.class_store); - - jvm.heap_area.object_area.set_array_element(array_reference, 0, java_home_key_reference.into()); - jvm.heap_area.object_area.set_array_element(array_reference, 1, java_home_value_reference.into()); - } + let array_reference = jvm.heap_area.make_empty_array(&jvm.class_store, AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/String".into()) }, 2); Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(array_reference))) } @@ -915,20 +696,6 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul Ok(todo_call) } - ("java/lang/StringUTF16", "isBigEndian") => { - // until JDK 23 - let expected_descriptor = MethodDescriptor { - argument_types: Box::new([]), - return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Boolean() }, - }; - - if m.descriptor != expected_descriptor { - return Err(Error::RunTimeError(format!("Native descriptor mismatch for method '{class_name}.{method_name}': found '{}' but expected '{}'", m.descriptor.source_string(), expected_descriptor.source_string()))); - } - - Ok(JavaLangStringUTF16::is_big_endian) - } - ("java/lang/Object", "clone") => { let expected_descriptor = MethodDescriptor { argument_types: Box::new([]),