7182152: Instrumentation hot swap test incorrect monitor count
authordcubed
Wed, 06 Feb 2013 14:31:37 -0800
changeset 15591 b8aa0577f137
parent 15469 7719efe7b23d
child 15592 4eec33e264bb
child 15593 860cf6c70c06
7182152: Instrumentation hot swap test incorrect monitor count Summary: Add/refine new tracing support using -XX:TraceRedefineClasses=16384. Reviewed-by: coleenp, acorn, sspitsyn
hotspot/src/share/vm/oops/cpCache.cpp
hotspot/src/share/vm/oops/cpCache.hpp
hotspot/src/share/vm/oops/klassVtable.cpp
hotspot/src/share/vm/oops/klassVtable.hpp
hotspot/src/share/vm/oops/method.cpp
hotspot/src/share/vm/oops/method.hpp
hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp
hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp
hotspot/src/share/vm/prims/jvmtiRedefineClassesTrace.hpp
hotspot/src/share/vm/utilities/accessFlags.cpp
hotspot/src/share/vm/utilities/accessFlags.hpp
--- a/hotspot/src/share/vm/oops/cpCache.cpp	Tue Feb 05 00:59:40 2013 -0800
+++ b/hotspot/src/share/vm/oops/cpCache.cpp	Wed Feb 06 14:31:37 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -401,8 +401,9 @@
 }
 
 
+#if INCLUDE_JVMTI
 // RedefineClasses() API support:
-// If this constantPoolCacheEntry refers to old_method then update it
+// If this ConstantPoolCacheEntry refers to old_method then update it
 // to refer to new_method.
 bool ConstantPoolCacheEntry::adjust_method_entry(Method* old_method,
        Method* new_method, bool * trace_name_printed) {
@@ -460,16 +461,24 @@
   return false;
 }
 
-#ifndef PRODUCT
-bool ConstantPoolCacheEntry::check_no_old_entries() {
+// a constant pool cache entry should never contain old or obsolete methods
+bool ConstantPoolCacheEntry::check_no_old_or_obsolete_entries() {
   if (is_vfinal()) {
+    // virtual and final so _f2 contains method ptr instead of vtable index
     Metadata* f2 = (Metadata*)_f2;
-    return (f2->is_valid() && f2->is_method() && !((Method*)f2)->is_old());
-  } else {
-    return (_f1 == NULL || (_f1->is_valid() && _f1->is_method() && !((Method*)_f1)->is_old()));
+    // Return false if _f2 refers to an old or an obsolete method.
+    // _f2 == NULL || !_f2->is_method() are just as unexpected here.
+    return (f2 != NULL NOT_PRODUCT(&& f2->is_valid()) && f2->is_method() &&
+            !((Method*)f2)->is_old() && !((Method*)f2)->is_obsolete());
+  } else if (_f1 == NULL ||
+             (NOT_PRODUCT(_f1->is_valid() &&) !_f1->is_method())) {
+    // _f1 == NULL || !_f1->is_method() are OK here
+    return true;
   }
+  // return false if _f1 refers to an old or an obsolete method
+  return (NOT_PRODUCT(_f1->is_valid() &&) _f1->is_method() &&
+          !((Method*)_f1)->is_old() && !((Method*)_f1)->is_obsolete());
 }
-#endif
 
 bool ConstantPoolCacheEntry::is_interesting_method_entry(Klass* k) {
   if (!is_method_entry()) {
@@ -502,13 +511,15 @@
   // the method is in the interesting class so the entry is interesting
   return true;
 }
+#endif // INCLUDE_JVMTI
 
 void ConstantPoolCacheEntry::print(outputStream* st, int index) const {
   // print separator
   if (index == 0) st->print_cr("                 -------------");
   // print entry
   st->print("%3d  ("PTR_FORMAT")  ", index, (intptr_t)this);
-    st->print_cr("[%02x|%02x|%5d]", bytecode_2(), bytecode_1(), constant_pool_index());
+  st->print_cr("[%02x|%02x|%5d]", bytecode_2(), bytecode_1(),
+               constant_pool_index());
   st->print_cr("                 [   "PTR_FORMAT"]", (intptr_t)_f1);
   st->print_cr("                 [   "PTR_FORMAT"]", (intptr_t)_f2);
   st->print_cr("                 [   "PTR_FORMAT"]", (intptr_t)_flags);
@@ -552,8 +563,9 @@
   }
 }
 
+#if INCLUDE_JVMTI
 // RedefineClasses() API support:
-// If any entry of this constantPoolCache points to any of
+// 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) {
@@ -572,7 +584,7 @@
       continue;
     }
 
-    // The constantPoolCache contains entries for several different
+    // 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.
@@ -591,17 +603,25 @@
   }
 }
 
-#ifndef PRODUCT
-bool ConstantPoolCache::check_no_old_entries() {
+// the constant pool cache should never contain old or obsolete methods
+bool ConstantPoolCache::check_no_old_or_obsolete_entries() {
   for (int i = 1; i < length(); i++) {
     if (entry_at(i)->is_interesting_method_entry(NULL) &&
-       !entry_at(i)->check_no_old_entries()) {
+        !entry_at(i)->check_no_old_or_obsolete_entries()) {
       return false;
     }
   }
   return true;
 }
-#endif // PRODUCT
+
+void ConstantPoolCache::dump_cache() {
+  for (int i = 1; i < length(); i++) {
+    if (entry_at(i)->is_interesting_method_entry(NULL)) {
+      entry_at(i)->print(tty, i);
+    }
+  }
+}
+#endif // INCLUDE_JVMTI
 
 
 // Printing
--- a/hotspot/src/share/vm/oops/cpCache.hpp	Tue Feb 05 00:59:40 2013 -0800
+++ b/hotspot/src/share/vm/oops/cpCache.hpp	Wed Feb 06 14:31:37 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -337,16 +337,18 @@
   static ByteSize f2_offset()                    { return byte_offset_of(ConstantPoolCacheEntry, _f2); }
   static ByteSize flags_offset()                 { return byte_offset_of(ConstantPoolCacheEntry, _flags); }
 
+#if INCLUDE_JVMTI
   // RedefineClasses() API support:
-  // If this constantPoolCacheEntry refers to old_method then update it
+  // If this ConstantPoolCacheEntry refers to old_method then update it
   // to refer to new_method.
   // 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.
   bool adjust_method_entry(Method* old_method, Method* new_method,
          bool * trace_name_printed);
-  NOT_PRODUCT(bool check_no_old_entries();)
+  bool check_no_old_or_obsolete_entries();
   bool is_interesting_method_entry(Klass* k);
+#endif // INCLUDE_JVMTI
 
   // Debugging & Printing
   void print (outputStream* st, int index) const;
@@ -423,15 +425,18 @@
     return (base_offset() + ConstantPoolCacheEntry::size_in_bytes() * index);
   }
 
+#if INCLUDE_JVMTI
   // RedefineClasses() API support:
-  // If any entry of this constantPoolCache points to any of
+  // If any entry of this ConstantPoolCache points to any of
   // old_methods, replace it with the corresponding new_method.
   // 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);
-  NOT_PRODUCT(bool check_no_old_entries();)
+  bool check_no_old_or_obsolete_entries();
+  void dump_cache();
+#endif // INCLUDE_JVMTI
 
   // Deallocate - no fields to deallocate
   DEBUG_ONLY(bool on_stack() { return false; })
--- a/hotspot/src/share/vm/oops/klassVtable.cpp	Tue Feb 05 00:59:40 2013 -0800
+++ b/hotspot/src/share/vm/oops/klassVtable.cpp	Wed Feb 06 14:31:37 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -610,6 +610,7 @@
   Copy::disjoint_words((HeapWord*)table(), (HeapWord*)start, _length * vtableEntry::size());
 }
 
+#if INCLUDE_JVMTI
 void klassVtable::adjust_method_entries(Method** old_methods, Method** new_methods,
                                         int methods_length, bool * trace_name_printed) {
   // search the vtable for uses of either obsolete or EMCP methods
@@ -638,11 +639,39 @@
                                 new_method->name()->as_C_string(),
                                 new_method->signature()->as_C_string()));
         }
+        // cannot 'break' here; see for-loop comment above.
       }
     }
   }
 }
 
+// a vtable should never contain old or obsolete methods
+bool klassVtable::check_no_old_or_obsolete_entries() {
+  for (int i = 0; i < length(); i++) {
+    Method* m = unchecked_method_at(i);
+    if (m != NULL &&
+        (NOT_PRODUCT(!m->is_valid() ||) m->is_old() || m->is_obsolete())) {
+      return false;
+    }
+  }
+  return true;
+}
+
+void klassVtable::dump_vtable() {
+  tty->print_cr("vtable dump --");
+  for (int i = 0; i < length(); i++) {
+    Method* m = unchecked_method_at(i);
+    if (m != NULL) {
+      tty->print("      (%5d)  ", i);
+      m->access_flags().print_on(tty);
+      tty->print(" --  ");
+      m->print_name(tty);
+      tty->cr();
+    }
+  }
+}
+#endif // INCLUDE_JVMTI
+
 // CDS/RedefineClasses support - clear vtables so they can be reinitialized
 void klassVtable::clear_vtable() {
   for (int i = 0; i < _length; i++) table()[i].clear();
@@ -805,6 +834,7 @@
   }
 }
 
+#if INCLUDE_JVMTI
 void klassItable::adjust_method_entries(Method** old_methods, Method** new_methods,
                                         int methods_length, bool * trace_name_printed) {
   // search the itable for uses of either obsolete or EMCP methods
@@ -833,13 +863,44 @@
             new_method->name()->as_C_string(),
             new_method->signature()->as_C_string()));
         }
-        // Cannot break because there might be another entry for this method
+        // cannot 'break' here; see for-loop comment above.
       }
       ime++;
     }
   }
 }
 
+// an itable should never contain old or obsolete methods
+bool klassItable::check_no_old_or_obsolete_entries() {
+  itableMethodEntry* ime = method_entry(0);
+  for (int i = 0; i < _size_method_table; i++) {
+    Method* m = ime->method();
+    if (m != NULL &&
+        (NOT_PRODUCT(!m->is_valid() ||) m->is_old() || m->is_obsolete())) {
+      return false;
+    }
+    ime++;
+  }
+  return true;
+}
+
+void klassItable::dump_itable() {
+  itableMethodEntry* ime = method_entry(0);
+  tty->print_cr("itable dump --");
+  for (int i = 0; i < _size_method_table; i++) {
+    Method* m = ime->method();
+    if (m != NULL) {
+      tty->print("      (%5d)  ", i);
+      m->access_flags().print_on(tty);
+      tty->print(" --  ");
+      m->print_name(tty);
+      tty->cr();
+    }
+    ime++;
+  }
+}
+#endif // INCLUDE_JVMTI
+
 
 // Setup
 class InterfaceVisiterClosure : public StackObj {
@@ -1126,43 +1187,6 @@
   tty->print_cr("%6d bytes total", total);
 }
 
-bool klassVtable::check_no_old_entries() {
-  // Check that there really is no entry
-  for (int i = 0; i < length(); i++) {
-    Method* m = unchecked_method_at(i);
-    if (m != NULL) {
-        if (!m->is_valid() || m->is_old()) {
-            return false;
-        }
-    }
-  }
-  return true;
-}
-
-void klassVtable::dump_vtable() {
-  tty->print_cr("vtable dump --");
-  for (int i = 0; i < length(); i++) {
-    Method* m = unchecked_method_at(i);
-    if (m != NULL) {
-      tty->print("      (%5d)  ", i);
-      m->access_flags().print_on(tty);
-      tty->print(" --  ");
-      m->print_name(tty);
-      tty->cr();
-    }
-  }
-}
-
-bool klassItable::check_no_old_entries() {
-  itableMethodEntry* ime = method_entry(0);
-  for(int i = 0; i < _size_method_table; i++) {
-    Method* m = ime->method();
-    if (m != NULL && (!m->is_valid() || m->is_old())) return false;
-    ime++;
-  }
-  return true;
-}
-
 int  klassItable::_total_classes;   // Total no. of classes with itables
 long klassItable::_total_size;      // Total no. of bytes used for itables
 
--- a/hotspot/src/share/vm/oops/klassVtable.hpp	Tue Feb 05 00:59:40 2013 -0800
+++ b/hotspot/src/share/vm/oops/klassVtable.hpp	Wed Feb 06 14:31:37 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -90,6 +90,7 @@
       Array<Method*>* methods, AccessFlags class_flags, Handle classloader,
       Symbol* classname, Array<Klass*>* local_interfaces, TRAPS);
 
+#if INCLUDE_JVMTI
   // RedefineClasses() API support:
   // If any entry of this vtable points to any of old_methods,
   // replace it with the corresponding new_method.
@@ -98,17 +99,15 @@
   // group don't print the klass name.
   void adjust_method_entries(Method** old_methods, Method** new_methods,
                              int methods_length, bool * trace_name_printed);
+  bool check_no_old_or_obsolete_entries();
+  void dump_vtable();
+#endif // INCLUDE_JVMTI
 
   // Debugging code
   void print()                                              PRODUCT_RETURN;
   void verify(outputStream* st, bool force = false);
   static void print_statistics()                            PRODUCT_RETURN;
 
-#ifndef PRODUCT
-  bool check_no_old_entries();
-  void dump_vtable();
-#endif
-
  protected:
   friend class vtableEntry;
  private:
@@ -275,6 +274,7 @@
   // Updates
   void initialize_with_method(Method* m);
 
+#if INCLUDE_JVMTI
   // RedefineClasses() API support:
   // if any entry of this itable points to any of old_methods,
   // replace it with the corresponding new_method.
@@ -283,6 +283,9 @@
   // group don't print the klass name.
   void adjust_method_entries(Method** old_methods, Method** new_methods,
                              int methods_length, bool * trace_name_printed);
+  bool check_no_old_or_obsolete_entries();
+  void dump_itable();
+#endif // INCLUDE_JVMTI
 
   // Setup of itable
   static int compute_itable_size(Array<Klass*>* transitive_interfaces);
@@ -307,11 +310,6 @@
   NOT_PRODUCT(static long _total_size;)      // Total no. of bytes used for itables
 
   static void update_stats(int size) PRODUCT_RETURN NOT_PRODUCT({ _total_classes++; _total_size += size; })
-
- public:
-#ifndef PRODUCT
-  bool check_no_old_entries();
-#endif
 };
 
 #endif // SHARE_VM_OOPS_KLASSVTABLE_HPP
--- a/hotspot/src/share/vm/oops/method.cpp	Tue Feb 05 00:59:40 2013 -0800
+++ b/hotspot/src/share/vm/oops/method.cpp	Wed Feb 06 14:31:37 2013 -0800
@@ -1386,9 +1386,9 @@
 
 
 //-----------------------------------------------------------------------------------
-// Non-product code
+// Non-product code unless JVM/TI needs it
 
-#ifndef PRODUCT
+#if !defined(PRODUCT) || INCLUDE_JVMTI
 class SignatureTypePrinter : public SignatureTypeNames {
  private:
   outputStream* _st;
@@ -1423,8 +1423,13 @@
   sig.print_parameters();
   st->print(")");
 }
+#endif // !PRODUCT || INCLUDE_JVMTI
 
 
+//-----------------------------------------------------------------------------------
+// Non-product code
+
+#ifndef PRODUCT
 void Method::print_codes_on(outputStream* st) const {
   print_codes_on(0, code_size(), st);
 }
--- a/hotspot/src/share/vm/oops/method.hpp	Tue Feb 05 00:59:40 2013 -0800
+++ b/hotspot/src/share/vm/oops/method.hpp	Wed Feb 06 14:31:37 2013 -0800
@@ -800,8 +800,12 @@
   static bool has_unloaded_classes_in_signature(methodHandle m, TRAPS);
 
   // Printing
-  void print_short_name(outputStream* st = tty)  /*PRODUCT_RETURN*/; // prints as klassname::methodname; Exposed so field engineers can debug VM
+  void print_short_name(outputStream* st = tty); // prints as klassname::methodname; Exposed so field engineers can debug VM
+#if INCLUDE_JVMTI
+  void print_name(outputStream* st = tty); // prints as "virtual void foo(int)"; exposed for TraceRedefineClasses
+#else
   void print_name(outputStream* st = tty)        PRODUCT_RETURN; // prints as "virtual void foo(int)"
+#endif
 
   // Helper routine used for method sorting
   static void sort_methods(Array<Method*>* methods,
--- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp	Tue Feb 05 00:59:40 2013 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp	Wed Feb 06 14:31:37 2013 -0800
@@ -154,8 +154,15 @@
   // See jvmtiExport.hpp for detailed explanation.
   JvmtiExport::set_has_redefined_a_class();
 
-#ifdef ASSERT
-  SystemDictionary::classes_do(check_class, thread);
+// check_class() is optionally called for product bits, but is
+// always called for non-product bits.
+#ifdef PRODUCT
+  if (RC_TRACE_ENABLED(0x00004000)) {
+#endif
+    RC_TRACE_WITH_THREAD(0x00004000, thread, ("calling check_class"));
+    SystemDictionary::classes_do(check_class, thread);
+#ifdef PRODUCT
+  }
 #endif
 }
 
@@ -1564,9 +1571,9 @@
             bcp, cp_index, new_index));
           // Rewriter::rewrite_method() uses put_native_u2() in this
           // situation because it is reusing the constant pool index
-          // location for a native index into the constantPoolCache.
+          // location for a native index into the ConstantPoolCache.
           // Since we are updating the constant pool index prior to
-          // verification and constantPoolCache initialization, we
+          // verification and ConstantPoolCache initialization, we
           // need to keep the new index in Java byte order.
           Bytes::put_Java_u2(p, new_index);
         }
@@ -3371,7 +3378,6 @@
   }
 }
 
-#ifndef PRODUCT
 void VM_RedefineClasses::check_class(Klass* k_oop,
                                      ClassLoaderData* initiating_loader,
                                      TRAPS) {
@@ -3379,82 +3385,110 @@
   if (k->oop_is_instance()) {
     HandleMark hm(THREAD);
     InstanceKlass *ik = (InstanceKlass *) k;
-
-    if (ik->vtable_length() > 0) {
-      ResourceMark rm(THREAD);
-      if (!ik->vtable()->check_no_old_entries()) {
-        tty->print_cr("klassVtable::check_no_old_entries failure -- OLD method found -- class: %s", ik->signature_name());
+    bool no_old_methods = true;  // be optimistic
+    ResourceMark rm(THREAD);
+
+    // a vtable should never contain old or obsolete methods
+    if (ik->vtable_length() > 0 &&
+        !ik->vtable()->check_no_old_or_obsolete_entries()) {
+      if (RC_TRACE_ENABLED(0x00004000)) {
+        RC_TRACE_WITH_THREAD(0x00004000, THREAD,
+          ("klassVtable::check_no_old_or_obsolete_entries failure"
+           " -- OLD or OBSOLETE method found -- class: %s",
+           ik->signature_name()));
         ik->vtable()->dump_vtable();
-        assert(false, "OLD method found");
       }
+      no_old_methods = false;
     }
-    if (ik->itable_length() > 0) {
-      ResourceMark rm(THREAD);
-      if (!ik->itable()->check_no_old_entries()) {
-        tty->print_cr("klassItable::check_no_old_entries failure -- OLD method found -- class: %s", ik->signature_name());
-        assert(false, "OLD method found");
+
+    // an itable should never contain old or obsolete methods
+    if (ik->itable_length() > 0 &&
+        !ik->itable()->check_no_old_or_obsolete_entries()) {
+      if (RC_TRACE_ENABLED(0x00004000)) {
+        RC_TRACE_WITH_THREAD(0x00004000, THREAD,
+          ("klassItable::check_no_old_or_obsolete_entries failure"
+           " -- OLD or OBSOLETE method found -- class: %s",
+           ik->signature_name()));
+        ik->itable()->dump_itable();
       }
+      no_old_methods = false;
     }
-    // Check that the constant pool cache has no deleted entries.
+
+    // the constant pool cache should never contain old or obsolete methods
     if (ik->constants() != NULL &&
         ik->constants()->cache() != NULL &&
-       !ik->constants()->cache()->check_no_old_entries()) {
-      tty->print_cr("klassVtable::check_no_old_entries failure -- OLD method found -- class: %s", ik->signature_name());
-      assert(false, "OLD method found");
+        !ik->constants()->cache()->check_no_old_or_obsolete_entries()) {
+      if (RC_TRACE_ENABLED(0x00004000)) {
+        RC_TRACE_WITH_THREAD(0x00004000, THREAD,
+          ("cp-cache::check_no_old_or_obsolete_entries failure"
+           " -- OLD or OBSOLETE method found -- class: %s",
+           ik->signature_name()));
+        ik->constants()->cache()->dump_cache();
+      }
+      no_old_methods = false;
+    }
+
+    if (!no_old_methods) {
+      if (RC_TRACE_ENABLED(0x00004000)) {
+        dump_methods();
+      } else {
+        tty->print_cr("INFO: use the '-XX:TraceRedefineClasses=16384' option "
+          "to see more info about the following guarantee() failure.");
+      }
+      guarantee(false, "OLD and/or OBSOLETE method(s) found");
     }
   }
 }
 
 void VM_RedefineClasses::dump_methods() {
-        int j;
-        tty->print_cr("_old_methods --");
-        for (j = 0; j < _old_methods->length(); ++j) {
-          Method* m = _old_methods->at(j);
-          tty->print("%4d  (%5d)  ", j, m->vtable_index());
-          m->access_flags().print_on(tty);
-          tty->print(" --  ");
-          m->print_name(tty);
-          tty->cr();
-        }
-        tty->print_cr("_new_methods --");
-        for (j = 0; j < _new_methods->length(); ++j) {
-          Method* m = _new_methods->at(j);
-          tty->print("%4d  (%5d)  ", j, m->vtable_index());
-          m->access_flags().print_on(tty);
-          tty->print(" --  ");
-          m->print_name(tty);
-          tty->cr();
-        }
-        tty->print_cr("_matching_(old/new)_methods --");
-        for (j = 0; j < _matching_methods_length; ++j) {
-          Method* m = _matching_old_methods[j];
-          tty->print("%4d  (%5d)  ", j, m->vtable_index());
-          m->access_flags().print_on(tty);
-          tty->print(" --  ");
-          m->print_name(tty);
-          tty->cr();
-          m = _matching_new_methods[j];
-          tty->print("      (%5d)  ", m->vtable_index());
-          m->access_flags().print_on(tty);
-          tty->cr();
-        }
-        tty->print_cr("_deleted_methods --");
-        for (j = 0; j < _deleted_methods_length; ++j) {
-          Method* m = _deleted_methods[j];
-          tty->print("%4d  (%5d)  ", j, m->vtable_index());
-          m->access_flags().print_on(tty);
-          tty->print(" --  ");
-          m->print_name(tty);
-          tty->cr();
-        }
-        tty->print_cr("_added_methods --");
-        for (j = 0; j < _added_methods_length; ++j) {
-          Method* m = _added_methods[j];
-          tty->print("%4d  (%5d)  ", j, m->vtable_index());
-          m->access_flags().print_on(tty);
-          tty->print(" --  ");
-          m->print_name(tty);
-          tty->cr();
-        }
+  int j;
+  RC_TRACE(0x00004000, ("_old_methods --"));
+  for (j = 0; j < _old_methods->length(); ++j) {
+    Method* m = _old_methods->at(j);
+    RC_TRACE_NO_CR(0x00004000, ("%4d  (%5d)  ", j, m->vtable_index()));
+    m->access_flags().print_on(tty);
+    tty->print(" --  ");
+    m->print_name(tty);
+    tty->cr();
+  }
+  RC_TRACE(0x00004000, ("_new_methods --"));
+  for (j = 0; j < _new_methods->length(); ++j) {
+    Method* m = _new_methods->at(j);
+    RC_TRACE_NO_CR(0x00004000, ("%4d  (%5d)  ", j, m->vtable_index()));
+    m->access_flags().print_on(tty);
+    tty->print(" --  ");
+    m->print_name(tty);
+    tty->cr();
+  }
+  RC_TRACE(0x00004000, ("_matching_(old/new)_methods --"));
+  for (j = 0; j < _matching_methods_length; ++j) {
+    Method* m = _matching_old_methods[j];
+    RC_TRACE_NO_CR(0x00004000, ("%4d  (%5d)  ", j, m->vtable_index()));
+    m->access_flags().print_on(tty);
+    tty->print(" --  ");
+    m->print_name(tty);
+    tty->cr();
+    m = _matching_new_methods[j];
+    RC_TRACE_NO_CR(0x00004000, ("      (%5d)  ", m->vtable_index()));
+    m->access_flags().print_on(tty);
+    tty->cr();
+  }
+  RC_TRACE(0x00004000, ("_deleted_methods --"));
+  for (j = 0; j < _deleted_methods_length; ++j) {
+    Method* m = _deleted_methods[j];
+    RC_TRACE_NO_CR(0x00004000, ("%4d  (%5d)  ", j, m->vtable_index()));
+    m->access_flags().print_on(tty);
+    tty->print(" --  ");
+    m->print_name(tty);
+    tty->cr();
+  }
+  RC_TRACE(0x00004000, ("_added_methods --"));
+  for (j = 0; j < _added_methods_length; ++j) {
+    Method* m = _added_methods[j];
+    RC_TRACE_NO_CR(0x00004000, ("%4d  (%5d)  ", j, m->vtable_index()));
+    m->access_flags().print_on(tty);
+    tty->print(" --  ");
+    m->print_name(tty);
+    tty->cr();
+  }
 }
-#endif
--- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp	Tue Feb 05 00:59:40 2013 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp	Wed Feb 06 14:31:37 2013 -0800
@@ -468,9 +468,9 @@
 
   void flush_dependent_code(instanceKlassHandle k_h, TRAPS);
 
-  static void check_class(Klass* k_oop, ClassLoaderData* initiating_loader, TRAPS) PRODUCT_RETURN;
-
-  static void dump_methods()   PRODUCT_RETURN;
+  static void check_class(Klass* k_oop, ClassLoaderData* initiating_loader,
+                TRAPS);
+  static void dump_methods();
 
  public:
   VM_RedefineClasses(jint class_count,
--- a/hotspot/src/share/vm/prims/jvmtiRedefineClassesTrace.hpp	Tue Feb 05 00:59:40 2013 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiRedefineClassesTrace.hpp	Wed Feb 06 14:31:37 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -54,7 +54,7 @@
 //    0x00000800 |       2048 - previous class breakpoint mgmt
 //    0x00001000 |       4096 - detect calls to obsolete methods
 //    0x00002000 |       8192 - fail a guarantee() in addition to detection
-//    0x00004000 |      16384 - unused
+//    0x00004000 |      16384 - detect old/obsolete methods in metadata
 //    0x00008000 |      32768 - old/new method matching/add/delete
 //    0x00010000 |      65536 - impl details: CP size info
 //    0x00020000 |     131072 - impl details: CP merge pass info
@@ -82,6 +82,13 @@
     tty->print_cr args; \
   } while (0)
 
+#define RC_TRACE_NO_CR(level, args) \
+  if ((TraceRedefineClasses & level) != 0) { \
+    ResourceMark rm; \
+    tty->print("RedefineClasses-0x%x: ", level); \
+    tty->print args; \
+  } while (0)
+
 #define RC_TRACE_WITH_THREAD(level, thread, args) \
   if ((TraceRedefineClasses & level) != 0) { \
     ResourceMark rm(thread); \
--- a/hotspot/src/share/vm/utilities/accessFlags.cpp	Tue Feb 05 00:59:40 2013 -0800
+++ b/hotspot/src/share/vm/utilities/accessFlags.cpp	Wed Feb 06 14:31:37 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -59,7 +59,7 @@
   } while(f != old_flags);
 }
 
-#ifndef PRODUCT
+#if !defined(PRODUCT) || INCLUDE_JVMTI
 
 void AccessFlags::print_on(outputStream* st) const {
   if (is_public      ()) st->print("public "      );
@@ -80,7 +80,7 @@
   if (on_stack       ()) st->print("{on_stack} "  );
 }
 
-#endif
+#endif // !PRODUCT || INCLUDE_JVMTI
 
 void accessFlags_init() {
   assert(sizeof(AccessFlags) == sizeof(jint), "just checking size of flags");
--- a/hotspot/src/share/vm/utilities/accessFlags.hpp	Tue Feb 05 00:59:40 2013 -0800
+++ b/hotspot/src/share/vm/utilities/accessFlags.hpp	Wed Feb 06 14:31:37 2013 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -239,7 +239,11 @@
   inline friend AccessFlags accessFlags_from(jint flags);
 
   // Printing/debugging
+#if INCLUDE_JVMTI
+  void print_on(outputStream* st) const;
+#else
   void print_on(outputStream* st) const PRODUCT_RETURN;
+#endif
 };
 
 inline AccessFlags accessFlags_from(jint flags) {