Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
Serial-ATA committed Nov 29, 2024
1 parent e32a6be commit 82b0ff5
Show file tree
Hide file tree
Showing 13 changed files with 192 additions and 173 deletions.
1 change: 1 addition & 0 deletions jimage/src/parse/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod header;
pub(crate) mod index;
#[cfg(test)]
mod tests;

use crate::error::Result;
Expand Down
2 changes: 1 addition & 1 deletion runtime/src/classpath/classloader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down
21 changes: 9 additions & 12 deletions runtime/src/initialization.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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");
Expand All @@ -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");
Expand Down Expand Up @@ -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),
)
Expand All @@ -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),
)
Expand Down Expand Up @@ -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),
)
Expand Down
23 changes: 4 additions & 19 deletions runtime/src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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();

Expand All @@ -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
Expand All @@ -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
Expand All @@ -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)
}
Expand Down
8 changes: 4 additions & 4 deletions runtime/src/native/java/io/FileDescriptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,18 @@ pub fn initIDs(_: NonNull<JniEnv>) {

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;
},
Expand Down
2 changes: 1 addition & 1 deletion runtime/src/native/java/io/FileInputStream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ pub fn initIDs(_: NonNull<JniEnv>) {

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;
}
Expand Down
112 changes: 58 additions & 54 deletions runtime/src/native/java/lang/Throwable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ mod stacktrace_element {

use common::traits::PtrType;
use instructions::Operand;
use symbols::sym;

static mut INITIALIZED: Mutex<bool> = Mutex::new(false);

Expand All @@ -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;
}
Expand Down Expand Up @@ -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();
Expand Down
4 changes: 2 additions & 2 deletions runtime/src/native/jdk/internal/misc/Unsafe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}

Expand Down Expand Up @@ -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"),
Expand Down
Loading

0 comments on commit 82b0ff5

Please sign in to comment.