RFR: 8361099: Shenandoah: Improve heap lock contention by using CAS for memory allocation [v20]

Xiaolong Peng xpeng at openjdk.org
Fri Jan 9 19:28:21 UTC 2026


On Tue, 6 Jan 2026 01:28:42 GMT, Kelvin Nilsen <kdnilsen at openjdk.org> wrote:

>> Xiaolong Peng has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 265 commits:
>> 
>>  - Merge branch 'openjdk:master' into cas-alloc-1
>>  - Fix build error after merging from tip
>>  - Merge branch 'master' into cas-alloc-1
>>  - Merge branch 'master' into cas-alloc-1
>>  - Some comments updates as suggested in PR review
>>  - Fix build failure after merge
>>  - Expend promoted from ShenandoahOldCollectorAllocator
>>  - Merge branch 'master' into cas-alloc-1
>>  - Address PR comments
>>  - Merge branch 'openjdk:master' into cas-alloc-1
>>  - ... and 255 more: https://git.openjdk.org/jdk/compare/de81d389...cf13b7b5
>
> src/hotspot/share/gc/shenandoah/shenandoahAllocator.cpp line 376:
> 
>> 374: }
>> 375: 
>> 376: THREAD_LOCAL uint ShenandoahMutatorAllocator::_alloc_start_index = UINT_MAX;
> 
> I raised questions about this in a previous review.  Have I overlooked your response?  What is the tradeoff between declaring this THREAD_LOCAL vs. creating a new field in ShenandoahThreadLocal?  I believe we need to use fields of ShenandoahThreadLocal so that we do not incur an overhead on all threads when JVM is not configured for Shenandoah GC.

I don't have concern to move it to ShenandoahThreadLocalData, the benefit of using THREAD_LOCAL is just better cohesive code because  _alloc_start_index is defined in the same namespace where it is used. Performance wise, I don't think there is much benefits.

I do see ZGC also use THREAD_LOCAL directly, I guess the overhead on all threads is not a huge concern. 
But given Shenandoah has ShenandoahThreadLocalData to manage all the thread locals, it make sense to not use THREAD_LOCAL directly, I'll update the PR to move _alloc_start_index to ShenandoahThreadLocalData.

> src/hotspot/share/gc/shenandoah/shenandoahAllocator.cpp line 436:
> 
>> 434:   // Make sure the old generation has room for either evacuations or promotions before trying to allocate.
>> 435:   auto old_gen = ShenandoahHeap::heap()->old_generation();
>> 436:   if (req.is_old() && !old_gen->can_allocate(req)) {
> 
> This test for req.is_old() appears to be unnecessary.  The verify(req) assert above requires that req.is_old().
> 
> Perhaps the verify() method is too abstract.  Add a comment there that says: "Confirm that req.is_old()"

Thanks for pointing out this, it is not necessary, I have removed it.

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/26171#discussion_r2677369816
PR Review Comment: https://git.openjdk.org/jdk/pull/26171#discussion_r2677373200


More information about the hotspot-gc-dev mailing list