Skip to content

Commit

Permalink
[GR-55115] Truffle-side version check for jargraal.
Browse files Browse the repository at this point in the history
(cherry picked from commit 8cbccfe)
  • Loading branch information
tzezula committed Jul 26, 2024
1 parent f64898a commit 0591618
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -229,32 +229,6 @@ public String printFormat(PrintFormat format) {

public static final String OPEN_LABSJDK_RELEASE_URL_PATTERN = "https://github.com/graalvm/labs-openjdk-*/releases";

private void failVersionCheck(boolean exit, String reason, Object... args) {
Formatter errorMessage = new Formatter().format(reason, args);
String javaHome = props.get("java.home");
String vmName = props.get("java.vm.name");
errorMessage.format("Set the JVMCI_VERSION_CHECK environment variable to \"ignore\" to suppress ");
errorMessage.format("this error or to \"warn\" to emit a warning and continue execution.%n");
errorMessage.format("Currently used Java home directory is %s.%n", javaHome);
errorMessage.format("Currently used VM configuration is: %s%n", vmName);
if (vmVersion.contains("-jvmci-")) {
errorMessage.format("Download the latest Labs OpenJDK from " + OPEN_LABSJDK_RELEASE_URL_PATTERN);
} else {
errorMessage.format("Download JDK %s or later.", JAVA_MIN_RELEASE);
}
String value = System.getenv("JVMCI_VERSION_CHECK");
if ("warn".equals(value)) {
System.err.println(errorMessage.toString());
} else if ("ignore".equals(value)) {
return;
} else if (exit) {
System.err.println(errorMessage.toString());
System.exit(-1);
} else {
throw new InternalError(errorMessage.toString());
}
}

private final String javaSpecVersion;
private final String vmVersion;
private final Map<String, String> props;
Expand Down Expand Up @@ -295,46 +269,114 @@ static void check(Map<String, String> props, boolean exitOnFailure, PrintFormat
* </ul>
*/
public static void check(Map<String, String> props, boolean exitOnFailure, PrintFormat format, Map<String, Map<String, Version>> jvmciMinVersions) {
JVMCIVersionCheck checker = newJVMCIVersionCheck(props);
String reason = checker.run(getMinVersion(props, jvmciMinVersions), format);
if (reason != null) {
Formatter errorMessage = new Formatter().format("%s%n", reason);
errorMessage.format("Set the JVMCI_VERSION_CHECK environment variable to \"ignore\" to suppress ");
errorMessage.format("this error or to \"warn\" to emit a warning and continue execution.%n");
checker.appendJVMInfo(errorMessage);
failVersionCheck(exitOnFailure, errorMessage.toString());
}
}

private static JVMCIVersionCheck newJVMCIVersionCheck(Map<String, String> props) {
String javaSpecVersion = getRequiredProperty(props, "java.specification.version");
String javaVmVersion = getRequiredProperty(props, "java.vm.version");
JVMCIVersionCheck checker = new JVMCIVersionCheck(props, javaSpecVersion, javaVmVersion);
checker.run(exitOnFailure, getMinVersion(props, jvmciMinVersions), format);
return new JVMCIVersionCheck(props, javaSpecVersion, javaVmVersion);
}

private void appendJVMInfo(Formatter formatter) {
String javaHome = props.get("java.home");
String vmName = props.get("java.vm.name");
formatter.format("Currently used Java home directory is %s.%n", javaHome);
formatter.format("Currently used VM configuration is: %s%n", vmName);
if (vmVersion.contains("-jvmci-")) {
formatter.format("Download the latest Labs OpenJDK from " + OPEN_LABSJDK_RELEASE_URL_PATTERN);
} else {
formatter.format("Download JDK %s or later.", JAVA_MIN_RELEASE);
}
}

private void run(boolean exitOnFailure, Version minVersion, PrintFormat format) {
private static void failVersionCheck(boolean exit, String errorMessage) {
String value = System.getenv("JVMCI_VERSION_CHECK");
if ("warn".equals(value)) {
System.err.println(errorMessage);
} else if ("ignore".equals(value)) {
return;
} else if (exit) {
System.err.println(errorMessage);
System.exit(-1);
} else {
throw new InternalError(errorMessage);
}
}

/**
* Checks the JVMCI version, returning an error message if an issue is found, or {@code null} if
* no error is detected.
*
* @param props system properties with the following required properties:
* <ul>
* <li>{@code java.specification.version}: Java specification version, e.g.,
* {@code "21"}</li>
* <li>{@code java.vm.version}: Full Java VM version string, e.g.,
* {@code "21+35"}</li>
* <li>{@code java.vm.vendor}: The vendor of the Java VM, e.g.,
* {@code "GraalVM Community"}</li>
* </ul>
* @return an error message if the version check fails, or {@code null} if no error is detected
*/
public static String check(Map<String, String> props) {
JVMCIVersionCheck checker = newJVMCIVersionCheck(props);
String reason = checker.run(getMinVersion(props, JVMCI_MIN_VERSIONS), null);
if (reason != null) {
Formatter errorMessage = new Formatter().format("%s%n", reason);
checker.appendJVMInfo(errorMessage);
return errorMessage.toString();
}
return null;
}

/**
* Performs the JVMCI version check.
*
* @return an error message if the version check fails, or {@code null} if no error is detected
*/
private String run(Version minVersion, PrintFormat format) {
if (javaSpecVersion.compareTo(Integer.toString(JAVA_MIN_RELEASE)) < 0) {
failVersionCheck(exitOnFailure, "Graal requires JDK " + JAVA_MIN_RELEASE + " or later.%n");
return "Graal requires JDK " + JAVA_MIN_RELEASE + " or later.";
} else {
if (vmVersion.contains("SNAPSHOT")) {
return;
return null;
}
if (vmVersion.contains("internal")) {
// Allow local builds
return;
return null;
}
if (!vmVersion.contains("-jvmci-")) {
var rv = Runtime.Version.parse(vmVersion);
if (rv.pre().isPresent() && !"ea".equals(rv.pre().get())) {
// Not a release or early access OpenJDK version
return;
return null;
}
}
// A "labsjdk" or a known OpenJDK
if (minVersion == null) {
failVersionCheck(exitOnFailure, "No minimum JVMCI version specified for JDK version %s.%n", javaSpecVersion);
return String.format("No minimum JVMCI version specified for JDK version %s.", javaSpecVersion);
}
Version v = Version.parse(vmVersion);
if (v != null) {
if (format != null) {
System.out.println(v.printFormat(format));
}
if (v.isLessThan(minVersion)) {
failVersionCheck(exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal: %s < %s.%n", v, minVersion);
return String.format("The VM does not support the minimum JVMCI API version required by Graal: %s < %s.", v, minVersion);
}
return;
return null;
}
failVersionCheck(exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" +
"Cannot read JVMCI version from java.vm.version property: %s.%n", vmVersion);
return String.format("The VM does not support the minimum JVMCI API version required by Graal.%n" +
"Cannot read JVMCI version from java.vm.version property: %s.", vmVersion);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@

import jdk.graal.compiler.hotspot.CompilerConfigurationFactory;
import jdk.graal.compiler.hotspot.HotSpotGraalOptionValues;
import jdk.graal.compiler.hotspot.JVMCIVersionCheck;
import jdk.graal.compiler.options.OptionValues;
import jdk.graal.compiler.truffle.AbstractTruffleCompilationSupport;

import com.oracle.truffle.compiler.TruffleCompiler;
import com.oracle.truffle.compiler.TruffleCompilerRuntime;

import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
import jdk.vm.ci.services.Services;

import java.io.BufferedReader;
import java.io.IOException;
Expand Down Expand Up @@ -93,4 +95,8 @@ public static String readCompilerVersion() {
throw new InternalError(ioe);
}
}

public static String verifyJVMCIVersion() {
return JVMCIVersionCheck.check(Services.getSavedProperties());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,10 @@ protected static TruffleRuntime createRuntime() {
Class<?> hotspotCompilationSupport = Class.forName(compilerModule, pkg + ".HotSpotTruffleCompilationSupport");
compilationSupport = (TruffleCompilationSupport) hotspotCompilationSupport.getConstructor().newInstance();
if (!Boolean.getBoolean("polyglotimpl.DisableVersionChecks")) {
String jvmciVersionCheckError = verifyJVMCIVersion(hotspotCompilationSupport);
if (jvmciVersionCheckError != null) {
return new DefaultTruffleRuntime(jvmciVersionCheckError);
}
Version truffleVersion = getTruffleVersion();
Version compilerVersion = getCompilerVersion(compilationSupport);
if (!compilerVersion.equals(truffleVersion)) {
Expand Down Expand Up @@ -258,6 +262,25 @@ private static Version getCompilerVersion(TruffleCompilationSupport compilationS
return compilerVersionString != null ? Version.parse(compilerVersionString) : Version.create(23, 1, 1);
}

private static String verifyJVMCIVersion(Class<?> hotspotCompilationSupport) {
/*
* The TruffleCompilationSupport is present in both the maven artifact
* org.graalvm.truffle/truffle-compiler and the JDK org.graalvm.truffle.compiler module. The
* JDK version of TruffleCompilationSupport may be outdated and lack the verifyJVMCIVersion
* method. To address this, we use reflection.
*/
String errorMessage = null;
try {
Method verifyJVMCIVersion = hotspotCompilationSupport.getDeclaredMethod("verifyJVMCIVersion");
errorMessage = (String) verifyJVMCIVersion.invoke(null);
} catch (NoSuchMethodException noMethod) {
// pass with result set to true
} catch (ReflectiveOperationException e) {
throw new InternalError(e);
}
return errorMessage;
}

/**
* Handle history of renamings applied to Graal.
*/
Expand Down

0 comments on commit 0591618

Please sign in to comment.