Add thread operations and improve thread initialization logic
This commit is contained in:
parent
1ed50300c4
commit
94f43066f9
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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(())
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
11
crates/roast-vm-sys/src/signal.rs
Normal file
11
crates/roast-vm-sys/src/signal.rs
Normal 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
|
||||||
|
}
|
||||||
22
crates/roast-vm-sys/src/thread.rs
Normal file
22
crates/roast-vm-sys/src/thread.rs
Normal 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
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user