Implemented opcodes, natives, fixed iterators
This commit is contained in:
parent
49916f5564
commit
dfb6060df9
6 changed files with 1485 additions and 1585 deletions
|
@ -88,6 +88,8 @@ impl Bytecode {
|
||||||
0x5A => (Instruction::DuplicateInsertDown(), 1),
|
0x5A => (Instruction::DuplicateInsertDown(), 1),
|
||||||
|
|
||||||
0x60 => (Instruction::AddInt(), 1),
|
0x60 => (Instruction::AddInt(), 1),
|
||||||
|
0x61 => (Instruction::AddLong(), 1),
|
||||||
|
0x63 => (Instruction::AddDouble(), 1),
|
||||||
0x64 => (Instruction::SubtractInt(), 1),
|
0x64 => (Instruction::SubtractInt(), 1),
|
||||||
0x65 => (Instruction::SubtractLong(), 1),
|
0x65 => (Instruction::SubtractLong(), 1),
|
||||||
0x68 => (Instruction::MultiplyInt(), 1),
|
0x68 => (Instruction::MultiplyInt(), 1),
|
||||||
|
@ -95,10 +97,12 @@ impl Bytecode {
|
||||||
0x6A => (Instruction::MultiplyFloat(), 1),
|
0x6A => (Instruction::MultiplyFloat(), 1),
|
||||||
0x6C => (Instruction::DivideInt(), 1),
|
0x6C => (Instruction::DivideInt(), 1),
|
||||||
0x6D => (Instruction::DivideLong(), 1),
|
0x6D => (Instruction::DivideLong(), 1),
|
||||||
|
0x6E => (Instruction::DivideFloat(), 1),
|
||||||
|
|
||||||
0x74 => (Instruction::NegateInt(), 1),
|
0x74 => (Instruction::NegateInt(), 1),
|
||||||
0x75 => (Instruction::NegateLong(), 1),
|
0x75 => (Instruction::NegateLong(), 1),
|
||||||
0x78 => (Instruction::ArithmeticShiftIntLeft(), 1),
|
0x78 => (Instruction::ArithmeticShiftIntLeft(), 1),
|
||||||
|
0x79 => (Instruction::ArithmeticShiftLongLeft(), 1),
|
||||||
0x7A => (Instruction::ArithmeticShiftIntRight(), 1),
|
0x7A => (Instruction::ArithmeticShiftIntRight(), 1),
|
||||||
0x7C => (Instruction::LogicalShiftIntRight(), 1),
|
0x7C => (Instruction::LogicalShiftIntRight(), 1),
|
||||||
0x7E => (Instruction::AndInt(), 1),
|
0x7E => (Instruction::AndInt(), 1),
|
||||||
|
@ -110,7 +114,10 @@ impl Bytecode {
|
||||||
|
|
||||||
0x86 => (Instruction::ConvertIntToFloat(), 1),
|
0x86 => (Instruction::ConvertIntToFloat(), 1),
|
||||||
0x88 => (Instruction::ConvertLongToInt(), 1),
|
0x88 => (Instruction::ConvertLongToInt(), 1),
|
||||||
|
0x89 => (Instruction::ConvertLongToFloat(), 1),
|
||||||
0x8B => (Instruction::ConvertFloatToInt(), 1),
|
0x8B => (Instruction::ConvertFloatToInt(), 1),
|
||||||
|
0x8D => (Instruction::ConvertFloatToDouble(), 1),
|
||||||
|
0x8F => (Instruction::ConvertDoubleToLong(), 1),
|
||||||
0x91 => (Instruction::ConvertIntToByte(), 1),
|
0x91 => (Instruction::ConvertIntToByte(), 1),
|
||||||
0x92 => (Instruction::ConvertIntToChar(), 1),
|
0x92 => (Instruction::ConvertIntToChar(), 1),
|
||||||
0x94 => (Instruction::CompareLong(), 1),
|
0x94 => (Instruction::CompareLong(), 1),
|
||||||
|
@ -361,6 +368,8 @@ pub enum Instruction {
|
||||||
DuplicateInsertDown() = 0x5A, // duplicate top stack value and insert two low
|
DuplicateInsertDown() = 0x5A, // duplicate top stack value and insert two low
|
||||||
|
|
||||||
AddInt() = 0x60, // int addition
|
AddInt() = 0x60, // int addition
|
||||||
|
AddLong() = 0x61, // long addition
|
||||||
|
AddDouble() = 0x63, // double addition
|
||||||
SubtractInt() = 0x64, // int subtraction
|
SubtractInt() = 0x64, // int subtraction
|
||||||
SubtractLong() = 0x65, // long subtraction
|
SubtractLong() = 0x65, // long subtraction
|
||||||
MultiplyInt() = 0x68, // int multiplication
|
MultiplyInt() = 0x68, // int multiplication
|
||||||
|
@ -368,10 +377,12 @@ pub enum Instruction {
|
||||||
MultiplyFloat() = 0x6A, // float multiplication
|
MultiplyFloat() = 0x6A, // float multiplication
|
||||||
DivideInt() = 0x6C, // integer division, round toward zero and more rules
|
DivideInt() = 0x6C, // integer division, round toward zero and more rules
|
||||||
DivideLong() = 0x6D, // long division
|
DivideLong() = 0x6D, // long division
|
||||||
|
DivideFloat() = 0x6E, // float division
|
||||||
|
|
||||||
NegateInt() = 0x74, // arithmetic negation
|
NegateInt() = 0x74, // arithmetic negation
|
||||||
NegateLong() = 0x75, // arithmetic negation
|
NegateLong() = 0x75, // arithmetic negation
|
||||||
ArithmeticShiftIntLeft() = 0x78, // shift int left, preserve sign
|
ArithmeticShiftIntLeft() = 0x78, // shift int left, preserve sign
|
||||||
|
ArithmeticShiftLongLeft() = 0x79, // shift long left, preserve sign
|
||||||
ArithmeticShiftIntRight() = 0x7A, // shift int right, preserve sign
|
ArithmeticShiftIntRight() = 0x7A, // shift int right, preserve sign
|
||||||
LogicalShiftIntRight() = 0x7C, // shift int right with zero extension
|
LogicalShiftIntRight() = 0x7C, // shift int right with zero extension
|
||||||
AndInt() = 0x7E, // bitwise and
|
AndInt() = 0x7E, // bitwise and
|
||||||
|
@ -383,7 +394,10 @@ pub enum Instruction {
|
||||||
|
|
||||||
ConvertIntToFloat() = 0x86, // change data type
|
ConvertIntToFloat() = 0x86, // change data type
|
||||||
ConvertLongToInt() = 0x88, // change data type
|
ConvertLongToInt() = 0x88, // change data type
|
||||||
|
ConvertLongToFloat() = 0x89, // change data type
|
||||||
ConvertFloatToInt() = 0x8B, // change data type
|
ConvertFloatToInt() = 0x8B, // change data type
|
||||||
|
ConvertFloatToDouble() = 0x8D, // change data type
|
||||||
|
ConvertDoubleToLong() = 0x8F, // change data type
|
||||||
ConvertIntToByte() = 0x91, // truncate int to 8 bits
|
ConvertIntToByte() = 0x91, // truncate int to 8 bits
|
||||||
ConvertIntToChar() = 0x92, // truncate int to 16 bits
|
ConvertIntToChar() = 0x92, // truncate int to 16 bits
|
||||||
CompareLong() = 0x94, // compare long
|
CompareLong() = 0x94, // compare long
|
||||||
|
|
|
@ -710,7 +710,7 @@ pub struct ObjectField {
|
||||||
pub value: FieldValue,
|
pub value: FieldValue,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub enum FieldValue {
|
pub enum FieldValue {
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
Byte(i8),
|
Byte(i8),
|
||||||
|
|
|
@ -74,14 +74,15 @@ impl <'i> Iterator for CompatibleTypesIterator<'i>{
|
||||||
|
|
||||||
Some(class_file.get_super_class_name().unwrap())
|
Some(class_file.get_super_class_name().unwrap())
|
||||||
} else {
|
} else {
|
||||||
None
|
let recursive_next = self.next();
|
||||||
|
recursive_next
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let interface_name = class_file.gather_class(class_file.interfaces[interface_index]).unwrap();
|
let interface_name = class_file.gather_class(class_file.interfaces[interface_index]).unwrap();
|
||||||
let interface_index = self.class_store.class_idx_from_name(interface_name).unwrap();
|
let interface_class_index = self.class_store.class_idx_from_name(interface_name).unwrap();
|
||||||
|
|
||||||
self.class_stack.push((class_index, interface_index + 1));
|
self.class_stack.push((class_index, interface_index + 1));
|
||||||
self.class_stack.push((interface_index, 0));
|
self.class_stack.push((interface_class_index, 0));
|
||||||
|
|
||||||
Some(interface_name)
|
Some(interface_name)
|
||||||
}
|
}
|
||||||
|
|
101
src/jvm.rs
101
src/jvm.rs
|
@ -157,7 +157,7 @@ impl JVM {
|
||||||
fn make_array_class(&mut self, element_class_ref: ObjectReference, element_descriptor: AbstractTypeDescription) {
|
fn make_array_class(&mut self, element_class_ref: ObjectReference, element_descriptor: AbstractTypeDescription) {
|
||||||
let class_class_index = self.class_store.class_idx_from_name(&"java/lang/Class".to_string()).unwrap();
|
let class_class_index = self.class_store.class_idx_from_name(&"java/lang/Class".to_string()).unwrap();
|
||||||
|
|
||||||
let array_class_object = self.heap_area.make_object(&self.class_store, 6);
|
let array_class_object = self.heap_area.make_object(&self.class_store, class_class_index);
|
||||||
let array_class_data_object = self.heap_area.make_object(&self.class_store, 1);
|
let array_class_data_object = self.heap_area.make_object(&self.class_store, 1);
|
||||||
let array_type_description = AbstractTypeDescription {
|
let array_type_description = AbstractTypeDescription {
|
||||||
array_level: 1 + element_descriptor.array_level,
|
array_level: 1 + element_descriptor.array_level,
|
||||||
|
@ -341,12 +341,12 @@ impl JVM {
|
||||||
|
|
||||||
self.class_store.add_class(entry_class, true)?; // 0
|
self.class_store.add_class(entry_class, true)?; // 0
|
||||||
self.class_store.add_class(JVM::class_native_class_data(), true)?; // 1
|
self.class_store.add_class(JVM::class_native_class_data(), true)?; // 1
|
||||||
self.load_class(&"java/lang/Object".to_string())?; // 2
|
self.load_class_hierarchy(&"java/lang/Object".to_string())?; // 2
|
||||||
self.load_class(&"java/lang/Number".to_string())?; // 3
|
self.load_class_hierarchy(&"java/lang/Number".to_string())?; // 3
|
||||||
let byte_class_index = self.load_class(&"java/lang/Byte".to_string())?; // 4
|
let byte_class_index = self.load_class_hierarchy(&"java/lang/Byte".to_string())?; // 4
|
||||||
let string_class_index = self.load_class(&"java/lang/String".to_string())?; // 5
|
let string_class_index = self.load_class_hierarchy(&"java/lang/String".to_string())?; // 5
|
||||||
let class_class_index = self.load_class(&"java/lang/Class".to_string())?; // 6
|
let class_class_index = self.load_class_hierarchy(&"java/lang/Class".to_string())?; // 6
|
||||||
let system_class_index = self.load_class(&"java/lang/System".to_string())?; // 7
|
let system_class_index = self.load_class_hierarchy(&"java/lang/System".to_string())?; // 7
|
||||||
|
|
||||||
self.make_class_class("Ljava/lang/Byte;");
|
self.make_class_class("Ljava/lang/Byte;");
|
||||||
self.make_class_class("Ljava/lang/String;");
|
self.make_class_class("Ljava/lang/String;");
|
||||||
|
@ -466,15 +466,21 @@ impl JVM {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_class_hierarchy(&mut self, name: &String) -> Result<(), Error> {
|
fn load_class_hierarchy(&mut self, name: &String) -> Result<usize, Error> {
|
||||||
let mut waiting_queue = VecDeque::new();
|
let mut waiting_queue = VecDeque::new();
|
||||||
waiting_queue.push_back(name.clone());
|
waiting_queue.push_back(name.clone());
|
||||||
|
let mut return_class_index = usize::MAX;
|
||||||
|
|
||||||
while waiting_queue.len() != 0 {
|
while waiting_queue.len() != 0 {
|
||||||
let class_name = waiting_queue.pop_front().unwrap();
|
let class_name = waiting_queue.pop_front().unwrap();
|
||||||
|
|
||||||
if ! self.class_store.have_class(&class_name) {
|
if ! self.class_store.have_class(&class_name) {
|
||||||
let new_class_index = self.load_class(&class_name)?;
|
let new_class_index = self.load_class(&class_name)?;
|
||||||
|
|
||||||
|
if class_name == *name {
|
||||||
|
return_class_index = new_class_index;
|
||||||
|
}
|
||||||
|
|
||||||
let (file, _) = self.class_store.get_class(&class_name).unwrap();
|
let (file, _) = self.class_store.get_class(&class_name).unwrap();
|
||||||
if file.has_super_class() {
|
if file.has_super_class() {
|
||||||
waiting_queue.push_back(file.get_super_class_name()?.to_string());
|
waiting_queue.push_back(file.get_super_class_name()?.to_string());
|
||||||
|
@ -488,7 +494,7 @@ impl JVM {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(return_class_index)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_class_hierarchy(&mut self, name: &String) -> Result<(), Error> {
|
fn init_class_hierarchy(&mut self, name: &String) -> Result<(), Error> {
|
||||||
|
@ -678,6 +684,13 @@ impl JVM {
|
||||||
|
|
||||||
match instruction {
|
match instruction {
|
||||||
|
|
||||||
|
Instruction::AddDouble() => {
|
||||||
|
let value_0 = wrap_stackframe_error(class, method, frame.operand_stack.pop_double(0))?;
|
||||||
|
let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_double(0))?;
|
||||||
|
|
||||||
|
wrap_stackframe_error(class, method, frame.operand_stack.push_double(value_0 + value_1))?;
|
||||||
|
}
|
||||||
|
|
||||||
Instruction::AddInt() => {
|
Instruction::AddInt() => {
|
||||||
let value_0 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
|
let value_0 = 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_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
|
||||||
|
@ -685,6 +698,13 @@ impl JVM {
|
||||||
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(value_0 + value_1)))?;
|
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(value_0 + value_1)))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Instruction::AddLong() => {
|
||||||
|
let value_0 = 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_0 + value_1))?;
|
||||||
|
}
|
||||||
|
|
||||||
Instruction::ArithmeticShiftIntLeft() => {
|
Instruction::ArithmeticShiftIntLeft() => {
|
||||||
let shift = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))? as u8 & 0b00011111;
|
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 int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
|
||||||
|
@ -700,6 +720,14 @@ impl JVM {
|
||||||
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(int >> shift)))?;
|
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(int >> shift)))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Instruction::ArithmeticShiftLongLeft() => {
|
||||||
|
let shift = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))? as u8 % 64;
|
||||||
|
let long = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
|
||||||
|
|
||||||
|
// rust does arithmetic shift on signed values
|
||||||
|
wrap_stackframe_error(class, method, frame.operand_stack.push_long(long << shift))?;
|
||||||
|
}
|
||||||
|
|
||||||
Instruction::ArrayLength() => {
|
Instruction::ArrayLength() => {
|
||||||
let array_reference = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?;
|
let array_reference = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?;
|
||||||
|
|
||||||
|
@ -884,6 +912,19 @@ impl JVM {
|
||||||
Instruction::CheckCast(classref_index) => {
|
Instruction::CheckCast(classref_index) => {
|
||||||
// TODO: Class loading checks
|
// TODO: Class loading checks
|
||||||
let class_name = class.gather_class(classref_index)?;
|
let class_name = class.gather_class(classref_index)?;
|
||||||
|
if ! class_name.starts_with("[") { // don't load array classes
|
||||||
|
if ! self.class_store.have_class(class_name) {
|
||||||
|
// rewind the bytecode offset, I'll need to execute this instruction again
|
||||||
|
frame.instruction_pointer -= offset as u32;
|
||||||
|
return Ok(JVMCallbackOperation::LoadClass(class_name.to_string()));
|
||||||
|
}
|
||||||
|
if ! self.class_store.was_init(class_name).unwrap() {
|
||||||
|
// rewind the bytecode offset, I'll need to execute this instruction again
|
||||||
|
frame.instruction_pointer -= offset as u32;
|
||||||
|
return Ok(JVMCallbackOperation::InitClass(class_name.to_string()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let object = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?;
|
let object = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?;
|
||||||
if object != ObjectReference::NULL {
|
if object != ObjectReference::NULL {
|
||||||
let native_class_name = self.heap_area.object_area.get_reference_native_class_name(object, &self.class_store);
|
let native_class_name = self.heap_area.object_area.get_reference_native_class_name(object, &self.class_store);
|
||||||
|
@ -957,6 +998,13 @@ impl JVM {
|
||||||
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(comparison_result)))?;
|
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(comparison_result)))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Instruction::ConvertFloatToDouble() => {
|
||||||
|
let float = wrap_stackframe_error(class, method, frame.operand_stack.pop_float(0))?;
|
||||||
|
let double = float as f64;
|
||||||
|
|
||||||
|
wrap_stackframe_error(class, method, frame.operand_stack.push_double(double))?;
|
||||||
|
}
|
||||||
|
|
||||||
Instruction::ConvertFloatToInt() => {
|
Instruction::ConvertFloatToInt() => {
|
||||||
let float = wrap_stackframe_error(class, method, frame.operand_stack.pop_float(0))?;
|
let float = wrap_stackframe_error(class, method, frame.operand_stack.pop_float(0))?;
|
||||||
let int_value = match float {
|
let int_value = match float {
|
||||||
|
@ -965,7 +1013,18 @@ impl JVM {
|
||||||
v @ _ => if v.is_nan() { 0 } else { v as i32 } ,
|
v @ _ => if v.is_nan() { 0 } else { v as i32 } ,
|
||||||
};
|
};
|
||||||
|
|
||||||
frame.operand_stack.push(StackValue::Int(int_value)).unwrap();
|
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(int_value)))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Instruction::ConvertDoubleToLong() => {
|
||||||
|
let double = wrap_stackframe_error(class, method, frame.operand_stack.pop_double(0))?;
|
||||||
|
let long = match double {
|
||||||
|
f64::INFINITY => i64::MAX,
|
||||||
|
f64::NEG_INFINITY => i64::MIN,
|
||||||
|
v @ _ => if v.is_nan() { 0 } else { v as i64 }
|
||||||
|
};
|
||||||
|
|
||||||
|
wrap_stackframe_error(class, method, frame.operand_stack.push_long(long))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction::ConvertIntToByte() => {
|
Instruction::ConvertIntToByte() => {
|
||||||
|
@ -1003,6 +1062,21 @@ impl JVM {
|
||||||
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(int_value)))?;
|
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(int_value)))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Instruction::ConvertLongToFloat() => {
|
||||||
|
let long_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
|
||||||
|
let float_value = long_value as f32;
|
||||||
|
|
||||||
|
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Float(float_value)))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Instruction::DivideFloat() => {
|
||||||
|
// TODO: Obey all the rules
|
||||||
|
let quotient = wrap_stackframe_error(class, method, frame.operand_stack.pop_float(0))?;
|
||||||
|
let divident = wrap_stackframe_error(class, method, frame.operand_stack.pop_float(0))?;
|
||||||
|
|
||||||
|
frame.operand_stack.push(StackValue::Float(divident / quotient)).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
Instruction::DivideInt() => {
|
Instruction::DivideInt() => {
|
||||||
// TODO: Obey all the rules
|
// TODO: Obey all the rules
|
||||||
let quotient = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
|
let quotient = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
|
||||||
|
@ -1051,10 +1125,10 @@ impl JVM {
|
||||||
|
|
||||||
// TODO: Are there any methods callable on arrays?
|
// TODO: Are there any methods callable on arrays?
|
||||||
let this_object_class_index = self.heap_area.object_area.get_object_class_index(this_object);
|
let this_object_class_index = self.heap_area.object_area.get_object_class_index(this_object);
|
||||||
let this_object_class_name = self.class_store.class_name_from_index(this_object_class_index).unwrap().to_string();
|
let this_object_class_name = self.class_store.class_name_from_index(this_object_class_index).unwrap();
|
||||||
let this_object_descriptor = AbstractTypeDescription {
|
let this_object_descriptor = AbstractTypeDescription {
|
||||||
array_level: 0,
|
array_level: 0,
|
||||||
kind: AbstractTypeKind::Classname(this_object_class_name.clone())
|
kind: AbstractTypeKind::Classname(this_object_class_name.to_string())
|
||||||
};
|
};
|
||||||
let object_descriptor = AbstractTypeDescription {
|
let object_descriptor = AbstractTypeDescription {
|
||||||
array_level: 0,
|
array_level: 0,
|
||||||
|
@ -1815,6 +1889,9 @@ impl JVM {
|
||||||
wrap_stackframe_error(class, method, frame.operand_stack.pop_computational_1(0))?;
|
wrap_stackframe_error(class, method, frame.operand_stack.pop_computational_1(0))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Instruction::PushConstDouble1() => {
|
||||||
|
wrap_stackframe_error(class, method, frame.operand_stack.push_double(1.0))?;
|
||||||
|
}
|
||||||
Instruction::PushConstFloat0() => {
|
Instruction::PushConstFloat0() => {
|
||||||
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Float(0.0)))?;
|
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Float(0.0)))?;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -268,14 +268,14 @@ impl OperandStack {
|
||||||
|
|
||||||
pub fn pop_double(&mut self, index: usize) -> Result<f64, Error> {
|
pub fn pop_double(&mut self, index: usize) -> Result<f64, Error> {
|
||||||
let absolute_index = self.depth as usize - 1 - index;
|
let absolute_index = self.depth as usize - 1 - index;
|
||||||
let higher_bytes = self.stack[absolute_index];
|
let double1 = self.stack[absolute_index];
|
||||||
let lower_bytes = self.stack[absolute_index + 1];
|
let double0 = self.stack[absolute_index - 1];
|
||||||
self.depth -= 2;
|
self.depth -= 2;
|
||||||
match (higher_bytes, lower_bytes) {
|
match (double0, double1) {
|
||||||
(StackValue::Double0(double), StackValue::Double1()) => {
|
(StackValue::Double0(double), StackValue::Double1()) => {
|
||||||
Ok(double)
|
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))))
|
_ => Err(Error::LocalError(format!("Mismatched types at index {} of the function operand stack, expected (Double0, Double1) but found '{:?}'", index, (double1, double0))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue