Skip to content

Commit 4f071ce

Browse files
author
Kim Barrett
committed
8311163: Parallel: Improve large object handling during evacuation
Reviewed-by: tschatzl, ayang
1 parent b840b13 commit 4f071ce

File tree

5 files changed

+82
-67
lines changed

5 files changed

+82
-67
lines changed

src/hotspot/share/gc/parallel/psPromotionManager.cpp

Lines changed: 66 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,8 @@
3131
#include "gc/parallel/psScavenge.inline.hpp"
3232
#include "gc/shared/continuationGCSupport.inline.hpp"
3333
#include "gc/shared/gcTrace.hpp"
34+
#include "gc/shared/partialArrayState.hpp"
35+
#include "gc/shared/partialArrayTaskStepper.inline.hpp"
3436
#include "gc/shared/preservedMarks.inline.hpp"
3537
#include "gc/shared/taskqueue.inline.hpp"
3638
#include "logging/log.hpp"
@@ -42,12 +44,14 @@
4244
#include "memory/resourceArea.hpp"
4345
#include "oops/access.inline.hpp"
4446
#include "oops/compressedOops.inline.hpp"
47+
#include "utilities/checkedCast.hpp"
4548

4649
PaddedEnd<PSPromotionManager>* PSPromotionManager::_manager_array = nullptr;
4750
PSPromotionManager::PSScannerTasksQueueSet* PSPromotionManager::_stack_array_depth = nullptr;
4851
PreservedMarksSet* PSPromotionManager::_preserved_marks_set = nullptr;
4952
PSOldGen* PSPromotionManager::_old_gen = nullptr;
5053
MutableSpace* PSPromotionManager::_young_space = nullptr;
54+
PartialArrayStateAllocator* PSPromotionManager::_partial_array_state_allocator = nullptr;
5155

5256
void PSPromotionManager::initialize() {
5357
ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
@@ -62,11 +66,16 @@ void PSPromotionManager::initialize() {
6266
assert(_manager_array == nullptr, "Attempt to initialize twice");
6367
_manager_array = PaddedArray<PSPromotionManager, mtGC>::create_unfreeable(promotion_manager_num);
6468

69+
assert(_partial_array_state_allocator == nullptr, "Attempt to initialize twice");
70+
_partial_array_state_allocator
71+
= new PartialArrayStateAllocator(ParallelGCThreads);
72+
6573
_stack_array_depth = new PSScannerTasksQueueSet(ParallelGCThreads);
6674

6775
// Create and register the PSPromotionManager(s) for the worker threads.
6876
for(uint i=0; i<ParallelGCThreads; i++) {
6977
stack_array_depth()->register_queue(i, _manager_array[i].claimed_stack_depth());
78+
_manager_array[i]._partial_array_state_allocator_index = i;
7079
}
7180
// The VMThread gets its own PSPromotionManager, which is not available
7281
// for work stealing.
@@ -124,6 +133,10 @@ bool PSPromotionManager::post_scavenge(YoungGCTracer& gc_tracer) {
124133
manager->flush_labs();
125134
manager->flush_string_dedup_requests();
126135
}
136+
// All PartialArrayStates have been returned to the allocator, since the
137+
// claimed_stack_depths are all empty. Leave them there for use by future
138+
// collections.
139+
127140
if (!promotion_failure_occurred) {
128141
// If there was no promotion failure, the preserved mark stacks
129142
// should be empty.
@@ -172,7 +185,10 @@ void PSPromotionManager::reset_stats() {
172185
}
173186
#endif // TASKQUEUE_STATS
174187

175-
PSPromotionManager::PSPromotionManager() {
188+
// Most members are initialized either by initialize() or reset().
189+
PSPromotionManager::PSPromotionManager()
190+
: _partial_array_stepper(ParallelGCThreads, ParGCArrayScanChunk)
191+
{
176192
// We set the old lab's start array.
177193
_old_lab.set_start_array(old_gen()->start_array());
178194

@@ -182,9 +198,11 @@ PSPromotionManager::PSPromotionManager() {
182198
_target_stack_size = GCDrainStackTargetSize;
183199
}
184200

185-
_array_chunk_size = ParGCArrayScanChunk;
201+
// Initialize to a bad value; fixed by initialize().
202+
_partial_array_state_allocator_index = UINT_MAX;
203+
186204
// let's choose 1.5x the chunk size
187-
_min_array_size_for_chunking = 3 * _array_chunk_size / 2;
205+
_min_array_size_for_chunking = (3 * ParGCArrayScanChunk / 2);
188206

189207
_preserved_marks = nullptr;
190208

@@ -277,37 +295,57 @@ template <class T> void PSPromotionManager::process_array_chunk_work(
277295
}
278296
}
279297

280-
void PSPromotionManager::process_array_chunk(PartialArrayScanTask task) {
281-
assert(PSChunkLargeArrays, "invariant");
282-
283-
oop old = task.to_source_array();
284-
assert(old->is_objArray(), "invariant");
285-
assert(old->is_forwarded(), "invariant");
286-
298+
void PSPromotionManager::process_array_chunk(PartialArrayState* state) {
287299
TASKQUEUE_STATS_ONLY(++_array_chunks_processed);
288300

289-
oop const obj = old->forwardee();
290-
291-
int start;
292-
int const end = arrayOop(old)->length();
293-
if (end > (int) _min_array_size_for_chunking) {
294-
// we'll chunk more
295-
start = end - _array_chunk_size;
296-
assert(start > 0, "invariant");
297-
arrayOop(old)->set_length(start);
298-
push_depth(ScannerTask(PartialArrayScanTask(old)));
299-
TASKQUEUE_STATS_ONLY(++_array_chunk_pushes);
301+
// Claim a chunk. Push additional tasks before processing the claimed
302+
// chunk to allow other workers to steal while we're processing.
303+
PartialArrayTaskStepper::Step step = _partial_array_stepper.next(state);
304+
if (step._ncreate > 0) {
305+
state->add_references(step._ncreate);
306+
for (uint i = 0; i < step._ncreate; ++i) {
307+
push_depth(ScannerTask(state));
308+
}
309+
TASKQUEUE_STATS_ONLY(_array_chunk_pushes += step._ncreate);
310+
}
311+
int start = checked_cast<int>(step._index);
312+
int end = checked_cast<int>(step._index + _partial_array_stepper.chunk_size());
313+
assert(start < end, "invariant");
314+
if (UseCompressedOops) {
315+
process_array_chunk_work<narrowOop>(state->destination(), start, end);
300316
} else {
301-
// this is the final chunk for this array
302-
start = 0;
303-
int const actual_length = arrayOop(obj)->length();
304-
arrayOop(old)->set_length(actual_length);
317+
process_array_chunk_work<oop>(state->destination(), start, end);
305318
}
319+
// Release reference to state, now that we're done with it.
320+
_partial_array_state_allocator->release(_partial_array_state_allocator_index, state);
321+
}
306322

323+
void PSPromotionManager::push_objArray(oop old_obj, oop new_obj) {
324+
assert(old_obj->is_objArray(), "precondition");
325+
assert(old_obj->is_forwarded(), "precondition");
326+
assert(old_obj->forwardee() == new_obj, "precondition");
327+
assert(new_obj->is_objArray(), "precondition");
328+
329+
size_t array_length = objArrayOop(new_obj)->length();
330+
PartialArrayTaskStepper::Step step = _partial_array_stepper.start(array_length);
331+
332+
if (step._ncreate > 0) {
333+
TASKQUEUE_STATS_ONLY(++_arrays_chunked);
334+
PartialArrayState* state =
335+
_partial_array_state_allocator->allocate(_partial_array_state_allocator_index,
336+
old_obj, new_obj,
337+
step._index,
338+
array_length,
339+
step._ncreate);
340+
for (uint i = 0; i < step._ncreate; ++i) {
341+
push_depth(ScannerTask(state));
342+
}
343+
TASKQUEUE_STATS_ONLY(_array_chunk_pushes += step._ncreate);
344+
}
307345
if (UseCompressedOops) {
308-
process_array_chunk_work<narrowOop>(obj, start, end);
346+
process_array_chunk_work<narrowOop>(new_obj, 0, checked_cast<int>(step._index));
309347
} else {
310-
process_array_chunk_work<oop>(obj, start, end);
348+
process_array_chunk_work<oop>(new_obj, 0, checked_cast<int>(step._index));
311349
}
312350
}
313351

src/hotspot/share/gc/parallel/psPromotionManager.hpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@
2828
#include "gc/parallel/psPromotionLAB.hpp"
2929
#include "gc/shared/copyFailedInfo.hpp"
3030
#include "gc/shared/gcTrace.hpp"
31+
#include "gc/shared/partialArrayTaskStepper.hpp"
3132
#include "gc/shared/preservedMarks.hpp"
3233
#include "gc/shared/stringdedup/stringDedup.hpp"
3334
#include "gc/shared/taskqueue.hpp"
@@ -49,6 +50,8 @@
4950
class MutableSpace;
5051
class PSOldGen;
5152
class ParCompactionManager;
53+
class PartialArrayState;
54+
class PartialArrayStateAllocator;
5255

5356
class PSPromotionManager {
5457
friend class PSScavenge;
@@ -85,7 +88,9 @@ class PSPromotionManager {
8588

8689
uint _target_stack_size;
8790

88-
uint _array_chunk_size;
91+
static PartialArrayStateAllocator* _partial_array_state_allocator;
92+
PartialArrayTaskStepper _partial_array_stepper;
93+
uint _partial_array_state_allocator_index;
8994
uint _min_array_size_for_chunking;
9095

9196
PreservedMarks* _preserved_marks;
@@ -101,7 +106,8 @@ class PSPromotionManager {
101106

102107
template <class T> void process_array_chunk_work(oop obj,
103108
int start, int end);
104-
void process_array_chunk(PartialArrayScanTask task);
109+
void process_array_chunk(PartialArrayState* state);
110+
void push_objArray(oop old_obj, oop new_obj);
105111

106112
void push_depth(ScannerTask task);
107113

src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -276,9 +276,7 @@ inline oop PSPromotionManager::copy_unmarked_to_survivor_space(oop o,
276276
if (new_obj_size > _min_array_size_for_chunking &&
277277
new_obj->is_objArray() &&
278278
PSChunkLargeArrays) {
279-
// we'll chunk it
280-
push_depth(ScannerTask(PartialArrayScanTask(o)));
281-
TASKQUEUE_STATS_ONLY(++_arrays_chunked; ++_array_chunk_pushes);
279+
push_objArray(o, new_obj);
282280
} else {
283281
// we'll just push its contents
284282
push_contents(new_obj);
@@ -322,9 +320,9 @@ inline void PSPromotionManager::copy_and_push_safe_barrier(T* p) {
322320
}
323321

324322
inline void PSPromotionManager::process_popped_location_depth(ScannerTask task) {
325-
if (task.is_partial_array_task()) {
323+
if (task.is_partial_array_state()) {
326324
assert(PSChunkLargeArrays, "invariant");
327-
process_array_chunk(task.to_partial_array_task());
325+
process_array_chunk(task.to_partial_array_state());
328326
} else {
329327
if (task.is_narrow_oop_ptr()) {
330328
assert(UseCompressedOops, "Error");
@@ -341,7 +339,7 @@ inline bool PSPromotionManager::steal_depth(int queue_num, ScannerTask& t) {
341339

342340
#if TASKQUEUE_STATS
343341
void PSPromotionManager::record_steal(ScannerTask task) {
344-
if (task.is_partial_array_task()) {
342+
if (task.is_partial_array_state()) {
345343
++_array_chunk_steals;
346344
}
347345
}

src/hotspot/share/gc/shared/partialArrayState.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#ifndef SHARE_GC_SHARED_PARTIALARRAYSTATE_HPP
2626
#define SHARE_GC_SHARED_PARTIALARRAYSTATE_HPP
2727

28+
#include "memory/allocation.hpp"
2829
#include "oops/oopsHierarchy.hpp"
2930
#include "utilities/globalDefinitions.hpp"
3031
#include "utilities/macros.hpp"
@@ -109,7 +110,7 @@ class PartialArrayState {
109110
// the worker_id used in the operation. This avoids locking and such on those
110111
// data structures, at the cost of possibly doing more total arena allocation
111112
// that would be needed with a single shared arena and free-list.
112-
class PartialArrayStateAllocator {
113+
class PartialArrayStateAllocator : public CHeapObj<mtGC> {
113114
class Impl;
114115
Impl* _impl;
115116

src/hotspot/share/gc/shared/taskqueue.hpp

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -573,20 +573,6 @@ class ObjArrayTask
573573
int _index;
574574
};
575575

576-
// Wrapper over an oop that is a partially scanned array.
577-
// Can be converted to a ScannerTask for placement in associated task queues.
578-
// Refers to the partially copied source array oop.
579-
// Temporarily retained to support ParallelGC until it adopts PartialArrayState.
580-
class PartialArrayScanTask {
581-
oop _src;
582-
583-
public:
584-
explicit PartialArrayScanTask(oop src_array) : _src(src_array) {}
585-
// Trivially copyable.
586-
587-
oop to_source_array() const { return _src; }
588-
};
589-
590576
class PartialArrayState;
591577

592578
// Discriminated union over oop*, narrowOop*, and PartialArrayState.
@@ -627,10 +613,6 @@ class ScannerTask {
627613

628614
explicit ScannerTask(narrowOop* p) : _p(encode(p, NarrowOopTag)) {}
629615

630-
// Temporarily retained to support ParallelGC until it adopts PartialArrayState.
631-
explicit ScannerTask(PartialArrayScanTask t) :
632-
_p(encode(t.to_source_array(), PartialArrayTag)) {}
633-
634616
explicit ScannerTask(PartialArrayState* state) :
635617
_p(encode(state, PartialArrayTag)) {}
636618

@@ -646,11 +628,6 @@ class ScannerTask {
646628
return (raw_value() & NarrowOopTag) != 0;
647629
}
648630

649-
// Temporarily retained to support ParallelGC until it adopts PartialArrayState.
650-
bool is_partial_array_task() const {
651-
return (raw_value() & PartialArrayTag) != 0;
652-
}
653-
654631
bool is_partial_array_state() const {
655632
return (raw_value() & PartialArrayTag) != 0;
656633
}
@@ -663,11 +640,6 @@ class ScannerTask {
663640
return static_cast<narrowOop*>(decode(NarrowOopTag));
664641
}
665642

666-
// Temporarily retained to support ParallelGC until it adopts PartialArrayState.
667-
PartialArrayScanTask to_partial_array_task() const {
668-
return PartialArrayScanTask(cast_to_oop(decode(PartialArrayTag)));
669-
}
670-
671643
PartialArrayState* to_partial_array_state() const {
672644
return static_cast<PartialArrayState*>(decode(PartialArrayTag));
673645
}

0 commit comments

Comments
 (0)