8242365: Shenandoah: use uint16_t instead of jushort for liveness cache

Reviewed-by: rkennke
This commit is contained in:
Aleksey Shipilev 2020-04-08 13:44:58 +02:00
parent ab6f7ba627
commit 8dbc0af2ff
5 changed files with 28 additions and 27 deletions

View File

@ -802,7 +802,7 @@ void ShenandoahConcurrentMark::mark_loop_prework(uint w, ShenandoahTaskTerminato
bool strdedup) {
ShenandoahObjToScanQueue* q = get_queue(w);
jushort* ld = _heap->get_liveness_cache(w);
ShenandoahLiveData* ld = _heap->get_liveness_cache(w);
// TODO: We can clean up this if we figure out how to do templated oop closures that
// play nice with specialized_oop_iterators.
@ -848,7 +848,7 @@ void ShenandoahConcurrentMark::mark_loop_prework(uint w, ShenandoahTaskTerminato
}
template <class T, bool CANCELLABLE>
void ShenandoahConcurrentMark::mark_loop_work(T* cl, jushort* live_data, uint worker_id, ShenandoahTaskTerminator *terminator) {
void ShenandoahConcurrentMark::mark_loop_work(T* cl, ShenandoahLiveData* live_data, uint worker_id, ShenandoahTaskTerminator *terminator) {
uintx stride = ShenandoahMarkLoopStride;
ShenandoahHeap* heap = ShenandoahHeap::heap();

View File

@ -44,7 +44,7 @@ public:
//
private:
template <class T>
inline void do_task(ShenandoahObjToScanQueue* q, T* cl, jushort* live_data, ShenandoahMarkTask* task);
inline void do_task(ShenandoahObjToScanQueue* q, T* cl, ShenandoahLiveData* live_data, ShenandoahMarkTask* task);
template <class T>
inline void do_chunked_array_start(ShenandoahObjToScanQueue* q, T* cl, oop array);
@ -52,10 +52,10 @@ private:
template <class T>
inline void do_chunked_array(ShenandoahObjToScanQueue* q, T* cl, oop array, int chunk, int pow);
inline void count_liveness(jushort* live_data, oop obj);
inline void count_liveness(ShenandoahLiveData* live_data, oop obj);
template <class T, bool CANCELLABLE>
void mark_loop_work(T* cl, jushort* live_data, uint worker_id, ShenandoahTaskTerminator *t);
void mark_loop_work(T* cl, ShenandoahLiveData* live_data, uint worker_id, ShenandoahTaskTerminator *t);
template <bool CANCELLABLE>
void mark_loop_prework(uint worker_id, ShenandoahTaskTerminator *terminator, ReferenceProcessor *rp, bool strdedup);

View File

@ -37,7 +37,7 @@
#include "runtime/prefetch.inline.hpp"
template <class T>
void ShenandoahConcurrentMark::do_task(ShenandoahObjToScanQueue* q, T* cl, jushort* live_data, ShenandoahMarkTask* task) {
void ShenandoahConcurrentMark::do_task(ShenandoahObjToScanQueue* q, T* cl, ShenandoahLiveData* live_data, ShenandoahMarkTask* task) {
oop obj = task->obj();
shenandoah_assert_not_forwarded(NULL, obj);
@ -67,23 +67,22 @@ void ShenandoahConcurrentMark::do_task(ShenandoahObjToScanQueue* q, T* cl, jusho
}
}
inline void ShenandoahConcurrentMark::count_liveness(jushort* live_data, oop obj) {
inline void ShenandoahConcurrentMark::count_liveness(ShenandoahLiveData* live_data, oop obj) {
size_t region_idx = _heap->heap_region_index_containing(obj);
ShenandoahHeapRegion* region = _heap->get_region(region_idx);
size_t size = obj->size();
if (!region->is_humongous_start()) {
assert(!region->is_humongous(), "Cannot have continuations here");
size_t max = (1 << (sizeof(jushort) * 8)) - 1;
jushort cur = live_data[region_idx];
ShenandoahLiveData cur = live_data[region_idx];
size_t new_val = size + cur;
if (new_val >= max) {
if (new_val >= SHENANDOAH_LIVEDATA_MAX) {
// overflow, flush to region data
region->increase_live_data_gc_words(new_val);
live_data[region_idx] = 0;
} else {
// still good, remember in locals
live_data[region_idx] = (jushort) new_val;
live_data[region_idx] = (ShenandoahLiveData) new_val;
}
} else {
shenandoah_assert_in_correct_region(NULL, obj);

View File

@ -353,10 +353,10 @@ jint ShenandoahHeap::initialize() {
// Initialize the rest of GC subsystems
//
_liveness_cache = NEW_C_HEAP_ARRAY(jushort*, _max_workers, mtGC);
_liveness_cache = NEW_C_HEAP_ARRAY(ShenandoahLiveData*, _max_workers, mtGC);
for (uint worker = 0; worker < _max_workers; worker++) {
_liveness_cache[worker] = NEW_C_HEAP_ARRAY(jushort, _num_regions, mtGC);
Copy::fill_to_bytes(_liveness_cache[worker], _num_regions * sizeof(jushort));
_liveness_cache[worker] = NEW_C_HEAP_ARRAY(ShenandoahLiveData, _num_regions, mtGC);
Copy::fill_to_bytes(_liveness_cache[worker], _num_regions * sizeof(ShenandoahLiveData));
}
// There should probably be Shenandoah-specific options for these,
@ -2903,7 +2903,7 @@ const char* ShenandoahHeap::degen_event_message(ShenandoahDegenPoint point) cons
}
}
jushort* ShenandoahHeap::get_liveness_cache(uint worker_id) {
ShenandoahLiveData* ShenandoahHeap::get_liveness_cache(uint worker_id) {
#ifdef ASSERT
assert(_liveness_cache != NULL, "sanity");
assert(worker_id < _max_workers, "sanity");
@ -2917,9 +2917,9 @@ jushort* ShenandoahHeap::get_liveness_cache(uint worker_id) {
void ShenandoahHeap::flush_liveness_cache(uint worker_id) {
assert(worker_id < _max_workers, "sanity");
assert(_liveness_cache != NULL, "sanity");
jushort* ld = _liveness_cache[worker_id];
ShenandoahLiveData* ld = _liveness_cache[worker_id];
for (uint i = 0; i < num_regions(); i++) {
jushort live = ld[i];
ShenandoahLiveData live = ld[i];
if (live > 0) {
ShenandoahHeapRegion* r = get_region(i);
r->increase_live_data_gc_words(live);

View File

@ -61,6 +61,16 @@ class ShenandoahVerifier;
class ShenandoahWorkGang;
class VMStructs;
// Used for buffering per-region liveness data.
// Needed since ShenandoahHeapRegion uses atomics to update liveness.
// The ShenandoahHeap array has max-workers elements, each of which is an array of
// uint16_t * max_regions. The choice of uint16_t is not accidental:
// there is a tradeoff between static/dynamic footprint that translates
// into cache pressure (which is already high during marking), and
// too many atomic updates. uint32_t is too large, uint8_t is too small.
typedef uint16_t ShenandoahLiveData;
#define SHENANDOAH_LIVEDATA_MAX ((ShenandoahLiveData)-1)
class ShenandoahRegionIterator : public StackObj {
private:
ShenandoahHeap* _heap;
@ -612,15 +622,7 @@ private:
bool _bitmap_region_special;
bool _aux_bitmap_region_special;
// Used for buffering per-region liveness data.
// Needed since ShenandoahHeapRegion uses atomics to update liveness.
//
// The array has max-workers elements, each of which is an array of
// jushort * max_regions. The choice of jushort is not accidental:
// there is a tradeoff between static/dynamic footprint that translates
// into cache pressure (which is already high during marking), and
// too many atomic updates. size_t/jint is too large, jbyte is too small.
jushort** _liveness_cache;
ShenandoahLiveData** _liveness_cache;
public:
inline ShenandoahMarkingContext* complete_marking_context() const;
@ -650,7 +652,7 @@ public:
bool is_bitmap_slice_committed(ShenandoahHeapRegion* r, bool skip_self = false);
// Liveness caching support
jushort* get_liveness_cache(uint worker_id);
ShenandoahLiveData* get_liveness_cache(uint worker_id);
void flush_liveness_cache(uint worker_id);
// ---------- Evacuation support