src/share/vm/prims/methodHandles.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File
8014013 Cdiff src/share/vm/prims/methodHandles.cpp
src/share/vm/prims/methodHandles.cpp
Print this page
*** 125,229 ****
if (!k->is_initialized()) k->initialize(CHECK_(empty));
return Handle(THREAD, k->allocate_instance(THREAD));
}
oop MethodHandles::init_MemberName(Handle mname, Handle target) {
Thread* thread = Thread::current();
oop target_oop = target();
Klass* target_klass = target_oop->klass();
if (target_klass == SystemDictionary::reflect_Field_klass()) {
oop clazz = java_lang_reflect_Field::clazz(target_oop); // fd.field_holder()
int slot = java_lang_reflect_Field::slot(target_oop); // fd.index()
- int mods = java_lang_reflect_Field::modifiers(target_oop);
- oop type = java_lang_reflect_Field::type(target_oop);
- oop name = java_lang_reflect_Field::name(target_oop);
KlassHandle k(thread, java_lang_Class::as_Klass(clazz));
! intptr_t offset = InstanceKlass::cast(k())->field_offset(slot);
! return init_field_MemberName(mname, k, accessFlags_from(mods), type, name, offset);
} else if (target_klass == SystemDictionary::reflect_Method_klass()) {
oop clazz = java_lang_reflect_Method::clazz(target_oop);
int slot = java_lang_reflect_Method::slot(target_oop);
KlassHandle k(thread, java_lang_Class::as_Klass(clazz));
if (!k.is_null() && k->oop_is_instance()) {
Method* m = InstanceKlass::cast(k())->method_with_idnum(slot);
! return init_method_MemberName(mname, m, true, k);
}
} else if (target_klass == SystemDictionary::reflect_Constructor_klass()) {
oop clazz = java_lang_reflect_Constructor::clazz(target_oop);
int slot = java_lang_reflect_Constructor::slot(target_oop);
KlassHandle k(thread, java_lang_Class::as_Klass(clazz));
if (!k.is_null() && k->oop_is_instance()) {
Method* m = InstanceKlass::cast(k())->method_with_idnum(slot);
! return init_method_MemberName(mname, m, false, k);
! }
! } else if (target_klass == SystemDictionary::MemberName_klass()) {
! // Note: This only works if the MemberName has already been resolved.
! oop clazz = java_lang_invoke_MemberName::clazz(target_oop);
! int flags = java_lang_invoke_MemberName::flags(target_oop);
! Metadata* vmtarget=java_lang_invoke_MemberName::vmtarget(target_oop);
! intptr_t vmindex = java_lang_invoke_MemberName::vmindex(target_oop);
! KlassHandle k(thread, java_lang_Class::as_Klass(clazz));
! int ref_kind = (flags >> REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK;
! if (vmtarget == NULL) return NULL; // not resolved
! if ((flags & IS_FIELD) != 0) {
! assert(vmtarget->is_klass(), "field vmtarget is Klass*");
! int basic_mods = (ref_kind_is_static(ref_kind) ? JVM_ACC_STATIC : 0);
! // FIXME: how does k (receiver_limit) contribute?
! KlassHandle k_vmtarget(thread, (Klass*)vmtarget);
! return init_field_MemberName(mname, k_vmtarget, accessFlags_from(basic_mods), NULL, NULL, vmindex);
! } else if ((flags & (IS_METHOD | IS_CONSTRUCTOR)) != 0) {
! assert(vmtarget->is_method(), "method or constructor vmtarget is Method*");
! return init_method_MemberName(mname, (Method*)vmtarget, ref_kind_does_dispatch(ref_kind), k);
! } else {
! return NULL;
}
}
return NULL;
}
! oop MethodHandles::init_method_MemberName(Handle mname, Method* m, bool do_dispatch,
! KlassHandle receiver_limit_h) {
! Klass* receiver_limit = receiver_limit_h();
! AccessFlags mods = m->access_flags();
! int flags = (jushort)( mods.as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS );
! int vmindex = Method::nonvirtual_vtable_index; // implies never any dispatch
! Klass* mklass = m->method_holder();
! if (receiver_limit == NULL)
! receiver_limit = mklass;
! if (m->is_initializer()) {
! flags |= IS_CONSTRUCTOR | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT);
! } else if (mods.is_static()) {
! flags |= IS_METHOD | (JVM_REF_invokeStatic << REFERENCE_KIND_SHIFT);
! } else if (receiver_limit != mklass &&
! !receiver_limit->is_subtype_of(mklass)) {
! return NULL; // bad receiver limit
! } else if (do_dispatch && receiver_limit->is_interface() &&
! mklass->is_interface()) {
flags |= IS_METHOD | (JVM_REF_invokeInterface << REFERENCE_KIND_SHIFT);
! receiver_limit = mklass; // ignore passed-in limit; interfaces are interconvertible
! vmindex = klassItable::compute_itable_index(m);
! } else if (do_dispatch && mklass != receiver_limit && mklass->is_interface()) {
flags |= IS_METHOD | (JVM_REF_invokeVirtual << REFERENCE_KIND_SHIFT);
! // it is a miranda method, so m->vtable_index is not what we want
! ResourceMark rm;
! klassVtable* vt = InstanceKlass::cast(receiver_limit)->vtable();
! vmindex = vt->index_of_miranda(m->name(), m->signature());
! } else if (!do_dispatch || m->can_be_statically_bound()) {
! flags |= IS_METHOD | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT);
} else {
! flags |= IS_METHOD | (JVM_REF_invokeVirtual << REFERENCE_KIND_SHIFT);
! vmindex = m->vtable_index();
}
// @CallerSensitive annotation detected
if (m->caller_sensitive()) {
flags |= CALLER_SENSITIVE;
}
oop mname_oop = mname();
java_lang_invoke_MemberName::set_flags( mname_oop, flags);
! java_lang_invoke_MemberName::set_vmtarget(mname_oop, m);
java_lang_invoke_MemberName::set_vmindex( mname_oop, vmindex); // vtable/itable index
java_lang_invoke_MemberName::set_clazz( mname_oop, receiver_limit->java_mirror());
// Note: name and type can be lazily computed by resolve_MemberName,
// if Java code needs them as resolved String and MethodType objects.
// The clazz must be eagerly stored, because it provides a GC
--- 125,226 ----
if (!k->is_initialized()) k->initialize(CHECK_(empty));
return Handle(THREAD, k->allocate_instance(THREAD));
}
oop MethodHandles::init_MemberName(Handle mname, Handle target) {
+ // This method is used from java.lang.invoke.MemberName constructors.
+ // It fills in the new MemberName from a java.lang.reflect.Member.
Thread* thread = Thread::current();
oop target_oop = target();
Klass* target_klass = target_oop->klass();
if (target_klass == SystemDictionary::reflect_Field_klass()) {
oop clazz = java_lang_reflect_Field::clazz(target_oop); // fd.field_holder()
int slot = java_lang_reflect_Field::slot(target_oop); // fd.index()
KlassHandle k(thread, java_lang_Class::as_Klass(clazz));
! if (!k.is_null() && k->oop_is_instance()) {
! fieldDescriptor fd(InstanceKlass::cast(k()), slot);
! oop mname2 = init_field_MemberName(mname, fd);
! if (mname2 != NULL) {
! // Since we have the reified name and type handy, add them to the result.
! if (java_lang_invoke_MemberName::name(mname2) == NULL)
! java_lang_invoke_MemberName::set_name(mname2, java_lang_reflect_Field::name(target_oop));
! if (java_lang_invoke_MemberName::type(mname2) == NULL)
! java_lang_invoke_MemberName::set_type(mname2, java_lang_reflect_Field::type(target_oop));
! }
! return mname2;
! }
} else if (target_klass == SystemDictionary::reflect_Method_klass()) {
oop clazz = java_lang_reflect_Method::clazz(target_oop);
int slot = java_lang_reflect_Method::slot(target_oop);
KlassHandle k(thread, java_lang_Class::as_Klass(clazz));
if (!k.is_null() && k->oop_is_instance()) {
Method* m = InstanceKlass::cast(k())->method_with_idnum(slot);
! if (m == NULL || is_signature_polymorphic(m->intrinsic_id()))
! return NULL; // do not resolve unless there is a concrete signature
! CallInfo info(m, k());
! return init_method_MemberName(mname, info);
}
} else if (target_klass == SystemDictionary::reflect_Constructor_klass()) {
oop clazz = java_lang_reflect_Constructor::clazz(target_oop);
int slot = java_lang_reflect_Constructor::slot(target_oop);
KlassHandle k(thread, java_lang_Class::as_Klass(clazz));
if (!k.is_null() && k->oop_is_instance()) {
Method* m = InstanceKlass::cast(k())->method_with_idnum(slot);
! if (m == NULL) return NULL;
! CallInfo info(m, k());
! return init_method_MemberName(mname, info);
}
}
return NULL;
}
! oop MethodHandles::init_method_MemberName(Handle mname, CallInfo& info) {
! assert(info.resolved_appendix().is_null(), "only normal methods here");
! KlassHandle receiver_limit = info.resolved_klass();
! methodHandle m = info.resolved_method();
! int flags = (jushort)( m->access_flags().as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS );
! int vmindex = Method::invalid_vtable_index;
!
! switch (info.call_kind()) {
! case CallInfo::itable_call:
! vmindex = info.itable_index();
! // More importantly, the itable index only works with the method holder.
! receiver_limit = m->method_holder();
! assert(receiver_limit->verify_itable_index(vmindex), "");
flags |= IS_METHOD | (JVM_REF_invokeInterface << REFERENCE_KIND_SHIFT);
! break;
!
! case CallInfo::vtable_call:
! vmindex = info.vtable_index();
flags |= IS_METHOD | (JVM_REF_invokeVirtual << REFERENCE_KIND_SHIFT);
! assert(receiver_limit->is_subtype_of(m->method_holder()), "virtual call must be type-safe");
! break;
!
! case CallInfo::direct_call:
! vmindex = Method::nonvirtual_vtable_index;
! if (m->is_static()) {
! flags |= IS_METHOD | (JVM_REF_invokeStatic << REFERENCE_KIND_SHIFT);
! } else if (m->is_initializer()) {
! flags |= IS_CONSTRUCTOR | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT);
! assert(receiver_limit == m->method_holder(), "constructor call must be exactly typed");
} else {
! flags |= IS_METHOD | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT);
! assert(receiver_limit->is_subtype_of(m->method_holder()), "special call must be type-safe");
! }
! break;
!
! default: assert(false, "bad CallInfo"); return NULL;
}
// @CallerSensitive annotation detected
if (m->caller_sensitive()) {
flags |= CALLER_SENSITIVE;
}
oop mname_oop = mname();
java_lang_invoke_MemberName::set_flags( mname_oop, flags);
! java_lang_invoke_MemberName::set_vmtarget(mname_oop, m());
java_lang_invoke_MemberName::set_vmindex( mname_oop, vmindex); // vtable/itable index
java_lang_invoke_MemberName::set_clazz( mname_oop, receiver_limit->java_mirror());
// Note: name and type can be lazily computed by resolve_MemberName,
// if Java code needs them as resolved String and MethodType objects.
// The clazz must be eagerly stored, because it provides a GC
*** 235,297 ****
m->method_holder()->add_member_name(m->method_idnum(), mname);
return mname();
}
! Handle MethodHandles::init_method_MemberName(Handle mname, CallInfo& info, TRAPS) {
! Handle empty;
! if (info.resolved_appendix().not_null()) {
! // The resolved MemberName must not be accompanied by an appendix argument,
! // since there is no way to bind this value into the MemberName.
! // Caller is responsible to prevent this from happening.
! THROW_MSG_(vmSymbols::java_lang_InternalError(), "appendix", empty);
! }
! methodHandle m = info.resolved_method();
! KlassHandle defc = info.resolved_klass();
! int vmindex = Method::invalid_vtable_index;
! if (defc->is_interface() && m->method_holder()->is_interface()) {
! // static interface methods do not reference vtable or itable
! if (m->is_static()) {
! vmindex = Method::nonvirtual_vtable_index;
! }
! // interface methods invoked via invokespecial also
! // do not reference vtable or itable.
! int ref_kind = ((java_lang_invoke_MemberName::flags(mname()) >>
! REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK);
! if (ref_kind == JVM_REF_invokeSpecial) {
! vmindex = Method::nonvirtual_vtable_index;
! }
! // If neither m is static nor ref_kind is invokespecial,
! // set it to itable index.
! if (vmindex == Method::invalid_vtable_index) {
! // LinkResolver does not report itable indexes! (fix this?)
! vmindex = klassItable::compute_itable_index(m());
! }
! } else if (m->can_be_statically_bound()) {
! // LinkResolver reports vtable index even for final methods!
! vmindex = Method::nonvirtual_vtable_index;
! } else {
! vmindex = info.vtable_index();
! }
! oop res = init_method_MemberName(mname, m(), (vmindex >= 0), defc());
! assert(res == NULL || (java_lang_invoke_MemberName::vmindex(res) == vmindex), "");
! return Handle(THREAD, res);
! }
!
! oop MethodHandles::init_field_MemberName(Handle mname, KlassHandle field_holder,
! AccessFlags mods, oop type, oop name,
! intptr_t offset, bool is_setter) {
! int flags = (jushort)( mods.as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS );
! flags |= IS_FIELD | ((mods.is_static() ? JVM_REF_getStatic : JVM_REF_getField) << REFERENCE_KIND_SHIFT);
if (is_setter) flags += ((JVM_REF_putField - JVM_REF_getField) << REFERENCE_KIND_SHIFT);
! Metadata* vmtarget = field_holder();
! int vmindex = offset; // determines the field uniquely when combined with static bit
oop mname_oop = mname();
java_lang_invoke_MemberName::set_flags(mname_oop, flags);
java_lang_invoke_MemberName::set_vmtarget(mname_oop, vmtarget);
java_lang_invoke_MemberName::set_vmindex(mname_oop, vmindex);
! java_lang_invoke_MemberName::set_clazz(mname_oop, field_holder->java_mirror());
if (name != NULL)
java_lang_invoke_MemberName::set_name(mname_oop, name);
if (type != NULL)
java_lang_invoke_MemberName::set_type(mname_oop, type);
// Note: name and type can be lazily computed by resolve_MemberName,
--- 232,254 ----
m->method_holder()->add_member_name(m->method_idnum(), mname);
return mname();
}
! oop MethodHandles::init_field_MemberName(Handle mname, fieldDescriptor& fd, bool is_setter) {
! int flags = (jushort)( fd.access_flags().as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS );
! flags |= IS_FIELD | ((fd.is_static() ? JVM_REF_getStatic : JVM_REF_getField) << REFERENCE_KIND_SHIFT);
if (is_setter) flags += ((JVM_REF_putField - JVM_REF_getField) << REFERENCE_KIND_SHIFT);
! Metadata* vmtarget = fd.field_holder();
! int vmindex = fd.offset(); // determines the field uniquely when combined with static bit
oop mname_oop = mname();
java_lang_invoke_MemberName::set_flags(mname_oop, flags);
java_lang_invoke_MemberName::set_vmtarget(mname_oop, vmtarget);
java_lang_invoke_MemberName::set_vmindex(mname_oop, vmindex);
! java_lang_invoke_MemberName::set_clazz(mname_oop, fd.field_holder()->java_mirror());
! oop type = field_signature_type_or_null(fd.signature());
! oop name = field_name_or_null(fd.name());
if (name != NULL)
java_lang_invoke_MemberName::set_name(mname_oop, name);
if (type != NULL)
java_lang_invoke_MemberName::set_type(mname_oop, type);
// Note: name and type can be lazily computed by resolve_MemberName,
*** 303,325 ****
// we do not use it, because it is harder to decode.
// TO DO: maybe intern mname_oop
return mname();
}
- Handle MethodHandles::init_field_MemberName(Handle mname, FieldAccessInfo& info, TRAPS) {
- return Handle();
- #if 0 // FIXME
- KlassHandle field_holder = info.klass();
- intptr_t field_offset = info.field_offset();
- return init_field_MemberName(mname_oop, field_holder(),
- info.access_flags(),
- type, name,
- field_offset, false /*is_setter*/);
- #endif
- }
-
-
// JVM 2.9 Special Methods:
// A method is signature polymorphic if and only if all of the following conditions hold :
// * It is declared in the java.lang.invoke.MethodHandle class.
// * It has a single formal parameter of type Object[].
// * It has a return type of Object.
--- 260,269 ----
*** 571,586 ****
static oop object_java_mirror() {
return SystemDictionary::Object_klass()->java_mirror();
}
! static oop field_name_or_null(Symbol* s) {
if (s == NULL) return NULL;
return StringTable::lookup(s);
}
! static oop field_signature_type_or_null(Symbol* s) {
if (s == NULL) return NULL;
BasicType bt = FieldType::basic_type(s);
if (is_java_primitive(bt)) {
assert(s->utf8_length() == 1, "");
return java_lang_Class::primitive_mirror(bt);
--- 515,530 ----
static oop object_java_mirror() {
return SystemDictionary::Object_klass()->java_mirror();
}
! oop MethodHandles::field_name_or_null(Symbol* s) {
if (s == NULL) return NULL;
return StringTable::lookup(s);
}
! oop MethodHandles::field_signature_type_or_null(Symbol* s) {
if (s == NULL) return NULL;
BasicType bt = FieldType::basic_type(s);
if (is_java_primitive(bt)) {
assert(s->utf8_length() == 1, "");
return java_lang_Class::primitive_mirror(bt);
*** 699,709 ****
}
if (HAS_PENDING_EXCEPTION) {
return empty;
}
}
! return init_method_MemberName(mname, result, THREAD);
}
case IS_CONSTRUCTOR:
{
CallInfo result;
{
--- 643,660 ----
}
if (HAS_PENDING_EXCEPTION) {
return empty;
}
}
! if (result.resolved_appendix().not_null()) {
! // The resolved MemberName must not be accompanied by an appendix argument,
! // since there is no way to bind this value into the MemberName.
! // Caller is responsible to prevent this from happening.
! THROW_MSG_(vmSymbols::java_lang_InternalError(), "appendix", empty);
! }
! oop mname2 = init_method_MemberName(mname, result);
! return Handle(THREAD, mname2);
}
case IS_CONSTRUCTOR:
{
CallInfo result;
{
*** 717,742 ****
if (HAS_PENDING_EXCEPTION) {
return empty;
}
}
assert(result.is_statically_bound(), "");
! return init_method_MemberName(mname, result, THREAD);
}
case IS_FIELD:
{
! // This is taken from LinkResolver::resolve_field, sans access checks.
! fieldDescriptor fd; // find_field initializes fd if found
! KlassHandle sel_klass(THREAD, InstanceKlass::cast(defc())->find_field(name, type, &fd));
! // check if field exists; i.e., if a klass containing the field def has been selected
! if (sel_klass.is_null()) return empty; // should not happen
! oop type = field_signature_type_or_null(fd.signature());
! oop name = field_name_or_null(fd.name());
! bool is_setter = (ref_kind_is_valid(ref_kind) && ref_kind_is_setter(ref_kind));
! mname = Handle(THREAD,
! init_field_MemberName(mname, sel_klass,
! fd.access_flags(), type, name, fd.offset(), is_setter));
! return mname;
}
default:
THROW_MSG_(vmSymbols::java_lang_InternalError(), "unrecognized MemberName format", empty);
}
--- 668,692 ----
if (HAS_PENDING_EXCEPTION) {
return empty;
}
}
assert(result.is_statically_bound(), "");
! oop mname2 = init_method_MemberName(mname, result);
! return Handle(THREAD, mname2);
}
case IS_FIELD:
{
! fieldDescriptor result; // find_field initializes fd if found
! {
! assert(!HAS_PENDING_EXCEPTION, "");
! LinkResolver::resolve_field(result, defc, name, type, KlassHandle(), Bytecodes::_nop, false, false, THREAD);
! if (HAS_PENDING_EXCEPTION) {
! return empty;
! }
! }
! oop mname2 = init_field_MemberName(mname, result, ref_kind_is_setter(ref_kind));
! return Handle(THREAD, mname2);
}
default:
THROW_MSG_(vmSymbols::java_lang_InternalError(), "unrecognized MemberName format", empty);
}
*** 791,801 ****
}
return;
}
case IS_FIELD:
{
- // This is taken from LinkResolver::resolve_field, sans access checks.
assert(vmtarget->is_klass(), "field vmtarget is Klass*");
if (!((Klass*) vmtarget)->oop_is_instance()) break;
instanceKlassHandle defc(THREAD, (Klass*) vmtarget);
DEBUG_ONLY(vmtarget = NULL); // safety
bool is_static = ((flags & JVM_ACC_STATIC) != 0);
--- 741,750 ----
*** 870,884 ****
--rskip;
} else if (rfill < rlimit) {
Handle result(thread, results->obj_at(rfill++));
if (!java_lang_invoke_MemberName::is_instance(result()))
return -99; // caller bug!
! oop type = field_signature_type_or_null(st.signature());
! oop name = field_name_or_null(st.name());
! oop saved = MethodHandles::init_field_MemberName(result, st.klass(),
! st.access_flags(), type, name,
! st.offset());
if (saved != result())
results->obj_at_put(rfill-1, saved); // show saved instance to user
} else if (++overflow >= overflow_limit) {
match_flags = 0; break; // got tired of looking at overflow
}
--- 819,829 ----
--rskip;
} else if (rfill < rlimit) {
Handle result(thread, results->obj_at(rfill++));
if (!java_lang_invoke_MemberName::is_instance(result()))
return -99; // caller bug!
! oop saved = MethodHandles::init_field_MemberName(result, st.field_descriptor());
if (saved != result())
results->obj_at_put(rfill-1, saved); // show saved instance to user
} else if (++overflow >= overflow_limit) {
match_flags = 0; break; // got tired of looking at overflow
}
*** 924,934 ****
--rskip;
} else if (rfill < rlimit) {
Handle result(thread, results->obj_at(rfill++));
if (!java_lang_invoke_MemberName::is_instance(result()))
return -99; // caller bug!
! oop saved = MethodHandles::init_method_MemberName(result, m, true, NULL);
if (saved != result())
results->obj_at_put(rfill-1, saved); // show saved instance to user
} else if (++overflow >= overflow_limit) {
match_flags = 0; break; // got tired of looking at overflow
}
--- 869,880 ----
--rskip;
} else if (rfill < rlimit) {
Handle result(thread, results->obj_at(rfill++));
if (!java_lang_invoke_MemberName::is_instance(result()))
return -99; // caller bug!
! CallInfo info(m);
! oop saved = MethodHandles::init_method_MemberName(result, info);
if (saved != result())
results->obj_at_put(rfill-1, saved); // show saved instance to user
} else if (++overflow >= overflow_limit) {
match_flags = 0; break; // got tired of looking at overflow
}
*** 1225,1235 ****
x = NULL;
} else if (vmtarget->is_klass()) {
x = ((Klass*) vmtarget)->java_mirror();
} else if (vmtarget->is_method()) {
Handle mname2 = MethodHandles::new_MemberName(CHECK_NULL);
! x = MethodHandles::init_method_MemberName(mname2, (Method*)vmtarget, false, NULL);
}
result->obj_at_put(1, x);
return JNIHandles::make_local(env, result());
}
JVM_END
--- 1171,1182 ----
x = NULL;
} else if (vmtarget->is_klass()) {
x = ((Klass*) vmtarget)->java_mirror();
} else if (vmtarget->is_method()) {
Handle mname2 = MethodHandles::new_MemberName(CHECK_NULL);
! CallInfo info((Method*)vmtarget);
! x = MethodHandles::init_method_MemberName(mname2, info);
}
result->obj_at_put(1, x);
return JNIHandles::make_local(env, result());
}
JVM_END
src/share/vm/prims/methodHandles.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File