From ef82e6dec73fd94569547a13b9bcd1f1b22f897e Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Fri, 19 Apr 2024 13:19:03 +0200 Subject: [PATCH] Add more layered image singleton support. --- .../svm/core/graal/llvm/LLVMFeature.java | 16 ++++--- .../svm/core/posix/thread/PosixVMThreads.java | 5 +-- .../oracle/svm/core/heap/PhysicalMemory.java | 3 +- .../LayeredImageSingletonSupport.java | 36 +++++++++++++++ .../RuntimeOnlyImageSingleton.java | 40 +++++++++++++++++ .../RuntimeOnlyWrapper.java | 32 +++++++++++++ .../UnsupportedLayeredSingleton.java | 45 +++++++++++++++++++ .../com/oracle/svm/core/thread/VMThreads.java | 6 +-- .../stubs/AMD64StubForeignCallsFeature.java | 14 +++--- .../hosted/ImageSingletonsSupportImpl.java | 35 ++++++++++++--- .../svm/hosted/NativeImageGenerator.java | 4 +- .../svm/hosted/SVMImageLayerSupport.java | 4 ++ .../code/SubstrateLIRBackendFeature.java | 13 +++--- .../code/amd64/AMD64HostedPatcherFeature.java | 12 ++--- .../amd64/AMD64HostedTrampolineSupport.java | 16 ++++--- .../svm/hosted/meta/KnownOffsetsFeature.java | 4 +- .../SubstrateGraphBuilderPlugins.java | 15 ++++++- ...allyRegisteredImageSingletonProcessor.java | 6 ++- 18 files changed, 259 insertions(+), 47 deletions(-) create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/LayeredImageSingletonSupport.java create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/RuntimeOnlyImageSingleton.java create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/RuntimeOnlyWrapper.java create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/UnsupportedLayeredSingleton.java diff --git a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMFeature.java b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMFeature.java index 037ef75bb1b7..c0bc6e828411 100644 --- a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMFeature.java +++ b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMFeature.java @@ -27,12 +27,6 @@ import java.nio.file.Path; import java.util.Map; -import jdk.graal.compiler.graph.Node; -import jdk.graal.compiler.graph.NodeClass; -import jdk.graal.compiler.nodes.java.LoadExceptionObjectNode; -import jdk.graal.compiler.options.OptionValues; -import jdk.graal.compiler.phases.util.Providers; -import jdk.graal.compiler.replacements.TargetGraphBuilderPlugins; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -58,6 +52,7 @@ import com.oracle.svm.core.graal.llvm.util.LLVMOptions; import com.oracle.svm.core.graal.meta.RuntimeConfiguration; import com.oracle.svm.core.graal.snippets.NodeLoweringProvider; +import com.oracle.svm.core.layeredimagesingleton.UnsupportedLayeredSingleton; import com.oracle.svm.core.option.HostedOptionKey; import com.oracle.svm.core.snippets.ExceptionUnwind; import com.oracle.svm.core.util.UserError; @@ -72,6 +67,13 @@ import com.oracle.svm.hosted.image.ObjectFileFactory; import com.oracle.svm.util.ModuleSupport; +import jdk.graal.compiler.graph.Node; +import jdk.graal.compiler.graph.NodeClass; +import jdk.graal.compiler.nodes.java.LoadExceptionObjectNode; +import jdk.graal.compiler.options.OptionValues; +import jdk.graal.compiler.phases.util.Providers; +import jdk.graal.compiler.replacements.TargetGraphBuilderPlugins; + /* * This feature enables the LLVM backend of Native Image. It does so by registering the backend, * lowerings, code cache and exception handling mechanism required to emit LLVM bitcode @@ -79,7 +81,7 @@ */ @AutomaticallyRegisteredFeature @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) -public class LLVMFeature implements Feature, InternalFeature { +public class LLVMFeature implements Feature, InternalFeature, UnsupportedLayeredSingleton { @Override public boolean isInConfiguration(IsInConfigurationAccess access) { diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/thread/PosixVMThreads.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/thread/PosixVMThreads.java index 62b501f76ea8..a32408e9283c 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/thread/PosixVMThreads.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/thread/PosixVMThreads.java @@ -51,11 +51,10 @@ import com.oracle.svm.core.util.TimeUtils; import com.oracle.svm.core.util.VMError; -import jdk.graal.compiler.api.replacements.Fold; - @AutomaticallyRegisteredImageSingleton(VMThreads.class) public final class PosixVMThreads extends VMThreads { - @Fold + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static PosixVMThreads singleton() { return (PosixVMThreads) ImageSingletons.lookup(VMThreads.class); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/PhysicalMemory.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/PhysicalMemory.java index bbb12df9e4a4..4797e5cff21f 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/PhysicalMemory.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/PhysicalMemory.java @@ -41,6 +41,7 @@ import com.oracle.svm.core.Containers; import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.Uninterruptible; +import com.oracle.svm.core.layeredimagesingleton.RuntimeOnlyImageSingleton; import com.oracle.svm.core.stack.StackOverflowCheck; import com.oracle.svm.core.thread.PlatformThreads; import com.oracle.svm.core.thread.VMOperation; @@ -54,7 +55,7 @@ public class PhysicalMemory { /** Implemented by operating-system specific code. */ - public interface PhysicalMemorySupport { + public interface PhysicalMemorySupport extends RuntimeOnlyImageSingleton { /** Get the size of physical memory from the OS. */ UnsignedWord size(); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/LayeredImageSingletonSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/LayeredImageSingletonSupport.java new file mode 100644 index 000000000000..9ecc481ed01f --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/LayeredImageSingletonSupport.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024, 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 com.oracle.svm.core.layeredimagesingleton; + +import org.graalvm.nativeimage.ImageSingletons; + +public interface LayeredImageSingletonSupport { + + static LayeredImageSingletonSupport singleton() { + return ImageSingletons.lookup(LayeredImageSingletonSupport.class); + } + + T runtimeLookup(Class key); +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/RuntimeOnlyImageSingleton.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/RuntimeOnlyImageSingleton.java new file mode 100644 index 000000000000..bc151fb1aed8 --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/RuntimeOnlyImageSingleton.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024, 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 com.oracle.svm.core.layeredimagesingleton; + +import java.util.EnumSet; + +public interface RuntimeOnlyImageSingleton extends LayeredImageSingleton { + + @Override + default EnumSet getImageBuilderFlags() { + return EnumSet.of(ImageBuilderFlags.RUNTIME_ACCESS, ImageBuilderFlags.ALLOW_CONSTANT_FOLDING); + } + + @Override + default PersistFlags preparePersist(ImageSingletonWriter writer) { + return PersistFlags.NOTHING; + } +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/RuntimeOnlyWrapper.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/RuntimeOnlyWrapper.java new file mode 100644 index 000000000000..6660b2ba8525 --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/RuntimeOnlyWrapper.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024, 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 com.oracle.svm.core.layeredimagesingleton; + +/** + * This is used to wrap singletons which are only allowed to be accessed at runtime. When a + * singleton wrapped with this is called during image build time an error is thrown. + */ +public record RuntimeOnlyWrapper(LayeredImageSingleton wrappedObject) { +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/UnsupportedLayeredSingleton.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/UnsupportedLayeredSingleton.java new file mode 100644 index 000000000000..2e608c9be612 --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/UnsupportedLayeredSingleton.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024, 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 com.oracle.svm.core.layeredimagesingleton; + +import java.util.EnumSet; + +import com.oracle.svm.core.util.VMError; + +/** + * Marker for singletons which currently cannot be part of layered images. + */ +public interface UnsupportedLayeredSingleton extends LayeredImageSingleton { + + @Override + default EnumSet getImageBuilderFlags() { + return EnumSet.of(ImageBuilderFlags.UNSUPPORTED); + } + + @Override + default PersistFlags preparePersist(ImageSingletonWriter writer) { + throw VMError.shouldNotReachHere("Unsupported feature singleton cannot be added to image"); + } +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java index db22367483b3..fd7bd5884c63 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java @@ -48,6 +48,7 @@ import com.oracle.svm.core.heap.VMOperationInfos; import com.oracle.svm.core.jdk.UninterruptibleUtils; import com.oracle.svm.core.jdk.UninterruptibleUtils.AtomicWord; +import com.oracle.svm.core.layeredimagesingleton.RuntimeOnlyImageSingleton; import com.oracle.svm.core.locks.VMCondition; import com.oracle.svm.core.locks.VMLockSupport; import com.oracle.svm.core.locks.VMMutex; @@ -65,7 +66,6 @@ import com.oracle.svm.core.util.VMError; import jdk.graal.compiler.api.directives.GraalDirectives; -import jdk.graal.compiler.api.replacements.Fold; import jdk.graal.compiler.core.common.SuppressFBWarnings; import jdk.graal.compiler.replacements.ReplacementsUtil; import jdk.graal.compiler.replacements.nodes.AssertionNode; @@ -73,9 +73,9 @@ /** * Utility methods for the manipulation and iteration of {@link IsolateThread}s. */ -public abstract class VMThreads { +public abstract class VMThreads implements RuntimeOnlyImageSingleton { - @Fold + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static VMThreads singleton() { return ImageSingletons.lookup(VMThreads.class); } diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/stubs/AMD64StubForeignCallsFeature.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/stubs/AMD64StubForeignCallsFeature.java index 15af110370ac..90043a5df99d 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/stubs/AMD64StubForeignCallsFeature.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/stubs/AMD64StubForeignCallsFeature.java @@ -32,6 +32,13 @@ import java.util.EnumSet; +import org.graalvm.nativeimage.Platform.AMD64; +import org.graalvm.nativeimage.Platforms; + +import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; +import com.oracle.svm.core.layeredimagesingleton.FeatureSingleton; +import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton; + import jdk.graal.compiler.replacements.StringLatin1InflateNode; import jdk.graal.compiler.replacements.StringUTF16CompressNode; import jdk.graal.compiler.replacements.nodes.AESNode; @@ -57,16 +64,11 @@ import jdk.graal.compiler.replacements.nodes.MessageDigestNode.SHA512Node; import jdk.graal.compiler.replacements.nodes.VectorizedHashCodeNode; import jdk.graal.compiler.replacements.nodes.VectorizedMismatchNode; -import org.graalvm.nativeimage.Platform.AMD64; -import org.graalvm.nativeimage.Platforms; - -import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; - import jdk.vm.ci.amd64.AMD64.CPUFeature; @AutomaticallyRegisteredFeature @Platforms(AMD64.class) -public class AMD64StubForeignCallsFeature extends StubForeignCallsFeatureBase { +public class AMD64StubForeignCallsFeature extends StubForeignCallsFeatureBase implements FeatureSingleton, UnsavedSingleton { private static final EnumSet BASELINE = EnumSet.of(SSE2); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageSingletonsSupportImpl.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageSingletonsSupportImpl.java index 4ed691a301e5..21c08ab83c86 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageSingletonsSupportImpl.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageSingletonsSupportImpl.java @@ -35,11 +35,13 @@ import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton.PersistFlags; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonSupport; import com.oracle.svm.core.layeredimagesingleton.LoadedLayeredImageSingletonInfo; +import com.oracle.svm.core.layeredimagesingleton.RuntimeOnlyWrapper; import com.oracle.svm.core.util.UserError; import com.oracle.svm.hosted.heap.SVMImageLayerLoader; -public final class ImageSingletonsSupportImpl extends ImageSingletonsSupport { +public final class ImageSingletonsSupportImpl extends ImageSingletonsSupport implements LayeredImageSingletonSupport { @Override public void add(Class key, T value) { @@ -48,7 +50,12 @@ public void add(Class key, T value) { @Override public T lookup(Class key) { - return HostedManagement.getAndAssertExists().doLookup(key); + return HostedManagement.getAndAssertExists().doLookup(key, false); + } + + @Override + public T runtimeLookup(Class key) { + return HostedManagement.getAndAssertExists().doLookup(key, true); } @Override @@ -135,9 +142,15 @@ public static void persist() { } private final Map, Object> configObjects; + private final boolean checkUnsupported; public HostedManagement() { + this(false); + } + + public HostedManagement(boolean checkUnsupported) { this.configObjects = new ConcurrentHashMap<>(); + this.checkUnsupported = checkUnsupported; } void doAdd(Class key, T value) { @@ -150,28 +163,40 @@ private void doAddInternal(Class key, Object value) { throw UserError.abort("ImageSingletons do not allow null value for key %s", key.getTypeName()); } + Object storedValue = value; if (value instanceof LayeredImageSingleton singleton) { assert singleton.verifyImageBuilderFlags(); - if (singleton.getImageBuilderFlags().contains(LayeredImageSingleton.ImageBuilderFlags.UNSUPPORTED)) { + if (checkUnsupported && singleton.getImageBuilderFlags().contains(LayeredImageSingleton.ImageBuilderFlags.UNSUPPORTED)) { throw UserError.abort("Unsupported image singleton is being installed %s %s", key.getTypeName(), singleton); } + + if (!singleton.getImageBuilderFlags().contains(LayeredImageSingleton.ImageBuilderFlags.BUILDTIME_ACCESS)) { + storedValue = new RuntimeOnlyWrapper(singleton); + } } - Object prevValue = configObjects.putIfAbsent(key, value); + Object prevValue = configObjects.putIfAbsent(key, storedValue); if (prevValue != null) { throw UserError.abort("ImageSingletons.add must not overwrite existing key %s%nExisting value: %s%nNew value: %s", key.getTypeName(), prevValue, value); } } - T doLookup(Class key) { + T doLookup(Class key, boolean stripRuntimeOnly) { checkKey(key); Object result = configObjects.get(key); if (result == null) { throw UserError.abort("ImageSingletons do not contain key %s", key.getTypeName()); } else if (result == SINGLETON_INSTALLATION_FOBIDDEN) { throw UserError.abort("A LayeredImageSingleton was installed in a prior layer which forbids creating the singleton in a subsequent layer. Key %s", key.getTypeName()); + } else if (result instanceof RuntimeOnlyWrapper wrapper) { + if (!stripRuntimeOnly) { + throw UserError.abort("A LayeredImageSingleton was accessed during image building which does not have %s access. Key: %s, object %s", + LayeredImageSingleton.ImageBuilderFlags.BUILDTIME_ACCESS, key, wrapper.wrappedObject()); + } + result = wrapper.wrappedObject(); + } return key.cast(result); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java index 953b8b7bf53f..3af1705942c1 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java @@ -173,6 +173,7 @@ import com.oracle.svm.core.hub.LayoutEncoding; import com.oracle.svm.core.image.ImageHeapLayouter; import com.oracle.svm.core.jdk.ServiceCatalogSupport; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonSupport; import com.oracle.svm.core.option.HostedOptionValues; import com.oracle.svm.core.option.OptionClassFilter; import com.oracle.svm.core.option.RuntimeOptionValues; @@ -528,8 +529,9 @@ public void run(Map entryPoints, var hostedOptionValues = new HostedOptionValues(optionProvider.getHostedValues()); SVMImageLayerSupport imageLayerSupport = SVMImageLayerSupport.initialize(hostedOptionValues); - ImageSingletonsSupportImpl.HostedManagement.install(new ImageSingletonsSupportImpl.HostedManagement(), imageLayerSupport); + ImageSingletonsSupportImpl.HostedManagement.install(new ImageSingletonsSupportImpl.HostedManagement(imageLayerSupport.enabled()), imageLayerSupport); + ImageSingletons.add(LayeredImageSingletonSupport.class, (LayeredImageSingletonSupport) ImageSingletonsSupportImpl.get()); ImageSingletons.add(SVMImageLayerSupport.class, imageLayerSupport); ImageSingletons.add(ProgressReporter.class, reporter); ImageSingletons.add(DeadlockWatchdog.class, loader.watchdog); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMImageLayerSupport.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMImageLayerSupport.java index 88e10784cf77..1f6340dd344f 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMImageLayerSupport.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMImageLayerSupport.java @@ -52,6 +52,10 @@ public static SVMImageLayerSupport singleton() { return ImageSingletons.lookup(SVMImageLayerSupport.class); } + public boolean enabled() { + return loader != null || writer != null; + } + public boolean hasLoader() { return loader != null; } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SubstrateLIRBackendFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SubstrateLIRBackendFeature.java index 1a74490603d8..a88380cbbfeb 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SubstrateLIRBackendFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SubstrateLIRBackendFeature.java @@ -26,10 +26,6 @@ import java.util.Map; -import jdk.graal.compiler.graph.Node; -import jdk.graal.compiler.nodes.java.LoadExceptionObjectNode; -import jdk.graal.compiler.options.OptionValues; -import jdk.graal.compiler.phases.util.Providers; import org.graalvm.nativeimage.ImageSingletons; import com.oracle.svm.core.SubstrateOptions; @@ -38,12 +34,19 @@ import com.oracle.svm.core.graal.meta.RuntimeConfiguration; import com.oracle.svm.core.graal.snippets.ExceptionSnippets; import com.oracle.svm.core.graal.snippets.NodeLoweringProvider; +import com.oracle.svm.core.layeredimagesingleton.FeatureSingleton; +import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton; import com.oracle.svm.hosted.HostedConfiguration; import com.oracle.svm.hosted.image.NativeImageCodeCacheFactory; import com.oracle.svm.hosted.image.ObjectFileFactory; +import jdk.graal.compiler.graph.Node; +import jdk.graal.compiler.nodes.java.LoadExceptionObjectNode; +import jdk.graal.compiler.options.OptionValues; +import jdk.graal.compiler.phases.util.Providers; + @AutomaticallyRegisteredFeature -class SubstrateLIRBackendFeature implements InternalFeature { +class SubstrateLIRBackendFeature implements InternalFeature, FeatureSingleton, UnsavedSingleton { @Override public boolean isInConfiguration(IsInConfigurationAccess access) { return SubstrateOptions.useLIRBackend(); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/amd64/AMD64HostedPatcherFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/amd64/AMD64HostedPatcherFeature.java index 580b8cd59175..2356789077a4 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/amd64/AMD64HostedPatcherFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/amd64/AMD64HostedPatcherFeature.java @@ -26,10 +26,6 @@ import java.util.function.Consumer; -import jdk.graal.compiler.asm.Assembler; -import jdk.graal.compiler.asm.amd64.AMD64BaseAssembler.AddressDisplacementAnnotation; -import jdk.graal.compiler.asm.amd64.AMD64BaseAssembler.OperandDataAnnotation; -import jdk.graal.compiler.code.CompilationResult; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -40,12 +36,18 @@ import com.oracle.svm.core.feature.InternalFeature; import com.oracle.svm.core.graal.code.CGlobalDataReference; import com.oracle.svm.core.graal.code.PatchConsumerFactory; +import com.oracle.svm.core.layeredimagesingleton.FeatureSingleton; +import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton; import com.oracle.svm.core.meta.SubstrateMethodPointerConstant; import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.code.HostedImageHeapConstantPatch; import com.oracle.svm.hosted.code.HostedPatcher; import com.oracle.svm.hosted.image.RelocatableBuffer; +import jdk.graal.compiler.asm.Assembler; +import jdk.graal.compiler.asm.amd64.AMD64BaseAssembler.AddressDisplacementAnnotation; +import jdk.graal.compiler.asm.amd64.AMD64BaseAssembler.OperandDataAnnotation; +import jdk.graal.compiler.code.CompilationResult; import jdk.vm.ci.code.site.ConstantReference; import jdk.vm.ci.code.site.DataSectionReference; import jdk.vm.ci.code.site.Reference; @@ -53,7 +55,7 @@ @AutomaticallyRegisteredFeature @Platforms({Platform.AMD64.class}) -class AMD64HostedPatcherFeature implements InternalFeature { +class AMD64HostedPatcherFeature implements InternalFeature, FeatureSingleton, UnsavedSingleton { @Override public void afterRegistration(AfterRegistrationAccess access) { ImageSingletons.add(PatchConsumerFactory.HostedPatchConsumerFactory.class, new PatchConsumerFactory.HostedPatchConsumerFactory() { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/amd64/AMD64HostedTrampolineSupport.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/amd64/AMD64HostedTrampolineSupport.java index 1b21808d5e1f..de4419681363 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/amd64/AMD64HostedTrampolineSupport.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/amd64/AMD64HostedTrampolineSupport.java @@ -26,28 +26,30 @@ import java.util.function.Consumer; -import jdk.graal.compiler.asm.Assembler; -import jdk.graal.compiler.asm.amd64.AMD64Assembler; -import jdk.graal.compiler.asm.amd64.AMD64MacroAssembler; -import jdk.graal.compiler.code.CompilationResult; -import jdk.graal.compiler.core.common.NumUtil; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import com.oracle.svm.core.SubstrateOptions; -import com.oracle.svm.core.graal.code.PatchConsumerFactory; import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton; +import com.oracle.svm.core.graal.code.PatchConsumerFactory; +import com.oracle.svm.core.layeredimagesingleton.FeatureSingleton; +import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton; import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.code.HostedDirectCallTrampolineSupport; import com.oracle.svm.hosted.code.HostedPatcher; import com.oracle.svm.hosted.meta.HostedMethod; +import jdk.graal.compiler.asm.Assembler; +import jdk.graal.compiler.asm.amd64.AMD64Assembler; +import jdk.graal.compiler.asm.amd64.AMD64MacroAssembler; +import jdk.graal.compiler.code.CompilationResult; +import jdk.graal.compiler.core.common.NumUtil; import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.code.TargetDescription; @AutomaticallyRegisteredImageSingleton(HostedDirectCallTrampolineSupport.class) @Platforms(Platform.AMD64.class) -public class AMD64HostedTrampolineSupport implements HostedDirectCallTrampolineSupport { +public class AMD64HostedTrampolineSupport implements HostedDirectCallTrampolineSupport, FeatureSingleton, UnsavedSingleton { @Override public boolean mayNeedTrampolines() { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/KnownOffsetsFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/KnownOffsetsFeature.java index e8df947bd36d..e105654e5edf 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/KnownOffsetsFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/KnownOffsetsFeature.java @@ -38,6 +38,8 @@ import com.oracle.svm.core.feature.InternalFeature; import com.oracle.svm.core.graal.meta.KnownOffsets; import com.oracle.svm.core.hub.DynamicHub; +import com.oracle.svm.core.layeredimagesingleton.FeatureSingleton; +import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton; import com.oracle.svm.core.stack.JavaFrameAnchor; import com.oracle.svm.core.thread.VMThreads; import com.oracle.svm.hosted.FeatureImpl.BeforeCompilationAccessImpl; @@ -49,7 +51,7 @@ @AutomaticallyRegisteredFeature @Platforms(InternalPlatform.NATIVE_ONLY.class) -public final class KnownOffsetsFeature implements InternalFeature { +public final class KnownOffsetsFeature implements InternalFeature, FeatureSingleton, UnsavedSingleton { @Override public List> getRequiredFeatures() { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java index bb17223c64d6..508c9329b30c 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java @@ -65,6 +65,7 @@ import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.classinitialization.EnsureClassInitializedNode; import com.oracle.svm.core.config.ConfigurationValues; +import com.oracle.svm.core.graal.RuntimeCompilation; import com.oracle.svm.core.graal.jdk.SubstrateObjectCloneWithExceptionNode; import com.oracle.svm.core.graal.nodes.DeoptEntryNode; import com.oracle.svm.core.graal.nodes.FarReturnNode; @@ -85,6 +86,8 @@ import com.oracle.svm.core.hub.DynamicHub; import com.oracle.svm.core.identityhashcode.SubstrateIdentityHashCodeNode; import com.oracle.svm.core.jdk.proxy.DynamicProxyRegistry; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonSupport; import com.oracle.svm.core.option.HostedOptionKey; import com.oracle.svm.core.snippets.KnownIntrinsics; import com.oracle.svm.core.util.UserError; @@ -1115,7 +1118,17 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unused, ValueNode classNode) { Class key = constantObjectParameter(b, targetMethod, 0, Class.class, classNode); - Object result = ImageSingletons.lookup(key); + Object result = LayeredImageSingletonSupport.singleton().runtimeLookup(key); + if (result instanceof LayeredImageSingleton layeredSingleton && !layeredSingleton.getImageBuilderFlags().contains(LayeredImageSingleton.ImageBuilderFlags.RUNTIME_ACCESS)) { + /* + * Runtime compilation installs many singletons into the image which are + * otherwise hosted only. Note the platform checks still apply and can be used + * to ensure certain singleton are not installed into the image. + */ + if (!RuntimeCompilation.isEnabled()) { + throw b.bailout("Layered image singleton without runtime access is in runtime graph: " + result); + } + } b.addPush(JavaKind.Object, ConstantNode.forConstant(b.getSnippetReflection().forObject(result), b.getMetaAccess())); return true; } diff --git a/substratevm/src/com.oracle.svm.processor/src/com/oracle/svm/processor/AutomaticallyRegisteredImageSingletonProcessor.java b/substratevm/src/com.oracle.svm.processor/src/com/oracle/svm/processor/AutomaticallyRegisteredImageSingletonProcessor.java index 98a9f20fa4f6..b96111145da5 100644 --- a/substratevm/src/com.oracle.svm.processor/src/com/oracle/svm/processor/AutomaticallyRegisteredImageSingletonProcessor.java +++ b/substratevm/src/com.oracle.svm.processor/src/com/oracle/svm/processor/AutomaticallyRegisteredImageSingletonProcessor.java @@ -49,6 +49,8 @@ public class AutomaticallyRegisteredImageSingletonProcessor extends AbstractProc static final String ANNOTATION_CLASS_NAME = "com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton"; static final String LAYERED_SINGLETON_INFO = "com.oracle.svm.core.layeredimagesingleton.LoadedLayeredImageSingletonInfo"; + static final String FEATURE_SINGLETON_NAME = "com.oracle.svm.core.layeredimagesingleton.FeatureSingleton"; + static final String UNSAVED_SINGLETON_NAME = "com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton"; private final Set processed = new HashSet<>(); @@ -71,7 +73,6 @@ private void processElement(TypeElement annotatedType) { out.println(""); out.println("import org.graalvm.nativeimage.ImageSingletons;"); out.println("import " + AutomaticallyRegisteredFeatureProcessor.ANNOTATION_CLASS_NAME + ";"); - out.println("import " + AutomaticallyRegisteredFeatureProcessor.FEATURE_INTERFACE_CLASS_NAME + ";"); if (platformsAnnotation != null) { out.println("import org.graalvm.nativeimage.Platforms;"); } @@ -82,7 +83,8 @@ private void processElement(TypeElement annotatedType) { out.println("@Platforms({" + platforms + "})"); } out.println("@" + getSimpleName(AutomaticallyRegisteredFeatureProcessor.ANNOTATION_CLASS_NAME)); - out.println("public final class " + featureClassName + " implements " + getSimpleName(AutomaticallyRegisteredFeatureProcessor.FEATURE_INTERFACE_CLASS_NAME) + " {"); + out.println("public final class " + featureClassName + " implements " + + String.join(", ", new String[]{AutomaticallyRegisteredFeatureProcessor.FEATURE_INTERFACE_CLASS_NAME, FEATURE_SINGLETON_NAME, UNSAVED_SINGLETON_NAME}) + " {"); out.println(" @Override"); out.println(" public void afterRegistration(AfterRegistrationAccess access) {");