8146987: Improve Parallel GC Full GC by caching results of live_words_in_range()
authortschatzl
Thu, 28 Jan 2016 13:30:12 +0100
changeset 35877 a2a62511d0f8
parent 35873 96fb98b25b13
child 35878 c22a2dd2416c
8146987: Improve Parallel GC Full GC by caching results of live_words_in_range() Summary: A large part of time in the parallel scavenge collector is spent finding out the amount of live words within memory ranges to find out where to move an object to. Try to incrementally calculate this value. Reviewed-by: tschatzl, mgerdin, jmasa Contributed-by: ray alex <sky1young@gmail.com>
hotspot/src/share/vm/gc/parallel/parMarkBitMap.cpp
hotspot/src/share/vm/gc/parallel/parMarkBitMap.hpp
hotspot/src/share/vm/gc/parallel/psCompactionManager.cpp
hotspot/src/share/vm/gc/parallel/psCompactionManager.hpp
hotspot/src/share/vm/gc/parallel/psCompactionManager.inline.hpp
hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp
hotspot/src/share/vm/gc/parallel/psParallelCompact.hpp
hotspot/src/share/vm/gc/parallel/psParallelCompact.inline.hpp
hotspot/src/share/vm/oops/instanceClassLoaderKlass.hpp
hotspot/src/share/vm/oops/instanceKlass.hpp
hotspot/src/share/vm/oops/instanceMirrorKlass.hpp
hotspot/src/share/vm/oops/instanceRefKlass.hpp
hotspot/src/share/vm/oops/klass.hpp
hotspot/src/share/vm/oops/objArrayKlass.hpp
hotspot/src/share/vm/oops/oop.hpp
hotspot/src/share/vm/oops/oop.inline.hpp
hotspot/src/share/vm/oops/typeArrayKlass.hpp
--- a/hotspot/src/share/vm/gc/parallel/parMarkBitMap.cpp	Thu Jan 28 10:18:45 2016 +0100
+++ b/hotspot/src/share/vm/gc/parallel/parMarkBitMap.cpp	Thu Jan 28 13:30:12 2016 +0100
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "gc/parallel/parMarkBitMap.hpp"
+#include "gc/parallel/psCompactionManager.inline.hpp"
 #include "gc/parallel/psParallelCompact.inline.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/atomic.inline.hpp"
@@ -96,7 +97,20 @@
   return false;
 }
 
-size_t ParMarkBitMap::live_words_in_range(HeapWord* beg_addr, oop end_obj) const
+inline bool
+ParMarkBitMap::is_live_words_in_range_in_cache(ParCompactionManager* cm, HeapWord* beg_addr) const {
+  return cm->last_query_begin() == beg_addr;
+}
+
+inline void
+ParMarkBitMap::update_live_words_in_range_cache(ParCompactionManager* cm, HeapWord* beg_addr, oop end_obj, size_t result) const {
+  cm->set_last_query_begin(beg_addr);
+  cm->set_last_query_object(end_obj);
+  cm->set_last_query_return(result);
+}
+
+size_t
+ParMarkBitMap::live_words_in_range_helper(HeapWord* beg_addr, oop end_obj) const
 {
   assert(beg_addr <= (HeapWord*)end_obj, "bad range");
   assert(is_marked(end_obj), "end_obj must be live");
@@ -117,6 +131,42 @@
   return bits_to_words(live_bits);
 }
 
+size_t
+ParMarkBitMap::live_words_in_range_use_cache(ParCompactionManager* cm, HeapWord* beg_addr, oop end_obj) const
+{
+  HeapWord* last_beg = cm->last_query_begin();
+  oop last_obj = cm->last_query_object();
+  size_t last_ret = cm->last_query_return();
+  if (end_obj > last_obj) {
+    last_ret = last_ret + live_words_in_range_helper((HeapWord*)last_obj, end_obj);
+    last_obj = end_obj;
+  } else if (end_obj < last_obj) {
+    // The cached value is for an object that is to the left (lower address) of the current
+    // end_obj. Calculate back from that cached value.
+    if (pointer_delta((HeapWord*)end_obj, (HeapWord*)beg_addr) > pointer_delta((HeapWord*)last_obj, (HeapWord*)end_obj)) {
+      last_ret = last_ret - live_words_in_range_helper((HeapWord*)end_obj, last_obj);
+    } else {
+      last_ret = live_words_in_range_helper(beg_addr, end_obj);
+    }
+    last_obj = end_obj;
+  }
+
+  update_live_words_in_range_cache(cm, last_beg, last_obj, last_ret);
+  return last_ret;
+}
+
+size_t
+ParMarkBitMap::live_words_in_range(ParCompactionManager* cm, HeapWord* beg_addr, oop end_obj) const
+{
+  // Try to reuse result from ParCompactionManager cache first.
+  if (is_live_words_in_range_in_cache(cm, beg_addr)) {
+    return live_words_in_range_use_cache(cm, beg_addr, end_obj);
+  }
+  size_t ret = live_words_in_range_helper(beg_addr, end_obj);
+  update_live_words_in_range_cache(cm, beg_addr, end_obj, ret);
+  return ret;
+}
+
 ParMarkBitMap::IterationStatus
 ParMarkBitMap::iterate(ParMarkBitMapClosure* live_closure,
                        idx_t range_beg, idx_t range_end) const
--- a/hotspot/src/share/vm/gc/parallel/parMarkBitMap.hpp	Thu Jan 28 10:18:45 2016 +0100
+++ b/hotspot/src/share/vm/gc/parallel/parMarkBitMap.hpp	Thu Jan 28 13:30:12 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, 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
@@ -31,6 +31,7 @@
 
 class ParMarkBitMapClosure;
 class PSVirtualSpace;
+class ParCompactionManager;
 
 class ParMarkBitMap: public CHeapObj<mtGC>
 {
@@ -124,7 +125,7 @@
   // the range are included in the result. The end of the range must be a live object,
   // which is the case when updating pointers.  This allows a branch to be removed
   // from inside the loop.
-  size_t live_words_in_range(HeapWord* beg_addr, oop end_obj) const;
+  size_t live_words_in_range(ParCompactionManager* cm, HeapWord* beg_addr, oop end_obj) const;
 
   inline HeapWord* region_start() const;
   inline HeapWord* region_end() const;
@@ -167,6 +168,12 @@
 #endif  // #ifdef ASSERT
 
 private:
+  size_t live_words_in_range_helper(HeapWord* beg_addr, oop end_obj) const;
+
+  bool is_live_words_in_range_in_cache(ParCompactionManager* cm, HeapWord* beg_addr) const;
+  size_t live_words_in_range_use_cache(ParCompactionManager* cm, HeapWord* beg_addr, oop end_obj) const;
+  void update_live_words_in_range_cache(ParCompactionManager* cm, HeapWord* beg_addr, oop end_obj, size_t result) const;
+
   // Each bit in the bitmap represents one unit of 'object granularity.' Objects
   // are double-word aligned in 32-bit VMs, but not in 64-bit VMs, so the 32-bit
   // granularity is 2, 64-bit is 1.
--- a/hotspot/src/share/vm/gc/parallel/psCompactionManager.cpp	Thu Jan 28 10:18:45 2016 +0100
+++ b/hotspot/src/share/vm/gc/parallel/psCompactionManager.cpp	Thu Jan 28 13:30:12 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, 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
@@ -68,6 +68,8 @@
 
   marking_stack()->initialize();
   _objarray_stack.initialize();
+
+  reset_bitmap_query_cache();
 }
 
 ParCompactionManager::~ParCompactionManager() {
@@ -124,6 +126,13 @@
     "Not initialized?");
 }
 
+void ParCompactionManager::reset_all_bitmap_query_caches() {
+  uint parallel_gc_threads = PSParallelCompact::gc_task_manager()->workers();
+  for (uint i=0; i<=parallel_gc_threads; i++) {
+    _manager_array[i]->reset_bitmap_query_cache();
+  }
+}
+
 int ParCompactionManager::pop_recycled_stack_index() {
   assert(_recycled_bottom <= _recycled_top, "list is empty");
   // Get the next available index
--- a/hotspot/src/share/vm/gc/parallel/psCompactionManager.hpp	Thu Jan 28 10:18:45 2016 +0100
+++ b/hotspot/src/share/vm/gc/parallel/psCompactionManager.hpp	Thu Jan 28 13:30:12 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, 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
@@ -109,6 +109,10 @@
 
   Action _action;
 
+  HeapWord* _last_query_beg;
+  oop _last_query_obj;
+  size_t _last_query_ret;
+
   static PSOldGen* old_gen()             { return _old_gen; }
   static ObjectStartArray* start_array() { return _start_array; }
   static OopTaskQueueSet* stack_array()  { return _stack_array; }
@@ -127,9 +131,26 @@
   // marking stack and overflow stack directly.
 
  public:
+  void reset_bitmap_query_cache() {
+    _last_query_beg = NULL;
+    _last_query_obj = NULL;
+    _last_query_ret = 0;
+  }
+
   Action action() { return _action; }
   void set_action(Action v) { _action = v; }
 
+  // Bitmap query support, cache last query and result
+  HeapWord* last_query_begin() { return _last_query_beg; }
+  oop last_query_object() { return _last_query_obj; }
+  size_t last_query_return() { return _last_query_ret; }
+
+  void set_last_query_begin(HeapWord *new_beg) { _last_query_beg = new_beg; }
+  void set_last_query_object(oop new_obj) { _last_query_obj = new_obj; }
+  void set_last_query_return(size_t new_ret) { _last_query_ret = new_ret; }
+
+  static void reset_all_bitmap_query_caches();
+
   RegionTaskQueue* region_stack()                { return _region_stack; }
   void set_region_stack(RegionTaskQueue* v)       { _region_stack = v; }
 
--- a/hotspot/src/share/vm/gc/parallel/psCompactionManager.inline.hpp	Thu Jan 28 10:18:45 2016 +0100
+++ b/hotspot/src/share/vm/gc/parallel/psCompactionManager.inline.hpp	Thu Jan 28 13:30:12 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2016, 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
@@ -144,7 +144,7 @@
 }
 
 inline void ParCompactionManager::update_contents(oop obj) {
-  obj->pc_update_contents();
+  obj->pc_update_contents(this);
 }
 
 #endif // SHARE_VM_GC_PARALLEL_PSCOMPACTIONMANAGER_INLINE_HPP
--- a/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp	Thu Jan 28 10:18:45 2016 +0100
+++ b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp	Thu Jan 28 13:30:12 2016 +0100
@@ -751,7 +751,7 @@
   return true;
 }
 
-HeapWord* ParallelCompactData::calc_new_pointer(HeapWord* addr) {
+HeapWord* ParallelCompactData::calc_new_pointer(HeapWord* addr, ParCompactionManager* cm) {
   assert(addr != NULL, "Should detect NULL oop earlier");
   assert(ParallelScavengeHeap::heap()->is_in(addr), "not in heap");
   assert(PSParallelCompact::mark_bitmap()->is_marked(addr), "not marked");
@@ -788,7 +788,7 @@
   const size_t block_offset = addr_to_block_ptr(addr)->offset();
 
   const ParMarkBitMap* bitmap = PSParallelCompact::mark_bitmap();
-  const size_t live = bitmap->live_words_in_range(search_start, oop(addr));
+  const size_t live = bitmap->live_words_in_range(cm, search_start, oop(addr));
   result += block_offset + live;
   DEBUG_ONLY(PSParallelCompact::check_new_location(addr, result));
   return result;
@@ -825,11 +825,9 @@
 
 bool PSParallelCompact::IsAliveClosure::do_object_b(oop p) { return mark_bitmap()->is_marked(p); }
 
-PSParallelCompact::AdjustPointerClosure PSParallelCompact::_adjust_pointer_closure;
-PSParallelCompact::AdjustKlassClosure PSParallelCompact::_adjust_klass_closure;
-
 void PSParallelCompact::AdjustKlassClosure::do_klass(Klass* klass) {
-  klass->oops_do(&PSParallelCompact::_adjust_pointer_closure);
+  PSParallelCompact::AdjustPointerClosure closure(_cm);
+  klass->oops_do(&closure);
 }
 
 void PSParallelCompact::post_initialize() {
@@ -977,6 +975,8 @@
 
   // Have worker threads release resources the next time they run a task.
   gc_task_manager()->release_all_resources();
+
+  ParCompactionManager::reset_all_bitmap_query_caches();
 }
 
 void PSParallelCompact::post_compact()
@@ -1801,7 +1801,7 @@
 
     // adjust_roots() updates Universe::_intArrayKlassObj which is
     // needed by the compaction for filling holes in the dense prefix.
-    adjust_roots();
+    adjust_roots(vmthread_cm);
 
     compaction_start.update();
     compact();
@@ -2142,39 +2142,42 @@
 };
 static PSAlwaysTrueClosure always_true;
 
-void PSParallelCompact::adjust_roots() {
+void PSParallelCompact::adjust_roots(ParCompactionManager* cm) {
   // Adjust the pointers to reflect the new locations
   GCTraceTime(Trace, gc, phases) tm("Adjust Roots", &_gc_timer);
 
   // Need new claim bits when tracing through and adjusting pointers.
   ClassLoaderDataGraph::clear_claimed_marks();
 
+  PSParallelCompact::AdjustPointerClosure oop_closure(cm);
+  PSParallelCompact::AdjustKlassClosure klass_closure(cm);
+
   // General strong roots.
-  Universe::oops_do(adjust_pointer_closure());
-  JNIHandles::oops_do(adjust_pointer_closure());   // Global (strong) JNI handles
-  CLDToOopClosure adjust_from_cld(adjust_pointer_closure());
-  Threads::oops_do(adjust_pointer_closure(), &adjust_from_cld, NULL);
-  ObjectSynchronizer::oops_do(adjust_pointer_closure());
-  FlatProfiler::oops_do(adjust_pointer_closure());
-  Management::oops_do(adjust_pointer_closure());
-  JvmtiExport::oops_do(adjust_pointer_closure());
-  SystemDictionary::oops_do(adjust_pointer_closure());
-  ClassLoaderDataGraph::oops_do(adjust_pointer_closure(), adjust_klass_closure(), true);
+  Universe::oops_do(&oop_closure);
+  JNIHandles::oops_do(&oop_closure);   // Global (strong) JNI handles
+  CLDToOopClosure adjust_from_cld(&oop_closure);
+  Threads::oops_do(&oop_closure, &adjust_from_cld, NULL);
+  ObjectSynchronizer::oops_do(&oop_closure);
+  FlatProfiler::oops_do(&oop_closure);
+  Management::oops_do(&oop_closure);
+  JvmtiExport::oops_do(&oop_closure);
+  SystemDictionary::oops_do(&oop_closure);
+  ClassLoaderDataGraph::oops_do(&oop_closure, &klass_closure, true);
 
   // Now adjust pointers in remaining weak roots.  (All of which should
   // have been cleared if they pointed to non-surviving objects.)
   // Global (weak) JNI handles
-  JNIHandles::weak_oops_do(&always_true, adjust_pointer_closure());
-
-  CodeBlobToOopClosure adjust_from_blobs(adjust_pointer_closure(), CodeBlobToOopClosure::FixRelocations);
+  JNIHandles::weak_oops_do(&always_true, &oop_closure);
+
+  CodeBlobToOopClosure adjust_from_blobs(&oop_closure, CodeBlobToOopClosure::FixRelocations);
   CodeCache::blobs_do(&adjust_from_blobs);
-  StringTable::oops_do(adjust_pointer_closure());
-  ref_processor()->weak_oops_do(adjust_pointer_closure());
+  StringTable::oops_do(&oop_closure);
+  ref_processor()->weak_oops_do(&oop_closure);
   // Roots were visited so references into the young gen in roots
   // may have been scanned.  Process them also.
   // Should the reference processor have a span that excludes
   // young gen objects?
-  PSScavenge::reference_processor()->weak_oops_do(adjust_pointer_closure());
+  PSScavenge::reference_processor()->weak_oops_do(&oop_closure);
 }
 
 // Helper class to print 8 region numbers per line and then print the total at the end.
@@ -3062,18 +3065,20 @@
   update_state(words);
 }
 
-void InstanceKlass::oop_pc_update_pointers(oop obj) {
-  oop_oop_iterate_oop_maps<true>(obj, PSParallelCompact::adjust_pointer_closure());
+void InstanceKlass::oop_pc_update_pointers(oop obj, ParCompactionManager* cm) {
+  PSParallelCompact::AdjustPointerClosure closure(cm);
+  oop_oop_iterate_oop_maps<true>(obj, &closure);
 }
 
-void InstanceMirrorKlass::oop_pc_update_pointers(oop obj) {
-  InstanceKlass::oop_pc_update_pointers(obj);
-
-  oop_oop_iterate_statics<true>(obj, PSParallelCompact::adjust_pointer_closure());
+void InstanceMirrorKlass::oop_pc_update_pointers(oop obj, ParCompactionManager* cm) {
+  InstanceKlass::oop_pc_update_pointers(obj, cm);
+
+  PSParallelCompact::AdjustPointerClosure closure(cm);
+  oop_oop_iterate_statics<true>(obj, &closure);
 }
 
-void InstanceClassLoaderKlass::oop_pc_update_pointers(oop obj) {
-  InstanceKlass::oop_pc_update_pointers(obj);
+void InstanceClassLoaderKlass::oop_pc_update_pointers(oop obj, ParCompactionManager* cm) {
+  InstanceKlass::oop_pc_update_pointers(obj, cm);
 }
 
 #ifdef ASSERT
@@ -3092,33 +3097,34 @@
 #endif
 
 template <class T>
-static void oop_pc_update_pointers_specialized(oop obj) {
+static void oop_pc_update_pointers_specialized(oop obj, ParCompactionManager* cm) {
   T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj);
-  PSParallelCompact::adjust_pointer(referent_addr);
+  PSParallelCompact::adjust_pointer(referent_addr, cm);
   T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
-  PSParallelCompact::adjust_pointer(next_addr);
+  PSParallelCompact::adjust_pointer(next_addr, cm);
   T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
-  PSParallelCompact::adjust_pointer(discovered_addr);
+  PSParallelCompact::adjust_pointer(discovered_addr, cm);
   debug_only(trace_reference_gc("InstanceRefKlass::oop_update_ptrs", obj,
                                 referent_addr, next_addr, discovered_addr);)
 }
 
-void InstanceRefKlass::oop_pc_update_pointers(oop obj) {
-  InstanceKlass::oop_pc_update_pointers(obj);
+void InstanceRefKlass::oop_pc_update_pointers(oop obj, ParCompactionManager* cm) {
+  InstanceKlass::oop_pc_update_pointers(obj, cm);
 
   if (UseCompressedOops) {
-    oop_pc_update_pointers_specialized<narrowOop>(obj);
+    oop_pc_update_pointers_specialized<narrowOop>(obj, cm);
   } else {
-    oop_pc_update_pointers_specialized<oop>(obj);
+    oop_pc_update_pointers_specialized<oop>(obj, cm);
   }
 }
 
-void ObjArrayKlass::oop_pc_update_pointers(oop obj) {
+void ObjArrayKlass::oop_pc_update_pointers(oop obj, ParCompactionManager* cm) {
   assert(obj->is_objArray(), "obj must be obj array");
-  oop_oop_iterate_elements<true>(objArrayOop(obj), PSParallelCompact::adjust_pointer_closure());
+  PSParallelCompact::AdjustPointerClosure closure(cm);
+  oop_oop_iterate_elements<true>(objArrayOop(obj), &closure);
 }
 
-void TypeArrayKlass::oop_pc_update_pointers(oop obj) {
+void TypeArrayKlass::oop_pc_update_pointers(oop obj, ParCompactionManager* cm) {
   assert(obj->is_typeArray(),"must be a type array");
 }
 
@@ -3128,7 +3134,7 @@
   assert(bitmap()->obj_size(addr) == words, "bad size");
 
   _source = addr;
-  assert(PSParallelCompact::summary_data().calc_new_pointer(source()) ==
+  assert(PSParallelCompact::summary_data().calc_new_pointer(source(), compaction_manager()) ==
          destination(), "wrong destination");
 
   if (words > words_remaining()) {
--- a/hotspot/src/share/vm/gc/parallel/psParallelCompact.hpp	Thu Jan 28 10:18:45 2016 +0100
+++ b/hotspot/src/share/vm/gc/parallel/psParallelCompact.hpp	Thu Jan 28 13:30:12 2016 +0100
@@ -451,10 +451,10 @@
   HeapWord* partial_obj_end(size_t region_idx) const;
 
   // Return the location of the object after compaction.
-  HeapWord* calc_new_pointer(HeapWord* addr);
+  HeapWord* calc_new_pointer(HeapWord* addr, ParCompactionManager* cm);
 
-  HeapWord* calc_new_pointer(oop p) {
-    return calc_new_pointer((HeapWord*) p);
+  HeapWord* calc_new_pointer(oop p, ParCompactionManager* cm) {
+    return calc_new_pointer((HeapWord*) p, cm);
   }
 
 #ifdef  ASSERT
@@ -937,17 +937,29 @@
 
   class AdjustPointerClosure: public ExtendedOopClosure {
    public:
+    AdjustPointerClosure(ParCompactionManager* cm) {
+      assert(cm != NULL, "associate ParCompactionManage should not be NULL");
+      _cm = cm;
+    }
     template <typename T> void do_oop_nv(T* p);
     virtual void do_oop(oop* p);
     virtual void do_oop(narrowOop* p);
 
     // This closure provides its own oop verification code.
     debug_only(virtual bool should_verify_oops() { return false; })
+   private:
+    ParCompactionManager* _cm;
   };
 
   class AdjustKlassClosure : public KlassClosure {
    public:
+    AdjustKlassClosure(ParCompactionManager* cm) {
+      assert(cm != NULL, "associate ParCompactionManage should not be NULL");
+      _cm = cm;
+    }
     void do_klass(Klass* klass);
+   private:
+    ParCompactionManager* _cm;
   };
 
   friend class AdjustPointerClosure;
@@ -966,8 +978,6 @@
   static ParallelCompactData  _summary_data;
   static IsAliveClosure       _is_alive_closure;
   static SpaceInfo            _space_info[last_space_id];
-  static AdjustPointerClosure _adjust_pointer_closure;
-  static AdjustKlassClosure   _adjust_klass_closure;
 
   // Reference processing (used in ...follow_contents)
   static ReferenceProcessor*  _ref_processor;
@@ -1063,7 +1073,7 @@
   static void summary_phase(ParCompactionManager* cm, bool maximum_compaction);
 
   // Adjust addresses in roots.  Does not adjust addresses in heap.
-  static void adjust_roots();
+  static void adjust_roots(ParCompactionManager* cm);
 
   DEBUG_ONLY(static void write_block_fill_histogram();)
 
@@ -1109,10 +1119,6 @@
   static bool initialize();
 
   // Closure accessors
-  static PSParallelCompact::AdjustPointerClosure* adjust_pointer_closure() {
-    return &_adjust_pointer_closure;
-  }
-  static KlassClosure* adjust_klass_closure()      { return (KlassClosure*)&_adjust_klass_closure; }
   static BoolObjectClosure* is_alive_closure()     { return (BoolObjectClosure*)&_is_alive_closure; }
 
   // Public accessors
@@ -1127,7 +1133,7 @@
   static inline bool mark_obj(oop obj);
   static inline bool is_marked(oop obj);
 
-  template <class T> static inline void adjust_pointer(T* p);
+  template <class T> static inline void adjust_pointer(T* p, ParCompactionManager* cm);
 
   // Compaction support.
   // Return true if p is in the range [beg_addr, end_addr).
--- a/hotspot/src/share/vm/gc/parallel/psParallelCompact.inline.hpp	Thu Jan 28 10:18:45 2016 +0100
+++ b/hotspot/src/share/vm/gc/parallel/psParallelCompact.inline.hpp	Thu Jan 28 13:30:12 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -42,13 +42,13 @@
 }
 
 template <class T>
-inline void PSParallelCompact::adjust_pointer(T* p) {
+inline void PSParallelCompact::adjust_pointer(T* p, ParCompactionManager* cm) {
   T heap_oop = oopDesc::load_heap_oop(p);
   if (!oopDesc::is_null(heap_oop)) {
     oop obj     = oopDesc::decode_heap_oop_not_null(heap_oop);
     assert(ParallelScavengeHeap::heap()->is_in(obj), "should be in heap");
 
-    oop new_obj = (oop)summary_data().calc_new_pointer(obj);
+    oop new_obj = (oop)summary_data().calc_new_pointer(obj, cm);
     assert(new_obj != NULL,                    // is forwarding ptr?
            "should be forwarded");
     // Just always do the update unconditionally?
@@ -62,7 +62,7 @@
 
 template <typename T>
 void PSParallelCompact::AdjustPointerClosure::do_oop_nv(T* p) {
-  adjust_pointer(p);
+  adjust_pointer(p, _cm);
 }
 
 inline void PSParallelCompact::AdjustPointerClosure::do_oop(oop* p)       { do_oop_nv(p); }
--- a/hotspot/src/share/vm/oops/instanceClassLoaderKlass.hpp	Thu Jan 28 10:18:45 2016 +0100
+++ b/hotspot/src/share/vm/oops/instanceClassLoaderKlass.hpp	Thu Jan 28 13:30:12 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, 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
@@ -55,7 +55,7 @@
   void oop_ps_push_contents(  oop obj, PSPromotionManager* pm);
   // Parallel Compact
   void oop_pc_follow_contents(oop obj, ParCompactionManager* cm);
-  void oop_pc_update_pointers(oop obj);
+  void oop_pc_update_pointers(oop obj, ParCompactionManager* cm);
 #endif
 
   // Oop fields (and metadata) iterators
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp	Thu Jan 28 10:18:45 2016 +0100
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp	Thu Jan 28 13:30:12 2016 +0100
@@ -1050,7 +1050,7 @@
   void oop_ps_push_contents(  oop obj, PSPromotionManager* pm);
   // Parallel Compact
   void oop_pc_follow_contents(oop obj, ParCompactionManager* cm);
-  void oop_pc_update_pointers(oop obj);
+  void oop_pc_update_pointers(oop obj, ParCompactionManager* cm);
 #endif
 
   // Oop fields (and metadata) iterators
--- a/hotspot/src/share/vm/oops/instanceMirrorKlass.hpp	Thu Jan 28 10:18:45 2016 +0100
+++ b/hotspot/src/share/vm/oops/instanceMirrorKlass.hpp	Thu Jan 28 13:30:12 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, 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
@@ -96,7 +96,7 @@
   void oop_ps_push_contents(  oop obj, PSPromotionManager* pm);
   // Parallel Compact
   void oop_pc_follow_contents(oop obj, ParCompactionManager* cm);
-  void oop_pc_update_pointers(oop obj);
+  void oop_pc_update_pointers(oop obj, ParCompactionManager* cm);
 #endif
 
   // Oop fields (and metadata) iterators
--- a/hotspot/src/share/vm/oops/instanceRefKlass.hpp	Thu Jan 28 10:18:45 2016 +0100
+++ b/hotspot/src/share/vm/oops/instanceRefKlass.hpp	Thu Jan 28 13:30:12 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -65,7 +65,7 @@
   void oop_ps_push_contents(  oop obj, PSPromotionManager* pm);
   // Parallel Compact
   void oop_pc_follow_contents(oop obj, ParCompactionManager* cm);
-  void oop_pc_update_pointers(oop obj);
+  void oop_pc_update_pointers(oop obj, ParCompactionManager* cm);
 #endif
 
   // Oop fields (and metadata) iterators
--- a/hotspot/src/share/vm/oops/klass.hpp	Thu Jan 28 10:18:45 2016 +0100
+++ b/hotspot/src/share/vm/oops/klass.hpp	Thu Jan 28 13:30:12 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -578,7 +578,7 @@
   virtual void oop_ps_push_contents(  oop obj, PSPromotionManager* pm)   = 0;
   // Parallel Compact
   virtual void oop_pc_follow_contents(oop obj, ParCompactionManager* cm) = 0;
-  virtual void oop_pc_update_pointers(oop obj) = 0;
+  virtual void oop_pc_update_pointers(oop obj, ParCompactionManager* cm) = 0;
 #endif
 
   // Iterators specialized to particular subtypes
--- a/hotspot/src/share/vm/oops/objArrayKlass.hpp	Thu Jan 28 10:18:45 2016 +0100
+++ b/hotspot/src/share/vm/oops/objArrayKlass.hpp	Thu Jan 28 13:30:12 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -116,7 +116,7 @@
   void oop_ps_push_contents(  oop obj, PSPromotionManager* pm);
   // Parallel Compact
   void oop_pc_follow_contents(oop obj, ParCompactionManager* cm);
-  void oop_pc_update_pointers(oop obj);
+  void oop_pc_update_pointers(oop obj, ParCompactionManager* cm);
 #endif
 
   // Oop fields (and metadata) iterators
--- a/hotspot/src/share/vm/oops/oop.hpp	Thu Jan 28 10:18:45 2016 +0100
+++ b/hotspot/src/share/vm/oops/oop.hpp	Thu Jan 28 13:30:12 2016 +0100
@@ -330,8 +330,8 @@
   inline int  ms_adjust_pointers();
 #if INCLUDE_ALL_GCS
   // Parallel Compact
-  inline void pc_follow_contents(ParCompactionManager* pc);
-  inline void pc_update_contents();
+  inline void pc_follow_contents(ParCompactionManager* cm);
+  inline void pc_update_contents(ParCompactionManager* cm);
   // Parallel Scavenge
   inline void ps_push_contents(PSPromotionManager* pm);
 #endif
--- a/hotspot/src/share/vm/oops/oop.inline.hpp	Thu Jan 28 10:18:45 2016 +0100
+++ b/hotspot/src/share/vm/oops/oop.inline.hpp	Thu Jan 28 13:30:12 2016 +0100
@@ -650,11 +650,11 @@
   klass()->oop_pc_follow_contents(this, cm);
 }
 
-void oopDesc::pc_update_contents() {
+void oopDesc::pc_update_contents(ParCompactionManager* cm) {
   Klass* k = klass();
   if (!k->is_typeArray_klass()) {
     // It might contain oops beyond the header, so take the virtual call.
-    k->oop_pc_update_pointers(this);
+    k->oop_pc_update_pointers(this, cm);
   }
   // Else skip it.  The TypeArrayKlass in the header never needs scavenging.
 }
--- a/hotspot/src/share/vm/oops/typeArrayKlass.hpp	Thu Jan 28 10:18:45 2016 +0100
+++ b/hotspot/src/share/vm/oops/typeArrayKlass.hpp	Thu Jan 28 13:30:12 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -81,7 +81,7 @@
   void oop_ps_push_contents(  oop obj, PSPromotionManager* pm);
   // Parallel Compact
   void oop_pc_follow_contents(oop obj, ParCompactionManager* cm);
-  void oop_pc_update_pointers(oop obj);
+  void oop_pc_update_pointers(oop obj, ParCompactionManager* cm);
 #endif
 
   // Oop iterators. Since there are no oops in TypeArrayKlasses,