Implemented a lot of opcodes and some native methods

This commit is contained in:
VegOwOtenks 2024-11-03 17:42:04 +01:00
parent 4c43e9290f
commit 272a34b7cd
5 changed files with 394 additions and 101 deletions

View file

@ -35,12 +35,17 @@ impl Bytecode {
0x14 => (Instruction::LoadConstant64((self.bytes[offset+1] as u16) << 8 | self.bytes[offset+2] as u16), 3),
0x15 => (Instruction::LoadLocalInt(self.bytes[offset+1]), 2),
0x16 => (Instruction::LoadLocalLong(self.bytes[offset+1]), 2),
0x17 => (Instruction::LoadLocalFloat(self.bytes[offset+1]), 2),
0x19 => (Instruction::LoadLocalReference(self.bytes[offset+1]), 2),
0x1A => (Instruction::LoadLocalInt0(), 1),
0x1B => (Instruction::LoadLocalInt1(), 1),
0x1C => (Instruction::LoadLocalInt2(), 1),
0x1D => (Instruction::LoadLocalInt3(), 1),
0x1E => (Instruction::LoadLocalLong0(), 1),
0x1F => (Instruction::LoadLocalLong1(), 1),
0x20 => (Instruction::LoadLocalLong2(), 1),
0x21 => (Instruction::LoadLocalLong3(), 1),
0x22 => (Instruction::LoadLocalFloat0(), 1),
0x23 => (Instruction::LoadLocalFloat1(), 1),
0x24 => (Instruction::LoadLocalFloat2(), 1),
@ -64,6 +69,10 @@ impl Bytecode {
0x3C => (Instruction::StoreLocalInt1(), 1),
0x3D => (Instruction::StoreLocalInt2(), 1),
0x3E => (Instruction::StoreLocalInt3(), 1),
0x3F => (Instruction::StoreLocalLong0(), 1),
0x40 => (Instruction::StoreLocalLong1(), 1),
0x41 => (Instruction::StoreLocalLong2(), 1),
0x42 => (Instruction::StoreLocalLong3(), 1),
0x4B => (Instruction::StoreLocalReference0(), 1),
0x4C => (Instruction::StoreLocalReference1(), 1),
0x4D => (Instruction::StoreLocalReference2(), 1),
@ -80,11 +89,15 @@ impl Bytecode {
0x60 => (Instruction::AddInt(), 1),
0x64 => (Instruction::SubtractInt(), 1),
0x65 => (Instruction::SubtractLong(), 1),
0x68 => (Instruction::MultiplyInt(), 1),
0x69 => (Instruction::MultiplyLong(), 1),
0x6A => (Instruction::MultiplyFloat(), 1),
0x6C => (Instruction::DivideInt(), 1),
0x6D => (Instruction::DivideLong(), 1),
0x74 => (Instruction::NegateInt(), 1),
0x75 => (Instruction::NegateLong(), 1),
0x78 => (Instruction::ArithmeticShiftIntLeft(), 1),
0x7A => (Instruction::ArithmeticShiftIntRight(), 1),
0x7C => (Instruction::LogicalShiftIntRight(), 1),
@ -93,10 +106,14 @@ impl Bytecode {
0x80 => (Instruction::OrInt(), 1),
0x82 => (Instruction::XorInt(), 1),
0x84 => (Instruction::IncrementLocalInt(self.bytes[offset+1], i8::from_be_bytes([self.bytes[offset+2]])), 3),
0x85 => (Instruction::ConvertIntToLong(), 1),
0x86 => (Instruction::ConvertIntToFloat(), 1),
0x88 => (Instruction::ConvertLongToInt(), 1),
0x8B => (Instruction::ConvertFloatToInt(), 1),
0x91 => (Instruction::ConvertIntToByte(), 1),
0x92 => (Instruction::ConvertIntToChar(), 1),
0x94 => (Instruction::CompareLong(), 1),
0x95 => (Instruction::CompareFloatL(), 1),
0x96 => (Instruction::CompareFloatG(), 1),
0x99 => {
@ -207,6 +224,7 @@ impl Bytecode {
(Instruction::LookupSwitch(default, pairs_vec.into()), 1 + padding + 4 + 4 + npairs as usize * 8)
}
0xAC => (Instruction::ReturnInt(), 1),
0xAD => (Instruction::ReturnLong(), 1),
0xB0 => (Instruction::ReturnReference(), 1),
0xB1 => (Instruction::ReturnVoid(), 1),
@ -290,12 +308,17 @@ pub enum Instruction {
// double or long or whatever
LoadConstant64(u16) = 0x14, // Push Long or Double from constant pool
LoadLocalInt(u8) = 0x15, // Load int from indexed local variable
LoadLocalFloat(u8) = 0x17, // Load int from indexed local variable
LoadLocalLong(u8) = 0x16, // Load long from indexed local variable
LoadLocalFloat(u8) = 0x17, // Load float from indexed local variable
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
LoadLocalLong0() = 0x1E, // load long from local variable
LoadLocalLong1() = 0x1F, // load long from local variable
LoadLocalLong2() = 0x20, // load long from local variable
LoadLocalLong3() = 0x21, // load long from local variable
LoadLocalFloat0() = 0x22, // Load local double variable reference onto stack
LoadLocalFloat1() = 0x23, // Load local double variable reference onto stack
@ -320,6 +343,10 @@ pub enum Instruction {
StoreLocalInt1() = 0x3C, // store int into local variable
StoreLocalInt2() = 0x3D, // store int into local variable
StoreLocalInt3() = 0x3E, // store int into local variable
StoreLocalLong0() = 0x3F, // store int into local variable
StoreLocalLong1() = 0x40, // store int into local variable
StoreLocalLong2() = 0x41, // store int into local variable
StoreLocalLong3() = 0x42, // 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
@ -335,11 +362,15 @@ pub enum Instruction {
AddInt() = 0x60, // int addition
SubtractInt() = 0x64, // int subtraction
SubtractLong() = 0x65, // long subtraction
MultiplyInt() = 0x68, // int multiplication
MultiplyLong() = 0x69, // long multiplication
MultiplyFloat() = 0x6A, // float multiplication
DivideInt() = 0x6C, // integer division, round toward zero and more rules
DivideLong() = 0x6D, // long division
NegateInt() = 0x74, // arithmetic negation
NegateLong() = 0x75, // arithmetic negation
ArithmeticShiftIntLeft() = 0x78, // shift int left, preserve sign
ArithmeticShiftIntRight() = 0x7A, // shift int right, preserve sign
LogicalShiftIntRight() = 0x7C, // shift int right with zero extension
@ -348,10 +379,14 @@ pub enum Instruction {
OrInt() = 0x80, // value, value => or
XorInt() = 0x82, // value, value => xor
IncrementLocalInt(u8, i8) = 0x84, // increment local variable by constant i8
ConvertIntToLong() = 0x85, // convert int on stack to long
ConvertIntToFloat() = 0x86, // change data type
ConvertLongToInt() = 0x88, // change data type
ConvertFloatToInt() = 0x8B, // change data type
ConvertIntToByte() = 0x91, // truncate int to 8 bits
ConvertIntToChar() = 0x92, // truncate int to 16 bits
CompareLong() = 0x94, // compare long
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
@ -374,6 +409,7 @@ pub enum Instruction {
TableSwitch(i32, i32, i32, Box<[i32]>) = 0xAA, // jump based on indexed range
LookupSwitch(i32, Box<[(i32, i32)]>) = 0xAB, // jump based on switch value
ReturnInt() = 0xAC, // return integer from function
ReturnLong() = 0xAD, // return long from function
ReturnReference() = 0xB0, // return top-ref from current function
ReturnVoid() = 0xB1, // return void from function

View file

@ -6,6 +6,7 @@ use core::str::Utf8Error;
use crate::accessmasks::*;
use crate::bytecode::Bytecode;
use crate::constantpool::{ ConstantFieldRefInfo, ConstantPoolInfo, ConstantUtf8Info, ConstantInterfaceMethodRefInfo, ConstantStringInfo, ConstantMethodRefInfo, ConstantFloatInfo, ConstantClassInfo, ConstantNameAndTypeInfo, ConstantIntegerInfo, ConstantLongInfo };
use crate::constantpool::ConstantDoubleInfo;
#[derive(Debug)]
pub enum Error {
@ -266,6 +267,15 @@ impl JavaClassFile {
};
}
pub fn pool_double_entry(&self, index: u16) -> Result<&ConstantDoubleInfo, Error> {
let pool_entry = self.pool_entry(index)?;
return match pool_entry {
ConstantPoolInfo::Double(data) => Ok(data),
_ => Err(Error::BadFileError(format!("Expected constant pool entry {} in class {} to be of type Double but found {:?}", index, self.get_classname()?, pool_entry)))
};
}
pub fn pool_long_entry(&self, index: u16) -> Result<&ConstantLongInfo, Error> {
let pool_entry = self.pool_entry(index)?;

View file

@ -442,7 +442,7 @@ impl JVM {
};
let class = self.class_store.class_file_from_idx(frame.class_index).unwrap();
let method = & class.methods[frame.method_index as usize];
wrap_stackframe_error(class, method, self.stack_frames.last_mut().unwrap().operand_stack.push(value))?;
wrap_stackframe_error(class, method, self.stack_frames.last_mut().unwrap().operand_stack.push_field_value(value))?;
}
JVMCallbackOperation::PushFrame(frame) => self.stack_frames.push(frame),
@ -580,6 +580,11 @@ impl JVM {
FieldValue::Float(float_entry.value)
},
AbstractTypeKind::Double() => {
let double_entry = class_file.pool_double_entry(constant_value_info.constant_value_index)?;
FieldValue::Double(double_entry.value)
}
AbstractTypeKind::Classname(ref name) => {
if name == "java/lang/String" {
let string_entry = class_file.gather_string(constant_value_info.constant_value_index)?;
@ -880,6 +885,7 @@ impl JVM {
// TODO: Class loading checks
let class_name = class.gather_class(classref_index)?;
let object = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?;
if object != ObjectReference::NULL {
let native_class_name = self.heap_area.object_area.get_reference_native_class_name(object, &self.class_store);
let instruction_result = if class_name == native_class_name {
@ -898,8 +904,9 @@ impl JVM {
// 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() => {
@ -936,6 +943,20 @@ impl JVM {
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(comparison_result)))?;
}
Instruction::CompareLong() => {
let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
let comparison_result = if value_1 > value_2 {
1
} else if value_1 < value_2 {
-1
} else {
0
};
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(comparison_result)))?;
}
Instruction::ConvertFloatToInt() => {
let float = wrap_stackframe_error(class, method, frame.operand_stack.pop_float(0))?;
let int_value = match float {
@ -947,6 +968,13 @@ impl JVM {
frame.operand_stack.push(StackValue::Int(int_value)).unwrap();
}
Instruction::ConvertIntToByte() => {
let int_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
let byte_value = int_value & 0x000000FF;
frame.operand_stack.push(StackValue::Int(byte_value)).unwrap();
}
Instruction::ConvertIntToChar() => {
let int_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
let char_value = int_value & 0x0000FFFF;
@ -961,6 +989,20 @@ impl JVM {
frame.operand_stack.push(StackValue::Float(float_value)).unwrap();
}
Instruction::ConvertIntToLong() => {
let int_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
let long_value = int_value as i64;
wrap_stackframe_error(class, method, frame.operand_stack.push_long(long_value))?;
}
Instruction::ConvertLongToInt() => {
let long_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
let int_value = long_value as i32;
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(int_value)))?;
}
Instruction::DivideInt() => {
// TODO: Obey all the rules
let quotient = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
@ -969,6 +1011,15 @@ impl JVM {
frame.operand_stack.push(StackValue::Int(divident / quotient)).unwrap();
}
Instruction::DivideLong() => {
// TODO: Obey all the rules
let quotient = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
let divident = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
let result = divident / quotient;
wrap_stackframe_error(class, method, frame.operand_stack.push_long(result))?;
}
Instruction::Duplicate() => {
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))?;
@ -1474,6 +1525,11 @@ impl JVM {
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(int_value)))?;
}
ConstantPoolInfo::Float(float_data) => {
let float_value = float_data.value;
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Float(float_value)))?;
}
_ => {
println!("{:?}", class.pool_entry(wide_index).unwrap());
todo!()
@ -1488,6 +1544,11 @@ impl JVM {
wrap_stackframe_error(class, method, frame.operand_stack.push_long(long_value))?;
}
ConstantPoolInfo::Double(double_data) => {
let double = double_data.value;
wrap_stackframe_error(class, method, frame.operand_stack.push_double(double))?;
}
_ => {
println!("{:?}", class.pool_entry(wide_index).unwrap());
todo!()
@ -1527,6 +1588,28 @@ impl JVM {
load_local_int(class, method, frame, 3)?;
}
Instruction::LoadLocalLong(index) => {
let long_value = wrap_stackframe_error(class, method, frame.load_local_long(index as u16))?;
wrap_stackframe_error(class, method, frame.operand_stack.push_long(long_value))?;
}
Instruction::LoadLocalLong0() => {
let long_value = wrap_stackframe_error(class, method, frame.load_local_long(0))?;
wrap_stackframe_error(class, method, frame.operand_stack.push_long(long_value))?;
}
Instruction::LoadLocalLong1() => {
let long_value = wrap_stackframe_error(class, method, frame.load_local_long(1))?;
wrap_stackframe_error(class, method, frame.operand_stack.push_long(long_value))?;
}
Instruction::LoadLocalLong2() => {
let long_value = wrap_stackframe_error(class, method, frame.load_local_long(2))?;
wrap_stackframe_error(class, method, frame.operand_stack.push_long(long_value))?;
}
Instruction::LoadLocalLong3() => {
let long_value = wrap_stackframe_error(class, method, frame.load_local_long(3))?;
wrap_stackframe_error(class, method, frame.operand_stack.push_long(long_value))?;
}
Instruction::LoadLocalReference(index) => {
load_local_reference(class, method, frame, index as usize)?;
}
@ -1588,6 +1671,27 @@ impl JVM {
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(java_result)))?;
}
Instruction::MultiplyLong() => {
let factor_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
let factor_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
let result = factor_1 * factor_2;
wrap_stackframe_error(class, method, frame.operand_stack.push_long(result))?;
}
Instruction::NegateInt() => {
let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
let negated = -int;
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(negated)))?;
}
Instruction::NegateLong() => {
let long = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
let negated = -long;
wrap_stackframe_error(class, method, frame.operand_stack.push_long(negated))?;
}
Instruction::NewArray(component_class_index) => {
// construct single level array
let component_class_name = class.gather_class(component_class_index)?;
@ -1743,6 +1847,7 @@ impl JVM {
StackValue::Int(i) => FieldValue::Int(i),
StackValue::Reference(r) => FieldValue::Reference(r),
StackValue::Float(f) => FieldValue::Float(f),
StackValue::Byte(b) => FieldValue::Byte(b),
stack_value @ _ => {
println!("{stack_value:?}");
todo!()
@ -1845,17 +1950,28 @@ impl JVM {
let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
return Ok(JVMCallbackOperation::ReturnFrame(StackValue::Int(int)));
return Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Int(int)));
}
Instruction::ReturnLong() => {
match (method.descriptor.return_type.array_level, &method.descriptor.return_type.kind) {
(0, AbstractTypeKind::Long()) => (),
_ => return Err(Error::OpcodeError(format!("Found opcode '{:?}' on method returning '{:?}'", instruction, method.descriptor.return_type)))
}
let long = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
return Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Long(long)));
}
Instruction::ReturnReference() => {
match (method.descriptor.return_type.array_level, &method.descriptor.return_type.kind) {
(1..=u8::MAX, _) => (),
(_, AbstractTypeKind::Classname(_)) => (),
_ => return Err(Error::OpcodeError(format!("Found opcode '{:?}' on method returning '{:?}'", instruction, method.descriptor.return_type)))
}
let ref_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?;
return Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(ref_value)));
return Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Reference(ref_value)));
}
Instruction::ReturnVoid() => {
let expected_type = AbstractTypeDescription {
@ -1928,6 +2044,13 @@ impl JVM {
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(value_1 - value_2)))?;
}
Instruction::SubtractLong() => {
let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
wrap_stackframe_error(class, method, frame.operand_stack.push_long(value_1 - value_2))?;
}
Instruction::StoreLocalFloat(index) => {
let float = wrap_stackframe_error(class, method, frame.operand_stack.pop_float(0))?;
@ -1961,11 +2084,39 @@ impl JVM {
}
Instruction::StoreLocalLong(index) => {
let long1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_long1(0))?;
let _ = wrap_stackframe_error(class, method, frame.operand_stack.pop_long1(0))?;
let long0 = wrap_stackframe_error(class, method, frame.operand_stack.pop_long0(0))?;
wrap_stackframe_error(class, method, frame.store_local(index as u16, StackValue::Long0(long0)))?;
wrap_stackframe_error(class, method, frame.store_local(index as u16 + 1, StackValue::Long1(long1)))?;
wrap_stackframe_error(class, method, frame.store_local(index as u16 + 1, StackValue::Long1()))?;
}
Instruction::StoreLocalLong0() => {
let _ = wrap_stackframe_error(class, method, frame.operand_stack.pop_long1(0))?;
let long0 = wrap_stackframe_error(class, method, frame.operand_stack.pop_long0(0))?;
wrap_stackframe_error(class, method, frame.store_local(1, StackValue::Long0(long0)))?;
wrap_stackframe_error(class, method, frame.store_local(2, StackValue::Long1()))?;
}
Instruction::StoreLocalLong1() => {
let _ = wrap_stackframe_error(class, method, frame.operand_stack.pop_long1(0))?;
let long0 = wrap_stackframe_error(class, method, frame.operand_stack.pop_long0(0))?;
wrap_stackframe_error(class, method, frame.store_local(1, StackValue::Long0(long0)))?;
wrap_stackframe_error(class, method, frame.store_local(2, StackValue::Long1()))?;
}
Instruction::StoreLocalLong2() => {
let _ = wrap_stackframe_error(class, method, frame.operand_stack.pop_long1(0))?;
let long0 = wrap_stackframe_error(class, method, frame.operand_stack.pop_long0(0))?;
wrap_stackframe_error(class, method, frame.store_local(2, StackValue::Long0(long0)))?;
wrap_stackframe_error(class, method, frame.store_local(3, StackValue::Long1()))?;
}
Instruction::StoreLocalLong3() => {
let _ = wrap_stackframe_error(class, method, frame.operand_stack.pop_long1(0))?;
let long0 = wrap_stackframe_error(class, method, frame.operand_stack.pop_long0(0))?;
wrap_stackframe_error(class, method, frame.store_local(3, StackValue::Long0(long0)))?;
wrap_stackframe_error(class, method, frame.store_local(4, StackValue::Long1()))?;
}
Instruction::StoreLocalReference(index) => {
@ -2029,7 +2180,7 @@ impl JVM {
pub enum JVMCallbackOperation {
PopFrame(),
ReturnFrame(StackValue),
ReturnFrame(FieldValue),
PushFrame(StackFrame),
LoadClass(String),
InitClass(String),
@ -2053,9 +2204,9 @@ fn load_local_float(class: &JavaClassFile, method: &MethodInfo, frame: &mut Stac
}
fn load_local_int(class: &JavaClassFile, method: &MethodInfo, frame: &mut StackFrame, index: usize) -> Result<(), Error> {
let loaded_value = wrap_stackframe_error(class, method, frame.load_local_int(index as u16))?;
let int_compatible_stackvalue = wrap_stackframe_error(class, method, frame.load_local_int_compatible(index as u16))?;
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(loaded_value)))?;
wrap_stackframe_error(class, method, frame.operand_stack.push(int_compatible_stackvalue))?;
Ok(())
}
@ -2095,15 +2246,12 @@ fn fill_arguments(class: &JavaClassFile, method: &MethodInfo, arguments: &mut Ve
)
},
AbstractTypeKind::Double() => {
arguments.push_front(
StackValue::Double1(
wrap_stackframe_error(
class,
method,
stack.pop_double1(0)
)?
)
);
)?;
arguments.push_front(StackValue::Double1());
arguments.push_front(
StackValue::Double0(
wrap_stackframe_error(
@ -2137,13 +2285,13 @@ fn fill_arguments(class: &JavaClassFile, method: &MethodInfo, arguments: &mut Ve
)
},
AbstractTypeKind::Long() => {
arguments.push_front(
StackValue::Long1(
wrap_stackframe_error(
class,
method,
stack.pop_long1(0)
)?
)?;
arguments.push_front(
StackValue::Long1(
)
);
arguments.push_front(

View file

@ -87,7 +87,7 @@ impl JavaLangClass {
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)))
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::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(
@ -114,7 +114,7 @@ impl JavaLangClass {
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)))
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::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(
@ -141,7 +141,7 @@ impl JavaLangClass {
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)))
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::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(
@ -168,7 +168,7 @@ impl JavaLangClass {
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)))
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::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(
@ -195,7 +195,7 @@ impl JavaLangClass {
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)))
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::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(
@ -222,7 +222,7 @@ impl JavaLangClass {
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)))
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::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(
@ -249,7 +249,7 @@ impl JavaLangClass {
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)))
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::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(
@ -276,17 +276,55 @@ impl JavaLangClass {
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)))
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Reference(long_class_ref)))
} else {
Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(ObjectReference::NULL)))
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Reference(ObjectReference::NULL)))
}
}
_ => Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(ObjectReference::NULL)))
_ => Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Reference(ObjectReference::NULL)))
}
}
pub fn desired_assertion_status_0(_: &mut JVM) -> Result<JVMCallbackOperation, Error> {
Ok(JVMCallbackOperation::ReturnFrame(StackValue::Int(1)))
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Int(1)))
}
}
struct JavaLangFloat {}
impl JavaLangFloat {
pub fn float_to_raw_int_bits(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
let frame = {
let frame_index = jvm.stack_frames.len() - 1;
&mut jvm.stack_frames[frame_index]
};
let class = jvm.class_store.class_file_from_idx(frame.class_index).unwrap();
let method = & class.methods[frame.method_index as usize];
let float_value = wrap_stackframe_error(class, method, frame.load_local_float(0))?;
let ubits = float_value.to_bits();
let ibits = i32::from_ne_bytes(ubits.to_ne_bytes());
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Int(ibits)))
}
}
struct JavaLangDouble {}
impl JavaLangDouble {
pub fn double_to_raw_long_bits(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
let frame = {
let frame_index = jvm.stack_frames.len() - 1;
&mut jvm.stack_frames[frame_index]
};
let class = jvm.class_store.class_file_from_idx(frame.class_index).unwrap();
let method = & class.methods[frame.method_index as usize];
let double_value = wrap_stackframe_error(class, method, frame.load_local_double(0))?;
let ubits = double_value.to_bits();
let ibits = i64::from_ne_bytes(ubits.to_ne_bytes());
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Long(ibits)))
}
}
@ -294,7 +332,7 @@ struct JavaLangStringUTF16 {}
impl JavaLangStringUTF16 {
pub fn is_big_endian(_jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
Ok(JVMCallbackOperation::ReturnFrame(StackValue::Int(if cfg!(target_endian = "big") {1} else {0})))
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Int(if cfg!(target_endian = "big") {1} else {0})))
}
}
@ -336,12 +374,12 @@ impl JdkInternalMiscUnsafe {
std::mem::size_of::<usize>() as i32
};
Ok(JVMCallbackOperation::ReturnFrame(StackValue::Int(index_scale)))
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Int(index_scale)))
}
pub fn array_base_offset_0(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
// TODO: Check passed class
Ok(JVMCallbackOperation::ReturnFrame(StackValue::Int(0)))
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Int(0)))
}
}
@ -390,7 +428,7 @@ impl JdkInternalUtilSystemPropsRaw {
}
Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(array_reference)))
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Reference(array_reference)))
}
// command-line configured properties, should return at least java.home
@ -404,6 +442,7 @@ impl JdkInternalUtilSystemPropsRaw {
("user.country", "US"),
("user.variant", ""),
("sun.nio.MaxDirectMemorySize", "9223372036854775807"),
("sun.nio.PageAlignDirectMemory", "false"),
];
// TODO: Cross-Platform tmpdir
// TODO: locale detection
@ -420,7 +459,7 @@ impl JdkInternalUtilSystemPropsRaw {
jvm.heap_area.object_area.set_array_element(array_reference, index * 2 + 1, value_reference.into());
}
Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(array_reference)))
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Reference(array_reference)))
}
}
@ -921,6 +960,36 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
Ok(todo_call)
}
("java/lang/Double", "doubleToRawLongBits") => {
let expected_descriptor = MethodDescriptor {
argument_types: Box::new([
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Double() }
]),
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Long() },
};
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(JavaLangDouble::double_to_raw_long_bits)
}
("java/lang/Double", "longBitsToDouble") => {
let expected_descriptor = MethodDescriptor {
argument_types: Box::new([
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Long() }
]),
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Double() },
};
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(JavaLangDouble::double_to_raw_long_bits)
}
("java/lang/Float", "intBitsToFloat") => {
let expected_descriptor = MethodDescriptor {
argument_types: Box::new([
@ -948,7 +1017,7 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
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(todo_call)
Ok(JavaLangFloat::float_to_raw_int_bits)
}
("java/lang/String", "intern") => {

View file

@ -6,17 +6,17 @@ use crate::heap_area::{ ObjectReference, FieldValue };
#[derive(Copy, Clone, Debug)]
pub enum StackValue {
Boolean(bool),
Byte(u8),
Byte(i8),
Char(u16),
Short(u16),
Int(i32),
Float(f32),
Reference(ObjectReference),
ReturnAddress(u32),
Double0(u32),
Double1(u32),
Long0(u32),
Long1(u32),
Double0(f64),
Double1(),
Long0(i64),
Long1(),
Empty(),
}
@ -59,12 +59,15 @@ impl OperandStack {
}
pub fn push_long(&mut self, long: i64) -> Result<(), Error> {
let long_bytes: [u8; 8] = long.to_be_bytes();
self.push(StackValue::Long0(long))?;
self.push(StackValue::Long1())?;
let long0_bytes = u32::from_be_bytes([long_bytes[0], long_bytes[1], long_bytes[2], long_bytes[3]]);
self.push(StackValue::Long0(long0_bytes))?;
let long1_bytes = u32::from_be_bytes([long_bytes[4], long_bytes[5], long_bytes[6], long_bytes[7]]);
self.push(StackValue::Long1(long1_bytes))?;
Ok(())
}
pub fn push_double(&mut self, double: f64) -> Result<(), Error> {
self.push(StackValue::Double0(double))?;
self.push(StackValue::Double1())?;
Ok(())
}
@ -91,6 +94,10 @@ impl OperandStack {
self.push(StackValue::Float(i))
}
FieldValue::Long(l) => {
self.push_long(l)
}
_ => {
println!("{value:?}");
todo!();
@ -106,19 +113,12 @@ impl OperandStack {
self.depth -= 2;
match (value_bot, value_top) {
(StackValue::Long0(l0), StackValue::Long1(l1)) => {
let l0_bytes = l0.to_ne_bytes();
let l1_bytes = l1.to_ne_bytes();
let concat_bytes = [l0_bytes[0], l0_bytes[1], l0_bytes[2], l0_bytes[3], l1_bytes[0], l1_bytes[1], l1_bytes[2], l1_bytes[3]];
(StackValue::Long0(l0), StackValue::Long1()) => {
Ok(FieldValue::Long(i64::from_ne_bytes(concat_bytes)))
Ok(FieldValue::Long(l0))
}
(StackValue::Double0(d0), StackValue::Double1(d1)) => {
let d0_bytes = d0.to_ne_bytes();
let d1_bytes = d1.to_ne_bytes();
let concat_bytes = [d0_bytes[0], d0_bytes[1], d0_bytes[2], d0_bytes[3], d1_bytes[0], d1_bytes[1], d1_bytes[2], d1_bytes[3]];
Ok(FieldValue::Double(f64::from_ne_bytes(concat_bytes)))
(StackValue::Double0(d0), StackValue::Double1()) => {
Ok(FieldValue::Double(d0))
}
_ => Err(Error::LocalError(format!("Mismatched type at index {index} of the function operand stack, expected type with computational type 2 but found '{value_bot:?}, {value_top:?}'")))
}
@ -130,7 +130,7 @@ impl OperandStack {
self.depth -= 1;
match value {
StackValue::Long0(_) | StackValue::Long1(_) | StackValue::Double0(_) | StackValue::Double1(_) => {
StackValue::Long0(_) | StackValue::Long1() | StackValue::Double0(_) | StackValue::Double1() => {
Err(Error::LocalError(format!("Mismatched type at index {} of the function operand stack, expected type with computational type 1 but found '{:?}'", index, value)))
},
_ => Ok(value),
@ -147,12 +147,13 @@ impl OperandStack {
}
}
pub fn pop_byte(&mut self, index: usize) -> Result<u8, Error> {
pub fn pop_byte(&mut self, index: usize) -> Result<i8, Error> {
let absolute_index = self.depth as usize - 1 - index;
let value = self.stack[absolute_index];
self.depth -= 1;
match value {
StackValue::Byte(b) => Ok(b),
_ => Err(Error::LocalError(format!("Mismatched type at index {} of the function operand stack, expected Byte but found '{:?}'", index, value)))
StackValue::Int(b) => Ok(b as i8),
_ => Err(Error::LocalError(format!("Mismatched type at index {} of the function operand stack, expected Int(Byte) but found '{:?}'", index, value)))
}
}
@ -225,7 +226,7 @@ impl OperandStack {
}
}
pub fn pop_double0(&mut self, index: usize) -> Result<u32, Error> {
pub fn pop_double0(&mut self, index: usize) -> Result<f64, Error> {
let absolute_index = self.depth as usize - 1 - index;
let value = self.stack[absolute_index];
self.depth -= 1;
@ -235,17 +236,17 @@ impl OperandStack {
}
}
pub fn pop_double1(&mut self, index: usize) -> Result<u32, Error> {
pub fn pop_double1(&mut self, index: usize) -> Result<(), Error> {
let absolute_index = self.depth as usize - 1 - index;
let value = self.stack[absolute_index];
self.depth -= 1;
match value {
StackValue::Double1(a) => Ok(a),
StackValue::Double1() => Ok(()),
_ => Err(Error::LocalError(format!("Mismatched type at index {} of the function operand stack, expected Double1 but found '{:?}'", index, value)))
}
}
pub fn pop_long0(&mut self, index: usize) -> Result<u32, Error> {
pub fn pop_long0(&mut self, index: usize) -> Result<i64, Error> {
let absolute_index = self.depth as usize - 1 - index;
let value = self.stack[absolute_index];
self.depth -= 1;
@ -255,12 +256,12 @@ impl OperandStack {
}
}
pub fn pop_long1(&mut self, index: usize) -> Result<u32, Error> {
pub fn pop_long1(&mut self, index: usize) -> Result<(), Error> {
let absolute_index = self.depth as usize - 1 - index;
let value = self.stack[absolute_index];
self.depth -= 1;
match value {
StackValue::Long1(a) => Ok(a),
StackValue::Long1() => Ok(()),
_ => Err(Error::LocalError(format!("Mismatched type at index {} of the function operand stack, expected Long1 but found '{:?}'", index, value)))
}
}
@ -271,11 +272,8 @@ impl OperandStack {
let lower_bytes = self.stack[absolute_index + 1];
self.depth -= 2;
match (higher_bytes, lower_bytes) {
(StackValue::Double0(hi), StackValue::Double1(lo)) => {
let v: u64 = ((hi as u64) << 32) | lo as u64;
Ok(
f64::from_bits(v)
)
(StackValue::Double0(double), StackValue::Double1()) => {
Ok(double)
},
_ => Err(Error::LocalError(format!("Mismatched types at index {} of the function operand stack, expected (Double0, Double1) but found '{:?}'", index, (higher_bytes, lower_bytes))))
}
@ -283,17 +281,14 @@ impl OperandStack {
pub fn pop_long(&mut self, index: usize) -> Result<i64, Error> {
let absolute_index = self.depth as usize - 1 - index;
let lower_bytes = self.stack[absolute_index];
let higher_bytes = self.stack[absolute_index - 1];
let long0 = self.stack[absolute_index];
let long1 = self.stack[absolute_index - 1];
self.depth -= 2;
match (higher_bytes, lower_bytes) {
(StackValue::Long0(hi), StackValue::Long1(lo)) => {
let concat_u64 = ((hi as u64) << 32) | lo as u64;
let concat_array = concat_u64.to_ne_bytes();
let long_value = i64::from_ne_bytes(concat_array);
Ok(long_value)
match (long1, long0) {
(StackValue::Long0(long), StackValue::Long1()) => {
Ok(long)
},
_ => Err(Error::LocalError(format!("Mismatched types at index {} of the function operand stack, expected (Long0, Long1) but found '{:?}'", index, (higher_bytes, lower_bytes))))
_ => Err(Error::LocalError(format!("Mismatched types at index {} of the function operand stack, expected (Long0, Long1) but found '{:?}'", index, (long1, long0))))
}
}
}
@ -339,6 +334,18 @@ impl StackFrame {
}
}
pub fn load_local_long(&self, index: u16) -> Result<i64, Error> {
let long0 = self.locals[index as usize];
let long1 = self.locals[index as usize + 1];
match (long0, long1) {
(StackValue::Long0(long), StackValue::Long1()) => {
Ok(long)
}
_ => Err(Error::LocalError(format!("Mismatched type at index {} of the function locals, expected Long0, Long1 but found '{:?},{:?}'", index, long0, long1)))
}
}
pub fn load_local_float(&self, index: u16) -> Result<f32, Error> {
let local = self.locals[index as usize];
match local {
@ -347,6 +354,18 @@ impl StackFrame {
}
}
pub fn load_local_double(&self, index: u16) -> Result<f64, Error> {
let double0 = self.locals[index as usize];
let double1 = self.locals[index as usize + 1];
match (double0, double1) {
(StackValue::Double0(double), StackValue::Double1()) => {
Ok(double)
}
_ => Err(Error::LocalError(format!("Mismatched type at index {} of the function locals, expected Long0, Long1 but found '{:?},{:?}'", index, double0, double1)))
}
}
pub fn load_local_int(&self, index: u16) -> Result<i32, Error> {
let local = self.locals[index as usize];
match local {
@ -355,6 +374,17 @@ impl StackFrame {
}
}
pub fn load_local_int_compatible(&self, index: u16) -> Result<StackValue, Error> {
let local = self.locals[index as usize];
match local {
StackValue::Int(_) => Ok(local),
StackValue::Short(_) => Ok(local),
StackValue::Char(_) => Ok(local),
StackValue::Byte(_) => Ok(local),
_ => Err(Error::LocalError(format!("Mismatched type at index {} of the function locals, expected Int but found '{:?}'", index, local)))
}
}
pub fn load_local_reference(&self, index: u16) -> Result<ObjectReference, Error> {
let local = self.locals[index as usize];
match local {