< prev index next >

src/hotspot/share/gc/parallel/psParallelCompact.cpp

Print this page
*** 74,16 ***
--- 74,18 ---
  #include "memory/metaspaceUtils.hpp"
  #include "memory/resourceArea.hpp"
  #include "memory/universe.hpp"
  #include "nmt/memTracker.hpp"
  #include "oops/access.inline.hpp"
+ #include "oops/flatArrayKlass.inline.hpp"
  #include "oops/instanceClassLoaderKlass.inline.hpp"
  #include "oops/instanceKlass.inline.hpp"
  #include "oops/instanceMirrorKlass.inline.hpp"
  #include "oops/methodData.hpp"
  #include "oops/objArrayKlass.inline.hpp"
  #include "oops/oop.inline.hpp"
+ #include "runtime/arguments.hpp"
  #include "runtime/atomicAccess.hpp"
  #include "runtime/handles.inline.hpp"
  #include "runtime/java.hpp"
  #include "runtime/safepoint.hpp"
  #include "runtime/threads.hpp"

*** 1446,10 ***
--- 1448,24 ---
                    + MIN2(checked_cast<size_t>(worker_id), remainder);
    *worker_end = *worker_start + num_regions_per_worker
                  + (worker_id < remainder ? 1 : 0);
  }
  
+ static bool safe_to_read_header(size_t words) {
+   precond(words > 0);
+ 
+   // Safe to read if we have enough words for the full header, i.e., both
+   // markWord and Klass pointer.
+   const bool safe = words >= (size_t)oopDesc::header_size();
+ 
+   // If using Compact Object Headers, the full header is inside the markWord,
+   // so will always be safe to read
+   assert(!UseCompactObjectHeaders || safe, "Compact Object Headers should always be safe");
+ 
+   return safe;
+ }
+ 
  void PSParallelCompact::forward_to_new_addr() {
    GCTraceTime(Info, gc, phases) tm("Forward", &_gc_timer);
    uint nworkers = ParallelScavengeHeap::heap()->workers().active_workers();
  
    struct ForwardTask final : public WorkerTask {

*** 1457,10 ***
--- 1473,27 ---
  
      explicit ForwardTask(uint num_workers) :
        WorkerTask("PSForward task"),
        _num_workers(num_workers) {}
  
+     static bool should_preserve_mark(oop obj, HeapWord* end_addr) {
+       size_t remaining_words = pointer_delta(end_addr, cast_from_oop<HeapWord*>(obj));
+ 
+       if (Arguments::is_valhalla_enabled() && !safe_to_read_header(remaining_words)) {
+         // When using Valhalla, it might be necessary to preserve the Valhalla-
+         // specific bits in the markWord. If the entire object header is
+         // copied, the correct markWord (with the appropriate Valhalla bits)
+         // can be safely read from the Klass. However, if the full header is
+         // not copied, we cannot safely read the Klass to obtain this information.
+         // In such cases, we always preserve the markWord to ensure that all
+         // relevant bits, including Valhalla-specific ones, are retained.
+         return true;
+       } else {
+         return obj->mark().must_be_preserved();
+       }
+     }
+ 
      static void forward_objs_in_range(ParCompactionManager* cm,
                                        HeapWord* start,
                                        HeapWord* end,
                                        HeapWord* destination) {
        HeapWord* cur_addr = start;

*** 1471,12 ***
          if (cur_addr >= end) {
            return;
          }
          assert(mark_bitmap()->is_marked(cur_addr), "inv");
          oop obj = cast_to_oop(cur_addr);
          if (new_addr != cur_addr) {
!           cm->preserved_marks()->push_if_necessary(obj, obj->mark());
            FullGCForwarding::forward_to(obj, cast_to_oop(new_addr));
          }
          size_t obj_size = obj->size();
          new_addr += obj_size;
          cur_addr += obj_size;
--- 1504,16 ---
          if (cur_addr >= end) {
            return;
          }
          assert(mark_bitmap()->is_marked(cur_addr), "inv");
          oop obj = cast_to_oop(cur_addr);
+ 
          if (new_addr != cur_addr) {
!           if (should_preserve_mark(obj, end)) {
+             cm->preserved_marks()->push_always(obj, obj->mark());
+           }
+ 
            FullGCForwarding::forward_to(obj, cast_to_oop(new_addr));
          }
          size_t obj_size = obj->size();
          new_addr += obj_size;
          cur_addr += obj_size;

*** 2114,10 ***
--- 2151,24 ---
      }
    }
    return region_start_addr + accumulated_size;
  }
  
+ static markWord safe_mark_word_prototype(HeapWord* cur_addr, HeapWord* end_addr) {
+   // If the original markWord contains bits that cannot be reconstructed because
+   // the header cannot be safely read, a placeholder is used. In this case,
+   // the correct markWord is preserved before compaction and restored after
+   // compaction completes.
+   size_t remaining_words = pointer_delta(end_addr, cur_addr);
+ 
+   if (UseCompactObjectHeaders || (Arguments::is_valhalla_enabled() && safe_to_read_header(remaining_words))) {
+     return cast_to_oop(cur_addr)->klass()->prototype_header();
+   } else {
+     return markWord::prototype();
+   }
+ }
+ 
  // Use region_idx as the destination region, and evacuate all live objs on its
  // source regions to this destination region.
  void PSParallelCompact::fill_region(ParCompactionManager* cm, MoveAndUpdateClosure& closure, size_t region_idx)
  {
    ParMarkBitMap* const bitmap = mark_bitmap();

*** 2229,11 ***
          obj_size = pointer_delta(partial_obj_end(end_addr), cur_addr);
        } else {
          // This obj doesn't extend into next region; size() is safe to use.
          obj_size = cast_to_oop(cur_addr)->size();
        }
!       closure.do_addr(cur_addr, obj_size);
        cur_addr += obj_size;
      } while (cur_addr < end_addr && !closure.is_full());
  
      if (closure.is_full()) {
        decrement_destination_counts(cm, src_space_id, src_region_idx, closure.source());
--- 2280,16 ---
          obj_size = pointer_delta(partial_obj_end(end_addr), cur_addr);
        } else {
          // This obj doesn't extend into next region; size() is safe to use.
          obj_size = cast_to_oop(cur_addr)->size();
        }
! 
+       markWord mark = safe_mark_word_prototype(cur_addr, end_addr);
+ 
+       // Perform the move and update of the object
+       closure.do_addr(cur_addr, obj_size, mark);
+ 
        cur_addr += obj_size;
      } while (cur_addr < end_addr && !closure.is_full());
  
      if (closure.is_full()) {
        decrement_destination_counts(cm, src_space_id, src_region_idx, closure.source());

*** 2349,11 ***
  void MoveAndUpdateClosure::complete_region(HeapWord* dest_addr, PSParallelCompact::RegionData* region_ptr) {
    assert(region_ptr->shadow_state() == ParallelCompactData::RegionData::NormalRegion, "Region should be finished");
    region_ptr->set_completed();
  }
  
! void MoveAndUpdateClosure::do_addr(HeapWord* addr, size_t words) {
    assert(destination() != nullptr, "sanity");
    _source = addr;
  
    // The start_array must be updated even if the object is not moving.
    if (_start_array != nullptr) {
--- 2405,11 ---
  void MoveAndUpdateClosure::complete_region(HeapWord* dest_addr, PSParallelCompact::RegionData* region_ptr) {
    assert(region_ptr->shadow_state() == ParallelCompactData::RegionData::NormalRegion, "Region should be finished");
    region_ptr->set_completed();
  }
  
! void MoveAndUpdateClosure::do_addr(HeapWord* addr, size_t words, markWord mark) {
    assert(destination() != nullptr, "sanity");
    _source = addr;
  
    // The start_array must be updated even if the object is not moving.
    if (_start_array != nullptr) {

*** 2368,11 ***
      DEBUG_ONLY(PSParallelCompact::check_new_location(source(), destination());)
      assert(source() != destination(), "inv");
      assert(FullGCForwarding::is_forwarded(cast_to_oop(source())), "inv");
      assert(FullGCForwarding::forwardee(cast_to_oop(source())) == cast_to_oop(destination()), "inv");
      Copy::aligned_conjoint_words(source(), copy_destination(), words);
!     cast_to_oop(copy_destination())->init_mark();
    }
  
    update_state(words);
  }
  
--- 2424,11 ---
      DEBUG_ONLY(PSParallelCompact::check_new_location(source(), destination());)
      assert(source() != destination(), "inv");
      assert(FullGCForwarding::is_forwarded(cast_to_oop(source())), "inv");
      assert(FullGCForwarding::forwardee(cast_to_oop(source())) == cast_to_oop(destination()), "inv");
      Copy::aligned_conjoint_words(source(), copy_destination(), words);
!     cast_to_oop(copy_destination())->set_mark(mark);
    }
  
    update_state(words);
  }
  
< prev index next >