From 059161834d0df9c6e2c955ceb0b1a055c2a63f46 Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Tue, 16 Jul 2024 13:03:35 +0200 Subject: [PATCH] [GR-55115] Truffle-side version check for jargraal. (cherry picked from commit 8cbccfe885512db1b16cd610cee71d4de633752e) --- .../compiler/hotspot/JVMCIVersionCheck.java | 118 ++++++++++++------ .../HotSpotTruffleCompilationSupport.java | 6 + .../hotspot/HotSpotTruffleRuntimeAccess.java | 23 ++++ 3 files changed, 109 insertions(+), 38 deletions(-) diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java index ccc9700b17d0..26572adc16e3 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java @@ -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 props; @@ -295,33 +269,101 @@ static void check(Map props, boolean exitOnFailure, PrintFormat * */ public static void check(Map props, boolean exitOnFailure, PrintFormat format, Map> 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 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: + *
    + *
  • {@code java.specification.version}: Java specification version, e.g., + * {@code "21"}
  • + *
  • {@code java.vm.version}: Full Java VM version string, e.g., + * {@code "21+35"}
  • + *
  • {@code java.vm.vendor}: The vendor of the Java VM, e.g., + * {@code "GraalVM Community"}
  • + *
+ * @return an error message if the version check fails, or {@code null} if no error is detected + */ + public static String check(Map 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) { @@ -329,12 +371,12 @@ private void run(boolean exitOnFailure, Version minVersion, PrintFormat format) 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); } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/HotSpotTruffleCompilationSupport.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/HotSpotTruffleCompilationSupport.java index ae85051f31a8..f41fd91982e4 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/HotSpotTruffleCompilationSupport.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/HotSpotTruffleCompilationSupport.java @@ -26,6 +26,7 @@ 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; @@ -33,6 +34,7 @@ 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; @@ -93,4 +95,8 @@ public static String readCompilerVersion() { throw new InternalError(ioe); } } + + public static String verifyJVMCIVersion() { + return JVMCIVersionCheck.check(Services.getSavedProperties()); + } } diff --git a/truffle/src/com.oracle.truffle.runtime/src/com/oracle/truffle/runtime/hotspot/HotSpotTruffleRuntimeAccess.java b/truffle/src/com.oracle.truffle.runtime/src/com/oracle/truffle/runtime/hotspot/HotSpotTruffleRuntimeAccess.java index 8f21fbe0e888..3c5f2cba3423 100644 --- a/truffle/src/com.oracle.truffle.runtime/src/com/oracle/truffle/runtime/hotspot/HotSpotTruffleRuntimeAccess.java +++ b/truffle/src/com.oracle.truffle.runtime/src/com/oracle/truffle/runtime/hotspot/HotSpotTruffleRuntimeAccess.java @@ -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)) { @@ -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. */