diff --git a/mx.trufflesqueak/mx_trufflesqueak.py b/mx.trufflesqueak/mx_trufflesqueak.py index 46d2713ab..49a21738f 100644 --- a/mx.trufflesqueak/mx_trufflesqueak.py +++ b/mx.trufflesqueak/mx_trufflesqueak.py @@ -26,6 +26,9 @@ # Tweak Runtime '-Xss64M', # Increase stack size (`-XX:ThreadStackSize=64M` not working) + # Make ReflectionUtils work + '--add-exports=java.base/jdk.internal.module=ALL-UNNAMED', + # Make Truffle.getRuntime() accessible for VM introspection '--add-opens=jdk.internal.vm.compiler/org.graalvm.compiler.truffle.runtime=ALL-UNNAMED', # Enable access to HostObject and others diff --git a/mx.trufflesqueak/suite.py b/mx.trufflesqueak/suite.py index f4efc2737..494e1e9d8 100644 --- a/mx.trufflesqueak/suite.py +++ b/mx.trufflesqueak/suite.py @@ -90,6 +90,9 @@ "java.management", "jdk.unsupported", ], + "requiresConcealed" : { + "java.base" : ["jdk.internal.module"], + }, "checkstyleVersion": "8.36.1", "jacoco": "include", "javaCompliance": "11+", @@ -182,18 +185,18 @@ "description": "TruffleSqueak engine", "moduleInfo": { "name": "de.hpi.swa.trufflesqueak", - "requiresConcealed": { - "org.graalvm.truffle": [ - "com.oracle.truffle.api", - "com.oracle.truffle.api.instrumentation", - ], - }, "exports": [ "de.hpi.swa.trufflesqueak to org.graalvm.truffle", ], "requires": [ "jdk.unsupported" # sun.misc.Unsafe ], + "requiresConcealed": { + "org.graalvm.truffle": [ + "com.oracle.truffle.api", + "com.oracle.truffle.api.instrumentation", + ], + }, }, "dependencies": [ "de.hpi.swa.trufflesqueak", diff --git a/src/de.hpi.swa.trufflesqueak.test/src/de/hpi/swa/trufflesqueak/test/tests.properties b/src/de.hpi.swa.trufflesqueak.test/src/de/hpi/swa/trufflesqueak/test/tests.properties index 4d119cb5c..392db7cfe 100644 --- a/src/de.hpi.swa.trufflesqueak.test/src/de/hpi/swa/trufflesqueak/test/tests.properties +++ b/src/de.hpi.swa.trufflesqueak.test/src/de/hpi/swa/trufflesqueak/test/tests.properties @@ -3021,6 +3021,7 @@ JavaTest>>testJavaLocalDate=passing JavaTest>>testJavaLocalTime=passing JavaTest>>testJavaString=passing JavaTest>>testJavaZoneId=passing +JavaTest>>testLanguageClass=passing JPEGReadWriter2PluginTest>>testPluginPresent=passing JPEGReadWriter2PluginTest>>testPrimJPEGReadImage=passing # Expected form has an off-by-one pixel diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/PolyglotPlugin.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/PolyglotPlugin.java index 44d2f4089..091e8bb52 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/PolyglotPlugin.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/PolyglotPlugin.java @@ -7,10 +7,14 @@ package de.hpi.swa.trufflesqueak.nodes.plugins; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.nio.ByteOrder; import java.util.List; import java.util.Map; +import org.graalvm.polyglot.Engine; + import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; @@ -68,6 +72,7 @@ import de.hpi.swa.trufflesqueak.util.ArrayUtils; import de.hpi.swa.trufflesqueak.util.LogUtils; import de.hpi.swa.trufflesqueak.util.MiscUtils; +import de.hpi.swa.trufflesqueak.util.ReflectionUtils; import de.hpi.swa.trufflesqueak.util.UnsafeUtils; public final class PolyglotPlugin extends AbstractPrimitiveFactoryHolder { @@ -2056,6 +2061,28 @@ protected final Object doLookupHostSymbol(@SuppressWarnings("unused") final Obje } } + @GenerateNodeFactory + @SqueakPrimitive(names = "primitiveLoadLanguageClass") + protected abstract static class PrimLoadLanguageClassNode extends AbstractPrimitiveNode implements BinaryPrimitiveFallback { + private static final Method LOAD_LANGUAGE_CLASS = ReflectionUtils.lookupMethod(Engine.class, "loadLanguageClass", String.class); + + @TruffleBoundary + @Specialization(guards = {"value.isByteType()"}) + protected final Object doLoadLanguageClass(@SuppressWarnings("unused") final Object receiver, final NativeObject value) { + final String symbolName = value.asStringUnsafe(); + try { + final Class languageSymbol = (Class) LOAD_LANGUAGE_CLASS.invoke(null, symbolName); + if (languageSymbol != null) { + return getContext().env.asHostSymbol(languageSymbol); + } else { + return NilObject.SINGLETON; + } + } catch (final RuntimeException | IllegalAccessException | InvocationTargetException e) { + throw primitiveFailedInInterpreterCapturing(e); + } + } + } + @GenerateNodeFactory @SqueakPrimitive(names = "primitiveIsHostFunction") protected abstract static class PrimIsHostFunctionNode extends AbstractPrimitiveNode { diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/ReflectionUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/ReflectionUtils.java new file mode 100644 index 000000000..d6edb6535 --- /dev/null +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/ReflectionUtils.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2022 Software Architecture Group, Hasso Plattner Institute + * Copyright (c) 2022 Oracle and/or its affiliates + * + * Licensed under the MIT License. + */ +package de.hpi.swa.trufflesqueak.util; + +import java.lang.reflect.Method; + +import jdk.internal.module.Modules; + +public final class ReflectionUtils { + public static Method lookupMethod(final Class declaringClass, final String methodName, final Class... parameterTypes) { + try { + final Method result = declaringClass.getDeclaredMethod(methodName, parameterTypes); + openModule(declaringClass); + result.setAccessible(true); + return result; + } catch (final ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } + + /** + * Ensure that this class is allowed to call setAccessible for an element of the provided + * declaring class. + */ + private static void openModule(final Class declaringClass) { + openModuleByClass(declaringClass, ReflectionUtils.class); + } + + private static void openModuleByClass(final Class declaringClass, final Class accessingClass) { + final Module declaringModule = declaringClass.getModule(); + final String packageName = declaringClass.getPackageName(); + Module namedAccessingModule = null; + if (accessingClass != null) { + final Module accessingModule = accessingClass.getModule(); + if (accessingModule.isNamed()) { + namedAccessingModule = accessingModule; + } + } + if (namedAccessingModule != null ? declaringModule.isOpen(packageName, namedAccessingModule) : declaringModule.isOpen(packageName)) { + return; + } + if (namedAccessingModule != null) { + Modules.addOpens(declaringModule, packageName, namedAccessingModule); + } else { + Modules.addOpensToAllUnnamed(declaringModule, packageName); + } + } +} diff --git a/src/image b/src/image index fbb9a61e6..a289d9d8d 160000 --- a/src/image +++ b/src/image @@ -1 +1 @@ -Subproject commit fbb9a61e6e1e883e1b64e9028542fee358a82f6a +Subproject commit a289d9d8d607c01e81d0082ea90614ec36565c6a