Skip to content

Commit 51e2897

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

File tree

6 files changed

+147
-10
lines changed

6 files changed

+147
-10
lines changed

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/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/InternalResourceTest.java

Lines changed: 76 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,12 @@
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;
7779
import org.graalvm.polyglot.Context;
7880
import org.graalvm.polyglot.Engine;
81+
import org.graalvm.polyglot.PolyglotException;
7982
import org.junit.Assert;
8083
import org.junit.BeforeClass;
8184
import org.junit.Test;
@@ -1308,6 +1311,79 @@ protected Object execute(RootNode node, Env env, Object[] contextArguments, Obje
13081311
}
13091312
}
13101313

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

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

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,33 @@ enum OS {
484484
*
485485
* @since 23.1
486486
*/
487-
WINDOWS("windows");
487+
WINDOWS("windows"),
488+
489+
UNSUPPORTED("unsupported");
490+
491+
private static final String PROPERTY_ALLOW_UNSUPPORTED_PLATFORM = "polyglot.engine.allowUnsupportedPlatform";
492+
493+
private static volatile Boolean allowsUnsupportedPlatformValue;
494+
495+
private static boolean allowsUnsupportedPlatform() {
496+
Boolean res = allowsUnsupportedPlatformValue;
497+
if (res == null) {
498+
synchronized (OS.class) {
499+
res = allowsUnsupportedPlatformValue;
500+
if (res == null) {
501+
res = Boolean.getBoolean(OS.PROPERTY_ALLOW_UNSUPPORTED_PLATFORM);
502+
if (!ImageInfo.inImageBuildtimeCode()) {
503+
/*
504+
* Avoid caching the property value during image build time, as it would
505+
* require resetting it in the image heap later.
506+
*/
507+
allowsUnsupportedPlatformValue = res;
508+
}
509+
}
510+
}
511+
}
512+
return res;
513+
}
488514

489515
private final String id;
490516

@@ -517,8 +543,12 @@ public static OS getCurrent() {
517543
return DARWIN;
518544
} else if (os.toLowerCase().startsWith("windows")) {
519545
return WINDOWS;
546+
} else if (allowsUnsupportedPlatform()) {
547+
return UNSUPPORTED;
520548
} else {
521-
throw CompilerDirectives.shouldNotReachHere("Unsupported OS name " + os);
549+
throw new IllegalStateException(String.format("Unsupported operating system: '%s'. " +
550+
"If you want to allow unsupported operating systems (which will cause the fallback Truffle runtime to be used and may disable some language features), " +
551+
"set the system property '-D%s=true'.", os, PROPERTY_ALLOW_UNSUPPORTED_PLATFORM));
522552
}
523553
}
524554
}
@@ -542,7 +572,9 @@ enum CPUArchitecture {
542572
*
543573
* @since 23.1
544574
*/
545-
AMD64("amd64");
575+
AMD64("amd64"),
576+
577+
UNSUPPORTED("unsupported");
546578

547579
private final String id;
548580

@@ -573,7 +605,15 @@ public static CPUArchitecture getCurrent() {
573605
return switch (arch) {
574606
case "amd64", "x86_64" -> AMD64;
575607
case "aarch64", "arm64" -> AARCH64;
576-
default -> throw CompilerDirectives.shouldNotReachHere("Unsupported CPU architecture " + arch);
608+
default -> {
609+
if (OS.allowsUnsupportedPlatform()) {
610+
yield UNSUPPORTED;
611+
} else {
612+
throw new IllegalStateException(String.format("Unsupported CPU architecture: '%s'. " +
613+
"If you want to allow unsupported CPU architectures (which will cause the fallback Truffle runtime to be used and may disable some language features), " +
614+
"set the system property '-D%s=true'.", arch, OS.PROPERTY_ALLOW_UNSUPPORTED_PLATFORM));
615+
}
616+
}
577617
};
578618
}
579619
}

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: 6 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 (OS.getCurrent() == OS.UNSUPPORTED || CPUArchitecture.getCurrent() == CPUArchitecture.UNSUPPORTED) {
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"));

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

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@
7171
import java.util.function.Supplier;
7272
import java.util.logging.Level;
7373

74+
import com.oracle.truffle.api.InternalResource.CPUArchitecture;
75+
import com.oracle.truffle.api.InternalResource.OS;
7476
import org.graalvm.options.OptionDescriptors;
7577
import org.graalvm.polyglot.Engine;
7678
import org.graalvm.polyglot.HostAccess.TargetMappingPrecedence;
@@ -204,11 +206,21 @@ PolyglotEngineImpl getPreinitializedEngine() {
204206

205207
@Override
206208
public void initialize() {
207-
super.initialize();
208-
this.hostNull = getAPIAccess().newValue(PolyglotValueDispatch.createHostNull(this), null, EngineAccessor.HOST.getHostNull(), null);
209-
this.disconnectedHostValue = new PolyglotValueDispatch.HostValue(this);
210-
this.disconnectedBigIntegerHostValue = new PolyglotValueDispatch.BigIntegerHostValue(this);
211-
PolyglotValueDispatch.createDefaultValues(this, null, primitiveValues);
209+
try {
210+
super.initialize();
211+
/*
212+
* Eagerly check for unsupported platforms to provide a clear exception, avoiding an
213+
* ExceptionInInitializerError with a long chain of causes.
214+
*/
215+
OS.getCurrent();
216+
CPUArchitecture.getCurrent();
217+
this.hostNull = getAPIAccess().newValue(PolyglotValueDispatch.createHostNull(this), null, EngineAccessor.HOST.getHostNull(), null);
218+
this.disconnectedHostValue = new PolyglotValueDispatch.HostValue(this);
219+
this.disconnectedBigIntegerHostValue = new PolyglotValueDispatch.BigIntegerHostValue(this);
220+
PolyglotValueDispatch.createDefaultValues(this, null, primitiveValues);
221+
} catch (Throwable t) {
222+
throw PolyglotImpl.guestToHostException(this, t);
223+
}
212224
}
213225

214226
@Override

0 commit comments

Comments
 (0)