From 138a1f59d4c325d77c830c897b67334a928c7536 Mon Sep 17 00:00:00 2001 From: sspitsyn Date: Thu, 30 Apr 2015 03:31:58 -0700 Subject: [PATCH] 8073705: more performance issues in class redefinition Summary: Optimize the method pointer adjustments for prev klass versions and MNT Reviewed-by: dcubed, coleenp --- src/share/vm/classfile/javaClasses.cpp | 27 ------------- src/share/vm/classfile/javaClasses.hpp | 4 -- src/share/vm/oops/cpCache.cpp | 38 ----------------- src/share/vm/oops/cpCache.hpp | 2 - src/share/vm/prims/jvmtiRedefineClasses.cpp | 10 +---- src/share/vm/prims/methodHandles.cpp | 45 +++++++++++++++------ src/share/vm/prims/methodHandles.hpp | 6 +-- 7 files changed, 37 insertions(+), 95 deletions(-) diff --git a/src/share/vm/classfile/javaClasses.cpp b/src/share/vm/classfile/javaClasses.cpp index e94d32c64..3ffca687e 100644 --- a/src/share/vm/classfile/javaClasses.cpp +++ b/src/share/vm/classfile/javaClasses.cpp @@ -2801,33 +2801,6 @@ bool java_lang_invoke_MemberName::is_method(oop mname) { 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 --git a/src/share/vm/classfile/javaClasses.hpp b/src/share/vm/classfile/javaClasses.hpp index 5d489c7c4..9a8b248ff 100644 --- a/src/share/vm/classfile/javaClasses.hpp +++ b/src/share/vm/classfile/javaClasses.hpp @@ -1096,10 +1096,6 @@ class java_lang_invoke_MemberName: AllStatic { 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 --git a/src/share/vm/oops/cpCache.cpp b/src/share/vm/oops/cpCache.cpp index 59eb5747f..d0c77501e 100644 --- a/src/share/vm/oops/cpCache.cpp +++ b/src/share/vm/oops/cpCache.cpp @@ -602,44 +602,6 @@ void ConstantPoolCache::initialize(const intArray& inverse_index_map, #if INCLUDE_JVMTI // 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) { diff --git a/src/share/vm/oops/cpCache.hpp b/src/share/vm/oops/cpCache.hpp index 6aed2cf44..1d5f8013e 100644 --- a/src/share/vm/oops/cpCache.hpp +++ b/src/share/vm/oops/cpCache.hpp @@ -476,8 +476,6 @@ class ConstantPoolCache: public MetaspaceObj { // 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 --git a/src/share/vm/prims/jvmtiRedefineClasses.cpp b/src/share/vm/prims/jvmtiRedefineClasses.cpp index ba702135c..c16482616 100644 --- a/src/share/vm/prims/jvmtiRedefineClasses.cpp +++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp @@ -3433,10 +3433,7 @@ void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) { 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 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass, 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 --git a/src/share/vm/prims/methodHandles.cpp b/src/share/vm/prims/methodHandles.cpp index 7c95d515f..62aece732 100644 --- a/src/share/vm/prims/methodHandles.cpp +++ b/src/share/vm/prims/methodHandles.cpp @@ -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 @@ void MemberNameTable::add_member_name(jweak mem_name_wref) { #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]; - - // 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); + 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()); + + 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 --git a/src/share/vm/prims/methodHandles.hpp b/src/share/vm/prims/methodHandles.hpp index 9caf8004e..c28d29460 100644 --- a/src/share/vm/prims/methodHandles.hpp +++ b/src/share/vm/prims/methodHandles.hpp @@ -240,10 +240,8 @@ class MemberNameTable : public GrowableArray { #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 }; -- GitLab