src/hotspot/share/gc/shenandoah/shenandoahMarkCompact.cpp
changeset 55076 785a12e0f89b
parent 54924 ba1eccda5450
child 55513 be05771cdfdf
child 58678 9cf78a70fa4f
equal deleted inserted replaced
55075:044f2ca6ce22 55076:785a12e0f89b
    23 
    23 
    24 #include "precompiled.hpp"
    24 #include "precompiled.hpp"
    25 
    25 
    26 #include "code/codeCache.hpp"
    26 #include "code/codeCache.hpp"
    27 #include "gc/shared/gcTraceTime.inline.hpp"
    27 #include "gc/shared/gcTraceTime.inline.hpp"
       
    28 #include "gc/shared/preservedMarks.inline.hpp"
    28 #include "gc/shenandoah/shenandoahForwarding.inline.hpp"
    29 #include "gc/shenandoah/shenandoahForwarding.inline.hpp"
    29 #include "gc/shenandoah/shenandoahConcurrentMark.inline.hpp"
    30 #include "gc/shenandoah/shenandoahConcurrentMark.inline.hpp"
    30 #include "gc/shenandoah/shenandoahCollectionSet.hpp"
    31 #include "gc/shenandoah/shenandoahCollectionSet.hpp"
    31 #include "gc/shenandoah/shenandoahFreeSet.hpp"
    32 #include "gc/shenandoah/shenandoahFreeSet.hpp"
    32 #include "gc/shenandoah/shenandoahPhaseTimings.hpp"
    33 #include "gc/shenandoah/shenandoahPhaseTimings.hpp"
    44 #include "gc/shenandoah/shenandoahWorkerPolicy.hpp"
    45 #include "gc/shenandoah/shenandoahWorkerPolicy.hpp"
    45 #include "memory/metaspace.hpp"
    46 #include "memory/metaspace.hpp"
    46 #include "memory/universe.hpp"
    47 #include "memory/universe.hpp"
    47 #include "oops/compressedOops.inline.hpp"
    48 #include "oops/compressedOops.inline.hpp"
    48 #include "oops/oop.inline.hpp"
    49 #include "oops/oop.inline.hpp"
       
    50 #include "runtime/biasedLocking.hpp"
    49 #include "runtime/thread.hpp"
    51 #include "runtime/thread.hpp"
    50 #include "utilities/copy.hpp"
    52 #include "utilities/copy.hpp"
    51 #include "utilities/growableArray.hpp"
    53 #include "utilities/growableArray.hpp"
    52 #include "gc/shared/workgroup.hpp"
    54 #include "gc/shared/workgroup.hpp"
       
    55 
       
    56 ShenandoahMarkCompact::ShenandoahMarkCompact() :
       
    57   _gc_timer(NULL),
       
    58   _preserved_marks(new PreservedMarksSet(true)) {}
    53 
    59 
    54 void ShenandoahMarkCompact::initialize(GCTimer* gc_timer) {
    60 void ShenandoahMarkCompact::initialize(GCTimer* gc_timer) {
    55   _gc_timer = gc_timer;
    61   _gc_timer = gc_timer;
    56 }
    62 }
    57 
    63 
   119     rp->abandon_partial_discovery();
   125     rp->abandon_partial_discovery();
   120     rp->verify_no_references_recorded();
   126     rp->verify_no_references_recorded();
   121 
   127 
   122     // e. Set back forwarded objects bit back, in case some steps above dropped it.
   128     // e. Set back forwarded objects bit back, in case some steps above dropped it.
   123     heap->set_has_forwarded_objects(has_forwarded_objects);
   129     heap->set_has_forwarded_objects(has_forwarded_objects);
       
   130 
       
   131     // The rest of prologue:
       
   132     BiasedLocking::preserve_marks();
       
   133     _preserved_marks->init(heap->workers()->active_workers());
   124   }
   134   }
   125 
   135 
   126   heap->make_parsable(true);
   136   heap->make_parsable(true);
   127 
   137 
   128   OrderAccess::fence();
   138   OrderAccess::fence();
   157     phase3_update_references();
   167     phase3_update_references();
   158 
   168 
   159     phase4_compact_objects(worker_slices);
   169     phase4_compact_objects(worker_slices);
   160   }
   170   }
   161 
   171 
       
   172   {
       
   173     // Epilogue
       
   174     SharedRestorePreservedMarksTaskExecutor exec(heap->workers());
       
   175     _preserved_marks->restore(&exec);
       
   176     BiasedLocking::restore_marks();
       
   177     _preserved_marks->reclaim();
       
   178 
       
   179     JvmtiExport::gc_epilogue();
       
   180   }
       
   181 
   162   // Resize metaspace
   182   // Resize metaspace
   163   MetaspaceGC::compute_new_size();
   183   MetaspaceGC::compute_new_size();
   164 
   184 
   165   // Free worker slices
   185   // Free worker slices
   166   for (uint i = 0; i < heap->max_workers(); i++) {
   186   for (uint i = 0; i < heap->max_workers(); i++) {
   167     delete worker_slices[i];
   187     delete worker_slices[i];
   168   }
   188   }
   169   FREE_C_HEAP_ARRAY(ShenandoahHeapRegionSet*, worker_slices);
   189   FREE_C_HEAP_ARRAY(ShenandoahHeapRegionSet*, worker_slices);
   170 
       
   171   JvmtiExport::gc_epilogue();
       
   172 
   190 
   173   heap->set_full_gc_move_in_progress(false);
   191   heap->set_full_gc_move_in_progress(false);
   174   heap->set_full_gc_in_progress(false);
   192   heap->set_full_gc_in_progress(false);
   175 
   193 
   176   if (ShenandoahVerify) {
   194   if (ShenandoahVerify) {
   228   heap->mark_complete_marking_context();
   246   heap->mark_complete_marking_context();
   229 }
   247 }
   230 
   248 
   231 class ShenandoahPrepareForCompactionObjectClosure : public ObjectClosure {
   249 class ShenandoahPrepareForCompactionObjectClosure : public ObjectClosure {
   232 private:
   250 private:
       
   251   PreservedMarks*          const _preserved_marks;
   233   ShenandoahHeap*          const _heap;
   252   ShenandoahHeap*          const _heap;
   234   GrowableArray<ShenandoahHeapRegion*>& _empty_regions;
   253   GrowableArray<ShenandoahHeapRegion*>& _empty_regions;
   235   int _empty_regions_pos;
   254   int _empty_regions_pos;
   236   ShenandoahHeapRegion*          _to_region;
   255   ShenandoahHeapRegion*          _to_region;
   237   ShenandoahHeapRegion*          _from_region;
   256   ShenandoahHeapRegion*          _from_region;
   238   HeapWord* _compact_point;
   257   HeapWord* _compact_point;
   239 
   258 
   240 public:
   259 public:
   241   ShenandoahPrepareForCompactionObjectClosure(GrowableArray<ShenandoahHeapRegion*>& empty_regions, ShenandoahHeapRegion* to_region) :
   260   ShenandoahPrepareForCompactionObjectClosure(PreservedMarks* preserved_marks,
       
   261                                               GrowableArray<ShenandoahHeapRegion*>& empty_regions,
       
   262                                               ShenandoahHeapRegion* to_region) :
       
   263     _preserved_marks(preserved_marks),
   242     _heap(ShenandoahHeap::heap()),
   264     _heap(ShenandoahHeap::heap()),
   243     _empty_regions(empty_regions),
   265     _empty_regions(empty_regions),
   244     _empty_regions_pos(0),
   266     _empty_regions_pos(0),
   245     _to_region(to_region),
   267     _to_region(to_region),
   246     _from_region(NULL),
   268     _from_region(NULL),
   266   void do_object(oop p) {
   288   void do_object(oop p) {
   267     assert(_from_region != NULL, "must set before work");
   289     assert(_from_region != NULL, "must set before work");
   268     assert(_heap->complete_marking_context()->is_marked(p), "must be marked");
   290     assert(_heap->complete_marking_context()->is_marked(p), "must be marked");
   269     assert(!_heap->complete_marking_context()->allocated_after_mark_start((HeapWord*) p), "must be truly marked");
   291     assert(!_heap->complete_marking_context()->allocated_after_mark_start((HeapWord*) p), "must be truly marked");
   270 
   292 
   271     size_t obj_size = p->size() + ShenandoahForwarding::word_size();
   293     size_t obj_size = p->size();
   272     if (_compact_point + obj_size > _to_region->end()) {
   294     if (_compact_point + obj_size > _to_region->end()) {
   273       finish_region();
   295       finish_region();
   274 
   296 
   275       // Object doesn't fit. Pick next empty region and start compacting there.
   297       // Object doesn't fit. Pick next empty region and start compacting there.
   276       ShenandoahHeapRegion* new_to_region;
   298       ShenandoahHeapRegion* new_to_region;
   289     }
   311     }
   290 
   312 
   291     // Object fits into current region, record new location:
   313     // Object fits into current region, record new location:
   292     assert(_compact_point + obj_size <= _to_region->end(), "must fit");
   314     assert(_compact_point + obj_size <= _to_region->end(), "must fit");
   293     shenandoah_assert_not_forwarded(NULL, p);
   315     shenandoah_assert_not_forwarded(NULL, p);
   294     ShenandoahForwarding::set_forwardee_raw(p, _compact_point + ShenandoahForwarding::word_size());
   316     _preserved_marks->push_if_necessary(p, p->mark_raw());
       
   317     p->forward_to(oop(_compact_point));
   295     _compact_point += obj_size;
   318     _compact_point += obj_size;
   296   }
   319   }
   297 };
   320 };
   298 
   321 
   299 class ShenandoahPrepareForCompactionTask : public AbstractGangTask {
   322 class ShenandoahPrepareForCompactionTask : public AbstractGangTask {
   300 private:
   323 private:
       
   324   PreservedMarksSet*        const _preserved_marks;
   301   ShenandoahHeap*           const _heap;
   325   ShenandoahHeap*           const _heap;
   302   ShenandoahHeapRegionSet** const _worker_slices;
   326   ShenandoahHeapRegionSet** const _worker_slices;
   303   ShenandoahRegionIterator        _heap_regions;
   327   ShenandoahRegionIterator        _heap_regions;
   304 
   328 
   305   ShenandoahHeapRegion* next_from_region(ShenandoahHeapRegionSet* slice) {
   329   ShenandoahHeapRegion* next_from_region(ShenandoahHeapRegionSet* slice) {
   318 
   342 
   319     return from_region;
   343     return from_region;
   320   }
   344   }
   321 
   345 
   322 public:
   346 public:
   323   ShenandoahPrepareForCompactionTask(ShenandoahHeapRegionSet** worker_slices) :
   347   ShenandoahPrepareForCompactionTask(PreservedMarksSet* preserved_marks, ShenandoahHeapRegionSet** worker_slices) :
   324     AbstractGangTask("Shenandoah Prepare For Compaction Task"),
   348     AbstractGangTask("Shenandoah Prepare For Compaction Task"),
       
   349     _preserved_marks(preserved_marks),
   325     _heap(ShenandoahHeap::heap()), _worker_slices(worker_slices) {
   350     _heap(ShenandoahHeap::heap()), _worker_slices(worker_slices) {
   326   }
   351   }
   327 
   352 
   328   void work(uint worker_id) {
   353   void work(uint worker_id) {
   329     ShenandoahHeapRegionSet* slice = _worker_slices[worker_id];
   354     ShenandoahHeapRegionSet* slice = _worker_slices[worker_id];
   335 
   360 
   336     // Sliding compaction. Walk all regions in the slice, and compact them.
   361     // Sliding compaction. Walk all regions in the slice, and compact them.
   337     // Remember empty regions and reuse them as needed.
   362     // Remember empty regions and reuse them as needed.
   338     ResourceMark rm;
   363     ResourceMark rm;
   339     GrowableArray<ShenandoahHeapRegion*> empty_regions((int)_heap->num_regions());
   364     GrowableArray<ShenandoahHeapRegion*> empty_regions((int)_heap->num_regions());
   340     ShenandoahPrepareForCompactionObjectClosure cl(empty_regions, from_region);
   365     ShenandoahPrepareForCompactionObjectClosure cl(_preserved_marks->get(worker_id), empty_regions, from_region);
   341     while (from_region != NULL) {
   366     while (from_region != NULL) {
   342       cl.set_from_region(from_region);
   367       cl.set_from_region(from_region);
   343       if (from_region->has_live()) {
   368       if (from_region->has_live()) {
   344         _heap->marked_object_iterate(from_region, &cl);
   369         _heap->marked_object_iterate(from_region, &cl);
   345       }
   370       }
   375   // detected, then sliding restarts towards that non-movable region.
   400   // detected, then sliding restarts towards that non-movable region.
   376 
   401 
   377   size_t to_begin = heap->num_regions();
   402   size_t to_begin = heap->num_regions();
   378   size_t to_end = heap->num_regions();
   403   size_t to_end = heap->num_regions();
   379 
   404 
   380   for (size_t c = heap->num_regions() - 1; c > 0; c--) {
   405   for (size_t c = heap->num_regions(); c > 0; c--) {
   381     ShenandoahHeapRegion *r = heap->get_region(c);
   406     ShenandoahHeapRegion *r = heap->get_region(c - 1);
   382     if (r->is_humongous_continuation() || (r->new_top() == r->bottom())) {
   407     if (r->is_humongous_continuation() || (r->new_top() == r->bottom())) {
   383       // To-region candidate: record this, and continue scan
   408       // To-region candidate: record this, and continue scan
   384       to_begin = r->region_number();
   409       to_begin = r->region_number();
   385       continue;
   410       continue;
   386     }
   411     }
   387 
   412 
   388     if (r->is_humongous_start() && r->is_move_allowed()) {
   413     if (r->is_humongous_start() && r->is_move_allowed()) {
   389       // From-region candidate: movable humongous region
   414       // From-region candidate: movable humongous region
   390       oop old_obj = oop(r->bottom() + ShenandoahForwarding::word_size());
   415       oop old_obj = oop(r->bottom());
   391       size_t words_size = old_obj->size() + ShenandoahForwarding::word_size();
   416       size_t words_size = old_obj->size();
   392       size_t num_regions = ShenandoahHeapRegion::required_regions(words_size * HeapWordSize);
   417       size_t num_regions = ShenandoahHeapRegion::required_regions(words_size * HeapWordSize);
   393 
   418 
   394       size_t start = to_end - num_regions;
   419       size_t start = to_end - num_regions;
   395 
   420 
   396       if (start >= to_begin && start != r->region_number()) {
   421       if (start >= to_begin && start != r->region_number()) {
   397         // Fits into current window, and the move is non-trivial. Record the move then, and continue scan.
   422         // Fits into current window, and the move is non-trivial. Record the move then, and continue scan.
   398         ShenandoahForwarding::set_forwardee_raw(old_obj, heap->get_region(start)->bottom() + ShenandoahForwarding::word_size());
   423         _preserved_marks->get(0)->push_if_necessary(old_obj, old_obj->mark_raw());
       
   424         old_obj->forward_to(oop(heap->get_region(start)->bottom()));
   399         to_end = start;
   425         to_end = start;
   400         continue;
   426         continue;
   401       }
   427       }
   402     }
   428     }
   403 
   429 
   441     _heap(ShenandoahHeap::heap()),
   467     _heap(ShenandoahHeap::heap()),
   442     _ctx(ShenandoahHeap::heap()->complete_marking_context()) {}
   468     _ctx(ShenandoahHeap::heap()->complete_marking_context()) {}
   443 
   469 
   444   void heap_region_do(ShenandoahHeapRegion* r) {
   470   void heap_region_do(ShenandoahHeapRegion* r) {
   445     if (r->is_humongous_start()) {
   471     if (r->is_humongous_start()) {
   446       oop humongous_obj = oop(r->bottom() + ShenandoahForwarding::word_size());
   472       oop humongous_obj = oop(r->bottom());
   447       if (!_ctx->is_marked(humongous_obj)) {
   473       if (!_ctx->is_marked(humongous_obj)) {
   448         assert(!r->has_live(),
   474         assert(!r->has_live(),
   449                "Region " SIZE_FORMAT " is not marked, should not have live", r->region_number());
   475                "Region " SIZE_FORMAT " is not marked, should not have live", r->region_number());
   450         _heap->trash_humongous_region_at(r);
   476         _heap->trash_humongous_region_at(r);
   451       } else {
   477       } else {
   482   }
   508   }
   483 
   509 
   484   // Compute the new addresses for regular objects
   510   // Compute the new addresses for regular objects
   485   {
   511   {
   486     ShenandoahGCPhase phase(ShenandoahPhaseTimings::full_gc_calculate_addresses_regular);
   512     ShenandoahGCPhase phase(ShenandoahPhaseTimings::full_gc_calculate_addresses_regular);
   487     ShenandoahPrepareForCompactionTask prepare_task(worker_slices);
   513     ShenandoahPrepareForCompactionTask prepare_task(_preserved_marks, worker_slices);
   488     heap->workers()->run_task(&prepare_task);
   514     heap->workers()->run_task(&prepare_task);
   489   }
   515   }
   490 
   516 
   491   // Compute the new addresses for humongous objects
   517   // Compute the new addresses for humongous objects
   492   {
   518   {
   504   inline void do_oop_work(T* p) {
   530   inline void do_oop_work(T* p) {
   505     T o = RawAccess<>::oop_load(p);
   531     T o = RawAccess<>::oop_load(p);
   506     if (!CompressedOops::is_null(o)) {
   532     if (!CompressedOops::is_null(o)) {
   507       oop obj = CompressedOops::decode_not_null(o);
   533       oop obj = CompressedOops::decode_not_null(o);
   508       assert(_ctx->is_marked(obj), "must be marked");
   534       assert(_ctx->is_marked(obj), "must be marked");
   509       oop forw = oop(ShenandoahForwarding::get_forwardee_raw(obj));
   535       if (obj->is_forwarded()) {
   510       RawAccess<IS_NOT_NULL>::oop_store(p, forw);
   536         oop forw = obj->forwardee();
       
   537         RawAccess<IS_NOT_NULL>::oop_store(p, forw);
       
   538       }
   511     }
   539     }
   512   }
   540   }
   513 
   541 
   514 public:
   542 public:
   515   ShenandoahAdjustPointersClosure() :
   543   ShenandoahAdjustPointersClosure() :
   529   ShenandoahAdjustPointersObjectClosure() :
   557   ShenandoahAdjustPointersObjectClosure() :
   530     _heap(ShenandoahHeap::heap()) {
   558     _heap(ShenandoahHeap::heap()) {
   531   }
   559   }
   532   void do_object(oop p) {
   560   void do_object(oop p) {
   533     assert(_heap->complete_marking_context()->is_marked(p), "must be marked");
   561     assert(_heap->complete_marking_context()->is_marked(p), "must be marked");
   534     HeapWord* forw = ShenandoahForwarding::get_forwardee_raw(p);
       
   535     p->oop_iterate(&_cl);
   562     p->oop_iterate(&_cl);
   536   }
   563   }
   537 };
   564 };
   538 
   565 
   539 class ShenandoahAdjustPointersTask : public AbstractGangTask {
   566 class ShenandoahAdjustPointersTask : public AbstractGangTask {
   560 };
   587 };
   561 
   588 
   562 class ShenandoahAdjustRootPointersTask : public AbstractGangTask {
   589 class ShenandoahAdjustRootPointersTask : public AbstractGangTask {
   563 private:
   590 private:
   564   ShenandoahRootAdjuster* _rp;
   591   ShenandoahRootAdjuster* _rp;
   565 
   592   PreservedMarksSet* _preserved_marks;
   566 public:
   593 public:
   567   ShenandoahAdjustRootPointersTask(ShenandoahRootAdjuster* rp) :
   594   ShenandoahAdjustRootPointersTask(ShenandoahRootAdjuster* rp, PreservedMarksSet* preserved_marks) :
   568     AbstractGangTask("Shenandoah Adjust Root Pointers Task"),
   595     AbstractGangTask("Shenandoah Adjust Root Pointers Task"),
   569     _rp(rp) {}
   596     _rp(rp),
       
   597     _preserved_marks(preserved_marks) {}
   570 
   598 
   571   void work(uint worker_id) {
   599   void work(uint worker_id) {
   572     ShenandoahAdjustPointersClosure cl;
   600     ShenandoahAdjustPointersClosure cl;
   573     _rp->roots_do(worker_id, &cl);
   601     _rp->roots_do(worker_id, &cl);
       
   602     _preserved_marks->get(worker_id)->adjust_during_full_gc();
   574   }
   603   }
   575 };
   604 };
   576 
   605 
   577 void ShenandoahMarkCompact::phase3_update_references() {
   606 void ShenandoahMarkCompact::phase3_update_references() {
   578   GCTraceTime(Info, gc, phases) time("Phase 3: Adjust pointers", _gc_timer);
   607   GCTraceTime(Info, gc, phases) time("Phase 3: Adjust pointers", _gc_timer);
   585   {
   614   {
   586 #if COMPILER2_OR_JVMCI
   615 #if COMPILER2_OR_JVMCI
   587     DerivedPointerTable::clear();
   616     DerivedPointerTable::clear();
   588 #endif
   617 #endif
   589     ShenandoahRootAdjuster rp(nworkers, ShenandoahPhaseTimings::full_gc_roots);
   618     ShenandoahRootAdjuster rp(nworkers, ShenandoahPhaseTimings::full_gc_roots);
   590     ShenandoahAdjustRootPointersTask task(&rp);
   619     ShenandoahAdjustRootPointersTask task(&rp, _preserved_marks);
   591     workers->run_task(&task);
   620     workers->run_task(&task);
   592 #if COMPILER2_OR_JVMCI
   621 #if COMPILER2_OR_JVMCI
   593     DerivedPointerTable::update_pointers();
   622     DerivedPointerTable::update_pointers();
   594 #endif
   623 #endif
   595   }
   624   }
   608     _heap(ShenandoahHeap::heap()), _worker_id(worker_id) {}
   637     _heap(ShenandoahHeap::heap()), _worker_id(worker_id) {}
   609 
   638 
   610   void do_object(oop p) {
   639   void do_object(oop p) {
   611     assert(_heap->complete_marking_context()->is_marked(p), "must be marked");
   640     assert(_heap->complete_marking_context()->is_marked(p), "must be marked");
   612     size_t size = (size_t)p->size();
   641     size_t size = (size_t)p->size();
   613     HeapWord* compact_to = ShenandoahForwarding::get_forwardee_raw(p);
   642     if (p->is_forwarded()) {
   614     HeapWord* compact_from = (HeapWord*) p;
   643       HeapWord* compact_from = (HeapWord*) p;
   615     if (compact_from != compact_to) {
   644       HeapWord* compact_to = (HeapWord*) p->forwardee();
   616       Copy::aligned_conjoint_words(compact_from, compact_to, size);
   645       Copy::aligned_conjoint_words(compact_from, compact_to, size);
   617     }
   646       oop new_obj = oop(compact_to);
   618     oop new_obj = oop(compact_to);
   647       new_obj->init_mark_raw();
   619     ShenandoahForwarding::initialize(new_obj);
   648     }
   620   }
   649   }
   621 };
   650 };
   622 
   651 
   623 class ShenandoahCompactObjectsTask : public AbstractGangTask {
   652 class ShenandoahCompactObjectsTask : public AbstractGangTask {
   624 private:
   653 private:
   705   // humongous regions are already compacted, and do not require further moves, which alleviates
   734   // humongous regions are already compacted, and do not require further moves, which alleviates
   706   // sliding costs. We may consider doing this in parallel in future.
   735   // sliding costs. We may consider doing this in parallel in future.
   707 
   736 
   708   ShenandoahHeap* heap = ShenandoahHeap::heap();
   737   ShenandoahHeap* heap = ShenandoahHeap::heap();
   709 
   738 
   710   for (size_t c = heap->num_regions() - 1; c > 0; c--) {
   739   for (size_t c = heap->num_regions(); c > 0; c--) {
   711     ShenandoahHeapRegion* r = heap->get_region(c);
   740     ShenandoahHeapRegion* r = heap->get_region(c - 1);
   712     if (r->is_humongous_start()) {
   741     if (r->is_humongous_start()) {
   713       oop old_obj = oop(r->bottom() + ShenandoahForwarding::word_size());
   742       oop old_obj = oop(r->bottom());
   714       size_t words_size = old_obj->size() + ShenandoahForwarding::word_size();
   743       if (!old_obj->is_forwarded()) {
       
   744         // No need to move the object, it stays at the same slot
       
   745         continue;
       
   746       }
       
   747       size_t words_size = old_obj->size();
   715       size_t num_regions = ShenandoahHeapRegion::required_regions(words_size * HeapWordSize);
   748       size_t num_regions = ShenandoahHeapRegion::required_regions(words_size * HeapWordSize);
   716 
   749 
   717       size_t old_start = r->region_number();
   750       size_t old_start = r->region_number();
   718       size_t old_end   = old_start + num_regions - 1;
   751       size_t old_end   = old_start + num_regions - 1;
   719       size_t new_start = heap->heap_region_index_containing(ShenandoahForwarding::get_forwardee_raw(old_obj));
   752       size_t new_start = heap->heap_region_index_containing(old_obj->forwardee());
   720       size_t new_end   = new_start + num_regions - 1;
   753       size_t new_end   = new_start + num_regions - 1;
   721 
   754       assert(old_start != new_start, "must be real move");
   722       if (old_start == new_start) {
       
   723         // No need to move the object, it stays at the same slot
       
   724         continue;
       
   725       }
       
   726 
       
   727       assert (r->is_move_allowed(), "should be movable");
   755       assert (r->is_move_allowed(), "should be movable");
   728 
   756 
   729       Copy::aligned_conjoint_words(heap->get_region(old_start)->bottom(),
   757       Copy::aligned_conjoint_words(heap->get_region(old_start)->bottom(),
   730                                    heap->get_region(new_start)->bottom(),
   758                                    heap->get_region(new_start)->bottom(),
   731                                    ShenandoahHeapRegion::region_size_words()*num_regions);
   759                                    ShenandoahHeapRegion::region_size_words()*num_regions);
   732 
   760 
   733       oop new_obj = oop(heap->get_region(new_start)->bottom() + ShenandoahForwarding::word_size());
   761       oop new_obj = oop(heap->get_region(new_start)->bottom());
   734       ShenandoahForwarding::initialize(new_obj);
   762       new_obj->init_mark_raw();
   735 
   763 
   736       {
   764       {
   737         for (size_t c = old_start; c <= old_end; c++) {
   765         for (size_t c = old_start; c <= old_end; c++) {
   738           ShenandoahHeapRegion* r = heap->get_region(c);
   766           ShenandoahHeapRegion* r = heap->get_region(c);
   739           r->make_regular_bypass();
   767           r->make_regular_bypass();