Sat, 20 Apr 2013 04:07:08 -0700
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
1.1 --- a/src/share/vm/classfile/javaClasses.cpp Fri Apr 19 16:51:27 2013 -0700 1.2 +++ b/src/share/vm/classfile/javaClasses.cpp Sat Apr 20 04:07:08 2013 -0700 1.3 @@ -2625,6 +2625,15 @@ 1.4 return (Metadata*)mname->address_field(_vmtarget_offset); 1.5 } 1.6 1.7 +#if INCLUDE_JVMTI 1.8 +// Can be executed on VM thread only 1.9 +void java_lang_invoke_MemberName::adjust_vmtarget(oop mname, Metadata* ref) { 1.10 + assert((is_instance(mname) && (flags(mname) & (MN_IS_METHOD | MN_IS_CONSTRUCTOR)) > 0), "wrong type"); 1.11 + assert(Thread::current()->is_VM_thread(), "not VM thread"); 1.12 + mname->address_field_put(_vmtarget_offset, (address)ref); 1.13 +} 1.14 +#endif // INCLUDE_JVMTI 1.15 + 1.16 void java_lang_invoke_MemberName::set_vmtarget(oop mname, Metadata* ref) { 1.17 assert(is_instance(mname), "wrong type"); 1.18 // check the type of the vmtarget
2.1 --- a/src/share/vm/classfile/javaClasses.hpp Fri Apr 19 16:51:27 2013 -0700 2.2 +++ b/src/share/vm/classfile/javaClasses.hpp Sat Apr 20 04:07:08 2013 -0700 2.3 @@ -1036,6 +1036,9 @@ 2.4 2.5 static Metadata* vmtarget(oop mname); 2.6 static void set_vmtarget(oop mname, Metadata* target); 2.7 +#if INCLUDE_JVMTI 2.8 + static void adjust_vmtarget(oop mname, Metadata* target); 2.9 +#endif // INCLUDE_JVMTI 2.10 2.11 static intptr_t vmindex(oop mname); 2.12 static void set_vmindex(oop mname, intptr_t index);
3.1 --- a/src/share/vm/oops/instanceKlass.cpp Fri Apr 19 16:51:27 2013 -0700 3.2 +++ b/src/share/vm/oops/instanceKlass.cpp Sat Apr 20 04:07:08 2013 -0700 3.3 @@ -2329,6 +2329,12 @@ 3.4 FreeHeap(jmeths); 3.5 } 3.6 3.7 + MemberNameTable* mnt = member_names(); 3.8 + if (mnt != NULL) { 3.9 + delete mnt; 3.10 + set_member_names(NULL); 3.11 + } 3.12 + 3.13 int* indices = methods_cached_itable_indices_acquire(); 3.14 if (indices != (int*)NULL) { 3.15 release_set_methods_cached_itable_indices(NULL); 3.16 @@ -2757,6 +2763,17 @@ 3.17 return NULL; 3.18 } 3.19 3.20 +void InstanceKlass::add_member_name(Handle mem_name) { 3.21 + jweak mem_name_wref = JNIHandles::make_weak_global(mem_name); 3.22 + MutexLocker ml(MemberNameTable_lock); 3.23 + DEBUG_ONLY(No_Safepoint_Verifier nsv); 3.24 + 3.25 + if (_member_names == NULL) { 3.26 + _member_names = new (ResourceObj::C_HEAP, mtClass) MemberNameTable(); 3.27 + } 3.28 + _member_names->add_member_name(mem_name_wref); 3.29 +} 3.30 + 3.31 // ----------------------------------------------------------------------------------------------------- 3.32 // Printing 3.33
4.1 --- a/src/share/vm/oops/instanceKlass.hpp Fri Apr 19 16:51:27 2013 -0700 4.2 +++ b/src/share/vm/oops/instanceKlass.hpp Sat Apr 20 04:07:08 2013 -0700 4.3 @@ -90,6 +90,7 @@ 4.4 class nmethodBucket; 4.5 class PreviousVersionNode; 4.6 class JvmtiCachedClassFieldMap; 4.7 +class MemberNameTable; 4.8 4.9 // This is used in iterators below. 4.10 class FieldClosure: public StackObj { 4.11 @@ -246,6 +247,7 @@ 4.12 int _vtable_len; // length of Java vtable (in words) 4.13 int _itable_len; // length of Java itable (in words) 4.14 OopMapCache* volatile _oop_map_cache; // OopMapCache for all methods in the klass (allocated lazily) 4.15 + MemberNameTable* _member_names; // Member names 4.16 JNIid* _jni_ids; // First JNI identifier for static fields in this class 4.17 jmethodID* _methods_jmethod_ids; // jmethodIDs corresponding to method_idnum, or NULL if none 4.18 int* _methods_cached_itable_indices; // itable_index cache for JNI invoke corresponding to methods idnum, or NULL 4.19 @@ -1028,6 +1030,11 @@ 4.20 // jvm support 4.21 jint compute_modifier_flags(TRAPS) const; 4.22 4.23 + // JSR-292 support 4.24 + MemberNameTable* member_names() { return _member_names; } 4.25 + void set_member_names(MemberNameTable* member_names) { _member_names = member_names; } 4.26 + void add_member_name(Handle member_name); 4.27 + 4.28 public: 4.29 // JVMTI support 4.30 jint jvmti_class_status() const;
5.1 --- a/src/share/vm/prims/jvmtiRedefineClasses.cpp Fri Apr 19 16:51:27 2013 -0700 5.2 +++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp Sat Apr 20 04:07:08 2013 -0700 5.3 @@ -3284,6 +3284,16 @@ 5.4 // that reference methods of the evolved class. 5.5 SystemDictionary::classes_do(adjust_cpool_cache_and_vtable, THREAD); 5.6 5.7 + // JSR-292 support 5.8 + MemberNameTable* mnt = the_class->member_names(); 5.9 + if (mnt != NULL) { 5.10 + bool trace_name_printed = false; 5.11 + mnt->adjust_method_entries(_matching_old_methods, 5.12 + _matching_new_methods, 5.13 + _matching_methods_length, 5.14 + &trace_name_printed); 5.15 + } 5.16 + 5.17 // Fix Resolution Error table also to remove old constant pools 5.18 SystemDictionary::delete_resolution_error(old_constants); 5.19
6.1 --- a/src/share/vm/prims/methodHandles.cpp Fri Apr 19 16:51:27 2013 -0700 6.2 +++ b/src/share/vm/prims/methodHandles.cpp Sat Apr 20 04:07:08 2013 -0700 6.3 @@ -29,6 +29,7 @@ 6.4 #include "interpreter/oopMapCache.hpp" 6.5 #include "memory/allocation.inline.hpp" 6.6 #include "memory/oopFactory.hpp" 6.7 +#include "prims/jvmtiRedefineClassesTrace.hpp" 6.8 #include "prims/methodHandles.hpp" 6.9 #include "runtime/compilationPolicy.hpp" 6.10 #include "runtime/javaCalls.hpp" 6.11 @@ -124,7 +125,9 @@ 6.12 return Handle(THREAD, k->allocate_instance(THREAD)); 6.13 } 6.14 6.15 -oop MethodHandles::init_MemberName(oop mname_oop, oop target_oop) { 6.16 +oop MethodHandles::init_MemberName(Handle mname, Handle target) { 6.17 + Thread* thread = Thread::current(); 6.18 + oop target_oop = target(); 6.19 Klass* target_klass = target_oop->klass(); 6.20 if (target_klass == SystemDictionary::reflect_Field_klass()) { 6.21 oop clazz = java_lang_reflect_Field::clazz(target_oop); // fd.field_holder() 6.22 @@ -132,24 +135,24 @@ 6.23 int mods = java_lang_reflect_Field::modifiers(target_oop); 6.24 oop type = java_lang_reflect_Field::type(target_oop); 6.25 oop name = java_lang_reflect_Field::name(target_oop); 6.26 - Klass* k = java_lang_Class::as_Klass(clazz); 6.27 - intptr_t offset = InstanceKlass::cast(k)->field_offset(slot); 6.28 - return init_field_MemberName(mname_oop, k, accessFlags_from(mods), type, name, offset); 6.29 + KlassHandle k(thread, java_lang_Class::as_Klass(clazz)); 6.30 + intptr_t offset = InstanceKlass::cast(k())->field_offset(slot); 6.31 + return init_field_MemberName(mname, k, accessFlags_from(mods), type, name, offset); 6.32 } else if (target_klass == SystemDictionary::reflect_Method_klass()) { 6.33 oop clazz = java_lang_reflect_Method::clazz(target_oop); 6.34 int slot = java_lang_reflect_Method::slot(target_oop); 6.35 - Klass* k = java_lang_Class::as_Klass(clazz); 6.36 - if (k != NULL && k->oop_is_instance()) { 6.37 - Method* m = InstanceKlass::cast(k)->method_with_idnum(slot); 6.38 - return init_method_MemberName(mname_oop, m, true, k); 6.39 + KlassHandle k(thread, java_lang_Class::as_Klass(clazz)); 6.40 + if (!k.is_null() && k->oop_is_instance()) { 6.41 + Method* m = InstanceKlass::cast(k())->method_with_idnum(slot); 6.42 + return init_method_MemberName(mname, m, true, k); 6.43 } 6.44 } else if (target_klass == SystemDictionary::reflect_Constructor_klass()) { 6.45 oop clazz = java_lang_reflect_Constructor::clazz(target_oop); 6.46 int slot = java_lang_reflect_Constructor::slot(target_oop); 6.47 - Klass* k = java_lang_Class::as_Klass(clazz); 6.48 - if (k != NULL && k->oop_is_instance()) { 6.49 - Method* m = InstanceKlass::cast(k)->method_with_idnum(slot); 6.50 - return init_method_MemberName(mname_oop, m, false, k); 6.51 + KlassHandle k(thread, java_lang_Class::as_Klass(clazz)); 6.52 + if (!k.is_null() && k->oop_is_instance()) { 6.53 + Method* m = InstanceKlass::cast(k())->method_with_idnum(slot); 6.54 + return init_method_MemberName(mname, m, false, k); 6.55 } 6.56 } else if (target_klass == SystemDictionary::MemberName_klass()) { 6.57 // Note: This only works if the MemberName has already been resolved. 6.58 @@ -157,17 +160,18 @@ 6.59 int flags = java_lang_invoke_MemberName::flags(target_oop); 6.60 Metadata* vmtarget=java_lang_invoke_MemberName::vmtarget(target_oop); 6.61 intptr_t vmindex = java_lang_invoke_MemberName::vmindex(target_oop); 6.62 - Klass* k = java_lang_Class::as_Klass(clazz); 6.63 + KlassHandle k(thread, java_lang_Class::as_Klass(clazz)); 6.64 int ref_kind = (flags >> REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK; 6.65 if (vmtarget == NULL) return NULL; // not resolved 6.66 if ((flags & IS_FIELD) != 0) { 6.67 assert(vmtarget->is_klass(), "field vmtarget is Klass*"); 6.68 int basic_mods = (ref_kind_is_static(ref_kind) ? JVM_ACC_STATIC : 0); 6.69 // FIXME: how does k (receiver_limit) contribute? 6.70 - return init_field_MemberName(mname_oop, (Klass*)vmtarget, accessFlags_from(basic_mods), NULL, NULL, vmindex); 6.71 + KlassHandle k_vmtarget(thread, (Klass*)vmtarget); 6.72 + return init_field_MemberName(mname, k_vmtarget, accessFlags_from(basic_mods), NULL, NULL, vmindex); 6.73 } else if ((flags & (IS_METHOD | IS_CONSTRUCTOR)) != 0) { 6.74 assert(vmtarget->is_method(), "method or constructor vmtarget is Method*"); 6.75 - return init_method_MemberName(mname_oop, (Method*)vmtarget, ref_kind_does_dispatch(ref_kind), k); 6.76 + return init_method_MemberName(mname, (Method*)vmtarget, ref_kind_does_dispatch(ref_kind), k); 6.77 } else { 6.78 return NULL; 6.79 } 6.80 @@ -175,8 +179,9 @@ 6.81 return NULL; 6.82 } 6.83 6.84 -oop MethodHandles::init_method_MemberName(oop mname_oop, Method* m, bool do_dispatch, 6.85 - Klass* receiver_limit) { 6.86 +oop MethodHandles::init_method_MemberName(Handle mname, Method* m, bool do_dispatch, 6.87 + KlassHandle receiver_limit_h) { 6.88 + Klass* receiver_limit = receiver_limit_h(); 6.89 AccessFlags mods = m->access_flags(); 6.90 int flags = (jushort)( mods.as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS ); 6.91 int vmindex = Method::nonvirtual_vtable_index; // implies never any dispatch 6.92 @@ -218,6 +223,7 @@ 6.93 flags |= CALLER_SENSITIVE; 6.94 } 6.95 6.96 + oop mname_oop = mname(); 6.97 java_lang_invoke_MemberName::set_flags( mname_oop, flags); 6.98 java_lang_invoke_MemberName::set_vmtarget(mname_oop, m); 6.99 java_lang_invoke_MemberName::set_vmindex( mname_oop, vmindex); // vtable/itable index 6.100 @@ -230,10 +236,11 @@ 6.101 // This is done eagerly, since it is readily available without 6.102 // constructing any new objects. 6.103 // TO DO: maybe intern mname_oop 6.104 - return mname_oop; 6.105 + m->method_holder()->add_member_name(mname); 6.106 + return mname(); 6.107 } 6.108 6.109 -Handle MethodHandles::init_method_MemberName(oop mname_oop, CallInfo& info, TRAPS) { 6.110 +Handle MethodHandles::init_method_MemberName(Handle mname, CallInfo& info, TRAPS) { 6.111 Handle empty; 6.112 if (info.resolved_appendix().not_null()) { 6.113 // The resolved MemberName must not be accompanied by an appendix argument, 6.114 @@ -253,19 +260,20 @@ 6.115 } else { 6.116 vmindex = info.vtable_index(); 6.117 } 6.118 - oop res = init_method_MemberName(mname_oop, m(), (vmindex >= 0), defc()); 6.119 + oop res = init_method_MemberName(mname, m(), (vmindex >= 0), defc()); 6.120 assert(res == NULL || (java_lang_invoke_MemberName::vmindex(res) == vmindex), ""); 6.121 return Handle(THREAD, res); 6.122 } 6.123 6.124 -oop MethodHandles::init_field_MemberName(oop mname_oop, Klass* field_holder, 6.125 +oop MethodHandles::init_field_MemberName(Handle mname, KlassHandle field_holder, 6.126 AccessFlags mods, oop type, oop name, 6.127 intptr_t offset, bool is_setter) { 6.128 int flags = (jushort)( mods.as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS ); 6.129 flags |= IS_FIELD | ((mods.is_static() ? JVM_REF_getStatic : JVM_REF_getField) << REFERENCE_KIND_SHIFT); 6.130 if (is_setter) flags += ((JVM_REF_putField - JVM_REF_getField) << REFERENCE_KIND_SHIFT); 6.131 - Metadata* vmtarget = field_holder; 6.132 + Metadata* vmtarget = field_holder(); 6.133 int vmindex = offset; // determines the field uniquely when combined with static bit 6.134 + oop mname_oop = mname(); 6.135 java_lang_invoke_MemberName::set_flags(mname_oop, flags); 6.136 java_lang_invoke_MemberName::set_vmtarget(mname_oop, vmtarget); 6.137 java_lang_invoke_MemberName::set_vmindex(mname_oop, vmindex); 6.138 @@ -282,10 +290,11 @@ 6.139 // Although the fieldDescriptor::_index would also identify the field, 6.140 // we do not use it, because it is harder to decode. 6.141 // TO DO: maybe intern mname_oop 6.142 - return mname_oop; 6.143 + InstanceKlass::cast(field_holder())->add_member_name(mname); 6.144 + return mname(); 6.145 } 6.146 6.147 -Handle MethodHandles::init_field_MemberName(oop mname_oop, FieldAccessInfo& info, TRAPS) { 6.148 +Handle MethodHandles::init_field_MemberName(Handle mname, FieldAccessInfo& info, TRAPS) { 6.149 return Handle(); 6.150 #if 0 // FIXME 6.151 KlassHandle field_holder = info.klass(); 6.152 @@ -684,7 +693,7 @@ 6.153 return empty; 6.154 } 6.155 } 6.156 - return init_method_MemberName(mname(), result, THREAD); 6.157 + return init_method_MemberName(mname, result, THREAD); 6.158 } 6.159 case IS_CONSTRUCTOR: 6.160 { 6.161 @@ -702,7 +711,7 @@ 6.162 } 6.163 } 6.164 assert(result.is_statically_bound(), ""); 6.165 - return init_method_MemberName(mname(), result, THREAD); 6.166 + return init_method_MemberName(mname, result, THREAD); 6.167 } 6.168 case IS_FIELD: 6.169 { 6.170 @@ -715,7 +724,7 @@ 6.171 oop name = field_name_or_null(fd.name()); 6.172 bool is_setter = (ref_kind_is_valid(ref_kind) && ref_kind_is_setter(ref_kind)); 6.173 mname = Handle(THREAD, 6.174 - init_field_MemberName(mname(), sel_klass(), 6.175 + init_field_MemberName(mname, sel_klass, 6.176 fd.access_flags(), type, name, fd.offset(), is_setter)); 6.177 return mname; 6.178 } 6.179 @@ -807,16 +816,15 @@ 6.180 THROW_MSG(vmSymbols::java_lang_InternalError(), "unrecognized MemberName format"); 6.181 } 6.182 6.183 -int MethodHandles::find_MemberNames(Klass* k, 6.184 +int MethodHandles::find_MemberNames(KlassHandle k, 6.185 Symbol* name, Symbol* sig, 6.186 - int mflags, Klass* caller, 6.187 - int skip, objArrayOop results) { 6.188 - DEBUG_ONLY(No_Safepoint_Verifier nsv); 6.189 - // this code contains no safepoints! 6.190 - 6.191 + int mflags, KlassHandle caller, 6.192 + int skip, objArrayHandle results) { 6.193 // %%% take caller into account! 6.194 6.195 - if (k == NULL || !k->oop_is_instance()) return -1; 6.196 + Thread* thread = Thread::current(); 6.197 + 6.198 + if (k.is_null() || !k->oop_is_instance()) return -1; 6.199 6.200 int rfill = 0, rlimit = results->length(), rskip = skip; 6.201 // overflow measurement: 6.202 @@ -844,7 +852,7 @@ 6.203 } 6.204 6.205 if ((match_flags & IS_FIELD) != 0) { 6.206 - for (FieldStream st(k, local_only, !search_intfc); !st.eos(); st.next()) { 6.207 + for (FieldStream st(k(), local_only, !search_intfc); !st.eos(); st.next()) { 6.208 if (name != NULL && st.name() != name) 6.209 continue; 6.210 if (sig != NULL && st.signature() != sig) 6.211 @@ -853,15 +861,15 @@ 6.212 if (rskip > 0) { 6.213 --rskip; 6.214 } else if (rfill < rlimit) { 6.215 - oop result = results->obj_at(rfill++); 6.216 - if (!java_lang_invoke_MemberName::is_instance(result)) 6.217 + Handle result(thread, results->obj_at(rfill++)); 6.218 + if (!java_lang_invoke_MemberName::is_instance(result())) 6.219 return -99; // caller bug! 6.220 oop type = field_signature_type_or_null(st.signature()); 6.221 oop name = field_name_or_null(st.name()); 6.222 - oop saved = MethodHandles::init_field_MemberName(result, st.klass()(), 6.223 + oop saved = MethodHandles::init_field_MemberName(result, st.klass(), 6.224 st.access_flags(), type, name, 6.225 st.offset()); 6.226 - if (saved != result) 6.227 + if (saved != result()) 6.228 results->obj_at_put(rfill-1, saved); // show saved instance to user 6.229 } else if (++overflow >= overflow_limit) { 6.230 match_flags = 0; break; // got tired of looking at overflow 6.231 @@ -894,7 +902,7 @@ 6.232 } else { 6.233 // caller will accept either sort; no need to adjust name 6.234 } 6.235 - for (MethodStream st(k, local_only, !search_intfc); !st.eos(); st.next()) { 6.236 + for (MethodStream st(k(), local_only, !search_intfc); !st.eos(); st.next()) { 6.237 Method* m = st.method(); 6.238 Symbol* m_name = m->name(); 6.239 if (m_name == clinit_name) 6.240 @@ -907,11 +915,11 @@ 6.241 if (rskip > 0) { 6.242 --rskip; 6.243 } else if (rfill < rlimit) { 6.244 - oop result = results->obj_at(rfill++); 6.245 - if (!java_lang_invoke_MemberName::is_instance(result)) 6.246 + Handle result(thread, results->obj_at(rfill++)); 6.247 + if (!java_lang_invoke_MemberName::is_instance(result())) 6.248 return -99; // caller bug! 6.249 oop saved = MethodHandles::init_method_MemberName(result, m, true, NULL); 6.250 - if (saved != result) 6.251 + if (saved != result()) 6.252 results->obj_at_put(rfill-1, saved); // show saved instance to user 6.253 } else if (++overflow >= overflow_limit) { 6.254 match_flags = 0; break; // got tired of looking at overflow 6.255 @@ -922,6 +930,99 @@ 6.256 // return number of elements we at leasted wanted to initialize 6.257 return rfill + overflow; 6.258 } 6.259 + 6.260 +//------------------------------------------------------------------------------ 6.261 +// MemberNameTable 6.262 +// 6.263 + 6.264 +MemberNameTable::MemberNameTable() : GrowableArray<jweak>(10, true) { 6.265 + assert_locked_or_safepoint(MemberNameTable_lock); 6.266 +} 6.267 + 6.268 +MemberNameTable::~MemberNameTable() { 6.269 + assert_locked_or_safepoint(MemberNameTable_lock); 6.270 + int len = this->length(); 6.271 + 6.272 + for (int idx = 0; idx < len; idx++) { 6.273 + jweak ref = this->at(idx); 6.274 + JNIHandles::destroy_weak_global(ref); 6.275 + } 6.276 +} 6.277 + 6.278 +// Return entry index if found, return -1 otherwise. 6.279 +int MemberNameTable::find_member_name(oop mem_name) { 6.280 + assert_locked_or_safepoint(MemberNameTable_lock); 6.281 + int len = this->length(); 6.282 + 6.283 + for (int idx = 0; idx < len; idx++) { 6.284 + jweak ref = this->at(idx); 6.285 + oop entry = JNIHandles::resolve(ref); 6.286 + if (entry == mem_name) { 6.287 + return idx; 6.288 + } 6.289 + } 6.290 + return -1; 6.291 +} 6.292 + 6.293 +void MemberNameTable::add_member_name(jweak mem_name_wref) { 6.294 + assert_locked_or_safepoint(MemberNameTable_lock); 6.295 + oop mem_name = JNIHandles::resolve(mem_name_wref); 6.296 + 6.297 + // Each member name may appear just once: add only if not found 6.298 + if (find_member_name(mem_name) == -1) { 6.299 + this->append(mem_name_wref); 6.300 + } 6.301 +} 6.302 + 6.303 +#if INCLUDE_JVMTI 6.304 +oop MemberNameTable::find_member_name_by_method(Method* old_method) { 6.305 + assert_locked_or_safepoint(MemberNameTable_lock); 6.306 + oop found = NULL; 6.307 + int len = this->length(); 6.308 + 6.309 + for (int idx = 0; idx < len; idx++) { 6.310 + oop mem_name = JNIHandles::resolve(this->at(idx)); 6.311 + if (mem_name == NULL) { 6.312 + continue; 6.313 + } 6.314 + Method* method = (Method*)java_lang_invoke_MemberName::vmtarget(mem_name); 6.315 + if (method == old_method) { 6.316 + found = mem_name; 6.317 + break; 6.318 + } 6.319 + } 6.320 + return found; 6.321 +} 6.322 + 6.323 +// It is called at safepoint only 6.324 +void MemberNameTable::adjust_method_entries(Method** old_methods, Method** new_methods, 6.325 + int methods_length, bool *trace_name_printed) { 6.326 + assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint"); 6.327 + // search the MemberNameTable for uses of either obsolete or EMCP methods 6.328 + for (int j = 0; j < methods_length; j++) { 6.329 + Method* old_method = old_methods[j]; 6.330 + Method* new_method = new_methods[j]; 6.331 + oop mem_name = find_member_name_by_method(old_method); 6.332 + if (mem_name != NULL) { 6.333 + java_lang_invoke_MemberName::adjust_vmtarget(mem_name, new_method); 6.334 + 6.335 + if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) { 6.336 + if (!(*trace_name_printed)) { 6.337 + // RC_TRACE_MESG macro has an embedded ResourceMark 6.338 + RC_TRACE_MESG(("adjust: name=%s", 6.339 + old_method->method_holder()->external_name())); 6.340 + *trace_name_printed = true; 6.341 + } 6.342 + // RC_TRACE macro has an embedded ResourceMark 6.343 + RC_TRACE(0x00400000, ("MemberName method update: %s(%s)", 6.344 + new_method->name()->as_C_string(), 6.345 + new_method->signature()->as_C_string())); 6.346 + } 6.347 + } 6.348 + } 6.349 +} 6.350 +#endif // INCLUDE_JVMTI 6.351 + 6.352 // 6.353 // Here are the native methods in java.lang.invoke.MethodHandleNatives 6.354 // They are the private interface between this JVM and the HotSpot-specific 6.355 @@ -1015,8 +1116,8 @@ 6.356 if (mname_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "mname is null"); } 6.357 if (target_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "target is null"); } 6.358 Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh)); 6.359 - oop target_oop = JNIHandles::resolve_non_null(target_jh); 6.360 - MethodHandles::init_MemberName(mname(), target_oop); 6.361 + Handle target(THREAD, JNIHandles::resolve_non_null(target_jh)); 6.362 + MethodHandles::init_MemberName(mname, target); 6.363 } 6.364 JVM_END 6.365 6.366 @@ -1123,7 +1224,7 @@ 6.367 x = ((Klass*) vmtarget)->java_mirror(); 6.368 } else if (vmtarget->is_method()) { 6.369 Handle mname2 = MethodHandles::new_MemberName(CHECK_NULL); 6.370 - x = MethodHandles::init_method_MemberName(mname2(), (Method*)vmtarget, false, NULL); 6.371 + x = MethodHandles::init_method_MemberName(mname2, (Method*)vmtarget, false, NULL); 6.372 } 6.373 result->obj_at_put(1, x); 6.374 return JNIHandles::make_local(env, result()); 6.375 @@ -1166,8 +1267,8 @@ 6.376 // %%% TO DO 6.377 } 6.378 6.379 - int res = MethodHandles::find_MemberNames(k(), name, sig, mflags, 6.380 - caller(), skip, results()); 6.381 + int res = MethodHandles::find_MemberNames(k, name, sig, mflags, 6.382 + caller, skip, results); 6.383 // TO DO: expand at least some of the MemberNames, to avoid massive callbacks 6.384 return res; 6.385 }
7.1 --- a/src/share/vm/prims/methodHandles.hpp Fri Apr 19 16:51:27 2013 -0700 7.2 +++ b/src/share/vm/prims/methodHandles.hpp Sat Apr 20 04:07:08 2013 -0700 7.3 @@ -54,23 +54,23 @@ 7.4 static Handle resolve_MemberName(Handle mname, TRAPS); // compute vmtarget/vmindex from name/type 7.5 static void expand_MemberName(Handle mname, int suppress, TRAPS); // expand defc/name/type if missing 7.6 static Handle new_MemberName(TRAPS); // must be followed by init_MemberName 7.7 - static oop init_MemberName(oop mname_oop, oop target_oop); // compute vmtarget/vmindex from target 7.8 - static oop init_method_MemberName(oop mname_oop, Method* m, bool do_dispatch, 7.9 - Klass* receiver_limit); 7.10 - static oop init_field_MemberName(oop mname_oop, Klass* field_holder, 7.11 + static oop init_MemberName(Handle mname_h, Handle target_h); // compute vmtarget/vmindex from target 7.12 + static oop init_method_MemberName(Handle mname_h, Method* m, bool do_dispatch, 7.13 + KlassHandle receiver_limit_h); 7.14 + static oop init_field_MemberName(Handle mname_h, KlassHandle field_holder_h, 7.15 AccessFlags mods, oop type, oop name, 7.16 intptr_t offset, bool is_setter = false); 7.17 - static Handle init_method_MemberName(oop mname_oop, CallInfo& info, TRAPS); 7.18 - static Handle init_field_MemberName(oop mname_oop, FieldAccessInfo& info, TRAPS); 7.19 + static Handle init_method_MemberName(Handle mname_h, CallInfo& info, TRAPS); 7.20 + static Handle init_field_MemberName(Handle mname_h, FieldAccessInfo& info, TRAPS); 7.21 static int method_ref_kind(Method* m, bool do_dispatch_if_possible = true); 7.22 - static int find_MemberNames(Klass* k, Symbol* name, Symbol* sig, 7.23 - int mflags, Klass* caller, 7.24 - int skip, objArrayOop results); 7.25 + static int find_MemberNames(KlassHandle k, Symbol* name, Symbol* sig, 7.26 + int mflags, KlassHandle caller, 7.27 + int skip, objArrayHandle results); 7.28 // bit values for suppress argument to expand_MemberName: 7.29 enum { _suppress_defc = 1, _suppress_name = 2, _suppress_type = 4 }; 7.30 7.31 // Generate MethodHandles adapters. 7.32 - static void generate_adapters(); 7.33 + static void generate_adapters(); 7.34 7.35 // Called from MethodHandlesAdapterGenerator. 7.36 static address generate_method_handle_interpreter_entry(MacroAssembler* _masm, vmIntrinsics::ID iid); 7.37 @@ -230,4 +230,27 @@ 7.38 void generate(); 7.39 }; 7.40 7.41 +//------------------------------------------------------------------------------ 7.42 +// MemberNameTable 7.43 +// 7.44 +class MemberNameTable : public GrowableArray<jweak> { 7.45 + public: 7.46 + MemberNameTable(); 7.47 + ~MemberNameTable(); 7.48 + void add_member_name(jweak mem_name_ref); 7.49 + private: 7.50 + int find_member_name(oop mem_name); 7.51 + 7.52 +#if INCLUDE_JVMTI 7.53 + public: 7.54 + // RedefineClasses() API support: 7.55 + // If a MemberName refers to old_method then update it 7.56 + // to refer to new_method. 7.57 + void adjust_method_entries(Method** old_methods, Method** new_methods, 7.58 + int methods_length, bool *trace_name_printed); 7.59 + private: 7.60 + oop find_member_name_by_method(Method* old_method); 7.61 +#endif // INCLUDE_JVMTI 7.62 +}; 7.63 + 7.64 #endif // SHARE_VM_PRIMS_METHODHANDLES_HPP
8.1 --- a/src/share/vm/runtime/mutexLocker.cpp Fri Apr 19 16:51:27 2013 -0700 8.2 +++ b/src/share/vm/runtime/mutexLocker.cpp Sat Apr 20 04:07:08 2013 -0700 8.3 @@ -46,6 +46,7 @@ 8.4 Mutex* JNIGlobalHandle_lock = NULL; 8.5 Mutex* JNIHandleBlockFreeList_lock = NULL; 8.6 Mutex* JNICachedItableIndex_lock = NULL; 8.7 +Mutex* MemberNameTable_lock = NULL; 8.8 Mutex* JmethodIdCreation_lock = NULL; 8.9 Mutex* JfieldIdCreation_lock = NULL; 8.10 Monitor* JNICritical_lock = NULL; 8.11 @@ -252,6 +253,7 @@ 8.12 def(Heap_lock , Monitor, nonleaf+1, false); 8.13 def(JfieldIdCreation_lock , Mutex , nonleaf+1, true ); // jfieldID, Used in VM_Operation 8.14 def(JNICachedItableIndex_lock , Mutex , nonleaf+1, false); // Used to cache an itable index during JNI invoke 8.15 + def(MemberNameTable_lock , Mutex , nonleaf+1, false); // Used to protect MemberNameTable 8.16 8.17 def(CompiledIC_lock , Mutex , nonleaf+2, false); // locks VtableStubs_lock, InlineCacheBuffer_lock 8.18 def(CompileTaskAlloc_lock , Mutex , nonleaf+2, true );
9.1 --- a/src/share/vm/runtime/mutexLocker.hpp Fri Apr 19 16:51:27 2013 -0700 9.2 +++ b/src/share/vm/runtime/mutexLocker.hpp Sat Apr 20 04:07:08 2013 -0700 9.3 @@ -51,6 +51,7 @@ 9.4 extern Mutex* JNIGlobalHandle_lock; // a lock on creating JNI global handles 9.5 extern Mutex* JNIHandleBlockFreeList_lock; // a lock on the JNI handle block free list 9.6 extern Mutex* JNICachedItableIndex_lock; // a lock on caching an itable index during JNI invoke 9.7 +extern Mutex* MemberNameTable_lock; // a lock on the MemberNameTable updates 9.8 extern Mutex* JmethodIdCreation_lock; // a lock on creating JNI method identifiers 9.9 extern Mutex* JfieldIdCreation_lock; // a lock on creating JNI static field identifiers 9.10 extern Monitor* JNICritical_lock; // a lock used while entering and exiting JNI critical regions, allows GC to sometimes get in