< prev index next >

src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp

Print this page
@@ -249,19 +249,23 @@
    {
      // The rest of code performs region moves, where region status is undefined
      // until all phases run together.
      ShenandoahHeapLocker lock(heap->lock());
  
+     FullGCForwarding::begin();
+ 
      phase2_calculate_target_addresses(worker_slices);
  
      OrderAccess::fence();
  
      phase3_update_references();
  
      phase4_compact_objects(worker_slices);
  
      phase5_epilog();
+ 
+     FullGCForwarding::end();
    }
    heap->start_idle_span();
  
    // Resize metaspace
    MetaspaceGC::compute_new_size();

@@ -360,11 +364,13 @@
      assert(_from_region != nullptr, "must set before work");
      assert(_heap->global_generation()->is_mark_complete(), "marking must be finished");
      assert(_heap->marking_context()->is_marked(p), "must be marked");
      assert(!_heap->marking_context()->allocated_after_mark_start(p), "must be truly marked");
  
-     size_t obj_size = p->size();
+     size_t old_size = p->size();
+     size_t new_size = p->copy_size(old_size, p->mark());
+     size_t obj_size = _compact_point == cast_from_oop<HeapWord*>(p) ? old_size : new_size;
      if (_compact_point + obj_size > _to_region->end()) {
        finish();
  
        // Object doesn't fit. Pick next empty region and start compacting there.
        ShenandoahHeapRegion* new_to_region;

@@ -378,10 +384,11 @@
  
        assert(new_to_region != _to_region, "must not reuse same to-region");
        assert(new_to_region != nullptr, "must not be null");
        _to_region = new_to_region;
        _compact_point = _to_region->bottom();
+       obj_size = _compact_point == cast_from_oop<HeapWord*>(p) ? old_size : new_size;
      }
  
      // Object fits into current region, record new location, if object does not move:
      assert(_compact_point + obj_size <= _to_region->end(), "must fit");
      shenandoah_assert_not_forwarded(nullptr, p);

@@ -507,21 +514,27 @@
      }
  
      if (r->is_humongous_start() && r->is_stw_move_allowed()) {
        // From-region candidate: movable humongous region
        oop old_obj = cast_to_oop(r->bottom());
-       size_t words_size = old_obj->size();
-       size_t num_regions = ShenandoahHeapRegion::required_regions(words_size * HeapWordSize);
- 
-       size_t start = to_end - num_regions;
- 
-       if (start >= to_begin && start != r->index()) {
-         // Fits into current window, and the move is non-trivial. Record the move then, and continue scan.
-         _preserved_marks->get(0)->push_if_necessary(old_obj, old_obj->mark());
-         FullGCForwarding::forward_to(old_obj, cast_to_oop(heap->get_region(start)->bottom()));
-         to_end = start;
-         continue;
+       size_t new_words_size = old_obj->copy_size(old_obj->size(), old_obj->mark());
+       size_t num_regions = ShenandoahHeapRegion::required_regions(new_words_size * HeapWordSize);
+ 
+       // Test the fit before computing the slide target. With compact object headers
+       // the expanded size can require one region more than the object currently
+       // occupies, so num_regions may exceed the available window. Comparing against
+       // the window size (to_end - to_begin) avoids the unsigned underflow that
+       // "to_end - num_regions" would suffer when the object does not fit.
+       if (num_regions <= to_end - to_begin) {
+         size_t start = to_end - num_regions;
+         if (start != r->index()) {
+           // Fits into current window, and the move is non-trivial. Record the move then, and continue scan.
+           _preserved_marks->get(0)->push_if_necessary(old_obj, old_obj->mark());
+           FullGCForwarding::forward_to(old_obj, cast_to_oop(heap->get_region(start)->bottom()));
+           to_end = start;
+           continue;
+         }
        }
      }
  
      // Failed to fit. Scan starting from current region.
      to_begin = r->index();

@@ -890,11 +903,12 @@
        oop new_obj = cast_to_oop(compact_to);
  
        // Restore the mark word before relativizing the stack chunk. The copy's
        // mark word contains the full GC forwarding encoding, which would cause
        // is_stackChunk() to read garbage (especially with compact headers).
-       new_obj->init_mark();
+       new_obj->reinit_mark();
+       new_obj->initialize_hash_if_necessary(p);
        ContinuationGCSupport::relativize_stack_chunk(new_obj);
      }
    }
  };
  

@@ -1010,26 +1024,29 @@
        oop old_obj = cast_to_oop(r->bottom());
        if (!FullGCForwarding::is_forwarded(old_obj)) {
          // No need to move the object, it stays at the same slot
          continue;
        }
-       size_t words_size = old_obj->size();
-       size_t num_regions = ShenandoahHeapRegion::required_regions(words_size * HeapWordSize);
+       size_t old_words_size = old_obj->size();
+       size_t new_words_size = old_obj->copy_size(old_words_size, old_obj->mark());
+       size_t old_num_regions = ShenandoahHeapRegion::required_regions(old_words_size * HeapWordSize);
+       size_t new_num_regions = ShenandoahHeapRegion::required_regions(new_words_size * HeapWordSize);
  
        size_t old_start = r->index();
-       size_t old_end   = old_start + num_regions - 1;
+       size_t old_end   = old_start + old_num_regions - 1;
        size_t new_start = heap->heap_region_index_containing(FullGCForwarding::forwardee(old_obj));
-       size_t new_end   = new_start + num_regions - 1;
+       size_t new_end   = new_start + new_num_regions - 1;
        assert(old_start != new_start, "must be real move");
        assert(r->is_stw_move_allowed(), "Region %zu should be movable", r->index());
  
        log_debug(gc)("Full GC compaction moves humongous object from region %zu to region %zu", old_start, new_start);
-       Copy::aligned_conjoint_words(r->bottom(), heap->get_region(new_start)->bottom(), words_size);
+       Copy::aligned_conjoint_words(r->bottom(), heap->get_region(new_start)->bottom(), old_words_size);
        ContinuationGCSupport::relativize_stack_chunk(cast_to_oop<HeapWord*>(r->bottom()));
  
        oop new_obj = cast_to_oop(heap->get_region(new_start)->bottom());
-       new_obj->init_mark();
+       new_obj->reinit_mark();
+       new_obj->initialize_hash_if_necessary(old_obj);
  
        {
          ShenandoahAffiliation original_affiliation = r->affiliation();
          for (size_t c = old_start; c <= old_end; c++) {
            ShenandoahHeapRegion* r = heap->get_region(c);

@@ -1045,11 +1062,11 @@
            } else {
              r->make_humongous_cont_bypass(original_affiliation);
            }
  
            // Trailing region may be non-full, record the remainder there
-           size_t remainder = words_size & ShenandoahHeapRegion::region_size_words_mask();
+           size_t remainder = new_words_size & ShenandoahHeapRegion::region_size_words_mask();
            if ((c == new_end) && (remainder != 0)) {
              r->set_top(r->bottom() + remainder);
            } else {
              r->set_top(r->end());
            }
< prev index next >