stdout und stderr encoding

This commit is contained in:
VegOwOtenks 2024-10-22 13:01:20 +02:00
parent 022bfe9ee6
commit b4c33a0d9b
4 changed files with 116 additions and 6 deletions

View file

@ -35,6 +35,7 @@ impl Bytecode {
0x14 => (Instruction::LoadConstant64((self.bytes[offset+1] as u16) << 8 | self.bytes[offset+2] as u16), 3), 0x14 => (Instruction::LoadConstant64((self.bytes[offset+1] as u16) << 8 | self.bytes[offset+2] as u16), 3),
0x15 => (Instruction::LoadLocalInt(self.bytes[offset+1]), 2), 0x15 => (Instruction::LoadLocalInt(self.bytes[offset+1]), 2),
0x17 => (Instruction::LoadLocalFloat(self.bytes[offset+1]), 2),
0x19 => (Instruction::LoadLocalReference(self.bytes[offset+1]), 2), 0x19 => (Instruction::LoadLocalReference(self.bytes[offset+1]), 2),
0x1A => (Instruction::LoadLocalInt0(), 1), 0x1A => (Instruction::LoadLocalInt0(), 1),
0x1B => (Instruction::LoadLocalInt1(), 1), 0x1B => (Instruction::LoadLocalInt1(), 1),
@ -56,6 +57,7 @@ impl Bytecode {
0x32 => (Instruction::ArrayElement(), 1), 0x32 => (Instruction::ArrayElement(), 1),
0x33 => (Instruction::LoadFromBArray(), 1), 0x33 => (Instruction::LoadFromBArray(), 1),
0x36 => (Instruction::StoreLocalInt(self.bytes[offset+1]), 2), 0x36 => (Instruction::StoreLocalInt(self.bytes[offset+1]), 2),
0x38 => (Instruction::StoreLocalFloat(self.bytes[offset+1]), 2),
0x3A => (Instruction::StoreLocalReference(self.bytes[offset+1]), 2), 0x3A => (Instruction::StoreLocalReference(self.bytes[offset+1]), 2),
0x3B => (Instruction::StoreLocalInt0(), 1), 0x3B => (Instruction::StoreLocalInt0(), 1),
0x3C => (Instruction::StoreLocalInt1(), 1), 0x3C => (Instruction::StoreLocalInt1(), 1),
@ -72,10 +74,12 @@ impl Bytecode {
0x57 => (Instruction::Pop(), 1), 0x57 => (Instruction::Pop(), 1),
0x59 => (Instruction::Duplicate(), 1), 0x59 => (Instruction::Duplicate(), 1),
0x5A => (Instruction::DuplicateInsertDown(), 1),
0x60 => (Instruction::AddInt(), 1), 0x60 => (Instruction::AddInt(), 1),
0x64 => (Instruction::SubtractInt(), 1), 0x64 => (Instruction::SubtractInt(), 1),
0x68 => (Instruction::MultiplyInt(), 1), 0x68 => (Instruction::MultiplyInt(), 1),
0x6A => (Instruction::MultiplyFloat(), 1),
0x6C => (Instruction::DivideInt(), 1), 0x6C => (Instruction::DivideInt(), 1),
0x6D => (Instruction::DivideLong(), 1), 0x6D => (Instruction::DivideLong(), 1),
@ -88,6 +92,8 @@ impl Bytecode {
0x82 => (Instruction::XorInt(), 1), 0x82 => (Instruction::XorInt(), 1),
0x84 => (Instruction::IncrementLocalInt(self.bytes[offset+1], i8::from_be_bytes([self.bytes[offset+2]])), 3), 0x84 => (Instruction::IncrementLocalInt(self.bytes[offset+1], i8::from_be_bytes([self.bytes[offset+2]])), 3),
0x86 => (Instruction::ConvertIntToFloat(), 1),
0x8B => (Instruction::ConvertFloatToInt(), 1),
0x92 => (Instruction::ConvertIntToChar(), 1), 0x92 => (Instruction::ConvertIntToChar(), 1),
0x95 => (Instruction::CompareFloatL(), 1), 0x95 => (Instruction::CompareFloatL(), 1),
0x96 => (Instruction::CompareFloatG(), 1), 0x96 => (Instruction::CompareFloatG(), 1),
@ -209,7 +215,7 @@ impl Bytecode {
0xB6 => (Instruction::InvokeVirtual((self.bytes[offset+1] as u16) << 8 | self.bytes[offset+2] as u16), 3), 0xB6 => (Instruction::InvokeVirtual((self.bytes[offset+1] as u16) << 8 | self.bytes[offset+2] as u16), 3),
0xB7 => (Instruction::InvokeSpecial((self.bytes[offset+1] as u16) << 8 | self.bytes[offset+2] as u16), 3), 0xB7 => (Instruction::InvokeSpecial((self.bytes[offset+1] as u16) << 8 | self.bytes[offset+2] as u16), 3),
0xB8 => (Instruction::InvokeStatic((self.bytes[offset+1] as u16) << 8 | self.bytes[offset+2] as u16), 3), 0xB8 => (Instruction::InvokeStatic((self.bytes[offset+1] as u16) << 8 | self.bytes[offset+2] as u16), 3),
0xB9 => (Instruction::InvokeInterface((self.bytes[offset+1] as u16) << 8 | self.bytes[offset+2] as u16), 3), 0xB9 => (Instruction::InvokeInterface((self.bytes[offset+1] as u16) << 8 | self.bytes[offset+2] as u16), 5), // TODO: Figure out the additional arguments
0xBA => (Instruction::InvokeDynamic((self.bytes[offset+1] as u16) << 8 | self.bytes[offset+2] as u16, (self.bytes[offset+3] as u16) << 8 | self.bytes[offset+4] as u16), 5), 0xBA => (Instruction::InvokeDynamic((self.bytes[offset+1] as u16) << 8 | self.bytes[offset+2] as u16, (self.bytes[offset+3] as u16) << 8 | self.bytes[offset+4] as u16), 5),
0xBB => (Instruction::NewObject((self.bytes[offset+1] as u16) << 8 | self.bytes[offset+2] as u16), 3), 0xBB => (Instruction::NewObject((self.bytes[offset+1] as u16) << 8 | self.bytes[offset+2] as u16), 3),
0xBC => (Instruction::NewPrimitiveArray(self.bytes[offset+1]), 2), 0xBC => (Instruction::NewPrimitiveArray(self.bytes[offset+1]), 2),
@ -282,6 +288,7 @@ pub enum Instruction {
// double or long or whatever // double or long or whatever
LoadConstant64(u16) = 0x14, // Push Long or Double from constant pool LoadConstant64(u16) = 0x14, // Push Long or Double from constant pool
LoadLocalInt(u8) = 0x15, // Load int from indexed local variable LoadLocalInt(u8) = 0x15, // Load int from indexed local variable
LoadLocalFloat(u8) = 0x17, // Load int from indexed local variable
LoadLocalReference(u8) = 0x19, // Load reference from indexed local variable LoadLocalReference(u8) = 0x19, // Load reference from indexed local variable
LoadLocalInt0() = 0x1A, // Load int from local variable LoadLocalInt0() = 0x1A, // Load int from local variable
LoadLocalInt1() = 0x1B, // Load int from local variable LoadLocalInt1() = 0x1B, // Load int from local variable
@ -304,6 +311,7 @@ pub enum Instruction {
ArrayElement() = 0x32, // load element from array ArrayElement() = 0x32, // load element from array
LoadFromBArray() = 0x33, // store into byte array LoadFromBArray() = 0x33, // store into byte array
StoreLocalInt(u8) = 0x36, // store into indexed local variable StoreLocalInt(u8) = 0x36, // store into indexed local variable
StoreLocalFloat(u8) = 0x38, // store into indexed local variable
StoreLocalReference(u8) = 0x3A, // store into indexed local variable StoreLocalReference(u8) = 0x3A, // store into indexed local variable
StoreLocalInt0() = 0x3B, // store int into local variable StoreLocalInt0() = 0x3B, // store int into local variable
StoreLocalInt1() = 0x3C, // store int into local variable StoreLocalInt1() = 0x3C, // store int into local variable
@ -319,10 +327,12 @@ pub enum Instruction {
StoreIntoCArray() = 0x55, // store value into char array StoreIntoCArray() = 0x55, // store value into char array
Pop() = 0x57, // Pop top stack value Pop() = 0x57, // Pop top stack value
Duplicate() = 0x59, // duplicate top stack value Duplicate() = 0x59, // duplicate top stack value
DuplicateInsertDown() = 0x5A, // duplicate top stack value and insert two low
AddInt() = 0x60, // int addition AddInt() = 0x60, // int addition
SubtractInt() = 0x64, // int subtraction SubtractInt() = 0x64, // int subtraction
MultiplyInt() = 0x68, // int multiplication MultiplyInt() = 0x68, // int 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
@ -335,6 +345,8 @@ pub enum Instruction {
XorInt() = 0x82, // value, value => xor XorInt() = 0x82, // value, value => xor
IncrementLocalInt(u8, i8) = 0x84, // increment local variable by constant i8 IncrementLocalInt(u8, i8) = 0x84, // increment local variable by constant i8
ConvertIntToFloat() = 0x86, // change data type
ConvertFloatToInt() = 0x8B, // change data type
ConvertIntToChar() = 0x92, // truncate int to 16 bits ConvertIntToChar() = 0x92, // truncate int to 16 bits
CompareFloatL() = 0x95, // compare float, push -1 if one is NaN CompareFloatL() = 0x95, // compare float, push -1 if one is NaN
CompareFloatG() = 0x96, // compare float, push 1 if one is NaN CompareFloatG() = 0x96, // compare float, push 1 if one is NaN

View file

@ -667,7 +667,9 @@ impl JVM {
let (instruction, offset) = bytecode.next_instruction(frame.instruction_pointer as usize); let (instruction, offset) = bytecode.next_instruction(frame.instruction_pointer as usize);
frame.instruction_pointer += offset as u32; frame.instruction_pointer += offset as u32;
println!("{}{:25}.{:15}:{:<10}{instruction:?}", " ".repeat(frame_index), class.get_classname().unwrap(), method.name, frame.instruction_pointer); //println!("{} locals: {:?}", " ".repeat(frame_index), frame.locals);
println!("{} stack: {:?}", " ".repeat(frame_index), frame.operand_stack);
println!("{}{:25}.{:15}:{:<10}{instruction:?}\n", " ".repeat(frame_index), class.get_classname().unwrap(), method.name, frame.instruction_pointer);
match instruction { match instruction {
@ -835,6 +837,16 @@ impl JVM {
} }
} }
Instruction::BranchReferenceEquality(branch_offset) => {
let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?;
let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?;
if value_1 == value_2 {
frame.instruction_pointer -= offset as u32;
frame.instruction_pointer = if branch_offset < 0 { frame.instruction_pointer - branch_offset.abs() as u32} else { frame.instruction_pointer + branch_offset.abs() as u32};
}
}
Instruction::BranchReferenceInequality(branch_offset) => { Instruction::BranchReferenceInequality(branch_offset) => {
let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?; let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?;
let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?; let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?;
@ -914,6 +926,17 @@ 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::ConvertFloatToInt() => {
let float = wrap_stackframe_error(class, method, frame.operand_stack.pop_float(0))?;
let int_value = match float {
f32::INFINITY => i32::MAX,
f32::NEG_INFINITY => i32::MIN,
v @ _ => if v.is_nan() { 0 } else { v as i32 } ,
};
frame.operand_stack.push(StackValue::Int(int_value)).unwrap();
}
Instruction::ConvertIntToChar() => { Instruction::ConvertIntToChar() => {
let int_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?; let int_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
let char_value = int_value & 0x0000FFFF; let char_value = int_value & 0x0000FFFF;
@ -921,6 +944,13 @@ impl JVM {
frame.operand_stack.push(StackValue::Int(char_value)).unwrap(); frame.operand_stack.push(StackValue::Int(char_value)).unwrap();
} }
Instruction::ConvertIntToFloat() => {
let int_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
let float_value = int_value as f32;
frame.operand_stack.push(StackValue::Float(float_value)).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))?;
@ -935,6 +965,15 @@ impl JVM {
wrap_stackframe_error(class, method, frame.operand_stack.push(popped_value))?; wrap_stackframe_error(class, method, frame.operand_stack.push(popped_value))?;
} }
Instruction::DuplicateInsertDown() => {
let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_computational_1(0))?;
let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_computational_1(0))?;
wrap_stackframe_error(class, method, frame.operand_stack.push(value_1))?;
wrap_stackframe_error(class, method, frame.operand_stack.push(value_2))?;
wrap_stackframe_error(class, method, frame.operand_stack.push(value_1))?;
}
Instruction::EnterMonitor() => { Instruction::EnterMonitor() => {
// TODO: Revisit this when doing multi-threading // TODO: Revisit this when doing multi-threading
let _monitored_object = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?; let _monitored_object = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?;
@ -1410,6 +1449,9 @@ impl JVM {
} }
} }
Instruction::LoadLocalFloat(index) => {
load_local_float(class, method, frame, index as usize)?;
}
Instruction::LoadLocalFloat0() => { Instruction::LoadLocalFloat0() => {
load_local_float(class, method, frame, 0)?; load_local_float(class, method, frame, 0)?;
} }
@ -1476,10 +1518,28 @@ impl JVM {
frame.instruction_pointer = if jump_offset < 0 { frame.instruction_pointer - jump_offset.abs() as u32} else { frame.instruction_pointer + jump_offset.abs() as u32}; frame.instruction_pointer = if jump_offset < 0 { frame.instruction_pointer - jump_offset.abs() as u32} else { frame.instruction_pointer + jump_offset.abs() as u32};
} }
Instruction::MultiplyFloat() => {
let factor_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_float(0))?;
let factor_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_float(0))?;
let result = factor_1 * factor_2;
let java_result = result;
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Float(java_result)))?;
}
Instruction::MultiplyInt() => { Instruction::MultiplyInt() => {
let factor_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?; let factor_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
let factor_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?; let factor_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(factor_1 * factor_2)))?;
let (result, overflowed) = i32::overflowing_mul(factor_1, factor_2);
let java_result = match (overflowed, factor_1, factor_2) {
(true, 0..=i32::MAX, 0..=i32::MAX) => if result > 0 { -result } else { result },
(true, 0..=i32::MAX, i32::MIN..0) | (true, i32::MIN..0, 0..=i32::MAX) => if result < 0 { -result } else { result },
(true, i32::MIN..0, i32::MIN..0) => if result > 0 { - result } else { result },
(false, _, _) => result,
};
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(java_result)))?;
} }
Instruction::NewArray(component_class_index) => { Instruction::NewArray(component_class_index) => {
@ -1799,6 +1859,12 @@ impl JVM {
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(value_1 - value_2)))?; wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(value_1 - value_2)))?;
} }
Instruction::StoreLocalFloat(index) => {
let float = wrap_stackframe_error(class, method, frame.operand_stack.pop_float(0))?;
wrap_stackframe_error(class, method, frame.store_local(index as u16, StackValue::Float(float)))?;
}
Instruction::StoreLocalInt(index) => { Instruction::StoreLocalInt(index) => {
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))?;
@ -2038,7 +2104,7 @@ fn fill_arguments(class: &JavaClassFile, method: &MethodInfo, arguments: &mut Ve
}, },
AbstractTypeKind::Boolean() => { AbstractTypeKind::Boolean() => {
arguments.push_front( arguments.push_front(
StackValue::Boolean( StackValue::Int(
wrap_stackframe_error( wrap_stackframe_error(
class, class,
method, method,

View file

@ -361,6 +361,34 @@ impl JdkInternalUtilSystemPropsRaw {
}; };
let array_reference = jvm.heap_area.make_empty_array(&jvm.class_store, AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/String".into()) }, array_length); let array_reference = jvm.heap_area.make_empty_array(&jvm.class_store, AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/String".into()) }, array_length);
let utf8_string_ref = jvm.heap_area.make_handmade_string(&String::from("UTF-8"), &jvm.class_store);
{
let stdout_encoding_ndx_result = jvm.heap_area.static_area.get(
&String::from("jdk/internal/util/SystemProps$Raw"),
&String::from("_stdout_encoding_NDX"),
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Int() }
);
let stdout_encoding_ndx = match stdout_encoding_ndx_result {
Ok(FieldValue::Int(i)) => i as usize,
_ => unreachable!(),
};
jvm.heap_area.object_area.set_array_element(array_reference, stdout_encoding_ndx, FieldValue::Reference(utf8_string_ref));
}
{
let stderr_encoding_ndx_result = jvm.heap_area.static_area.get(
&String::from("jdk/internal/util/SystemProps$Raw"),
&String::from("_stderr_encoding_NDX"),
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Int() }
);
let stderr_encoding_ndx = match stderr_encoding_ndx_result {
Ok(FieldValue::Int(i)) => i as usize,
_ => unreachable!(),
};
jvm.heap_area.object_area.set_array_element(array_reference, stderr_encoding_ndx, FieldValue::Reference(utf8_string_ref));
}
Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(array_reference))) Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(array_reference)))
} }

View file

@ -68,6 +68,10 @@ impl OperandStack {
self.push(StackValue::Int(i)) self.push(StackValue::Int(i))
} }
FieldValue::Float(i) => {
self.push(StackValue::Float(i))
}
_ => { _ => {
println!("{value:?}"); println!("{value:?}");
todo!(); todo!();
@ -114,12 +118,12 @@ impl OperandStack {
} }
} }
pub fn pop_boolean(&mut self, index: usize) -> Result<bool, Error> { pub fn pop_boolean(&mut self, index: usize) -> Result<i32, Error> {
let absolute_index = self.depth as usize - 1 - index; let absolute_index = self.depth as usize - 1 - index;
let value = self.stack[absolute_index]; let value = self.stack[absolute_index];
self.depth -= 1; self.depth -= 1;
match value { match value {
StackValue::Boolean(b) => Ok(b), StackValue::Int(b) => Ok(b & 0x1),
_ => Err(Error::LocalError(format!("Mismatched type at index {} of the function operand stack, expected Boolean but found '{:?}'", index, value))) _ => Err(Error::LocalError(format!("Mismatched type at index {} of the function operand stack, expected Boolean but found '{:?}'", index, value)))
} }
} }