提交 e97a0e05 编写于 作者: S sspitsyn

8008511: JSR 292: MemberName vmtarget refs to methods must be updated at class redefinition

Summary: Lazily create and maintain the MemberNameTable to be able to update MemberName's
Reviewed-by: coleenp, jrose, dholmes
Contributed-by: serguei.spitsyn@oracle.com
上级 71b856e4
...@@ -2625,6 +2625,15 @@ Metadata* java_lang_invoke_MemberName::vmtarget(oop mname) { ...@@ -2625,6 +2625,15 @@ Metadata* java_lang_invoke_MemberName::vmtarget(oop mname) {
return (Metadata*)mname->address_field(_vmtarget_offset); return (Metadata*)mname->address_field(_vmtarget_offset);
} }
#if INCLUDE_JVMTI
// Can be executed on VM thread only
void java_lang_invoke_MemberName::adjust_vmtarget(oop mname, Metadata* ref) {
assert((is_instance(mname) && (flags(mname) & (MN_IS_METHOD | MN_IS_CONSTRUCTOR)) > 0), "wrong type");
assert(Thread::current()->is_VM_thread(), "not VM thread");
mname->address_field_put(_vmtarget_offset, (address)ref);
}
#endif // INCLUDE_JVMTI
void java_lang_invoke_MemberName::set_vmtarget(oop mname, Metadata* ref) { void java_lang_invoke_MemberName::set_vmtarget(oop mname, Metadata* ref) {
assert(is_instance(mname), "wrong type"); assert(is_instance(mname), "wrong type");
// check the type of the vmtarget // check the type of the vmtarget
......
...@@ -1036,6 +1036,9 @@ class java_lang_invoke_MemberName: AllStatic { ...@@ -1036,6 +1036,9 @@ class java_lang_invoke_MemberName: AllStatic {
static Metadata* vmtarget(oop mname); static Metadata* vmtarget(oop mname);
static void set_vmtarget(oop mname, Metadata* target); static void set_vmtarget(oop mname, Metadata* target);
#if INCLUDE_JVMTI
static void adjust_vmtarget(oop mname, Metadata* target);
#endif // INCLUDE_JVMTI
static intptr_t vmindex(oop mname); static intptr_t vmindex(oop mname);
static void set_vmindex(oop mname, intptr_t index); static void set_vmindex(oop mname, intptr_t index);
......
...@@ -2329,6 +2329,12 @@ void InstanceKlass::release_C_heap_structures() { ...@@ -2329,6 +2329,12 @@ void InstanceKlass::release_C_heap_structures() {
FreeHeap(jmeths); FreeHeap(jmeths);
} }
MemberNameTable* mnt = member_names();
if (mnt != NULL) {
delete mnt;
set_member_names(NULL);
}
int* indices = methods_cached_itable_indices_acquire(); int* indices = methods_cached_itable_indices_acquire();
if (indices != (int*)NULL) { if (indices != (int*)NULL) {
release_set_methods_cached_itable_indices(NULL); release_set_methods_cached_itable_indices(NULL);
...@@ -2757,6 +2763,17 @@ nmethod* InstanceKlass::lookup_osr_nmethod(Method* const m, int bci, int comp_le ...@@ -2757,6 +2763,17 @@ nmethod* InstanceKlass::lookup_osr_nmethod(Method* const m, int bci, int comp_le
return NULL; return NULL;
} }
void InstanceKlass::add_member_name(Handle mem_name) {
jweak mem_name_wref = JNIHandles::make_weak_global(mem_name);
MutexLocker ml(MemberNameTable_lock);
DEBUG_ONLY(No_Safepoint_Verifier nsv);
if (_member_names == NULL) {
_member_names = new (ResourceObj::C_HEAP, mtClass) MemberNameTable();
}
_member_names->add_member_name(mem_name_wref);
}
// ----------------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------------
// Printing // Printing
......
...@@ -90,6 +90,7 @@ class DepChange; ...@@ -90,6 +90,7 @@ class DepChange;
class nmethodBucket; class nmethodBucket;
class PreviousVersionNode; class PreviousVersionNode;
class JvmtiCachedClassFieldMap; class JvmtiCachedClassFieldMap;
class MemberNameTable;
// This is used in iterators below. // This is used in iterators below.
class FieldClosure: public StackObj { class FieldClosure: public StackObj {
...@@ -246,6 +247,7 @@ class InstanceKlass: public Klass { ...@@ -246,6 +247,7 @@ class InstanceKlass: public Klass {
int _vtable_len; // length of Java vtable (in words) int _vtable_len; // length of Java vtable (in words)
int _itable_len; // length of Java itable (in words) int _itable_len; // length of Java itable (in words)
OopMapCache* volatile _oop_map_cache; // OopMapCache for all methods in the klass (allocated lazily) OopMapCache* volatile _oop_map_cache; // OopMapCache for all methods in the klass (allocated lazily)
MemberNameTable* _member_names; // Member names
JNIid* _jni_ids; // First JNI identifier for static fields in this class JNIid* _jni_ids; // First JNI identifier for static fields in this class
jmethodID* _methods_jmethod_ids; // jmethodIDs corresponding to method_idnum, or NULL if none jmethodID* _methods_jmethod_ids; // jmethodIDs corresponding to method_idnum, or NULL if none
int* _methods_cached_itable_indices; // itable_index cache for JNI invoke corresponding to methods idnum, or NULL int* _methods_cached_itable_indices; // itable_index cache for JNI invoke corresponding to methods idnum, or NULL
...@@ -1028,6 +1030,11 @@ public: ...@@ -1028,6 +1030,11 @@ public:
// jvm support // jvm support
jint compute_modifier_flags(TRAPS) const; jint compute_modifier_flags(TRAPS) const;
// JSR-292 support
MemberNameTable* member_names() { return _member_names; }
void set_member_names(MemberNameTable* member_names) { _member_names = member_names; }
void add_member_name(Handle member_name);
public: public:
// JVMTI support // JVMTI support
jint jvmti_class_status() const; jint jvmti_class_status() const;
......
...@@ -3284,6 +3284,16 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass, ...@@ -3284,6 +3284,16 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass,
// that reference methods of the evolved class. // that reference methods of the evolved class.
SystemDictionary::classes_do(adjust_cpool_cache_and_vtable, THREAD); SystemDictionary::classes_do(adjust_cpool_cache_and_vtable, THREAD);
// JSR-292 support
MemberNameTable* mnt = the_class->member_names();
if (mnt != NULL) {
bool trace_name_printed = false;
mnt->adjust_method_entries(_matching_old_methods,
_matching_new_methods,
_matching_methods_length,
&trace_name_printed);
}
// Fix Resolution Error table also to remove old constant pools // Fix Resolution Error table also to remove old constant pools
SystemDictionary::delete_resolution_error(old_constants); SystemDictionary::delete_resolution_error(old_constants);
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "interpreter/oopMapCache.hpp" #include "interpreter/oopMapCache.hpp"
#include "memory/allocation.inline.hpp" #include "memory/allocation.inline.hpp"
#include "memory/oopFactory.hpp" #include "memory/oopFactory.hpp"
#include "prims/jvmtiRedefineClassesTrace.hpp"
#include "prims/methodHandles.hpp" #include "prims/methodHandles.hpp"
#include "runtime/compilationPolicy.hpp" #include "runtime/compilationPolicy.hpp"
#include "runtime/javaCalls.hpp" #include "runtime/javaCalls.hpp"
...@@ -124,7 +125,9 @@ Handle MethodHandles::new_MemberName(TRAPS) { ...@@ -124,7 +125,9 @@ Handle MethodHandles::new_MemberName(TRAPS) {
return Handle(THREAD, k->allocate_instance(THREAD)); return Handle(THREAD, k->allocate_instance(THREAD));
} }
oop MethodHandles::init_MemberName(oop mname_oop, oop target_oop) { oop MethodHandles::init_MemberName(Handle mname, Handle target) {
Thread* thread = Thread::current();
oop target_oop = target();
Klass* target_klass = target_oop->klass(); Klass* target_klass = target_oop->klass();
if (target_klass == SystemDictionary::reflect_Field_klass()) { if (target_klass == SystemDictionary::reflect_Field_klass()) {
oop clazz = java_lang_reflect_Field::clazz(target_oop); // fd.field_holder() oop clazz = java_lang_reflect_Field::clazz(target_oop); // fd.field_holder()
...@@ -132,24 +135,24 @@ oop MethodHandles::init_MemberName(oop mname_oop, oop target_oop) { ...@@ -132,24 +135,24 @@ oop MethodHandles::init_MemberName(oop mname_oop, oop target_oop) {
int mods = java_lang_reflect_Field::modifiers(target_oop); int mods = java_lang_reflect_Field::modifiers(target_oop);
oop type = java_lang_reflect_Field::type(target_oop); oop type = java_lang_reflect_Field::type(target_oop);
oop name = java_lang_reflect_Field::name(target_oop); oop name = java_lang_reflect_Field::name(target_oop);
Klass* k = java_lang_Class::as_Klass(clazz); KlassHandle k(thread, java_lang_Class::as_Klass(clazz));
intptr_t offset = InstanceKlass::cast(k)->field_offset(slot); intptr_t offset = InstanceKlass::cast(k())->field_offset(slot);
return init_field_MemberName(mname_oop, k, accessFlags_from(mods), type, name, offset); return init_field_MemberName(mname, k, accessFlags_from(mods), type, name, offset);
} else if (target_klass == SystemDictionary::reflect_Method_klass()) { } else if (target_klass == SystemDictionary::reflect_Method_klass()) {
oop clazz = java_lang_reflect_Method::clazz(target_oop); oop clazz = java_lang_reflect_Method::clazz(target_oop);
int slot = java_lang_reflect_Method::slot(target_oop); int slot = java_lang_reflect_Method::slot(target_oop);
Klass* k = java_lang_Class::as_Klass(clazz); KlassHandle k(thread, java_lang_Class::as_Klass(clazz));
if (k != NULL && k->oop_is_instance()) { if (!k.is_null() && k->oop_is_instance()) {
Method* m = InstanceKlass::cast(k)->method_with_idnum(slot); Method* m = InstanceKlass::cast(k())->method_with_idnum(slot);
return init_method_MemberName(mname_oop, m, true, k); return init_method_MemberName(mname, m, true, k);
} }
} else if (target_klass == SystemDictionary::reflect_Constructor_klass()) { } else if (target_klass == SystemDictionary::reflect_Constructor_klass()) {
oop clazz = java_lang_reflect_Constructor::clazz(target_oop); oop clazz = java_lang_reflect_Constructor::clazz(target_oop);
int slot = java_lang_reflect_Constructor::slot(target_oop); int slot = java_lang_reflect_Constructor::slot(target_oop);
Klass* k = java_lang_Class::as_Klass(clazz); KlassHandle k(thread, java_lang_Class::as_Klass(clazz));
if (k != NULL && k->oop_is_instance()) { if (!k.is_null() && k->oop_is_instance()) {
Method* m = InstanceKlass::cast(k)->method_with_idnum(slot); Method* m = InstanceKlass::cast(k())->method_with_idnum(slot);
return init_method_MemberName(mname_oop, m, false, k); return init_method_MemberName(mname, m, false, k);
} }
} else if (target_klass == SystemDictionary::MemberName_klass()) { } else if (target_klass == SystemDictionary::MemberName_klass()) {
// Note: This only works if the MemberName has already been resolved. // Note: This only works if the MemberName has already been resolved.
...@@ -157,17 +160,18 @@ oop MethodHandles::init_MemberName(oop mname_oop, oop target_oop) { ...@@ -157,17 +160,18 @@ oop MethodHandles::init_MemberName(oop mname_oop, oop target_oop) {
int flags = java_lang_invoke_MemberName::flags(target_oop); int flags = java_lang_invoke_MemberName::flags(target_oop);
Metadata* vmtarget=java_lang_invoke_MemberName::vmtarget(target_oop); Metadata* vmtarget=java_lang_invoke_MemberName::vmtarget(target_oop);
intptr_t vmindex = java_lang_invoke_MemberName::vmindex(target_oop); intptr_t vmindex = java_lang_invoke_MemberName::vmindex(target_oop);
Klass* k = java_lang_Class::as_Klass(clazz); KlassHandle k(thread, java_lang_Class::as_Klass(clazz));
int ref_kind = (flags >> REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK; int ref_kind = (flags >> REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK;
if (vmtarget == NULL) return NULL; // not resolved if (vmtarget == NULL) return NULL; // not resolved
if ((flags & IS_FIELD) != 0) { if ((flags & IS_FIELD) != 0) {
assert(vmtarget->is_klass(), "field vmtarget is Klass*"); assert(vmtarget->is_klass(), "field vmtarget is Klass*");
int basic_mods = (ref_kind_is_static(ref_kind) ? JVM_ACC_STATIC : 0); int basic_mods = (ref_kind_is_static(ref_kind) ? JVM_ACC_STATIC : 0);
// FIXME: how does k (receiver_limit) contribute? // FIXME: how does k (receiver_limit) contribute?
return init_field_MemberName(mname_oop, (Klass*)vmtarget, accessFlags_from(basic_mods), NULL, NULL, vmindex); 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) { } else if ((flags & (IS_METHOD | IS_CONSTRUCTOR)) != 0) {
assert(vmtarget->is_method(), "method or constructor vmtarget is Method*"); assert(vmtarget->is_method(), "method or constructor vmtarget is Method*");
return init_method_MemberName(mname_oop, (Method*)vmtarget, ref_kind_does_dispatch(ref_kind), k); return init_method_MemberName(mname, (Method*)vmtarget, ref_kind_does_dispatch(ref_kind), k);
} else { } else {
return NULL; return NULL;
} }
...@@ -175,8 +179,9 @@ oop MethodHandles::init_MemberName(oop mname_oop, oop target_oop) { ...@@ -175,8 +179,9 @@ oop MethodHandles::init_MemberName(oop mname_oop, oop target_oop) {
return NULL; return NULL;
} }
oop MethodHandles::init_method_MemberName(oop mname_oop, Method* m, bool do_dispatch, oop MethodHandles::init_method_MemberName(Handle mname, Method* m, bool do_dispatch,
Klass* receiver_limit) { KlassHandle receiver_limit_h) {
Klass* receiver_limit = receiver_limit_h();
AccessFlags mods = m->access_flags(); AccessFlags mods = m->access_flags();
int flags = (jushort)( mods.as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS ); int flags = (jushort)( mods.as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS );
int vmindex = Method::nonvirtual_vtable_index; // implies never any dispatch int vmindex = Method::nonvirtual_vtable_index; // implies never any dispatch
...@@ -218,6 +223,7 @@ oop MethodHandles::init_method_MemberName(oop mname_oop, Method* m, bool do_disp ...@@ -218,6 +223,7 @@ oop MethodHandles::init_method_MemberName(oop mname_oop, Method* m, bool do_disp
flags |= CALLER_SENSITIVE; flags |= CALLER_SENSITIVE;
} }
oop mname_oop = mname();
java_lang_invoke_MemberName::set_flags( mname_oop, flags); java_lang_invoke_MemberName::set_flags( mname_oop, flags);
java_lang_invoke_MemberName::set_vmtarget(mname_oop, m); 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_vmindex( mname_oop, vmindex); // vtable/itable index
...@@ -230,10 +236,11 @@ oop MethodHandles::init_method_MemberName(oop mname_oop, Method* m, bool do_disp ...@@ -230,10 +236,11 @@ oop MethodHandles::init_method_MemberName(oop mname_oop, Method* m, bool do_disp
// This is done eagerly, since it is readily available without // This is done eagerly, since it is readily available without
// constructing any new objects. // constructing any new objects.
// TO DO: maybe intern mname_oop // TO DO: maybe intern mname_oop
return mname_oop; m->method_holder()->add_member_name(mname);
return mname();
} }
Handle MethodHandles::init_method_MemberName(oop mname_oop, CallInfo& info, TRAPS) { Handle MethodHandles::init_method_MemberName(Handle mname, CallInfo& info, TRAPS) {
Handle empty; Handle empty;
if (info.resolved_appendix().not_null()) { if (info.resolved_appendix().not_null()) {
// The resolved MemberName must not be accompanied by an appendix argument, // The resolved MemberName must not be accompanied by an appendix argument,
...@@ -253,19 +260,20 @@ Handle MethodHandles::init_method_MemberName(oop mname_oop, CallInfo& info, TRAP ...@@ -253,19 +260,20 @@ Handle MethodHandles::init_method_MemberName(oop mname_oop, CallInfo& info, TRAP
} else { } else {
vmindex = info.vtable_index(); vmindex = info.vtable_index();
} }
oop res = init_method_MemberName(mname_oop, m(), (vmindex >= 0), defc()); oop res = init_method_MemberName(mname, m(), (vmindex >= 0), defc());
assert(res == NULL || (java_lang_invoke_MemberName::vmindex(res) == vmindex), ""); assert(res == NULL || (java_lang_invoke_MemberName::vmindex(res) == vmindex), "");
return Handle(THREAD, res); return Handle(THREAD, res);
} }
oop MethodHandles::init_field_MemberName(oop mname_oop, Klass* field_holder, oop MethodHandles::init_field_MemberName(Handle mname, KlassHandle field_holder,
AccessFlags mods, oop type, oop name, AccessFlags mods, oop type, oop name,
intptr_t offset, bool is_setter) { intptr_t offset, bool is_setter) {
int flags = (jushort)( mods.as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS ); 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); 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); if (is_setter) flags += ((JVM_REF_putField - JVM_REF_getField) << REFERENCE_KIND_SHIFT);
Metadata* vmtarget = field_holder; Metadata* vmtarget = field_holder();
int vmindex = offset; // determines the field uniquely when combined with static bit 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_flags(mname_oop, flags);
java_lang_invoke_MemberName::set_vmtarget(mname_oop, vmtarget); java_lang_invoke_MemberName::set_vmtarget(mname_oop, vmtarget);
java_lang_invoke_MemberName::set_vmindex(mname_oop, vmindex); java_lang_invoke_MemberName::set_vmindex(mname_oop, vmindex);
...@@ -282,10 +290,11 @@ oop MethodHandles::init_field_MemberName(oop mname_oop, Klass* field_holder, ...@@ -282,10 +290,11 @@ oop MethodHandles::init_field_MemberName(oop mname_oop, Klass* field_holder,
// Although the fieldDescriptor::_index would also identify the field, // Although the fieldDescriptor::_index would also identify the field,
// we do not use it, because it is harder to decode. // we do not use it, because it is harder to decode.
// TO DO: maybe intern mname_oop // TO DO: maybe intern mname_oop
return mname_oop; InstanceKlass::cast(field_holder())->add_member_name(mname);
return mname();
} }
Handle MethodHandles::init_field_MemberName(oop mname_oop, FieldAccessInfo& info, TRAPS) { Handle MethodHandles::init_field_MemberName(Handle mname, FieldAccessInfo& info, TRAPS) {
return Handle(); return Handle();
#if 0 // FIXME #if 0 // FIXME
KlassHandle field_holder = info.klass(); KlassHandle field_holder = info.klass();
...@@ -684,7 +693,7 @@ Handle MethodHandles::resolve_MemberName(Handle mname, TRAPS) { ...@@ -684,7 +693,7 @@ Handle MethodHandles::resolve_MemberName(Handle mname, TRAPS) {
return empty; return empty;
} }
} }
return init_method_MemberName(mname(), result, THREAD); return init_method_MemberName(mname, result, THREAD);
} }
case IS_CONSTRUCTOR: case IS_CONSTRUCTOR:
{ {
...@@ -702,7 +711,7 @@ Handle MethodHandles::resolve_MemberName(Handle mname, TRAPS) { ...@@ -702,7 +711,7 @@ Handle MethodHandles::resolve_MemberName(Handle mname, TRAPS) {
} }
} }
assert(result.is_statically_bound(), ""); assert(result.is_statically_bound(), "");
return init_method_MemberName(mname(), result, THREAD); return init_method_MemberName(mname, result, THREAD);
} }
case IS_FIELD: case IS_FIELD:
{ {
...@@ -715,7 +724,7 @@ Handle MethodHandles::resolve_MemberName(Handle mname, TRAPS) { ...@@ -715,7 +724,7 @@ Handle MethodHandles::resolve_MemberName(Handle mname, TRAPS) {
oop name = field_name_or_null(fd.name()); oop name = field_name_or_null(fd.name());
bool is_setter = (ref_kind_is_valid(ref_kind) && ref_kind_is_setter(ref_kind)); bool is_setter = (ref_kind_is_valid(ref_kind) && ref_kind_is_setter(ref_kind));
mname = Handle(THREAD, mname = Handle(THREAD,
init_field_MemberName(mname(), sel_klass(), init_field_MemberName(mname, sel_klass,
fd.access_flags(), type, name, fd.offset(), is_setter)); fd.access_flags(), type, name, fd.offset(), is_setter));
return mname; return mname;
} }
...@@ -807,16 +816,15 @@ void MethodHandles::expand_MemberName(Handle mname, int suppress, TRAPS) { ...@@ -807,16 +816,15 @@ void MethodHandles::expand_MemberName(Handle mname, int suppress, TRAPS) {
THROW_MSG(vmSymbols::java_lang_InternalError(), "unrecognized MemberName format"); THROW_MSG(vmSymbols::java_lang_InternalError(), "unrecognized MemberName format");
} }
int MethodHandles::find_MemberNames(Klass* k, int MethodHandles::find_MemberNames(KlassHandle k,
Symbol* name, Symbol* sig, Symbol* name, Symbol* sig,
int mflags, Klass* caller, int mflags, KlassHandle caller,
int skip, objArrayOop results) { int skip, objArrayHandle results) {
DEBUG_ONLY(No_Safepoint_Verifier nsv);
// this code contains no safepoints!
// %%% take caller into account! // %%% take caller into account!
if (k == NULL || !k->oop_is_instance()) return -1; Thread* thread = Thread::current();
if (k.is_null() || !k->oop_is_instance()) return -1;
int rfill = 0, rlimit = results->length(), rskip = skip; int rfill = 0, rlimit = results->length(), rskip = skip;
// overflow measurement: // overflow measurement:
...@@ -844,7 +852,7 @@ int MethodHandles::find_MemberNames(Klass* k, ...@@ -844,7 +852,7 @@ int MethodHandles::find_MemberNames(Klass* k,
} }
if ((match_flags & IS_FIELD) != 0) { if ((match_flags & IS_FIELD) != 0) {
for (FieldStream st(k, local_only, !search_intfc); !st.eos(); st.next()) { for (FieldStream st(k(), local_only, !search_intfc); !st.eos(); st.next()) {
if (name != NULL && st.name() != name) if (name != NULL && st.name() != name)
continue; continue;
if (sig != NULL && st.signature() != sig) if (sig != NULL && st.signature() != sig)
...@@ -853,15 +861,15 @@ int MethodHandles::find_MemberNames(Klass* k, ...@@ -853,15 +861,15 @@ int MethodHandles::find_MemberNames(Klass* k,
if (rskip > 0) { if (rskip > 0) {
--rskip; --rskip;
} else if (rfill < rlimit) { } else if (rfill < rlimit) {
oop result = results->obj_at(rfill++); Handle result(thread, results->obj_at(rfill++));
if (!java_lang_invoke_MemberName::is_instance(result)) if (!java_lang_invoke_MemberName::is_instance(result()))
return -99; // caller bug! return -99; // caller bug!
oop type = field_signature_type_or_null(st.signature()); oop type = field_signature_type_or_null(st.signature());
oop name = field_name_or_null(st.name()); oop name = field_name_or_null(st.name());
oop saved = MethodHandles::init_field_MemberName(result, st.klass()(), oop saved = MethodHandles::init_field_MemberName(result, st.klass(),
st.access_flags(), type, name, st.access_flags(), type, name,
st.offset()); st.offset());
if (saved != result) if (saved != result())
results->obj_at_put(rfill-1, saved); // show saved instance to user results->obj_at_put(rfill-1, saved); // show saved instance to user
} else if (++overflow >= overflow_limit) { } else if (++overflow >= overflow_limit) {
match_flags = 0; break; // got tired of looking at overflow match_flags = 0; break; // got tired of looking at overflow
...@@ -894,7 +902,7 @@ int MethodHandles::find_MemberNames(Klass* k, ...@@ -894,7 +902,7 @@ int MethodHandles::find_MemberNames(Klass* k,
} else { } else {
// caller will accept either sort; no need to adjust name // caller will accept either sort; no need to adjust name
} }
for (MethodStream st(k, local_only, !search_intfc); !st.eos(); st.next()) { for (MethodStream st(k(), local_only, !search_intfc); !st.eos(); st.next()) {
Method* m = st.method(); Method* m = st.method();
Symbol* m_name = m->name(); Symbol* m_name = m->name();
if (m_name == clinit_name) if (m_name == clinit_name)
...@@ -907,11 +915,11 @@ int MethodHandles::find_MemberNames(Klass* k, ...@@ -907,11 +915,11 @@ int MethodHandles::find_MemberNames(Klass* k,
if (rskip > 0) { if (rskip > 0) {
--rskip; --rskip;
} else if (rfill < rlimit) { } else if (rfill < rlimit) {
oop result = results->obj_at(rfill++); Handle result(thread, results->obj_at(rfill++));
if (!java_lang_invoke_MemberName::is_instance(result)) if (!java_lang_invoke_MemberName::is_instance(result()))
return -99; // caller bug! return -99; // caller bug!
oop saved = MethodHandles::init_method_MemberName(result, m, true, NULL); oop saved = MethodHandles::init_method_MemberName(result, m, true, NULL);
if (saved != result) if (saved != result())
results->obj_at_put(rfill-1, saved); // show saved instance to user results->obj_at_put(rfill-1, saved); // show saved instance to user
} else if (++overflow >= overflow_limit) { } else if (++overflow >= overflow_limit) {
match_flags = 0; break; // got tired of looking at overflow match_flags = 0; break; // got tired of looking at overflow
...@@ -922,6 +930,99 @@ int MethodHandles::find_MemberNames(Klass* k, ...@@ -922,6 +930,99 @@ int MethodHandles::find_MemberNames(Klass* k,
// return number of elements we at leasted wanted to initialize // return number of elements we at leasted wanted to initialize
return rfill + overflow; return rfill + overflow;
} }
//------------------------------------------------------------------------------
// MemberNameTable
//
MemberNameTable::MemberNameTable() : GrowableArray<jweak>(10, true) {
assert_locked_or_safepoint(MemberNameTable_lock);
}
MemberNameTable::~MemberNameTable() {
assert_locked_or_safepoint(MemberNameTable_lock);
int len = this->length();
for (int idx = 0; idx < len; idx++) {
jweak ref = this->at(idx);
JNIHandles::destroy_weak_global(ref);
}
}
// Return entry index if found, return -1 otherwise.
int MemberNameTable::find_member_name(oop mem_name) {
assert_locked_or_safepoint(MemberNameTable_lock);
int len = this->length();
for (int idx = 0; idx < len; idx++) {
jweak ref = this->at(idx);
oop entry = JNIHandles::resolve(ref);
if (entry == mem_name) {
return idx;
}
}
return -1;
}
void MemberNameTable::add_member_name(jweak mem_name_wref) {
assert_locked_or_safepoint(MemberNameTable_lock);
oop mem_name = JNIHandles::resolve(mem_name_wref);
// Each member name may appear just once: add only if not found
if (find_member_name(mem_name) == -1) {
this->append(mem_name_wref);
}
}
#if INCLUDE_JVMTI
oop MemberNameTable::find_member_name_by_method(Method* old_method) {
assert_locked_or_safepoint(MemberNameTable_lock);
oop found = NULL;
int len = this->length();
for (int idx = 0; idx < len; idx++) {
oop mem_name = JNIHandles::resolve(this->at(idx));
if (mem_name == NULL) {
continue;
}
Method* method = (Method*)java_lang_invoke_MemberName::vmtarget(mem_name);
if (method == old_method) {
found = mem_name;
break;
}
}
return found;
}
// It is called at safepoint only
void MemberNameTable::adjust_method_entries(Method** old_methods, Method** new_methods,
int methods_length, bool *trace_name_printed) {
assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
// search the MemberNameTable for uses of either obsolete or EMCP methods
for (int j = 0; j < methods_length; j++) {
Method* old_method = old_methods[j];
Method* new_method = new_methods[j];
oop mem_name = find_member_name_by_method(old_method);
if (mem_name != NULL) {
java_lang_invoke_MemberName::adjust_vmtarget(mem_name, new_method);
if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
if (!(*trace_name_printed)) {
// RC_TRACE_MESG macro has an embedded ResourceMark
RC_TRACE_MESG(("adjust: name=%s",
old_method->method_holder()->external_name()));
*trace_name_printed = true;
}
// RC_TRACE macro has an embedded ResourceMark
RC_TRACE(0x00400000, ("MemberName method update: %s(%s)",
new_method->name()->as_C_string(),
new_method->signature()->as_C_string()));
}
}
}
}
#endif // INCLUDE_JVMTI
// //
// Here are the native methods in java.lang.invoke.MethodHandleNatives // Here are the native methods in java.lang.invoke.MethodHandleNatives
// They are the private interface between this JVM and the HotSpot-specific // They are the private interface between this JVM and the HotSpot-specific
...@@ -1015,8 +1116,8 @@ JVM_ENTRY(void, MHN_init_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jobje ...@@ -1015,8 +1116,8 @@ JVM_ENTRY(void, MHN_init_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jobje
if (mname_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "mname is null"); } if (mname_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "mname is null"); }
if (target_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "target is null"); } if (target_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "target is null"); }
Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh)); Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh));
oop target_oop = JNIHandles::resolve_non_null(target_jh); Handle target(THREAD, JNIHandles::resolve_non_null(target_jh));
MethodHandles::init_MemberName(mname(), target_oop); MethodHandles::init_MemberName(mname, target);
} }
JVM_END JVM_END
...@@ -1123,7 +1224,7 @@ JVM_ENTRY(jobject, MHN_getMemberVMInfo(JNIEnv *env, jobject igcls, jobject mname ...@@ -1123,7 +1224,7 @@ JVM_ENTRY(jobject, MHN_getMemberVMInfo(JNIEnv *env, jobject igcls, jobject mname
x = ((Klass*) vmtarget)->java_mirror(); x = ((Klass*) vmtarget)->java_mirror();
} else if (vmtarget->is_method()) { } else if (vmtarget->is_method()) {
Handle mname2 = MethodHandles::new_MemberName(CHECK_NULL); Handle mname2 = MethodHandles::new_MemberName(CHECK_NULL);
x = MethodHandles::init_method_MemberName(mname2(), (Method*)vmtarget, false, NULL); x = MethodHandles::init_method_MemberName(mname2, (Method*)vmtarget, false, NULL);
} }
result->obj_at_put(1, x); result->obj_at_put(1, x);
return JNIHandles::make_local(env, result()); return JNIHandles::make_local(env, result());
...@@ -1166,8 +1267,8 @@ JVM_ENTRY(jint, MHN_getMembers(JNIEnv *env, jobject igcls, ...@@ -1166,8 +1267,8 @@ JVM_ENTRY(jint, MHN_getMembers(JNIEnv *env, jobject igcls,
// %%% TO DO // %%% TO DO
} }
int res = MethodHandles::find_MemberNames(k(), name, sig, mflags, int res = MethodHandles::find_MemberNames(k, name, sig, mflags,
caller(), skip, results()); caller, skip, results);
// TO DO: expand at least some of the MemberNames, to avoid massive callbacks // TO DO: expand at least some of the MemberNames, to avoid massive callbacks
return res; return res;
} }
......
...@@ -54,18 +54,18 @@ class MethodHandles: AllStatic { ...@@ -54,18 +54,18 @@ class MethodHandles: AllStatic {
static Handle resolve_MemberName(Handle mname, TRAPS); // compute vmtarget/vmindex from name/type static Handle resolve_MemberName(Handle mname, TRAPS); // compute vmtarget/vmindex from name/type
static void expand_MemberName(Handle mname, int suppress, TRAPS); // expand defc/name/type if missing static void expand_MemberName(Handle mname, int suppress, TRAPS); // expand defc/name/type if missing
static Handle new_MemberName(TRAPS); // must be followed by init_MemberName static Handle new_MemberName(TRAPS); // must be followed by init_MemberName
static oop init_MemberName(oop mname_oop, oop target_oop); // compute vmtarget/vmindex from target static oop init_MemberName(Handle mname_h, Handle target_h); // compute vmtarget/vmindex from target
static oop init_method_MemberName(oop mname_oop, Method* m, bool do_dispatch, static oop init_method_MemberName(Handle mname_h, Method* m, bool do_dispatch,
Klass* receiver_limit); KlassHandle receiver_limit_h);
static oop init_field_MemberName(oop mname_oop, Klass* field_holder, static oop init_field_MemberName(Handle mname_h, KlassHandle field_holder_h,
AccessFlags mods, oop type, oop name, AccessFlags mods, oop type, oop name,
intptr_t offset, bool is_setter = false); intptr_t offset, bool is_setter = false);
static Handle init_method_MemberName(oop mname_oop, CallInfo& info, TRAPS); static Handle init_method_MemberName(Handle mname_h, CallInfo& info, TRAPS);
static Handle init_field_MemberName(oop mname_oop, FieldAccessInfo& info, TRAPS); static Handle init_field_MemberName(Handle mname_h, FieldAccessInfo& info, TRAPS);
static int method_ref_kind(Method* m, bool do_dispatch_if_possible = true); static int method_ref_kind(Method* m, bool do_dispatch_if_possible = true);
static int find_MemberNames(Klass* k, Symbol* name, Symbol* sig, static int find_MemberNames(KlassHandle k, Symbol* name, Symbol* sig,
int mflags, Klass* caller, int mflags, KlassHandle caller,
int skip, objArrayOop results); int skip, objArrayHandle results);
// bit values for suppress argument to expand_MemberName: // bit values for suppress argument to expand_MemberName:
enum { _suppress_defc = 1, _suppress_name = 2, _suppress_type = 4 }; enum { _suppress_defc = 1, _suppress_name = 2, _suppress_type = 4 };
...@@ -230,4 +230,27 @@ public: ...@@ -230,4 +230,27 @@ public:
void generate(); void generate();
}; };
//------------------------------------------------------------------------------
// MemberNameTable
//
class MemberNameTable : public GrowableArray<jweak> {
public:
MemberNameTable();
~MemberNameTable();
void add_member_name(jweak mem_name_ref);
private:
int find_member_name(oop mem_name);
#if INCLUDE_JVMTI
public:
// RedefineClasses() API support:
// If a MemberName refers to old_method then update it
// to refer to new_method.
void adjust_method_entries(Method** old_methods, Method** new_methods,
int methods_length, bool *trace_name_printed);
private:
oop find_member_name_by_method(Method* old_method);
#endif // INCLUDE_JVMTI
};
#endif // SHARE_VM_PRIMS_METHODHANDLES_HPP #endif // SHARE_VM_PRIMS_METHODHANDLES_HPP
...@@ -46,6 +46,7 @@ Mutex* VMStatistic_lock = NULL; ...@@ -46,6 +46,7 @@ Mutex* VMStatistic_lock = NULL;
Mutex* JNIGlobalHandle_lock = NULL; Mutex* JNIGlobalHandle_lock = NULL;
Mutex* JNIHandleBlockFreeList_lock = NULL; Mutex* JNIHandleBlockFreeList_lock = NULL;
Mutex* JNICachedItableIndex_lock = NULL; Mutex* JNICachedItableIndex_lock = NULL;
Mutex* MemberNameTable_lock = NULL;
Mutex* JmethodIdCreation_lock = NULL; Mutex* JmethodIdCreation_lock = NULL;
Mutex* JfieldIdCreation_lock = NULL; Mutex* JfieldIdCreation_lock = NULL;
Monitor* JNICritical_lock = NULL; Monitor* JNICritical_lock = NULL;
...@@ -252,6 +253,7 @@ void mutex_init() { ...@@ -252,6 +253,7 @@ void mutex_init() {
def(Heap_lock , Monitor, nonleaf+1, false); def(Heap_lock , Monitor, nonleaf+1, false);
def(JfieldIdCreation_lock , Mutex , nonleaf+1, true ); // jfieldID, Used in VM_Operation def(JfieldIdCreation_lock , Mutex , nonleaf+1, true ); // jfieldID, Used in VM_Operation
def(JNICachedItableIndex_lock , Mutex , nonleaf+1, false); // Used to cache an itable index during JNI invoke def(JNICachedItableIndex_lock , Mutex , nonleaf+1, false); // Used to cache an itable index during JNI invoke
def(MemberNameTable_lock , Mutex , nonleaf+1, false); // Used to protect MemberNameTable
def(CompiledIC_lock , Mutex , nonleaf+2, false); // locks VtableStubs_lock, InlineCacheBuffer_lock def(CompiledIC_lock , Mutex , nonleaf+2, false); // locks VtableStubs_lock, InlineCacheBuffer_lock
def(CompileTaskAlloc_lock , Mutex , nonleaf+2, true ); def(CompileTaskAlloc_lock , Mutex , nonleaf+2, true );
......
...@@ -51,6 +51,7 @@ extern Mutex* VMStatistic_lock; // a lock used to guard statist ...@@ -51,6 +51,7 @@ extern Mutex* VMStatistic_lock; // a lock used to guard statist
extern Mutex* JNIGlobalHandle_lock; // a lock on creating JNI global handles extern Mutex* JNIGlobalHandle_lock; // a lock on creating JNI global handles
extern Mutex* JNIHandleBlockFreeList_lock; // a lock on the JNI handle block free list extern Mutex* JNIHandleBlockFreeList_lock; // a lock on the JNI handle block free list
extern Mutex* JNICachedItableIndex_lock; // a lock on caching an itable index during JNI invoke extern Mutex* JNICachedItableIndex_lock; // a lock on caching an itable index during JNI invoke
extern Mutex* MemberNameTable_lock; // a lock on the MemberNameTable updates
extern Mutex* JmethodIdCreation_lock; // a lock on creating JNI method identifiers extern Mutex* JmethodIdCreation_lock; // a lock on creating JNI method identifiers
extern Mutex* JfieldIdCreation_lock; // a lock on creating JNI static field identifiers extern Mutex* JfieldIdCreation_lock; // a lock on creating JNI static field identifiers
extern Monitor* JNICritical_lock; // a lock used while entering and exiting JNI critical regions, allows GC to sometimes get in extern Monitor* JNICritical_lock; // a lock used while entering and exiting JNI critical regions, allows GC to sometimes get in
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册