8365218: [JVMCI] AArch64 CPU features are not computed correctly after 8364128

Reviewed-by: dnsimon
This commit is contained in:
Yudi Zheng 2025-08-14 07:39:49 +00:00
parent 3e3298509f
commit e320162815
4 changed files with 20 additions and 65 deletions

View file

@ -27,10 +27,10 @@ import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.LongFunction;
import jdk.vm.ci.common.JVMCIError;
import jdk.vm.ci.runtime.JVMCIBackend;
import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
public interface HotSpotJVMCIBackendFactory {
@ -48,7 +48,8 @@ public interface HotSpotJVMCIBackendFactory {
* @param enumType the class of {@code CPUFeatureType}
* @param constants VM constants. Each entry whose key starts with {@code "VM_Version::CPU_"}
* specifies a CPU feature and its value is a mask for a bit in {@code features}
* @param features bits specifying CPU features
* @param bitMaskSupplier supplier to get the bit mask for the corresponding VM constant
* @param featuresSupplier supplier to get the bits specifying CPU features
* @param renaming maps from VM feature names to enum constant names where the two differ
* @throws IllegalArgumentException if any VM CPU feature constant cannot be converted to an
* enum value
@ -57,18 +58,19 @@ public interface HotSpotJVMCIBackendFactory {
static <CPUFeatureType extends Enum<CPUFeatureType>> EnumSet<CPUFeatureType> convertFeatures(
Class<CPUFeatureType> enumType,
Map<String, Long> constants,
long features,
LongFunction<Long> bitMaskSupplier,
LongFunction<Long> featuresSupplier,
Map<String, String> renaming) {
EnumSet<CPUFeatureType> outFeatures = EnumSet.noneOf(enumType);
List<String> missing = new ArrayList<>();
for (Entry<String, Long> e : constants.entrySet()) {
long bitMask = e.getValue();
long bitMask = bitMaskSupplier.apply(e.getValue());
String key = e.getKey();
if (key.startsWith("VM_Version::CPU_")) {
String name = key.substring("VM_Version::CPU_".length());
try {
CPUFeatureType feature = Enum.valueOf(enumType, renaming.getOrDefault(name, name));
if ((features & bitMask) != 0) {
if ((featuresSupplier.apply(e.getValue()) & bitMask) != 0) {
outFeatures.add(feature);
}
} catch (IllegalArgumentException iae) {
@ -82,57 +84,4 @@ public interface HotSpotJVMCIBackendFactory {
return outFeatures;
}
/**
* Converts CPU features bit map into enum constants.
*
* @param <CPUFeatureType> CPU feature enum type
* @param enumType the class of {@code CPUFeatureType}
* @param constants VM constants. Each entry whose key starts with {@code "VM_Version::CPU_"}
* specifies a CPU feature and its value is a mask for a bit in {@code features}
* @param featuresBitMapAddress pointer to {@code VM_Features::_features_bitmap} field of {@code VM_Version::_features}
* @param featuresBitMapSize size of feature bit map in bytes
* @param renaming maps from VM feature names to enum constant names where the two differ
* @throws IllegalArgumentException if any VM CPU feature constant cannot be converted to an
* enum value
* @return the set of converted values
*/
static <CPUFeatureType extends Enum<CPUFeatureType>> EnumSet<CPUFeatureType> convertFeatures(
Class<CPUFeatureType> enumType,
Map<String, Long> constants,
long featuresBitMapAddress,
long featuresBitMapSize,
Map<String, String> renaming) {
EnumSet<CPUFeatureType> outFeatures = EnumSet.noneOf(enumType);
List<String> missing = new ArrayList<>();
for (Entry<String, Long> e : constants.entrySet()) {
String key = e.getKey();
long bitIndex = e.getValue();
if (key.startsWith("VM_Version::CPU_")) {
String name = key.substring("VM_Version::CPU_".length());
try {
final long featuresElementShiftCount = 6; // log (# of bits per long)
final long featuresElementMask = (1L << featuresElementShiftCount) - 1;
CPUFeatureType feature = Enum.valueOf(enumType, renaming.getOrDefault(name, name));
long featureIndex = bitIndex >>> featuresElementShiftCount;
long featureBitMask = 1L << (bitIndex & featuresElementMask);
assert featureIndex < featuresBitMapSize;
long featuresElement = UNSAFE.getLong(featuresBitMapAddress + featureIndex * Long.BYTES);
if ((featuresElement & featureBitMask) != 0) {
outFeatures.add(feature);
}
} catch (IllegalArgumentException iae) {
missing.add(name);
}
}
}
if (!missing.isEmpty()) {
throw new JVMCIError("Missing CPU feature constants: %s", missing);
}
return outFeatures;
}
}

View file

@ -49,7 +49,7 @@ public class AArch64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFac
private static EnumSet<AArch64.CPUFeature> computeFeatures(AArch64HotSpotVMConfig config) {
// Configure the feature set using the HotSpot flag settings.
Map<String, Long> constants = config.getStore().getConstants();
return HotSpotJVMCIBackendFactory.convertFeatures(CPUFeature.class, constants, config.vmVersionFeatures, emptyMap());
return HotSpotJVMCIBackendFactory.convertFeatures(CPUFeature.class, constants, idx -> 1L << idx, _ -> config.vmVersionFeatures, emptyMap());
}
private static TargetDescription createTarget(AArch64HotSpotVMConfig config) {

View file

@ -26,6 +26,8 @@ import static jdk.vm.ci.common.InitTimer.timer;
import java.util.EnumSet;
import java.util.Map;
import jdk.internal.misc.Unsafe;
import jdk.internal.util.OperatingSystem;
import jdk.vm.ci.amd64.AMD64;
import jdk.vm.ci.amd64.AMD64.CPUFeature;
@ -50,11 +52,15 @@ public class AMD64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFacto
Map<String, Long> constants = config.getStore().getConstants();
Map<String, String> renaming = Map.of("3DNOW_PREFETCH", "AMD_3DNOW_PREFETCH");
long featuresBitMapAddress = config.vmVersionFeatures + config.vmFeaturesFeaturesOffset;
EnumSet<CPUFeature> features = HotSpotJVMCIBackendFactory.convertFeatures(CPUFeature.class,
constants,
featuresBitMapAddress,
config.vmFeaturesFeaturesSize,
renaming);
EnumSet<CPUFeature> features = HotSpotJVMCIBackendFactory.convertFeatures(CPUFeature.class, constants, idx -> {
final long featuresElementShiftCount = 6; // log (# of bits per long)
final long featuresElementMask = (1L << featuresElementShiftCount) - 1;
return 1L << (idx & featuresElementMask);
}, idx -> {
final long featuresElementShiftCount = 6; // log (# of bits per long)
long featureIndex = idx >>> featuresElementShiftCount;
return Unsafe.getUnsafe().getLong(featuresBitMapAddress + featureIndex * Long.BYTES);
}, renaming);
assert features.contains(AMD64.CPUFeature.SSE) : "minimum config for x64";
assert features.contains(AMD64.CPUFeature.SSE2) : "minimum config for x64";
return features;

View file

@ -49,7 +49,7 @@ public class RISCV64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFac
private static EnumSet<RISCV64.CPUFeature> computeFeatures(RISCV64HotSpotVMConfig config) {
// Configure the feature set using the HotSpot flag settings.
Map<String, Long> constants = config.getStore().getConstants();
return HotSpotJVMCIBackendFactory.convertFeatures(CPUFeature.class, constants, config.vmVersionFeatures, emptyMap());
return HotSpotJVMCIBackendFactory.convertFeatures(CPUFeature.class, constants, mask -> mask, _ -> config.vmVersionFeatures, emptyMap());
}
private static TargetDescription createTarget(RISCV64HotSpotVMConfig config) {