diff --git a/crates/core/src/objects/object_manager.rs b/crates/core/src/objects/object_manager.rs index 651a1ca..d4d466b 100644 --- a/crates/core/src/objects/object_manager.rs +++ b/crates/core/src/objects/object_manager.rs @@ -522,4 +522,54 @@ impl ObjectManager { } constructor_object } + + pub fn new_thread_group( + &mut self, + thread_group_class: Arc, + name: ObjectReference, + max_priority: jint, + ) -> ObjectReference { + let tg_object = self.new_object(thread_group_class); + { + let obj = tg_object.lock(); + obj.set_field("name", name.into()); + obj.set_field("maxPriority", max_priority.into()); + } + tg_object + } + pub fn new_holder( + &mut self, + holder_class: Arc, + group: ObjectReference, + priority: jint, + status: jint, + ) -> ObjectReference { + let holder_object = self.new_object(holder_class); + { + let obj = holder_object.lock(); + obj.set_field("group", group.into()); + obj.set_field("priority", priority.into()); + obj.set_field("threadStatus", status.into()); + } + holder_object + } + + pub fn new_thread( + &mut self, + thread_class: Arc, + eetop: jlong, + tid: jlong, + name: ObjectReference, + holder: ObjectReference, + ) -> ObjectReference { + let tg_object = self.new_object(thread_class); + { + let obj = tg_object.lock(); + obj.set_field("eetop", eetop.into()); + obj.set_field("tid", tid.into()); + obj.set_field("name", name.into()); + obj.set_field("holder", holder.into()); + } + tg_object + } } diff --git a/crates/core/src/thread.rs b/crates/core/src/thread.rs index c86fd2a..8f7468b 100644 --- a/crates/core/src/thread.rs +++ b/crates/core/src/thread.rs @@ -22,8 +22,8 @@ use std::cell::RefCell; use std::collections::VecDeque; use std::ops::{Add, Deref}; use std::ptr::null_mut; -use std::sync::Arc; use std::sync::atomic::{AtomicU64, Ordering}; +use std::sync::{Arc, OnceLock}; use std::thread; use std::vec::IntoIter; @@ -46,12 +46,12 @@ pub struct VmThread { pub frame_stack: Mutex>, pub gc: Arc>, pub jni_env: JNIEnv, + pub mirror: OnceLock, } impl VmThread { pub fn new(vm: Arc, loader: Option) -> Arc { - static NEXT_ID: AtomicU64 = AtomicU64::new(0); - let id = ThreadId(NEXT_ID.fetch_add(1, Ordering::SeqCst)); + let id = ThreadId(vm.NEXT_ID.fetch_add(1, Ordering::SeqCst)); let loader = loader.unwrap_or(vm.loader.clone()); let gc = vm.gc.clone(); @@ -64,6 +64,7 @@ impl VmThread { frame_stack: Default::default(), gc, jni_env, + mirror: Default::default(), } }) } @@ -286,7 +287,7 @@ impl VmThread { } pub fn invoke(&self, method_reference: MethodRef, args: Vec) -> MethodCallResult { - if self.gc.read().objects.len() > 2230 { + if self.gc.read().objects.len() > 2235 { INIT_LOGGER.call_once(|| { env_logger::Builder::from_default_env() .filter_level(LevelFilter::Trace) @@ -320,9 +321,9 @@ impl VmThread { pub fn invoke_native(&self, method: &MethodRef, mut args: Vec) -> MethodCallResult { let symbol_name = generate_jni_method_name(method, false); - if symbol_name.contains("Java_jdk_internal_misc_Signal_handle0") { + if symbol_name.contains("Java_jdk_internal_misc_Unsafe_getLongVolatile") { return Err(VmError::Debug( - "RoastVM specific implementation required for Java_jdk_internal_misc_Signal_handle0", + "RoastVM specific implementation required for Java_jdk_internal_misc_Unsafe_getLongVolatile", )); } @@ -601,4 +602,26 @@ impl VmThread { gc.get_interned_string(utf) .unwrap_or_else(|| gc.new_string(byte_array_class, string_class, utf)) } + + pub fn bootstrap_mirror(&self) { + let thread_id = self.id.0 as jlong; + let main = self.intern_string("main"); + let system = self.intern_string("system"); + let thread_klass = self.get_class("java/lang/Thread").unwrap(); + let thread_group_klass = self.get_class("java/lang/ThreadGroup").unwrap(); + let field_holder_klass = self.get_class("java/lang/Thread$FieldHolder").unwrap(); + let group = self + .gc + .write() + .new_thread_group(thread_group_klass, system, 10 as jint); + let holder = self + .gc + .write() + .new_holder(field_holder_klass, group, 5 as jint, 5 as jint); + let thread = self + .gc + .write() + .new_thread(thread_klass, thread_id, thread_id, main, holder); + self.mirror.set(thread.lock().id).unwrap(); + } } diff --git a/crates/core/src/vm.rs b/crates/core/src/vm.rs index 1a63b61..d5153e9 100644 --- a/crates/core/src/vm.rs +++ b/crates/core/src/vm.rs @@ -21,6 +21,7 @@ use imp::Library; use log::trace; use parking_lot::{Mutex, RwLock}; use std::sync::Arc; +use std::sync::atomic::AtomicU64; type NativeLibraries = Arc>>; @@ -34,6 +35,7 @@ pub struct Vm { pub native_libraries: NativeLibraries, pub gc: Arc>, pub safent: RwLock, + pub NEXT_ID: AtomicU64, } impl Vm { @@ -47,6 +49,7 @@ impl Vm { native_libraries: Arc::new(RwLock::new(Vec::new())), gc: Default::default(), safent: Default::default(), + NEXT_ID: AtomicU64::new(0), }); // Create main thread @@ -160,6 +163,10 @@ impl Vm { name: "initPhase1".to_string(), desc: MethodDescriptor::void(), }; + self.threads + .get(&self.main_thread_id) + .unwrap() + .bootstrap_mirror(); thread.invoke(phase1ref, Vec::new())?; panic!("HOLY FUCKING SHIT, DID WE PHASE 1!?"); Ok(()) diff --git a/crates/roast-vm-sys/src/lib.rs b/crates/roast-vm-sys/src/lib.rs index 06b359e..7b1f348 100644 --- a/crates/roast-vm-sys/src/lib.rs +++ b/crates/roast-vm-sys/src/lib.rs @@ -2,12 +2,14 @@ mod CDS; mod class; -mod memaccess; mod misc_unsafe; mod object; mod reflection; mod runtime; +mod scoped_memory_access; +mod signal; mod system; +mod thread; use jni::objects::{JClass, JObject, JString}; use jni::strings::JNIString; diff --git a/crates/roast-vm-sys/src/misc_unsafe.rs b/crates/roast-vm-sys/src/misc_unsafe.rs index 6300425..69c82f9 100644 --- a/crates/roast-vm-sys/src/misc_unsafe.rs +++ b/crates/roast-vm-sys/src/misc_unsafe.rs @@ -571,3 +571,42 @@ pub unsafe extern "system" fn Java_jdk_internal_misc_Unsafe_fullFence( ) { std::sync::atomic::fence(std::sync::atomic::Ordering::SeqCst); } + +#[unsafe(no_mangle)] +pub unsafe extern "system" fn Java_jdk_internal_misc_Unsafe_getLongVolatile( + env: *mut JNIEnv, + _unsafe_obj: jobject, + obj: jobject, + offset: jlong, +) -> jlong { + let thread = &*get_thread(env); + let reference = thread.gc.read().get(obj as u32); + + match reference { + ReferenceKind::ArrayReference(array_ref) => { + if let ArrayReference::Long(arr) = array_ref { + let guard = arr.lock(); + let index = (offset / 8) as usize; + guard.backing[index] + } else { + panic!("getLongVolatile on non-long array") + } + } + ReferenceKind::ObjectReference(obj_ref) => { + let key = thread + .vm + .safent + .read() + .resolve_field(offset) + .expect("unregistered field offset"); + let guard = obj_ref.lock(); + guard + .fields + .get(&key.field_name) + .unwrap() + .clone() + .try_into_jlong() + .unwrap() + } + } +} diff --git a/crates/roast-vm-sys/src/memaccess.rs b/crates/roast-vm-sys/src/scoped_memory_access.rs similarity index 100% rename from crates/roast-vm-sys/src/memaccess.rs rename to crates/roast-vm-sys/src/scoped_memory_access.rs diff --git a/crates/roast-vm-sys/src/signal.rs b/crates/roast-vm-sys/src/signal.rs new file mode 100644 index 0000000..62d9842 --- /dev/null +++ b/crates/roast-vm-sys/src/signal.rs @@ -0,0 +1,11 @@ +use jni::sys::{JNIEnv, jclass, jint, jlong}; +#[unsafe(no_mangle)] +unsafe extern "system" fn Java_jdk_internal_misc_Signal_handle0( + _env: *mut JNIEnv, + _cls: jclass, + _sig: jint, + _handler: jlong, +) -> jlong { + // Return 0 (SIG_DFL) - pretend no previous handler existed + 0 +} diff --git a/crates/roast-vm-sys/src/thread.rs b/crates/roast-vm-sys/src/thread.rs new file mode 100644 index 0000000..13791be --- /dev/null +++ b/crates/roast-vm-sys/src/thread.rs @@ -0,0 +1,22 @@ +use crate::get_thread; +use jni::sys::{JNIEnv, jclass, jint, jlong, jobject}; +use std::sync::atomic::Ordering; + +#[unsafe(no_mangle)] +unsafe extern "system" fn Java_java_lang_Thread_currentThread( + env: *mut JNIEnv, + _cls: jclass, +) -> jobject { + let thread = &*get_thread(env); + let thread_id_obj = thread.mirror.get().unwrap(); + *thread_id_obj as jobject +} + +#[unsafe(no_mangle)] +unsafe extern "system" fn Java_java_lang_Thread_getNextThreadIdOffset( + env: *mut JNIEnv, + _cls: jclass, +) -> jlong { + let thread = &*get_thread(env); + thread.vm.NEXT_ID.fetch_add(1, Ordering::Relaxed) as jlong +}