Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
8242365: Shenandoah: use uint16_t instead of jushort for liveness cache
- Loading branch information
|
@@ -817,7 +817,7 @@ void ShenandoahConcurrentMark::mark_loop_prework(uint w, TaskTerminator *t, Refe |
|
|
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. |
|
@@ -863,7 +863,7 @@ void ShenandoahConcurrentMark::mark_loop_prework(uint w, TaskTerminator *t, Refe |
|
|
} |
|
|
|
|
|
template <class T, bool CANCELLABLE> |
|
|
void ShenandoahConcurrentMark::mark_loop_work(T* cl, jushort* live_data, uint worker_id, TaskTerminator *terminator) { |
|
|
void ShenandoahConcurrentMark::mark_loop_work(T* cl, ShenandoahLiveData* live_data, uint worker_id, TaskTerminator *terminator) { |
|
|
uintx stride = ShenandoahMarkLoopStride; |
|
|
|
|
|
ShenandoahHeap* heap = ShenandoahHeap::heap(); |
|
|
|
@@ -46,18 +46,18 @@ class ShenandoahConcurrentMark: public CHeapObj<mtGC> { |
|
|
// |
|
|
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); |
|
|
|
|
|
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, TaskTerminator *t); |
|
|
void mark_loop_work(T* cl, ShenandoahLiveData* live_data, uint worker_id, TaskTerminator *t); |
|
|
|
|
|
template <bool CANCELLABLE> |
|
|
void mark_loop_prework(uint worker_id, TaskTerminator *terminator, ReferenceProcessor *rp, bool strdedup); |
|
|
|
@@ -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); |
|
|
|
@@ -357,10 +357,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, |
|
@@ -3008,7 +3008,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"); |
|
@@ -3022,9 +3022,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); |
|
|
|
@@ -62,6 +62,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; |
|
@@ -613,15 +623,7 @@ class ShenandoahHeap : public CollectedHeap { |
|
|
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; |
|
@@ -651,7 +653,7 @@ class ShenandoahHeap : public CollectedHeap { |
|
|
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 |
|
|