[GR-78989] Generational Shenandoah fix: Skip card mark for off-heap stores - #14300
Merged
Conversation
Generational Shenandoah crashed with SIGSEGV/SIGBUS in Graal compiled code when storing an oop into the contents of an OopHandle, such as the store emitted by the Thread.setScopedValueCache intrinsic. HotSpotShenandoahBarrierSet.writeBarrierType() answers BarrierType.FIELD for an OopHandleLocationIdentity so that the SATB pre barrier is emitted, but ShenandoahBarrierSet.addWriteBarriers() then attached a card barrier unconditionally. An OopHandle's contents live in a native OopStorage rather than in the Java heap, so the card address computed as card_table_base + (store_address >> card_shift) lands outside the card table. The card write then silently corrupts unrelated memory, or faults when the page it hits happens to be read only. Gate the card barrier on a new overridable isInHeap() predicate. This mirrors HotSpot, which gates the card barrier on the IN_HEAP decorator via ShenandoahBarrierSet::need_card_barrier and splits oop_store_in_heap from oop_store_not_in_heap. The SATB pre barrier is retained, matching oop_store_not_in_heap. Other collectors were unaffected: G1 does not override writeBarrierType(LocationIdentity) and so emits no barrier here at all, while ZGC carries the off-heap distinction down to its LIR generators as StoreKind.Native. Also pass 32 rather than 8 as the cbz operand size in the AArch64 card barrier op. cbz has no 8 bit form and asserted on every conditional card mark. With assertions disabled the encoder falls back to a 32 bit cbz, which is accidentally correct because the preceding ldrb zero extends, so this is benign in a product build but makes the path impossible to exercise in an assertion enabled build. It is a prerequisite for the in-heap case of the test added here. Add ShenandoahOopHandleBarrierTest, asserting that an OopHandle oop store keeps its SATB pre barrier and is not card marked, and that an ordinary in-heap oop store still is. Two notes for anyone extending it: Shenandoah inserts barriers in the low tier, so the verification phase hooks LOW_TIER_BARRIER_ADDITION rather than the mid tier used by the card table collectors, and barriers are matched by address rather than by graph adjacency because PublishWrites can sit between a write and its barriers. Verified on aarch64 with a ScopedValue stress reproducer that drives first-time ScopedValue.get() calls on freshly created threads. Unpatched it crashes within a second; patched it survives 271M virtual thread and 1.8M platform thread iterations, including under -XX:+ShenandoahVerify, which also validates remembered set integrity. The new test fails without the isInHeap() gate and passes with it. jdk.graal.compiler.hotspot.test passes 23603 tests under -XX:ShenandoahGCMode=generational, where the cbz assertion previously prevented compiling any in-heap oop store.
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
#14239
Generational Shenandoah crashed with SIGSEGV/SIGBUS in Graal-compiled code when storing an oop into the contents of an OopHandle, such as the store performed by the Thread.setScopedValueCache intrinsic.
This is analogous to the
StoreKind.Naitvehandling in ZGC.