Optimize imports, remove println/debug statements, update type handling, and format code

This commit is contained in:
james 2025-12-18 17:01:01 +10:30
parent a6f6507a85
commit 025e6633be
No known key found for this signature in database
GPG Key ID: E1FFBA228F4CAD87
14 changed files with 57 additions and 96 deletions

View File

@ -33,7 +33,6 @@
<option name="SOFT_MARGINS" value="100" /> <option name="SOFT_MARGINS" value="100" />
<indentOptions> <indentOptions>
<option name="USE_TAB_CHARACTER" value="true" /> <option name="USE_TAB_CHARACTER" value="true" />
<option name="SMART_TABS" value="true" />
</indentOptions> </indentOptions>
</codeStyleSettings> </codeStyleSettings>
<codeStyleSettings language="TOML"> <codeStyleSettings language="TOML">

View File

@ -1,6 +1,6 @@
[workspace] [workspace]
members = [ members = [
"crates/*" "crates/*"
] ]
resolver = "3" resolver = "3"
@ -10,13 +10,17 @@ deku_derive = "0.20.0"
log = "0.4.28" log = "0.4.28"
env_logger = "0.11.8" env_logger = "0.11.8"
itertools = "0.14.0" itertools = "0.14.0"
indexmap = "2.12.1"
sevenz-rust2 = { version = "0.19.3", features = ["brotli", "zstd"] } sevenz-rust2 = { version = "0.19.3", features = ["brotli", "zstd"] }
dashmap = "7.0.0-rc2" dashmap = "7.0.0-rc2"
libloading = "0.8.9" libloading = "0.8.9"
libffi = "5.0.0" libffi = "5.0.0"
jni = "0.21.1" jni = "0.21.1"
roast-vm-sys = { path = "crates/roast-vm-sys", version = "0.1.0" } roast-vm-sys = { path = "crates/roast-vm-sys" }
roast-vm-core = { path = "crates/core", version = "0.1.0" } roast-vm-core = { path = "crates/core" }
colored = "3.0.0"
parking_lot = "0.12"
cesu8 = "1.1.0"
[profile.dev-opt] [profile.dev-opt]
inherits = "dev" inherits = "dev"

View File

@ -1,6 +1,6 @@
[package] [package]
name = "roast-vm-core" name = "roast-vm-core"
version = "0.1.0" version = "0.1.5"
edition = "2024" edition = "2024"
publish = ["nexus"] publish = ["nexus"]
@ -15,15 +15,11 @@ libloading = { workspace = true }
libffi = { workspace = true } libffi = { workspace = true }
jni = { workspace = true } jni = { workspace = true }
itertools = { workspace = true } itertools = { workspace = true }
colored = "3.0.0" colored = { workspace = true }
parking_lot = "0.12" parking_lot = { workspace = true }
cesu8 = "1.1.0" cesu8 = { workspace = true }
[build-dependencies]
bindgen = "0.72.1"
[lints.rust]
#missing_docs = "warn"
[[bin]] [[bin]]
name = "roast" name = "roast"

View File

@ -196,15 +196,7 @@ impl ClassLoader {
.bimage .bimage
.get_class(module, class_fqn) .get_class(module, class_fqn)
.or_else(|e| Self::load_class_from_disk(what)) .or_else(|e| Self::load_class_from_disk(what))
.map_err(|e1| { .map_err(|e1| VmError::LoaderError(format!("failed to find class: {}", what)))?;
let classes = self
.classes
.iter()
.map(|x| x.this_class.clone())
.collect::<Vec<_>>();
// println!("{:#?}", classes);
VmError::LoaderError(format!("failed to find class: {:?}\n{:#?}", what, classes))
})?;
let (_, cf) = let (_, cf) =
ClassFile::from_bytes((bytes.as_ref(), 0)).map_err(|e| VmError::DekuError(e))?; ClassFile::from_bytes((bytes.as_ref(), 0)).map_err(|e| VmError::DekuError(e))?;
let runtime = self.runtime_class(cf); let runtime = self.runtime_class(cf);

View File

@ -4,15 +4,15 @@ use crate::class_file::constant_pool::{ConstantPoolExt, ConstantPoolGet};
use crate::class_file::{Bytecode, ConstantPoolEntry, MethodRef}; use crate::class_file::{Bytecode, ConstantPoolEntry, MethodRef};
use crate::error::{StackTraceElement, VmError}; use crate::error::{StackTraceElement, VmError};
use crate::instructions::{Ops, WideData}; use crate::instructions::{Ops, WideData};
use crate::objects::array::ArrayReference;
use crate::objects::ReferenceKind; use crate::objects::ReferenceKind;
use crate::objects::array::ArrayReference;
use crate::prim::*; use crate::prim::*;
use crate::value::{LocalVariables, OperandStack, Primitive, Value}; use crate::value::{LocalVariables, OperandStack, Primitive, Value};
use crate::vm::Vm; use crate::vm::Vm;
use crate::{ use crate::{
array_store, array_store_cast, binary_op, convert_float_to_int, convert_int_narrow, BaseType, FieldType, VmThread, array_store, array_store_cast, binary_op, convert_float_to_int,
convert_simple, error, float_cmp, if_int_cmp, if_int_zero, int_div_rem, load, shift_op, store, convert_int_narrow, convert_simple, error, float_cmp, if_int_cmp, if_int_zero, int_div_rem,
unary_op, BaseType, FieldType, VmThread, load, shift_op, store, unary_op,
}; };
use deku::DekuContainerRead; use deku::DekuContainerRead;
use log::{info, trace, warn}; use log::{info, trace, warn};
@ -134,19 +134,10 @@ impl Frame {
line_number_table, line_number_table,
} }
} }
pub(crate) fn execute(&mut self) -> Result<Option<Value>, error::VmError> { pub(crate) fn execute(&mut self) -> Result<Option<Value>, VmError> {
// todo remove
if self.method_ref.name.eq("<clinit>") {
if self.class.this_class.contains("IBM437") {
println!("[DEBUG] START");
}
}
let binding = self.bytecode.code.clone();
loop { loop {
let (offset, op) = self.next().expect("No ops :("); let (offset, op) = self.next().unwrap();
// trace!("pre set: {}", self.pc);
self.pc = offset as i64; self.pc = offset as i64;
// trace!("post set: {}", self.pc);
trace!("Executing Op: {:?}", op); trace!("Executing Op: {:?}", op);
let result = self.execute_instruction(op.clone()); let result = self.execute_instruction(op.clone());
match result { match result {
@ -988,7 +979,7 @@ impl Frame {
_ => { _ => {
return Err(VmError::InvariantError( return Err(VmError::InvariantError(
"ireturn requires integer-compatible value".to_owned(), "ireturn requires integer-compatible value".to_owned(),
)) ));
} }
}; };
@ -1346,7 +1337,6 @@ impl Frame {
Ops::wide(data) => match data { Ops::wide(data) => match data {
WideData::iinc(idx, increment) => { WideData::iinc(idx, increment) => {
println!("index: {idx}, inc: {increment}");
let int = self.vars.get(idx as usize).clone().try_into_jint()?; let int = self.vars.get(idx as usize).clone().try_into_jint()?;
let new_val = int + increment as i32; let new_val = int + increment as i32;
self.vars.set(idx as usize, new_val.into()); self.vars.set(idx as usize, new_val.into());

View File

@ -24,7 +24,7 @@ fn run() {
// .filter_module("roast_vm_core::instructions", LevelFilter::Info) // .filter_module("roast_vm_core::instructions", LevelFilter::Info)
// .init(); // .init();
stack_used(); stack_used();
let vm = Vm::new(); let mut vm = Vm::new();
vm.load_native_library("roast_vm.dll", load("roast_vm.dll").into()); vm.load_native_library("roast_vm.dll", load("roast_vm.dll").into());
vm.load_native_library("jvm.dll", load("jvm.dll").into()); vm.load_native_library("jvm.dll", load("jvm.dll").into());
vm.load_native_library("java.dll", load("java.dll").into()); vm.load_native_library("java.dll", load("java.dll").into());

View File

@ -10,10 +10,10 @@ use crate::value::{Primitive, Value};
use crate::{BaseType, FieldType, MethodDescriptor}; use crate::{BaseType, FieldType, MethodDescriptor};
use itertools::Itertools; use itertools::Itertools;
use jni::sys::*; use jni::sys::*;
use jni::sys::{jclass, jint, jobject, JNINativeInterface_}; use jni::sys::{JNIEnv, jstring};
use jni::sys::{jstring, JNIEnv}; use jni::sys::{JNINativeInterface_, jclass, jint, jobject};
use log::{error, info, trace, warn}; use log::{error, info, trace, warn};
use std::ffi::{c_char, CStr, CString}; use std::ffi::{CStr, CString, c_char};
use std::ptr; use std::ptr;
use std::sync::Arc; use std::sync::Arc;
@ -318,7 +318,7 @@ unsafe extern "system" fn get_string_utfchars(
_ => return ptr::null(), _ => return ptr::null(),
}; };
let obj = obj_ref.lock(); let mut obj = obj_ref.lock();
let field_ref = FieldRef { let field_ref = FieldRef {
class: "java/lang/String".to_string(), class: "java/lang/String".to_string(),
name: "value".to_string(), name: "value".to_string(),
@ -1076,11 +1076,7 @@ unsafe extern "system" fn get_boolean_field(
}; };
let val = object.lock().get_field(&field_ref); let val = object.lock().get_field(&field_ref);
if let Value::Primitive(Primitive::Boolean(bool)) = val { if let Value::Primitive(Primitive::Boolean(bool)) = val {
if bool { if bool { JNI_TRUE } else { JNI_FALSE }
JNI_TRUE
} else {
JNI_FALSE
}
} else { } else {
JNI_FALSE JNI_FALSE
} }
@ -1457,11 +1453,7 @@ unsafe extern "system" fn get_static_boolean_field(
let field_again = class.find_field(&field_ref.name, &field_ref.desc).unwrap(); let field_again = class.find_field(&field_ref.name, &field_ref.desc).unwrap();
let val = field_again.value.lock().clone(); let val = field_again.value.lock().clone();
if let Some(Value::Primitive(Primitive::Boolean(bool))) = val { if let Some(Value::Primitive(Primitive::Boolean(bool))) = val {
if bool { if bool { JNI_TRUE } else { JNI_FALSE }
JNI_TRUE
} else {
JNI_FALSE
}
} else { } else {
JNI_FALSE JNI_FALSE
} }
@ -2147,9 +2139,7 @@ unsafe extern "system" fn get_string_utf_region(
) { ) {
trace!( trace!(
"get_string_utf_region: start={}, len={}, buf={:?}", "get_string_utf_region: start={}, len={}, buf={:?}",
start, start, len, buf
len,
buf
); );
let thread = &*get_thread(env); let thread = &*get_thread(env);
let string_obj = resolve_object(thread, str).unwrap(); let string_obj = resolve_object(thread, str).unwrap();

View File

@ -1,5 +1,4 @@
use crate::class_file::ConstantPoolEntry; use crate::class_file::ConstantPoolEntry;
use dashmap::DashMap;
use libloading::Library; use libloading::Library;
use std::collections::HashMap; use std::collections::HashMap;

View File

@ -6,17 +6,17 @@ use crate::objects::array::{
Array, ArrayReference, ArrayValue, ObjectArrayReference, PrimitiveArrayReference, Array, ArrayReference, ArrayValue, ObjectArrayReference, PrimitiveArrayReference,
}; };
use crate::objects::object::{ use crate::objects::object::{
string_from_bytes, Object, ObjectReference, Reference, ReferenceKind, Object, ObjectReference, Reference, ReferenceKind, string_from_bytes,
}; };
use crate::value::{Primitive, Value}; use crate::value::{Primitive, Value};
use crate::{objects, rng, ThreadId}; use crate::{ThreadId, objects, rng};
use dashmap::DashMap; use dashmap::DashMap;
use jni::sys::{jboolean, jbyte, jchar, jdouble, jfloat, jint, jlong, jshort}; use jni::sys::{jboolean, jbyte, jchar, jdouble, jfloat, jint, jlong, jshort};
use log::warn; use log::warn;
use parking_lot::{Condvar, Mutex}; use parking_lot::{Condvar, Mutex};
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::Arc; use std::sync::Arc;
use std::sync::atomic::{AtomicU32, Ordering};
#[derive(Default)] #[derive(Default)]
pub struct ObjectManager { pub struct ObjectManager {
@ -63,7 +63,7 @@ impl ObjectManager {
.iter() .iter()
.map(|(id, obj)| format!("id: {id} obj: {}", obj.class().this_class)) .map(|(id, obj)| format!("id: {id} obj: {}", obj.class().this_class))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
println!("next: {} all: \n{:#?}", next, key_pairs) eprintln!("next: {} all: \n{:#?}", next, key_pairs)
} }
assert!( assert!(
!self.objects.contains_key(&id), !self.objects.contains_key(&id),
@ -265,7 +265,7 @@ impl ObjectManager {
_ => { _ => {
return Err(VmError::InvariantError( return Err(VmError::InvariantError(
"String value field must be a byte array".to_string(), "String value field must be a byte array".to_string(),
)) ));
} }
}; };
@ -277,7 +277,7 @@ impl ObjectManager {
_ => { _ => {
return Err(VmError::InvariantError( return Err(VmError::InvariantError(
"String value must be a byte array".to_string(), "String value must be a byte array".to_string(),
)) ));
} }
}; };
Ok(string_from_bytes(&bytes)) Ok(string_from_bytes(&bytes))

View File

@ -8,13 +8,13 @@ use crate::objects::object::{ObjectReference, ReferenceKind};
use crate::objects::object_manager::ObjectManager; use crate::objects::object_manager::ObjectManager;
use crate::value::{Primitive, Value}; use crate::value::{Primitive, Value};
use crate::vm::Vm; use crate::vm::Vm;
use crate::{stack_used, BaseType, FieldType, MethodDescriptor, ThreadId}; use crate::{BaseType, FieldType, MethodDescriptor, ThreadId, stack_used};
use deku::DekuError::Incomplete; use deku::DekuError::Incomplete;
use itertools::Itertools; use itertools::Itertools;
use jni::sys::{jboolean, jbyte, jchar, jdouble, jfloat, jint, jlong, jobject, jshort, JNIEnv}; use jni::sys::{JNIEnv, jboolean, jbyte, jchar, jdouble, jfloat, jint, jlong, jobject, jshort};
use libffi::low::call; use libffi::low::call;
use libffi::middle::*; use libffi::middle::*;
use log::{info, trace, warn, LevelFilter}; use log::{LevelFilter, info, trace, warn};
use parking_lot::{Mutex, Once, ReentrantMutex, RwLock}; use parking_lot::{Mutex, Once, ReentrantMutex, RwLock};
use std::any::Any; use std::any::Any;
@ -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::atomic::{AtomicU64, Ordering};
use std::sync::Arc; use std::sync::Arc;
use std::sync::atomic::{AtomicU64, Ordering};
use std::thread; use std::thread;
use std::vec::IntoIter; use std::vec::IntoIter;
@ -286,7 +286,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() > 2210 { if self.gc.read().objects.len() > 2230 {
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)
@ -319,7 +319,6 @@ 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);
println!("Invoke native for native symbol: {:?}", &symbol_name);
// if symbol_name.contains("Java_jdk_internal_reflect_Reflection_getClassAccessFlags") { // if symbol_name.contains("Java_jdk_internal_reflect_Reflection_getClassAccessFlags") {
// return Err(VmError::Debug( // return Err(VmError::Debug(

View File

@ -1,5 +1,6 @@
#[cfg(libloading_docs)] #[cfg(libloading_docs)]
use super::os::unix as imp; use super::os::unix as imp;
use std::collections::HashMap;
use std::ffi::c_void; use std::ffi::c_void;
// the implementation used here doesn't matter particularly much... // the implementation used here doesn't matter particularly much...
#[cfg(all(not(libloading_docs), unix))] #[cfg(all(not(libloading_docs), unix))]
@ -21,6 +22,8 @@ use log::trace;
use parking_lot::{Mutex, RwLock}; use parking_lot::{Mutex, RwLock};
use std::sync::Arc; use std::sync::Arc;
type NativeLibraries = Arc<RwLock<Vec<(String, Library)>>>;
// struct AbstractObject<'a> {} // struct AbstractObject<'a> {}
pub struct Vm { pub struct Vm {
// Thread registry - maps ThreadId to VmThread // Thread registry - maps ThreadId to VmThread
@ -28,7 +31,7 @@ pub struct Vm {
pub main_thread_id: ThreadId, pub main_thread_id: ThreadId,
pub loader: Arc<Mutex<ClassLoader>>, pub loader: Arc<Mutex<ClassLoader>>,
pub native_methods: DashMap<String, *const c_void>, pub native_methods: DashMap<String, *const c_void>,
pub native_libraries: DashMap<String, Library>, pub native_libraries: NativeLibraries,
pub gc: Arc<RwLock<ObjectManager>>, pub gc: Arc<RwLock<ObjectManager>>,
pub safent: RwLock<UnsafeSupport>, pub safent: RwLock<UnsafeSupport>,
} }
@ -41,7 +44,7 @@ impl Vm {
main_thread_id: ThreadId(0), main_thread_id: ThreadId(0),
loader: Arc::new(Mutex::from(ClassLoader::default())), loader: Arc::new(Mutex::from(ClassLoader::default())),
native_methods: DashMap::new(), native_methods: DashMap::new(),
native_libraries: DashMap::new(), native_libraries: Arc::new(RwLock::new(Vec::new())),
gc: Default::default(), gc: Default::default(),
safent: Default::default(), safent: Default::default(),
}); });
@ -59,7 +62,7 @@ impl Vm {
} }
pub fn load_native_library(&self, name: &str, lib: Library) { pub fn load_native_library(&self, name: &str, lib: Library) {
self.native_libraries.insert(name.to_string(), lib); self.native_libraries.write().push((name.to_string(), lib));
} }
pub fn find_native_method(&self, name: &str) -> Option<*const c_void> { pub fn find_native_method(&self, name: &str) -> Option<*const c_void> {
@ -68,22 +71,13 @@ impl Vm {
return Some(registered.clone()); return Some(registered.clone());
} }
{ for (lib_name, lib) in self.native_libraries.read().iter() {
let lib = self.native_libraries.get("roast_vm.dll").unwrap();
let res = unsafe { lib.get::<unsafe extern "system" fn()>(name.as_bytes()) };
if res.is_ok() {
let symbol = res.unwrap();
let ptr = *symbol as *const c_void;
self.native_methods.insert(name.to_string(), ptr);
return Some(ptr);
}
}
for entry in self.native_libraries.iter() {
let (_lib_name, lib) = entry.pair();
let res = unsafe { lib.get::<unsafe extern "system" fn()>(name.as_bytes()) }; let res = unsafe { lib.get::<unsafe extern "system" fn()>(name.as_bytes()) };
if res.is_ok() { if res.is_ok() {
println!(
"Invoke native for native symbol: {} out of: {}",
&name, lib_name
);
let symbol = res.unwrap(); let symbol = res.unwrap();
let ptr = *symbol as *const c_void; let ptr = *symbol as *const c_void;
self.native_methods.insert(name.to_string(), ptr); self.native_methods.insert(name.to_string(), ptr);

View File

@ -1,13 +1,13 @@
[package] [package]
name = "roast-vm-sys" name = "roast-vm-sys"
version = "0.1.0" version = "0.1.5"
edition = "2024" edition = "2024"
publish = ["nexus"] publish = ["nexus"]
[dependencies] [dependencies]
jni = { workspace = true } jni = { workspace = true }
roast-vm-core = { workspace = true } roast-vm-core = { workspace = true }
log = "0.4.28" log = { workspace = true }
[lib] [lib]
name = "roast_vm" name = "roast_vm"

View File

@ -1,6 +1,6 @@
use crate::{get_thread, resolve_object}; use crate::{get_thread, resolve_object};
use jni::sys::{jboolean, jclass, jobject, JNI_TRUE}; use jni::sys::{JNI_TRUE, jboolean, jclass, jobject};
use jni::sys::{jint, JNIEnv}; use jni::sys::{JNIEnv, jint};
use jni::sys::{jobjectArray, jstring}; use jni::sys::{jobjectArray, jstring};
use log::trace; use log::trace;
use roast_vm_core::class_file::FieldRef; use roast_vm_core::class_file::FieldRef;
@ -78,7 +78,6 @@ pub unsafe extern "system" fn Java_java_lang_Class_forName0(
// Convert "java.lang.String" -> "java/lang/String" // Convert "java.lang.String" -> "java/lang/String"
let class_name = class_name.replace('.', "/"); let class_name = class_name.replace('.', "/");
println!("forName0: class name is : {}", class_name);
// Load the class // Load the class
let rtc = match thread.get_class(&class_name) { let rtc = match thread.get_class(&class_name) {
@ -93,7 +92,6 @@ pub unsafe extern "system" fn Java_java_lang_Class_forName0(
thread.ensure_initialised(&rtc).unwrap(); thread.ensure_initialised(&rtc).unwrap();
} }
println!("returning");
// Return the mirror // Return the mirror
*rtc.mirror.get().unwrap() as jclass *rtc.mirror.get().unwrap() as jclass
} }

View File

@ -1,10 +1,10 @@
use crate::{get_thread, resolve_array, resolve_object}; use crate::{get_thread, resolve_array, resolve_object};
use jni::sys::{jboolean, jclass, jint, jlong, jobject, jstring, JNIEnv, JNI_FALSE, JNI_TRUE}; use jni::sys::{JNI_FALSE, JNI_TRUE, JNIEnv, jboolean, jclass, jint, jlong, jobject, jstring};
use log::warn; use log::warn;
use roast_vm_core::native::r#unsafe::OffsetKind; use roast_vm_core::native::r#unsafe::OffsetKind;
use roast_vm_core::objects::ReferenceKind;
use roast_vm_core::objects::array::ArrayReference; use roast_vm_core::objects::array::ArrayReference;
use roast_vm_core::objects::object::string_from_bytes; use roast_vm_core::objects::object::string_from_bytes;
use roast_vm_core::objects::ReferenceKind;
use roast_vm_core::value::Value; use roast_vm_core::value::Value;
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
@ -13,7 +13,7 @@ pub unsafe extern "system" fn Java_jdk_internal_misc_Unsafe_registerNatives(
obj: jclass, obj: jclass,
) { ) {
//no op //no op
println!("Unsafe_registerNatives is NO OP") warn!("Unsafe_registerNatives is NO OP")
} }
#[unsafe(no_mangle)] #[unsafe(no_mangle)]