Add thread operations and improve thread initialization logic

This commit is contained in:
james 2025-12-19 05:50:28 +10:30
parent 1ed50300c4
commit 94f43066f9
No known key found for this signature in database
GPG Key ID: E1FFBA228F4CAD87
8 changed files with 161 additions and 7 deletions

View File

@ -522,4 +522,54 @@ impl ObjectManager {
} }
constructor_object constructor_object
} }
pub fn new_thread_group(
&mut self,
thread_group_class: Arc<RuntimeClass>,
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<RuntimeClass>,
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<RuntimeClass>,
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
}
} }

View File

@ -22,8 +22,8 @@ use std::cell::RefCell;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::ops::{Add, Deref}; use std::ops::{Add, Deref};
use std::ptr::null_mut; use std::ptr::null_mut;
use std::sync::Arc;
use std::sync::atomic::{AtomicU64, Ordering}; use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::{Arc, OnceLock};
use std::thread; use std::thread;
use std::vec::IntoIter; use std::vec::IntoIter;
@ -46,12 +46,12 @@ pub struct VmThread {
pub frame_stack: Mutex<Vec<Frame>>, pub frame_stack: Mutex<Vec<Frame>>,
pub gc: Arc<RwLock<ObjectManager>>, pub gc: Arc<RwLock<ObjectManager>>,
pub jni_env: JNIEnv, pub jni_env: JNIEnv,
pub mirror: OnceLock<u32>,
} }
impl VmThread { impl VmThread {
pub fn new(vm: Arc<Vm>, loader: Option<LoaderRef>) -> Arc<Self> { pub fn new(vm: Arc<Vm>, loader: Option<LoaderRef>) -> Arc<Self> {
static NEXT_ID: AtomicU64 = AtomicU64::new(0); let id = ThreadId(vm.NEXT_ID.fetch_add(1, Ordering::SeqCst));
let id = ThreadId(NEXT_ID.fetch_add(1, Ordering::SeqCst));
let loader = loader.unwrap_or(vm.loader.clone()); let loader = loader.unwrap_or(vm.loader.clone());
let gc = vm.gc.clone(); let gc = vm.gc.clone();
@ -64,6 +64,7 @@ impl VmThread {
frame_stack: Default::default(), frame_stack: Default::default(),
gc, gc,
jni_env, jni_env,
mirror: Default::default(),
} }
}) })
} }
@ -286,7 +287,7 @@ impl VmThread {
} }
pub fn invoke(&self, method_reference: MethodRef, args: Vec<Value>) -> MethodCallResult { pub fn invoke(&self, method_reference: MethodRef, args: Vec<Value>) -> MethodCallResult {
if self.gc.read().objects.len() > 2230 { if self.gc.read().objects.len() > 2235 {
INIT_LOGGER.call_once(|| { INIT_LOGGER.call_once(|| {
env_logger::Builder::from_default_env() env_logger::Builder::from_default_env()
.filter_level(LevelFilter::Trace) .filter_level(LevelFilter::Trace)
@ -320,9 +321,9 @@ impl VmThread {
pub fn invoke_native(&self, method: &MethodRef, mut args: Vec<Value>) -> MethodCallResult { pub fn invoke_native(&self, method: &MethodRef, mut args: Vec<Value>) -> MethodCallResult {
let symbol_name = generate_jni_method_name(method, false); 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( 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) gc.get_interned_string(utf)
.unwrap_or_else(|| gc.new_string(byte_array_class, string_class, 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();
}
} }

View File

@ -21,6 +21,7 @@ use imp::Library;
use log::trace; use log::trace;
use parking_lot::{Mutex, RwLock}; use parking_lot::{Mutex, RwLock};
use std::sync::Arc; use std::sync::Arc;
use std::sync::atomic::AtomicU64;
type NativeLibraries = Arc<RwLock<Vec<(String, Library)>>>; type NativeLibraries = Arc<RwLock<Vec<(String, Library)>>>;
@ -34,6 +35,7 @@ pub struct Vm {
pub native_libraries: NativeLibraries, pub native_libraries: NativeLibraries,
pub gc: Arc<RwLock<ObjectManager>>, pub gc: Arc<RwLock<ObjectManager>>,
pub safent: RwLock<UnsafeSupport>, pub safent: RwLock<UnsafeSupport>,
pub NEXT_ID: AtomicU64,
} }
impl Vm { impl Vm {
@ -47,6 +49,7 @@ impl Vm {
native_libraries: Arc::new(RwLock::new(Vec::new())), native_libraries: Arc::new(RwLock::new(Vec::new())),
gc: Default::default(), gc: Default::default(),
safent: Default::default(), safent: Default::default(),
NEXT_ID: AtomicU64::new(0),
}); });
// Create main thread // Create main thread
@ -160,6 +163,10 @@ impl Vm {
name: "initPhase1".to_string(), name: "initPhase1".to_string(),
desc: MethodDescriptor::void(), desc: MethodDescriptor::void(),
}; };
self.threads
.get(&self.main_thread_id)
.unwrap()
.bootstrap_mirror();
thread.invoke(phase1ref, Vec::new())?; thread.invoke(phase1ref, Vec::new())?;
panic!("HOLY FUCKING SHIT, DID WE PHASE 1!?"); panic!("HOLY FUCKING SHIT, DID WE PHASE 1!?");
Ok(()) Ok(())

View File

@ -2,12 +2,14 @@
mod CDS; mod CDS;
mod class; mod class;
mod memaccess;
mod misc_unsafe; mod misc_unsafe;
mod object; mod object;
mod reflection; mod reflection;
mod runtime; mod runtime;
mod scoped_memory_access;
mod signal;
mod system; mod system;
mod thread;
use jni::objects::{JClass, JObject, JString}; use jni::objects::{JClass, JObject, JString};
use jni::strings::JNIString; use jni::strings::JNIString;

View File

@ -571,3 +571,42 @@ pub unsafe extern "system" fn Java_jdk_internal_misc_Unsafe_fullFence(
) { ) {
std::sync::atomic::fence(std::sync::atomic::Ordering::SeqCst); 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()
}
}
}

View File

@ -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
}

View File

@ -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
}