< 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 +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) {
-           cm->preserved_marks()->push_if_necessary(obj, obj->mark());
+           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 +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();
        }
-       closure.do_addr(cur_addr, obj_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 +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) {
+ 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 +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())->init_mark();
+     cast_to_oop(copy_destination())->set_mark(mark);
    }
  
    update_state(words);
  }
  
< prev index next >