From d38d5b2897cf51cc74d9ee0acc4076c716c2bba3 Mon Sep 17 00:00:00 2001 From: VegOwOtenks Date: Thu, 7 Nov 2024 10:35:02 +0100 Subject: [PATCH] Implemented more opcodes and unsafe stuff --- src/bytecode.rs | 6 + src/heap_area.rs | 23 +++- src/jvm.rs | 101 ++++++++++------ src/native_methods.rs | 263 +++++++++++++++++++++++++++++++++++------- src/stackframe.rs | 31 +++++ 5 files changed, 340 insertions(+), 84 deletions(-) diff --git a/src/bytecode.rs b/src/bytecode.rs index a077f36..42336a9 100644 --- a/src/bytecode.rs +++ b/src/bytecode.rs @@ -19,6 +19,8 @@ impl Bytecode { 0x06 => (Instruction::PushConstInt3(), 1), 0x07 => (Instruction::PushConstInt4(), 1), 0x08 => (Instruction::PushConstInt5(), 1), + 0x09 => (Instruction::PushConstLong0(), 1), + 0x0A => (Instruction::PushConstLong1(), 1), 0x0B => (Instruction::PushConstFloat0(), 1), 0x0C => (Instruction::PushConstFloat1(), 1), 0x0D => (Instruction::PushConstFloat2(), 1), @@ -86,6 +88,7 @@ impl Bytecode { 0x57 => (Instruction::Pop(), 1), 0x59 => (Instruction::Duplicate(), 1), 0x5A => (Instruction::DuplicateInsertDown(), 1), + 0x5C => (Instruction::DuplicateComputationalValue(), 1), 0x60 => (Instruction::AddInt(), 1), 0x61 => (Instruction::AddLong(), 1), @@ -302,6 +305,8 @@ pub enum Instruction { PushConstInt3() = 0x06, // Push 3 PushConstInt4() = 0x07, // Push 4 PushConstInt5() = 0x08, // Push 5 + PushConstLong0() = 0x09, // Push 0 + PushConstLong1() = 0x0A, // Push 1 PushConstFloat0() = 0x0B, // Push 0.0f PushConstFloat1() = 0x0C, // Push 1.0f PushConstFloat2() = 0x0D, // Push 2.0f @@ -366,6 +371,7 @@ pub enum Instruction { Pop() = 0x57, // Pop top stack value Duplicate() = 0x59, // duplicate top stack value DuplicateInsertDown() = 0x5A, // duplicate top stack value and insert two low + DuplicateComputationalValue() = 0x5C, // duplicate top computational value AddInt() = 0x60, // int addition AddLong() = 0x61, // long addition diff --git a/src/heap_area.rs b/src/heap_area.rs index ac5e3fd..e6174b4 100644 --- a/src/heap_area.rs +++ b/src/heap_area.rs @@ -280,12 +280,15 @@ impl ObjectArea { } } - fn get_reference_class_ref(&self, reference: ObjectReference, class_store: &ClassStore) -> ObjectReference { + pub 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::ReferenceArray(a) => a.class_ref, CompartmentEntry::ByteArray(a) => a.class_ref, - _ => unreachable!(), + CompartmentEntry::CharArray(a) => a.class_ref, + CompartmentEntry::IntArray(a) => a.class_ref, + CompartmentEntry::EmptyNext(_) => unreachable!(), + CompartmentEntry::EmptyTail() => unreachable!(), } } @@ -326,6 +329,18 @@ impl ObjectArea { return object; } + pub fn is_array_reference(&mut self, reference: ObjectReference) -> bool { + match self.get_entry(reference) { + CompartmentEntry::Object(_) => false, + CompartmentEntry::ReferenceArray(_) => true, + CompartmentEntry::ByteArray(_) => true, + CompartmentEntry::CharArray(_) => true, + CompartmentEntry::IntArray(_) => true, + CompartmentEntry::EmptyNext(_) => true, + CompartmentEntry::EmptyTail() => true, + } + } + pub fn get_array_length(&self, reference: ObjectReference) -> usize { // TODO: Throw errors match self.get_entry(reference) { @@ -734,14 +749,14 @@ impl FieldValue { } } - fn expect_reference(&self) -> ObjectReference { + pub fn expect_reference(&self) -> ObjectReference { match self { Self::Reference(r) => *r, _ => unreachable!() } } - fn expect_byte(&self) -> i8 { + pub fn expect_byte(&self) -> i8 { match self { Self::Byte(b) => *b, _ => unreachable!() diff --git a/src/jvm.rs b/src/jvm.rs index ab5c77b..5ee469a 100644 --- a/src/jvm.rs +++ b/src/jvm.rs @@ -706,8 +706,8 @@ impl JVM { } Instruction::ArithmeticShiftIntLeft() => { - 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 shift = wrap_stackframe_error(class, method, frame.operand_stack.pop_int_compatible(0))? as u8 & 0b00011111; + let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int_compatible(0))?; // rust does arithmetic shift on singed values wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(int << shift)))?; @@ -746,8 +746,8 @@ impl JVM { } Instruction::AndInt() => { - 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))?; + let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int_compatible(0))?; + let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int_compatible(0))?; wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(value_1 & value_2)))?; } @@ -758,8 +758,8 @@ impl JVM { } Instruction::BranchIntEquality(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))?; + let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int_compatible(0))?; + let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int_compatible(0))?; if value_1 == value_2 { frame.instruction_pointer -= offset as u32; @@ -768,8 +768,8 @@ 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))?; + let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int_compatible(0))?; + let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int_compatible(0))?; if value_1 >= value_2 { frame.instruction_pointer -= offset as u32; @@ -778,8 +778,8 @@ impl JVM { } Instruction::BranchIntGreaterThan(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))?; + let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int_compatible(0))?; + let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int_compatible(0))?; if value_1 > value_2 { frame.instruction_pointer -= offset as u32; @@ -788,8 +788,8 @@ impl JVM { } 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))?; + let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int_compatible(0))?; + let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int_compatible(0))?; if value_1 != value_2 { frame.instruction_pointer -= offset as u32; @@ -798,8 +798,8 @@ impl JVM { } Instruction::BranchIntLessEquals(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))?; + let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int_compatible(0))?; + let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int_compatible(0))?; if value_1 <= value_2 { frame.instruction_pointer -= offset as u32; @@ -1100,6 +1100,18 @@ impl JVM { wrap_stackframe_error(class, method, frame.operand_stack.push(popped_value))?; } + Instruction::DuplicateComputationalValue() => { + if frame.operand_stack.computational_type_at(0) == 1 { + let popped_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_computational_1(0))?; + wrap_stackframe_error(class, method, frame.operand_stack.push(popped_value))?; + wrap_stackframe_error(class, method, frame.operand_stack.push(popped_value))?; + } else { + let popped_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_computational_2(0))?; + wrap_stackframe_error(class, method, frame.operand_stack.push_field_value(popped_value))?; + wrap_stackframe_error(class, method, frame.operand_stack.push_field_value(popped_value))?; + } + } + Instruction::DuplicateInsertDown() => { let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_computational_1(0))?; let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_computational_1(0))?; @@ -1182,34 +1194,39 @@ impl JVM { Instruction::InstanceOf(classref_index) => { let class_name = class.gather_class(classref_index)?; let object = wrap_stackframe_error(class, method, frame.operand_stack.peek_reference(0))?; - let native_class_name = self.heap_area.object_area.get_reference_native_class_name(object, &self.class_store); - if class_name.starts_with("[") { - // TODO: Create array class on demand + let instruction_result = if object == ObjectReference::NULL { + frame.operand_stack.pop_reference(0).unwrap(); + 0 } else { - if ! self.class_store.have_class(class_name) { - frame.instruction_pointer -= offset as u32; - return Ok(JVMCallbackOperation::LoadClass(class_name.to_string())); + let native_class_name = self.heap_area.object_area.get_reference_native_class_name(object, &self.class_store); + + if class_name.starts_with("[") { + // TODO: Create array class on demand + } else { + if ! self.class_store.have_class(class_name) { + frame.instruction_pointer -= offset as u32; + return Ok(JVMCallbackOperation::LoadClass(class_name.to_string())); + } + if ! self.class_store.was_init(class_name).unwrap() { + frame.instruction_pointer -= offset as u32; + return Ok(JVMCallbackOperation::InitClass(class_name.to_string())); + } } - if ! self.class_store.was_init(class_name).unwrap() { - frame.instruction_pointer -= offset as u32; - return Ok(JVMCallbackOperation::InitClass(class_name.to_string())); + + frame.operand_stack.pop_reference(0).unwrap(); + + if class_name == native_class_name { + 1 + } else { + 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_description = AbstractTypeDescription::parse_full(native_class_name)?; + if self.class_store.are_types_compatible(&object_description, &class_description) { 1 } else { 0 } } - } - - frame.operand_stack.pop_reference(0).unwrap(); - - - let instruction_result = if class_name == native_class_name { - 1 - } else { - 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_description = AbstractTypeDescription::parse_full(native_class_name)?; - if self.class_store.are_types_compatible(&object_description, &class_description) { 1 } else { 0 } }; @@ -1924,6 +1941,13 @@ impl JVM { wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(5)))?; } + Instruction::PushConstLong0() => { + wrap_stackframe_error(class, method, frame.operand_stack.push_long(0))?; + } + Instruction::PushConstLong1() => { + wrap_stackframe_error(class, method, frame.operand_stack.push_long(1))?; + } + Instruction::PushNull() => { wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Reference(ObjectReference::NULL)))?; } @@ -1937,6 +1961,7 @@ impl JVM { StackValue::Int(i) => { match expected_field_descriptor.as_str() { "Z" => FieldValue::Boolean(i != 0), + "B" => FieldValue::Byte(i as i8), _ => FieldValue::Int(i) } } diff --git a/src/native_methods.rs b/src/native_methods.rs index 0d455f8..4b6ec3e 100644 --- a/src/native_methods.rs +++ b/src/native_methods.rs @@ -1,3 +1,5 @@ +use crate::classfile::FieldInfo; +use crate::classstore::ClassStore; use crate::stackframe::StackFrame; use crate::heap_area::ObjectReference; use crate::heap_area::FieldValue; @@ -344,9 +346,204 @@ impl JavaLangStringUTF16 { } } +struct JavaLangSystem {} + +impl JavaLangSystem { + pub fn arraycopy(jvm: &mut JVM) -> Result { + let frame = { + let frame_index = jvm.stack_frames.len() - 1; + &mut jvm.stack_frames[frame_index] + }; + let src = frame.load_local_reference(0).unwrap(); + let src_pos = frame.load_local_int(1).unwrap(); + let dest = frame.load_local_reference(2).unwrap(); + let dest_pos = frame.load_local_int(3).unwrap(); + let length = frame.load_local_int(4).unwrap(); + + for i in 0..length { + let src_value = jvm.heap_area.object_area.get_array_element(src, src_pos + i); + jvm.heap_area.object_area.set_array_element(dest, (dest_pos + i) as usize, src_value); + } + + Ok(JVMCallbackOperation::PopFrame()) + } +} + +struct JavaLangThrowable {} + +impl JavaLangThrowable { + +} + struct JdkInternalMiscUnsafe {} impl JdkInternalMiscUnsafe { + + fn class_field_at_offset(class_index: usize, class_store: &ClassStore, offset: i64) -> Result<&FieldInfo, Error> { + let mut offset_counter = offset; + match ClassFieldIterator::new(class_index, class_store) + .take_while(|f| { + let result = offset_counter >= 0; + offset_counter -= f.descriptor.storage_size() as i64; + + result + }) + .last() { + Some(f) => Ok(f), + None => Err(Error::RunTimeError(format!("Couldn't find int field at offset {offset} in class {}", class_store.class_name_from_index(class_index).unwrap()))) + } + } + + fn array_class_reference_index_scale(class_reference: ObjectReference, jvm: &JVM) -> i32 { + let class_class_index = jvm.class_store.class_idx_from_name(&String::from("java/lang/Class")).unwrap(); + let component_class_reference = match jvm.heap_area.object_area.get_object_field(class_reference, "componentType", class_class_index, &jvm.class_store).unwrap() { + FieldValue::Reference(r) => r, + _ => unreachable!(), + }; + + if component_class_reference == jvm.class_store.primitive_classes.boolean_class { + 1 + } else if component_class_reference == jvm.class_store.primitive_classes.byte_class { + 1 + } else if component_class_reference == jvm.class_store.primitive_classes.short_class { + 2 + } else if component_class_reference == jvm.class_store.primitive_classes.char_class { + 2 + } else if component_class_reference == jvm.class_store.primitive_classes.int_class { + 4 + } else if component_class_reference == jvm.class_store.primitive_classes.float_class { + 4 + } else if component_class_reference == jvm.class_store.primitive_classes.double_class { + 8 + } else if component_class_reference == jvm.class_store.primitive_classes.long_class { + 8 + } else { + std::mem::size_of::() as i32 + } + } + + pub fn compare_and_set_reference(jvm: &mut JVM) -> Result { + let frame = { + let frame_index = jvm.stack_frames.len() - 1; + &mut jvm.stack_frames[frame_index] + }; + + let object = frame.load_local_reference(1).unwrap(); + let offset = frame.load_local_long(2).unwrap(); + let expected = frame.load_local_reference(4).unwrap(); + let replacement = frame.load_local_reference(5).unwrap(); + + if jvm.heap_area.object_area.is_array_reference(object) { + let class_reference = jvm.heap_area.object_area.get_reference_class_ref(object, &jvm.class_store); + let scale = JdkInternalMiscUnsafe::array_class_reference_index_scale(class_reference, jvm); + let index = offset / (scale as i64); + + let value = jvm.heap_area.object_area.get_array_element(object, index as i32); + + let success = if value.expect_reference() == expected { + jvm.heap_area.object_area.set_array_element(object, index as usize, replacement.into()); + true + } else { + false + }; + + Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Boolean(success))) + } else { + todo!() + } + } + + pub fn put_reference_volatile(jvm: &mut JVM) -> Result { + let frame = { + let frame_index = jvm.stack_frames.len() - 1; + &mut jvm.stack_frames[frame_index] + }; + + let object = frame.load_local_reference(1).unwrap(); + let offset = frame.load_local_long(2).unwrap(); + let replacement = frame.load_local_reference(4).unwrap(); + + if jvm.heap_area.object_area.is_array_reference(object) { + let class_reference = jvm.heap_area.object_area.get_reference_class_ref(object, &jvm.class_store); + let scale = JdkInternalMiscUnsafe::array_class_reference_index_scale(class_reference, jvm); + let index = offset / (scale as i64); + + jvm.heap_area.object_area.set_array_element(object, index as usize, replacement.into()); + + Ok(JVMCallbackOperation::PopFrame()) + } else { + todo!() + } + } + + pub fn get_reference_volatile(jvm: &mut JVM) -> Result { + let frame = { + let frame_index = jvm.stack_frames.len() - 1; + &mut jvm.stack_frames[frame_index] + }; + + let object = frame.load_local_reference(1).unwrap(); + let offset = frame.load_local_long(2).unwrap(); + + if jvm.heap_area.object_area.is_array_reference(object) { + let class_reference = jvm.heap_area.object_area.get_reference_class_ref(object, &jvm.class_store); + let scale = JdkInternalMiscUnsafe::array_class_reference_index_scale(class_reference, jvm); + let index = offset / (scale as i64); + + let value = jvm.heap_area.object_area.get_array_element(object, index as i32); + + Ok(JVMCallbackOperation::ReturnFrame(value)) + } else { + let object_class_descriptor = jvm.heap_area.object_area.get_reference_native_class_name(object, &jvm.class_store); + let object_class_index = jvm.class_store.class_index_for_type(AbstractTypeDescription::parse_full(object_class_descriptor).unwrap()).unwrap(); + + let field = JdkInternalMiscUnsafe::class_field_at_offset(object_class_index, &jvm.class_store, offset)?; + + // TODO: Type checking + let value = jvm.heap_area.object_area.get_object_field( + object, + &field.name, + object_class_index, + &jvm.class_store + )?; + + Ok(JVMCallbackOperation::ReturnFrame(value)) + } + } + + pub fn compare_and_set_long(jvm: &mut JVM) -> Result { + let frame = { + let frame_index = jvm.stack_frames.len() - 1; + &mut jvm.stack_frames[frame_index] + }; + + let object = frame.load_local_reference(1).unwrap(); + let offset = frame.load_local_long(2).unwrap(); + let expected = frame.load_local_long(4).unwrap(); + let replacement = frame.load_local_long(6).unwrap(); + + let object_class_descriptor = jvm.heap_area.object_area.get_reference_native_class_name(object, &jvm.class_store); + let object_class_index = jvm.class_store.class_index_for_type(AbstractTypeDescription::parse_full(object_class_descriptor).unwrap()).unwrap(); + + let field = JdkInternalMiscUnsafe::class_field_at_offset(object_class_index, &jvm.class_store, offset)?; + + // TODO: Type checking + let function_result = if jvm.heap_area.object_area.get_object_field(object, &field.name, object_class_index, &jvm.class_store)? == FieldValue::Long(expected) { + jvm.heap_area.object_area.set_object_field( + object, + &field.name, + FieldValue::Long(replacement), + object_class_index, + &jvm.class_store + )?; + true + } else { + false + }; + + Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Boolean(function_result))) + } + pub fn compare_and_set_int(jvm: &mut JVM) -> Result { let frame = { let frame_index = jvm.stack_frames.len() - 1; @@ -361,19 +558,9 @@ impl JdkInternalMiscUnsafe { let object_class_descriptor = jvm.heap_area.object_area.get_reference_native_class_name(object, &jvm.class_store); let object_class_index = jvm.class_store.class_index_for_type(AbstractTypeDescription::parse_full(object_class_descriptor).unwrap()).unwrap(); - let mut offset_counter = offset; - let field = match ClassFieldIterator::new(object_class_index, &jvm.class_store) - .take_while(|f| { - let result = offset_counter >= 0; - offset_counter -= f.descriptor.storage_size() as i64; - - result - }) - .last() { - Some(f) => f, - None => return Err(Error::RunTimeError(format!("Couldn't find int field at offset {offset} in class {object_class_descriptor}"))) - }; + let field = JdkInternalMiscUnsafe::class_field_at_offset(object_class_index, &jvm.class_store, offset)?; + // TODO: Type checking let function_result = if jvm.heap_area.object_area.get_object_field(object, &field.name, object_class_index, &jvm.class_store)? == FieldValue::Int(expected) { jvm.heap_area.object_area.set_object_field( object, @@ -419,33 +606,10 @@ impl JdkInternalMiscUnsafe { }; 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 class_reference = wrap_stackframe_error(class, method, frame.load_local_reference(1))?; - let component_class_reference = match jvm.heap_area.object_area.get_object_field(class_reference, "componentType", class_class_index, &jvm.class_store).unwrap() { - FieldValue::Reference(r) => r, - _ => unreachable!(), - }; - let index_scale: i32 = if component_class_reference == jvm.class_store.primitive_classes.boolean_class { - 1 - } else if component_class_reference == jvm.class_store.primitive_classes.byte_class { - 1 - } else if component_class_reference == jvm.class_store.primitive_classes.short_class { - 2 - } else if component_class_reference == jvm.class_store.primitive_classes.char_class { - 2 - } else if component_class_reference == jvm.class_store.primitive_classes.int_class { - 4 - } else if component_class_reference == jvm.class_store.primitive_classes.float_class { - 4 - } else if component_class_reference == jvm.class_store.primitive_classes.double_class { - 8 - } else if component_class_reference == jvm.class_store.primitive_classes.long_class { - 8 - } else { - std::mem::size_of::() as i32 - }; + let index_scale = JdkInternalMiscUnsafe::array_class_reference_index_scale(class_reference, jvm); Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Int(index_scale))) } @@ -507,13 +671,16 @@ impl JdkInternalUtilSystemPropsRaw { // command-line configured properties, should return at least java.home pub fn vm_properties(jvm: &mut JVM) -> Result { let native_array = vec![ - ("java.home", "./"), + ("java.home", "./"), // TODO ("stdout.encoding", "UTF-8"), ("java.io.tmpdir", "/tmp"), ("user.language", "en"), ("user.script", ""), ("user.country", "US"), ("user.variant", ""), + ("user.dir", "./"), + ("user.home", "./"), // TODO + ("user.name", "java"), // TODO ("sun.nio.MaxDirectMemorySize", "9223372036854775807"), ("sun.nio.PageAlignDirectMemory", "false"), ]; @@ -1121,7 +1288,7 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul ]), return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void()}, }, - todo_call + JavaLangSystem::arraycopy ), ( @@ -1450,7 +1617,7 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul ]), return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Boolean() }, }, - todo_call + JdkInternalMiscUnsafe::compare_and_set_long ), ( @@ -1465,7 +1632,7 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul ]), return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Boolean() }, }, - todo_call + JdkInternalMiscUnsafe::compare_and_set_reference ), ( @@ -1772,7 +1939,7 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul ]), return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname(String::from("java/lang/Object"))}, }, - todo_call + JdkInternalMiscUnsafe::get_reference_volatile ), ( @@ -2215,7 +2382,7 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul ]), return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void() }, }, - todo_call + JdkInternalMiscUnsafe::put_reference_volatile ), ( @@ -2684,6 +2851,18 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul }, todo_call ), + + ( + "java/lang/Throwable", + "fillInStackTrace", + MethodDescriptor { + argument_types: Box::new([ + AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Int()} + ]), + return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Throwable".to_string())}, + }, + JavaLangThrowable::fill_in_stacktrace() + ), ]; for (classname, methodname, methoddescriptor, binding) in native_mappings { diff --git a/src/stackframe.rs b/src/stackframe.rs index 0a4bfa6..2c31173 100644 --- a/src/stackframe.rs +++ b/src/stackframe.rs @@ -105,6 +105,26 @@ impl OperandStack { } } + pub fn computational_type_at(&self, index: usize) -> u8 { + let absolute_index = self.depth as usize - 1 - index; + + match self.stack[absolute_index] { + StackValue::Boolean(_) => 1, + StackValue::Byte(_) => 1, + StackValue::Char(_) => 1, + StackValue::Short(_) => 1, + StackValue::Int(_) => 1, + StackValue::Float(_) => 1, + StackValue::Reference(_) => 1, + StackValue::ReturnAddress(_) => 1, + StackValue::Double0(_) => 0, + StackValue::Double1() => 0, + StackValue::Long0(_) => 0, + StackValue::Long1() => 0, + _ => unreachable!() + } + } + pub fn pop_computational_2(&mut self, index: usize) -> Result { let absolute_index = self.depth as usize - 1 - index; let value_top = self.stack[absolute_index]; @@ -187,6 +207,17 @@ impl OperandStack { } } + pub fn pop_int_compatible(&mut self, index: usize) -> Result { + let absolute_index = self.depth as usize - 1 - index; + let value = self.stack[absolute_index]; + self.depth -= 1; + match value { + StackValue::Int(i) => Ok(i), + StackValue::Byte(b) => Ok(b as i32), + _ => Err(Error::LocalError(format!("Mismatched type at index {} of the function operand stack, expected Int-compatible but found '{:?}'", index, value))) + } + } + pub fn pop_float(&mut self, index: usize) -> Result { let absolute_index = self.depth as usize - 1 - index; let value = self.stack[absolute_index];