8028993: Full collections with ParallelScavenge slower in JDK 8 compared to 7u40

Reducing the number of calls to follow_class_loader to speed up the marking phase. Also removed some unnecessary calls to adjust_klass.

Reviewed-by: stefank, jmasa, mgerdin
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp
index 8e9dd8d..8b4f0bd 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp
@@ -2433,20 +2433,6 @@
   _gc_tracer.report_object_count_after_gc(is_alive_closure());
 }
 
-void PSParallelCompact::follow_klass(ParCompactionManager* cm, Klass* klass) {
-  ClassLoaderData* cld = klass->class_loader_data();
-  // The actual processing of the klass is done when we
-  // traverse the list of Klasses in the class loader data.
-  PSParallelCompact::follow_class_loader(cm, cld);
-}
-
-void PSParallelCompact::adjust_klass(ParCompactionManager* cm, Klass* klass) {
-  ClassLoaderData* cld = klass->class_loader_data();
-  // The actual processing of the klass is done when we
-  // traverse the list of Klasses in the class loader data.
-  PSParallelCompact::adjust_class_loader(cm, cld);
-}
-
 void PSParallelCompact::follow_class_loader(ParCompactionManager* cm,
                                             ClassLoaderData* cld) {
   PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
@@ -2455,13 +2441,6 @@
   cld->oops_do(&mark_and_push_closure, &follow_klass_closure, true);
 }
 
-void PSParallelCompact::adjust_class_loader(ParCompactionManager* cm,
-                                            ClassLoaderData* cld) {
-  cld->oops_do(PSParallelCompact::adjust_pointer_closure(),
-               PSParallelCompact::adjust_klass_closure(),
-               true);
-}
-
 // This should be moved to the shared markSweep code!
 class PSAlwaysTrueClosure: public BoolObjectClosure {
 public:
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp
index 2ba4eb4..0f1b77b 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp
@@ -1200,13 +1200,10 @@
                                                       T* p);
   template <class T> static inline void adjust_pointer(T* p);
 
-  static void follow_klass(ParCompactionManager* cm, Klass* klass);
-  static void adjust_klass(ParCompactionManager* cm, Klass* klass);
+  static inline void follow_klass(ParCompactionManager* cm, Klass* klass);
 
   static void follow_class_loader(ParCompactionManager* cm,
                                   ClassLoaderData* klass);
-  static void adjust_class_loader(ParCompactionManager* cm,
-                                  ClassLoaderData* klass);
 
   // Compaction support.
   // Return true if p is in the range [beg_addr, end_addr).
@@ -1380,6 +1377,11 @@
   }
 }
 
+inline void PSParallelCompact::follow_klass(ParCompactionManager* cm, Klass* klass) {
+  oop holder = klass->klass_holder();
+  PSParallelCompact::mark_and_push(cm, &holder);
+}
+
 template <class T>
 inline void PSParallelCompact::KeepAliveClosure::do_oop_work(T* p) {
   mark_and_push(_compaction_manager, p);
diff --git a/hotspot/src/share/vm/oops/instanceClassLoaderKlass.cpp b/hotspot/src/share/vm/oops/instanceClassLoaderKlass.cpp
index 507206f..e57a0b7 100644
--- a/hotspot/src/share/vm/oops/instanceClassLoaderKlass.cpp
+++ b/hotspot/src/share/vm/oops/instanceClassLoaderKlass.cpp
@@ -150,10 +150,6 @@
 
 int InstanceClassLoaderKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) {
   InstanceKlass::oop_update_pointers(cm, obj);
-  ClassLoaderData * const loader_data = java_lang_ClassLoader::loader_data(obj);
-  if (loader_data != NULL) {
-    PSParallelCompact::adjust_class_loader(cm, loader_data);
-  }
   return size_helper();
 }
 #endif // INCLUDE_ALL_GCS
diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp
index 77be530..7c63c48 100644
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp
@@ -2199,7 +2199,6 @@
     obj, \
     PSParallelCompact::adjust_pointer(p), \
     assert_is_in)
-  obj->update_header(cm);
   return size;
 }
 
diff --git a/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp b/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp
index 8256332..0e903b3 100644
--- a/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp
+++ b/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp
@@ -155,8 +155,13 @@
   // Follow the klass field in the mirror.
   Klass* klass = java_lang_Class::as_Klass(obj);
   if (klass != NULL) {
-    // For anonymous classes we need to handle the class loader data,
-    // otherwise it won't be claimed and can be unloaded.
+    // An anonymous class doesn't have its own class loader, so the call
+    // to follow_klass will mark and push its java mirror instead of the
+    // class loader. When handling the java mirror for an anonymous class
+    // we need to make sure its class loader data is claimed, this is done
+    // by calling follow_class_loader explicitly. For non-anonymous classes
+    // the call to follow_class_loader is made when the class loader itself
+    // is handled.
     if (klass->oop_is_instance() && InstanceKlass::cast(klass)->is_anonymous()) {
       MarkSweep::follow_class_loader(klass->class_loader_data());
     } else {
@@ -183,7 +188,18 @@
   // Follow the klass field in the mirror.
   Klass* klass = java_lang_Class::as_Klass(obj);
   if (klass != NULL) {
-    PSParallelCompact::follow_klass(cm, klass);
+    // An anonymous class doesn't have its own class loader, so the call
+    // to follow_klass will mark and push its java mirror instead of the
+    // class loader. When handling the java mirror for an anonymous class
+    // we need to make sure its class loader data is claimed, this is done
+    // by calling follow_class_loader explicitly. For non-anonymous classes
+    // the call to follow_class_loader is made when the class loader itself
+    // is handled.
+    if (klass->oop_is_instance() && InstanceKlass::cast(klass)->is_anonymous()) {
+      PSParallelCompact::follow_class_loader(cm, klass->class_loader_data());
+    } else {
+      PSParallelCompact::follow_klass(cm, klass);
+    }
   } else {
     // If klass is NULL then this a mirror for a primitive type.
     // We don't have to follow them, since they are handled as strong
@@ -332,17 +348,6 @@
   int size = oop_size(obj);
   InstanceKlass::oop_update_pointers(cm, obj);
 
-  // Follow the klass field in the mirror.
-  Klass* klass = java_lang_Class::as_Klass(obj);
-  if (klass != NULL) {
-    PSParallelCompact::adjust_klass(cm, klass);
-  } else {
-    // If klass is NULL then this a mirror for a primitive type.
-    // We don't have to follow them, since they are handled as strong
-    // roots in Universe::oops_do.
-    assert(java_lang_Class::is_primitive(obj), "Sanity check");
-  }
-
   InstanceMirrorKlass_OOP_ITERATE(                                            \
     start_of_static_fields(obj), java_lang_Class::static_oop_field_count(obj),\
     PSParallelCompact::adjust_pointer(p),                                     \
diff --git a/hotspot/src/share/vm/oops/objArrayKlass.cpp b/hotspot/src/share/vm/oops/objArrayKlass.cpp
index 94c990a..4631fdd 100644
--- a/hotspot/src/share/vm/oops/objArrayKlass.cpp
+++ b/hotspot/src/share/vm/oops/objArrayKlass.cpp
@@ -587,7 +587,6 @@
   assert (obj->is_objArray(), "obj must be obj array");
   objArrayOop a = objArrayOop(obj);
   int size = a->object_size();
-  a->update_header(cm);
   ObjArrayKlass_OOP_ITERATE(a, p, PSParallelCompact::adjust_pointer(p))
   return size;
 }
diff --git a/hotspot/src/share/vm/oops/oop.hpp b/hotspot/src/share/vm/oops/oop.hpp
index 66a62ea..350c0fc 100644
--- a/hotspot/src/share/vm/oops/oop.hpp
+++ b/hotspot/src/share/vm/oops/oop.hpp
@@ -328,11 +328,6 @@
   // return the size of this oop.  This is used by the MarkSweep collector.
   int adjust_pointers();
 
-#if INCLUDE_ALL_GCS
-  // Parallel old
-  void update_header(ParCompactionManager* cm);
-#endif // INCLUDE_ALL_GCS
-
   // mark-sweep support
   void follow_body(int begin, int end);
 
diff --git a/hotspot/src/share/vm/oops/oop.pcgc.inline.hpp b/hotspot/src/share/vm/oops/oop.pcgc.inline.hpp
index d8e4047..178c8f4 100644
--- a/hotspot/src/share/vm/oops/oop.pcgc.inline.hpp
+++ b/hotspot/src/share/vm/oops/oop.pcgc.inline.hpp
@@ -80,8 +80,4 @@
   return forwardee();
 }
 
-inline void oopDesc::update_header(ParCompactionManager* cm) {
-  PSParallelCompact::adjust_klass(cm, klass());
-}
-
 #endif // SHARE_VM_OOPS_OOP_PCGC_INLINE_HPP