11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26
27 #include "compiler/oopMap.hpp"
28 #include "gc/shared/continuationGCSupport.hpp"
29 #include "gc/shared/gcTraceTime.inline.hpp"
30 #include "gc/shared/preservedMarks.inline.hpp"
31 #include "gc/shared/tlab_globals.hpp"
32 #include "gc/shared/workerThread.hpp"
33 #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp"
34 #include "gc/shenandoah/shenandoahCollectorPolicy.hpp"
35 #include "gc/shenandoah/shenandoahConcurrentGC.hpp"
36 #include "gc/shenandoah/shenandoahCollectionSet.hpp"
37 #include "gc/shenandoah/shenandoahFreeSet.hpp"
38 #include "gc/shenandoah/shenandoahFullGC.hpp"
39 #include "gc/shenandoah/shenandoahPhaseTimings.hpp"
40 #include "gc/shenandoah/shenandoahMark.inline.hpp"
41 #include "gc/shenandoah/shenandoahMonitoringSupport.hpp"
42 #include "gc/shenandoah/shenandoahHeapRegionSet.hpp"
43 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
44 #include "gc/shenandoah/shenandoahHeapRegion.inline.hpp"
45 #include "gc/shenandoah/shenandoahMarkingContext.inline.hpp"
46 #include "gc/shenandoah/shenandoahMetrics.hpp"
47 #include "gc/shenandoah/shenandoahOopClosures.inline.hpp"
48 #include "gc/shenandoah/shenandoahReferenceProcessor.hpp"
49 #include "gc/shenandoah/shenandoahRootProcessor.inline.hpp"
50 #include "gc/shenandoah/shenandoahSTWMark.hpp"
211 // Coming out of Full GC, we would not have any forwarded objects.
212 // This also prevents resolves with fwdptr from kicking in while adjusting pointers in phase3.
213 heap->set_has_forwarded_objects(false);
214
215 heap->set_full_gc_move_in_progress(true);
216
217 // Setup workers for the rest
218 OrderAccess::fence();
219
220 // Initialize worker slices
221 ShenandoahHeapRegionSet** worker_slices = NEW_C_HEAP_ARRAY(ShenandoahHeapRegionSet*, heap->max_workers(), mtGC);
222 for (uint i = 0; i < heap->max_workers(); i++) {
223 worker_slices[i] = new ShenandoahHeapRegionSet();
224 }
225
226 {
227 // The rest of code performs region moves, where region status is undefined
228 // until all phases run together.
229 ShenandoahHeapLocker lock(heap->lock());
230
231 phase2_calculate_target_addresses(worker_slices);
232
233 OrderAccess::fence();
234
235 phase3_update_references();
236
237 phase4_compact_objects(worker_slices);
238
239 phase5_epilog();
240 }
241
242 // Resize metaspace
243 MetaspaceGC::compute_new_size();
244
245 // Free worker slices
246 for (uint i = 0; i < heap->max_workers(); i++) {
247 delete worker_slices[i];
248 }
249 FREE_C_HEAP_ARRAY(ShenandoahHeapRegionSet*, worker_slices);
250
251 heap->set_full_gc_move_in_progress(false);
252 heap->set_full_gc_in_progress(false);
253
254 if (ShenandoahVerify) {
255 heap->verifier()->verify_after_fullgc();
256 }
257
258 if (VerifyAfterGC) {
259 Universe::verify();
352 ShenandoahHeapRegion* new_to_region;
353 if (_empty_regions_pos < _empty_regions.length()) {
354 new_to_region = _empty_regions.at(_empty_regions_pos);
355 _empty_regions_pos++;
356 } else {
357 // Out of empty region? Compact within the same region.
358 new_to_region = _from_region;
359 }
360
361 assert(new_to_region != _to_region, "must not reuse same to-region");
362 assert(new_to_region != nullptr, "must not be null");
363 _to_region = new_to_region;
364 _compact_point = _to_region->bottom();
365 }
366
367 // Object fits into current region, record new location, if object does not move:
368 assert(_compact_point + obj_size <= _to_region->end(), "must fit");
369 shenandoah_assert_not_forwarded(nullptr, p);
370 if (_compact_point != cast_from_oop<HeapWord*>(p)) {
371 _preserved_marks->push_if_necessary(p, p->mark());
372 p->forward_to(cast_to_oop(_compact_point));
373 }
374 _compact_point += obj_size;
375 }
376 };
377
378 class ShenandoahPrepareForCompactionTask : public WorkerTask {
379 private:
380 PreservedMarksSet* const _preserved_marks;
381 ShenandoahHeap* const _heap;
382 ShenandoahHeapRegionSet** const _worker_slices;
383
384 public:
385 ShenandoahPrepareForCompactionTask(PreservedMarksSet *preserved_marks, ShenandoahHeapRegionSet **worker_slices) :
386 WorkerTask("Shenandoah Prepare For Compaction"),
387 _preserved_marks(preserved_marks),
388 _heap(ShenandoahHeap::heap()), _worker_slices(worker_slices) {
389 }
390
391 static bool is_candidate_region(ShenandoahHeapRegion* r) {
392 // Empty region: get it into the slice to defragment the slice itself.
475
476 for (size_t c = heap->num_regions(); c > 0; c--) {
477 ShenandoahHeapRegion *r = heap->get_region(c - 1);
478 if (r->is_humongous_continuation() || (r->new_top() == r->bottom())) {
479 // To-region candidate: record this, and continue scan
480 to_begin = r->index();
481 continue;
482 }
483
484 if (r->is_humongous_start() && r->is_stw_move_allowed()) {
485 // From-region candidate: movable humongous region
486 oop old_obj = cast_to_oop(r->bottom());
487 size_t words_size = old_obj->size();
488 size_t num_regions = ShenandoahHeapRegion::required_regions(words_size * HeapWordSize);
489
490 size_t start = to_end - num_regions;
491
492 if (start >= to_begin && start != r->index()) {
493 // Fits into current window, and the move is non-trivial. Record the move then, and continue scan.
494 _preserved_marks->get(0)->push_if_necessary(old_obj, old_obj->mark());
495 old_obj->forward_to(cast_to_oop(heap->get_region(start)->bottom()));
496 to_end = start;
497 continue;
498 }
499 }
500
501 // Failed to fit. Scan starting from current region.
502 to_begin = r->index();
503 to_end = r->index();
504 }
505 }
506
507 class ShenandoahEnsureHeapActiveClosure: public ShenandoahHeapRegionClosure {
508 private:
509 ShenandoahHeap* const _heap;
510
511 public:
512 ShenandoahEnsureHeapActiveClosure() : _heap(ShenandoahHeap::heap()) {}
513 void heap_region_do(ShenandoahHeapRegion* r) {
514 if (r->is_trash()) {
515 r->recycle();
735 }
736
737 // Compute the new addresses for humongous objects
738 {
739 ShenandoahGCPhase phase(ShenandoahPhaseTimings::full_gc_calculate_addresses_humong);
740 calculate_target_humongous_objects();
741 }
742 }
743
744 class ShenandoahAdjustPointersClosure : public MetadataVisitingOopIterateClosure {
745 private:
746 ShenandoahHeap* const _heap;
747 ShenandoahMarkingContext* const _ctx;
748
749 template <class T>
750 inline void do_oop_work(T* p) {
751 T o = RawAccess<>::oop_load(p);
752 if (!CompressedOops::is_null(o)) {
753 oop obj = CompressedOops::decode_not_null(o);
754 assert(_ctx->is_marked(obj), "must be marked");
755 if (obj->is_forwarded()) {
756 oop forw = obj->forwardee();
757 RawAccess<IS_NOT_NULL>::oop_store(p, forw);
758 }
759 }
760 }
761
762 public:
763 ShenandoahAdjustPointersClosure() :
764 _heap(ShenandoahHeap::heap()),
765 _ctx(ShenandoahHeap::heap()->complete_marking_context()) {}
766
767 void do_oop(oop* p) { do_oop_work(p); }
768 void do_oop(narrowOop* p) { do_oop_work(p); }
769 void do_method(Method* m) {}
770 void do_nmethod(nmethod* nm) {}
771 };
772
773 class ShenandoahAdjustPointersObjectClosure : public ObjectClosure {
774 private:
775 ShenandoahHeap* const _heap;
776 ShenandoahAdjustPointersClosure _cl;
846 DerivedPointerTable::update_pointers();
847 #endif
848 }
849
850 ShenandoahAdjustPointersTask adjust_pointers_task;
851 workers->run_task(&adjust_pointers_task);
852 }
853
854 class ShenandoahCompactObjectsClosure : public ObjectClosure {
855 private:
856 ShenandoahHeap* const _heap;
857 uint const _worker_id;
858
859 public:
860 ShenandoahCompactObjectsClosure(uint worker_id) :
861 _heap(ShenandoahHeap::heap()), _worker_id(worker_id) {}
862
863 void do_object(oop p) {
864 assert(_heap->complete_marking_context()->is_marked(p), "must be marked");
865 size_t size = p->size();
866 if (p->is_forwarded()) {
867 HeapWord* compact_from = cast_from_oop<HeapWord*>(p);
868 HeapWord* compact_to = cast_from_oop<HeapWord*>(p->forwardee());
869 assert(compact_from != compact_to, "Forwarded object should move");
870 Copy::aligned_conjoint_words(compact_from, compact_to, size);
871 oop new_obj = cast_to_oop(compact_to);
872
873 ContinuationGCSupport::relativize_stack_chunk(new_obj);
874 new_obj->init_mark();
875 }
876 }
877 };
878
879 class ShenandoahCompactObjectsTask : public WorkerTask {
880 private:
881 ShenandoahHeap* const _heap;
882 ShenandoahHeapRegionSet** const _worker_slices;
883
884 public:
885 ShenandoahCompactObjectsTask(ShenandoahHeapRegionSet** worker_slices) :
886 WorkerTask("Shenandoah Compact Objects"),
887 _heap(ShenandoahHeap::heap()),
888 _worker_slices(worker_slices) {
953 }
954
955 size_t get_live() {
956 return _live;
957 }
958 };
959
960 void ShenandoahFullGC::compact_humongous_objects() {
961 // Compact humongous regions, based on their fwdptr objects.
962 //
963 // This code is serial, because doing the in-slice parallel sliding is tricky. In most cases,
964 // humongous regions are already compacted, and do not require further moves, which alleviates
965 // sliding costs. We may consider doing this in parallel in the future.
966
967 ShenandoahHeap* heap = ShenandoahHeap::heap();
968
969 for (size_t c = heap->num_regions(); c > 0; c--) {
970 ShenandoahHeapRegion* r = heap->get_region(c - 1);
971 if (r->is_humongous_start()) {
972 oop old_obj = cast_to_oop(r->bottom());
973 if (!old_obj->is_forwarded()) {
974 // No need to move the object, it stays at the same slot
975 continue;
976 }
977 size_t words_size = old_obj->size();
978 size_t num_regions = ShenandoahHeapRegion::required_regions(words_size * HeapWordSize);
979
980 size_t old_start = r->index();
981 size_t old_end = old_start + num_regions - 1;
982 size_t new_start = heap->heap_region_index_containing(old_obj->forwardee());
983 size_t new_end = new_start + num_regions - 1;
984 assert(old_start != new_start, "must be real move");
985 assert(r->is_stw_move_allowed(), "Region " SIZE_FORMAT " should be movable", r->index());
986
987 Copy::aligned_conjoint_words(r->bottom(), heap->get_region(new_start)->bottom(), words_size);
988 ContinuationGCSupport::relativize_stack_chunk(cast_to_oop<HeapWord*>(r->bottom()));
989
990 oop new_obj = cast_to_oop(heap->get_region(new_start)->bottom());
991 new_obj->init_mark();
992
993 {
994 for (size_t c = old_start; c <= old_end; c++) {
995 ShenandoahHeapRegion* r = heap->get_region(c);
996 r->make_regular_bypass();
997 r->set_top(r->bottom());
998 }
999
1000 for (size_t c = new_start; c <= new_end; c++) {
1001 ShenandoahHeapRegion* r = heap->get_region(c);
1002 if (c == new_start) {
|
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26
27 #include "compiler/oopMap.hpp"
28 #include "gc/shared/continuationGCSupport.hpp"
29 #include "gc/shared/gcTraceTime.inline.hpp"
30 #include "gc/shared/preservedMarks.inline.hpp"
31 #include "gc/shared/slidingForwarding.inline.hpp"
32 #include "gc/shared/tlab_globals.hpp"
33 #include "gc/shared/workerThread.hpp"
34 #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp"
35 #include "gc/shenandoah/shenandoahCollectorPolicy.hpp"
36 #include "gc/shenandoah/shenandoahConcurrentGC.hpp"
37 #include "gc/shenandoah/shenandoahCollectionSet.hpp"
38 #include "gc/shenandoah/shenandoahFreeSet.hpp"
39 #include "gc/shenandoah/shenandoahFullGC.hpp"
40 #include "gc/shenandoah/shenandoahPhaseTimings.hpp"
41 #include "gc/shenandoah/shenandoahMark.inline.hpp"
42 #include "gc/shenandoah/shenandoahMonitoringSupport.hpp"
43 #include "gc/shenandoah/shenandoahHeapRegionSet.hpp"
44 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
45 #include "gc/shenandoah/shenandoahHeapRegion.inline.hpp"
46 #include "gc/shenandoah/shenandoahMarkingContext.inline.hpp"
47 #include "gc/shenandoah/shenandoahMetrics.hpp"
48 #include "gc/shenandoah/shenandoahOopClosures.inline.hpp"
49 #include "gc/shenandoah/shenandoahReferenceProcessor.hpp"
50 #include "gc/shenandoah/shenandoahRootProcessor.inline.hpp"
51 #include "gc/shenandoah/shenandoahSTWMark.hpp"
212 // Coming out of Full GC, we would not have any forwarded objects.
213 // This also prevents resolves with fwdptr from kicking in while adjusting pointers in phase3.
214 heap->set_has_forwarded_objects(false);
215
216 heap->set_full_gc_move_in_progress(true);
217
218 // Setup workers for the rest
219 OrderAccess::fence();
220
221 // Initialize worker slices
222 ShenandoahHeapRegionSet** worker_slices = NEW_C_HEAP_ARRAY(ShenandoahHeapRegionSet*, heap->max_workers(), mtGC);
223 for (uint i = 0; i < heap->max_workers(); i++) {
224 worker_slices[i] = new ShenandoahHeapRegionSet();
225 }
226
227 {
228 // The rest of code performs region moves, where region status is undefined
229 // until all phases run together.
230 ShenandoahHeapLocker lock(heap->lock());
231
232 SlidingForwarding::begin();
233
234 phase2_calculate_target_addresses(worker_slices);
235
236 OrderAccess::fence();
237
238 phase3_update_references();
239
240 phase4_compact_objects(worker_slices);
241
242 phase5_epilog();
243
244 SlidingForwarding::end();
245 }
246
247 // Resize metaspace
248 MetaspaceGC::compute_new_size();
249
250 // Free worker slices
251 for (uint i = 0; i < heap->max_workers(); i++) {
252 delete worker_slices[i];
253 }
254 FREE_C_HEAP_ARRAY(ShenandoahHeapRegionSet*, worker_slices);
255
256 heap->set_full_gc_move_in_progress(false);
257 heap->set_full_gc_in_progress(false);
258
259 if (ShenandoahVerify) {
260 heap->verifier()->verify_after_fullgc();
261 }
262
263 if (VerifyAfterGC) {
264 Universe::verify();
357 ShenandoahHeapRegion* new_to_region;
358 if (_empty_regions_pos < _empty_regions.length()) {
359 new_to_region = _empty_regions.at(_empty_regions_pos);
360 _empty_regions_pos++;
361 } else {
362 // Out of empty region? Compact within the same region.
363 new_to_region = _from_region;
364 }
365
366 assert(new_to_region != _to_region, "must not reuse same to-region");
367 assert(new_to_region != nullptr, "must not be null");
368 _to_region = new_to_region;
369 _compact_point = _to_region->bottom();
370 }
371
372 // Object fits into current region, record new location, if object does not move:
373 assert(_compact_point + obj_size <= _to_region->end(), "must fit");
374 shenandoah_assert_not_forwarded(nullptr, p);
375 if (_compact_point != cast_from_oop<HeapWord*>(p)) {
376 _preserved_marks->push_if_necessary(p, p->mark());
377 SlidingForwarding::forward_to(p, cast_to_oop(_compact_point));
378 }
379 _compact_point += obj_size;
380 }
381 };
382
383 class ShenandoahPrepareForCompactionTask : public WorkerTask {
384 private:
385 PreservedMarksSet* const _preserved_marks;
386 ShenandoahHeap* const _heap;
387 ShenandoahHeapRegionSet** const _worker_slices;
388
389 public:
390 ShenandoahPrepareForCompactionTask(PreservedMarksSet *preserved_marks, ShenandoahHeapRegionSet **worker_slices) :
391 WorkerTask("Shenandoah Prepare For Compaction"),
392 _preserved_marks(preserved_marks),
393 _heap(ShenandoahHeap::heap()), _worker_slices(worker_slices) {
394 }
395
396 static bool is_candidate_region(ShenandoahHeapRegion* r) {
397 // Empty region: get it into the slice to defragment the slice itself.
480
481 for (size_t c = heap->num_regions(); c > 0; c--) {
482 ShenandoahHeapRegion *r = heap->get_region(c - 1);
483 if (r->is_humongous_continuation() || (r->new_top() == r->bottom())) {
484 // To-region candidate: record this, and continue scan
485 to_begin = r->index();
486 continue;
487 }
488
489 if (r->is_humongous_start() && r->is_stw_move_allowed()) {
490 // From-region candidate: movable humongous region
491 oop old_obj = cast_to_oop(r->bottom());
492 size_t words_size = old_obj->size();
493 size_t num_regions = ShenandoahHeapRegion::required_regions(words_size * HeapWordSize);
494
495 size_t start = to_end - num_regions;
496
497 if (start >= to_begin && start != r->index()) {
498 // Fits into current window, and the move is non-trivial. Record the move then, and continue scan.
499 _preserved_marks->get(0)->push_if_necessary(old_obj, old_obj->mark());
500 SlidingForwarding::forward_to(old_obj, cast_to_oop(heap->get_region(start)->bottom()));
501 to_end = start;
502 continue;
503 }
504 }
505
506 // Failed to fit. Scan starting from current region.
507 to_begin = r->index();
508 to_end = r->index();
509 }
510 }
511
512 class ShenandoahEnsureHeapActiveClosure: public ShenandoahHeapRegionClosure {
513 private:
514 ShenandoahHeap* const _heap;
515
516 public:
517 ShenandoahEnsureHeapActiveClosure() : _heap(ShenandoahHeap::heap()) {}
518 void heap_region_do(ShenandoahHeapRegion* r) {
519 if (r->is_trash()) {
520 r->recycle();
740 }
741
742 // Compute the new addresses for humongous objects
743 {
744 ShenandoahGCPhase phase(ShenandoahPhaseTimings::full_gc_calculate_addresses_humong);
745 calculate_target_humongous_objects();
746 }
747 }
748
749 class ShenandoahAdjustPointersClosure : public MetadataVisitingOopIterateClosure {
750 private:
751 ShenandoahHeap* const _heap;
752 ShenandoahMarkingContext* const _ctx;
753
754 template <class T>
755 inline void do_oop_work(T* p) {
756 T o = RawAccess<>::oop_load(p);
757 if (!CompressedOops::is_null(o)) {
758 oop obj = CompressedOops::decode_not_null(o);
759 assert(_ctx->is_marked(obj), "must be marked");
760 if (SlidingForwarding::is_forwarded(obj)) {
761 oop forw = SlidingForwarding::forwardee(obj);
762 RawAccess<IS_NOT_NULL>::oop_store(p, forw);
763 }
764 }
765 }
766
767 public:
768 ShenandoahAdjustPointersClosure() :
769 _heap(ShenandoahHeap::heap()),
770 _ctx(ShenandoahHeap::heap()->complete_marking_context()) {}
771
772 void do_oop(oop* p) { do_oop_work(p); }
773 void do_oop(narrowOop* p) { do_oop_work(p); }
774 void do_method(Method* m) {}
775 void do_nmethod(nmethod* nm) {}
776 };
777
778 class ShenandoahAdjustPointersObjectClosure : public ObjectClosure {
779 private:
780 ShenandoahHeap* const _heap;
781 ShenandoahAdjustPointersClosure _cl;
851 DerivedPointerTable::update_pointers();
852 #endif
853 }
854
855 ShenandoahAdjustPointersTask adjust_pointers_task;
856 workers->run_task(&adjust_pointers_task);
857 }
858
859 class ShenandoahCompactObjectsClosure : public ObjectClosure {
860 private:
861 ShenandoahHeap* const _heap;
862 uint const _worker_id;
863
864 public:
865 ShenandoahCompactObjectsClosure(uint worker_id) :
866 _heap(ShenandoahHeap::heap()), _worker_id(worker_id) {}
867
868 void do_object(oop p) {
869 assert(_heap->complete_marking_context()->is_marked(p), "must be marked");
870 size_t size = p->size();
871 if (SlidingForwarding::is_forwarded(p)) {
872 HeapWord* compact_from = cast_from_oop<HeapWord*>(p);
873 HeapWord* compact_to = cast_from_oop<HeapWord*>(SlidingForwarding::forwardee(p));
874 assert(compact_from != compact_to, "Forwarded object should move");
875 Copy::aligned_conjoint_words(compact_from, compact_to, size);
876 oop new_obj = cast_to_oop(compact_to);
877
878 ContinuationGCSupport::relativize_stack_chunk(new_obj);
879 new_obj->init_mark();
880 }
881 }
882 };
883
884 class ShenandoahCompactObjectsTask : public WorkerTask {
885 private:
886 ShenandoahHeap* const _heap;
887 ShenandoahHeapRegionSet** const _worker_slices;
888
889 public:
890 ShenandoahCompactObjectsTask(ShenandoahHeapRegionSet** worker_slices) :
891 WorkerTask("Shenandoah Compact Objects"),
892 _heap(ShenandoahHeap::heap()),
893 _worker_slices(worker_slices) {
958 }
959
960 size_t get_live() {
961 return _live;
962 }
963 };
964
965 void ShenandoahFullGC::compact_humongous_objects() {
966 // Compact humongous regions, based on their fwdptr objects.
967 //
968 // This code is serial, because doing the in-slice parallel sliding is tricky. In most cases,
969 // humongous regions are already compacted, and do not require further moves, which alleviates
970 // sliding costs. We may consider doing this in parallel in the future.
971
972 ShenandoahHeap* heap = ShenandoahHeap::heap();
973
974 for (size_t c = heap->num_regions(); c > 0; c--) {
975 ShenandoahHeapRegion* r = heap->get_region(c - 1);
976 if (r->is_humongous_start()) {
977 oop old_obj = cast_to_oop(r->bottom());
978 if (SlidingForwarding::is_not_forwarded(old_obj)) {
979 // No need to move the object, it stays at the same slot
980 continue;
981 }
982 size_t words_size = old_obj->size();
983 size_t num_regions = ShenandoahHeapRegion::required_regions(words_size * HeapWordSize);
984
985 size_t old_start = r->index();
986 size_t old_end = old_start + num_regions - 1;
987 size_t new_start = heap->heap_region_index_containing(SlidingForwarding::forwardee(old_obj));
988 size_t new_end = new_start + num_regions - 1;
989 assert(old_start != new_start, "must be real move");
990 assert(r->is_stw_move_allowed(), "Region " SIZE_FORMAT " should be movable", r->index());
991
992 Copy::aligned_conjoint_words(r->bottom(), heap->get_region(new_start)->bottom(), words_size);
993 ContinuationGCSupport::relativize_stack_chunk(cast_to_oop<HeapWord*>(r->bottom()));
994
995 oop new_obj = cast_to_oop(heap->get_region(new_start)->bottom());
996 new_obj->init_mark();
997
998 {
999 for (size_t c = old_start; c <= old_end; c++) {
1000 ShenandoahHeapRegion* r = heap->get_region(c);
1001 r->make_regular_bypass();
1002 r->set_top(r->bottom());
1003 }
1004
1005 for (size_t c = new_start; c <= new_end; c++) {
1006 ShenandoahHeapRegion* r = heap->get_region(c);
1007 if (c == new_start) {
|