src/hotspot/share/prims/jvmtiRedefineClasses.cpp
changeset 53904 9c3fe09f69bc
parent 53838 c8c9bd65c198
child 53924 09cba396916f
--- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp	Fri Feb 22 11:07:18 2019 -0800
+++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp	Fri Feb 22 13:56:08 2019 -0500
@@ -62,10 +62,11 @@
 Method**  VM_RedefineClasses::_matching_new_methods = NULL;
 Method**  VM_RedefineClasses::_deleted_methods      = NULL;
 Method**  VM_RedefineClasses::_added_methods        = NULL;
-int         VM_RedefineClasses::_matching_methods_length = 0;
-int         VM_RedefineClasses::_deleted_methods_length  = 0;
-int         VM_RedefineClasses::_added_methods_length    = 0;
-Klass*      VM_RedefineClasses::_the_class = NULL;
+int       VM_RedefineClasses::_matching_methods_length = 0;
+int       VM_RedefineClasses::_deleted_methods_length  = 0;
+int       VM_RedefineClasses::_added_methods_length    = 0;
+bool      VM_RedefineClasses::_has_redefined_Object = false;
+bool      VM_RedefineClasses::_has_null_class_loader = false;
 
 
 VM_RedefineClasses::VM_RedefineClasses(jint class_count,
@@ -76,6 +77,9 @@
   _class_load_kind = class_load_kind;
   _any_class_has_resolved_methods = false;
   _res = JVMTI_ERROR_NONE;
+  _the_class = NULL;
+  _has_redefined_Object = false;
+  _has_null_class_loader = false;
 }
 
 static inline InstanceKlass* get_ik(jclass def) {
@@ -214,11 +218,12 @@
   // Flush all compiled code that depends on the classes redefined.
   flush_dependent_code();
 
-  // Clean out MethodData pointing to old Method*
+  // Adjust constantpool caches and vtables for all classes
+  // that reference methods of the evolved classes.
   // Have to do this after all classes are redefined and all methods that
   // are redefined are marked as old.
-  MethodDataCleaner clean_weak_method_links;
-  ClassLoaderDataGraph::classes_do(&clean_weak_method_links);
+  AdjustAndCleanMetadata adjust_and_clean_metadata(thread);
+  ClassLoaderDataGraph::classes_do(&adjust_and_clean_metadata);
 
   // JSR-292 support
   if (_any_class_has_resolved_methods) {
@@ -3415,25 +3420,35 @@
 // Unevolving classes may point to methods of the_class directly
 // from their constant pool caches, itables, and/or vtables. We
 // use the ClassLoaderDataGraph::classes_do() facility and this helper
-// to fix up these pointers.
+// to fix up these pointers.  MethodData also points to old methods and
+// must be cleaned.
 
 // Adjust cpools and vtables closure
-void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) {
+void VM_RedefineClasses::AdjustAndCleanMetadata::do_klass(Klass* k) {
 
   // This is a very busy routine. We don't want too much tracing
   // printed out.
   bool trace_name_printed = false;
-  InstanceKlass *the_class = InstanceKlass::cast(_the_class);
 
   // If the class being redefined is java.lang.Object, we need to fix all
   // array class vtables also
-  if (k->is_array_klass() && _the_class == SystemDictionary::Object_klass()) {
-    k->vtable().adjust_method_entries(the_class, &trace_name_printed);
+  if (k->is_array_klass() && _has_redefined_Object) {
+    k->vtable().adjust_method_entries(&trace_name_printed);
 
   } else if (k->is_instance_klass()) {
     HandleMark hm(_thread);
     InstanceKlass *ik = InstanceKlass::cast(k);
 
+    // Clean MethodData of this class's methods so they don't refer to
+    // old methods that are no longer running.
+    Array<Method*>* methods = ik->methods();
+    int num_methods = methods->length();
+    for (int index = 0; index < num_methods; ++index) {
+      if (methods->at(index)->method_data() != NULL) {
+        methods->at(index)->method_data()->clean_weak_method_links();
+      }
+    }
+
     // HotSpot specific optimization! HotSpot does not currently
     // support delegation from the bootstrap class loader to a
     // user-defined class loader. This means that if the bootstrap
@@ -3446,57 +3461,29 @@
     // If the current class being redefined has a user-defined class
     // loader as its defining class loader, then we can skip all
     // classes loaded by the bootstrap class loader.
-    bool is_user_defined = (_the_class->class_loader() != NULL);
-    if (is_user_defined && ik->class_loader() == NULL) {
+    if (!_has_null_class_loader && ik->class_loader() == NULL) {
       return;
     }
 
-    // Fix the vtable embedded in the_class and subclasses of the_class,
-    // if one exists. We discard scratch_class and we don't keep an
-    // InstanceKlass around to hold obsolete methods so we don't have
-    // any other InstanceKlass embedded vtables to update. The vtable
-    // holds the Method*s for virtual (but not final) methods.
-    // Default methods, or concrete methods in interfaces are stored
-    // in the vtable, so if an interface changes we need to check
-    // adjust_method_entries() for every InstanceKlass, which will also
-    // adjust the default method vtable indices.
-    // We also need to adjust any default method entries that are
-    // not yet in the vtable, because the vtable setup is in progress.
-    // This must be done after we adjust the default_methods and
-    // default_vtable_indices for methods already in the vtable.
-    // If redefining Unsafe, walk all the vtables looking for entries.
-    if (ik->vtable_length() > 0 && (_the_class->is_interface()
-        || _the_class == SystemDictionary::internal_Unsafe_klass()
-        || ik->is_subtype_of(_the_class))) {
-      // ik->vtable() creates a wrapper object; rm cleans it up
-      ResourceMark rm(_thread);
-
-      ik->vtable().adjust_method_entries(the_class, &trace_name_printed);
-      ik->adjust_default_methods(the_class, &trace_name_printed);
+    // Adjust all vtables, default methods and itables, to clean out old methods.
+    ResourceMark rm(_thread);
+    if (ik->vtable_length() > 0) {
+      ik->vtable().adjust_method_entries(&trace_name_printed);
+      ik->adjust_default_methods(&trace_name_printed);
     }
 
-    // If the current class has an itable and we are either redefining an
-    // interface or if the current class is a subclass of the_class, then
-    // we potentially have to fix the itable. If we are redefining an
-    // interface, then we have to call adjust_method_entries() for
-    // every InstanceKlass that has an itable since there isn't a
-    // subclass relationship between an interface and an InstanceKlass.
-    // If redefining Unsafe, walk all the itables looking for entries.
-    if (ik->itable_length() > 0 && (_the_class->is_interface()
-        || _the_class == SystemDictionary::internal_Unsafe_klass()
-        || ik->is_subclass_of(_the_class))) {
-      ResourceMark rm(_thread);
-      ik->itable().adjust_method_entries(the_class, &trace_name_printed);
+    if (ik->itable_length() > 0) {
+      ik->itable().adjust_method_entries(&trace_name_printed);
     }
 
     // The constant pools in other classes (other_cp) can refer to
-    // methods in the_class. We have to update method information in
+    // old methods.  We have to update method information in
     // other_cp's cache. If other_cp has a previous version, then we
     // have to repeat the process for each previous version. The
     // constant pool cache holds the Method*s for non-virtual
     // methods and for virtual, final methods.
     //
-    // Special case: if the current class is the_class, then new_cp
+    // Special case: if the current class being redefined, then new_cp
     // has already been attached to the_class and old_cp has already
     // been added as a previous version. The new_cp doesn't have any
     // cached references to old methods so it doesn't need to be
@@ -3505,12 +3492,12 @@
     constantPoolHandle other_cp;
     ConstantPoolCache* cp_cache;
 
-    if (ik != _the_class) {
+    if (!ik->is_being_redefined()) {
       // this klass' constant pool cache may need adjustment
       other_cp = constantPoolHandle(ik->constants());
       cp_cache = other_cp->cache();
       if (cp_cache != NULL) {
-        cp_cache->adjust_method_entries(the_class, &trace_name_printed);
+        cp_cache->adjust_method_entries(&trace_name_printed);
       }
     }
 
@@ -3520,23 +3507,7 @@
          pv_node = pv_node->previous_versions()) {
       cp_cache = pv_node->constants()->cache();
       if (cp_cache != NULL) {
-        cp_cache->adjust_method_entries(pv_node, &trace_name_printed);
-      }
-    }
-  }
-}
-
-// Clean method data for this class
-void VM_RedefineClasses::MethodDataCleaner::do_klass(Klass* k) {
-  if (k->is_instance_klass()) {
-    InstanceKlass *ik = InstanceKlass::cast(k);
-    // Clean MethodData of this class's methods so they don't refer to
-    // old methods that are no longer running.
-    Array<Method*>* methods = ik->methods();
-    int num_methods = methods->length();
-    for (int index = 0; index < num_methods; ++index) {
-      if (methods->at(index)->method_data() != NULL) {
-        methods->at(index)->method_data()->clean_weak_method_links();
+        cp_cache->adjust_method_entries(&trace_name_printed);
       }
     }
   }
@@ -3972,6 +3943,10 @@
 
   InstanceKlass* the_class = get_ik(the_jclass);
 
+  // Set some flags to control and optimize adjusting method entries
+  _has_redefined_Object |= the_class == SystemDictionary::Object_klass();
+  _has_null_class_loader |= the_class->class_loader() == NULL;
+
   // Remove all breakpoints in methods of this class
   JvmtiBreakpoints& jvmti_breakpoints = JvmtiCurrentBreakpoints::get_jvmti_breakpoints();
   jvmti_breakpoints.clearall_in_class_at_safepoint(the_class);
@@ -4193,11 +4168,6 @@
     _timer_rsc_phase2.start();
   }
 
-  // Adjust constantpool caches and vtables for all classes
-  // that reference methods of the evolved class.
-  AdjustCpoolCacheAndVtable adjust_cpool_cache_and_vtable(THREAD);
-  ClassLoaderDataGraph::classes_do(&adjust_cpool_cache_and_vtable);
-
   if (the_class->oop_map_cache() != NULL) {
     // Flush references to any obsolete methods from the oop map cache
     // so that obsolete methods are not pinned.