# HG changeset patch # User sspitsyn # Date 1430389918 25200 # Node ID 157895117ad57dcb22def10fbfd3974ed74df46e # Parent 231481a06214be5778c3641acc54650f7421606e 8073705: more performance issues in class redefinition Summary: Optimize the method pointer adjustments for prev klass versions and MNT Reviewed-by: dcubed, coleenp diff -r 231481a06214 -r 157895117ad5 src/share/vm/classfile/javaClasses.cpp --- a/src/share/vm/classfile/javaClasses.cpp Wed Apr 29 11:22:15 2015 +0200 +++ b/src/share/vm/classfile/javaClasses.cpp Thu Apr 30 03:31:58 2015 -0700 @@ -2801,33 +2801,6 @@ return (flags(mname) & (MN_IS_METHOD | MN_IS_CONSTRUCTOR)) > 0; } -#if INCLUDE_JVMTI -// Can be executed on VM thread only -void java_lang_invoke_MemberName::adjust_vmtarget(oop mname, Method* old_method, - Method* new_method, bool* trace_name_printed) { - assert(is_method(mname), "wrong type"); - assert(Thread::current()->is_VM_thread(), "not VM thread"); - - Method* target = (Method*)mname->address_field(_vmtarget_offset); - if (target == old_method) { - mname->address_field_put(_vmtarget_offset, (address)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 - void java_lang_invoke_MemberName::set_vmtarget(oop mname, Metadata* ref) { assert(is_instance(mname), "wrong type"); // check the type of the vmtarget diff -r 231481a06214 -r 157895117ad5 src/share/vm/classfile/javaClasses.hpp --- a/src/share/vm/classfile/javaClasses.hpp Wed Apr 29 11:22:15 2015 +0200 +++ b/src/share/vm/classfile/javaClasses.hpp Thu Apr 30 03:31:58 2015 -0700 @@ -1096,10 +1096,6 @@ static Metadata* vmtarget(oop mname); static void set_vmtarget(oop mname, Metadata* target); -#if INCLUDE_JVMTI - static void adjust_vmtarget(oop mname, Method* old_method, Method* new_method, - bool* trace_name_printed); -#endif // INCLUDE_JVMTI static intptr_t vmindex(oop mname); static void set_vmindex(oop mname, intptr_t index); diff -r 231481a06214 -r 157895117ad5 src/share/vm/oops/cpCache.cpp --- a/src/share/vm/oops/cpCache.cpp Wed Apr 29 11:22:15 2015 +0200 +++ b/src/share/vm/oops/cpCache.cpp Thu Apr 30 03:31:58 2015 -0700 @@ -604,44 +604,6 @@ // RedefineClasses() API support: // If any entry of this ConstantPoolCache points to any of // old_methods, replace it with the corresponding new_method. -void ConstantPoolCache::adjust_method_entries(Method** old_methods, Method** new_methods, - int methods_length, bool * trace_name_printed) { - - if (methods_length == 0) { - // nothing to do if there are no methods - return; - } - - // get shorthand for the interesting class - Klass* old_holder = old_methods[0]->method_holder(); - - for (int i = 0; i < length(); i++) { - if (entry_at(i)->get_interesting_method_entry(old_holder) == NULL) { - // skip uninteresting methods - continue; - } - - // The ConstantPoolCache contains entries for several different - // things, but we only care about methods. In fact, we only care - // about methods in the same class as the one that contains the - // old_methods. At this point, we have an interesting entry. - - for (int j = 0; j < methods_length; j++) { - Method* old_method = old_methods[j]; - Method* new_method = new_methods[j]; - - if (entry_at(i)->adjust_method_entry(old_method, new_method, - trace_name_printed)) { - // current old_method matched this entry and we updated it so - // break out and get to the next interesting entry if there one - break; - } - } - } -} - -// If any entry of this ConstantPoolCache points to any of -// old_methods, replace it with the corresponding new_method. void ConstantPoolCache::adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed) { for (int i = 0; i < length(); i++) { ConstantPoolCacheEntry* entry = entry_at(i); diff -r 231481a06214 -r 157895117ad5 src/share/vm/oops/cpCache.hpp --- a/src/share/vm/oops/cpCache.hpp Wed Apr 29 11:22:15 2015 +0200 +++ b/src/share/vm/oops/cpCache.hpp Thu Apr 30 03:31:58 2015 -0700 @@ -476,8 +476,6 @@ // trace_name_printed is set to true if the current call has // printed the klass name so that other routines in the adjust_* // group don't print the klass name. - void adjust_method_entries(Method** old_methods, Method** new_methods, - int methods_length, bool* trace_name_printed); void adjust_method_entries(InstanceKlass* holder, bool* trace_name_printed); bool check_no_old_or_obsolete_entries(); void dump_cache(); diff -r 231481a06214 -r 157895117ad5 src/share/vm/prims/jvmtiRedefineClasses.cpp --- a/src/share/vm/prims/jvmtiRedefineClasses.cpp Wed Apr 29 11:22:15 2015 +0200 +++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp Thu Apr 30 03:31:58 2015 -0700 @@ -3433,10 +3433,7 @@ other_cp = pv_node->prev_constant_pool(); cp_cache = other_cp->cache(); if (cp_cache != NULL) { - cp_cache->adjust_method_entries(_matching_old_methods, - _matching_new_methods, - _matching_methods_length, - &trace_name_printed); + cp_cache->adjust_method_entries(other_cp->pool_holder(), &trace_name_printed); } } } @@ -4071,10 +4068,7 @@ 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); + mnt->adjust_method_entries(the_class(), &trace_name_printed); } // Fix Resolution Error table also to remove old constant pools diff -r 231481a06214 -r 157895117ad5 src/share/vm/prims/methodHandles.cpp --- a/src/share/vm/prims/methodHandles.cpp Wed Apr 29 11:22:15 2015 +0200 +++ b/src/share/vm/prims/methodHandles.cpp Thu Apr 30 03:31:58 2015 -0700 @@ -30,6 +30,7 @@ #include "memory/allocation.inline.hpp" #include "memory/oopFactory.hpp" #include "prims/methodHandles.hpp" +#include "prims/jvmtiRedefineClassesTrace.hpp" #include "runtime/compilationPolicy.hpp" #include "runtime/javaCalls.hpp" #include "runtime/reflection.hpp" @@ -955,21 +956,41 @@ #if INCLUDE_JVMTI // It is called at safepoint only for RedefineClasses -void MemberNameTable::adjust_method_entries(Method** old_methods, Method** new_methods, - int methods_length, bool *trace_name_printed) { +void MemberNameTable::adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed) { assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint"); // For each redefined method - for (int j = 0; j < methods_length; j++) { - Method* old_method = old_methods[j]; - Method* new_method = new_methods[j]; + for (int idx = 0; idx < length(); idx++) { + oop mem_name = JNIHandles::resolve(this->at(idx)); + if (mem_name == NULL) { + continue; + } + Method* old_method = (Method*)java_lang_invoke_MemberName::vmtarget(mem_name); + + if (old_method == NULL || !old_method->is_old()) { + continue; // skip uninteresting entries + } + if (old_method->is_deleted()) { + // skip entries with deleted methods + continue; + } + Method* new_method = holder->method_with_idnum(old_method->orig_method_idnum()); - // search the MemberNameTable for uses of either obsolete or EMCP methods - for (int idx = 0; idx < length(); idx++) { - oop mem_name = JNIHandles::resolve(this->at(idx)); - if (mem_name != NULL) { - java_lang_invoke_MemberName::adjust_vmtarget(mem_name, old_method, new_method, - trace_name_printed); + assert(new_method != NULL, "method_with_idnum() should not be NULL"); + assert(old_method != new_method, "sanity check"); + + java_lang_invoke_MemberName::set_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())); } } } diff -r 231481a06214 -r 157895117ad5 src/share/vm/prims/methodHandles.hpp --- a/src/share/vm/prims/methodHandles.hpp Wed Apr 29 11:22:15 2015 +0200 +++ b/src/share/vm/prims/methodHandles.hpp Thu Apr 30 03:31:58 2015 -0700 @@ -240,10 +240,8 @@ #if INCLUDE_JVMTI // 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); + // If a MemberName refers to old_method then update it to refer to new_method. + void adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed); #endif // INCLUDE_JVMTI };