Skip to content

Commit 9f2c78d

Browse files
committed
Shenandoah support
1 parent 381adbb commit 9f2c78d

28 files changed

+2077
-13
lines changed

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/phases/EconomyLowTier.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import jdk.graal.compiler.phases.common.LowTierLoweringPhase;
3737
import jdk.graal.compiler.phases.common.RemoveOpaqueValuePhase;
3838
import jdk.graal.compiler.phases.common.TransplantGraphsPhase;
39+
import jdk.graal.compiler.phases.common.WriteBarrierAdditionPhase;
3940
import jdk.graal.compiler.phases.schedule.SchedulePhase;
4041
import jdk.graal.compiler.phases.tiers.LowTierContext;
4142

@@ -50,6 +51,8 @@ public EconomyLowTier(OptionValues options) {
5051
appendPhase(new LowTierLoweringPhase(canonicalizer));
5152
appendPhase(new ExpandLogicPhase(canonicalizer));
5253

54+
appendPhase(new WriteBarrierAdditionPhase());
55+
5356
if (Assertions.assertionsEnabled()) {
5457
appendPhase(new BarrierSetVerificationPhase());
5558
}

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/phases/EconomyMidTier.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
import jdk.graal.compiler.phases.common.LoopSafepointInsertionPhase;
3131
import jdk.graal.compiler.phases.common.MidTierLoweringPhase;
3232
import jdk.graal.compiler.phases.common.RemoveValueProxyPhase;
33-
import jdk.graal.compiler.phases.common.WriteBarrierAdditionPhase;
3433
import jdk.graal.compiler.phases.tiers.MidTierContext;
3534

3635
public class EconomyMidTier extends BaseTier<MidTierContext> {
@@ -44,6 +43,5 @@ public EconomyMidTier() {
4443
appendPhase(new MidTierLoweringPhase(canonicalizer));
4544
appendPhase(new FrameStateAssignmentPhase());
4645
appendPhase(canonicalizer);
47-
appendPhase(new WriteBarrierAdditionPhase());
4846
}
4947
}

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/phases/LowTier.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import jdk.graal.compiler.phases.common.PropagateDeoptimizeProbabilityPhase;
4848
import jdk.graal.compiler.phases.common.RemoveOpaqueValuePhase;
4949
import jdk.graal.compiler.phases.common.TransplantGraphsPhase;
50+
import jdk.graal.compiler.phases.common.WriteBarrierAdditionPhase;
5051
import jdk.graal.compiler.phases.schedule.SchedulePhase;
5152
import jdk.graal.compiler.phases.schedule.SchedulePhase.SchedulingStrategy;
5253
import jdk.graal.compiler.phases.tiers.LowTierContext;
@@ -87,6 +88,8 @@ public LowTier(OptionValues options) {
8788
appendPhase(new FixReadsPhase(true,
8889
new SchedulePhase(GraalOptions.StressTestEarlyReads.getValue(options) ? SchedulingStrategy.EARLIEST : SchedulingStrategy.LATEST_OUT_OF_LOOPS_IMPLICIT_NULL_CHECKS)));
8990

91+
appendPhase(new WriteBarrierAdditionPhase());
92+
9093
appendPhase(canonicalizerWithoutGVN);
9194

9295
/*

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/phases/MidTier.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@
4848
import jdk.graal.compiler.phases.common.ReassociationPhase;
4949
import jdk.graal.compiler.phases.common.RemoveValueProxyPhase;
5050
import jdk.graal.compiler.phases.common.VerifyHeapAtReturnPhase;
51-
import jdk.graal.compiler.phases.common.WriteBarrierAdditionPhase;
5251
import jdk.graal.compiler.phases.tiers.MidTierContext;
5352

5453
public class MidTier extends BaseTier<MidTierContext> {
@@ -122,8 +121,6 @@ public MidTier(OptionValues options) {
122121
}
123122

124123
appendPhase(canonicalizer);
125-
126-
appendPhase(new WriteBarrierAdditionPhase());
127124
}
128125

129126
@Override

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,14 @@ public int threadLastJavaFpOffset() {
436436
public final int g1CardQueueBufferOffset = getConstant("G1ThreadLocalData::dirty_card_queue_buffer_offset", Integer.class, -1, !g1LowLatencyPostWriteBarrierSupport);
437437
public final int g1CardTableBaseOffset = getConstant("G1ThreadLocalData::card_table_base_offset", Integer.class, -1, g1LowLatencyPostWriteBarrierSupport);
438438

439+
public final boolean hasShenandoahGC = getStore().getConstants().containsKey("INCLUDE_SHENANDOAHGC") && getConstant("INCLUDE_SHENANDOAHGC", Boolean.class);
440+
public final int shenandoahGCStateOffset = getConstant("ShenandoahThreadLocalData::gc_state_offset", Integer.class, -1, hasShenandoahGC);
441+
public final int shenandoahSATBIndexOffset = getConstant("ShenandoahThreadLocalData::satb_mark_queue_index_offset", Integer.class, -1, hasShenandoahGC);
442+
public final int shenandoahSATBBufferOffset = getConstant("ShenandoahThreadLocalData::satb_mark_queue_buffer_offset", Integer.class, -1, hasShenandoahGC);
443+
public final int shenandoahCardTableOffset = getConstant("ShenandoahThreadLocalData::card_table_offset", Integer.class, -1, hasShenandoahGC);
444+
public final int shenandoahGCRegionSizeBytesShift = getFieldValue("CompilerToVM::Data::shenandoah_region_size_bytes_shift", Integer.class, "int", -1, hasShenandoahGC);
445+
public final long shenandoahGCCSetFastTestAddress = getFieldValue("CompilerToVM::Data::shenandoah_in_cset_fast_test_addr", Long.class, "address", -1L, hasShenandoahGC);
446+
439447
public final int klassOffset = getFieldValue("java_lang_Class::_klass_offset", Integer.class, "int");
440448
public final int arrayKlassOffset = getFieldValue("java_lang_Class::_array_klass_offset", Integer.class, "int");
441449

@@ -619,6 +627,14 @@ private long getZGCAddressField(String name) {
619627
public final long zBarrierSetRuntimeLoadBarrierOnOopArray = getZGCAddressField("ZBarrierSetRuntime::load_barrier_on_oop_array");
620628
public final int zPointerLoadShift = getConstant("ZPointerLoadShift", Integer.class, -1, osArch.equals("aarch64") && zgcSupport);
621629

630+
public final long shenandoahLoadBarrierStrong = getAddress("ShenandoahRuntime::load_reference_barrier_strong", -1L, hasShenandoahGC);
631+
public final long shenandoahLoadBarrierStrongNarrow = getAddress("ShenandoahRuntime::load_reference_barrier_strong_narrow", -1L, hasShenandoahGC);
632+
public final long shenandoahLoadBarrierWeak = getAddress("ShenandoahRuntime::load_reference_barrier_weak", -1L, hasShenandoahGC);
633+
public final long shenandoahLoadBarrierWeakNarrow = getAddress("ShenandoahRuntime::load_reference_barrier_weak_narrow", -1L, hasShenandoahGC);
634+
public final long shenandoahLoadBarrierPhantom = getAddress("ShenandoahRuntime::load_reference_barrier_phantom", -1L, hasShenandoahGC);
635+
public final long shenandoahLoadBarrierPhantomNarrow = getAddress("ShenandoahRuntime::load_reference_barrier_phantom_narrow", -1L, hasShenandoahGC);
636+
public final long shenandoahWriteBarrierPre = getAddress("ShenandoahRuntime::write_barrier_pre", -1L, hasShenandoahGC);
637+
622638
// aarch64 specific nmethod entry barrier support
623639
// @formatter:off
624640
public final int BarrierSetAssembler_nmethod_patching_type = getFieldValue("CompilerToVM::Data::BarrierSetAssembler_nmethod_patching_type", Integer.class, "int", -1, osArch.equals("aarch64"));

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactory.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,8 @@ private BarrierSet createBarrierSet(GraalHotSpotVMConfig config, MetaAccessProvi
259259
ResolvedJavaField referentField = HotSpotReplacementsUtil.referentField(metaAccess);
260260
if (config.gc == HotSpotGraalRuntime.HotSpotGC.Z) {
261261
return new HotSpotZBarrierSet(objectArrayType, referentField);
262+
} else if (config.gc == HotSpotGraalRuntime.HotSpotGC.Shenandoah) {
263+
return new HotSpotShenandoahBarrierSet(objectArrayType, referentField, config);
262264
} else if (config.gc == HotSpotGraalRuntime.HotSpotGC.Epsilon) {
263265
return new NoBarrierSet();
264266
} else if (config.useG1GC()) {

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalRuntime.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,9 +209,7 @@ public enum HotSpotGC {
209209
G1("UseG1GC"),
210210
Z(true, true, flagIsSet("UseZGC")),
211211
Epsilon(true, true, flagIsSet("UseEpsilonGC")),
212-
213-
// Unsupported GCs
214-
Shenandoah(false, true, flagIsSet("UseShenandoahGC"));
212+
Shenandoah(true, true, flagIsSet("UseShenandoahGC"));
215213

216214
HotSpotGC(String flag) {
217215
this(true, true, flagIsSet(flag));
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package jdk.graal.compiler.hotspot;
26+
27+
import jdk.graal.compiler.core.common.CompressEncoding;
28+
import jdk.graal.compiler.hotspot.nodes.HotSpotCompressionNode;
29+
import org.graalvm.word.LocationIdentity;
30+
31+
import jdk.graal.compiler.core.common.memory.BarrierType;
32+
import jdk.graal.compiler.core.common.type.AbstractObjectStamp;
33+
import jdk.graal.compiler.core.common.type.Stamp;
34+
import jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil;
35+
import jdk.graal.compiler.nodes.ValueNode;
36+
import jdk.graal.compiler.nodes.gc.shenandoah.ShenandoahBarrierSet;
37+
import jdk.vm.ci.meta.JavaKind;
38+
import jdk.vm.ci.meta.ResolvedJavaField;
39+
import jdk.vm.ci.meta.ResolvedJavaType;
40+
41+
/**
42+
* Specialization of {@link ShenandoahBarrierSet} that adds support for read barriers on handle
43+
* locations.
44+
*/
45+
public class HotSpotShenandoahBarrierSet extends ShenandoahBarrierSet {
46+
private CompressEncoding oopEncoding;
47+
48+
public HotSpotShenandoahBarrierSet(ResolvedJavaType objectArrayType, ResolvedJavaField referentField, GraalHotSpotVMConfig config) {
49+
super(objectArrayType, referentField);
50+
this.oopEncoding = config.getOopEncoding();
51+
this.useLoadRefBarrier = config.getFlag("ShenandoahLoadRefBarrier", Boolean.class);
52+
this.useSATBBarrier = config.getFlag("ShenandoahSATBBarrier", Boolean.class);
53+
this.useCASBarrier = config.getFlag("ShenandoahCASBarrier", Boolean.class);
54+
this.useCardBarrier = config.getFlag("ShenandoahCardBarrier", Boolean.class);
55+
}
56+
57+
@Override
58+
protected BarrierType barrierForLocation(BarrierType currentBarrier, LocationIdentity location, JavaKind storageKind) {
59+
if (location instanceof HotSpotReplacementsUtil.OopHandleLocationIdentity) {
60+
return BarrierType.READ;
61+
}
62+
return super.barrierForLocation(currentBarrier, location, storageKind);
63+
}
64+
65+
@Override
66+
public BarrierType readBarrierType(LocationIdentity location, ValueNode address, Stamp loadStamp) {
67+
if (location instanceof HotSpotReplacementsUtil.OopHandleLocationIdentity) {
68+
assert loadStamp instanceof AbstractObjectStamp : loadStamp;
69+
return BarrierType.READ;
70+
}
71+
return super.readBarrierType(location, address, loadStamp);
72+
}
73+
74+
@Override
75+
public BarrierType writeBarrierType(LocationIdentity location) {
76+
if (location instanceof HotSpotReplacementsUtil.OopHandleLocationIdentity) {
77+
return BarrierType.FIELD;
78+
}
79+
return BarrierType.NONE;
80+
}
81+
82+
@Override
83+
protected ValueNode maybeUncompressReference(ValueNode value, boolean narrow) {
84+
if (value != null && narrow) {
85+
return HotSpotCompressionNode.uncompressWithoutUnique(value.graph(), value, oopEncoding);
86+
}
87+
return value;
88+
}
89+
90+
@Override
91+
protected ValueNode maybeCompressReference(ValueNode value, boolean narrow) {
92+
if (value != null && narrow) {
93+
return HotSpotCompressionNode.compressWithoutUnique(value.graph(), value, oopEncoding);
94+
}
95+
return value;
96+
}
97+
}

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
import jdk.graal.compiler.hotspot.HotSpotLIRGenerator;
6363
import jdk.graal.compiler.hotspot.HotSpotLockStack;
6464
import jdk.graal.compiler.hotspot.aarch64.g1.AArch64HotSpotG1BarrierSetLIRTool;
65+
import jdk.graal.compiler.hotspot.aarch64.shenandoah.AArch64HotSpotShenandoahBarrierSetLIRGenerator;
6566
import jdk.graal.compiler.hotspot.aarch64.z.AArch64HotSpotZBarrierSetLIRGenerator;
6667
import jdk.graal.compiler.hotspot.debug.BenchmarkCounters;
6768
import jdk.graal.compiler.hotspot.meta.HotSpotProviders;
@@ -119,6 +120,9 @@ protected static BarrierSetLIRGeneratorTool getBarrierSet(GraalHotSpotVMConfig c
119120
if (config.gc == HotSpotGraalRuntime.HotSpotGC.Z) {
120121
return new AArch64HotSpotZBarrierSetLIRGenerator(config, providers);
121122
}
123+
if (config.gc == HotSpotGraalRuntime.HotSpotGC.Shenandoah) {
124+
return new AArch64HotSpotShenandoahBarrierSetLIRGenerator(config, providers);
125+
}
122126
return null;
123127
}
124128

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package jdk.graal.compiler.hotspot.aarch64.shenandoah;
26+
27+
import jdk.graal.compiler.asm.aarch64.AArch64Address;
28+
import jdk.graal.compiler.core.aarch64.AArch64LIRGenerator;
29+
import jdk.graal.compiler.core.common.LIRKind;
30+
import jdk.graal.compiler.core.common.spi.ForeignCallLinkage;
31+
import jdk.graal.compiler.hotspot.GraalHotSpotVMConfig;
32+
import jdk.graal.compiler.hotspot.meta.HotSpotHostForeignCallsProvider;
33+
import jdk.graal.compiler.hotspot.meta.HotSpotProviders;
34+
import jdk.graal.compiler.lir.aarch64.AArch64AddressValue;
35+
import jdk.graal.compiler.lir.gen.LIRGeneratorTool;
36+
import jdk.graal.compiler.lir.gen.ShenandoahBarrierSetLIRGeneratorTool;
37+
import jdk.graal.compiler.nodes.gc.shenandoah.ShenandoahLoadRefBarrierNode;
38+
import jdk.vm.ci.aarch64.AArch64Kind;
39+
import jdk.vm.ci.meta.AllocatableValue;
40+
import jdk.vm.ci.meta.PlatformKind;
41+
import jdk.vm.ci.meta.Value;
42+
43+
public class AArch64HotSpotShenandoahBarrierSetLIRGenerator implements ShenandoahBarrierSetLIRGeneratorTool {
44+
public AArch64HotSpotShenandoahBarrierSetLIRGenerator(GraalHotSpotVMConfig config, HotSpotProviders providers) {
45+
this.config = config;
46+
this.providers = providers;
47+
}
48+
49+
private final GraalHotSpotVMConfig config;
50+
private final HotSpotProviders providers;
51+
52+
private static ForeignCallLinkage getReadBarrierStub(LIRGeneratorTool tool, ShenandoahLoadRefBarrierNode.ReferenceStrength strength, boolean narrow) {
53+
return switch (strength) {
54+
case STRONG -> narrow ? tool.getForeignCalls().lookupForeignCall(HotSpotHostForeignCallsProvider.SHENANDOAH_LOAD_BARRIER_NARROW)
55+
: tool.getForeignCalls().lookupForeignCall(HotSpotHostForeignCallsProvider.SHENANDOAH_LOAD_BARRIER);
56+
case WEAK -> narrow ? tool.getForeignCalls().lookupForeignCall(HotSpotHostForeignCallsProvider.SHENANDOAH_LOAD_BARRIER_WEAK_NARROW)
57+
: tool.getForeignCalls().lookupForeignCall(HotSpotHostForeignCallsProvider.SHENANDOAH_LOAD_BARRIER_WEAK);
58+
case PHANTOM -> narrow ? tool.getForeignCalls().lookupForeignCall(HotSpotHostForeignCallsProvider.SHENANDOAH_LOAD_BARRIER_PHANTOM_NARROW)
59+
: tool.getForeignCalls().lookupForeignCall(HotSpotHostForeignCallsProvider.SHENANDOAH_LOAD_BARRIER_PHANTOM);
60+
};
61+
}
62+
63+
@Override
64+
public Value emitLoadReferenceBarrier(LIRGeneratorTool tool, Value obj, Value address, ShenandoahLoadRefBarrierNode.ReferenceStrength strength, boolean narrow, boolean notNull) {
65+
PlatformKind platformKind = obj.getPlatformKind();
66+
LIRKind kind = LIRKind.reference(platformKind);
67+
Value result = tool.newVariable(tool.toRegisterKind(kind));
68+
ForeignCallLinkage callTarget = getReadBarrierStub(tool, strength, narrow);
69+
AllocatableValue object = tool.asAllocatable(obj);
70+
AArch64AddressValue loadAddress = ((AArch64LIRGenerator) tool).asAddressValue(address, AArch64Address.ANY_SIZE);
71+
tool.getResult().getFrameMapBuilder().callsMethod(callTarget.getOutgoingCallingConvention());
72+
tool.append(new AArch64HotSpotShenandoahLoadRefBarrierOp(config, providers, tool.asAllocatable(result), object, loadAddress, callTarget, strength, notNull));
73+
return result;
74+
}
75+
76+
@Override
77+
public void emitPreWriteBarrier(LIRGeneratorTool lirTool, Value address, AllocatableValue expectedObject, boolean nonNull) {
78+
AllocatableValue temp = lirTool.newVariable(LIRKind.value(AArch64Kind.QWORD));
79+
// If the assembly must load the value then it's needs a temporary to store it
80+
AllocatableValue temp2 = expectedObject.equals(Value.ILLEGAL) ? lirTool.newVariable(LIRKind.value(AArch64Kind.QWORD)) : Value.ILLEGAL;
81+
82+
// Load the address into a register
83+
AllocatableValue addressValue = lirTool.newVariable(address.getValueKind());
84+
lirTool.emitMove(addressValue, address);
85+
86+
ForeignCallLinkage callTarget = lirTool.getForeignCalls().lookupForeignCall(HotSpotHostForeignCallsProvider.SHENANDOAH_WRITE_BARRIER_PRE);
87+
lirTool.getResult().getFrameMapBuilder().callsMethod(callTarget.getOutgoingCallingConvention());
88+
lirTool.append(new AArch64ShenandoahPreWriteBarrierOp(config, providers, addressValue, expectedObject, temp, temp2, callTarget, nonNull));
89+
}
90+
91+
@Override
92+
public void emitCardBarrier(LIRGeneratorTool lirTool, Value address) {
93+
AArch64AddressValue addr = ((AArch64LIRGenerator) lirTool).asAddressValue(address, AArch64Address.ANY_SIZE);
94+
AllocatableValue tmp = lirTool.newVariable(LIRKind.value(AArch64Kind.QWORD));
95+
lirTool.append(new AArch64HotSpotShenandoahCardBarrierOp(config, providers, addr, tmp));
96+
}
97+
}

0 commit comments

Comments
 (0)