From e62a7067590292d3e9a3b314e5f010720296c750 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Tue, 27 Jan 2026 10:14:03 +0100 Subject: [PATCH] More touchups, AArch64 version --- .../shenandoahBarrierSetAssembler_aarch64.cpp | 79 +++++++++---------- .../shenandoahBarrierSetAssembler_aarch64.hpp | 25 +++--- .../shenandoahBarrierSetAssembler_x86.cpp | 5 +- .../gc/shenandoah/shenandoahBarrierSet.cpp | 6 +- 4 files changed, 51 insertions(+), 64 deletions(-) diff --git a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp index 9a035d9f40e..5b9552e215a 100644 --- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp @@ -85,26 +85,16 @@ void ShenandoahBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, Dec } } -void ShenandoahBarrierSetAssembler::shenandoah_write_barrier_pre(MacroAssembler* masm, - Register obj, - Register pre_val, - Register thread, - Register tmp, - bool tosca_live, - bool expand_call) { - if (ShenandoahSATBBarrier) { - satb_write_barrier_pre(masm, obj, pre_val, thread, tmp, rscratch1, tosca_live, expand_call); - } -} +void ShenandoahBarrierSetAssembler::satb_barrier(MacroAssembler* masm, + Register obj, + Register pre_val, + Register thread, + Register tmp1, + Register tmp2, + bool tosca_live, + bool expand_call) { + assert(ShenandoahSATBBarrier, "Should be checked by caller"); -void ShenandoahBarrierSetAssembler::satb_write_barrier_pre(MacroAssembler* masm, - Register obj, - Register pre_val, - Register thread, - Register tmp1, - Register tmp2, - bool tosca_live, - bool expand_call) { // If expand_call is true then we expand the call_VM_leaf macro // directly to skip generating the check by // InterpreterMacroAssembler::call_VM_leaf_base that checks _last_sp. @@ -358,20 +348,20 @@ void ShenandoahBarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet d if (ShenandoahBarrierSet::need_keep_alive_barrier(decorators, type)) { __ enter(/*strip_ret_addr*/true); __ push_call_clobbered_registers(); - satb_write_barrier_pre(masm /* masm */, - noreg /* obj */, - dst /* pre_val */, - rthread /* thread */, - tmp1 /* tmp1 */, - tmp2 /* tmp2 */, - true /* tosca_live */, - true /* expand_call */); + satb_barrier(masm /* masm */, + noreg /* obj */, + dst /* pre_val */, + rthread /* thread */, + tmp1 /* tmp1 */, + tmp2 /* tmp2 */, + true /* tosca_live */, + true /* expand_call */); __ pop_call_clobbered_registers(); __ leave(); } } -void ShenandoahBarrierSetAssembler::store_check(MacroAssembler* masm, Register obj) { +void ShenandoahBarrierSetAssembler::card_barrier(MacroAssembler* masm, Register obj) { assert(ShenandoahCardBarrier, "Should have been checked by caller"); __ lsr(obj, obj, CardTable::card_shift()); @@ -394,13 +384,13 @@ void ShenandoahBarrierSetAssembler::store_check(MacroAssembler* masm, Register o void ShenandoahBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Address dst, Register val, Register tmp1, Register tmp2, Register tmp3) { - bool on_oop = is_reference_type(type); - if (!on_oop) { + // 1: non-reference types require no barriers + if (!is_reference_type(type)) { BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2, tmp3); return; } - // flatten object address if needed + // Flatten object address right away for simplicity: likely needed by barriers if (dst.index() == noreg && dst.offset() == 0) { if (dst.base() != tmp3) { __ mov(tmp3, dst.base()); @@ -409,20 +399,25 @@ void ShenandoahBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet __ lea(tmp3, dst); } - shenandoah_write_barrier_pre(masm, - tmp3 /* obj */, - tmp2 /* pre_val */, - rthread /* thread */, - tmp1 /* tmp */, - val != noreg /* tosca_live */, - false /* expand_call */); + bool storing_non_null = (val != noreg); + // 2: pre-barrier: SATB needs the previous value + if (ShenandoahBarrierSet::need_satb_barrier(decorators, type)) { + satb_barrier(masm, + tmp3 /* obj */, + tmp2 /* pre_val */, + rthread /* thread */, + tmp1 /* tmp */, + storing_non_null /* tosca_live */, + false /* expand_call */); + } + + // Store! BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp3, 0), val, noreg, noreg, noreg); - bool in_heap = (decorators & IN_HEAP) != 0; - bool needs_post_barrier = (val != noreg) && in_heap && ShenandoahCardBarrier; - if (needs_post_barrier) { - store_check(masm, tmp3); + // 3: post-barrier: card barrier needs store address + if (ShenandoahBarrierSet::need_card_barrier(decorators, type) && storing_non_null) { + card_barrier(masm, tmp3); } } diff --git a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp index c0e708e1292..362fcae1ccd 100644 --- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp @@ -40,23 +40,16 @@ class StubCodeGenerator; class ShenandoahBarrierSetAssembler: public BarrierSetAssembler { private: - void satb_write_barrier_pre(MacroAssembler* masm, - Register obj, - Register pre_val, - Register thread, - Register tmp1, - Register tmp2, - bool tosca_live, - bool expand_call); - void shenandoah_write_barrier_pre(MacroAssembler* masm, - Register obj, - Register pre_val, - Register thread, - Register tmp, - bool tosca_live, - bool expand_call); + void satb_barrier(MacroAssembler* masm, + Register obj, + Register pre_val, + Register thread, + Register tmp1, + Register tmp2, + bool tosca_live, + bool expand_call); - void store_check(MacroAssembler* masm, Register obj); + void card_barrier(MacroAssembler* masm, Register obj); void resolve_forward_pointer(MacroAssembler* masm, Register dst, Register tmp = noreg); void resolve_forward_pointer_not_null(MacroAssembler* masm, Register dst, Register tmp = noreg); diff --git a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp index e83ac3aa628..f1c67b0f27b 100644 --- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp @@ -181,7 +181,7 @@ void ShenandoahBarrierSetAssembler::satb_barrier(MacroAssembler* masm, bool tosca_live, bool expand_call) { assert(ShenandoahSATBBarrier, "Should be checked by caller"); - + // If expand_call is true then we expand the call_VM_leaf macro // directly to skip generating the check by // InterpreterMacroAssembler::call_VM_leaf_base that checks _last_sp. @@ -565,7 +565,7 @@ void ShenandoahBarrierSetAssembler::card_barrier(MacroAssembler* masm, Register void ShenandoahBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Address dst, Register val, Register tmp1, Register tmp2, Register tmp3) { - // 1: non-reference type, no barrier is needed + // 1: non-reference types require no barriers if (!is_reference_type(type)) { BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2, tmp3); return; @@ -573,7 +573,6 @@ void ShenandoahBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet // Flatten object address right away for simplicity: likely needed by barriers assert_different_registers(val, tmp1, tmp2, tmp3, r15_thread); - if (dst.index() == noreg && dst.disp() == 0) { if (dst.base() != tmp1) { __ movptr(tmp1, dst.base()); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp index 91c790ab875..004558a9fa8 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp @@ -78,7 +78,6 @@ bool ShenandoahBarrierSet::need_load_reference_barrier(DecoratorSet decorators, bool ShenandoahBarrierSet::need_keep_alive_barrier(DecoratorSet decorators, BasicType type) { if (!ShenandoahSATBBarrier) return false; if (!is_reference_type(type)) return false; - bool keep_alive = (decorators & AS_NO_KEEPALIVE) == 0; bool unknown = (decorators & ON_UNKNOWN_OOP_REF) != 0; bool on_weak_ref = (decorators & (ON_WEAK_OOP_REF | ON_PHANTOM_OOP_REF)) != 0; @@ -88,8 +87,9 @@ bool ShenandoahBarrierSet::need_keep_alive_barrier(DecoratorSet decorators, Basi bool ShenandoahBarrierSet::need_satb_barrier(DecoratorSet decorators, BasicType type) { if (!ShenandoahSATBBarrier) return false; if (!is_reference_type(type)) return false; - bool dest_initialized = (decorators & IS_DEST_UNINITIALIZED) == 0; - return dest_initialized; + bool as_normal = (decorators & AS_NORMAL) != 0; + bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0; + return as_normal && !dest_uninitialized; } bool ShenandoahBarrierSet::need_card_barrier(DecoratorSet decorators, BasicType type) {