Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/hotspot/share/gc/g1/g1CollectedHeap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2563,6 +2563,10 @@ void G1CollectedHeap::start_concurrent_cycle(bool concurrent_operation_is_full_m
G1CGC_lock->notify();
}

bool G1CollectedHeap::can_be_marked_through_immediately(oop obj) const {
return obj->is_array() && !obj->is_array_with_oops();
}

bool G1CollectedHeap::is_potential_eager_reclaim_candidate(G1HeapRegion* r) const {
// We don't nominate objects with many remembered set entries, on
// the assumption that such objects are likely still live.
Expand Down
5 changes: 5 additions & 0 deletions src/hotspot/share/gc/g1/g1CollectedHeap.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,11 @@ class G1CollectedHeap : public CollectedHeap {
void gc_prologue(bool full);
void gc_epilogue(bool full);

// Can concurrent mark process this object immediately, i.e. mark as live without the need
// of pushing it on the mark stack (to process references)?
// Used to keep objects that are potentially eagerly reclaimed out of the mark stack.
// Its klass may still need to be handled.
bool can_be_marked_through_immediately(oop obj) const;
// Does the given region fulfill remembered set based eager reclaim candidate requirements?
bool is_potential_eager_reclaim_candidate(G1HeapRegion* r) const;

Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include "gc/shared/collectedHeap.inline.hpp"
#include "gc/shared/markBitMap.inline.hpp"
#include "gc/shared/taskqueue.inline.hpp"
#include "oops/oop.inline.hpp"
#include "oops/stackChunkOop.hpp"
#include "runtime/threadSMR.inline.hpp"
#include "utilities/bitMap.inline.hpp"
Expand Down
14 changes: 9 additions & 5 deletions src/hotspot/share/gc/g1/g1ConcurrentMark.inline.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,8 @@ inline bool G1CMTask::is_below_finger(oop obj, HeapWord* global_finger) const {

template<bool scan>
inline void G1CMTask::process_grey_task_entry(G1TaskQueueEntry task_entry, bool stolen) {
assert(scan || (!task_entry.is_partial_array_state() && task_entry.to_oop()->is_typeArray()), "Skipping scan of grey non-typeArray");
assert(scan || (!task_entry.is_partial_array_state() && _g1h->can_be_marked_through_immediately(task_entry.to_oop())),
"Skipping scan of grey object that needs scanning");
assert(task_entry.is_partial_array_state() || _mark_bitmap->is_marked(cast_from_oop<HeapWord*>(task_entry.to_oop())),
"Any stolen object should be a slice or marked");

Expand All @@ -177,6 +178,9 @@ inline void G1CMTask::process_grey_task_entry(G1TaskQueueEntry task_entry, bool
_words_scanned += obj->oop_iterate_size(_cm_oop_closure);
}
}
} else {
// Need to process the klass always.
_cm_oop_closure->do_klass(task_entry.to_oop()->klass());
}
check_limits();
}
Expand Down Expand Up @@ -274,17 +278,17 @@ inline bool G1CMTask::make_reference_grey(oop obj) {
// correctness problems.
if (is_below_finger(obj, global_finger)) {
G1TaskQueueEntry entry(obj);
if (obj->is_typeArray()) {
// Immediately process arrays of primitive types, rather
if (_g1h->can_be_marked_through_immediately(obj)) {
// Immediately process arrays of types without oops, rather
// than pushing on the mark stack. This keeps us from
// adding humongous objects to the mark stack that might
// be reclaimed before the entry is processed - see
// selection of candidates for eager reclaim of humongous
// objects. The cost of the additional type test is
// mitigated by avoiding a trip through the mark stack,
// by only doing a bookkeeping update and avoiding the
// actual scan of the object - a typeArray contains no
// references, and the metadata is built-in.
// actual scan of the object - the object contains no
// references (but the metadata must be processed).
process_grey_task_entry<false>(entry, false /* stolen */);
} else {
push(entry);
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/gc/g1/g1FullCollector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

#include "classfile/classLoaderDataGraph.hpp"
#include "cppstdlib/new.hpp"
#include "gc/g1/g1CollectedHeap.hpp"
//#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1FullCollector.inline.hpp"
#include "gc/g1/g1FullGCAdjustTask.hpp"
#include "gc/g1/g1FullGCCompactTask.hpp"
Expand Down
33 changes: 18 additions & 15 deletions src/hotspot/share/gc/g1/g1YoungCollector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -341,13 +341,14 @@ class G1PrepareEvacuationTask : public WorkerTask {
// It also helps with G1 allocating humongous objects as old generation
// objects although they might also die quite quickly.
//
// TypeArray objects are allowed to be reclaimed even if allocated before
// Humongous objects without oops (typeArrays, flatArrays without oops in
// its elements) are allowed to be reclaimed even if allocated before
// the start of concurrent mark. For this we rely on mark stack insertion
// to exclude is_typeArray() objects, preventing reclaiming an object
// that is in the mark stack. We also rely on the metadata for
// such objects to be built-in and so ensured to be kept live.
// to exclude them, preventing reclaiming an object
// that is in the mark stack. That code also ensures that metadata (klass)
// is kept live.
//
// Non-typeArrays that were allocated before marking are excluded from
// Other humongous objects that were allocated before marking are excluded from
// eager reclaim during marking. One issue is the problem described
// above with scrubbing the mark stack, but there is also a problem
// causing these humongous objects being collected incorrectly:
Expand All @@ -362,16 +363,17 @@ class G1PrepareEvacuationTask : public WorkerTask {
// garbage collection. o1 still has the reference to o2, but since o1 had
// already been scanned we do not detect o2 to be still live and reclaim it.
//
// There is another minor problem with non-typeArray regions being the source
// of remembered set entries in other region's remembered sets. There are
// two cases: first, the remembered set entry is in a Free region after reclaim.
// We handle this case by ignoring these cards during merging the remembered
// sets.
// There is another minor problem with these humongous objects with oops being
// the source of remembered set entries in other region's remembered sets.
// There are two cases: first, the remembered set entry is in a Free region
// after reclaim. We handle this case by ignoring these cards during merging
// the remembered sets.
//
// Second, there may be cases where eagerly reclaimed regions were already
// reallocated. This may cause scanning of these outdated remembered set
// entries, containing some objects. But apart from extra work this does
// not cause correctness issues.
// Second, there may be cases where regions previously containing eagerly
// reclaimed objects were already allocated into again.
// This may cause scanning of these outdated remembered set entries,
// containing some objects. But apart from extra work this does not cause
// correctness issues.
// There is no difference between scanning cards covering an effectively
// dead humongous object vs. some other objects in reallocated regions.
//
Expand All @@ -388,7 +390,8 @@ class G1PrepareEvacuationTask : public WorkerTask {
//
// After the pause, having reclaimed h, obviously the mutator can't fetch
// the reference from h any more.
if (!obj->is_typeArray()) {
bool marked_immediately = _g1h->can_be_marked_through_immediately(obj);
if (!marked_immediately) {
// All regions that were allocated before marking have a TAMS != bottom.
bool allocated_before_mark_start = region->bottom() != _g1h->concurrent_mark()->top_at_mark_start(region);
bool mark_in_progress = _g1h->collector_state()->is_in_marking();
Expand Down
8 changes: 4 additions & 4 deletions src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -396,10 +396,10 @@ class G1FreeHumongousRegionClosure : public G1HeapRegionIndexClosure {
ResourceMark rm;
bool allocated_after_mark_start = r->bottom() == _g1h->concurrent_mark()->top_at_mark_start(r);
bool mark_in_progress = _g1h->collector_state()->is_in_marking();
guarantee(obj->is_typeArray() || (allocated_after_mark_start || !mark_in_progress),
"Only eagerly reclaiming primitive arrays is supported, other humongous objects only if allocated after mark start, but the object "
PTR_FORMAT " (%s) is not (mark %d allocated after mark: %d).",
p2i(r->bottom()), obj->klass()->name()->as_C_string(), mark_in_progress, allocated_after_mark_start);
guarantee(_g1h->can_be_marked_through_immediately(obj) || (allocated_after_mark_start || !mark_in_progress),
"Only eagerly reclaiming arrays without oops is always supported, other humongous objects only if allocated after mark start, but the object "
PTR_FORMAT " (%s) is not (allocated after mark: %d mark in progress %d marked immediately %d is_array %d array_with_oops %d).",
p2i(r->bottom()), obj->klass()->name()->as_C_string(), allocated_after_mark_start, mark_in_progress, _g1h->can_be_marked_through_immediately(obj), obj->is_array(), obj->is_array_with_oops());
}
log_debug(gc, humongous)("Reclaimed humongous region %u (object size %zu @ " PTR_FORMAT ")",
region_index,
Expand Down
Loading