< prev index next > src/hotspot/share/gc/parallel/psParallelCompact.cpp
Print this page
#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"
+ 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 {
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;
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;
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;
}
}
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();
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());
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());
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) {
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) {
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);
}
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 >