use crate::vm::error::{Error, Result};
use crate::vm::heap::heap::{with_heap_read_lock, with_heap_write_lock};
use crate::vm::method_area::method_area::with_method_area;
use crate::vm::system_native::method_handle_natives::member_name::{
set_reference_kind, MemberName,
};
use crate::vm::system_native::method_handle_natives::method_type::MethodType;
use crate::vm::system_native::method_handle_natives::resolved_method_name::ResolvedMethodName;
use crate::vm::system_native::method_handle_natives::types::ReferenceKind;
use crate::vm::system_native::method_handle_natives::types::ReferenceKind::*;
use jclassfile::methods::MethodFlags;
pub fn resolve(
member_name_ref: i32,
_caller_class_ref: i32,
_lookup_mode: i32,
_speculative_resolve: bool,
) -> Result<i32> {
let mut member_name = MemberName::new(member_name_ref)?;
let reference_kind = member_name.reference_kind();
match reference_kind {
REF_invokeVirtual | REF_invokeStatic | REF_invokeSpecial | REF_newInvokeSpecial
| REF_invokeInterface => resolve_method(&mut member_name),
REF_getField | REF_putField => Ok(member_name_ref),
REF_getStatic | REF_putStatic => resolve_static_field(&mut member_name),
}
}
fn resolve_method(member_name: &mut MemberName) -> Result<i32> {
let type_obj_ref = member_name.type_obj_ref();
let method_type = MethodType::new(type_obj_ref)?;
let method_name = member_name.name();
let ptype_names = method_type.ptype_names();
let rtype_name = method_type.rtype_name();
let full_method_signature = format!("{method_name}:{ptype_names}{rtype_name}");
let class_name = member_name.class_name();
let arc = with_method_area(|area| area.get(class_name))?;
let (method_index, method) = match arc.get_method_full(&full_method_signature) {
Some((method_index, method)) => (method_index, method),
None => {
return Ok(0); }
};
let current_flags = member_name.flags();
let flags_to_enrich_with = method.access_flags();
let enriched_flags = current_flags | flags_to_enrich_with;
member_name.propagate_flags(enriched_flags)?;
let this_class_name = arc.this_class_name();
let reflection_ref =
with_method_area(|method_area| method_area.load_reflection_class(this_class_name))?;
let resolved_method_name =
ResolvedMethodName::new_create_instance(reflection_ref, method_index as i64)?;
member_name.propagate_method(resolved_method_name)?;
Ok(member_name.member_name_ref())
}
fn resolve_static_field(member_name: &mut MemberName) -> Result<i32> {
let class_name = member_name.class_name();
let static_field_name = member_name.name();
let jc = with_method_area(|area| area.get(class_name))?;
let field_info = jc.field_info(static_field_name).ok_or_else(|| {
Error::new_execution(&format!(
"Static field not found: {class_name}:{static_field_name}"
))
})?;
let current_flags = member_name.flags();
let flags_to_enrich_with = field_info.flags() as i32;
let enriched_flags = current_flags | flags_to_enrich_with;
member_name.propagate_flags(enriched_flags)?;
Ok(member_name.member_name_ref())
}
pub(crate) fn member_name_init(member_name_ref: i32, obj_ref: i32) -> Result<()> {
const MN_IS_METHOD: i32 = 0x00010000; const MN_IS_CONSTRUCTOR: i32 = 0x00020000;
let obj_name = with_heap_read_lock(|heap| heap.get_instance_name(obj_ref))?;
match obj_name.as_str() {
"java/lang/reflect/Method" => {
let modifiers = with_heap_read_lock(|h| {
h.get_object_field_value(obj_ref, obj_name.as_str(), "modifiers")
})?[0];
let method_flags = MethodFlags::from_bits_truncate(modifiers as u16);
let kind = if method_flags.contains(MethodFlags::ACC_STATIC) {
REF_invokeStatic
} else {
todo!("member_name_init: Handle non-static method resolution")
};
init_from_method_or_constructor(member_name_ref, obj_ref, kind, MN_IS_METHOD)?;
}
"java/lang/reflect/Constructor" => {
init_from_method_or_constructor(
member_name_ref,
obj_ref,
REF_newInvokeSpecial,
MN_IS_CONSTRUCTOR,
)?;
}
"java/lang/reflect/Field" => {
todo!("Implement from Field initialization logic")
}
_ => {
return Err(Error::new_execution(&format!(
"method_handle_natives_init_wrp: Unsupported object type: {obj_name}"
)));
}
}
Ok(())
}
fn init_from_method_or_constructor(
member_name_ref: i32,
obj_ref: i32,
kind: ReferenceKind,
internal_flag: i32,
) -> Result<()> {
let obj_name = with_heap_read_lock(|heap| heap.get_instance_name(obj_ref))?;
let (clazz_ref, modifiers, slot) = with_heap_read_lock(|h| {
let clazz_ref = h.get_object_field_value(obj_ref, obj_name.as_str(), "clazz")?[0];
let modifiers = h.get_object_field_value(obj_ref, obj_name.as_str(), "modifiers")?[0];
let slot = h.get_object_field_value(obj_ref, obj_name.as_str(), "slot")?[0];
Ok::<(i32, i32, i32), Error>((clazz_ref, modifiers, slot))
})?;
let resolved_method_name = ResolvedMethodName::new_create_instance(clazz_ref, slot as i64)?;
resolved_method_name.propagate_all()?;
let method_ref = resolved_method_name.resolved_method_name_ref();
let enriched_with_kind = set_reference_kind(modifiers, kind);
let enriched_with_internal_flags = enriched_with_kind | internal_flag;
with_heap_write_lock(|h| {
h.set_object_field_value(
member_name_ref,
"java/lang/invoke/MemberName",
"clazz",
vec![clazz_ref],
)?;
h.set_object_field_value(
member_name_ref,
"java/lang/invoke/MemberName",
"flags",
vec![enriched_with_internal_flags],
)?;
h.set_object_field_value(
member_name_ref,
"java/lang/invoke/MemberName",
"method",
vec![method_ref],
)?;
Ok::<(), Error>(())
})?;
Ok(())
}