diff --git a/jimage/src/parse/mod.rs b/jimage/src/parse/mod.rs index 3c09be2..3a65e54 100644 --- a/jimage/src/parse/mod.rs +++ b/jimage/src/parse/mod.rs @@ -1,5 +1,6 @@ mod header; pub(crate) mod index; +#[cfg(test)] mod tests; use crate::error::Result; diff --git a/runtime/src/classpath/classloader.rs b/runtime/src/classpath/classloader.rs index 117caef..c2188af 100644 --- a/runtime/src/classpath/classloader.rs +++ b/runtime/src/classpath/classloader.rs @@ -137,7 +137,7 @@ impl ClassLoader { if let Some(mirror_class) = Self::lookup_class(sym!(java_lang_Class)) { // SAFETY: The only condition of `set_mirror` is that the class isn't in use yet. unsafe { - Class::set_mirror(mirror_class, class); + class.set_mirror(mirror_class); } } diff --git a/runtime/src/initialization.rs b/runtime/src/initialization.rs index e77961c..46f1e1c 100644 --- a/runtime/src/initialization.rs +++ b/runtime/src/initialization.rs @@ -1,12 +1,12 @@ use crate::class::Class; -use crate::classpath::classloader::ClassLoader; -use crate::native::jni::invocation_api::main_java_vm; -use crate::thread::JavaThread; - use crate::class_instance::ClassInstance; +use crate::classpath::classloader::ClassLoader; use crate::java_call; +use crate::native::jni::invocation_api::main_java_vm; use crate::reference::Reference; use crate::string_interner::StringInterner; +use crate::thread::JavaThread; + use classfile::accessflags::MethodAccessFlags; use classfile::FieldType; use common::int_types::s4; @@ -36,7 +36,7 @@ fn initialize_thread(thread: &mut JavaThread) { .fields() .find(|field| { !field.is_static() - && field.name == b"value" + && field.name == sym!(value) && matches!(field.descriptor, FieldType::Array(ref val) if **val == FieldType::Byte) }) .expect("java.lang.String should have a value field"); @@ -45,7 +45,7 @@ fn initialize_thread(thread: &mut JavaThread) { .fields() .find(|field| { field.is_final() - && field.name == b"coder" + && field.name == sym!(coder) && matches!(field.descriptor, FieldType::Byte) }) .expect("java.lang.String should have a value field"); @@ -159,8 +159,7 @@ fn create_thread_object(thread: &mut JavaThread) { /// * Thread group of the main thread fn init_phase_1(thread: &mut JavaThread) { let system_class = ClassLoader::Bootstrap.load(sym!(java_lang_System)).unwrap(); - let init_phase_1 = Class::resolve_method_step_two( - system_class, + let init_phase_1 = system_class.resolve_method_step_two( sym!(initPhase1_name), sym!(void_method_signature), ) @@ -181,8 +180,7 @@ fn init_phase_2(thread: &mut JavaThread) { let print_stacktrace_on_exception = true; // TODO: Need some way to check failure - let init_phase_2 = Class::resolve_method_step_two( - system_class, + let init_phase_2 = system_class.resolve_method_step_two( sym!(initPhase2_name), sym!(bool_bool_int_signature), ) @@ -210,8 +208,7 @@ fn init_phase_2(thread: &mut JavaThread) { fn init_phase_3(thread: &mut JavaThread) { let system_class = ClassLoader::Bootstrap.load(sym!(java_lang_System)).unwrap(); - let init_phase_3 = Class::resolve_method_step_two( - system_class, + let init_phase_3 = system_class.resolve_method_step_two( sym!(initPhase3_name), sym!(void_method_signature), ) diff --git a/runtime/src/interpreter.rs b/runtime/src/interpreter.rs index e6de1c1..188e225 100644 --- a/runtime/src/interpreter.rs +++ b/runtime/src/interpreter.rs @@ -762,7 +762,7 @@ impl Interpreter { let constant_pool = frame.constant_pool(); let constant = &constant_pool[idx]; - + // The run-time constant pool entry at index must be loadable (§5.1), match constant { // and not any of the following: @@ -935,18 +935,6 @@ impl Interpreter { } } - fn initialize_class_if_needed(classref: &'static Class, frame: &mut Frame) -> bool { - if classref.initialization_state() != ClassInitializationState::Uninit { - return false; - } - - // TODO: This is a hack - let _ = frame.thread().pc.fetch_sub(3, std::sync::atomic::Ordering::Relaxed); - - Class::initialize(&classref, frame.thread_mut()); - true - } - fn fetch_field(frame: &mut Frame, is_static: bool) -> Option<&'static Field> { let field_ref_idx = frame.read_byte2(); @@ -958,10 +946,9 @@ impl Interpreter { .load(Symbol::intern_bytes(class_name)) .unwrap(); - // If this is `None`, the class is initializing let ret = class.resolve_field(constant_pool, field_ref_idx); if ret.is_some() && is_static { - Self::initialize_class_if_needed(class, frame); + class.initialize(frame.thread_mut()); } ret @@ -976,9 +963,7 @@ impl Interpreter { let ret = class.resolve_method(frame.thread_mut(), method_ref_idx); if ret.is_some() && is_static { // On successful resolution of the method, the class or interface that declared the resolved method is initialized if that class or interface has not already been initialized - if Self::initialize_class_if_needed(class, frame) { - return None - } + class.initialize(frame.thread_mut()); } ret @@ -998,7 +983,7 @@ impl Interpreter { } // On successful resolution of the class, it is initialized if it has not already been initialized - Self::initialize_class_if_needed(class, frame); + class.initialize(frame.thread_mut()); ClassInstance::new(class) } diff --git a/runtime/src/native/java/io/FileDescriptor.rs b/runtime/src/native/java/io/FileDescriptor.rs index 5dba78a..86d13d0 100644 --- a/runtime/src/native/java/io/FileDescriptor.rs +++ b/runtime/src/native/java/io/FileDescriptor.rs @@ -41,18 +41,18 @@ pub fn initIDs(_: NonNull) { let mut fields = 0; for (index, field) in class.fields().enumerate() { - match &*field.name { - b"fd" => unsafe { + match field.name.as_str() { + "fd" => unsafe { assert!(fields & 1 << 3 == 0, "Field can only occur once"); *fd.get_mut() = index; fields |= 1 << 2; }, #[cfg(windows)] - b"handle" => unsafe { + "handle" => unsafe { *handle.get_mut() = index; fields |= 1 << 1; }, - b"append" => unsafe { + "append" => unsafe { *append.get_mut() = index; fields |= 1; }, diff --git a/runtime/src/native/java/io/FileInputStream.rs b/runtime/src/native/java/io/FileInputStream.rs index 130f7c7..bd109aa 100644 --- a/runtime/src/native/java/io/FileInputStream.rs +++ b/runtime/src/native/java/io/FileInputStream.rs @@ -80,7 +80,7 @@ pub fn initIDs(_: NonNull) { let mut field_set = false; for (index, field) in class.fields().enumerate() { - if field.name == b"fd" { + if field.name == sym!(fd) { unsafe { *fd.get_mut() = index; } diff --git a/runtime/src/native/java/lang/Throwable.rs b/runtime/src/native/java/lang/Throwable.rs index 2e3441f..8a312b7 100644 --- a/runtime/src/native/java/lang/Throwable.rs +++ b/runtime/src/native/java/lang/Throwable.rs @@ -26,6 +26,7 @@ mod stacktrace_element { use common::traits::PtrType; use instructions::Operand; + use symbols::sym; static mut INITIALIZED: Mutex = Mutex::new(false); @@ -43,59 +44,62 @@ mod stacktrace_element { return; } - StackTraceElement_classLoaderName_FIELD_OFFSET = class - .fields() - .find(|field| { - field.descriptor.is_class(b"java/lang/String") && field.name == b"classLoaderName" - }) - .expect("classLoaderName field should exist") - .idx; - - StackTraceElement_moduleName_FIELD_OFFSET = class - .fields() - .find(|field| { - field.descriptor.is_class(b"java/lang/String") && field.name == b"moduleName" - }) - .expect("moduleName field should exist") - .idx; - - StackTraceElement_moduleVersion_FIELD_OFFSET = class - .fields() - .find(|field| { - field.descriptor.is_class(b"java/lang/String") && field.name == b"moduleVersion" - }) - .expect("moduleVersion field should exist") - .idx; - - StackTraceElement_declaringClass_FIELD_OFFSET = class - .fields() - .find(|field| { - field.descriptor.is_class(b"java/lang/String") && field.name == b"declaringClass" - }) - .expect("declaringClass field should exist") - .idx; - - StackTraceElement_methodName_FIELD_OFFSET = class - .fields() - .find(|field| { - field.descriptor.is_class(b"java/lang/String") && field.name == b"methodName" - }) - .expect("methodName field should exist") - .idx; - - StackTraceElement_fileName_FIELD_OFFSET = class - .fields() - .find(|field| { - field.descriptor.is_class(b"java/lang/String") && field.name == b"fileName" - }) - .expect("fileName field should exist") - .idx; - - StackTraceElement_lineNumber_FIELD_OFFSET = class - .fields() - .find(|field| field.descriptor.is_int() && field.name == b"lineNumber") - .expect("lineNumber field should exist") - .idx; + let mut field_set = 0; + for field in class.fields() { + if field.name == sym!(classLoaderName) { + assert!(field.descriptor.is_class(b"java/lang/String")); + StackTraceElement_classLoaderName_FIELD_OFFSET = field.idx; + field_set |= 1; + continue; + } + + if field.name == sym!(moduleName) { + assert!(field.descriptor.is_class(b"java/lang/String")); + StackTraceElement_moduleName_FIELD_OFFSET = field.idx; + field_set |= 1 << 1; + continue; + } + + if field.name == sym!(moduleVersion) { + assert!(field.descriptor.is_class(b"java/lang/String")); + StackTraceElement_moduleVersion_FIELD_OFFSET = field.idx; + field_set |= 1 << 2; + continue; + } + + if field.name == sym!(declaringClass) { + assert!(field.descriptor.is_class(b"java/lang/String")); + StackTraceElement_declaringClass_FIELD_OFFSET = field.idx; + field_set |= 1 << 3; + continue; + } + + if field.name == sym!(methodName) { + assert!(field.descriptor.is_class(b"java/lang/String")); + StackTraceElement_methodName_FIELD_OFFSET = field.idx; + field_set |= 1 << 4; + continue; + } + + if field.name == sym!(fileName) { + assert!(field.descriptor.is_class(b"java/lang/String")); + StackTraceElement_fileName_FIELD_OFFSET = field.idx; + field_set |= 1 << 5; + continue; + } + + if field.name == sym!(lineNumber) { + assert!(field.descriptor.is_int()); + StackTraceElement_lineNumber_FIELD_OFFSET = field.idx; + field_set |= 1 << 6; + continue; + } + } + + assert_eq!( + field_set, 0b1111111, + "Not all fields were found in java/lang/StackTraceElement" + ); *initialized = true; } @@ -170,7 +174,7 @@ pub fn fillInStackTrace( let this_class = this_class_instance.get().class; // TODO: Make global field let stacktrace_field = this_class.fields().find(|field| { - field.name == b"stackTrace" && matches!(&field.descriptor, FieldType::Array(value) if value.is_class(b"java/lang/StackTraceElement")) + field.name.as_str() == "stackTrace" && matches!(&field.descriptor, FieldType::Array(value) if value.is_class(b"java/lang/StackTraceElement")) }).expect("Throwable should have a stackTrace field"); let stack_depth = current_thread.frame_stack().depth(); diff --git a/runtime/src/native/jdk/internal/misc/Unsafe.rs b/runtime/src/native/jdk/internal/misc/Unsafe.rs index 746bb9c..b2a169a 100644 --- a/runtime/src/native/jdk/internal/misc/Unsafe.rs +++ b/runtime/src/native/jdk/internal/misc/Unsafe.rs @@ -424,7 +424,7 @@ pub fn objectFieldOffset1( continue; } - if field.name == name_str.as_bytes() { + if field.name.as_str() == name_str { return (offset as jlong).into(); } @@ -467,7 +467,7 @@ pub fn ensureClassInitialized0( let target_class = mirror.get().expect_class(); match target_class.initialization_state() { - ClassInitializationState::Uninit => Class::initialize(&target_class, current_thread), + ClassInitializationState::Uninit => target_class.initialize(current_thread), ClassInitializationState::InProgress | ClassInitializationState::Init => {}, // TODO: Is this the best we can do? ClassInitializationState::Failed => unreachable!("Failed to ensure class initialization"), diff --git a/runtime/src/objects/class/mod.rs b/runtime/src/objects/class/mod.rs index 6f6c87f..77518a8 100644 --- a/runtime/src/objects/class/mod.rs +++ b/runtime/src/objects/class/mod.rs @@ -8,9 +8,10 @@ use super::vtable::VTable; use crate::classpath::classloader::ClassLoader; use crate::globals::PRIMITIVES; use crate::reference::{MirrorInstanceRef, Reference}; +use crate::thread::JavaThread; use spec::InitializationLock; -use std::cell::UnsafeCell; +use std::cell::{Cell, UnsafeCell}; use std::fmt::{Debug, Formatter}; use std::mem::MaybeUninit; use std::sync::Arc; @@ -31,7 +32,7 @@ struct MiscCache { struct FieldContainer { /// A list of all fields, including static - fields: UnsafeCell>, + fields: UnsafeCell>, /// All static field slots /// /// This needs to be scaled to the `fields` field, in that index 0 of this array relates @@ -47,20 +48,17 @@ impl FieldContainer { /// Used as the field container for arrays, as they have no instance fields. fn null() -> Self { Self { - fields: UnsafeCell::new(Vec::new()), + fields: UnsafeCell::new(box_slice![]), static_field_slots: box_slice![], instance_field_count: UnsafeCell::new(0), } } - fn new( - static_field_slots: Box<[UnsafeCell>]>, - instance_field_count: u4, - ) -> Self { + fn new(static_field_slots: Box<[UnsafeCell>]>) -> Self { Self { - fields: UnsafeCell::new(Vec::new()), + fields: UnsafeCell::new(box_slice![]), static_field_slots, - instance_field_count: UnsafeCell::new(instance_field_count), + instance_field_count: UnsafeCell::new(0), } } @@ -70,10 +68,10 @@ impl FieldContainer { } // This is only ever used in class loading - fn set_fields(&self, fields: Vec<&'static Field>) { - unsafe { - *self.fields.get() = fields; - } + fn set_fields(&self, new: Vec<&'static Field>) { + let fields = self.fields.get(); + let old = core::mem::replace(unsafe { &mut *fields }, new.into_boxed_slice()); + drop(old); } /// # SAFETY @@ -117,6 +115,9 @@ pub struct Class { pub(super) class_ty: ClassType, init_lock: Arc, + + // Used for fast path, initialization checks are needed for multiple instructions + is_initialized: Cell, } // SAFETY: Any pointer writes require synchronization @@ -464,10 +465,10 @@ impl Class { .iter() .filter(|field| field.access_flags.is_static()) .count(); - let mut instance_field_count = 0; + let mut super_instance_field_count = 0; if let Some(ref super_class) = super_class { - instance_field_count = super_class.field_container.instance_field_count(); + super_instance_field_count = super_class.field_container.instance_field_count(); } let interfaces = parsed_file @@ -496,10 +497,11 @@ impl Class { interfaces, misc_cache: UnsafeCell::new(MiscCache::default()), mirror: UnsafeCell::new(MaybeUninit::uninit()), // Set later - field_container: FieldContainer::new(static_field_slots, instance_field_count), + field_container: FieldContainer::new(static_field_slots), vtable: UnsafeCell::new(MaybeUninit::uninit()), // Set later class_ty: ClassType::Instance(class_instance), init_lock: Arc::new(InitializationLock::new()), + is_initialized: Cell::new(false), }; let class: &'static mut Class = Box::leak(Box::new(class)); @@ -512,20 +514,18 @@ impl Class { // Then the fields... let mut fields = - Vec::with_capacity(instance_field_count as usize + parsed_file.fields.len()); + Vec::with_capacity(super_instance_field_count as usize + parsed_file.fields.len()); if let Some(ref super_class) = class.super_class { // First we have to inherit the super classes' fields - for field in super_class.fields() { - if !field.is_static() { - fields.push(field); - } + for field in super_class.instance_fields() { + fields.push(field); } } // Now the fields defined in our class let mut static_idx = 0; // Continue the index from our existing instance fields - let mut instance_field_idx = core::cmp::max(0, instance_field_count) as usize; + let mut instance_field_idx = core::cmp::max(0, super_instance_field_count) as usize; let constant_pool = class .constant_pool() .expect("we just set the constant pool"); @@ -540,19 +540,14 @@ impl Class { *field_idx += 1; } + class.field_container.set_fields(fields); // Update the instance field count if we encountered any new ones if instance_field_idx > 0 { - if instance_field_count > 0 { - class - .field_container - .set_instance_field_count(instance_field_count + instance_field_idx as u4); - } else { - class - .field_container - .set_instance_field_count(instance_field_idx as u4); - } + class + .field_container + .set_instance_field_count(instance_field_idx as u4); } class @@ -600,6 +595,7 @@ impl Class { vtable: UnsafeCell::new(MaybeUninit::uninit()), // Set later class_ty: ClassType::Array(array_instance), init_lock: Arc::new(InitializationLock::new()), + is_initialized: Cell::new(false), }; let class: &'static mut Class = Box::leak(Box::new(class)); @@ -624,6 +620,15 @@ impl Class { _guard.initialization_state() } + pub fn initialize(&self, thread: &mut JavaThread) { + if self.is_initialized.get() { + return; + } + + self.initialization(thread); + self.is_initialized.set(true); + } + /// Set the mirror for this class /// /// # Safety diff --git a/runtime/src/objects/class/spec.rs b/runtime/src/objects/class/spec.rs index a20c91f..cee620f 100644 --- a/runtime/src/objects/class/spec.rs +++ b/runtime/src/objects/class/spec.rs @@ -161,7 +161,7 @@ impl Class { // 1. If C declares a field with the name and descriptor specified by the field reference, // field lookup succeeds. The declared field is the result of the field lookup. for field in self.fields() { - if field.name == field_name && field.descriptor == field_type { + if field.name.as_bytes() == field_name && field.descriptor == field_type { return Some(field); } } @@ -219,7 +219,7 @@ impl Class { } // 2. Otherwise, method resolution attempts to locate the referenced method in C and its superclasses: - if let ret @ Some(_) = Class::resolve_method_step_two(class, method_name, descriptor) { + if let ret @ Some(_) = class.resolve_method_step_two(method_name, descriptor) { return ret; } @@ -266,7 +266,7 @@ impl Class { // 2.3. Otherwise, if C has a superclass, step 2 of method resolution is recursively invoked on the direct superclass of C. if let Some(super_class) = self.super_class { if let Some(resolved_method) = - Class::resolve_method_step_two(super_class, method_name, descriptor) + super_class.resolve_method_step_two(method_name, descriptor) { return Some(&resolved_method); } @@ -366,13 +366,13 @@ impl Class { reason = "We have no way of checking of the executed successfully yet" )] #[tracing::instrument(skip_all)] - pub fn initialize(&self, thread: &mut JavaThread) { + pub fn initialization(&self, thread: &mut JavaThread) { // 1. Synchronize on the initialization lock, LC, for C. This involves waiting until the current thread can acquire LC. let init = self.initialization_lock(); let mut guard = init.lock(); // 2. If the Class object for C indicates that initialization is in progress for C by some other thread - if self.initialization_state() == ClassInitializationState::InProgress + if guard.initialization_state() == ClassInitializationState::InProgress && !guard.is_initialized_by(thread) { // then release LC and block the current thread until informed that the in-progress initialization @@ -382,23 +382,22 @@ impl Class { // 3. If the Class object for C indicates that initialization is in progress for C by the current thread, // then this must be a recursive request for initialization. Release LC and complete normally. - if self.initialization_state() == ClassInitializationState::InProgress + if guard.initialization_state() == ClassInitializationState::InProgress && guard.is_initialized_by(thread) { - panic!(); return; } // 4. If the Class object for C indicates that C has already been initialized, then no further action // is required. Release LC and complete normally. - if self.initialization_state() == ClassInitializationState::Init { + if guard.initialization_state() == ClassInitializationState::Init { return; } // TODO: // 5. If the Class object for C is in an erroneous state, then initialization is not possible. // Release LC and throw a NoClassDefFoundError. - if self.initialization_state() == ClassInitializationState::Failed { + if guard.initialization_state() == ClassInitializationState::Failed { panic!("NoClassDefFoundError"); } @@ -479,7 +478,7 @@ impl Class { // entire procedure for S. If necessary, verify and prepare S first. if !self.is_interface() { if let Some(super_class) = &self.super_class { - Class::initialize(super_class, thread); + super_class.initialize(thread); } for interface in &self.interfaces { @@ -488,7 +487,7 @@ impl Class { .iter() .any(|method| !method.is_abstract() && !method.is_static()) { - Class::initialize(interface, thread); + interface.initialize(thread); } } @@ -558,7 +557,7 @@ impl Class { // https://docs.oracle.com/javase/specs/jvms/se19/html/jvms-2.html#jvms-2.9.2 #[rustfmt::skip] #[tracing::instrument(skip_all)] - pub fn clinit(&self, thread: &mut JavaThread) { + fn clinit(&self, thread: &mut JavaThread) { // A class or interface has at most one class or interface initialization method and is initialized // by the Java Virtual Machine invoking that method (§5.5). diff --git a/runtime/src/objects/field.rs b/runtime/src/objects/field.rs index a761c22..7f29e98 100644 --- a/runtime/src/objects/field.rs +++ b/runtime/src/objects/field.rs @@ -5,20 +5,34 @@ use std::fmt::{Debug, Formatter}; use classfile::accessflags::FieldAccessFlags; use classfile::{ConstantPool, FieldInfo, FieldType}; -use common::int_types::{u1, u2}; +use common::int_types::u2; use instructions::Operand; +use symbols::Symbol; +// TODO: Make more fields private #[derive(Clone, PartialEq)] pub struct Field { pub idx: usize, // Used to set the value on `ClassInstance`s pub class: &'static Class, pub access_flags: FieldAccessFlags, - pub name: Vec, + pub name: Symbol, pub descriptor: FieldType, pub constant_value_index: Option, // TODO } +impl Debug for Field { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}#{} (index: {})", + self.class.name.as_str(), + self.name.as_str(), + self.idx + ) + } +} + impl Field { /// Create a new `Field` instance /// @@ -33,7 +47,8 @@ impl Field { let access_flags = field_info.access_flags; let name_index = field_info.name_index; - let name = constant_pool.get_constant_utf8(name_index).to_vec(); + let name_bytes = constant_pool.get_constant_utf8(name_index); + let name = Symbol::intern_bytes(name_bytes); let descriptor_index = field_info.descriptor_index; let mut descriptor_bytes = constant_pool.get_constant_utf8(descriptor_index); @@ -89,18 +104,3 @@ impl Field { } } } - -impl Debug for Field { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - f.debug_struct("Field") - .field("idx", &self.idx) - .field("class", &self.class) - .field("access_flags", &self.access_flags) - .field("name", &unsafe { - std::str::from_utf8_unchecked(&self.name) - }) - .field("descriptor", &self.descriptor) - .field("constant_value_index", &self.constant_value_index) - .finish() - } -} diff --git a/runtime/src/thread.rs b/runtime/src/thread.rs index eebcf2b..7dc0a68 100644 --- a/runtime/src/thread.rs +++ b/runtime/src/thread.rs @@ -42,12 +42,19 @@ impl StackFrame { } } -#[derive(Debug, Default)] +#[derive(Debug)] pub struct FrameStack { inner: Vec, } impl FrameStack { + // TODO + fn new() -> Self { + FrameStack { + inner: Vec::with_capacity(1024), + } + } + fn current(&mut self) -> Option<&mut Frame> { let current_frame = self.inner.last_mut(); match current_frame { @@ -217,7 +224,7 @@ impl JavaThread { .filter(|field| !field.is_static()) .enumerate() { - if field.name == b"holder" { + if field.name == sym!(holder) { unsafe { crate::globals::field_offsets::set_thread_holder_field_offset(index); } @@ -229,14 +236,14 @@ impl JavaThread { { let class = crate::globals::classes::java_lang_Thread_FieldHolder(); for (index, field) in class.static_fields().enumerate() { - match &*field.name { - b"priority" => unsafe { + match field.name.as_str() { + "priority" => unsafe { crate::globals::field_offsets::set_field_holder_priority_field_offset(index) }, - b"daemon" => unsafe { + "daemon" => unsafe { crate::globals::field_offsets::set_field_holder_daemon_field_offset(index) }, - b"threadStatus" => unsafe { + "threadStatus" => unsafe { crate::globals::field_offsets::set_field_holder_thread_status_field_offset( index, ) @@ -282,7 +289,7 @@ impl JavaThread { obj: None, pc: AtomicIsize::new(0), - frame_stack: FrameStack::default(), + frame_stack: FrameStack::new(), remaining_operand: None, } } diff --git a/symbols/src/lib.rs b/symbols/src/lib.rs index ce37d36..9610d26 100644 --- a/symbols/src/lib.rs +++ b/symbols/src/lib.rs @@ -65,6 +65,26 @@ impl SymbolInterner { #[repr(transparent)] pub struct Symbol(u32); +impl Symbol { + /// Access the actual string associated with this symbol + pub fn as_str(&self) -> &'static str { + let guard = INTERNER.lock().unwrap(); + unsafe { std::str::from_utf8_unchecked(guard.get(*self)) } + } + + /// Access the byte string associated with this symbol + pub fn as_bytes(&self) -> &'static [u8] { + let guard = INTERNER.lock().unwrap(); + guard.get(*self) + } + + /// Access the `u32` representation of this symbol + #[inline] + pub fn as_u32(&self) -> u32 { + self.0 + } +} + impl Symbol { /// The maximum number of bits that a pre-interned symbol ID can occupy /// @@ -104,18 +124,6 @@ impl Symbol { let mut guard = INTERNER.lock().unwrap(); guard.intern(bytes) } - - /// Access the actual string associated with this symbol - pub fn as_str(&self) -> &'static str { - let guard = INTERNER.lock().unwrap(); - unsafe { std::str::from_utf8_unchecked(guard.get(*self)) } - } - - /// Access the `u32` representation of this symbol - #[inline] - pub fn as_u32(&self) -> u32 { - self.0 - } } /// Gets a generated symbol using the names defined in `vm_symbols::define_symbols!` @@ -190,4 +198,17 @@ vm_symbols::define_symbols! { printStackTrace_name: "printStackTrace", findNative_name: "findNative", // -- GENERATED METHOD NAME MARKER, DO NOT DELETE -- + + // Fields + holder: "holder", + value: "value", + coder: "coder", + fd: "fd", + classLoaderName: "classLoaderName", + moduleName: "moduleName", + moduleVersion: "moduleVersion", + declaringClass: "declaringClass", + methodName: "methodName", + fileName: "fileName", + lineNumber: "lineNumber", }