diff --git a/src/hotspot/share/c1/c1_GraphBuilder.cpp b/src/hotspot/share/c1/c1_GraphBuilder.cpp index f910ecadc164a..db7722ff09004 100644 --- a/src/hotspot/share/c1/c1_GraphBuilder.cpp +++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp @@ -3560,6 +3560,14 @@ const char* GraphBuilder::check_can_parse(ciMethod* callee) const { const char* GraphBuilder::should_not_inline(ciMethod* callee) const { if ( compilation()->directive()->should_not_inline(callee)) return "disallowed by CompileCommand"; if ( callee->dont_inline()) return "don't inline by annotation"; + + // Don't inline a method that changes Thread.currentThread() except + // into another method that is annotated @ChangesCurrentThread. + if (callee->changes_current_thread() + && !compilation()->method()->changes_current_thread()) { + return "method changes current thread"; + } + return nullptr; } diff --git a/src/hotspot/share/c1/c1_LIRGenerator.cpp b/src/hotspot/share/c1/c1_LIRGenerator.cpp index f6807abcd7acd..ea29940daf66f 100644 --- a/src/hotspot/share/c1/c1_LIRGenerator.cpp +++ b/src/hotspot/share/c1/c1_LIRGenerator.cpp @@ -1379,7 +1379,14 @@ void LIRGenerator::do_JavaThreadField(Intrinsic* x, ByteSize offset) { LIR_Opr temp = new_register(T_ADDRESS); LIR_Opr reg = rlock_result(x); __ move(new LIR_Address(getThreadPointer(), in_bytes(offset), T_ADDRESS), temp); - access_load(IN_NATIVE, T_OBJECT, + // OopHandle stores uncompressed oops in native memory. + // Use IN_NATIVE to ensure a raw 64-bit load without compressed oop handling. + // Use MO_ACQUIRE so that subsequent loads (e.g. Thread.cont used by + // Continuation.yield) cannot float above this load on weakly-ordered + // architectures such as AArch64. Without acquire semantics the hardware + // may reorder a later field load before the OopHandle dereference, + // observing a stale value after a virtual thread migrates between carriers. + access_load(IN_NATIVE | MO_ACQUIRE, T_OBJECT, LIR_OprFact::address(new LIR_Address(temp, T_OBJECT)), reg); } diff --git a/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp b/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp index a31078f7e6790..b4ad8f9a29f55 100644 --- a/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp +++ b/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp @@ -179,6 +179,7 @@ void BarrierSetC1::load_at_resolved(LIRAccess& access, LIR_Opr result) { LIRGenerator *gen = access.gen(); DecoratorSet decorators = access.decorators(); bool is_volatile = (decorators & MO_SEQ_CST) != 0; + bool is_acquire = (decorators & MO_ACQUIRE) != 0; bool needs_atomic = AlwaysAtomicAccesses && !access_is_atomic(result->type()); bool needs_patching = (decorators & C1_NEEDS_PATCHING) != 0; bool mask_boolean = (decorators & C1_MASK_BOOLEAN) != 0; @@ -197,7 +198,7 @@ void BarrierSetC1::load_at_resolved(LIRAccess& access, LIR_Opr result) { __ load(access.resolved_addr()->as_address_ptr(), result, access.access_emit_info(), patch_code); } - if (is_volatile) { + if (is_volatile || is_acquire) { __ membar_acquire(); } diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index 3627d06a87a2d..966a8fb7e5e0f 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -1000,7 +1000,14 @@ Node* LibraryCallKit::current_thread_helper(Node*& tls_output, ByteSize handle_o : make_load(nullptr, p, p->bottom_type()->is_ptr(), T_ADDRESS, MemNode::unordered)); thread_obj_handle = _gvn.transform(thread_obj_handle); - DecoratorSet decorators = IN_NATIVE; + // OopHandle stores uncompressed oops in native memory. + // Use IN_NATIVE to ensure proper handling without compressed oop decoding. + // Use MO_ACQUIRE so that subsequent loads (e.g. Thread.cont used by + // Continuation.yield) cannot float above this load on weakly-ordered + // architectures such as AArch64. Without acquire semantics the hardware + // may reorder a later field load before the OopHandle dereference, + // observing a stale value after a virtual thread migrates between carriers. + DecoratorSet decorators = IN_NATIVE | MO_ACQUIRE; if (is_immutable) { decorators |= C2_IMMUTABLE_MEMORY; } diff --git a/src/java.base/share/classes/jdk/internal/vm/Continuation.java b/src/java.base/share/classes/jdk/internal/vm/Continuation.java index a7eb3ea6a9fa5..147cdaaae6fd5 100644 --- a/src/java.base/share/classes/jdk/internal/vm/Continuation.java +++ b/src/java.base/share/classes/jdk/internal/vm/Continuation.java @@ -342,6 +342,7 @@ private boolean isEmpty() { * @throws IllegalStateException if not currently in the given {@code scope}, */ @Hidden + @DontInline @JvmtiHideEvents public static boolean yield(ContinuationScope scope) { Continuation cont = JLA.getContinuation(currentCarrierThread());