Skip to content

Shenandoah support #10904

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

import jdk.graal.compiler.debug.Assertions;
import jdk.graal.compiler.graph.Graph;
import jdk.graal.compiler.nodes.GraphState;
import jdk.graal.compiler.options.OptionValues;
import jdk.graal.compiler.phases.PlaceholderPhase;
import jdk.graal.compiler.phases.common.AddressLoweringPhase;
Expand All @@ -36,6 +37,7 @@
import jdk.graal.compiler.phases.common.LowTierLoweringPhase;
import jdk.graal.compiler.phases.common.RemoveOpaqueValuePhase;
import jdk.graal.compiler.phases.common.TransplantGraphsPhase;
import jdk.graal.compiler.phases.common.WriteBarrierAdditionPhase;
import jdk.graal.compiler.phases.schedule.SchedulePhase;
import jdk.graal.compiler.phases.tiers.LowTierContext;

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

appendPhase(new WriteBarrierAdditionPhase(GraphState.StageFlag.LOW_TIER_BARRIER_ADDITION));

if (Assertions.assertionsEnabled()) {
appendPhase(new BarrierSetVerificationPhase());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

import jdk.graal.compiler.core.common.GraalOptions;
import jdk.graal.compiler.graph.Graph;
import jdk.graal.compiler.nodes.GraphState;
import jdk.graal.compiler.options.Option;
import jdk.graal.compiler.options.OptionKey;
import jdk.graal.compiler.options.OptionType;
Expand All @@ -47,6 +48,7 @@
import jdk.graal.compiler.phases.common.PropagateDeoptimizeProbabilityPhase;
import jdk.graal.compiler.phases.common.RemoveOpaqueValuePhase;
import jdk.graal.compiler.phases.common.TransplantGraphsPhase;
import jdk.graal.compiler.phases.common.WriteBarrierAdditionPhase;
import jdk.graal.compiler.phases.schedule.SchedulePhase;
import jdk.graal.compiler.phases.schedule.SchedulePhase.SchedulingStrategy;
import jdk.graal.compiler.phases.tiers.LowTierContext;
Expand Down Expand Up @@ -87,6 +89,8 @@ public LowTier(OptionValues options) {
appendPhase(new FixReadsPhase(true,
new SchedulePhase(GraalOptions.StressTestEarlyReads.getValue(options) ? SchedulingStrategy.EARLIEST : SchedulingStrategy.LATEST_OUT_OF_LOOPS_IMPLICIT_NULL_CHECKS)));

appendPhase(new WriteBarrierAdditionPhase(GraphState.StageFlag.LOW_TIER_BARRIER_ADDITION));

appendPhase(canonicalizerWithoutGVN);

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,44 @@ private long getZGCAddressField(String name) {
public final long zBarrierSetRuntimeLoadBarrierOnOopArray = getZGCAddressField("ZBarrierSetRuntime::load_barrier_on_oop_array");
public final int zPointerLoadShift = getConstant("ZPointerLoadShift", Integer.class, -1, osArch.equals("aarch64") && zgcSupport);

/*
* Shenandoah GC support.
*/
/**
* Indicates whether or not the HotSpot VM has been built with Shenandoah support.
* If not, then we don't expect the Shenandoah symbols to be present in JVMCI.
*/
public final boolean hasShenandoahGC = getStore().getConstants().containsKey("INCLUDE_SHENANDOAHGC") && getConstant("INCLUDE_SHENANDOAHGC", Boolean.class);

/*
* Various Shenandoah GC constants.
*/
public final int shenandoahGCStateOffset = getConstant("ShenandoahThreadLocalData::gc_state_offset", Integer.class, -1, hasShenandoahGC);
public final int shenandoahSATBIndexOffset = getConstant("ShenandoahThreadLocalData::satb_mark_queue_index_offset", Integer.class, -1, hasShenandoahGC);
public final int shenandoahSATBBufferOffset = getConstant("ShenandoahThreadLocalData::satb_mark_queue_buffer_offset", Integer.class, -1, hasShenandoahGC);
public final int shenandoahCardTableOffset = getConstant("ShenandoahThreadLocalData::card_table_offset", Integer.class, -1, hasShenandoahGC);
public final int shenandoahGCRegionSizeBytesShift = getFieldValue("CompilerToVM::Data::shenandoah_region_size_bytes_shift", Integer.class, "int", -1, hasShenandoahGC);
public final long shenandoahGCCSetFastTestAddress = getFieldValue("CompilerToVM::Data::shenandoah_in_cset_fast_test_addr", Long.class, "address", -1L, hasShenandoahGC);

public final int shenandoahGCStateHasForwarded = getConstant("ShenandoahHeap::HAS_FORWARDED", Integer.class, -1, hasShenandoahGC);
public final int shenandoahGCStateMarking = getConstant("ShenandoahHeap::MARKING", Integer.class, -1, hasShenandoahGC);
public final int shenandoahGCStateEvacuation = getConstant("ShenandoahHeap::EVACUATION", Integer.class, -1, hasShenandoahGC);
public final int shenandoahGCStateUpdateRefs = getConstant("ShenandoahHeap::UPDATE_REFS", Integer.class, -1, hasShenandoahGC);
public final int shenandoahGCStateWeakRoots = getConstant("ShenandoahHeap::WEAK_ROOTS", Integer.class, -1, hasShenandoahGC);
public final int shenandoahGCStateYoungMarking = getConstant("ShenandoahHeap::YOUNG_MARKING", Integer.class, -1, hasShenandoahGC);
public final int shenandoahGCStateOldMarking = getConstant("ShenandoahHeap::OLD_MARKING", Integer.class, -1, hasShenandoahGC);

/*
* Shenandoah barrier slow-paths.
*/
public final long shenandoahLoadBarrierStrong = getAddress("ShenandoahRuntime::load_reference_barrier_strong", -1L, hasShenandoahGC);
public final long shenandoahLoadBarrierStrongNarrow = getAddress("ShenandoahRuntime::load_reference_barrier_strong_narrow", -1L, hasShenandoahGC);
public final long shenandoahLoadBarrierWeak = getAddress("ShenandoahRuntime::load_reference_barrier_weak", -1L, hasShenandoahGC);
public final long shenandoahLoadBarrierWeakNarrow = getAddress("ShenandoahRuntime::load_reference_barrier_weak_narrow", -1L, hasShenandoahGC);
public final long shenandoahLoadBarrierPhantom = getAddress("ShenandoahRuntime::load_reference_barrier_phantom", -1L, hasShenandoahGC);
public final long shenandoahLoadBarrierPhantomNarrow = getAddress("ShenandoahRuntime::load_reference_barrier_phantom_narrow", -1L, hasShenandoahGC);
public final long shenandoahWriteBarrierPre = getAddress("ShenandoahRuntime::write_barrier_pre", -1L, hasShenandoahGC);

// aarch64 specific nmethod entry barrier support
// @formatter:off
public final int BarrierSetAssembler_nmethod_patching_type = getFieldValue("CompilerToVM::Data::BarrierSetAssembler_nmethod_patching_type", Integer.class, "int", -1, osArch.equals("aarch64"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,8 @@ private BarrierSet createBarrierSet(GraalHotSpotVMConfig config, MetaAccessProvi
ResolvedJavaField referentField = HotSpotReplacementsUtil.referentField(metaAccess);
if (config.gc == HotSpotGraalRuntime.HotSpotGC.Z) {
return new HotSpotZBarrierSet(objectArrayType, referentField);
} else if (config.gc == HotSpotGraalRuntime.HotSpotGC.Shenandoah) {
return new HotSpotShenandoahBarrierSet(objectArrayType, referentField, config);
} else if (config.gc == HotSpotGraalRuntime.HotSpotGC.Epsilon) {
return new NoBarrierSet();
} else if (config.useG1GC()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,7 @@ public enum HotSpotGC {
G1("UseG1GC"),
Z(true, true, flagIsSet("UseZGC")),
Epsilon(true, true, flagIsSet("UseEpsilonGC")),

// Unsupported GCs
Shenandoah(false, true, flagIsSet("UseShenandoahGC"));
Shenandoah(true, true, flagIsSet("UseShenandoahGC"));

HotSpotGC(String flag) {
this(true, true, flagIsSet(flag));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.graal.compiler.hotspot;

import jdk.graal.compiler.core.common.CompressEncoding;
import jdk.graal.compiler.debug.GraalError;
import jdk.graal.compiler.hotspot.nodes.HotSpotCompressionNode;
import org.graalvm.word.LocationIdentity;

import jdk.graal.compiler.core.common.memory.BarrierType;
import jdk.graal.compiler.core.common.type.AbstractObjectStamp;
import jdk.graal.compiler.core.common.type.Stamp;
import jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil;
import jdk.graal.compiler.nodes.ValueNode;
import jdk.graal.compiler.nodes.gc.shenandoah.ShenandoahBarrierSet;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.ResolvedJavaField;
import jdk.vm.ci.meta.ResolvedJavaType;

/**
* Specialization of {@link ShenandoahBarrierSet} that adds support for read barriers on handle
* locations and compressed references.
*/
public class HotSpotShenandoahBarrierSet extends ShenandoahBarrierSet {
private final CompressEncoding oopEncoding;

public HotSpotShenandoahBarrierSet(ResolvedJavaType objectArrayType, ResolvedJavaField referentField, GraalHotSpotVMConfig config) {
super(objectArrayType, referentField);
this.oopEncoding = config.getOopEncoding();
this.useLoadRefBarrier = config.getFlag("ShenandoahLoadRefBarrier", Boolean.class);
this.useSATBBarrier = config.getFlag("ShenandoahSATBBarrier", Boolean.class);
this.useCASBarrier = config.getFlag("ShenandoahCASBarrier", Boolean.class);
this.useCardBarrier = config.getFlag("ShenandoahCardBarrier", Boolean.class);
}

@Override
protected BarrierType barrierForLocation(BarrierType currentBarrier, LocationIdentity location, JavaKind storageKind) {
if (location instanceof HotSpotReplacementsUtil.OopHandleLocationIdentity) {
return BarrierType.READ;
}
return super.barrierForLocation(currentBarrier, location, storageKind);
}

@Override
public BarrierType readBarrierType(LocationIdentity location, ValueNode address, Stamp loadStamp) {
if (location instanceof HotSpotReplacementsUtil.OopHandleLocationIdentity) {
GraalError.guarantee(loadStamp instanceof AbstractObjectStamp, "expect object, got: " + loadStamp);
return BarrierType.READ;
}
return super.readBarrierType(location, address, loadStamp);
}

@Override
public BarrierType writeBarrierType(LocationIdentity location) {
if (location instanceof HotSpotReplacementsUtil.OopHandleLocationIdentity) {
return BarrierType.FIELD;
}
return BarrierType.NONE;
}

@Override
protected ValueNode maybeUncompressReference(ValueNode value, boolean narrow) {
if (value != null && narrow) {
return HotSpotCompressionNode.uncompressWithoutUnique(value.graph(), value, oopEncoding);
}
return value;
}

@Override
protected ValueNode maybeCompressReference(ValueNode value, boolean narrow) {
if (value != null && narrow) {
return HotSpotCompressionNode.compressWithoutUnique(value.graph(), value, oopEncoding);
}
return value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
import jdk.graal.compiler.hotspot.HotSpotLIRGenerator;
import jdk.graal.compiler.hotspot.HotSpotLockStack;
import jdk.graal.compiler.hotspot.aarch64.g1.AArch64HotSpotG1BarrierSetLIRTool;
import jdk.graal.compiler.hotspot.aarch64.shenandoah.AArch64HotSpotShenandoahBarrierSetLIRGenerator;
import jdk.graal.compiler.hotspot.aarch64.z.AArch64HotSpotZBarrierSetLIRGenerator;
import jdk.graal.compiler.hotspot.debug.BenchmarkCounters;
import jdk.graal.compiler.hotspot.meta.HotSpotProviders;
Expand Down Expand Up @@ -119,6 +120,9 @@ protected static BarrierSetLIRGeneratorTool getBarrierSet(GraalHotSpotVMConfig c
if (config.gc == HotSpotGraalRuntime.HotSpotGC.Z) {
return new AArch64HotSpotZBarrierSetLIRGenerator(config, providers);
}
if (config.gc == HotSpotGraalRuntime.HotSpotGC.Shenandoah) {
return new AArch64HotSpotShenandoahBarrierSetLIRGenerator(config, providers);
}
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
Register resultRegister = asRegister(result);
Register ptr = asRegister(input);
Register base = (isRegister(baseRegister) ? asRegister(baseRegister) : zr);
emitCompressCode(masm, ptr, resultRegister, base, encoding, nonNull);
}

public static void emitCompressCode(AArch64MacroAssembler masm, Register ptr, Register resultRegister, Register base, CompressEncoding encoding, boolean nonNull) {
// result = (ptr - base) >> shift
if (!encoding.hasBase()) {
if (encoding.hasShift()) {
Expand Down
Loading
Loading