< 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 ***
      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();
      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;
--- 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 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 ***
      }
  
      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;
        }
      }
  
      // Failed to fit. Scan starting from current region.
      to_begin = r->index();
--- 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 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 ***
        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();
        ContinuationGCSupport::relativize_stack_chunk(new_obj);
      }
    }
  };
  
--- 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->reinit_mark();
+       new_obj->initialize_hash_if_necessary(p);
        ContinuationGCSupport::relativize_stack_chunk(new_obj);
      }
    }
  };
  

*** 1010,26 ***
        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_start = r->index();
!       size_t old_end   = old_start + 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;
        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);
        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();
  
        {
          ShenandoahAffiliation original_affiliation = r->affiliation();
          for (size_t c = old_start; c <= old_end; c++) {
            ShenandoahHeapRegion* r = heap->get_region(c);
--- 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 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 + old_num_regions - 1;
        size_t new_start = heap->heap_region_index_containing(FullGCForwarding::forwardee(old_obj));
!       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(), 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->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 ***
            } 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();
            if ((c == new_end) && (remainder != 0)) {
              r->set_top(r->bottom() + remainder);
            } else {
              r->set_top(r->end());
            }
--- 1062,11 ---
            } else {
              r->make_humongous_cont_bypass(original_affiliation);
            }
  
            // Trailing region may be non-full, record the remainder there
!           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 >