Skip to content

Commit a4a0dac

Browse files
committed
Allow language interpreter to run on z/OS and s390x architecture.
1 parent dbdbfa8 commit a4a0dac

File tree

9 files changed

+183
-6
lines changed

9 files changed

+183
-6
lines changed

sdk/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
This changelog summarizes major changes between GraalVM SDK versions. The main focus is on APIs exported by GraalVM SDK.
44

5+
## Version 26.0.0
6+
* GR-65048: GR-65048: Introduced the `-Dpolyglot.engine.allowUnsupportedPlatform=true` system property to enable Truffle to run on unsupported platforms.
7+
If this property is not set, creating a Engine instance on an unsupported platform will result in a failure. When the property is enabled and Truffle is
8+
running on an unsupported platform, it will fall back to the default Truffle runtime.
9+
510
## Version 25.0.0
611
* GR-60636 Truffle now stops compiling when the code cache fills up on HotSpot. A warning is printed when that happens.
712
* GR-51664 Improved `PolyglotException#toString` and `PolyglotException#printStackTrace`.

sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/Engine.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -781,7 +781,7 @@ static Map<String, String> readOptionsFromSystemProperties(Map<String, String> o
781781
for (Object systemKey : properties.keySet()) {
782782
String key = (String) systemKey;
783783
if ("polyglot.engine.AllowExperimentalOptions".equals(key) || key.equals("polyglot.engine.resourcePath") || key.startsWith("polyglot.engine.resourcePath.") ||
784-
key.equals("polyglot.engine.userResourceCache")) {
784+
key.equals("polyglot.engine.userResourceCache") || key.equals("polyglot.engine.allowUnsupportedPlatform")) {
785785
continue;
786786
}
787787
if (key.startsWith(systemPropertyPrefix)) {

truffle/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
This changelog summarizes major changes between Truffle versions relevant to languages implementors building upon the Truffle framework. The main focus is on APIs exported by Truffle.
44

5+
## Version 26.0
6+
* GR-65048: Introduced `InternalResource.OS.UNSUPPORTED` and `InternalResource.CPUArchitecture.UNSUPPORTED` to represent unsupported platforms.
7+
Execution on unsupported platforms must be explicitly enabled using the system property `-Dpolyglot.engine.allowUnsupportedPlatform=true`.
8+
If this property is not set, calls to `OS.getCurrent()` or `CPUArchitecture.getCurrent()` will throw an `IllegalStateException` when running on an unsupported platform.
9+
510
## Version 25.0
611
* GR-31495 Added ability to specify language and instrument specific options using `Source.Builder.option(String, String)`. Languages may describe available source options by implementing `TruffleLanguage.getSourceOptionDescriptors()` and `TruffleInstrument.getSourceOptionDescriptors()` respectively.
712
* GR-61493 Added `RootNode.prepareForCall` which allows root nodes to prepare themselves for use as a call target (or to validate whether they can be used as a call target).

truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/InternalResourceTest.java

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
import java.nio.file.attribute.FileTime;
6060
import java.time.Instant;
6161
import java.util.ArrayList;
62+
import java.util.HashMap;
6263
import java.util.List;
6364
import java.util.Map;
6465
import java.util.Objects;
@@ -72,10 +73,13 @@
7273
import com.oracle.truffle.api.instrumentation.TruffleInstrument;
7374
import com.oracle.truffle.api.test.OSUtils;
7475
import com.oracle.truffle.api.test.ReflectionUtils;
76+
import com.oracle.truffle.api.test.SubprocessTestUtils;
7577
import com.oracle.truffle.api.test.common.TestUtils;
7678
import com.oracle.truffle.tck.tests.TruffleTestAssumptions;
79+
import org.graalvm.nativeimage.ImageInfo;
7780
import org.graalvm.polyglot.Context;
7881
import org.graalvm.polyglot.Engine;
82+
import org.graalvm.polyglot.PolyglotException;
7983
import org.junit.Assert;
8084
import org.junit.BeforeClass;
8185
import org.junit.Test;
@@ -91,6 +95,7 @@
9195
import static org.junit.Assert.assertNotNull;
9296
import static org.junit.Assert.assertTrue;
9397
import static com.oracle.truffle.api.test.polyglot.AbstractPolyglotTest.assertFails;
98+
import static org.junit.Assume.assumeFalse;
9499

95100
public class InternalResourceTest {
96101

@@ -1308,6 +1313,82 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje
13081313
}
13091314
}
13101315

1316+
@Test
1317+
public void testUnsupportedPlatformDisabled() throws IOException, InterruptedException {
1318+
assumeFalse(ImageInfo.inImageCode());
1319+
SubprocessTestUtils.newBuilder(InternalResourceTest.class, () -> {
1320+
var prevProperties = setUnsupportedArchitecture();
1321+
try {
1322+
AbstractPolyglotTest.assertFails(() -> Context.create(), PolyglotException.class, (e) -> {
1323+
assertEquals("java.lang.IllegalStateException: Unsupported operating system: 'z/os'. " +
1324+
"If you want to allow unsupported operating systems (which will cause the fallback Truffle runtime to be used and may disable some language features)," +
1325+
" set the system property '-Dpolyglot.engine.allowUnsupportedPlatform=true'.", e.getMessage());
1326+
});
1327+
} finally {
1328+
restoreArchitecture(prevProperties);
1329+
}
1330+
}).run();
1331+
}
1332+
1333+
@Test
1334+
public void testUnsupportedPlatformEnabled() throws IOException, InterruptedException {
1335+
assumeFalse(ImageInfo.inImageCode());
1336+
SubprocessTestUtils.newBuilder(InternalResourceTest.class, () -> {
1337+
var prevProperties = setUnsupportedArchitecture();
1338+
try {
1339+
AbstractPolyglotTest.assertFails(() -> Context.create(), PolyglotException.class, (e) -> {
1340+
assertEquals("java.lang.IllegalStateException: Truffle is running on an unsupported platform. " +
1341+
"On unsupported platforms, you must explicitly set the default cache directory " +
1342+
"using the system property '-Dpolyglot.engine.userResourceCache=<path_to_cache_folder>'.", e.getMessage());
1343+
});
1344+
} finally {
1345+
restoreArchitecture(prevProperties);
1346+
}
1347+
}).prefixVmOption("-Dpolyglot.engine.allowUnsupportedPlatform=true").run();
1348+
}
1349+
1350+
@Test
1351+
public void testUnsupportedPlatformEnabledWithExplicitCacheFolder() throws IOException, InterruptedException {
1352+
assumeFalse(ImageInfo.inImageCode());
1353+
Path tmp = SubprocessTestUtils.isSubprocess() ? null : Files.createTempDirectory("test_cache_root").toAbsolutePath();
1354+
try {
1355+
SubprocessTestUtils.newBuilder(InternalResourceTest.class, () -> {
1356+
var prevProperties = setUnsupportedArchitecture();
1357+
try {
1358+
Context context = Context.create();
1359+
context.close();
1360+
} finally {
1361+
restoreArchitecture(prevProperties);
1362+
}
1363+
}).//
1364+
prefixVmOption("-Dpolyglot.engine.allowUnsupportedPlatform=true").//
1365+
prefixVmOption("-Dpolyglot.engine.userResourceCache=" + tmp).//
1366+
onExit((subprocess) -> {
1367+
assertTrue(subprocess.output.stream().anyMatch((l) -> l.contains("Truffle is running on an unsupported platform where the TruffleAttach library is unavailable.")));
1368+
}).//
1369+
run();
1370+
} finally {
1371+
if (tmp != null) {
1372+
delete(tmp);
1373+
}
1374+
}
1375+
}
1376+
1377+
private static Map<String, String> setUnsupportedArchitecture() {
1378+
Map<String, String> prev = new HashMap<>();
1379+
prev.put("os.name", System.getProperty("os.name"));
1380+
prev.put("os.arch", System.getProperty("os.arch"));
1381+
System.setProperty("os.name", "z/os");
1382+
System.setProperty("os.arch", "s390x");
1383+
return prev;
1384+
}
1385+
1386+
private static void restoreArchitecture(Map<String, String> properties) {
1387+
for (var entry : properties.entrySet()) {
1388+
System.setProperty(entry.getKey(), entry.getValue());
1389+
}
1390+
}
1391+
13111392
private static String findLine(String pattern, String[] lines) {
13121393
Pattern p = Pattern.compile(pattern);
13131394
for (String line : lines) {

truffle/src/com.oracle.truffle.api/snapshot.sigtest

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ CLSS public final static !enum com.oracle.truffle.api.InternalResource$CPUArchit
175175
outer com.oracle.truffle.api.InternalResource
176176
fld public final static com.oracle.truffle.api.InternalResource$CPUArchitecture AARCH64
177177
fld public final static com.oracle.truffle.api.InternalResource$CPUArchitecture AMD64
178+
fld public final static com.oracle.truffle.api.InternalResource$CPUArchitecture UNSUPPORTED
178179
meth public java.lang.String toString()
179180
meth public static com.oracle.truffle.api.InternalResource$CPUArchitecture getCurrent()
180181
meth public static com.oracle.truffle.api.InternalResource$CPUArchitecture valueOf(java.lang.String)
@@ -207,13 +208,14 @@ CLSS public final static !enum com.oracle.truffle.api.InternalResource$OS
207208
outer com.oracle.truffle.api.InternalResource
208209
fld public final static com.oracle.truffle.api.InternalResource$OS DARWIN
209210
fld public final static com.oracle.truffle.api.InternalResource$OS LINUX
211+
fld public final static com.oracle.truffle.api.InternalResource$OS UNSUPPORTED
210212
fld public final static com.oracle.truffle.api.InternalResource$OS WINDOWS
211213
meth public java.lang.String toString()
212214
meth public static com.oracle.truffle.api.InternalResource$OS getCurrent()
213215
meth public static com.oracle.truffle.api.InternalResource$OS valueOf(java.lang.String)
214216
meth public static com.oracle.truffle.api.InternalResource$OS[] values()
215217
supr java.lang.Enum<com.oracle.truffle.api.InternalResource$OS>
216-
hfds id
218+
hfds PROPERTY_ALLOW_UNSUPPORTED_PLATFORM,allowsUnsupportedPlatformValue,id
217219

218220
CLSS public com.oracle.truffle.api.OptimizationFailedException
219221
cons public init(java.lang.Throwable,com.oracle.truffle.api.RootCallTarget)

truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/InternalResource.java

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,43 @@ enum OS {
484484
*
485485
* @since 23.1
486486
*/
487-
WINDOWS("windows");
487+
WINDOWS("windows"),
488+
489+
/**
490+
* Represents an unsupported operating system.
491+
* <p>
492+
* To enable execution on unsupported platforms, the system property
493+
* {@code -Dpolyglot.engine.allowUnsupportedPlatform=true} must be explicitly set. If this
494+
* property is not set and the platform is unsupported, the {@link #getCurrent()} method
495+
* will throw an {@link IllegalStateException}.
496+
*
497+
* @since 26.0
498+
*/
499+
UNSUPPORTED("unsupported");
500+
501+
private static final String PROPERTY_ALLOW_UNSUPPORTED_PLATFORM = "polyglot.engine.allowUnsupportedPlatform";
502+
503+
private static volatile Boolean allowsUnsupportedPlatformValue;
504+
505+
private static boolean allowsUnsupportedPlatform() {
506+
Boolean res = allowsUnsupportedPlatformValue;
507+
if (res == null) {
508+
synchronized (OS.class) {
509+
res = allowsUnsupportedPlatformValue;
510+
if (res == null) {
511+
res = Boolean.getBoolean(OS.PROPERTY_ALLOW_UNSUPPORTED_PLATFORM);
512+
if (!ImageInfo.inImageBuildtimeCode()) {
513+
/*
514+
* Avoid caching the property value during image build time, as it would
515+
* require resetting it in the image heap later.
516+
*/
517+
allowsUnsupportedPlatformValue = res;
518+
}
519+
}
520+
}
521+
}
522+
return res;
523+
}
488524

489525
private final String id;
490526

@@ -517,8 +553,12 @@ public static OS getCurrent() {
517553
return DARWIN;
518554
} else if (os.toLowerCase().startsWith("windows")) {
519555
return WINDOWS;
556+
} else if (allowsUnsupportedPlatform()) {
557+
return UNSUPPORTED;
520558
} else {
521-
throw CompilerDirectives.shouldNotReachHere("Unsupported OS name " + os);
559+
throw new IllegalStateException(String.format("Unsupported operating system: '%s'. " +
560+
"If you want to allow unsupported operating systems (which will cause the fallback Truffle runtime to be used and may disable some language features), " +
561+
"set the system property '-D%s=true'.", os, PROPERTY_ALLOW_UNSUPPORTED_PLATFORM));
522562
}
523563
}
524564
}
@@ -542,7 +582,19 @@ enum CPUArchitecture {
542582
*
543583
* @since 23.1
544584
*/
545-
AMD64("amd64");
585+
AMD64("amd64"),
586+
587+
/**
588+
* Represents an unsupported architecture.
589+
* <p>
590+
* To enable execution on unsupported platforms, the system property
591+
* {@code -Dpolyglot.engine.allowUnsupportedPlatform=true} must be explicitly set. If this
592+
* property is not set and the platform is unsupported, the {@link #getCurrent()} method
593+
* will throw an {@link IllegalStateException}.
594+
*
595+
* @since 26.0
596+
*/
597+
UNSUPPORTED("unsupported");
546598

547599
private final String id;
548600

@@ -573,7 +625,15 @@ public static CPUArchitecture getCurrent() {
573625
return switch (arch) {
574626
case "amd64", "x86_64" -> AMD64;
575627
case "aarch64", "arm64" -> AARCH64;
576-
default -> throw CompilerDirectives.shouldNotReachHere("Unsupported CPU architecture " + arch);
628+
default -> {
629+
if (OS.allowsUnsupportedPlatform()) {
630+
yield UNSUPPORTED;
631+
} else {
632+
throw new IllegalStateException(String.format("Unsupported CPU architecture: '%s'. " +
633+
"If you want to allow unsupported CPU architectures (which will cause the fallback Truffle runtime to be used and may disable some language features), " +
634+
"set the system property '-D%s=true'.", arch, OS.PROPERTY_ALLOW_UNSUPPORTED_PLATFORM));
635+
}
636+
}
577637
};
578638
}
579639
}

truffle/src/com.oracle.truffle.nfi.backend.panama.jdk22/src/com/oracle/truffle/nfi/backend/panama/ErrorContext.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ public class ErrorContext extends AbstractErrorContext {
5555
case DARWIN -> "__error";
5656
case LINUX -> "__errno_location";
5757
case WINDOWS -> "_errno";
58+
case UNSUPPORTED -> throw new IllegalStateException("NFI is not supported on unsupported platforms.");
5859
};
5960

6061
public static final VarHandle INT_VAR_HANDLE = ValueLayout.JAVA_INT.varHandle();

truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/InternalResourceRoots.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,9 @@ private static ResolvedCacheFolder findCacheRootDefault() {
339339
yield userCacheDir;
340340
}
341341
case WINDOWS -> new ResolvedCacheFolder(userHome.resolve(Path.of("AppData", "Local")), "user home", userHome);
342+
case UNSUPPORTED -> throw new IllegalStateException(String.format("Truffle is running on an unsupported platform. " +
343+
"On unsupported platforms, you must explicitly set the default cache directory using the system property " +
344+
"'-D%s=<path_to_cache_folder>'.", PROPERTY_USER_RESOURCE_CACHE));
342345
};
343346
return container.resolve("org.graalvm.polyglot");
344347
}

truffle/src/com.oracle.truffle.polyglot/src/com/oracle/truffle/polyglot/JDKSupport.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@
7070
import java.util.stream.Stream;
7171

7272
import com.oracle.truffle.api.InternalResource;
73+
import com.oracle.truffle.api.InternalResource.OS;
74+
import com.oracle.truffle.api.InternalResource.CPUArchitecture;
7375
import com.oracle.truffle.api.Truffle;
7476
import com.oracle.truffle.api.impl.Accessor;
7577
import com.oracle.truffle.api.impl.Accessor.JavaLangSupport;
@@ -112,6 +114,10 @@ final class JDKSupport {
112114
private static ModulesAccessor initializeModuleAccessor() {
113115
String attachLibPath = System.getProperty("truffle.attach.library");
114116
if (attachLibPath == null) {
117+
if (isUnsupportedPlatform()) {
118+
performTruffleAttachLoadFailureAction("Truffle is running on an unsupported platform where the TruffleAttach library is unavailable.", null);
119+
return null;
120+
}
115121
try {
116122
Path truffleAttachRoot = InternalResourceCache.installRuntimeResource(new LibTruffleAttachResource());
117123
Path libAttach = truffleAttachRoot.resolve("bin").resolve(System.mapLibraryName("truffleattach"));
@@ -148,6 +154,20 @@ private static ModulesAccessor initializeModuleAccessor() {
148154
}
149155
}
150156

157+
private static boolean isUnsupportedPlatform() {
158+
try {
159+
return OS.getCurrent() == OS.UNSUPPORTED || CPUArchitecture.getCurrent() == CPUArchitecture.UNSUPPORTED;
160+
} catch (IllegalStateException ise) {
161+
/*
162+
* Avoid throwing exceptions from the static initializer of JDKSupport. It is
163+
* initialized early by PolyglotImpl#initialize, and any failure during static
164+
* initialization results in an ExceptionInInitializerError with a long, unreadable
165+
* chain of causes.
166+
*/
167+
return true;
168+
}
169+
}
170+
151171
private static native void addExports0(Module m1, String pn, Module m2);
152172

153173
private static void performTruffleAttachLoadFailureAction(String reason, Throwable t) {

0 commit comments

Comments
 (0)