Now calls the main method with an uncountable amount of hacks
This commit is contained in:
parent
c4da80f23c
commit
90e244c964
4 changed files with 325 additions and 88 deletions
114
src/jvm.rs
114
src/jvm.rs
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::virtual_thread::VirtualThread;
|
||||||
use crate::classfile::ExceptionTableEntry;
|
use crate::classfile::ExceptionTableEntry;
|
||||||
use core::fmt::{Display, Formatter};
|
use core::fmt::{Display, Formatter};
|
||||||
|
|
||||||
|
@ -55,18 +56,20 @@ impl Display for Error {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct JVM {
|
pub struct JVM {
|
||||||
pub class_store: ClassStore,
|
pub class_store: ClassStore,
|
||||||
pub stack_frames: Vec<StackFrame>,
|
|
||||||
pub heap_area: HeapArea,
|
pub heap_area: HeapArea,
|
||||||
pub native_registry: NativeRegistry,
|
pub native_registry: NativeRegistry,
|
||||||
|
pub threads: Vec<VirtualThread>,
|
||||||
|
pub active_thread: usize
|
||||||
}
|
}
|
||||||
|
|
||||||
impl JVM {
|
impl JVM {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
return JVM {
|
return JVM {
|
||||||
class_store: ClassStore::new(),
|
class_store: ClassStore::new(),
|
||||||
stack_frames: Vec::new(),
|
|
||||||
heap_area: HeapArea::new(usize::MAX),
|
heap_area: HeapArea::new(usize::MAX),
|
||||||
native_registry: NativeRegistry::default(),
|
native_registry: NativeRegistry::default(),
|
||||||
|
threads: Vec::new(),
|
||||||
|
active_thread: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,37 +465,97 @@ impl JVM {
|
||||||
.collect();
|
.collect();
|
||||||
let argument_array_ref = self.heap_area.make_array(&self.class_store, string_refs);
|
let argument_array_ref = self.heap_area.make_array(&self.class_store, string_refs);
|
||||||
|
|
||||||
|
self.setup_main_thread()?;
|
||||||
|
|
||||||
// push the entry frame which will call main
|
// push the entry frame which will call main
|
||||||
let entry_frame = StackFrame::new(self.class_store.get_class(&String::from("::EntryPoint")).unwrap().0, 0, 0, &[StackValue::Reference(argument_array_ref)]);
|
let entry_frame = StackFrame::new(self.class_store.get_class(&String::from("::EntryPoint")).unwrap().0, 0, 0, &[StackValue::Reference(argument_array_ref)]);
|
||||||
self.stack_frames.push(entry_frame);
|
self.active_thread_mut().add_frame(entry_frame);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setup_main_thread(&mut self) -> Result<(), Error> {
|
||||||
|
let thread_group_class_index = self.load_class_hierarchy(&"java/lang/ThreadGroup".to_string())?;
|
||||||
|
let main_thread_group_reference = self.heap_area.make_object(&self.class_store, thread_group_class_index);
|
||||||
|
|
||||||
|
let holder_class_index = self.load_class_hierarchy(&"java/lang/Thread$FieldHolder".to_string())?;
|
||||||
|
let main_thread_holder_reference = self.heap_area.make_object(&self.class_store, holder_class_index);
|
||||||
|
self.heap_area.object_area.set_object_field(
|
||||||
|
main_thread_holder_reference,
|
||||||
|
"threadStatus",
|
||||||
|
FieldValue::Int(1), // alive
|
||||||
|
holder_class_index,
|
||||||
|
&self.class_store
|
||||||
|
)?;
|
||||||
|
self.heap_area.object_area.set_object_field(
|
||||||
|
main_thread_holder_reference,
|
||||||
|
"group",
|
||||||
|
main_thread_group_reference.into(),
|
||||||
|
holder_class_index,
|
||||||
|
&self.class_store
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let thread_class_index = self.load_class_hierarchy(&"java/lang/Thread".to_string())?;
|
||||||
|
let main_thread_reference = {
|
||||||
|
self.heap_area.make_object(&self.class_store, thread_class_index)
|
||||||
|
};
|
||||||
|
self.heap_area.object_area.set_object_field(
|
||||||
|
main_thread_reference,
|
||||||
|
"eetop",
|
||||||
|
FieldValue::Long(0), // thread array index
|
||||||
|
thread_class_index,
|
||||||
|
&self.class_store
|
||||||
|
)?;
|
||||||
|
let main_thread_name = self.heap_area.make_handmade_string(&"main".to_string(), &self.class_store);
|
||||||
|
self.heap_area.object_area.set_object_field(
|
||||||
|
main_thread_reference,
|
||||||
|
"name",
|
||||||
|
FieldValue::Reference(main_thread_name),
|
||||||
|
thread_class_index,
|
||||||
|
&self.class_store
|
||||||
|
)?;
|
||||||
|
self.heap_area.object_area.set_object_field(
|
||||||
|
main_thread_reference,
|
||||||
|
"holder",
|
||||||
|
FieldValue::Reference(main_thread_holder_reference),
|
||||||
|
thread_class_index,
|
||||||
|
&self.class_store
|
||||||
|
)?;
|
||||||
|
|
||||||
|
|
||||||
|
self.threads.push(
|
||||||
|
VirtualThread::new(main_thread_reference)
|
||||||
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self) -> Result<(), Error> {
|
pub fn run(&mut self) -> Result<(), Error> {
|
||||||
while self.stack_frames.len() != 0 {
|
while self.active_thread_mut().stack_frames.len() != 0 {
|
||||||
|
|
||||||
let jvm_op = self.bytecode_loop()?;
|
let jvm_op = self.bytecode_loop()?;
|
||||||
match jvm_op {
|
match jvm_op {
|
||||||
JVMCallbackOperation::PopFrame() => {
|
JVMCallbackOperation::PopFrame() => {
|
||||||
self.stack_frames.truncate(self.stack_frames.len() - 1)
|
let frame_count = self.active_thread_mut().stack_frames.len() - 1;
|
||||||
|
self.active_thread_mut().stack_frames.truncate(frame_count);
|
||||||
},
|
},
|
||||||
|
|
||||||
JVMCallbackOperation::ReturnFrame(value) => {
|
JVMCallbackOperation::ReturnFrame(value) => {
|
||||||
// Pop returning frame
|
// Pop returning frame
|
||||||
self.stack_frames.truncate(self.stack_frames.len() - 1);
|
let frame_count = self.active_thread_mut().stack_frames.len() - 1;
|
||||||
|
self.active_thread_mut().stack_frames.truncate(frame_count);
|
||||||
|
|
||||||
let frame = {
|
let frame = {
|
||||||
let frame_index = self.stack_frames.len() - 1;
|
let thread = &mut self.threads[self.active_thread];
|
||||||
&mut self.stack_frames[frame_index]
|
let frame_index = thread.stack_frames.len() - 1;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
};
|
};
|
||||||
let class = self.class_store.class_file_from_idx(frame.class_index).unwrap();
|
let class = self.class_store.class_file_from_idx(frame.class_index).unwrap();
|
||||||
let method = & class.methods[frame.method_index as usize];
|
let method = & class.methods[frame.method_index as usize];
|
||||||
wrap_stackframe_error(class, method, self.stack_frames.last_mut().unwrap().operand_stack.push_field_value(value))?;
|
wrap_stackframe_error(class, method, frame.operand_stack.push_field_value(value))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
JVMCallbackOperation::PushFrame(frame) => self.stack_frames.push(frame),
|
JVMCallbackOperation::PushFrame(frame) => self.active_thread_mut().stack_frames.push(frame),
|
||||||
|
|
||||||
JVMCallbackOperation::LoadClass(name) => {
|
JVMCallbackOperation::LoadClass(name) => {
|
||||||
// TODO: throw exception
|
// TODO: throw exception
|
||||||
|
@ -514,8 +577,9 @@ impl JVM {
|
||||||
while ! is_handler_found {
|
while ! is_handler_found {
|
||||||
is_handler_found = {
|
is_handler_found = {
|
||||||
let frame = {
|
let frame = {
|
||||||
let frame_index = self.stack_frames.len() - 1;
|
let thread = &mut self.threads[self.active_thread];
|
||||||
&mut self.stack_frames[frame_index]
|
let frame_index = thread.stack_frames.len() - 1;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
};
|
};
|
||||||
let class = self.class_store.class_file_from_idx(frame.class_index).unwrap();
|
let class = self.class_store.class_file_from_idx(frame.class_index).unwrap();
|
||||||
let method = &class.methods[frame.method_index as usize];
|
let method = &class.methods[frame.method_index as usize];
|
||||||
|
@ -527,14 +591,15 @@ impl JVM {
|
||||||
};
|
};
|
||||||
|
|
||||||
if ! is_handler_found {
|
if ! is_handler_found {
|
||||||
self.stack_frames.pop();
|
self.active_thread_mut().stack_frames.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_handler_found {
|
if is_handler_found {
|
||||||
let frame = {
|
let frame = {
|
||||||
let frame_index = self.stack_frames.len() - 1;
|
let thread = &mut self.threads[self.active_thread];
|
||||||
&mut self.stack_frames[frame_index]
|
let frame_index = thread.stack_frames.len() - 1;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
};
|
};
|
||||||
let class = self.class_store.class_file_from_idx(frame.class_index).unwrap();
|
let class = self.class_store.class_file_from_idx(frame.class_index).unwrap();
|
||||||
let method = &class.methods[frame.method_index as usize];
|
let method = &class.methods[frame.method_index as usize];
|
||||||
|
@ -703,7 +768,7 @@ impl JVM {
|
||||||
&[],
|
&[],
|
||||||
);
|
);
|
||||||
|
|
||||||
self.stack_frames.push(clinit_frame);
|
self.active_thread_mut().add_frame(clinit_frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
// finish
|
// finish
|
||||||
|
@ -714,8 +779,9 @@ impl JVM {
|
||||||
|
|
||||||
fn native_call(&mut self) -> Result<JVMCallbackOperation, Error> {
|
fn native_call(&mut self) -> Result<JVMCallbackOperation, Error> {
|
||||||
let frame = {
|
let frame = {
|
||||||
let frame_index = self.stack_frames.len() - 1;
|
let thread = &mut self.threads[self.active_thread];
|
||||||
&mut self.stack_frames[frame_index]
|
let frame_index = thread.stack_frames.len() - 1;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
};
|
};
|
||||||
let class = self.class_store.class_file_from_idx(frame.class_index).unwrap();
|
let class = self.class_store.class_file_from_idx(frame.class_index).unwrap();
|
||||||
let method = & class.methods[frame.method_index as usize];
|
let method = & class.methods[frame.method_index as usize];
|
||||||
|
@ -734,8 +800,12 @@ impl JVM {
|
||||||
fn bytecode_loop(&mut self) -> Result<JVMCallbackOperation, Error> {
|
fn bytecode_loop(&mut self) -> Result<JVMCallbackOperation, Error> {
|
||||||
//println!("Enter bytecode loop:");
|
//println!("Enter bytecode loop:");
|
||||||
|
|
||||||
let frame_index = self.stack_frames.len() - 1;
|
let frame_index = self.active_thread_mut().stack_frames.len() - 1;
|
||||||
let frame = &mut self.stack_frames[frame_index];
|
let frame = {
|
||||||
|
let thread = &mut self.threads[self.active_thread];
|
||||||
|
let frame_index = thread.stack_frames.len() - 1;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
|
};
|
||||||
let class = self.class_store.class_file_from_idx(frame.class_index).unwrap();
|
let class = self.class_store.class_file_from_idx(frame.class_index).unwrap();
|
||||||
let method = & class.methods[frame.method_index as usize];
|
let method = & class.methods[frame.method_index as usize];
|
||||||
|
|
||||||
|
@ -2541,6 +2611,10 @@ impl JVM {
|
||||||
Ok(JVMCallbackOperation::PopFrame())
|
Ok(JVMCallbackOperation::PopFrame())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn active_thread_mut(&mut self) -> &mut VirtualThread {
|
||||||
|
return &mut self.threads[self.active_thread];
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum JVMCallbackOperation {
|
pub enum JVMCallbackOperation {
|
||||||
|
|
|
@ -9,6 +9,7 @@ mod heap_area;
|
||||||
mod iterators;
|
mod iterators;
|
||||||
mod native_registry;
|
mod native_registry;
|
||||||
mod native_methods;
|
mod native_methods;
|
||||||
|
mod virtual_thread;
|
||||||
|
|
||||||
//use std::fs::File;
|
//use std::fs::File;
|
||||||
//
|
//
|
||||||
|
|
|
@ -11,6 +11,7 @@ use crate::native_registry::NativeMethodCallable;
|
||||||
use crate::jvm::JVM;
|
use crate::jvm::JVM;
|
||||||
use crate::jvm::Error;
|
use crate::jvm::Error;
|
||||||
use crate::jvm::JVMCallbackOperation;
|
use crate::jvm::JVMCallbackOperation;
|
||||||
|
use crate::virtual_thread::VirtualThread;
|
||||||
|
|
||||||
pub fn ignore_call(_: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
pub fn ignore_call(_: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
Ok(JVMCallbackOperation::PopFrame())
|
Ok(JVMCallbackOperation::PopFrame())
|
||||||
|
@ -60,8 +61,9 @@ impl JavaLangClass {
|
||||||
|
|
||||||
fn is_array(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
fn is_array(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
let frame = {
|
let frame = {
|
||||||
let frame_index = jvm.stack_frames.len() - 1;
|
let thread = &mut jvm.threads[jvm.active_thread];
|
||||||
&mut jvm.stack_frames[frame_index]
|
let frame_index = thread.stack_frames.len() - 1;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
};
|
};
|
||||||
let this = frame.load_local_reference(0).unwrap();
|
let this = frame.load_local_reference(0).unwrap();
|
||||||
let class_class_index = jvm.heap_area.object_area.get_object_class_index(this);
|
let class_class_index = jvm.heap_area.object_area.get_object_class_index(this);
|
||||||
|
@ -77,8 +79,9 @@ impl JavaLangClass {
|
||||||
|
|
||||||
pub fn get_primitive_class(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
pub fn get_primitive_class(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
let frame = {
|
let frame = {
|
||||||
let frame_index = jvm.stack_frames.len() - 1;
|
let thread = &mut jvm.threads[jvm.active_thread];
|
||||||
&mut jvm.stack_frames[frame_index]
|
let frame_index = thread.stack_frames.len() - 1;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
};
|
};
|
||||||
// max_locals: 1
|
// max_locals: 1
|
||||||
// max_stack: 1
|
// max_stack: 1
|
||||||
|
@ -328,8 +331,9 @@ struct JavaLangFloat {}
|
||||||
impl JavaLangFloat {
|
impl JavaLangFloat {
|
||||||
pub fn float_to_raw_int_bits(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
pub fn float_to_raw_int_bits(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
let frame = {
|
let frame = {
|
||||||
let frame_index = jvm.stack_frames.len() - 1;
|
let thread = &mut jvm.threads[jvm.active_thread];
|
||||||
&mut jvm.stack_frames[frame_index]
|
let frame_index = thread.stack_frames.len() - 1;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
};
|
};
|
||||||
let class = jvm.class_store.class_file_from_idx(frame.class_index).unwrap();
|
let class = jvm.class_store.class_file_from_idx(frame.class_index).unwrap();
|
||||||
let method = & class.methods[frame.method_index as usize];
|
let method = & class.methods[frame.method_index as usize];
|
||||||
|
@ -347,8 +351,9 @@ struct JavaLangDouble {}
|
||||||
impl JavaLangDouble {
|
impl JavaLangDouble {
|
||||||
pub fn double_to_raw_long_bits(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
pub fn double_to_raw_long_bits(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
let frame = {
|
let frame = {
|
||||||
let frame_index = jvm.stack_frames.len() - 1;
|
let thread = &mut jvm.threads[jvm.active_thread];
|
||||||
&mut jvm.stack_frames[frame_index]
|
let frame_index = thread.stack_frames.len() - 1;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
};
|
};
|
||||||
let class = jvm.class_store.class_file_from_idx(frame.class_index).unwrap();
|
let class = jvm.class_store.class_file_from_idx(frame.class_index).unwrap();
|
||||||
let method = & class.methods[frame.method_index as usize];
|
let method = & class.methods[frame.method_index as usize];
|
||||||
|
@ -366,8 +371,9 @@ struct JavaLangObject {}
|
||||||
impl JavaLangObject {
|
impl JavaLangObject {
|
||||||
fn clone(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
fn clone(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
let frame = {
|
let frame = {
|
||||||
let frame_index = jvm.stack_frames.len() - 1;
|
let thread = &mut jvm.threads[jvm.active_thread];
|
||||||
&mut jvm.stack_frames[frame_index]
|
let frame_index = thread.stack_frames.len() - 1;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
};
|
};
|
||||||
let this = frame.load_local_reference(0).unwrap();
|
let this = frame.load_local_reference(0).unwrap();
|
||||||
|
|
||||||
|
@ -378,8 +384,9 @@ impl JavaLangObject {
|
||||||
|
|
||||||
fn get_class(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
fn get_class(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
let frame = {
|
let frame = {
|
||||||
let frame_index = jvm.stack_frames.len() - 1;
|
let thread = &mut jvm.threads[jvm.active_thread];
|
||||||
&mut jvm.stack_frames[frame_index]
|
let frame_index = thread.stack_frames.len() - 1;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
};
|
};
|
||||||
let this = frame.load_local_reference(0).unwrap();
|
let this = frame.load_local_reference(0).unwrap();
|
||||||
|
|
||||||
|
@ -390,8 +397,9 @@ impl JavaLangObject {
|
||||||
|
|
||||||
fn hashcode(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
fn hashcode(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
let frame = {
|
let frame = {
|
||||||
let frame_index = jvm.stack_frames.len() - 1;
|
let thread = &mut jvm.threads[jvm.active_thread];
|
||||||
&mut jvm.stack_frames[frame_index]
|
let frame_index = thread.stack_frames.len() - 1;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
};
|
};
|
||||||
if frame.operand_stack.capacity() == 1 {
|
if frame.operand_stack.capacity() == 1 {
|
||||||
frame.operand_stack.grow(2);
|
frame.operand_stack.grow(2);
|
||||||
|
@ -447,6 +455,15 @@ impl JavaLangObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct JavaLangRefFinalizer {}
|
||||||
|
|
||||||
|
impl JavaLangRefFinalizer {
|
||||||
|
pub fn is_finalization_enabled(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
|
// TODO: enable
|
||||||
|
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Boolean(false)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct JavaLangRuntime {}
|
struct JavaLangRuntime {}
|
||||||
|
|
||||||
impl JavaLangRuntime {
|
impl JavaLangRuntime {
|
||||||
|
@ -460,8 +477,9 @@ struct JavaLangSignal {}
|
||||||
impl JavaLangSignal {
|
impl JavaLangSignal {
|
||||||
fn find_signal_0(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
fn find_signal_0(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
let frame = {
|
let frame = {
|
||||||
let frame_index = jvm.stack_frames.len() - 1;
|
let thread = &mut jvm.threads[jvm.active_thread];
|
||||||
&mut jvm.stack_frames[frame_index]
|
let frame_index = thread.stack_frames.len() - 1;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
};
|
};
|
||||||
let string_ref = frame.load_local_reference(0).unwrap();
|
let string_ref = frame.load_local_reference(0).unwrap();
|
||||||
let rust_string = jvm.heap_area.decode_java_string(string_ref, &jvm.class_store);
|
let rust_string = jvm.heap_area.decode_java_string(string_ref, &jvm.class_store);
|
||||||
|
@ -485,8 +503,9 @@ impl JavaLangSystem {
|
||||||
fn register_natives(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
fn register_natives(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
// Load class because it won't be loaded otherwise
|
// Load class because it won't be loaded otherwise
|
||||||
let frame = {
|
let frame = {
|
||||||
let frame_index = jvm.stack_frames.len() - 1;
|
let thread = &mut jvm.threads[jvm.active_thread];
|
||||||
&mut jvm.stack_frames[frame_index]
|
let frame_index = thread.stack_frames.len() - 1;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
};
|
};
|
||||||
|
|
||||||
let r#return = match frame.instruction_pointer {
|
let r#return = match frame.instruction_pointer {
|
||||||
|
@ -508,8 +527,9 @@ impl JavaLangSystem {
|
||||||
|
|
||||||
fn set_err_0(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
fn set_err_0(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
let frame = {
|
let frame = {
|
||||||
let frame_index = jvm.stack_frames.len() - 1;
|
let thread = &mut jvm.threads[jvm.active_thread];
|
||||||
&mut jvm.stack_frames[frame_index]
|
let frame_index = thread.stack_frames.len() - 1;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
};
|
};
|
||||||
let input_stream = frame.load_local_reference(0).unwrap();
|
let input_stream = frame.load_local_reference(0).unwrap();
|
||||||
|
|
||||||
|
@ -525,8 +545,9 @@ impl JavaLangSystem {
|
||||||
|
|
||||||
fn set_out_0(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
fn set_out_0(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
let frame = {
|
let frame = {
|
||||||
let frame_index = jvm.stack_frames.len() - 1;
|
let thread = &mut jvm.threads[jvm.active_thread];
|
||||||
&mut jvm.stack_frames[frame_index]
|
let frame_index = thread.stack_frames.len() - 1;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
};
|
};
|
||||||
let input_stream = frame.load_local_reference(0).unwrap();
|
let input_stream = frame.load_local_reference(0).unwrap();
|
||||||
|
|
||||||
|
@ -542,8 +563,9 @@ impl JavaLangSystem {
|
||||||
|
|
||||||
fn set_in_0(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
fn set_in_0(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
let frame = {
|
let frame = {
|
||||||
let frame_index = jvm.stack_frames.len() - 1;
|
let thread = &mut jvm.threads[jvm.active_thread];
|
||||||
&mut jvm.stack_frames[frame_index]
|
let frame_index = thread.stack_frames.len() - 1;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
};
|
};
|
||||||
let input_stream = frame.load_local_reference(0).unwrap();
|
let input_stream = frame.load_local_reference(0).unwrap();
|
||||||
|
|
||||||
|
@ -559,8 +581,9 @@ impl JavaLangSystem {
|
||||||
|
|
||||||
pub fn arraycopy(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
pub fn arraycopy(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
let frame = {
|
let frame = {
|
||||||
let frame_index = jvm.stack_frames.len() - 1;
|
let thread = &mut jvm.threads[jvm.active_thread];
|
||||||
&mut jvm.stack_frames[frame_index]
|
let frame_index = thread.stack_frames.len() - 1;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
};
|
};
|
||||||
let src = frame.load_local_reference(0).unwrap();
|
let src = frame.load_local_reference(0).unwrap();
|
||||||
let src_pos = frame.load_local_int(1).unwrap();
|
let src_pos = frame.load_local_int(1).unwrap();
|
||||||
|
@ -577,6 +600,60 @@ impl JavaLangSystem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct JavaLangThread {}
|
||||||
|
|
||||||
|
impl JavaLangThread {
|
||||||
|
pub fn start_0(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
|
let frame = {
|
||||||
|
let thread = &mut jvm.threads[jvm.active_thread];
|
||||||
|
let frame_index = thread.stack_frames.len() - 1;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
|
};
|
||||||
|
let this = frame.load_local_reference(0).unwrap();
|
||||||
|
|
||||||
|
jvm.threads.push(VirtualThread::new(this));
|
||||||
|
// TODO: Push frames
|
||||||
|
|
||||||
|
Ok(JVMCallbackOperation::PopFrame())
|
||||||
|
}
|
||||||
|
pub fn set_priority_0(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
|
let frame = {
|
||||||
|
let thread = &mut jvm.threads[jvm.active_thread];
|
||||||
|
let frame_index = thread.stack_frames.len() - 1;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
|
};
|
||||||
|
let this = frame.load_local_reference(0).unwrap();
|
||||||
|
let priority = frame.load_local_int(1).unwrap();
|
||||||
|
let thread_class_index = frame.class_index;
|
||||||
|
|
||||||
|
let holder = jvm.heap_area.object_area.get_object_field(
|
||||||
|
this,
|
||||||
|
"holder",
|
||||||
|
thread_class_index,
|
||||||
|
&jvm.class_store,
|
||||||
|
)?.expect_reference();
|
||||||
|
|
||||||
|
let holder_class_index = jvm.heap_area.object_area.get_reference_class_index(holder, &jvm.class_store);
|
||||||
|
jvm.heap_area.object_area.set_object_field(
|
||||||
|
holder,
|
||||||
|
"priority",
|
||||||
|
FieldValue::Int(priority),
|
||||||
|
holder_class_index,
|
||||||
|
&jvm.class_store,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(JVMCallbackOperation::PopFrame())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_next_thread_id_offset(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
|
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Long(0xDEADBEEF))) // this offset will be passed to getAndAddLong
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn current_thread(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
|
Ok(JVMCallbackOperation::ReturnFrame(jvm.active_thread_mut().thread_object.into()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct JavaLangThrowable {}
|
struct JavaLangThrowable {}
|
||||||
|
|
||||||
impl JavaLangThrowable {
|
impl JavaLangThrowable {
|
||||||
|
@ -598,13 +675,15 @@ impl JavaLangThrowable {
|
||||||
|
|
||||||
let this = {
|
let this = {
|
||||||
let frame = {
|
let frame = {
|
||||||
let frame_index = jvm.stack_frames.len() - 1;
|
let thread = &mut jvm.threads[jvm.active_thread];
|
||||||
&jvm.stack_frames[frame_index]
|
let frame_index = thread.stack_frames.len() - 1;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
};
|
};
|
||||||
frame.load_local_reference(0).unwrap()
|
frame.load_local_reference(0).unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
let stackelement_array = jvm.heap_area.make_empty_array(&jvm.class_store, AbstractTypeDescription::class_type("java/lang/StackTraceElement"), jvm.stack_frames.len());
|
let frame_count = jvm.active_thread_mut().stack_frames.len();
|
||||||
|
let stackelement_array = jvm.heap_area.make_empty_array(&jvm.class_store, AbstractTypeDescription::class_type("java/lang/StackTraceElement"), frame_count);
|
||||||
|
|
||||||
jvm.heap_area.object_area.set_object_field(
|
jvm.heap_area.object_area.set_object_field(
|
||||||
this,
|
this,
|
||||||
|
@ -614,7 +693,12 @@ impl JavaLangThrowable {
|
||||||
&jvm.class_store
|
&jvm.class_store
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
for (index, frame) in (&jvm.stack_frames).into_iter().enumerate() {
|
let active_thread_frames = {
|
||||||
|
let thread = &mut jvm.threads[jvm.active_thread];
|
||||||
|
&mut thread.stack_frames
|
||||||
|
};
|
||||||
|
|
||||||
|
for (index, frame) in (active_thread_frames).into_iter().enumerate() {
|
||||||
let class_file = jvm.class_store.class_file_from_idx(frame.class_index).unwrap();
|
let class_file = jvm.class_store.class_file_from_idx(frame.class_index).unwrap();
|
||||||
let method_info = &class_file.methods[frame.method_index as usize];
|
let method_info = &class_file.methods[frame.method_index as usize];
|
||||||
|
|
||||||
|
@ -739,8 +823,9 @@ impl JdkInternalMiscUnsafe {
|
||||||
|
|
||||||
pub fn compare_and_set_reference(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
pub fn compare_and_set_reference(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
let frame = {
|
let frame = {
|
||||||
let frame_index = jvm.stack_frames.len() - 1;
|
let thread = &mut jvm.threads[jvm.active_thread];
|
||||||
&mut jvm.stack_frames[frame_index]
|
let frame_index = thread.stack_frames.len() - 1;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
};
|
};
|
||||||
|
|
||||||
let object = frame.load_local_reference(1).unwrap();
|
let object = frame.load_local_reference(1).unwrap();
|
||||||
|
@ -770,8 +855,9 @@ impl JdkInternalMiscUnsafe {
|
||||||
|
|
||||||
pub fn put_reference_volatile(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
pub fn put_reference_volatile(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
let frame = {
|
let frame = {
|
||||||
let frame_index = jvm.stack_frames.len() - 1;
|
let thread = &mut jvm.threads[jvm.active_thread];
|
||||||
&mut jvm.stack_frames[frame_index]
|
let frame_index = thread.stack_frames.len() - 1;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
};
|
};
|
||||||
|
|
||||||
let object = frame.load_local_reference(1).unwrap();
|
let object = frame.load_local_reference(1).unwrap();
|
||||||
|
@ -791,10 +877,28 @@ impl JdkInternalMiscUnsafe {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_long_volatile(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
|
let frame = {
|
||||||
|
let thread = &mut jvm.threads[jvm.active_thread];
|
||||||
|
let frame_index = thread.stack_frames.len() - 1;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
|
};
|
||||||
|
|
||||||
|
let object = frame.load_local_reference(1).unwrap();
|
||||||
|
let offset = frame.load_local_long(2).unwrap();
|
||||||
|
|
||||||
|
if object == ObjectReference::NULL && offset == 0xDEADBEEF {
|
||||||
|
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Long(jvm.threads.len() as i64 - 1)))
|
||||||
|
} else {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_reference_volatile(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
pub fn get_reference_volatile(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
let frame = {
|
let frame = {
|
||||||
let frame_index = jvm.stack_frames.len() - 1;
|
let thread = &mut jvm.threads[jvm.active_thread];
|
||||||
&mut jvm.stack_frames[frame_index]
|
let frame_index = thread.stack_frames.len() - 1;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
};
|
};
|
||||||
|
|
||||||
let object = frame.load_local_reference(1).unwrap();
|
let object = frame.load_local_reference(1).unwrap();
|
||||||
|
@ -828,8 +932,9 @@ impl JdkInternalMiscUnsafe {
|
||||||
|
|
||||||
pub fn compare_and_set_long(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
pub fn compare_and_set_long(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
let frame = {
|
let frame = {
|
||||||
let frame_index = jvm.stack_frames.len() - 1;
|
let thread = &mut jvm.threads[jvm.active_thread];
|
||||||
&mut jvm.stack_frames[frame_index]
|
let frame_index = thread.stack_frames.len() - 1;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
};
|
};
|
||||||
|
|
||||||
let object = frame.load_local_reference(1).unwrap();
|
let object = frame.load_local_reference(1).unwrap();
|
||||||
|
@ -837,6 +942,11 @@ impl JdkInternalMiscUnsafe {
|
||||||
let expected = frame.load_local_long(4).unwrap();
|
let expected = frame.load_local_long(4).unwrap();
|
||||||
let replacement = frame.load_local_long(6).unwrap();
|
let replacement = frame.load_local_long(6).unwrap();
|
||||||
|
|
||||||
|
if object == ObjectReference::NULL && offset == 0xDEADBEEF {
|
||||||
|
let success = jvm.threads.len() as i64 - 1 == expected;
|
||||||
|
return Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Boolean(success)))
|
||||||
|
}
|
||||||
|
|
||||||
let object_class_descriptor = jvm.heap_area.object_area.get_reference_native_class_name(object, &jvm.class_store);
|
let object_class_descriptor = jvm.heap_area.object_area.get_reference_native_class_name(object, &jvm.class_store);
|
||||||
let object_class_index = jvm.class_store.class_index_for_type(AbstractTypeDescription::parse_full(object_class_descriptor).unwrap()).unwrap();
|
let object_class_index = jvm.class_store.class_index_for_type(AbstractTypeDescription::parse_full(object_class_descriptor).unwrap()).unwrap();
|
||||||
|
|
||||||
|
@ -861,8 +971,9 @@ impl JdkInternalMiscUnsafe {
|
||||||
|
|
||||||
pub fn compare_and_set_int(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
pub fn compare_and_set_int(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
let frame = {
|
let frame = {
|
||||||
let frame_index = jvm.stack_frames.len() - 1;
|
let thread = &mut jvm.threads[jvm.active_thread];
|
||||||
&mut jvm.stack_frames[frame_index]
|
let frame_index = thread.stack_frames.len() - 1;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
};
|
};
|
||||||
|
|
||||||
let object = frame.load_local_reference(1).unwrap();
|
let object = frame.load_local_reference(1).unwrap();
|
||||||
|
@ -895,8 +1006,9 @@ impl JdkInternalMiscUnsafe {
|
||||||
pub fn object_field_offset_1(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
pub fn object_field_offset_1(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
// args: Class class, String fieldName
|
// args: Class class, String fieldName
|
||||||
let frame = {
|
let frame = {
|
||||||
let frame_index = jvm.stack_frames.len() - 1;
|
let thread = &mut jvm.threads[jvm.active_thread];
|
||||||
&mut jvm.stack_frames[frame_index]
|
let frame_index = thread.stack_frames.len() - 1;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
};
|
};
|
||||||
|
|
||||||
let class_object_reference = frame.load_local_reference(1).unwrap();
|
let class_object_reference = frame.load_local_reference(1).unwrap();
|
||||||
|
@ -916,8 +1028,9 @@ impl JdkInternalMiscUnsafe {
|
||||||
|
|
||||||
pub fn array_index_scale_0(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
pub fn array_index_scale_0(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
let frame = {
|
let frame = {
|
||||||
let frame_index = jvm.stack_frames.len() - 1;
|
let thread = &mut jvm.threads[jvm.active_thread];
|
||||||
&mut jvm.stack_frames[frame_index]
|
let frame_index = thread.stack_frames.len() - 1;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
};
|
};
|
||||||
let class = jvm.class_store.class_file_from_idx(frame.class_index).unwrap();
|
let class = jvm.class_store.class_file_from_idx(frame.class_index).unwrap();
|
||||||
let method = & class.methods[frame.method_index as usize];
|
let method = & class.methods[frame.method_index as usize];
|
||||||
|
@ -939,7 +1052,11 @@ struct JdkInternalReflectReflection {}
|
||||||
|
|
||||||
impl JdkInternalReflectReflection {
|
impl JdkInternalReflectReflection {
|
||||||
pub fn get_caller_class(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
pub fn get_caller_class(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
let caller_frame = &jvm.stack_frames[jvm.stack_frames.len() - 2];
|
let caller_frame = {
|
||||||
|
let thread = &mut jvm.threads[jvm.active_thread];
|
||||||
|
let frame_index = thread.stack_frames.len() - 2;
|
||||||
|
&mut thread.stack_frames[frame_index]
|
||||||
|
};
|
||||||
let caller_class_index = caller_frame.class_index;
|
let caller_class_index = caller_frame.class_index;
|
||||||
let caller_class_reference = jvm.class_store.get_class_objectref_from_index(caller_class_index);
|
let caller_class_reference = jvm.class_store.get_class_objectref_from_index(caller_class_index);
|
||||||
|
|
||||||
|
@ -1533,7 +1650,7 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
|
||||||
argument_types: Box::new([]),
|
argument_types: Box::new([]),
|
||||||
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void()},
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void()},
|
||||||
},
|
},
|
||||||
todo_call
|
ignore_call // TODO: Unpark threads or something
|
||||||
),
|
),
|
||||||
|
|
||||||
(
|
(
|
||||||
|
@ -2246,7 +2363,7 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
|
||||||
]),
|
]),
|
||||||
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Long()},
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Long()},
|
||||||
},
|
},
|
||||||
todo_call
|
JdkInternalMiscUnsafe::get_long_volatile
|
||||||
),
|
),
|
||||||
|
|
||||||
(
|
(
|
||||||
|
@ -2962,7 +3079,7 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
|
||||||
argument_types: Box::new([]),
|
argument_types: Box::new([]),
|
||||||
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Thread".to_string())},
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Thread".to_string())},
|
||||||
},
|
},
|
||||||
todo_call
|
JavaLangThread::current_thread,
|
||||||
),
|
),
|
||||||
|
|
||||||
(
|
(
|
||||||
|
@ -3053,7 +3170,7 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
|
||||||
]),
|
]),
|
||||||
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void()},
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void()},
|
||||||
},
|
},
|
||||||
todo_call
|
JavaLangThread::start_0
|
||||||
),
|
),
|
||||||
|
|
||||||
(
|
(
|
||||||
|
@ -3111,7 +3228,7 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
|
||||||
]),
|
]),
|
||||||
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void()},
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void()},
|
||||||
},
|
},
|
||||||
todo_call
|
JavaLangThread::set_priority_0
|
||||||
),
|
),
|
||||||
|
|
||||||
(
|
(
|
||||||
|
@ -3155,7 +3272,7 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
|
||||||
]),
|
]),
|
||||||
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Long()},
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Long()},
|
||||||
},
|
},
|
||||||
todo_call
|
JavaLangThread::get_next_thread_id_offset
|
||||||
),
|
),
|
||||||
|
|
||||||
(
|
(
|
||||||
|
@ -3992,6 +4109,29 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
|
||||||
},
|
},
|
||||||
todo_call
|
todo_call
|
||||||
),
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
"java/lang/ref/Finalizer",
|
||||||
|
"isFinalizationEnabled",
|
||||||
|
MethodDescriptor {
|
||||||
|
argument_types: Box::new([
|
||||||
|
]),
|
||||||
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Boolean() },
|
||||||
|
},
|
||||||
|
JavaLangRefFinalizer::is_finalization_enabled
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
"java/lang/ref/Finalizer",
|
||||||
|
"reportComplete",
|
||||||
|
MethodDescriptor {
|
||||||
|
argument_types: Box::new([
|
||||||
|
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Object".to_string()) },
|
||||||
|
]),
|
||||||
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void() },
|
||||||
|
},
|
||||||
|
todo_call
|
||||||
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
for (classname, methodname, methoddescriptor, binding) in native_mappings {
|
for (classname, methodname, methoddescriptor, binding) in native_mappings {
|
||||||
|
|
22
src/virtual_thread.rs
Normal file
22
src/virtual_thread.rs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
|
||||||
|
use crate::heap_area::ObjectReference;
|
||||||
|
use crate::stackframe::StackFrame;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct VirtualThread {
|
||||||
|
pub stack_frames: Vec<StackFrame>,
|
||||||
|
pub thread_object: ObjectReference,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VirtualThread {
|
||||||
|
pub fn new(thread_reference: ObjectReference) -> Self {
|
||||||
|
VirtualThread {
|
||||||
|
stack_frames: Vec::new(),
|
||||||
|
thread_object: thread_reference,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_frame(&mut self, frame: StackFrame) -> () {
|
||||||
|
self.stack_frames.push(frame)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue