Skip to content

Commit e9de7db

Browse files
committed
Shenandoah support
1 parent 23125d9 commit e9de7db

28 files changed

+2161
-7
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
import jdk.graal.compiler.debug.Assertions;
2828
import jdk.graal.compiler.graph.Graph;
29+
import jdk.graal.compiler.nodes.GraphState;
2930
import jdk.graal.compiler.options.OptionValues;
3031
import jdk.graal.compiler.phases.PlaceholderPhase;
3132
import jdk.graal.compiler.phases.common.AddressLoweringPhase;
@@ -36,6 +37,7 @@
3637
import jdk.graal.compiler.phases.common.LowTierLoweringPhase;
3738
import jdk.graal.compiler.phases.common.RemoveOpaqueValuePhase;
3839
import jdk.graal.compiler.phases.common.TransplantGraphsPhase;
40+
import jdk.graal.compiler.phases.common.WriteBarrierAdditionPhase;
3941
import jdk.graal.compiler.phases.schedule.SchedulePhase;
4042
import jdk.graal.compiler.phases.tiers.LowTierContext;
4143

@@ -50,6 +52,8 @@ public EconomyLowTier(OptionValues options) {
5052
appendPhase(new LowTierLoweringPhase(canonicalizer));
5153
appendPhase(new ExpandLogicPhase(canonicalizer));
5254

55+
appendPhase(new WriteBarrierAdditionPhase(GraphState.StageFlag.LOW_TIER_BARRIER_ADDITION));
56+
5357
if (Assertions.assertionsEnabled()) {
5458
appendPhase(new BarrierSetVerificationPhase());
5559
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
import jdk.graal.compiler.core.common.GraalOptions;
3030
import jdk.graal.compiler.graph.Graph;
31+
import jdk.graal.compiler.nodes.GraphState;
3132
import jdk.graal.compiler.options.Option;
3233
import jdk.graal.compiler.options.OptionKey;
3334
import jdk.graal.compiler.options.OptionType;
@@ -47,6 +48,7 @@
4748
import jdk.graal.compiler.phases.common.PropagateDeoptimizeProbabilityPhase;
4849
import jdk.graal.compiler.phases.common.RemoveOpaqueValuePhase;
4950
import jdk.graal.compiler.phases.common.TransplantGraphsPhase;
51+
import jdk.graal.compiler.phases.common.WriteBarrierAdditionPhase;
5052
import jdk.graal.compiler.phases.schedule.SchedulePhase;
5153
import jdk.graal.compiler.phases.schedule.SchedulePhase.SchedulingStrategy;
5254
import jdk.graal.compiler.phases.tiers.LowTierContext;
@@ -87,6 +89,8 @@ public LowTier(OptionValues options) {
8789
appendPhase(new FixReadsPhase(true,
8890
new SchedulePhase(GraalOptions.StressTestEarlyReads.getValue(options) ? SchedulingStrategy.EARLIEST : SchedulingStrategy.LATEST_OUT_OF_LOOPS_IMPLICIT_NULL_CHECKS)));
8991

92+
appendPhase(new WriteBarrierAdditionPhase(GraphState.StageFlag.LOW_TIER_BARRIER_ADDITION));
93+
9094
appendPhase(canonicalizerWithoutGVN);
9195

9296
/*

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 and compressed references.
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,100 @@
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+
/**
44+
* Lowers Shenandoah barriers to AArch64 LIR.
45+
*/
46+
public class AArch64HotSpotShenandoahBarrierSetLIRGenerator implements ShenandoahBarrierSetLIRGeneratorTool {
47+
public AArch64HotSpotShenandoahBarrierSetLIRGenerator(GraalHotSpotVMConfig config, HotSpotProviders providers) {
48+
this.config = config;
49+
this.providers = providers;
50+
}
51+
52+
private final GraalHotSpotVMConfig config;
53+
private final HotSpotProviders providers;
54+
55+
private static ForeignCallLinkage getReadBarrierStub(LIRGeneratorTool tool, ShenandoahLoadRefBarrierNode.ReferenceStrength strength, boolean narrow) {
56+
return switch (strength) {
57+
case STRONG -> narrow ? tool.getForeignCalls().lookupForeignCall(HotSpotHostForeignCallsProvider.SHENANDOAH_LOAD_BARRIER_NARROW)
58+
: tool.getForeignCalls().lookupForeignCall(HotSpotHostForeignCallsProvider.SHENANDOAH_LOAD_BARRIER);
59+
case WEAK -> narrow ? tool.getForeignCalls().lookupForeignCall(HotSpotHostForeignCallsProvider.SHENANDOAH_LOAD_BARRIER_WEAK_NARROW)
60+
: tool.getForeignCalls().lookupForeignCall(HotSpotHostForeignCallsProvider.SHENANDOAH_LOAD_BARRIER_WEAK);
61+
case PHANTOM -> narrow ? tool.getForeignCalls().lookupForeignCall(HotSpotHostForeignCallsProvider.SHENANDOAH_LOAD_BARRIER_PHANTOM_NARROW)
62+
: tool.getForeignCalls().lookupForeignCall(HotSpotHostForeignCallsProvider.SHENANDOAH_LOAD_BARRIER_PHANTOM);
63+
};
64+
}
65+
66+
@Override
67+
public Value emitLoadReferenceBarrier(LIRGeneratorTool tool, Value obj, Value address, ShenandoahLoadRefBarrierNode.ReferenceStrength strength, boolean narrow, boolean notNull) {
68+
PlatformKind platformKind = obj.getPlatformKind();
69+
LIRKind kind = LIRKind.reference(platformKind);
70+
Value result = tool.newVariable(tool.toRegisterKind(kind));
71+
ForeignCallLinkage callTarget = getReadBarrierStub(tool, strength, narrow);
72+
AllocatableValue object = tool.asAllocatable(obj);
73+
AArch64AddressValue loadAddress = ((AArch64LIRGenerator) tool).asAddressValue(address, AArch64Address.ANY_SIZE);
74+
tool.getResult().getFrameMapBuilder().callsMethod(callTarget.getOutgoingCallingConvention());
75+
tool.append(new AArch64HotSpotShenandoahLoadRefBarrierOp(config, providers, tool.asAllocatable(result), object, loadAddress, callTarget, strength, notNull));
76+
return result;
77+
}
78+
79+
@Override
80+
public void emitPreWriteBarrier(LIRGeneratorTool lirTool, Value address, AllocatableValue expectedObject, boolean nonNull) {
81+
AllocatableValue temp = lirTool.newVariable(LIRKind.value(AArch64Kind.QWORD));
82+
// If the assembly must load the value then it's needs a temporary to store it
83+
AllocatableValue temp2 = expectedObject.equals(Value.ILLEGAL) ? lirTool.newVariable(LIRKind.value(AArch64Kind.QWORD)) : Value.ILLEGAL;
84+
85+
// Load the address into a register
86+
AllocatableValue addressValue = lirTool.newVariable(address.getValueKind());
87+
lirTool.emitMove(addressValue, address);
88+
89+
ForeignCallLinkage callTarget = lirTool.getForeignCalls().lookupForeignCall(HotSpotHostForeignCallsProvider.SHENANDOAH_WRITE_BARRIER_PRE);
90+
lirTool.getResult().getFrameMapBuilder().callsMethod(callTarget.getOutgoingCallingConvention());
91+
lirTool.append(new AArch64HotSpotShenandoahSATBBarrierOp(config, providers, addressValue, expectedObject, temp, temp2, callTarget, nonNull));
92+
}
93+
94+
@Override
95+
public void emitCardBarrier(LIRGeneratorTool lirTool, Value address) {
96+
AArch64AddressValue addr = ((AArch64LIRGenerator) lirTool).asAddressValue(address, AArch64Address.ANY_SIZE);
97+
AllocatableValue tmp = lirTool.newVariable(LIRKind.value(AArch64Kind.QWORD));
98+
lirTool.append(new AArch64HotSpotShenandoahCardBarrierOp(config, providers, addr, tmp));
99+
}
100+
}

0 commit comments

Comments
 (0)