stdout und stderr encoding
This commit is contained in:
parent
022bfe9ee6
commit
b4c33a0d9b
4 changed files with 116 additions and 6 deletions
|
@ -35,6 +35,7 @@ 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),
|
||||
0x17 => (Instruction::LoadLocalFloat(self.bytes[offset+1]), 2),
|
||||
0x19 => (Instruction::LoadLocalReference(self.bytes[offset+1]), 2),
|
||||
0x1A => (Instruction::LoadLocalInt0(), 1),
|
||||
0x1B => (Instruction::LoadLocalInt1(), 1),
|
||||
|
@ -56,6 +57,7 @@ impl Bytecode {
|
|||
0x32 => (Instruction::ArrayElement(), 1),
|
||||
0x33 => (Instruction::LoadFromBArray(), 1),
|
||||
0x36 => (Instruction::StoreLocalInt(self.bytes[offset+1]), 2),
|
||||
0x38 => (Instruction::StoreLocalFloat(self.bytes[offset+1]), 2),
|
||||
0x3A => (Instruction::StoreLocalReference(self.bytes[offset+1]), 2),
|
||||
0x3B => (Instruction::StoreLocalInt0(), 1),
|
||||
0x3C => (Instruction::StoreLocalInt1(), 1),
|
||||
|
@ -72,10 +74,12 @@ impl Bytecode {
|
|||
|
||||
0x57 => (Instruction::Pop(), 1),
|
||||
0x59 => (Instruction::Duplicate(), 1),
|
||||
0x5A => (Instruction::DuplicateInsertDown(), 1),
|
||||
|
||||
0x60 => (Instruction::AddInt(), 1),
|
||||
0x64 => (Instruction::SubtractInt(), 1),
|
||||
0x68 => (Instruction::MultiplyInt(), 1),
|
||||
0x6A => (Instruction::MultiplyFloat(), 1),
|
||||
0x6C => (Instruction::DivideInt(), 1),
|
||||
0x6D => (Instruction::DivideLong(), 1),
|
||||
|
||||
|
@ -88,6 +92,8 @@ impl Bytecode {
|
|||
0x82 => (Instruction::XorInt(), 1),
|
||||
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),
|
||||
0x95 => (Instruction::CompareFloatL(), 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),
|
||||
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),
|
||||
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),
|
||||
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),
|
||||
|
@ -282,6 +288,7 @@ 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
|
||||
LoadLocalReference(u8) = 0x19, // Load reference from indexed local variable
|
||||
LoadLocalInt0() = 0x1A, // 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
|
||||
LoadFromBArray() = 0x33, // store into byte array
|
||||
StoreLocalInt(u8) = 0x36, // store into indexed local variable
|
||||
StoreLocalFloat(u8) = 0x38, // store into indexed local variable
|
||||
StoreLocalReference(u8) = 0x3A, // store into indexed local variable
|
||||
StoreLocalInt0() = 0x3B, // 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
|
||||
Pop() = 0x57, // Pop top stack value
|
||||
Duplicate() = 0x59, // duplicate top stack value
|
||||
DuplicateInsertDown() = 0x5A, // duplicate top stack value and insert two low
|
||||
|
||||
AddInt() = 0x60, // int addition
|
||||
SubtractInt() = 0x64, // int subtraction
|
||||
MultiplyInt() = 0x68, // int multiplication
|
||||
MultiplyFloat() = 0x6A, // float multiplication
|
||||
DivideInt() = 0x6C, // integer division, round toward zero and more rules
|
||||
DivideLong() = 0x6D, // long division
|
||||
|
||||
|
@ -335,6 +345,8 @@ pub enum Instruction {
|
|||
XorInt() = 0x82, // value, value => xor
|
||||
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
|
||||
CompareFloatL() = 0x95, // compare float, push -1 if one is NaN
|
||||
CompareFloatG() = 0x96, // compare float, push 1 if one is NaN
|
||||
|
|
72
src/jvm.rs
72
src/jvm.rs
|
@ -667,7 +667,9 @@ impl JVM {
|
|||
let (instruction, offset) = bytecode.next_instruction(frame.instruction_pointer as usize);
|
||||
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 {
|
||||
|
||||
|
@ -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) => {
|
||||
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))?;
|
||||
|
@ -914,6 +926,17 @@ impl JVM {
|
|||
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() => {
|
||||
let int_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
|
||||
let char_value = int_value & 0x0000FFFF;
|
||||
|
@ -921,6 +944,13 @@ impl JVM {
|
|||
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() => {
|
||||
// TODO: Obey all the rules
|
||||
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))?;
|
||||
}
|
||||
|
||||
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() => {
|
||||
// TODO: Revisit this when doing multi-threading
|
||||
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() => {
|
||||
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};
|
||||
}
|
||||
|
||||
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() => {
|
||||
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))?;
|
||||
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) => {
|
||||
|
@ -1799,6 +1859,12 @@ impl JVM {
|
|||
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) => {
|
||||
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() => {
|
||||
arguments.push_front(
|
||||
StackValue::Boolean(
|
||||
StackValue::Int(
|
||||
wrap_stackframe_error(
|
||||
class,
|
||||
method,
|
||||
|
|
|
@ -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 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)))
|
||||
}
|
||||
|
|
|
@ -68,6 +68,10 @@ impl OperandStack {
|
|||
self.push(StackValue::Int(i))
|
||||
}
|
||||
|
||||
FieldValue::Float(i) => {
|
||||
self.push(StackValue::Float(i))
|
||||
}
|
||||
|
||||
_ => {
|
||||
println!("{value:?}");
|
||||
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 value = self.stack[absolute_index];
|
||||
self.depth -= 1;
|
||||
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)))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue