From 504159b21b55be0406569b6c01ea2321fdab2f1b Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Tue, 2 Apr 2024 14:14:04 +0200 Subject: [PATCH 1/8] Support OpenJDK versions in JVMCIVersionCheck --- .../compiler/hotspot/JVMCIVersionCheck.java | 81 +++++++++++++------ 1 file changed, 58 insertions(+), 23 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 b73f0c254e90..5f1cd7381f45 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 @@ -31,6 +31,7 @@ import java.util.Properties; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; /** * Mechanism for checking that the current Java runtime environment supports the minimum JVMCI API @@ -68,6 +69,7 @@ public static class Version { private final int jvmciMinor; private final int jvmciBuild; private final boolean legacy; + private final boolean isOpenJDK; static Version parse(String vmVersion) { Matcher m = Pattern.compile("(.+)-jvmci(-(\\d+)\\.(\\d+))?-b(\\d+).*").matcher(vmVersion); @@ -88,16 +90,45 @@ static Version parse(String vmVersion) { } catch (NumberFormatException e) { // ignore } + } else { + try { + // assume OpenJDK version + return new Version(stripVersion(vmVersion)); + } catch (IllegalArgumentException e) { + // ignore + } } return null; } + /** + * Returns a {@linkplain java.lang.Runtime.Version version string} without + * {@link java.lang.Runtime.Version#pre()} and {@link java.lang.Runtime.Version#optional()}. + */ + private static String stripVersion(String versionString) { + var rv = Runtime.Version.parse(versionString); + var sb = new StringBuilder(rv.version().stream().map(Object::toString).collect(Collectors.joining("."))); + if (rv.build().isPresent()) { + sb.append("+").append(rv.build().get()); + } + return sb.toString(); + } + /** * Convenience constructor for the current version scheme that only uses the JDK version and * the JVMCI build number. */ public Version(String jdkVersionString, int jvmciBuild) { - this(jdkVersionString, NA, NA, jvmciBuild, false); + this(jdkVersionString, NA, NA, jvmciBuild, false, false); + } + + /** + * Convenience constructor for the current version scheme that only uses the JDK version + * without a JVMCI build number. This is used when running on a plain OpenJDK, not + * a custom LabsJDK build. + */ + public Version(String jdkVersionString) { + this(jdkVersionString, NA, NA, NA, false, true); } /** @@ -105,19 +136,20 @@ public Version(String jdkVersionString, int jvmciBuild) { * to {@code 21}. While this is not entirely correct, it works for our purposes. */ public Version(int jvmciMajor, int jvmciMinor, int jvmciBuild) { - this("21", jvmciMajor, jvmciMinor, jvmciBuild, true); + this("21", jvmciMajor, jvmciMinor, jvmciBuild, true, false); } - private Version(String jdkVersionString, int jvmciMajor, int jvmciMinor, int jvmciBuild, boolean legacy) { - this(Runtime.Version.parse(jdkVersionString), jvmciMajor, jvmciMinor, jvmciBuild, legacy); + private Version(String jdkVersionString, int jvmciMajor, int jvmciMinor, int jvmciBuild, boolean legacy, boolean isOpenJDK) { + this(Runtime.Version.parse(jdkVersionString), jvmciMajor, jvmciMinor, jvmciBuild, legacy, isOpenJDK); } - private Version(Runtime.Version jdkVersion, int jvmciMajor, int jvmciMinor, int jvmciBuild, boolean legacy) { + private Version(Runtime.Version jdkVersion, int jvmciMajor, int jvmciMinor, int jvmciBuild, boolean legacy, boolean isOpenJDK) { this.jdkVersion = jdkVersion; this.jvmciMajor = jvmciMajor; this.jvmciMinor = jvmciMinor; this.jvmciBuild = jvmciBuild; this.legacy = legacy; + this.isOpenJDK = isOpenJDK; } boolean isGreaterThan(Version other) { @@ -132,11 +164,15 @@ public boolean isLessThan(Version other) { return true; } if (this.legacy == other.legacy) { - int compareTo = this.legacy ? 0 : this.jdkVersion.compareTo(other.jdkVersion); + int compareTo = this.legacy ? 0 : this.jdkVersion.compareToIgnoreOptional(other.jdkVersion); if (compareTo < 0) { return true; } if (compareTo == 0) { + if (this.isOpenJDK != other.isOpenJDK) { + // comparing OpenJDK version with LabsJDK version. + return false; + } if (this.jvmciMajor < other.jvmciMajor) { return true; } @@ -171,6 +207,9 @@ public int hashCode() { @Override public String toString() { + if (isOpenJDK) { + return jdkVersion.toString(); + } if (!legacy) { return String.format(AS_TAG_FORMAT_22_AND_LATER, jdkVersion, jvmciBuild); } else { @@ -271,26 +310,22 @@ private void run(boolean exitOnFailure, Version minVersion, PrintFormat format) // Allow local builds return; } - if (vmVersion.contains("-jvmci-")) { - // A "labsjdk" - if (minVersion == null) { - failVersionCheck(exitOnFailure, "No minimum JVMCI version specified for JDK version %s.%n", javaSpecVersion); + // A "labsjdk" + if (minVersion == null) { + failVersionCheck(exitOnFailure, "No minimum JVMCI version specified for JDK version %s.%n", javaSpecVersion); + } + Version v = Version.parse(vmVersion); + if (v != null) { + if (format != null) { + System.out.println(v.printFormat(format)); } - 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; + if (v.isLessThan(minVersion)) { + failVersionCheck(exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal: %s < %s.%n", v, minVersion); } - 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); - } else { - // Graal is compatible with all JDK versions as of JAVA_MIN_RELEASE + return; } + 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); } } From 61c489ae5290c496ca3af2e0da15688b0f0e846c Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Tue, 2 Apr 2024 16:47:47 +0200 Subject: [PATCH 2/8] compiler: support OpenJDK version with JVMCI_VERSION_CHECK=strict --- compiler/mx.compiler/mx_compiler.py | 74 +++++++++++++++++++++-------- 1 file changed, 55 insertions(+), 19 deletions(-) diff --git a/compiler/mx.compiler/mx_compiler.py b/compiler/mx.compiler/mx_compiler.py index 566ad5bc9946..c26ab955b13e 100644 --- a/compiler/mx.compiler/mx_compiler.py +++ b/compiler/mx.compiler/mx_compiler.py @@ -25,6 +25,7 @@ from __future__ import print_function import os +from functools import total_ordering from os.path import join, exists, basename, dirname, isdir import argparse from argparse import ArgumentParser, RawDescriptionHelpFormatter, REMAINDER @@ -124,10 +125,48 @@ def feature(self): self._feature = int(JavaLangRuntimeVersion._feature_re.match(self.version).group(0)) return self._feature +@total_ordering +class JVMCIVersionCheckVersion(object): + def __init__(self, jdk_version, jvmci_major, jvmci_minor, jvmci_build): + """ + Python version of jdk.graal.compiler.hotspot.JVMCIVersionCheck.Version + + jdk_version is a JavaLangRuntimeVersion + jvmci_major and jvmci_minor might be 0 if not needed (JDK 22+) + """ + assert isinstance(jdk_version, JavaLangRuntimeVersion) + assert isinstance(jvmci_major, int) + assert isinstance(jvmci_minor, int) + assert isinstance(jvmci_build, int) + self.jdk_version = jdk_version + self.jvmci_major = jvmci_major + self.jvmci_minor = jvmci_minor + self.jvmci_build = jvmci_build + + def _as_tuple(self): + return (self.jdk_version, self.jvmci_major, self.jvmci_minor, self.jvmci_build) + + def __eq__(self, other): + if not isinstance(other, JVMCIVersionCheckVersion): + return False + return self._as_tuple() == other._as_tuple() + + def __lt__(self, other): + if not isinstance(other, JVMCIVersionCheckVersion): + return NotImplemented + return self._as_tuple() < other._as_tuple() + + def __str__(self): + jdk_version, jvmci_major, jvmci_minor, jvmci_build = self._as_tuple() + if jvmci_major == 0: + if jvmci_build == 0: + return f'(openjdk|oraclejdk)-{jdk_version}' + else: + return f'labsjdk-(ce|ee)-{jdk_version}-jvmci-b{jvmci_build:02d}' + else: + return f'labsjdk-(ce|ee)-{jdk_version}-jvmci-{jvmci_major}.{jvmci_minor}-b{jvmci_build:02d}' + -#: 4-tuple (jdk_version, jvmci_major, jvmci_minor, jvmci_build) of JVMCI version, if any, denoted by `jdk` -# jdk_version is a JavaLangRuntimeVersion -# jvmci_major and jvmci_minor might be 0 if not needed (JDK 22+) _jdk_jvmci_version = None _jdk_min_jvmci_version = None @@ -145,7 +184,7 @@ def _capture_jvmci_version(args=None): if out.data: try: (jdk_version, jvmci_major, jvmci_minor, jvmci_build) = out.data.split(',') - return (JavaLangRuntimeVersion(jdk_version), int(jvmci_major), int(jvmci_minor), int(jvmci_build)) + return JVMCIVersionCheckVersion(JavaLangRuntimeVersion(jdk_version), int(jvmci_major), int(jvmci_minor), int(jvmci_build)) except ValueError: mx.warn(f'Could not parse jvmci version from JVMCIVersionCheck output:\n{out.data}') return None @@ -1165,7 +1204,7 @@ def _check_latest_jvmci_version(): ``common.json`` file and issues a warning if not. """ jvmci_re = re.compile(r'(?:ce|ee)-(?P.+)-jvmci(?:-(?P\d+)\.(?P\d+))?-b(?P\d+)') - common_path = join(_suite.dir, '..', 'common.json') + common_path = os.path.normpath(join(_suite.dir, '..', 'common.json')) if _jdk_jvmci_version is None: # Not using a JVMCI JDK @@ -1183,8 +1222,13 @@ def get_latest_jvmci_version(): if not match: mx.abort(f'Cannot parse version {version}') (jdk_version, jvmci_major, jvmci_minor, jvmci_build) = match.groups(default=0) - current = (JavaLangRuntimeVersion(jdk_version), int(jvmci_major), int(jvmci_minor), int(jvmci_build)) - if current[0].feature() == _jdk_jvmci_version[0].feature(): + if _jdk_jvmci_version.jvmci_build == 0: + # jvmci_build == 0 indicates an OpenJDK version has been specified in JVMCIVersionCheck.java. + # The JDK does not know the jvmci_build number that might have been specified in common.json, + # as it is only a repackaged JDK. Thus, we reset the jvmci_build because we cannot validate it. + jvmci_build = 0 + current = JVMCIVersionCheckVersion(JavaLangRuntimeVersion(jdk_version), int(jvmci_major), int(jvmci_minor), int(jvmci_build)) + if current.jdk_version.feature() == _jdk_jvmci_version.jdk_version.feature(): # only compare the same major versions if latest == 'not found': latest = current @@ -1196,20 +1240,13 @@ def get_latest_jvmci_version(): return False, distribution return not isinstance(latest, str), latest - def jvmci_version_str(version): - jdk_version, jvmci_major, jvmci_minor, jvmci_build = version - if jvmci_major == 0: - return f'labsjdk-(ce|ee)-{jdk_version}-jvmci-b{jvmci_build:02d}' - else: - return f'labsjdk-(ce|ee)-{jdk_version}-jvmci-{jvmci_major}.{jvmci_minor}-b{jvmci_build:02d}' - version_check_setting = os.environ.get('JVMCI_VERSION_CHECK', None) success, latest = get_latest_jvmci_version() if version_check_setting == 'strict' and _jdk_jvmci_version != _jdk_min_jvmci_version: msg = f'JVMCI_MIN_VERSION specified in JVMCIVersionCheck.java is older than in {common_path}:' - msg += os.linesep + f'{jvmci_version_str(_jdk_min_jvmci_version)} < {jvmci_version_str(_jdk_jvmci_version)} ' + msg += os.linesep + f'{_jdk_min_jvmci_version} < {_jdk_jvmci_version} ' msg += os.linesep + f'Did you forget to update JVMCI_MIN_VERSION after updating {common_path}?' msg += os.linesep + 'Set the JVMCI_VERSION_CHECK environment variable to something else then "strict" to' msg += ' suppress this error.' @@ -1217,7 +1254,7 @@ def jvmci_version_str(version): if version_check_setting == 'strict' and not success: if latest == 'not found': - msg = f'No JVMCI JDK found in {common_path} that matches {jvmci_version_str(_jdk_jvmci_version)}.' + msg = f'No JVMCI JDK found in {common_path} that matches {_jdk_jvmci_version}.' msg += os.linesep + f'Check that {latest} matches the versions of the other JVMCI JDKs.' else: msg = f'Version mismatch in {common_path}:' @@ -1227,10 +1264,9 @@ def jvmci_version_str(version): mx.abort(msg) if success and _jdk_jvmci_version < latest: - common_path = os.path.normpath(common_path) - msg = f'JVMCI version of JAVA_HOME is older than in {common_path}: {jvmci_version_str(_jdk_jvmci_version)} < {jvmci_version_str(latest)} ' + msg = f'JVMCI version of JAVA_HOME is older than in {common_path}: {_jdk_jvmci_version} < {latest} ' msg += os.linesep + 'This poses the risk of hitting JVMCI bugs that have already been fixed.' - msg += os.linesep + f'Consider using {jvmci_version_str(latest)}, which you can get via:' + msg += os.linesep + f'Consider using {latest}, which you can get via:' msg += os.linesep + f'mx fetch-jdk --configuration {common_path}' mx.abort_or_warn(msg, version_check_setting == 'strict') From 1543c02dbb820284b0d6057ce3301da95d444120 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Mon, 8 Apr 2024 10:10:47 +0200 Subject: [PATCH 3/8] compiler: use well-named factory methods for creating JVMCIVersionCheck.Version objects --- .../test/JVMCIVersionCheckMaxValueTest.java | 2 +- .../hotspot/test/JVMCIVersionCheckTest.java | 4 +- .../test/JVMCIVersionCheckVendorTest.java | 4 +- .../compiler/hotspot/JVMCIVersionCheck.java | 50 ++++++++++++------- 4 files changed, 36 insertions(+), 24 deletions(-) diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/JVMCIVersionCheckMaxValueTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/JVMCIVersionCheckMaxValueTest.java index f43b22766813..7a8c61a47673 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/JVMCIVersionCheckMaxValueTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/JVMCIVersionCheckMaxValueTest.java @@ -54,7 +54,7 @@ public void testNewVersion() { private static void testVersion(String javaVmVersion) { try { - JVMCIVersionCheck.Version minVersion = new JVMCIVersionCheck.Version(20, 0, 1); + JVMCIVersionCheck.Version minVersion = JVMCIVersionCheck.createLegacyVersion(20, 0, 1); // Use a javaSpecVersion that will likely not fail in the near future String javaSpecVersion = "99"; var props = JVMCIVersionCheckTest.createTestProperties(javaSpecVersion, javaVmVersion, null); diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/JVMCIVersionCheckTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/JVMCIVersionCheckTest.java index df02322a252f..1ae2ce178322 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/JVMCIVersionCheckTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/JVMCIVersionCheckTest.java @@ -110,10 +110,10 @@ public static Collection data() { private static Version getVersion(String jdkVersion, int major, int minor, int build) { if (jdkVersion != null) { // new version scheme - return new Version(jdkVersion, build); + return JVMCIVersionCheck.createLabsJDKVersion(jdkVersion, build); } else { // legacy version scheme - return new Version(major, minor, build); + return JVMCIVersionCheck.createLegacyVersion(major, minor, build); } } diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/JVMCIVersionCheckVendorTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/JVMCIVersionCheckVendorTest.java index 4c9bfa6ece76..f08ef1dbd2f9 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/JVMCIVersionCheckVendorTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/JVMCIVersionCheckVendorTest.java @@ -41,8 +41,8 @@ public class JVMCIVersionCheckVendorTest extends GraalCompilerTest { private static final Map> VERSION_MAP = Map.of("99", Map.of( - DEFAULT_VENDOR_ENTRY, new JVMCIVersionCheck.Version("99+99", 1), - "Vendor Specific", new JVMCIVersionCheck.Version("99.0.1", 1))); + DEFAULT_VENDOR_ENTRY, JVMCIVersionCheck.createLabsJDKVersion("99+99", 1), + "Vendor Specific", JVMCIVersionCheck.createLabsJDKVersion("99.0.1", 1))); private static void expect(String javaVmVendor, String expected) { var props = JVMCIVersionCheckTest.createTestProperties("99", null, javaVmVendor); 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 5f1cd7381f45..e594776c1611 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 @@ -63,6 +63,31 @@ public final class JVMCIVersionCheck { */ private static final int JAVA_MIN_RELEASE = 21; + /** + * Convenience factory for the current version scheme that only uses the JDK version and the + * JVMCI build number. + */ + public static Version createLabsJDKVersion(String jdkVersionString, int jvmciBuild) { + return new Version(jdkVersionString, jvmciBuild); + } + + /** + * Convenience factory for the current version scheme that only uses the JDK version + * without a JVMCI build number. This is used when running on a plain OpenJDK, not a + * custom LabsJDK build. + */ + public static Version createOpenJDKVersion(String jdkVersionString) { + return new Version(jdkVersionString); + } + + /** + * Legacy factory for versions without JDK version. This force sets {@link Version#jdkVersion} + * to {@code 21}. While this is not entirely correct, it works for our purposes. + */ + public static Version createLegacyVersion(int jvmciMajor, int jvmciMinor, int jvmciBuild) { + return new Version(jvmciMajor, jvmciMinor, jvmciBuild); + } + public static class Version { private final Runtime.Version jdkVersion; private final int jvmciMajor; @@ -79,12 +104,12 @@ static Version parse(String vmVersion) { assert m.group(4) == null : "if jvmciMajor is null jvmciMinor must also be null"; String jdkVersion = m.group(1); int jvmciBuild = Integer.parseInt(m.group(5)); - return new Version(jdkVersion, jvmciBuild); + return createLabsJDKVersion(jdkVersion, jvmciBuild); } else { int jvmciMajor = Integer.parseInt(m.group(3)); int jvmciMinor = Integer.parseInt(m.group(4)); int jvmciBuild = Integer.parseInt(m.group(5)); - return new Version(jvmciMajor, jvmciMinor, jvmciBuild); + return createLegacyVersion(jvmciMajor, jvmciMinor, jvmciBuild); } } catch (NumberFormatException e) { @@ -93,7 +118,7 @@ static Version parse(String vmVersion) { } else { try { // assume OpenJDK version - return new Version(stripVersion(vmVersion)); + return createOpenJDKVersion(stripVersion(vmVersion)); } catch (IllegalArgumentException e) { // ignore } @@ -114,28 +139,15 @@ private static String stripVersion(String versionString) { return sb.toString(); } - /** - * Convenience constructor for the current version scheme that only uses the JDK version and - * the JVMCI build number. - */ - public Version(String jdkVersionString, int jvmciBuild) { + private Version(String jdkVersionString, int jvmciBuild) { this(jdkVersionString, NA, NA, jvmciBuild, false, false); } - /** - * Convenience constructor for the current version scheme that only uses the JDK version - * without a JVMCI build number. This is used when running on a plain OpenJDK, not - * a custom LabsJDK build. - */ - public Version(String jdkVersionString) { + private Version(String jdkVersionString) { this(jdkVersionString, NA, NA, NA, false, true); } - /** - * Legacy construction for versions without JDK version. This force sets {@link #jdkVersion} - * to {@code 21}. While this is not entirely correct, it works for our purposes. - */ - public Version(int jvmciMajor, int jvmciMinor, int jvmciBuild) { + private Version(int jvmciMajor, int jvmciMinor, int jvmciBuild) { this("21", jvmciMajor, jvmciMinor, jvmciBuild, true, false); } From 39d249732ad739b0ef3737d558aab183fd376a2c Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Tue, 2 Apr 2024 14:46:28 +0200 Subject: [PATCH 4/8] compiler: add JVMCIVersionCheckOpenJDKTest --- .../test/JVMCIVersionCheckOpenJDKTest.java | 140 ++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/JVMCIVersionCheckOpenJDKTest.java diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/JVMCIVersionCheckOpenJDKTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/JVMCIVersionCheckOpenJDKTest.java new file mode 100644 index 000000000000..5c439ccb9a53 --- /dev/null +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/JVMCIVersionCheckOpenJDKTest.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2024, 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.test; + +import org.junit.Assert; +import org.junit.Test; + +import jdk.graal.compiler.core.test.GraalCompilerTest; +import jdk.graal.compiler.hotspot.JVMCIVersionCheck; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static jdk.graal.compiler.hotspot.JVMCIVersionCheck.DEFAULT_VENDOR_ENTRY; + +/** + * Tests that {@link JVMCIVersionCheck} handles OpenJDK versions correctly. + */ +@RunWith(Parameterized.class) +public class JVMCIVersionCheckOpenJDKTest extends GraalCompilerTest { + + @Parameterized.Parameters(name = "{0} <= {1} = {2}") + public static Collection data() { + return List.of( + /* + * If comparing a LabsJDK version against an OpenJDK version, ignore the + * JVMCI build number. + */ + expectFail("99+99-jvmci-b02", "99+98"), + expectPass("99+99-jvmci-b02", "99+99"), + expectPass("99+99-jvmci-b02", "99+100"), + /* + * If comparing a LabsJDK version against a LabsJDK version, respect the + * JVMCI build. + */ + expectFail("99+99-jvmci-b02", "99+98-jvmci-b01"), + expectFail("99+99-jvmci-b02", "99+98-jvmci-b02"), + expectFail("99+99-jvmci-b02", "99+98-jvmci-b03"), + + expectFail("99+99-jvmci-b02", "99+99-jvmci-b01"), + expectPass("99+99-jvmci-b02", "99+99-jvmci-b02"), + expectPass("99+99-jvmci-b02", "99+99-jvmci-b03"), + + expectPass("99+99-jvmci-b02", "99+100-jvmci-b01"), + expectPass("99+99-jvmci-b02", "99+100-jvmci-b02"), + expectPass("99+99-jvmci-b02", "99+100-jvmci-b03"), + + /* Comparing an OpenJDK version against an OpenJDK version. */ + expectFail("99+99", "99+98"), + expectPass("99+99", "99+99"), + expectPass("99+99", "99+100"), + + /* Comparing an OpenJDK version against a LabsJDK version. */ + expectFail("99+99", "99+98-jvmci-b01"), + expectPass("99+99", "99+99-jvmci-b01"), + expectPass("99+99", "99+100-jvmci-b01")); + } + + private static Object[] expectPass(String minVersion, String javaVmVersion) { + return new Object[]{minVersion, javaVmVersion, true}; + } + + private static Object[] expectFail(String minVersion, String javaVmVersion) { + return new Object[]{minVersion, javaVmVersion, false}; + } + + @Parameterized.Parameter(0) public String minVersion; + @Parameterized.Parameter(1) public String javaVmVersion; + @Parameterized.Parameter(2) public boolean expectSuccess; + + @Test + public void compareToMinVersion() { + if (checkVersionProperties(getMinVersionMap(minVersion), javaVmVersion)) { + if (!expectSuccess) { + Assert.fail(String.format("Expected %s to be older than %s", javaVmVersion, minVersion)); + } + } else { + if (expectSuccess) { + Assert.fail(String.format("Expected %s not to be older than %s", javaVmVersion, minVersion)); + } + + } + } + + private static Map> getMinVersionMap(String minVersion) { + Runtime.Version version = Runtime.Version.parse(minVersion); + if (version.optional().isEmpty()) { + // OpenJDK version + return Map.of(Integer.toString(version.feature()), Map.of( + DEFAULT_VENDOR_ENTRY, JVMCIVersionCheck.createOpenJDKVersion(minVersion))); + } else { + // LabsJDK version + String optional = version.optional().get(); + // get the jvmci build number + Assert.assertTrue("expected jvmci build number", optional.startsWith("jvmci-b")); + int jvmciBuild = Integer.parseInt(optional.split("jvmci-b", 2)[1]); + // get the version string without the option part + String versionWithoutOptional = version.toString().split("-" + optional, 2)[0]; + return Map.of(Integer.toString(version.feature()), Map.of( + DEFAULT_VENDOR_ENTRY, JVMCIVersionCheck.createLabsJDKVersion(versionWithoutOptional, jvmciBuild))); + } + } + + private static boolean checkVersionProperties(Map> minVersionMap, String javaVmVersion) { + String javaSpecVersion = Integer.toString(Runtime.Version.parse(javaVmVersion).feature()); + var props = JVMCIVersionCheckTest.createTestProperties(javaSpecVersion, javaVmVersion, null); + try { + JVMCIVersionCheck.check(props, false, null, minVersionMap); + return true; + } catch (InternalError e) { + return false; + } + } + +} From 64a79a2eb104bc31f6e59cc59d80cb96f77b9841 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Mon, 8 Apr 2024 10:42:24 +0200 Subject: [PATCH 5/8] svm: add a helloworld gate running on oraclejdk --- substratevm/ci/ci.jsonnet | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/substratevm/ci/ci.jsonnet b/substratevm/ci/ci.jsonnet index f89c6c406b2d..21a6645731ea 100644 --- a/substratevm/ci/ci.jsonnet +++ b/substratevm/ci/ci.jsonnet @@ -25,6 +25,10 @@ local use_musl = sg.use_musl, local add_quickbuild = sg.add_quickbuild, + local use_oraclejdk_latest = task_spec(run_spec.evaluate_late({ + "use_oraclejdk_latest": common.oraclejdkLatest + galahad.exclude + })), + local maven = task_spec(evaluate_late('05_add_maven', function(b) if b.os == 'windows' then { downloads+: { @@ -128,6 +132,9 @@ "linux:amd64:jdk-latest": gate + gdb("10.2") + t("55:00"), }, }), + "oraclejdk-helloworld": mxgate("build,helloworld,hellomodule") + maven + jsonschema + platform_spec(no_jobs) + platform_spec({ + "linux:amd64:jdk-latest": gate + use_oraclejdk_latest + t("30:00"), + }), }, // END MAIN BUILD DEFINITION processed_builds::run_spec.process(task_dict), From f61909c6c85f239752d87e556ad9351c6bb19a20 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Mon, 8 Apr 2024 10:41:18 +0000 Subject: [PATCH 6/8] compiler: fix type in mx comment --- compiler/mx.compiler/mx_compiler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/mx.compiler/mx_compiler.py b/compiler/mx.compiler/mx_compiler.py index c26ab955b13e..b4511665451a 100644 --- a/compiler/mx.compiler/mx_compiler.py +++ b/compiler/mx.compiler/mx_compiler.py @@ -80,7 +80,7 @@ def get_vm_prefix(asList=True): class JavaLangRuntimeVersion(mx.Comparable): - """Wrapper for by java.lang.Runtime.Version""" + """Wrapper for java.lang.Runtime.Version""" _cmp_cache = {} _feature_re = re.compile('[1-9][0-9]*') From a61bd8b7d0474b117be58bbd840c76ff42904b4f Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Thu, 11 Apr 2024 10:01:18 +0200 Subject: [PATCH 7/8] compiler: improve comments JVMCIVersionCheck.Version#parse --- .../src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java | 4 ++-- 1 file changed, 2 insertions(+), 2 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 e594776c1611..419b54cdc281 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 @@ -113,14 +113,14 @@ static Version parse(String vmVersion) { } } catch (NumberFormatException e) { - // ignore + // cannot parse JVMCI version numbers -> be on the safe side and ignore } } else { try { // assume OpenJDK version return createOpenJDKVersion(stripVersion(vmVersion)); } catch (IllegalArgumentException e) { - // ignore + // unexpected version string -> be on the safe side and ignore } } return null; From 9d2481d7b313797b56b7f5c1dd004e46397a3a6d Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Thu, 11 Apr 2024 10:26:54 +0200 Subject: [PATCH 8/8] compiler: make JVMCIVersionCheck.Version final --- .../src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 419b54cdc281..dbbb1e8e8662 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 @@ -88,7 +88,7 @@ public static Version createLegacyVersion(int jvmciMajor, int jvmciMinor, int jv return new Version(jvmciMajor, jvmciMinor, jvmciBuild); } - public static class Version { + public static final class Version { private final Runtime.Version jdkVersion; private final int jvmciMajor; private final int jvmciMinor;