8073705: more performance issues in class redefinition
authorsspitsyn
Mon, 27 Apr 2015 19:51:00 -0700
changeset 30289 10b7b61d759a
parent 30288 476c276de939
child 30290 79e3c82e17aa
8073705: more performance issues in class redefinition Summary: Optimize the method pointer adjustments for prev klass versions and MNT Reviewed-by: dcubed, coleenp
hotspot/src/share/vm/classfile/javaClasses.cpp
hotspot/src/share/vm/classfile/javaClasses.hpp
hotspot/src/share/vm/oops/cpCache.cpp
hotspot/src/share/vm/oops/cpCache.hpp
hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp
hotspot/src/share/vm/prims/methodHandles.cpp
hotspot/src/share/vm/prims/methodHandles.hpp
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp	Mon Apr 27 09:02:41 2015 -0700
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp	Mon Apr 27 19:51:00 2015 -0700
@@ -2831,33 +2831,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
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp	Mon Apr 27 09:02:41 2015 -0700
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp	Mon Apr 27 19:51:00 2015 -0700
@@ -1092,10 +1092,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);
--- a/hotspot/src/share/vm/oops/cpCache.cpp	Mon Apr 27 09:02:41 2015 -0700
+++ b/hotspot/src/share/vm/oops/cpCache.cpp	Mon Apr 27 19:51:00 2015 -0700
@@ -606,44 +606,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);
--- a/hotspot/src/share/vm/oops/cpCache.hpp	Mon Apr 27 09:02:41 2015 -0700
+++ b/hotspot/src/share/vm/oops/cpCache.hpp	Mon Apr 27 19:51:00 2015 -0700
@@ -477,8 +477,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();
--- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp	Mon Apr 27 09:02:41 2015 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp	Mon Apr 27 19:51:00 2015 -0700
@@ -3433,10 +3433,7 @@
          pv_node = pv_node->previous_versions()) {
       cp_cache = pv_node->constants()->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(pv_node, &trace_name_printed);
       }
     }
   }
@@ -4085,10 +4082,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
--- a/hotspot/src/share/vm/prims/methodHandles.cpp	Mon Apr 27 09:02:41 2015 -0700
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp	Mon Apr 27 19:51:00 2015 -0700
@@ -35,6 +35,7 @@
 #include "oops/objArrayOop.inline.hpp"
 #include "oops/oop.inline.hpp"
 #include "prims/methodHandles.hpp"
+#include "prims/jvmtiRedefineClassesTrace.hpp"
 #include "runtime/compilationPolicy.hpp"
 #include "runtime/javaCalls.hpp"
 #include "runtime/reflection.hpp"
@@ -965,21 +966,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()));
     }
   }
 }
--- a/hotspot/src/share/vm/prims/methodHandles.hpp	Mon Apr 27 09:02:41 2015 -0700
+++ b/hotspot/src/share/vm/prims/methodHandles.hpp	Mon Apr 27 19:51:00 2015 -0700
@@ -238,10 +238,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
 };