Implemented a lot of opcodes and some native methods
This commit is contained in:
parent
4c43e9290f
commit
272a34b7cd
5 changed files with 394 additions and 101 deletions
|
@ -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),
|
||||
|
@ -289,13 +307,18 @@ pub enum Instruction {
|
|||
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
|
||||
LoadLocalInt(u8) = 0x15, // Load int from indexed local variable
|
||||
LoadLocalFloat(u8) = 0x17, // Load int from indexed local variable
|
||||
LoadLocalInt(u8) = 0x15, // 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
|
||||
|
|
|
@ -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)?;
|
||||
|
||||
|
|
222
src/jvm.rs
222
src/jvm.rs
|
@ -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,26 +885,28 @@ 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))?;
|
||||
let native_class_name = self.heap_area.object_area.get_reference_native_class_name(object, &self.class_store);
|
||||
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 {
|
||||
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 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 }
|
||||
};
|
||||
let object_description = AbstractTypeDescription::parse_full(native_class_name)?;
|
||||
if self.class_store.are_types_compatible(&object_description, &class_description) { 1 } else { 0 }
|
||||
};
|
||||
|
||||
if instruction_result == 0 {
|
||||
// TODO: Throw Exception
|
||||
return Err(Error::RunTimeError(format!("Trying to cast an object of type {native_class_name} to {class_name}")))
|
||||
if instruction_result == 0 {
|
||||
// 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)
|
||||
)?
|
||||
)
|
||||
);
|
||||
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() => {
|
||||
wrap_stackframe_error(
|
||||
class,
|
||||
method,
|
||||
stack.pop_long1(0)
|
||||
)?;
|
||||
arguments.push_front(
|
||||
StackValue::Long1(
|
||||
wrap_stackframe_error(
|
||||
class,
|
||||
method,
|
||||
stack.pop_long1(0)
|
||||
)?
|
||||
)
|
||||
);
|
||||
arguments.push_front(
|
||||
|
|
|
@ -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") => {
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue