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

Sat, 20 Apr 2013 04:07:08 -0700

author
sspitsyn
date
Sat, 20 Apr 2013 04:07:08 -0700
changeset 4965
6337ca4dcad8
parent 4964
5b6512efcdc4
child 4966
a527ddd44e07

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

src/share/vm/classfile/javaClasses.cpp file | annotate | diff | comparison | revisions
src/share/vm/classfile/javaClasses.hpp file | annotate | diff | comparison | revisions
src/share/vm/oops/instanceKlass.cpp file | annotate | diff | comparison | revisions
src/share/vm/oops/instanceKlass.hpp file | annotate | diff | comparison | revisions
src/share/vm/prims/jvmtiRedefineClasses.cpp file | annotate | diff | comparison | revisions
src/share/vm/prims/methodHandles.cpp file | annotate | diff | comparison | revisions
src/share/vm/prims/methodHandles.hpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/mutexLocker.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/mutexLocker.hpp file | annotate | diff | comparison | revisions
     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

mercurial