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
}
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::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<Vec<Frame>>,
pub gc: Arc<RwLock<ObjectManager>>,
pub jni_env: JNIEnv,
pub mirror: OnceLock<u32>,
}
impl VmThread {
pub fn new(vm: Arc<Vm>, loader: Option<LoaderRef>) -> Arc<Self> {
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<Value>) -> 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<Value>) -> 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();
}
}

View File

@ -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<RwLock<Vec<(String, Library)>>>;
@ -34,6 +35,7 @@ pub struct Vm {
pub native_libraries: NativeLibraries,
pub gc: Arc<RwLock<ObjectManager>>,
pub safent: RwLock<UnsafeSupport>,
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(())

View File

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

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);
}
#[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
}