# HG changeset patch
# User Haoyu Li <leihouyju@gmail.com>
# Date 1574820412 -28800
#      Wed Nov 27 10:06:52 2019 +0800
# Node ID e70a6c6c14d96bd432c24e70f914a4cc6f19d4fd
# Parent  2ab4b0dd19f59de56a39755492897c9fcbbc311d
make code more illustrative

diff -r 2ab4b0dd19f5 -r e70a6c6c14d9 src/hotspot/share/gc/parallel/psCompactionManager.cpp
--- a/src/hotspot/share/gc/parallel/psCompactionManager.cpp	Tue Nov 12 21:03:01 2019 +0800
+++ b/src/hotspot/share/gc/parallel/psCompactionManager.cpp	Wed Nov 27 10:06:52 2019 +0800
@@ -104,11 +104,9 @@
     "Not initialized?");
 
   _shadow_region_array = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<size_t >(10, true);
-  guarantee(_shadow_region_array != NULL, "Could not allocate shadow_region_array");
 
   _shadow_region_monitor = new Monitor(Mutex::barrier, "CompactionManager monitor",
                                        Mutex::_allow_vm_block_flag, Monitor::_safepoint_check_never);
-  guarantee(_shadow_region_monitor != NULL, "Could not allocate shadow_region_monitor");
 }
 
 void ParCompactionManager::reset_all_bitmap_query_caches() {
@@ -174,7 +172,7 @@
   } while (!region_stack()->is_empty());
 }
 
-size_t ParCompactionManager::acquire_shadow_region(PSParallelCompact::RegionData* region_ptr) {
+size_t ParCompactionManager::pop_shadow_region_mt_safe(PSParallelCompact::RegionData* region_ptr) {
   while (true) {
     MutexLocker ml(_shadow_region_monitor, Mutex::_no_safepoint_check_flag);
     if (_shadow_region_array->is_empty()) {
@@ -190,15 +188,15 @@
   }
 }
 
-void ParCompactionManager::release_shadow_region(size_t shadow_region) {
+void ParCompactionManager::push_shadow_region_mt_safe(size_t shadow_region) {
   MutexLocker ml(_shadow_region_monitor, Mutex::_no_safepoint_check_flag);
-  _shadow_region_array->append(shadow_region);
+  _shadow_region_array->push(shadow_region);
 }
 
-void ParCompactionManager::enqueue_shadow_region(size_t shadow_region) {
-  _shadow_region_array->append(shadow_region);
+void ParCompactionManager::push_shadow_region(size_t shadow_region) {
+  _shadow_region_array->push(shadow_region);
 }
 
-void ParCompactionManager::dequeue_shadow_region() {
+void ParCompactionManager::remove_all_shadow_regions() {
   _shadow_region_array->clear();
 }
\ No newline at end of file
diff -r 2ab4b0dd19f5 -r e70a6c6c14d9 src/hotspot/share/gc/parallel/psCompactionManager.hpp
--- a/src/hotspot/share/gc/parallel/psCompactionManager.hpp	Tue Nov 12 21:03:01 2019 +0800
+++ b/src/hotspot/share/gc/parallel/psCompactionManager.hpp	Wed Nov 27 10:06:52 2019 +0800
@@ -25,10 +25,10 @@
 #ifndef SHARE_GC_PARALLEL_PSCOMPACTIONMANAGER_HPP
 #define SHARE_GC_PARALLEL_PSCOMPACTIONMANAGER_HPP
 
+#include "gc/parallel/psParallelCompact.hpp"
 #include "gc/shared/taskqueue.hpp"
 #include "memory/allocation.hpp"
 #include "utilities/stack.hpp"
-#include "psParallelCompact.hpp"
 
 class MutableSpace;
 class PSOldGen;
@@ -78,7 +78,7 @@
 private:
   OverflowTaskQueue<oop, mtGC>        _marking_stack;
   ObjArrayTaskQueue             _objarray_stack;
-  size_t                        _shadow_record;
+  size_t                        _next_shadow_region;
 
   // Is there a way to reuse the _marking_stack for the
   // saving empty regions?  For now just create a different
@@ -87,12 +87,12 @@
 
   static ParMarkBitMap* _mark_bitmap;
 
-  // The shadow region array, we use it in a LIFO fashion, so
-  // that we can reuse shadow regions for better data locality
-  // and utilization
+  // Contains currently free shadow regions. We use it in
+  // a LIFO fashion for better data locality and utilization.
   static GrowableArray<size_t>* _shadow_region_array;
 
-  // This Monitor provides mutual exclusive access of _shadow_region_array
+  // Provides mutual exclusive access of _shadow_region_array.
+  // See pop/push_shadow_region_mt_safe() below
   static Monitor*               _shadow_region_monitor;
 
   Action _action;
@@ -119,13 +119,17 @@
   // marking stack and overflow stack directly.
 
  public:
-  static size_t  acquire_shadow_region(PSParallelCompact::RegionData* region_ptr);
-  static void    release_shadow_region(size_t shadow_region);
-  static void    enqueue_shadow_region(size_t shadow_region);
-  static void    dequeue_shadow_region();
-  inline size_t  shadow_record() { return _shadow_record; }
-  inline void    set_shadow_record(size_t record) { _shadow_record = record; }
-  inline size_t  next_shadow_record(size_t workers) { _shadow_record += workers; return shadow_record(); }
+  static size_t  pop_shadow_region_mt_safe(PSParallelCompact::RegionData* region_ptr);
+  static void    push_shadow_region_mt_safe(size_t shadow_region);
+  static void    push_shadow_region(size_t shadow_region);
+  static void    remove_all_shadow_regions();
+
+  inline size_t  next_shadow_region() { return _next_shadow_region; }
+  inline void    set_next_shadow_region(size_t record) { _next_shadow_region = record; }
+  inline size_t  move_next_shadow_region_by(size_t workers) {
+    _next_shadow_region += workers;
+    return next_shadow_region();
+  }
 
   void reset_bitmap_query_cache() {
     _last_query_beg = NULL;
diff -r 2ab4b0dd19f5 -r e70a6c6c14d9 src/hotspot/share/gc/parallel/psParallelCompact.cpp
--- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp	Tue Nov 12 21:03:01 2019 +0800
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp	Wed Nov 27 10:06:52 2019 +0800
@@ -125,11 +125,6 @@
 const ParallelCompactData::RegionData::region_sz_t
 ParallelCompactData::RegionData::dc_completed = 0xcU << dc_shift;
 
-const int ParallelCompactData::RegionData::UNUSED = 0;
-const int ParallelCompactData::RegionData::SHADOW = 1;
-const int ParallelCompactData::RegionData::FILLED = 2;
-const int ParallelCompactData::RegionData::FINISH = 3;
-
 SpaceInfo PSParallelCompact::_space_info[PSParallelCompact::last_space_id];
 
 SpanSubjectToDiscoveryClosure PSParallelCompact::_span_based_discoverer;
@@ -1028,7 +1023,7 @@
 void PSParallelCompact::post_compact()
 {
   GCTraceTime(Info, gc, phases) tm("Post Compact", &_gc_timer);
-  ParCompactionManager::dequeue_shadow_region();
+  ParCompactionManager::remove_all_shadow_regions();
 
   for (unsigned int id = old_space_id; id < last_space_id; ++id) {
     // Clear the marking bitmap, summary data and split info.
@@ -2423,10 +2418,10 @@
     for (size_t cur = end_region - 1; cur + 1 > beg_region; --cur) {
       if (sd.region(cur)->claim_unsafe()) {
         ParCompactionManager* cm = ParCompactionManager::manager_array(worker_id);
-        if (sd.region(cur)->try_push()) {
-          cm->region_stack()->push(cur);
-          region_logger.handle(cur);
-        }
+        bool result = sd.region(cur)->mark_normal();
+        assert(result, "Must succeed at this point.");
+        cm->region_stack()->push(cur);
+        region_logger.handle(cur);
         // Assign regions to tasks in round-robin fashion.
         if (++worker_id == parallel_gc_threads) {
           worker_id = 0;
@@ -2606,13 +2601,12 @@
 
   size_t region_index = 0;
 
-  PSParallelCompact::initialize_steal_record(worker_id);
   while (true) {
     if (ParCompactionManager::steal(worker_id, region_index)) {
       PSParallelCompact::fill_and_update_region(cm, region_index);
       cm->drain_region_stacks();
-    } else if (PSParallelCompact::steal_shadow_region(cm, region_index)) {
-      // Keep working with the help of shadow regions
+    } else if (PSParallelCompact::steal_unavailable_region(cm, region_index)) {
+      // Fill and update an unavailable region with the help of a shadow region
       PSParallelCompact::fill_and_update_shadow_region(cm, region_index);
       cm->drain_region_stacks();
     } else {
@@ -2669,7 +2663,7 @@
   //
   // max push count is thus: last_space_id * (active_gc_threads * PAR_OLD_DENSE_PREFIX_OVER_PARTITIONING + 1)
   TaskQueue task_queue(last_space_id * (active_gc_threads * PAR_OLD_DENSE_PREFIX_OVER_PARTITIONING + 1));
-  enqueue_shadow_region();
+  initialize_shadow_regions(active_gc_threads);
   prepare_region_draining_tasks(active_gc_threads);
   enqueue_dense_prefix_tasks(task_queue, active_gc_threads);
 
@@ -2976,13 +2970,13 @@
     assert(cur->data_size() > 0, "region must have live data");
     cur->decrement_destination_count();
     if (cur < enqueue_end && cur->available() && cur->claim()) {
-      if (cur->try_push()) {
+      if (cur->mark_normal()) {
         cm->push_region(sd.region(cur));
-      } else if (cur->try_copy()) {
+      } else if (cur->mark_copied()) {
         // Try to copy the content of the shadow region back to its corresponding
         // heap region if the shadow region is filled
         copy_back(sd.region_to_addr(cur->shadow_region()), sd.region_to_addr(cur));
-        cm->release_shadow_region(cur->shadow_region());
+        cm->push_shadow_region_mt_safe(cur->shadow_region());
         cur->set_completed();
       }
     }
@@ -3165,52 +3159,73 @@
   } while (true);
 }
 
-void PSParallelCompact::fill_and_update_region(ParCompactionManager* cm, size_t region_idx) {
+void PSParallelCompact::fill_and_update_region(ParCompactionManager* cm, size_t region_idx)
+{
   MoveAndUpdateClosure cl(mark_bitmap(), cm, region_idx);
   fill_region(cm, cl, region_idx);
 }
 
-void PSParallelCompact::fill_shadow_region(ParCompactionManager* cm, size_t region_idx)
+void PSParallelCompact::fill_and_update_shadow_region(ParCompactionManager* cm, size_t region_idx)
 {
-  // Acquire a shadow region at first
+  // Get a shadow region first
   ParallelCompactData& sd = summary_data();
   RegionData* const region_ptr = sd.region(region_idx);
-  size_t shadow_region = cm->acquire_shadow_region(region_ptr);
+  size_t shadow_region = cm->pop_shadow_region_mt_safe(region_ptr);
   // The zero return value indicates the corresponding heap region is available,
   // so use MoveAndUpdateClosure to fill the normal region. Otherwise, use
-  // ShadowClosure to fill the acquired shadow region.
+  // MoveAndUpdateShadowClosure to fill the acquired shadow region.
   if (shadow_region == 0) {
     MoveAndUpdateClosure cl(mark_bitmap(), cm, region_idx);
-    region_ptr->mark_normal();
+    region_ptr->shadow_to_normal();
     return fill_region(cm, cl, region_idx);
   } else {
-    ShadowClosure cl(mark_bitmap(), cm, region_idx, shadow_region);
+    MoveAndUpdateShadowClosure cl(mark_bitmap(), cm, region_idx, shadow_region);
     return fill_region(cm, cl, region_idx);
   }
 }
 
-void PSParallelCompact::copy_back(HeapWord *shadow_addr, HeapWord *region_addr) {
+void PSParallelCompact::copy_back(HeapWord *shadow_addr, HeapWord *region_addr)
+{
   Copy::aligned_conjoint_words(shadow_addr, region_addr, _summary_data.RegionSize);
 }
 
-bool PSParallelCompact::steal_shadow_region(ParCompactionManager* cm, size_t &region_idx) {
-  size_t record = cm->shadow_record();
-  ParallelCompactData& sd = _summary_data;
+bool PSParallelCompact::steal_unavailable_region(ParCompactionManager* cm, size_t &region_idx)
+{
+  size_t next = cm->next_shadow_region();
+  ParallelCompactData& sd = summary_data();
   size_t old_new_top = sd.addr_to_region_idx(_space_info[old_space_id].new_top());
   uint active_gc_threads = ParallelScavengeHeap::heap()->workers().active_workers();
 
-  while (record < old_new_top) {
-    if (sd.region(record)->try_steal()) {
-      region_idx = record;
+  while (next < old_new_top) {
+    if (sd.region(next)->mark_shadow()) {
+      region_idx = next;
       return true;
     }
-    record = cm->next_shadow_record(active_gc_threads);
+    next = cm->move_next_shadow_region_by(active_gc_threads);
   }
 
   return false;
 }
 
-void PSParallelCompact::enqueue_shadow_region() {
+// The shadow region is an optimization to address region dependencies in full GC. The basic
+// idea is making more regions available by temporally storing their live objects in empty
+// shadow regions to resolve dependencies between them and the destination regions. Therefore,
+// GC threads need not wait destination regions to be available before processing sources.
+//
+// A typical workflow would be:
+// After draining its own stack and failing to steal from others, a GC worker would pick an
+// unavailable region (destination count > 0) and get a shadow region. Then the worker fills
+// the shadow region by copying live objects from source regions of the unavailable one. Once
+// the unavailable region becomes available, the data in the shadow region will be copied back.
+// Shadow regions are empty regions in the to-space and regions between top and end of other spaces.
+//
+// More more details, please refer to §4.2 of the VEE'19 paper:
+// Haoyu Li, Mingyu Wu, Binyu Zang, and Haibo Chen. 2019. ScissorGC: scalable and efficient
+// compaction for Java full garbage collection. In Proceedings of the 15th ACM SIGPLAN/SIGOPS
+// International Conference on Virtual Execution Environments (VEE 2019). ACM, New York, NY, USA,
+// 108-121. DOI: https://doi.org/10.1145/3313808.3313820
+void PSParallelCompact::initialize_shadow_regions(uint parallel_gc_threads)
+{
   const ParallelCompactData& sd = PSParallelCompact::summary_data();
 
   for (unsigned int id = old_space_id; id < last_space_id; ++id) {
@@ -3222,17 +3237,16 @@
     const size_t end_region =
       sd.addr_to_region_idx(sd.region_align_down(space->end()));
 
-    for (size_t cur = beg_region + 1; cur < end_region; ++cur) {
-      ParCompactionManager::enqueue_shadow_region(cur);
+    for (size_t cur = beg_region; cur < end_region; ++cur) {
+      ParCompactionManager::push_shadow_region(cur);
     }
   }
-}
-
-void PSParallelCompact::initialize_steal_record(uint which) {
-  ParCompactionManager* cm = ParCompactionManager::gc_thread_compaction_manager(which);
-
-  size_t record = _summary_data.addr_to_region_idx(_space_info[old_space_id].dense_prefix());
-  cm->set_shadow_record(record + which);
+
+  size_t beg_region = sd.addr_to_region_idx(_space_info[old_space_id].dense_prefix());
+  for (uint i = 0; i < parallel_gc_threads; i++) {
+    ParCompactionManager *cm = ParCompactionManager::manager_array(i);
+    cm->set_next_shadow_region(beg_region + i);
+  }
 }
 
 void PSParallelCompact::fill_blocks(size_t region_idx)
@@ -3337,7 +3351,7 @@
 
 void MoveAndUpdateClosure::complete_region(ParCompactionManager *cm, HeapWord *dest_addr,
                                            PSParallelCompact::RegionData *region_ptr) {
-  assert(region_ptr->shadow_state() == ParallelCompactData::RegionData::FINISH, "Region should be finished");
+  assert(region_ptr->shadow_state() == ParallelCompactData::RegionData::FinishedShadow, "Region should be finished");
   region_ptr->set_completed();
 }
 
@@ -3373,19 +3387,19 @@
   return is_full() ? ParMarkBitMap::full : ParMarkBitMap::incomplete;
 }
 
-void ShadowClosure::complete_region(ParCompactionManager *cm, HeapWord *dest_addr,
-                                    PSParallelCompact::RegionData *region_ptr) {
-  assert(region_ptr->shadow_state() == ParallelCompactData::RegionData::SHADOW, "Region should be shadow");
+void MoveAndUpdateShadowClosure::complete_region(ParCompactionManager *cm, HeapWord *dest_addr,
+                                                 PSParallelCompact::RegionData *region_ptr) {
+  assert(region_ptr->shadow_state() == ParallelCompactData::RegionData::Shadow, "Region should be shadow");
   // Record the shadow region index
   region_ptr->set_shadow_region(_shadow);
   // Mark the shadow region filled
   region_ptr->mark_filled();
   // Try to copy the content of the shadow region back to its corresponding
   // heap region if available
-  if (((region_ptr->available() && region_ptr->claim()) || region_ptr->claimed()) && region_ptr->try_copy()) {
+  if (((region_ptr->available() && region_ptr->claim()) || region_ptr->claimed()) && region_ptr->mark_copied()) {
     region_ptr->set_completed();
     PSParallelCompact::copy_back(PSParallelCompact::summary_data().region_to_addr(_shadow), dest_addr);
-    cm->release_shadow_region(_shadow);
+    cm->push_shadow_region_mt_safe(_shadow);
   }
 }
 
diff -r 2ab4b0dd19f5 -r e70a6c6c14d9 src/hotspot/share/gc/parallel/psParallelCompact.hpp
--- a/src/hotspot/share/gc/parallel/psParallelCompact.hpp	Tue Nov 12 21:03:01 2019 +0800
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.hpp	Wed Nov 27 10:06:52 2019 +0800
@@ -332,24 +332,26 @@
 
     // Possible values of _shadow_state, and transition is as follows
     // Normal Path:
-    // UNUSED -> try_push() -> FINISHED
-    // Steal  Path:
-    // UNUSED -> try_steal() -> SHADOW -> mark_filled() -> FILLED -> try_copy() -> FINISHED
-    static const int UNUSED;                     // Original state
-    static const int SHADOW;                     // Stolen by an idle thread, and a shadow region is created for it
-    static const int FILLED;                     // Its shadow region has been filled and ready to be copied back
-    static const int FINISH;                     // Work has been done
+    // UnusedRegion -> mark_normal() -> NormalRegion
+    // Shadow Path:
+    // UnusedRegion -> mark_shadow() -> ShadowRegion ->
+    // mark_filled() -> FilledShadow -> mark_copied() -> CopiedShadow
+    static const int UnusedRegion = 0; // The region is not collected yet
+    static const int ShadowRegion = 1; // Stolen by an idle thread, and a shadow region is created for it
+    static const int FilledShadow = 2; // Its shadow region has been filled and ready to be copied back
+    static const int CopiedShadow = 3; // The data of the shadow region has been copied back
+    static const int NormalRegion = 4; // The region will be collected by the original parallel algorithm
 
-    // Preempt the region to avoid double processes
-    inline bool try_push();
-    inline bool try_steal();
-    // Mark the region as filled and ready to be copied back
+    // Mark the current region as normal or shadow to enter different processing paths
+    inline bool mark_normal();
+    inline bool mark_shadow();
+    // Mark the shadow region as filled and ready to be copied back
     inline void mark_filled();
-    // Preempt the region to copy the shadow region content back
-    inline bool try_copy();
-    // Special case: see the comment in PSParallelCompact::fill_shadow_region.
+    // Mark the shadow region as copied back to avoid double copying.
+    inline bool mark_copied();
+    // Special case: see the comment in PSParallelCompact::fill_and_update_shadow_region.
     // Return to the normal path here
-    inline void mark_normal();
+    inline void shadow_to_normal();
 
 
     int shadow_state() { return _shadow_state; }
@@ -625,26 +627,27 @@
   return old == los;
 }
 
-inline bool ParallelCompactData::RegionData::try_push() {
-  return Atomic::cmpxchg(FINISH, &_shadow_state, UNUSED) == UNUSED;
+inline bool ParallelCompactData::RegionData::mark_normal() {
+  return Atomic::cmpxchg(NormalRegion, &_shadow_state, UnusedRegion, memory_order_relaxed) == UnusedRegion;
 }
 
-inline bool ParallelCompactData::RegionData::try_steal() {
-  return Atomic::cmpxchg(SHADOW, &_shadow_state, UNUSED) == UNUSED;
+inline bool ParallelCompactData::RegionData::mark_shadow() {
+  if (_shadow_state != UnusedRegion) return false;
+  return Atomic::cmpxchg(ShadowRegion, &_shadow_state, UnusedRegion, memory_order_relaxed) == UnusedRegion;
 }
 
 inline void ParallelCompactData::RegionData::mark_filled() {
-  int old = Atomic::cmpxchg(FILLED, &_shadow_state, SHADOW);
-  assert(old == SHADOW, "Fail to mark the region as filled");
+  int old = Atomic::cmpxchg(FilledShadow, &_shadow_state, ShadowRegion, memory_order_relaxed);
+  assert(old == Shadow, "Fail to mark the region as filled");
 }
 
-inline bool ParallelCompactData::RegionData::try_copy() {
-  return Atomic::cmpxchg(FINISH, &_shadow_state, FILLED) == FILLED;
+inline bool ParallelCompactData::RegionData::mark_copied() {
+  return Atomic::cmpxchg(CopiedShadow, &_shadow_state, FilledShadow, memory_order_relaxed) == FilledShadow;
 }
 
-void ParallelCompactData::RegionData::mark_normal() {
-  int old = Atomic::cmpxchg(FINISH, &_shadow_state, SHADOW);
-  assert(old == SHADOW, "Fail to mark the region as finish");
+void ParallelCompactData::RegionData::shadow_to_normal() {
+  int old = Atomic::cmpxchg(NormalRegion, &_shadow_state, ShadowRegion, memory_order_relaxed);
+  assert(old == Shadow, "Fail to mark the region as finish");
 }
 
 inline ParallelCompactData::RegionData*
@@ -1233,17 +1236,13 @@
   static void fill_region(ParCompactionManager* cm, MoveAndUpdateClosure& closure, size_t region);
   static void fill_and_update_region(ParCompactionManager* cm, size_t region);
 
-  static bool steal_shadow_region(ParCompactionManager* cm, size_t& region_idx);
-  static void fill_shadow_region(ParCompactionManager* cm, size_t region_idx);
-  static void fill_and_update_shadow_region(ParCompactionManager* cm, size_t region) {
-    fill_shadow_region(cm, region);
-  }
+  static bool steal_unavailable_region(ParCompactionManager* cm, size_t& region_idx);
+  static void fill_and_update_shadow_region(ParCompactionManager* cm, size_t region);
   // Copy the content of a shadow region back to its corresponding heap region
   static void copy_back(HeapWord* shadow_addr, HeapWord* region_addr);
-  // Initialize the steal record of a GC thread
-  static void initialize_steal_record(uint which);
-  // Reuse the empty heap regions as shadow regions, like to-space regions
-  static void enqueue_shadow_region();
+  // Collect empty regions as shadow regions and initialize the
+  // _next_shadow_region filed for each compact manager
+  static void initialize_shadow_regions(uint parallel_gc_threads);
 
   // Fill in the block table for the specified region.
   static void fill_blocks(size_t region_idx);
@@ -1353,10 +1352,10 @@
   _destination += words;
 }
 
-class ShadowClosure: public MoveAndUpdateClosure {
+class MoveAndUpdateShadowClosure: public MoveAndUpdateClosure {
   inline size_t calculate_shadow_offset(size_t region_idx, size_t shadow_idx);
 public:
-  inline ShadowClosure(ParMarkBitMap* bitmap, ParCompactionManager* cm,
+  inline MoveAndUpdateShadowClosure(ParMarkBitMap* bitmap, ParCompactionManager* cm,
                        size_t region, size_t shadow);
 
   virtual void complete_region(ParCompactionManager* cm, HeapWord* dest_addr,
@@ -1366,7 +1365,7 @@
   size_t _shadow;
 };
 
-inline size_t ShadowClosure::calculate_shadow_offset(size_t region_idx, size_t shadow_idx) {
+inline size_t MoveAndUpdateShadowClosure::calculate_shadow_offset(size_t region_idx, size_t shadow_idx) {
   ParallelCompactData& sd = PSParallelCompact::summary_data();
   HeapWord* dest_addr = sd.region_to_addr(region_idx);
   HeapWord* shadow_addr = sd.region_to_addr(shadow_idx);
@@ -1374,10 +1373,10 @@
 }
 
 inline
-ShadowClosure::ShadowClosure(ParMarkBitMap *bitmap,
-                             ParCompactionManager *cm,
-                             size_t region,
-                             size_t shadow) :
+MoveAndUpdateShadowClosure::MoveAndUpdateShadowClosure(ParMarkBitMap *bitmap,
+                                                       ParCompactionManager *cm,
+                                                       size_t region,
+                                                       size_t shadow) :
   MoveAndUpdateClosure(bitmap, cm, region),
   _shadow(shadow) {
   _offset = calculate_shadow_offset(region, shadow);
