Implemented VM.initalize and LoadConstant64
This commit is contained in:
parent
b4c33a0d9b
commit
43ceaa95bb
3 changed files with 204 additions and 13 deletions
39
src/jvm.rs
39
src/jvm.rs
|
@ -1045,11 +1045,26 @@ impl JVM {
|
|||
}
|
||||
|
||||
Instruction::InstanceOf(classref_index) => {
|
||||
// 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 object = wrap_stackframe_error(class, method, frame.operand_stack.peek_reference(0))?;
|
||||
let native_class_name = self.heap_area.object_area.get_reference_native_class_name(object, &self.class_store);
|
||||
|
||||
if class_name.starts_with("[") {
|
||||
// TODO: Create array class on demand
|
||||
} else {
|
||||
if ! self.class_store.have_class(class_name) {
|
||||
frame.instruction_pointer -= offset as u32;
|
||||
return Ok(JVMCallbackOperation::LoadClass(class_name.to_string()));
|
||||
}
|
||||
if ! self.class_store.was_init(class_name).unwrap() {
|
||||
frame.instruction_pointer -= offset as u32;
|
||||
return Ok(JVMCallbackOperation::InitClass(class_name.to_string()));
|
||||
}
|
||||
}
|
||||
|
||||
frame.operand_stack.pop_reference(0).unwrap();
|
||||
|
||||
|
||||
let instruction_result = if class_name == native_class_name {
|
||||
1
|
||||
} else {
|
||||
|
@ -1449,6 +1464,20 @@ impl JVM {
|
|||
}
|
||||
}
|
||||
|
||||
Instruction::LoadConstant64(wide_index) => {
|
||||
match class.pool_entry(wide_index).unwrap() {
|
||||
ConstantPoolInfo::Long(long_data) => {
|
||||
let long_value = long_data.value;
|
||||
|
||||
wrap_stackframe_error(class, method, frame.operand_stack.push_long(long_value))?;
|
||||
}
|
||||
_ => {
|
||||
println!("{:?}", class.pool_entry(wide_index).unwrap());
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Instruction::LoadLocalFloat(index) => {
|
||||
load_local_float(class, method, frame, index as usize)?;
|
||||
}
|
||||
|
@ -1749,6 +1778,12 @@ impl JVM {
|
|||
FieldValue::Int(int_value)
|
||||
}
|
||||
|
||||
(0, AbstractTypeKind::Long()) => {
|
||||
let long_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
|
||||
|
||||
FieldValue::Long(long_value)
|
||||
}
|
||||
|
||||
(0..=255, AbstractTypeKind::Classname(_field_type_name)) => {
|
||||
let ref_value = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?;
|
||||
|
||||
|
|
|
@ -395,22 +395,42 @@ impl JdkInternalUtilSystemPropsRaw {
|
|||
|
||||
// command-line configured properties, should return at least java.home
|
||||
pub fn vm_properties(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||
let array_length = 4;
|
||||
let native_array = vec![
|
||||
("java.home", "./"),
|
||||
("stdout.encoding", "UTF-8"),
|
||||
("java.io.tmpdir", "/tmp"),
|
||||
("user.language", "en"),
|
||||
("user.script", ""),
|
||||
("user.country", "US"),
|
||||
("user.variant", ""),
|
||||
];
|
||||
// TODO: Cross-Platform tmpdir
|
||||
// TODO: locale detection
|
||||
let array_length = native_array.len() * 2 + 2;
|
||||
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);
|
||||
|
||||
{
|
||||
// TODO: Actual java home path
|
||||
let java_home_key_reference = jvm.heap_area.make_handmade_string(&String::from("java.home"), &jvm.class_store);
|
||||
let java_home_value_reference = jvm.heap_area.make_handmade_string(&String::from("./"), &jvm.class_store);
|
||||
for (index, (key, value)) in native_array.iter().enumerate() {
|
||||
let key_string: String = key.to_string();
|
||||
let value_string: String = value.to_string();
|
||||
let key_reference = jvm.heap_area.make_handmade_string(&key_string, &jvm.class_store);
|
||||
let value_reference = jvm.heap_area.make_handmade_string(&value_string, &jvm.class_store);
|
||||
|
||||
jvm.heap_area.object_area.set_array_element(array_reference, 0, java_home_key_reference.into());
|
||||
jvm.heap_area.object_area.set_array_element(array_reference, 1, java_home_value_reference.into());
|
||||
jvm.heap_area.object_area.set_array_element(array_reference, index * 2 , key_reference.into());
|
||||
jvm.heap_area.object_area.set_array_element(array_reference, index * 2 + 1, value_reference.into());
|
||||
}
|
||||
|
||||
Ok(JVMCallbackOperation::ReturnFrame(StackValue::Reference(array_reference)))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct JdkInternalMiscVM {}
|
||||
|
||||
impl JdkInternalMiscVM {
|
||||
pub fn initialize(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||
Ok(JVMCallbackOperation::PopFrame())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Result<NativeMethodCallable, Error> {
|
||||
let method_name: &str = &m.name;
|
||||
|
@ -2548,6 +2568,119 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
|
|||
Ok(todo_call)
|
||||
}
|
||||
|
||||
("jdk/internal/misc/VM", "getgid") => {
|
||||
let expected_descriptor = MethodDescriptor {
|
||||
argument_types: Box::new([
|
||||
]),
|
||||
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(todo_call)
|
||||
}
|
||||
|
||||
("jdk/internal/misc/VM", "getegid") => {
|
||||
let expected_descriptor = MethodDescriptor {
|
||||
argument_types: Box::new([
|
||||
]),
|
||||
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(todo_call)
|
||||
}
|
||||
|
||||
("jdk/internal/misc/VM", "geteuid") => {
|
||||
let expected_descriptor = MethodDescriptor {
|
||||
argument_types: Box::new([
|
||||
]),
|
||||
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(todo_call)
|
||||
}
|
||||
|
||||
("jdk/internal/misc/VM", "getuid") => {
|
||||
let expected_descriptor = MethodDescriptor {
|
||||
argument_types: Box::new([
|
||||
]),
|
||||
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(todo_call)
|
||||
}
|
||||
|
||||
("jdk/internal/misc/VM", "getNanoTimeAdjustment") => {
|
||||
let expected_descriptor = MethodDescriptor {
|
||||
argument_types: Box::new([
|
||||
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Long()},
|
||||
]),
|
||||
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(todo_call)
|
||||
}
|
||||
|
||||
("jdk/internal/misc/VM", "getRuntimeArguments") => {
|
||||
let expected_descriptor = MethodDescriptor {
|
||||
argument_types: Box::new([
|
||||
]),
|
||||
return_type: AbstractTypeDescription { array_level: 1, kind: AbstractTypeKind::Classname("java/lang/String".to_string())},
|
||||
};
|
||||
|
||||
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(todo_call)
|
||||
}
|
||||
|
||||
("jdk/internal/misc/VM", "initialize") => {
|
||||
let expected_descriptor = MethodDescriptor {
|
||||
argument_types: Box::new([
|
||||
]),
|
||||
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void()},
|
||||
};
|
||||
|
||||
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(JdkInternalMiscVM::initialize)
|
||||
}
|
||||
|
||||
("jdk/internal/misc/VM", "latestUserDefinedLoader0") => {
|
||||
let expected_descriptor = MethodDescriptor {
|
||||
argument_types: Box::new([
|
||||
]),
|
||||
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/ClassLoader".to_string())},
|
||||
};
|
||||
|
||||
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(todo_call)
|
||||
}
|
||||
|
||||
("jdk/internal/util/SystemProps$Raw", "platformProperties") => {
|
||||
let expected_descriptor = MethodDescriptor {
|
||||
argument_types: Box::new([
|
||||
|
|
|
@ -50,6 +50,17 @@ impl OperandStack {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn push_long(&mut self, long: i64) -> Result<(), Error> {
|
||||
let long_bytes: [u8; 8] = long.to_be_bytes();
|
||||
|
||||
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_field_value(&mut self, value: FieldValue) -> Result<(), Error> {
|
||||
match value {
|
||||
FieldValue::Reference(r) => {
|
||||
|
@ -187,6 +198,15 @@ impl OperandStack {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn peek_reference(&mut self, index: usize) -> Result<ObjectReference, Error> {
|
||||
let absolute_index = self.depth as usize - 1 - index;
|
||||
let value = self.stack[absolute_index];
|
||||
match value {
|
||||
StackValue::Reference(o) => Ok(o),
|
||||
_ => Err(Error::LocalError(format!("Mismatched type at index {} of the function operand stack, expected Reference but found '{:?}'", index, value)))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pop_returnaddress(&mut self, index: usize) -> Result<u32, Error> {
|
||||
let absolute_index = self.depth as usize - 1 - index;
|
||||
let value = self.stack[absolute_index];
|
||||
|
@ -253,14 +273,17 @@ impl OperandStack {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn pop_long(&mut self, index: usize) -> Result<u64, Error> {
|
||||
pub fn pop_long(&mut self, index: usize) -> Result<i64, Error> {
|
||||
let absolute_index = self.depth as usize - 1 - index;
|
||||
let higher_bytes = self.stack[absolute_index];
|
||||
let lower_bytes = self.stack[absolute_index + 1];
|
||||
let lower_bytes = self.stack[absolute_index];
|
||||
let higher_bytes = self.stack[absolute_index - 1];
|
||||
self.depth -= 2;
|
||||
match (higher_bytes, lower_bytes) {
|
||||
(StackValue::Long0(hi), StackValue::Long1(lo)) => {
|
||||
Ok(((hi as u64) << 32) | lo as u64)
|
||||
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)
|
||||
},
|
||||
_ => Err(Error::LocalError(format!("Mismatched types at index {} of the function operand stack, expected (Long0, Long1) but found '{:?}'", index, (higher_bytes, lower_bytes))))
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue