Skip to content

8253169: [BACKOUT] Improve large object handling during evacuation #181

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
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
125 changes: 48 additions & 77 deletions src/hotspot/share/gc/g1/g1ParScanThreadState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,15 @@
#include "gc/g1/g1RootClosures.hpp"
#include "gc/g1/g1StringDedup.hpp"
#include "gc/g1/g1Trace.hpp"
#include "gc/shared/partialArrayTaskStepper.inline.hpp"
#include "gc/shared/taskqueue.inline.hpp"
#include "memory/allocation.inline.hpp"
#include "oops/access.inline.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/atomic.hpp"
#include "runtime/prefetch.inline.hpp"
#include "utilities/globalDefinitions.hpp"

G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h,
G1RedirtyCardsQueueSet* rdcqs,
uint worker_id,
uint n_workers,
size_t young_cset_length,
size_t optional_cset_length)
: _g1h(g1h),
Expand All @@ -64,8 +60,6 @@ G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h,
_surviving_young_words(NULL),
_surviving_words_length(young_cset_length + 1),
_old_gen_is_full(false),
_partial_objarray_chunk_size(ParGCArrayScanChunk),
_partial_array_stepper(n_workers),
_num_optional_regions(optional_cset_length),
_numa(g1h->numa()),
_obj_alloc_stat(NULL)
Expand Down Expand Up @@ -205,59 +199,48 @@ void G1ParScanThreadState::do_partial_array(PartialArrayScanTask task) {

assert(_g1h->is_in_reserved(from_obj), "must be in heap.");
assert(from_obj->is_objArray(), "must be obj array");
assert(from_obj->is_forwarded(), "must be forwarded");
objArrayOop from_obj_array = objArrayOop(from_obj);
// The from-space object contains the real length.
int length = from_obj_array->length();

oop to_obj = from_obj->forwardee();
assert(from_obj->is_forwarded(), "must be forwarded");
oop to_obj = from_obj->forwardee();
assert(from_obj != to_obj, "should not be chunking self-forwarded objects");
assert(to_obj->is_objArray(), "must be obj array");
objArrayOop to_array = objArrayOop(to_obj);

PartialArrayTaskStepper::Step step
= _partial_array_stepper.next(objArrayOop(from_obj),
to_array,
_partial_objarray_chunk_size);
for (uint i = 0; i < step._ncreate; ++i) {
objArrayOop to_obj_array = objArrayOop(to_obj);
// We keep track of the next start index in the length field of the
// to-space object.
int next_index = to_obj_array->length();
assert(0 <= next_index && next_index < length,
"invariant, next index: %d, length: %d", next_index, length);

int start = next_index;
int end = length;
int remainder = end - start;
// We'll try not to push a range that's smaller than ParGCArrayScanChunk.
if (remainder > 2 * ParGCArrayScanChunk) {
end = start + ParGCArrayScanChunk;
to_obj_array->set_length(end);
// Push the remainder before we process the range in case another
// worker has run out of things to do and can steal it.
push_on_queue(ScannerTask(PartialArrayScanTask(from_obj)));
} else {
assert(length == end, "sanity");
// We'll process the final range for this object. Restore the length
// so that the heap remains parsable in case of evacuation failure.
to_obj_array->set_length(end);
}

HeapRegion* hr = _g1h->heap_region_containing(to_array);
HeapRegion* hr = _g1h->heap_region_containing(to_obj);
G1ScanInYoungSetter x(&_scanner, hr->is_young());
// Process claimed task. The length of to_array is not correct, but
// fortunately the iteration ignores the length field and just relies
// on start/end.
to_array->oop_iterate_range(&_scanner,
step._index,
step._index + _partial_objarray_chunk_size);
}

void G1ParScanThreadState::start_partial_objarray(G1HeapRegionAttr dest_attr,
oop from_obj,
oop to_obj) {
assert(from_obj->is_objArray(), "precondition");
assert(from_obj->is_forwarded(), "precondition");
assert(from_obj->forwardee() == to_obj, "precondition");
assert(from_obj != to_obj, "should not be scanning self-forwarded objects");
assert(to_obj->is_objArray(), "precondition");

objArrayOop to_array = objArrayOop(to_obj);

PartialArrayTaskStepper::Step step
= _partial_array_stepper.start(objArrayOop(from_obj),
to_array,
_partial_objarray_chunk_size);

// Push any needed partial scan tasks. Pushed before processing the
// intitial chunk to allow other workers to steal while we're processing.
for (uint i = 0; i < step._ncreate; ++i) {
push_on_queue(ScannerTask(PartialArrayScanTask(from_obj)));
}

G1ScanInYoungSetter x(&_scanner, dest_attr.is_young());
// Process the initial chunk. No need to process the type in the
// klass, as it will already be handled by processing the built-in
// module. The length of to_array is not correct, but fortunately
// the iteration ignores that length field and relies on start/end.
to_array->oop_iterate_range(&_scanner, 0, step._index);
// Process indexes [start,end). It will also process the header
// along with the first chunk (i.e., the chunk with start == 0).
// Note that at this point the length field of to_obj_array is not
// correct given that we are using it to keep track of the next
// start index. oop_iterate_range() (thankfully!) ignores the length
// field and only relies on the start / end parameters. It does
// however return the size of the object which will be incorrect. So
// we have to ignore it even if we wanted to use it.
to_obj_array->oop_iterate_range(&_scanner, start, end);
}

void G1ParScanThreadState::dispatch_task(ScannerTask task) {
Expand Down Expand Up @@ -411,10 +394,7 @@ oop G1ParScanThreadState::do_copy_to_survivor_space(G1HeapRegionAttr const regio
assert(region_attr.is_in_cset(),
"Unexpected region attr type: %s", region_attr.get_type_str());

// Get the klass once. We'll need it again later, and this avoids
// re-decoding when it's compressed.
Klass* klass = old->klass();
const size_t word_sz = old->size_given_klass(klass);
const size_t word_sz = old->size();

uint age = 0;
G1HeapRegionAttr dest_attr = next_region_attr(region_attr, old_mark, age);
Expand Down Expand Up @@ -481,20 +461,6 @@ oop G1ParScanThreadState::do_copy_to_survivor_space(G1HeapRegionAttr const regio
obj->set_mark_raw(old_mark);
}

// Most objects are not arrays, so do one array check rather than
// checking for each array category for each object.
if (klass->is_array_klass()) {
if (klass->is_objArray_klass()) {
start_partial_objarray(dest_attr, old, obj);
} else {
// Nothing needs to be done for typeArrays. Body doesn't contain
// any oops to scan, and the type in the klass will already be handled
// by processing the built-in module.
assert(klass->is_typeArray_klass(), "invariant");
}
return obj;
}

if (G1StringDedup::is_enabled()) {
const bool is_from_young = region_attr.is_young();
const bool is_to_young = dest_attr.is_young();
Expand All @@ -508,10 +474,17 @@ oop G1ParScanThreadState::do_copy_to_survivor_space(G1HeapRegionAttr const regio
obj);
}

G1ScanInYoungSetter x(&_scanner, dest_attr.is_young());
obj->oop_iterate_backwards(&_scanner);
if (obj->is_objArray() && arrayOop(obj)->length() >= ParGCArrayScanChunk) {
// We keep track of the next start index in the length field of
// the to-space object. The actual length can be found in the
// length field of the from-space object.
arrayOop(obj)->set_length(0);
do_partial_array(PartialArrayScanTask(old));
} else {
G1ScanInYoungSetter x(&_scanner, dest_attr.is_young());
obj->oop_iterate_backwards(&_scanner);
}
return obj;

} else {
_plab_allocator->undo_allocation(dest_attr, obj_ptr, word_sz, node_index);
return forward_ptr;
Expand All @@ -530,9 +503,7 @@ G1ParScanThreadState* G1ParScanThreadStateSet::state_for_worker(uint worker_id)
assert(worker_id < _n_workers, "out of bounds access");
if (_states[worker_id] == NULL) {
_states[worker_id] =
new G1ParScanThreadState(_g1h, _rdcqs,
worker_id, _n_workers,
_young_cset_length, _optional_cset_length);
new G1ParScanThreadState(_g1h, _rdcqs, worker_id, _young_cset_length, _optional_cset_length);
}
return _states[worker_id];
}
Expand Down
9 changes: 3 additions & 6 deletions src/hotspot/share/gc/g1/g1ParScanThreadState.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
#include "gc/g1/g1RemSet.hpp"
#include "gc/g1/heapRegionRemSet.hpp"
#include "gc/shared/ageTable.hpp"
#include "gc/shared/partialArrayTaskStepper.hpp"
#include "gc/shared/taskqueue.hpp"
#include "memory/allocation.hpp"
#include "oops/oop.hpp"
Expand Down Expand Up @@ -80,9 +79,6 @@ class G1ParScanThreadState : public CHeapObj<mtGC> {
// Indicates whether in the last generation (old) there is no more space
// available for allocation.
bool _old_gen_is_full;
// Size (in elements) of a partial objArray task chunk.
int _partial_objarray_chunk_size;
PartialArrayTaskStepper _partial_array_stepper;

G1RedirtyCardsQueue& redirty_cards_queue() { return _rdcq; }
G1CardTable* ct() { return _ct; }
Expand All @@ -109,7 +105,6 @@ class G1ParScanThreadState : public CHeapObj<mtGC> {
G1ParScanThreadState(G1CollectedHeap* g1h,
G1RedirtyCardsQueueSet* rdcqs,
uint worker_id,
uint n_workers,
size_t young_cset_length,
size_t optional_cset_length);
virtual ~G1ParScanThreadState();
Expand Down Expand Up @@ -162,7 +157,6 @@ class G1ParScanThreadState : public CHeapObj<mtGC> {

private:
inline void do_partial_array(PartialArrayScanTask task);
inline void start_partial_objarray(G1HeapRegionAttr dest_dir, oop from, oop to);

HeapWord* allocate_copy_slow(G1HeapRegionAttr* dest_attr,
oop old,
Expand Down Expand Up @@ -255,6 +249,9 @@ class G1ParScanThreadStateSet : public StackObj {
G1ParScanThreadState* state_for_worker(uint worker_id);

const size_t* surviving_young_words() const;

private:
G1ParScanThreadState* new_par_scan_state(uint worker_id, size_t young_cset_length);
};

#endif // SHARE_GC_G1_G1PARSCANTHREADSTATE_HPP
53 changes: 0 additions & 53 deletions src/hotspot/share/gc/shared/partialArrayTaskStepper.cpp

This file was deleted.

82 changes: 0 additions & 82 deletions src/hotspot/share/gc/shared/partialArrayTaskStepper.hpp

This file was deleted.

Loading