Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions sdk/mx.sdk/mx_sdk_vm_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -1255,6 +1255,7 @@ def contents(self):
image_config = self.subject.image_config
build_args = [
'--no-fallback',
'-march=compatibility', # Target maximum portability of all GraalVM images.
'-H:+AssertInitializationSpecifiedForAllClasses',
'-H:+EnforceMaxRuntimeCompileMethods',
'-Dorg.graalvm.version={}'.format(_suite.release_version()),
Expand Down
1 change: 1 addition & 0 deletions substratevm/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ This changelog summarizes major changes to GraalVM Native Image.
* (GR-38414) BellSoft implemented the `MemoryPoolMXBean` for the serial and epsilon GCs.
* (GR-40641) Dynamic linking of AWT libraries on Linux.
* (GR-40463) Red Hat added experimental support for JMX, which can be enabled with the `--enable-monitoring` option (e.g. `--enable-monitoring=jmxclient,jmxserver`).
* (GR-44110) Native Image now targets `x86-64-v3` by default on AMD64 and supports a new `-march` option. Use `-march=compatibility` for best compatibility (previous default) or `-march=native` for best performance if the native executable is deployed on the same machine or on a machine with the same CPU features. To list all available machine types, use `-march=list`.

## Version 22.3.0
* (GR-35721) Remove old build output style and the `-H:±BuildOutputUseNewStyle` option.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1008,15 +1008,15 @@ private int completeImageBuild() {
.collect(Collectors.joining(",", oHCLibraryPath, ""));
imageBuilderArgs.add(0, clibrariesBuilderArg);

String printFlagsDummyImage = "dummy-image-";
boolean printFlags = false;
if (printFlagsOptionQuery != null) {
printFlags = true;
addPlainImageBuilderArg(NativeImage.oH + enablePrintFlags + "=" + printFlagsOptionQuery);
addPlainImageBuilderArg(NativeImage.oR + enablePrintFlags + "=" + printFlagsOptionQuery);
addPlainImageBuilderArg(oHName + printFlagsDummyImage + "printFlagsOptionQuery");
} else if (printFlagsWithExtraHelpOptionQuery != null) {
printFlags = true;
addPlainImageBuilderArg(NativeImage.oH + enablePrintFlagsWithExtraHelp + "=" + printFlagsWithExtraHelpOptionQuery);
addPlainImageBuilderArg(NativeImage.oR + enablePrintFlagsWithExtraHelp + "=" + printFlagsWithExtraHelpOptionQuery);
addPlainImageBuilderArg(oHName + printFlagsDummyImage + "printFlagsWithExtraHelpOptionQuery");
}

if (shouldAddCWDToCP()) {
Expand Down Expand Up @@ -1062,9 +1062,12 @@ private int completeImageBuild() {
mainClass = getHostedOptionFinalArgumentValue(imageBuilderArgs, oHClass);
boolean buildExecutable = imageBuilderArgs.stream().noneMatch(arg -> arg.contains(oHEnableSharedLibraryFlag));
boolean listModules = imageBuilderArgs.stream().anyMatch(arg -> arg.contains(oH + "+" + "ListModules"));
boolean printFlags = imageBuilderArgs.stream().anyMatch(arg -> arg.contains(enablePrintFlags) || arg.contains(enablePrintFlagsWithExtraHelp));
printFlags |= imageBuilderArgs.stream().anyMatch(arg -> arg.contains("-march=list"));

if (!printFlags) {
if (printFlags) {
/* Ensure name for bundle support */
addPlainImageBuilderArg(oHName + "dummy-image");
} else {
List<String> extraImageArgs = new ArrayList<>();
ListIterator<String> leftoverArgsItr = leftoverArgs.listIterator();
while (leftoverArgsItr.hasNext()) {
Expand Down Expand Up @@ -1133,7 +1136,7 @@ private int completeImageBuild() {
Path imageNamePath = Path.of(imageName);
Path imageNamePathParent = imageNamePath.getParent();
if (imageNamePathParent != null) {
/* Readjust imageName & imagePath so that imageName is just a simple fileName */
/* Read just imageName & imagePath so that imageName is just a simple fileName */
imageName = imageNamePath.getFileName().toString();
if (!imageNamePathParent.isAbsolute()) {
imageNamePathParent = imagePath.resolve(imageNamePathParent);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2023, 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
Expand Down Expand Up @@ -115,9 +115,10 @@ protected <T extends Enum<T>> void initializeCPUFeatureAccessData(Enum<T>[] allC
}
}
if (!unknownFeatures.isEmpty()) {
throw VMError.shouldNotReachHere("Native image does not support the following JVMCI CPU features: " + unknownFeatures);
throw VMError.shouldNotReachHere("The image does not support the following JVMCI CPU features: " + unknownFeatures);
}
String errorMessage = "Current target does not support the following CPU features that are required by the image: " + buildtimeCPUFeatures.toString() + "\n\0";
String errorMessage = "The current machine does not support all of the following CPU features that are required by the image: " + buildtimeCPUFeatures.toString() + "." +
System.lineSeparator() + "Please rebuild the executable with an appropriate setting of the -march option.\0";
var cpuFeatureAccess = createCPUFeatureAccessSingleton(buildtimeCPUFeatures, cpuFeatureEnumToStructOffset, errorMessage.getBytes(StandardCharsets.UTF_8), requiredFeaturesStruct);
ImageSingletons.add(CPUFeatureAccess.class, cpuFeatureAccess);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2023, 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
Expand Down Expand Up @@ -293,6 +293,8 @@
import com.oracle.svm.hosted.substitute.AnnotationSubstitutionProcessor;
import com.oracle.svm.hosted.substitute.DeletedFieldsPlugin;
import com.oracle.svm.hosted.substitute.UnsafeAutomaticSubstitutionProcessor;
import com.oracle.svm.hosted.util.CPUTypeAArch64;
import com.oracle.svm.hosted.util.CPUTypeAMD64;
import com.oracle.svm.util.ClassUtil;
import com.oracle.svm.util.ImageBuildStatistics;
import com.oracle.svm.util.ReflectionUtil;
Expand Down Expand Up @@ -439,17 +441,8 @@ protected SubstrateTargetDescription createTarget() {

public static SubstrateTargetDescription createTarget(Platform platform) {
if (includedIn(platform, Platform.AMD64.class)) {
Architecture architecture;
EnumSet<AMD64.CPUFeature> features = EnumSet.noneOf(AMD64.CPUFeature.class);
if (NativeImageOptions.NativeArchitecture.getValue()) {
features.addAll(((AMD64) GraalAccess.getOriginalTarget().arch).getFeatures());
} else {
// SSE and SSE2 are added by default as they are required by Graal
features.add(AMD64.CPUFeature.SSE);
features.add(AMD64.CPUFeature.SSE2);

features.addAll(parseCSVtoEnum(AMD64.CPUFeature.class, NativeImageOptions.CPUFeatures.getValue().values(), AMD64.CPUFeature.values()));
}
EnumSet<AMD64.CPUFeature> features = CPUTypeAMD64.getSelectedFeatures();
features.addAll(parseCSVtoEnum(AMD64.CPUFeature.class, NativeImageOptions.CPUFeatures.getValue().values(), AMD64.CPUFeature.values()));
// GR-33542 RTM is only intermittently detected and is not used by Graal
features.remove(AMD64.CPUFeature.RTM);
// set up the runtime checked cpu features
Expand All @@ -464,50 +457,31 @@ public static SubstrateTargetDescription createTarget(Platform platform) {
}
}
}
architecture = new AMD64(features, AMD64CPUFeatureAccess.allAMD64Flags());
assert architecture instanceof AMD64 : "using AMD64 platform with a different architecture";
AMD64 architecture = new AMD64(features, AMD64CPUFeatureAccess.allAMD64Flags());
int deoptScratchSpace = 2 * 8; // Space for two 64-bit registers: rax and xmm0
return new SubstrateTargetDescription(architecture, true, 16, 0, deoptScratchSpace, runtimeCheckedFeatures);
} else if (includedIn(platform, Platform.AARCH64.class)) {
Architecture architecture;
if (NativeImageOptions.NativeArchitecture.getValue()) {
architecture = GraalAccess.getOriginalTarget().arch;
} else {
EnumSet<AArch64.CPUFeature> features = EnumSet.noneOf(AArch64.CPUFeature.class);
/*
* FP is added by default, as floating-point operations are required by Graal.
*/
features.add(AArch64.CPUFeature.FP);
/*
* ASIMD is added by default, as it is available in all AArch64 machines with
* floating-port support.
*/
features.add(AArch64.CPUFeature.ASIMD);

features.addAll(parseCSVtoEnum(AArch64.CPUFeature.class, NativeImageOptions.CPUFeatures.getValue().values(), AArch64.CPUFeature.values()));

architecture = new AArch64(features, AArch64CPUFeatureAccess.enabledAArch64Flags());
}
assert architecture instanceof AArch64 : "using AArch64 platform with a different architecture";
EnumSet<AArch64.CPUFeature> features = CPUTypeAArch64.getSelectedFeatures();
features.addAll(parseCSVtoEnum(AArch64.CPUFeature.class, NativeImageOptions.CPUFeatures.getValue().values(), AArch64.CPUFeature.values()));
AArch64 architecture = new AArch64(features, AArch64CPUFeatureAccess.enabledAArch64Flags());
// runtime checked features are the same as static features on AArch64 for now
EnumSet<AArch64.CPUFeature> runtimeCheckedFeatures = ((AArch64) architecture).getFeatures().clone();
EnumSet<AArch64.CPUFeature> runtimeCheckedFeatures = architecture.getFeatures().clone();
int deoptScratchSpace = 2 * 8; // Space for two 64-bit registers: r0 and v0.
return new SubstrateTargetDescription(architecture, true, 16, 0, deoptScratchSpace, runtimeCheckedFeatures);
} else if (includedIn(platform, Platform.RISCV64.class)) {
Class<?> riscv64CPUFeature = RISCV64ReflectionUtil.lookupClass(false, RISCV64ReflectionUtil.featureClass);
Architecture architecture;
if (NativeImageOptions.NativeArchitecture.getValue()) {
if (NativeImageOptions.MICRO_ARCHITECTURE_NATIVE.equals(NativeImageOptions.MicroArchitecture.getValue())) {
architecture = GraalAccess.getOriginalTarget().arch;
} else {
Method noneOf = RISCV64ReflectionUtil.lookupMethod(EnumSet.class, "noneOf", Class.class);
EnumSet<?> features = (EnumSet<?>) RISCV64ReflectionUtil.invokeMethod(noneOf, null, riscv64CPUFeature);
Method parseCSVtoEnum = RISCV64ReflectionUtil.lookupMethod(NativeImageGenerator.class, "parseCSVtoEnum", Class.class, List.class, Enum[].class);
parseCSVtoEnum.setAccessible(true);
Method addAll = RISCV64ReflectionUtil.lookupMethod(AbstractCollection.class, "addAll", Collection.class);

RISCV64ReflectionUtil.invokeMethod(addAll, features,
RISCV64ReflectionUtil.invokeMethod(parseCSVtoEnum, null, riscv64CPUFeature, NativeImageOptions.CPUFeatures.getValue().values(), riscv64CPUFeature.getEnumConstants()));

RISCV64ReflectionUtil.invokeMethod(parseCSVtoEnum, null, riscv64CPUFeature, NativeImageOptions.CPUFeatures.getValue().values(),
riscv64CPUFeature.getEnumConstants()));
architecture = (Architecture) ReflectionUtil.newInstance(ReflectionUtil.lookupConstructor(RISCV64ReflectionUtil.getArch(false), EnumSet.class, EnumSet.class), features,
RISCV64CPUFeatureAccess.enabledRISCV64Flags());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -521,13 +521,13 @@ public static void printCPUFeatures(Platform platform) {
if (NativeImageGenerator.includedIn(platform, Platform.AMD64.class)) {
message.append("All AMD64 CPUFeatures: ").append(Arrays.toString(AMD64.CPUFeature.values()));
if (arch instanceof AMD64) {
message.append("\nHost machine AMD64 CPUFeatures: ").append(((AMD64) arch).getFeatures().toString());
message.append(System.lineSeparator()).append("Host machine AMD64 CPUFeatures: ").append(((AMD64) arch).getFeatures().toString());
}
} else {
assert NativeImageGenerator.includedIn(platform, Platform.AARCH64.class);
message.append("All AArch64 CPUFeatures: ").append(Arrays.toString(AArch64.CPUFeature.values()));
if (arch instanceof AArch64) {
message.append("\nHost machine AArch64 CPUFeatures: ").append(((AArch64) arch).getFeatures().toString());
message.append(System.lineSeparator()).append("Host machine AArch64 CPUFeatures: ").append(((AArch64) arch).getFeatures().toString());
}
}
System.out.println(message);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2023, 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
Expand Down Expand Up @@ -47,8 +47,12 @@
import com.oracle.svm.core.option.HostedOptionKey;
import com.oracle.svm.core.option.LocatableMultiOptionValue;
import com.oracle.svm.core.option.SubstrateOptionsParser;
import com.oracle.svm.core.util.InterruptImageBuilding;
import com.oracle.svm.core.util.UserError;
import com.oracle.svm.hosted.classinitialization.ClassInitializationOptions;
import com.oracle.svm.hosted.util.CPUType;
import com.oracle.svm.hosted.util.CPUTypeAArch64;
import com.oracle.svm.hosted.util.CPUTypeAMD64;

public class NativeImageOptions {

Expand All @@ -58,7 +62,8 @@ public class NativeImageOptions {
"target executable, irrespective of whether they are supported by the hosted " +
"environment. Note that enabling features not present within the target environment " +
"may result in application crashes. The specific options available are target " +
"platform dependent. See --list-cpu-features for feature list.", type = User)//
"platform dependent. See --list-cpu-features for feature list. These features " +
"are in addition to -march.", type = User)//
public static final HostedOptionKey<LocatableMultiOptionValue.Strings> CPUFeatures = new HostedOptionKey<>(LocatableMultiOptionValue.Strings.buildWithCommaDelimiter());

@APIOption(name = "list-cpu-features")//
Expand All @@ -76,8 +81,37 @@ public class NativeImageOptions {
"AMD64: 'AVX,AVX2'; AArch64: ''", type = User)//
public static final HostedOptionKey<LocatableMultiOptionValue.Strings> RuntimeCheckedCPUFeatures = new HostedOptionKey<>(LocatableMultiOptionValue.Strings.buildWithCommaDelimiter());

@Option(help = "Overrides CPUFeatures and uses the native architecture, i.e., the architecture of a machine that builds an image. NativeArchitecture takes precedence over CPUFeatures", type = User)//
public static final HostedOptionKey<Boolean> NativeArchitecture = new HostedOptionKey<>(false);
public static final String MICRO_ARCHITECTURE_NATIVE = "native";
public static final String MICRO_ARCHITECTURE_COMPATIBILITY = "compatibility";
public static final String MICRO_ARCHITECTURE_LIST = "list";

@APIOption(name = "-march")//
@Option(help = "Generate instructions for a specific machine type. Defaults to 'x86-64-v3' on AMD64 and 'armv8-a' on AArch64. " +
"Use -march=" + MICRO_ARCHITECTURE_COMPATIBILITY + " for best compatibility, or -march=" + MICRO_ARCHITECTURE_NATIVE +
" for best performance if the native executable is deployed on the same machine or on a machine with the same CPU features. " +
"To list all available machine types, use -march=" + MICRO_ARCHITECTURE_LIST + ".", type = User)//
public static final HostedOptionKey<String> MicroArchitecture = new HostedOptionKey<>(null) {
protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, String oldValue, String newValue) {
if (MICRO_ARCHITECTURE_LIST.equals(newValue)) {
if (System.getProperty("os.arch").equalsIgnoreCase("aarch64")) {
CPUType.print("AArch64", CPUTypeAArch64.values());
CPUTypeAArch64.printFeatureModifiers();
} else {
CPUType.print("AMD64", CPUTypeAMD64.values());
}
throw new InterruptImageBuilding("");
}
}
};

@Option(help = "Uses the native architecture, i.e., the architecture of a machine that builds an image.", type = User, //
deprecated = true, deprecationMessage = "Please use -march=native instead. See --help for details.") //
public static final HostedOptionKey<Boolean> NativeArchitecture = new HostedOptionKey<>(false) {
@Override
protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, Boolean oldValue, Boolean newValue) {
MicroArchitecture.update(values, newValue ? MICRO_ARCHITECTURE_NATIVE : null);
}
};

@Option(help = "Print information about classes, methods, and fields that are present in the native image")//
public static final HostedOptionKey<Boolean> PrintUniverse = new HostedOptionKey<>(false);
Expand Down
Loading