From 05882095a8edd2d30201c09fb3e509ce849cb1d8 Mon Sep 17 00:00:00 2001 From: Axel Boldt-Christmas Date: Mon, 4 May 2026 05:51:18 +0000 Subject: [PATCH] 8379706: Cleanup and clarify BarrierSetAssembler::try_resolve_weak_handle_in_c2 Reviewed-by: mdoerr, fyang, amitkumar --- .../cpu/aarch64/c2_MacroAssembler_aarch64.cpp | 2 +- .../gc/shared/barrierSetAssembler_aarch64.cpp | 11 ++++----- .../gc/shared/barrierSetAssembler_aarch64.hpp | 5 +++- .../shenandoahBarrierSetAssembler_aarch64.cpp | 13 +++++----- .../shenandoahBarrierSetAssembler_aarch64.hpp | 5 ++-- .../gc/z/zBarrierSetAssembler_aarch64.cpp | 21 ++++++++-------- .../gc/z/zBarrierSetAssembler_aarch64.hpp | 3 ++- .../ppc/gc/shared/barrierSetAssembler_ppc.cpp | 7 +++--- .../ppc/gc/shared/barrierSetAssembler_ppc.hpp | 9 ++++--- .../shenandoahBarrierSetAssembler_ppc.cpp | 16 +++++++------ .../shenandoahBarrierSetAssembler_ppc.hpp | 3 ++- .../cpu/ppc/gc/z/zBarrierSetAssembler_ppc.cpp | 10 +++++--- .../cpu/ppc/gc/z/zBarrierSetAssembler_ppc.hpp | 3 ++- src/hotspot/cpu/ppc/macroAssembler_ppc.cpp | 2 +- .../cpu/riscv/c2_MacroAssembler_riscv.cpp | 2 +- .../gc/shared/barrierSetAssembler_riscv.cpp | 12 +++++----- .../gc/shared/barrierSetAssembler_riscv.hpp | 7 ++++-- .../shenandoahBarrierSetAssembler_riscv.cpp | 14 +++++------ .../shenandoahBarrierSetAssembler_riscv.hpp | 5 ++-- .../riscv/gc/z/zBarrierSetAssembler_riscv.cpp | 17 +++++++------ .../riscv/gc/z/zBarrierSetAssembler_riscv.hpp | 10 ++++---- .../gc/shared/barrierSetAssembler_s390.cpp | 7 +++--- .../gc/shared/barrierSetAssembler_s390.hpp | 8 +++---- src/hotspot/cpu/s390/macroAssembler_s390.cpp | 2 +- src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp | 2 +- .../x86/gc/shared/barrierSetAssembler_x86.cpp | 10 ++++---- .../x86/gc/shared/barrierSetAssembler_x86.hpp | 6 +++-- .../shenandoahBarrierSetAssembler_x86.cpp | 8 +++---- .../shenandoahBarrierSetAssembler_x86.hpp | 4 +--- .../cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp | 12 ++++++---- .../cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp | 4 ++-- src/hotspot/share/oops/accessDecorators.hpp | 24 +++++++++++++++---- 32 files changed, 150 insertions(+), 114 deletions(-) diff --git a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp index 3c179f21c14..67dc4966d64 100644 --- a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp @@ -265,7 +265,7 @@ void C2_MacroAssembler::fast_lock(Register obj, Register box, Register t1, // Check if object matches. ldr(t3, Address(t1_monitor, ObjectMonitor::object_offset())); BarrierSetAssembler* bs_asm = BarrierSet::barrier_set()->barrier_set_assembler(); - bs_asm->try_resolve_weak_handle_in_c2(this, t3, t2, slow_path); + bs_asm->try_peek_weak_handle_in_nmethod(this, t3, t3, t2, slow_path); cmp(t3, obj); br(Assembler::NE, slow_path); diff --git a/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp index 2a78d688097..38efcf80650 100644 --- a/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp @@ -393,6 +393,11 @@ void BarrierSetAssembler::check_oop(MacroAssembler* masm, Register obj, Register __ cbz(obj, error); // if klass is null it is broken } +void BarrierSetAssembler::try_peek_weak_handle_in_nmethod(MacroAssembler* masm, Register weak_handle, Register obj, Register tmp, Label& slow_path) { + // Load the oop from the weak handle without barriers. + __ ldr(obj, Address(weak_handle)); +} + #ifdef COMPILER2 OptoReg::Name BarrierSetAssembler::encode_float_vector_register_size(const Node* node, OptoReg::Name opto_reg) { @@ -440,12 +445,6 @@ OptoReg::Name BarrierSetAssembler::refine_register(const Node* node, OptoReg::Na return opto_reg; } - -void BarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path) { - // Load the oop from the weak handle. - __ ldr(obj, Address(obj)); -} - #undef __ #define __ _masm-> diff --git a/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.hpp index c2581b2f962..c8ed7941983 100644 --- a/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.hpp @@ -130,12 +130,15 @@ public: static void clear_patching_epoch(); static void increment_patching_epoch(); + // See AS_NO_KEEPALIVE for peek semantics + // weak_handle and obj may alias + virtual void try_peek_weak_handle_in_nmethod(MacroAssembler* masm, Register weak_handle, Register obj, Register tmp, Label& slow_path); + #ifdef COMPILER2 OptoReg::Name encode_float_vector_register_size(const Node* node, OptoReg::Name opto_reg); OptoReg::Name refine_register(const Node* node, OptoReg::Name opto_reg); - virtual void try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path); #endif // COMPILER2 }; diff --git a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp index 83c309e7257..af716b45269 100644 --- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp @@ -451,15 +451,15 @@ void ShenandoahBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler __ bind(done); } -#ifdef COMPILER2 -void ShenandoahBarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, - Register tmp, Label& slow_path) { - assert_different_registers(obj, tmp); +void ShenandoahBarrierSetAssembler::try_peek_weak_handle_in_nmethod(MacroAssembler* masm, Register weak_handle, Register obj, + Register tmp, Label& slow_path) { + assert_different_registers(weak_handle, tmp, noreg); + assert_different_registers(obj, tmp, noreg); Label done; - // Resolve weak handle using the standard implementation. - BarrierSetAssembler::try_resolve_weak_handle_in_c2(masm, obj, tmp, slow_path); + // Peek weak handle using the standard implementation. + BarrierSetAssembler::try_peek_weak_handle_in_nmethod(masm, weak_handle, obj, tmp, slow_path); // Check if the reference is null, and if it is, take the fast path. __ cbz(obj, done); @@ -473,7 +473,6 @@ void ShenandoahBarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler __ tbnz(tmp, ShenandoahHeap::WEAK_ROOTS_BITPOS, slow_path); __ bind(done); } -#endif // Special Shenandoah CAS implementation that handles false negatives due // to concurrent evacuation. The service is more complex than a diff --git a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp index d5d5ce8950e..1a56328c51e 100644 --- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp @@ -80,9 +80,8 @@ public: Address dst, Register val, Register tmp1, Register tmp2, Register tmp3); virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env, Register obj, Register tmp, Label& slowpath); -#ifdef COMPILER2 - virtual void try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path); -#endif + virtual void try_peek_weak_handle_in_nmethod(MacroAssembler* masm, Register weak_handle, Register obj, + Register tmp, Label& slow_path); void cmpxchg_oop(MacroAssembler* masm, Register addr, Register expected, Register new_val, bool acquire, bool release, bool is_cae, Register result); }; diff --git a/src/hotspot/cpu/aarch64/gc/z/zBarrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/z/zBarrierSetAssembler_aarch64.cpp index f0885fee93d..1eb96cdb6e7 100644 --- a/src/hotspot/cpu/aarch64/gc/z/zBarrierSetAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/z/zBarrierSetAssembler_aarch64.cpp @@ -1328,12 +1328,20 @@ void ZStoreBarrierStubC2Aarch64::emit_code(MacroAssembler& masm) { register_stub(this); } +#undef __ + +#endif // COMPILER2 + #undef __ #define __ masm-> -void ZBarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path) { - // Resolve weak handle using the standard implementation. - BarrierSetAssembler::try_resolve_weak_handle_in_c2(masm, obj, tmp, slow_path); +void ZBarrierSetAssembler::try_peek_weak_handle_in_nmethod(MacroAssembler* masm, Register weak_handle, Register obj, + Register tmp, Label& slow_path) { + assert_different_registers(weak_handle, tmp, noreg); + assert_different_registers(obj, tmp, noreg); + + // Peek weak handle using the standard implementation. + BarrierSetAssembler::try_peek_weak_handle_in_nmethod(masm, weak_handle, obj, tmp, slow_path); // Check if the oop is bad, in which case we need to take the slow path. __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatMarkBadBeforeMov); @@ -1345,13 +1353,6 @@ void ZBarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler* masm, R __ lsr(obj, obj, ZPointerLoadShift); } -#undef __ - -#endif // COMPILER2 - -#undef __ -#define __ masm-> - void ZBarrierSetAssembler::check_oop(MacroAssembler* masm, Register obj, Register tmp1, Register tmp2, Label& error) { // C1 calls verfy_oop in the middle of barriers, before they have been uncolored // and after being colored. Therefore, we must deal with colored oops as well. diff --git a/src/hotspot/cpu/aarch64/gc/z/zBarrierSetAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/gc/z/zBarrierSetAssembler_aarch64.hpp index fbbc5c1b517..a8fcb7696b4 100644 --- a/src/hotspot/cpu/aarch64/gc/z/zBarrierSetAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/gc/z/zBarrierSetAssembler_aarch64.hpp @@ -191,9 +191,10 @@ public: ZLoadBarrierStubC2* stub) const; void generate_c2_store_barrier_stub(MacroAssembler* masm, ZStoreBarrierStubC2* stub) const; - void try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path); #endif // COMPILER2 + void try_peek_weak_handle_in_nmethod(MacroAssembler* masm, Register weak_handle, Register obj, Register tmp, Label& slow_path); + void check_oop(MacroAssembler* masm, Register obj, Register tmp1, Register tmp2, Label& error); }; diff --git a/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp index db20439b066..7a9e29191b9 100644 --- a/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp @@ -179,9 +179,10 @@ void BarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, Re __ ld(dst, 0, dst); // Resolve (untagged) jobject. } -void BarrierSetAssembler::try_resolve_weak_handle(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path) { - // Load the oop from the weak handle. - __ ld(obj, 0, obj); +void BarrierSetAssembler::try_peek_weak_handle_in_nmethod(MacroAssembler* masm, Register weak_handle, Register obj, + Register tmp, Label& slow_path) { + // Load the oop from the weak handle without barriers. + __ ld(obj, 0, weak_handle); } void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Register tmp) { diff --git a/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp index 8112542d761..8e8c4d41c3b 100644 --- a/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp +++ b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp @@ -70,11 +70,10 @@ public: virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register dst, Register jni_env, Register obj, Register tmp, Label& slowpath); - // Can be used in nmethods including native wrappers. - // Attention: obj will only be valid until next safepoint (no SATB barrier). - // TODO: maybe rename to try_peek_weak_handle on all platforms (try: operation may fail, peek: obj is not kept alive) - // (other platforms currently use it for C2 only: try_resolve_weak_handle_in_c2) - virtual void try_resolve_weak_handle(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path); + // See AS_NO_KEEPALIVE for peek semantics + // weak_handle and obj may alias + virtual void try_peek_weak_handle_in_nmethod(MacroAssembler* masm, Register weak_handle, Register obj, + Register tmp, Label& slow_path); virtual void barrier_stubs_init() {} diff --git a/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp index 8e99d23cc99..43fd54eb78a 100644 --- a/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp @@ -663,16 +663,18 @@ void ShenandoahBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler __ block_comment("} try_resolve_jobject_in_native (shenandoahgc)"); } -void ShenandoahBarrierSetAssembler::try_resolve_weak_handle(MacroAssembler *masm, Register obj, - Register tmp, Label &slow_path) { - __ block_comment("try_resolve_weak_handle (shenandoahgc) {"); +void ShenandoahBarrierSetAssembler::try_peek_weak_handle_in_nmethod(MacroAssembler *masm, Register weak_handle, + Register obj, Register tmp, Label &slow_path) { + __ block_comment("try_peek_weak_handle_in_nmethod (shenandoahgc) {"); + + assert_different_registers(weak_handle, tmp, noreg); + assert_different_registers(obj, tmp, noreg); - assert_different_registers(obj, tmp); Label done; - // Resolve weak handle using the standard implementation. - BarrierSetAssembler::try_resolve_weak_handle(masm, obj, tmp, slow_path); + // Peek weak handle using the standard implementation. + BarrierSetAssembler::try_peek_weak_handle_in_nmethod(masm, weak_handle, obj, tmp, slow_path); // Check if the reference is null, and if it is, take the fast path. __ cmpdi(CR0, obj, 0); @@ -685,7 +687,7 @@ void ShenandoahBarrierSetAssembler::try_resolve_weak_handle(MacroAssembler *masm __ bne(CR0, slow_path); __ bind(done); - __ block_comment("} try_resolve_weak_handle (shenandoahgc)"); + __ block_comment("} try_peek_weak_handle_in_nmethod (shenandoahgc)"); } // Special shenandoah CAS implementation that handles false negatives due diff --git a/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.hpp b/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.hpp index 58180c49642..6033fbc54c4 100644 --- a/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.hpp +++ b/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.hpp @@ -123,7 +123,8 @@ public: virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register dst, Register jni_env, Register obj, Register tmp, Label& slowpath); - virtual void try_resolve_weak_handle(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path); + virtual void try_peek_weak_handle_in_nmethod(MacroAssembler* masm, Register weak_handle, Register obj, + Register tmp, Label& slow_path); }; #endif // CPU_PPC_GC_SHENANDOAH_SHENANDOAHBARRIERSETASSEMBLER_PPC_HPP diff --git a/src/hotspot/cpu/ppc/gc/z/zBarrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/z/zBarrierSetAssembler_ppc.cpp index 3e74dfb88cb..5264b284458 100644 --- a/src/hotspot/cpu/ppc/gc/z/zBarrierSetAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/z/zBarrierSetAssembler_ppc.cpp @@ -627,9 +627,13 @@ void ZBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, R __ block_comment("} try_resolve_jobject_in_native (zgc)"); } -void ZBarrierSetAssembler::try_resolve_weak_handle(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path) { - // Resolve weak handle using the standard implementation. - BarrierSetAssembler::try_resolve_weak_handle(masm, obj, tmp, slow_path); +void ZBarrierSetAssembler::try_peek_weak_handle_in_nmethod(MacroAssembler* masm, Register weak_handle, Register obj, + Register tmp, Label& slow_path) { + assert_different_registers(weak_handle, tmp, noreg); + assert_different_registers(obj, tmp, noreg); + + // Peek weak handle using the standard implementation. + BarrierSetAssembler::try_peek_weak_handle_in_nmethod(masm, weak_handle, obj, tmp, slow_path); // Check if the oop is bad, in which case we need to take the slow path. __ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatMarkBadMask); diff --git a/src/hotspot/cpu/ppc/gc/z/zBarrierSetAssembler_ppc.hpp b/src/hotspot/cpu/ppc/gc/z/zBarrierSetAssembler_ppc.hpp index 655184cf6a3..8e4bd209222 100644 --- a/src/hotspot/cpu/ppc/gc/z/zBarrierSetAssembler_ppc.hpp +++ b/src/hotspot/cpu/ppc/gc/z/zBarrierSetAssembler_ppc.hpp @@ -72,7 +72,8 @@ public: virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register dst, Register jni_env, Register obj, Register tmp, Label& slowpath); - virtual void try_resolve_weak_handle(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path); + virtual void try_peek_weak_handle_in_nmethod(MacroAssembler* masm, Register weak_handle, Register obj, + Register tmp, Label& slow_path); virtual void check_oop(MacroAssembler *masm, Register obj, const char* msg); diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp index 3efedc31d8f..24c314b8be3 100644 --- a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp @@ -2788,7 +2788,7 @@ void MacroAssembler::compiler_fast_lock_object(ConditionRegister flag, Register // Check if object matches. ld(tmp3, in_bytes(ObjectMonitor::object_offset()), monitor); BarrierSetAssembler* bs_asm = BarrierSet::barrier_set()->barrier_set_assembler(); - bs_asm->try_resolve_weak_handle(this, tmp3, tmp2, slow_path); + bs_asm->try_peek_weak_handle_in_nmethod(this, tmp3, tmp3, tmp2, slow_path); cmpd(CR0, tmp3, obj); bne(CR0, slow_path); diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp index c9cd8220551..8d383f07c9a 100644 --- a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp @@ -167,7 +167,7 @@ void C2_MacroAssembler::fast_lock(Register obj, Register box, // Check if object matches. ld(tmp3, Address(tmp1_monitor, ObjectMonitor::object_offset())); BarrierSetAssembler* bs_asm = BarrierSet::barrier_set()->barrier_set_assembler(); - bs_asm->try_resolve_weak_handle_in_c2(this, tmp3, tmp2, slow_path); + bs_asm->try_peek_weak_handle_in_nmethod(this, tmp3, tmp3, tmp2, slow_path); bne(tmp3, obj, slow_path); bind(monitor_found); diff --git a/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp index aeb9df06de6..5097d7ec58d 100644 --- a/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp @@ -354,6 +354,12 @@ void BarrierSetAssembler::check_oop(MacroAssembler* masm, Register obj, Register __ beqz(obj, error); // if klass is null it is broken } +void BarrierSetAssembler::try_peek_weak_handle_in_nmethod(MacroAssembler* masm, Register weak_handle, Register obj, + Register tmp, Label& slow_path) { + // Load the oop from the weak handle without barriers. + __ ld(obj, Address(weak_handle)); +} + #ifdef COMPILER2 OptoReg::Name BarrierSetAssembler::refine_register(const Node* node, OptoReg::Name opto_reg) { @@ -368,12 +374,6 @@ OptoReg::Name BarrierSetAssembler::refine_register(const Node* node, OptoReg::Na return opto_reg; } - -void BarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path) { - // Load the oop from the weak handle. - __ ld(obj, Address(obj)); -} - #undef __ #define __ _masm-> diff --git a/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.hpp b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.hpp index bbb2a5af824..4a14fa65e78 100644 --- a/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.hpp @@ -107,11 +107,14 @@ public: static void clear_patching_epoch(); static void increment_patching_epoch(); + // See AS_NO_KEEPALIVE for peek semantics + // weak_handle and obj may alias + virtual void try_peek_weak_handle_in_nmethod(MacroAssembler* masm, Register weak_handle, Register obj, + Register tmp, Label& slow_path); + #ifdef COMPILER2 OptoReg::Name refine_register(const Node* node, OptoReg::Name opto_reg); - virtual void try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, - Register tmp, Label& slow_path); #endif // COMPILER2 }; diff --git a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp index e900d9ac1a8..64d83082f20 100644 --- a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp @@ -462,15 +462,16 @@ void ShenandoahBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler __ bind(done); } -#ifdef COMPILER2 -void ShenandoahBarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler *masm, Register obj, - Register tmp, Label& slow_path) { - assert_different_registers(obj, tmp); +void ShenandoahBarrierSetAssembler::try_peek_weak_handle_in_nmethod(MacroAssembler *masm, Register weak_handle, + Register obj, Register tmp, Label& slow_path) { + assert_different_registers(weak_handle, tmp, noreg); + assert_different_registers(obj, tmp, noreg); + Label done; - // Resolve weak handle using the standard implementation. - BarrierSetAssembler::try_resolve_weak_handle_in_c2(masm, obj, tmp, slow_path); + // Peek weak handle using the standard implementation. + BarrierSetAssembler::try_peek_weak_handle_in_nmethod(masm, weak_handle, obj, tmp, slow_path); // Check if the reference is null, and if it is, take the fast path. __ beqz(obj, done); @@ -484,7 +485,6 @@ void ShenandoahBarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler __ bnez(tmp, slow_path); __ bind(done); } -#endif // Special Shenandoah CAS implementation that handles false negatives due // to concurrent evacuation. The service is more complex than a diff --git a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.hpp b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.hpp index e35e09c93da..5cfd500f7a6 100644 --- a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.hpp @@ -85,9 +85,8 @@ public: virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env, Register obj, Register tmp, Label& slowpath); -#ifdef COMPILER2 - virtual void try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path); -#endif + virtual void try_peek_weak_handle_in_nmethod(MacroAssembler* masm, Register weak_handle, Register obj, + Register tmp, Label& slow_path); void cmpxchg_oop(MacroAssembler* masm, Register addr, Register expected, Register new_val, Assembler::Aqrl acquire, Assembler::Aqrl release, bool is_cae, Register result); }; diff --git a/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.cpp index 1b4e522973b..bf37ccf64e2 100644 --- a/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.cpp @@ -602,12 +602,16 @@ void ZBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, BLOCK_COMMENT("} ZBarrierSetAssembler::try_resolve_jobject_in_native"); } -#ifdef COMPILER2 -void ZBarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path) { - BLOCK_COMMENT("ZBarrierSetAssembler::try_resolve_weak_handle_in_c2 {"); +void ZBarrierSetAssembler::try_peek_weak_handle_in_nmethod(MacroAssembler* masm, Register weak_handle, Register obj, + Register tmp, Label& slow_path) { + BLOCK_COMMENT("ZBarrierSetAssembler::try_peek_weak_handle_in_nmethod {"); - // Resolve weak handle using the standard implementation. - BarrierSetAssembler::try_resolve_weak_handle_in_c2(masm, obj, tmp, slow_path); + assert_different_registers(weak_handle, tmp, noreg); + assert_different_registers(obj, tmp, noreg); + + + // Peek weak handle using the standard implementation. + BarrierSetAssembler::try_peek_weak_handle_in_nmethod(masm, weak_handle, obj, tmp, slow_path); // Check if the oop is bad, in which case we need to take the slow path. __ relocate(barrier_Relocation::spec(), [&] { @@ -619,9 +623,8 @@ void ZBarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler* masm, R // Oop is okay, so we uncolor it. __ srli(obj, obj, ZPointerLoadShift); - BLOCK_COMMENT("} ZBarrierSetAssembler::try_resolve_weak_handle_in_c2"); + BLOCK_COMMENT("} ZBarrierSetAssembler::try_peek_weak_handle_in_nmethod"); } -#endif static uint16_t patch_barrier_relocation_value(int format) { switch (format) { diff --git a/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.hpp b/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.hpp index 648cb3bf63d..f99df299a77 100644 --- a/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.hpp @@ -170,12 +170,14 @@ public: ZLoadBarrierStubC2* stub) const; void generate_c2_store_barrier_stub(MacroAssembler* masm, ZStoreBarrierStubC2* stub) const; - void try_resolve_weak_handle_in_c2(MacroAssembler* masm, - Register obj, - Register tmp, - Label& slow_path); #endif // COMPILER2 + void try_peek_weak_handle_in_nmethod(MacroAssembler* masm, + Register weak_handle, + Register obj, + Register tmp, + Label& slow_path); + void check_oop(MacroAssembler* masm, Register obj, Register tmp1, Register tmp2, Label& error); }; diff --git a/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp b/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp index 9fac231df47..9a401766200 100644 --- a/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp @@ -169,9 +169,10 @@ void BarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, Re __ z_lg(obj, 0, obj); // Resolve (untagged) jobject. } -void BarrierSetAssembler::try_resolve_weak_handle(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path) { - // Load the oop from the weak handle. - __ z_lg(obj, Address(obj)); +void BarrierSetAssembler::try_peek_weak_handle_in_nmethod(MacroAssembler* masm, Register weak_handle, Register obj, + Register tmp, Label& slow_path) { + // Load the oop from the weak handle without barriers. + __ z_lg(obj, Address(weak_handle)); } void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm) { diff --git a/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.hpp b/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.hpp index 8e76ec2f4b4..6c729528a67 100644 --- a/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.hpp +++ b/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.hpp @@ -58,10 +58,10 @@ public: virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env, Register obj, Register tmp, Label& slowpath); - // Can be used in nmethods including native wrappers. - // Attention: obj will only be valid until next safepoint (no SATB barrier). - // (other platforms currently use it for C2 only: try_resolve_weak_handle_in_c2) - virtual void try_resolve_weak_handle(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path); + // See AS_NO_KEEPALIVE for peek semantics + // weak_handle and obj may alias + virtual void try_peek_weak_handle_in_nmethod(MacroAssembler* masm, Register weak_handle, Register obj, + Register tmp, Label& slow_path); virtual void nmethod_entry_barrier(MacroAssembler* masm); diff --git a/src/hotspot/cpu/s390/macroAssembler_s390.cpp b/src/hotspot/cpu/s390/macroAssembler_s390.cpp index b5898648014..4d2bbe796fb 100644 --- a/src/hotspot/cpu/s390/macroAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/macroAssembler_s390.cpp @@ -6395,7 +6395,7 @@ void MacroAssembler::compiler_fast_lock_object(Register obj, Register box, Regis // Check if object matches. z_lg(tmp2, Address(tmp1_monitor, ObjectMonitor::object_offset())); BarrierSetAssembler* bs_asm = BarrierSet::barrier_set()->barrier_set_assembler(); - bs_asm->try_resolve_weak_handle(this, tmp2, Z_R0_scratch, slow_path); + bs_asm->try_peek_weak_handle_in_nmethod(this, tmp2, tmp2, Z_R0_scratch, slow_path); z_cgr(obj, tmp2); z_brne(slow_path); diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp index e164ee37edf..3c4659934c6 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp @@ -336,7 +336,7 @@ void C2_MacroAssembler::fast_lock(Register obj, Register box, Register rax_reg, // Check if object matches. movptr(rax_reg, Address(monitor, ObjectMonitor::object_offset())); BarrierSetAssembler* bs_asm = BarrierSet::barrier_set()->barrier_set_assembler(); - bs_asm->try_resolve_weak_handle_in_c2(this, rax_reg, slow_path); + bs_asm->try_peek_weak_handle_in_nmethod(this, rax_reg, rax_reg, slow_path); cmpptr(rax_reg, obj); jcc(Assembler::notEqual, slow_path); diff --git a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp index 215dc30f7fd..731eef09c37 100644 --- a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp @@ -362,6 +362,11 @@ void BarrierSetAssembler::check_oop(MacroAssembler* masm, Register obj, Register __ jcc(Assembler::zero, error); // if klass is null it is broken } +void BarrierSetAssembler::try_peek_weak_handle_in_nmethod(MacroAssembler* masm, Register weak_handle, Register obj, Label& slowpath) { + // Load the oop from the weak handle without barriers. + __ movptr(obj, Address(weak_handle)); +} + #ifdef COMPILER2 OptoReg::Name BarrierSetAssembler::refine_register(const Node* node, OptoReg::Name opto_reg) { @@ -395,11 +400,6 @@ OptoReg::Name BarrierSetAssembler::refine_register(const Node* node, OptoReg::Na extern void vec_spill_helper(C2_MacroAssembler *masm, bool is_load, int stack_offset, int reg, uint ireg, outputStream* st); -void BarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Label& slowpath) { - // Load the oop from the weak handle. - __ movptr(obj, Address(obj)); -} - #undef __ #define __ _masm-> diff --git a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.hpp b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.hpp index 6aff29850e3..caf341dcdf3 100644 --- a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.hpp @@ -106,11 +106,13 @@ public: virtual void check_oop(MacroAssembler* masm, Register obj, Register tmp1, Register tmp2, Label& error); + // See AS_NO_KEEPALIVE for peek semantics + // weak_handle and obj may alias + virtual void try_peek_weak_handle_in_nmethod(MacroAssembler* masm, Register weak_handle, Register obj, Label& slowpath); + #ifdef COMPILER2 OptoReg::Name refine_register(const Node* node, OptoReg::Name opto_reg); - - virtual void try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Label& slowpath); #endif // COMPILER2 }; diff --git a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp index 7d92bfab2fe..0d7f90bccdb 100644 --- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp @@ -630,12 +630,11 @@ void ShenandoahBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler __ bind(done); } -#ifdef COMPILER2 -void ShenandoahBarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Label& slowpath) { +void ShenandoahBarrierSetAssembler::try_peek_weak_handle_in_nmethod(MacroAssembler* masm, Register weak_handle, Register obj, Label& slowpath) { Label done; - // Resolve weak handle using the standard implementation. - BarrierSetAssembler::try_resolve_weak_handle_in_c2(masm, obj, slowpath); + // Peek weak handle using the standard implementation. + BarrierSetAssembler::try_peek_weak_handle_in_nmethod(masm, weak_handle, obj, slowpath); // Check if the reference is null, and if it is, take the fast path. __ testptr(obj, obj); @@ -649,7 +648,6 @@ void ShenandoahBarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler __ jcc(Assembler::notZero, slowpath); __ bind(done); } -#endif // COMPILER2 // Special Shenandoah CAS implementation that handles false negatives // due to concurrent evacuation. diff --git a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp index 79540aa19e1..74e52d57c09 100644 --- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.hpp @@ -78,9 +78,7 @@ public: Address dst, Register val, Register tmp1, Register tmp2, Register tmp3); virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env, Register obj, Register tmp, Label& slowpath); -#ifdef COMPILER2 - virtual void try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Label& slowpath); -#endif // COMPILER2 + virtual void try_peek_weak_handle_in_nmethod(MacroAssembler* masm, Register weak_handle, Register obj, Label& slowpath); }; #endif // CPU_X86_GC_SHENANDOAH_SHENANDOAHBARRIERSETASSEMBLER_X86_HPP diff --git a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp index c20551b5084..8381881ed38 100644 --- a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp @@ -1329,9 +1329,14 @@ void ZBarrierSetAssembler::generate_c2_store_barrier_stub(MacroAssembler* masm, __ jmp(slow_continuation); } -void ZBarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Label& slow_path) { - // Resolve weak handle using the standard implementation. - BarrierSetAssembler::try_resolve_weak_handle_in_c2(masm, obj, slow_path); +#undef __ +#endif // COMPILER2 + +#define __ masm-> + +void ZBarrierSetAssembler::try_peek_weak_handle_in_nmethod(MacroAssembler* masm, Register weak_handle, Register obj, Label& slow_path) { + // Peek weak handle using the standard implementation. + BarrierSetAssembler::try_peek_weak_handle_in_nmethod(masm, weak_handle, obj, slow_path); // Check if the oop is bad, in which case we need to take the slow path. __ testptr(obj, Address(r15_thread, ZThreadLocalData::mark_bad_mask_offset())); @@ -1343,7 +1348,6 @@ void ZBarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler* masm, R } #undef __ -#endif // COMPILER2 static int patch_barrier_relocation_offset(int format) { switch (format) { diff --git a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp index ce0c4769716..476a316b2e1 100644 --- a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp @@ -167,10 +167,10 @@ public: ZLoadBarrierStubC2* stub) const; void generate_c2_store_barrier_stub(MacroAssembler* masm, ZStoreBarrierStubC2* stub) const; - - virtual void try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Label& slow_path); #endif // COMPILER2 + virtual void try_peek_weak_handle_in_nmethod(MacroAssembler* masm, Register weak_handle, Register obj, Label& slow_path); + void store_barrier_fast(MacroAssembler* masm, Address ref_addr, Register rnew_persistent, diff --git a/src/hotspot/share/oops/accessDecorators.hpp b/src/hotspot/share/oops/accessDecorators.hpp index bbf5cd8722e..852b7ecddd4 100644 --- a/src/hotspot/share/oops/accessDecorators.hpp +++ b/src/hotspot/share/oops/accessDecorators.hpp @@ -138,10 +138,26 @@ const DecoratorSet MO_DECORATOR_MASK = MO_UNORDERED | MO_RELAXED | // - Accesses on HeapWord* translate to a runtime check choosing one of the above // - Accesses on other types translate to raw memory accesses without runtime checks // * AS_NO_KEEPALIVE: The barrier is used only on oop references and will not keep any involved objects -// alive, regardless of the type of reference being accessed. It will however perform the memory access -// in a consistent way w.r.t. e.g. concurrent compaction, so that the right field is being accessed, -// or maintain, e.g. intergenerational or interregional pointers if applicable. This should be used with -// extreme caution in isolated scopes. +// alive, regardless of the type of reference being accessed. This should be used with extreme caution +// in isolated scopes. +// AS_NO_KEEPALIVE stores are currently used primarily by the VM implementation of java.lang.ref.Reference +// and reference processing. AS_NO_KEEPALIVE loads have broader use, e.g. VM / serviceability introspection, +// printing, liveness checks, and weak (hash) table lookups. +// AS_NO_KEEPALIVE does not establish liveness for the current GC cycle. The oop returned by such +// a load, and any oop reached only by traversing from it, must not be stored as a new oop edge into +// GC-visible state (GC roots and the object graph). For SATB marking, violating this rule breaks +// the snapshot invariant. This includes, but is not limited to: +// - object graph storage (e.g. static and non-static Object fields, Object array elements) +// - local root storage (e.g. Handles, OopMap/GC-tracked frame / register slots) +// - other root storage (e.g. OopHandles, WeakHandles, nmethod and class metadata) +// Before such an oop is stored into GC-visible state, liveness must first be explicitly re-established, +// for example by: +// - re-resolving without AS_NO_KEEPALIVE +// - using CollectedHeap::keep_alive(oop) +// Related special case: for CLD-owned OopHandles (notably java mirrors), loading the oop does not +// keep the owning CLD / Klass alive. In those cases, a plain resolve() is insufficient; use the corresponding +// owner keep-alive helper (e.g. Klass::keep_alive()) or CollectedHeap::keep_alive(oop), or have some +// other guarantee of liveness before storing the oop into GC-visible state. // * AS_NORMAL: The accesses will be resolved to an accessor on the BarrierSet class, giving the // responsibility of performing the access and what barriers to be performed to the GC. This is the default. // Note that primitive accesses will only be resolved on the barrier set if the appropriate build-time