Skip to content

Commit e1edcf1

Browse files
authored
Merge pull request #169 from bulasevich/GR-59688
[Backport][GR-59688] Allow compiler newer than Truffle runtime in a minor version.
2 parents c43cf29 + 02f1acd commit e1edcf1

File tree

5 files changed

+143
-23
lines changed

5 files changed

+143
-23
lines changed

sdk/src/org.graalvm.home.test/src/org/graalvm/home/test/VersionTest.java

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -48,10 +48,12 @@
4848
import static org.junit.Assert.fail;
4949

5050
import java.util.ArrayList;
51+
import java.util.Arrays;
5152
import java.util.Collections;
5253
import java.util.List;
5354

5455
import org.graalvm.home.Version;
56+
import org.junit.Assert;
5557
import org.junit.Test;
5658

5759
public class VersionTest {
@@ -208,6 +210,40 @@ public void testFormat() {
208210
assertFormat("%%[R%d.%%d]", "23.0", "%[R23.%d]");
209211
}
210212

213+
@Test
214+
public void testGetComponents() {
215+
Version version = Version.create(23, 1, 4);
216+
try {
217+
version.getComponent(-1);
218+
Assert.fail("Should not reach here");
219+
} catch (IllegalArgumentException illegalArgument) {
220+
// expected
221+
}
222+
assertVersionComponents(new int[]{23, 1, 4, 0}, version);
223+
version = Version.create(23, 1);
224+
assertVersionComponents(new int[]{23, 1, 0, 0}, version);
225+
version = Version.create(23);
226+
assertVersionComponents(new int[]{23, 0, 0, 0}, version);
227+
version = Version.create(23, 0, 0);
228+
assertVersionComponents(new int[]{23, 0, 0, 0}, version);
229+
version = Version.parse("23.1.4");
230+
assertVersionComponents(new int[]{23, 1, 4, 0}, version);
231+
version = Version.parse("23.1.4-snapshot");
232+
assertVersionComponents(new int[]{23, 1, 4, 0}, version);
233+
version = Version.parse("23.1.4-dev");
234+
assertVersionComponents(new int[]{23, 1, 4, 0}, version);
235+
version = Version.parse("dev");
236+
assertVersionComponents(new int[]{0, 0, 0, 0}, version);
237+
version = Version.parse("snapshot");
238+
assertVersionComponents(new int[]{0, 0, 0, 0}, version);
239+
}
240+
241+
private static void assertVersionComponents(int[] expectedComponents, Version version) {
242+
for (int i = 0; i < expectedComponents.length; i++) {
243+
assertEquals("Expected " + Arrays.toString(expectedComponents) + "components in " + version, expectedComponents[i], version.getComponent(i));
244+
}
245+
}
246+
211247
private static void assertFormat(String format, String version, String expected) {
212248
Version v = Version.parse(version);
213249
String result = v.format(format);

sdk/src/org.graalvm.home/snapshot.sigtest

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ meth public boolean equals(java.lang.Object)
3636
meth public boolean isRelease()
3737
meth public boolean isSnapshot()
3838
meth public int compareTo(org.graalvm.home.Version)
39+
meth public int getComponent(int)
3940
meth public int hashCode()
4041
meth public java.lang.String format(java.lang.String)
4142
meth public java.lang.String toString()

sdk/src/org.graalvm.home/src/org/graalvm/home/Version.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -338,6 +338,32 @@ public String format(String format) {
338338
return String.format(processFormat(format), args);
339339
}
340340

341+
/**
342+
* Retrieves the numeric value of the version component at the specified index.
343+
* <p>
344+
* Version components are indexed as follows:
345+
* <ul>
346+
* <li>{@code componentIndex = 0} represents the major version</li>
347+
* <li>{@code componentIndex = 1} represents the minor version</li>
348+
* <li>{@code componentIndex = 2} represents the update version</li>
349+
* </ul>
350+
* If the specified {@code componentIndex} exceeds the number of available components, the
351+
* method returns {@code 0}. For example, a version {@code 23.1} will return {@code 0} for
352+
* {@code componentIndex = 2}.
353+
* </p>
354+
*
355+
* @param componentIndex the index of the version component to retrieve; must be non-negative
356+
* @throws IllegalArgumentException if {@code componentIndex} is negative
357+
* @since 24.2
358+
* @see Version#create(int...)
359+
*/
360+
public int getComponent(int componentIndex) {
361+
if (componentIndex < 0) {
362+
throw new IllegalArgumentException("componentIndex must be non-negative: " + componentIndex);
363+
}
364+
return componentIndex < versions.length ? versions[componentIndex] : 0;
365+
}
366+
341367
/**
342368
* Parses a GraalVM version from its String raw format. Throws {@link IllegalArgumentException}
343369
* if the passed string is not a valid GraalVM version.

substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/TruffleBaseFeature.java

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -33,6 +33,9 @@
3333
import java.io.InputStream;
3434
import java.io.InputStreamReader;
3535
import java.lang.annotation.Annotation;
36+
import java.lang.invoke.MethodHandle;
37+
import java.lang.invoke.MethodHandles;
38+
import java.lang.invoke.MethodType;
3639
import java.lang.reflect.Constructor;
3740
import java.lang.reflect.Field;
3841
import java.lang.reflect.InvocationTargetException;
@@ -166,6 +169,20 @@
166169
*/
167170
public final class TruffleBaseFeature implements InternalFeature {
168171

172+
private static final MethodHandle VERSION_GET_COMPONENT = findVersionGetComponent();
173+
174+
@SuppressWarnings("unchecked")
175+
private static MethodHandle findVersionGetComponent() {
176+
try {
177+
return MethodHandles.lookup().findVirtual(Version.class, "getComponent", MethodType.methodType(int.class, int.class));
178+
} catch (ReflectiveOperationException e) {
179+
/*
180+
* Old org.graalvm.polyglot module without Version#getComponent(int) method.
181+
*/
182+
return null;
183+
}
184+
}
185+
169186
private static final String NATIVE_IMAGE_FILELIST_FILE_NAME = "native-image-resources.filelist";
170187

171188
private static final Version NEXT_POLYGLOT_VERSION_UPDATE = Version.create(25, 1);
@@ -306,11 +323,13 @@ private Object processInlinedField(Object obj) {
306323
public void afterRegistration(AfterRegistrationAccess a) {
307324
if (!Boolean.getBoolean("polyglotimpl.DisableVersionChecks")) {
308325
Version truffleVersion = getTruffleVersion(a);
326+
Version truffleMajorMinorVersion = stripUpdateVersion(truffleVersion);
309327
Version featureVersion = getSVMFeatureVersion();
328+
Version featureMajorMinorVersion = stripUpdateVersion(featureVersion);
310329
if (featureVersion.compareTo(NEXT_POLYGLOT_VERSION_UPDATE) >= 0) {
311330
throw new AssertionError("MAX_JDK_VERSION must be updated, please contact the Truffle team!");
312331
}
313-
if (featureVersion.compareTo(truffleVersion) > 0) {
332+
if (featureMajorMinorVersion.compareTo(truffleMajorMinorVersion) > 0) {
314333
// no forward compatibility
315334
throw throwVersionError("""
316335
Your Java runtime '%s' with native-image feature version '%s' is incompatible with polyglot version '%s'.
@@ -386,6 +405,28 @@ private Version getSVMFeatureVersion() {
386405
}
387406
}
388407

408+
private static Version stripUpdateVersion(Version version) {
409+
if (VERSION_GET_COMPONENT != null) {
410+
int major;
411+
int minor;
412+
try {
413+
major = (int) VERSION_GET_COMPONENT.invoke(version, 0);
414+
minor = (int) VERSION_GET_COMPONENT.invoke(version, 1);
415+
} catch (Throwable t) {
416+
throw new AssertionError(t);
417+
}
418+
if (major != 0 || minor != 0) {
419+
return Version.create(major, minor);
420+
} else {
421+
/*
422+
* Version represents a pure snapshot version without any numeric component.
423+
* Continue and return the original version.
424+
*/
425+
}
426+
}
427+
return version;
428+
}
429+
389430
private static RuntimeException throwVersionError(String errorFormat, Object... args) {
390431
StringBuilder errorMessage = new StringBuilder("Polyglot version compatibility check failed.\n");
391432
errorMessage.append(String.format(errorFormat, args));

truffle/src/com.oracle.truffle.runtime/src/com/oracle/truffle/runtime/hotspot/HotSpotTruffleRuntimeAccess.java

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -136,25 +136,30 @@ protected static TruffleRuntime createRuntime() {
136136
if (truffleVersion.compareTo(NEXT_VERSION_UPDATE) >= 0) {
137137
throw new AssertionError("MIN_COMPILER_VERSION, MIN_JDK_VERSION and MAX_JDK_VERSION must be updated!");
138138
}
139+
Version truffleMajorMinorVersion = stripUpdateVersion(truffleVersion);
139140
Version compilerVersion = getCompilerVersion(compilationSupport);
141+
Version compilerMajorMinorVersion = stripUpdateVersion(compilerVersion);
140142
int jdkFeatureVersion = Runtime.version().feature();
141143
if (jdkFeatureVersion < MIN_JDK_VERSION || jdkFeatureVersion >= MAX_JDK_VERSION) {
142-
throw throwVersionError("""
144+
return new DefaultTruffleRuntime(formatVersionWarningMessage("""
143145
Your Java runtime '%s' with compiler version '%s' is incompatible with polyglot version '%s'.
144146
The Java runtime version must be greater or equal to JDK '%d' and smaller than JDK '%d'.
145147
Update your Java runtime to resolve this.
146-
""", Runtime.version(), compilerVersion, truffleVersion, MIN_JDK_VERSION, MAX_JDK_VERSION);
147-
} else if (compilerVersion.compareTo(truffleVersion) > 0) {
148-
// no forward compatibility
149-
throw throwVersionError("""
148+
""", Runtime.version(), compilerVersion, truffleVersion, MIN_JDK_VERSION, MAX_JDK_VERSION));
149+
} else if (compilerMajorMinorVersion.compareTo(truffleMajorMinorVersion) > 0) {
150+
/*
151+
* Forward compatibility is supported only for minor updates, not for major
152+
* releases.
153+
*/
154+
return new DefaultTruffleRuntime(formatVersionWarningMessage("""
150155
Your Java runtime '%s' with compiler version '%s' is incompatible with polyglot version '%s'.
151156
Update the org.graalvm.polyglot versions to at least '%s' to resolve this.
152-
""", Runtime.version(), compilerVersion, truffleVersion, compilerVersion);
157+
""", Runtime.version(), compilerVersion, truffleVersion, compilerVersion));
153158
} else if (compilerVersion.compareTo(MIN_COMPILER_VERSION) < 0) {
154-
throw throwVersionError("""
159+
return new DefaultTruffleRuntime(formatVersionWarningMessage("""
155160
Your Java runtime '%s' with compiler version '%s' is incompatible with polyglot version '%s'.
156161
Update the Java runtime to the latest update release of JDK '%d'.
157-
""", Runtime.version(), compilerVersion, truffleVersion, jdkFeatureVersion);
162+
""", Runtime.version(), compilerVersion, truffleVersion, jdkFeatureVersion));
158163
}
159164
}
160165
} else {
@@ -171,12 +176,14 @@ protected static TruffleRuntime createRuntime() {
171176
compilationSupport = (TruffleCompilationSupport) hotspotCompilationSupport.getConstructor().newInstance();
172177
if (!Boolean.getBoolean("polyglotimpl.DisableVersionChecks")) {
173178
Version truffleVersion = getTruffleVersion();
179+
Version truffleMajorMinorVersion = stripUpdateVersion(truffleVersion);
174180
Version compilerVersion = getCompilerVersion(compilationSupport);
175-
if (!compilerVersion.equals(truffleVersion)) {
176-
throw throwVersionError("""
181+
Version compilerMajorMinorVersion = stripUpdateVersion(compilerVersion);
182+
if (!compilerMajorMinorVersion.equals(truffleMajorMinorVersion)) {
183+
return new DefaultTruffleRuntime(formatVersionWarningMessage("""
177184
The Graal compiler version '%s' is incompatible with polyglot version '%s'.
178185
Update the compiler version to '%s' to resolve this.
179-
""", compilerVersion, truffleVersion, truffleVersion);
186+
""", compilerVersion, truffleVersion, truffleVersion));
180187
}
181188
}
182189
} catch (ReflectiveOperationException e) {
@@ -188,18 +195,27 @@ protected static TruffleRuntime createRuntime() {
188195
return rt;
189196
}
190197

191-
private static RuntimeException throwVersionError(String errorFormat, Object... args) {
192-
StringBuilder errorMessage = new StringBuilder("Polyglot version compatibility check failed.\n");
198+
private static Version stripUpdateVersion(Version version) {
199+
int major = version.getComponent(0);
200+
int minor = version.getComponent(1);
201+
if (major == 0 && minor == 0) {
202+
/*
203+
* Version represents a pure snapshot version without any numeric component.
204+
*/
205+
return version;
206+
} else {
207+
return Version.create(major, minor);
208+
}
209+
}
210+
211+
private static String formatVersionWarningMessage(String errorFormat, Object... args) {
212+
StringBuilder errorMessage = new StringBuilder("Version check failed.\n");
193213
errorMessage.append(String.format(errorFormat, args));
194214
errorMessage.append("""
195-
Alternatively, it is possible to switch to the fallback runtime with -Dtruffle.UseFallbackRuntime=true.
196-
The fallback runtime is compatible to any Java 17 capable JDK.
197-
Execution with the fallback runtime does not support runtime compilation and therefore will negatively impact the guest application performance.
198-
For more information see: https://www.graalvm.org/latest/reference-manual/embed-languages/#runtime-optimization-support.
199215
To disable this version check the '-Dpolyglotimpl.DisableVersionChecks=true' system property can be used.
200216
It is not recommended to disable version checks.
201217
""");
202-
throw new IllegalStateException(errorMessage.toString());
218+
return errorMessage.toString();
203219
}
204220

205221
/**

0 commit comments

Comments
 (0)