mirror of
https://github.com/openjdk/jdk.git
synced 2026-07-24 18:03:10 +00:00
8388058: Shenandoah: Refactor arraycopy_work
Reviewed-by: kdnilsen, shade
This commit is contained in:
parent
0381286ade
commit
6ae23a0d65
@ -33,6 +33,7 @@
|
||||
class ShenandoahHeap;
|
||||
class ShenandoahBarrierSetAssembler;
|
||||
class ShenandoahCardTable;
|
||||
class ShenandoahMarkingContext;
|
||||
|
||||
class ShenandoahBarrierSet: public BarrierSet {
|
||||
private:
|
||||
@ -126,6 +127,10 @@ public:
|
||||
private:
|
||||
template <bool IS_GENERATIONAL, class T>
|
||||
void arraycopy_marking(T* dst, size_t count);
|
||||
|
||||
template <bool IS_GENERATIONAL, class T>
|
||||
bool is_above_tams(const ShenandoahMarkingContext* ctx, T* dst) const;
|
||||
|
||||
template <class T>
|
||||
inline void arraycopy_evacuation(T* src, size_t count);
|
||||
template <class T>
|
||||
@ -134,10 +139,7 @@ private:
|
||||
template <bool EVAC>
|
||||
inline void clone_work(oop src);
|
||||
|
||||
template <class T, bool HAS_FWD, bool EVAC, bool ENQUEUE>
|
||||
inline void arraycopy_work(T* src, size_t count);
|
||||
|
||||
inline bool need_bulk_update(HeapWord* dst);
|
||||
inline bool need_bulk_update(HeapWord* dst) const;
|
||||
public:
|
||||
// Callbacks for runtime accesses.
|
||||
template <DecoratorSet decorators, typename BarrierSetT = ShenandoahBarrierSet>
|
||||
|
||||
@ -509,40 +509,6 @@ OopCopyResult ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T, bool HAS_FWD, bool EVAC, bool ENQUEUE>
|
||||
void ShenandoahBarrierSet::arraycopy_work(T* src, size_t count) {
|
||||
// Young cycles are allowed to run when old marking is in progress. When old marking is in progress,
|
||||
// this barrier will be called with ENQUEUE=true and HAS_FWD=false, even though the young generation
|
||||
// may have forwarded objects.
|
||||
assert(HAS_FWD == _heap->has_forwarded_objects() || _heap->is_concurrent_old_mark_in_progress(), "Forwarded object status is sane");
|
||||
// This function cannot be called to handle marking and evacuation at the same time (they operate on
|
||||
// different sides of the copy).
|
||||
static_assert((HAS_FWD || EVAC) != ENQUEUE, "Cannot evacuate and mark both sides of copy.");
|
||||
|
||||
Thread* thread = Thread::current();
|
||||
SATBMarkQueue& queue = ShenandoahThreadLocalData::satb_mark_queue(thread);
|
||||
ShenandoahMarkingContext* ctx = _heap->marking_context();
|
||||
const ShenandoahCollectionSet* const cset = _heap->collection_set();
|
||||
T* end = src + count;
|
||||
for (T* elem_ptr = src; elem_ptr < end; elem_ptr++) {
|
||||
T o = RawAccess<>::oop_load(elem_ptr);
|
||||
if (!CompressedOops::is_null(o)) {
|
||||
oop obj = CompressedOops::decode_not_null(o);
|
||||
if (HAS_FWD && cset->is_in(obj)) {
|
||||
oop fwd = ShenandoahForwarding::get_forwardee(obj);
|
||||
if (EVAC && obj == fwd) {
|
||||
fwd = _heap->evacuate_object(obj, thread);
|
||||
}
|
||||
shenandoah_assert_forwarded_except(elem_ptr, obj, _heap->cancelled_gc());
|
||||
ShenandoahHeap::atomic_update_oop(fwd, elem_ptr, o);
|
||||
}
|
||||
if (ENQUEUE && !ctx->is_marked_strong(obj)) {
|
||||
_satb_mark_queue_set.enqueue_known_active(queue, obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void ShenandoahBarrierSet::arraycopy_barrier(T* src, T* dst, size_t count) {
|
||||
if (count == 0) {
|
||||
@ -574,31 +540,92 @@ void ShenandoahBarrierSet::arraycopy_barrier(T* src, T* dst, size_t count) {
|
||||
template <bool IS_GENERATIONAL, class T>
|
||||
void ShenandoahBarrierSet::arraycopy_marking(T* dst, size_t count) {
|
||||
assert(_heap->is_concurrent_mark_in_progress(), "only during marking");
|
||||
if (ShenandoahSATBBarrier) {
|
||||
if (!_heap->marking_context()->allocated_after_mark_start(reinterpret_cast<HeapWord*>(dst)) ||
|
||||
(IS_GENERATIONAL && _heap->heap_region_containing(dst)->is_old() && _heap->is_concurrent_young_mark_in_progress())) {
|
||||
arraycopy_work<T, false, false, true>(dst, count);
|
||||
if (!ShenandoahSATBBarrier) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ShenandoahMarkingContext* ctx = _heap->marking_context();
|
||||
// Everything allocated above TAMS is alive and doesn't need the barrier to keep it that way
|
||||
if (is_above_tams<IS_GENERATIONAL>(ctx, dst)) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(!_heap->has_forwarded_objects() || _heap->is_concurrent_old_mark_in_progress(), "Forwarded object status is sane");
|
||||
Thread* thread = Thread::current();
|
||||
SATBMarkQueue& queue = ShenandoahThreadLocalData::satb_mark_queue(thread);
|
||||
T* end = dst + count;
|
||||
for (T* elem_ptr = dst; elem_ptr < end; ++elem_ptr) {
|
||||
T o = RawAccess<>::oop_load(elem_ptr);
|
||||
if (!CompressedOops::is_null(o)) {
|
||||
oop obj = CompressedOops::decode_not_null(o);
|
||||
if (!ctx->is_marked_strong(obj)) {
|
||||
_satb_mark_queue_set.enqueue_known_active(queue, obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline bool ShenandoahBarrierSet::need_bulk_update(HeapWord* ary) {
|
||||
template <bool IS_GENERATIONAL, class T>
|
||||
bool ShenandoahBarrierSet::is_above_tams(const ShenandoahMarkingContext* ctx, T* dst) const {
|
||||
// TAMS for an old region is unreliable during a young-only mark, so overwritten pointers in old dst arrays must
|
||||
// be enqueued to preserve old->young referents copied in and overwritten after init mark. See JDK-8373116.
|
||||
return ctx->allocated_after_mark_start(reinterpret_cast<HeapWord*>(dst))
|
||||
&& !(IS_GENERATIONAL
|
||||
&& _heap->heap_region_containing(dst)->is_old()
|
||||
&& _heap->is_concurrent_young_mark_in_progress());
|
||||
}
|
||||
|
||||
inline bool ShenandoahBarrierSet::need_bulk_update(HeapWord* ary) const {
|
||||
return ary < _heap->heap_region_containing(ary)->get_update_watermark();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void ShenandoahBarrierSet::arraycopy_evacuation(T* src, size_t count) {
|
||||
assert(_heap->is_evacuation_in_progress(), "only during evacuation");
|
||||
if (need_bulk_update(reinterpret_cast<HeapWord*>(src))) {
|
||||
arraycopy_work<T, true, true, false>(src, count);
|
||||
if (!need_bulk_update(reinterpret_cast<HeapWord*>(src))) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(_heap->has_forwarded_objects(), "Forwarded object status is sane");
|
||||
Thread* thread = Thread::current();
|
||||
const ShenandoahCollectionSet* const cset = _heap->collection_set();
|
||||
T* end = src + count;
|
||||
for (T* elem_ptr = src; elem_ptr < end; ++elem_ptr) {
|
||||
T o = RawAccess<>::oop_load(elem_ptr);
|
||||
if (!CompressedOops::is_null(o)) {
|
||||
oop obj = CompressedOops::decode_not_null(o);
|
||||
if (cset->is_in(obj)) {
|
||||
oop fwd = ShenandoahForwarding::get_forwardee(obj);
|
||||
if (obj == fwd) {
|
||||
fwd = _heap->evacuate_object(obj, thread);
|
||||
}
|
||||
shenandoah_assert_forwarded_except(elem_ptr, obj, _heap->cancelled_gc());
|
||||
ShenandoahHeap::atomic_update_oop(fwd, elem_ptr, o);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void ShenandoahBarrierSet::arraycopy_update(T* src, size_t count) {
|
||||
assert(_heap->is_update_refs_in_progress(), "only during update-refs");
|
||||
if (need_bulk_update(reinterpret_cast<HeapWord*>(src))) {
|
||||
arraycopy_work<T, true, false, false>(src, count);
|
||||
if (!need_bulk_update(reinterpret_cast<HeapWord*>(src))) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(_heap->has_forwarded_objects(), "Forwarded object status is sane");
|
||||
const ShenandoahCollectionSet* const cset = _heap->collection_set();
|
||||
T* end = src + count;
|
||||
for (T* elem_ptr = src; elem_ptr < end; ++elem_ptr) {
|
||||
T o = RawAccess<>::oop_load(elem_ptr);
|
||||
if (!CompressedOops::is_null(o)) {
|
||||
oop obj = CompressedOops::decode_not_null(o);
|
||||
if (cset->is_in(obj)) {
|
||||
oop fwd = ShenandoahForwarding::get_forwardee(obj);
|
||||
shenandoah_assert_forwarded_except(elem_ptr, obj, _heap->cancelled_gc());
|
||||
ShenandoahHeap::atomic_update_oop(fwd, elem_ptr, o);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user