From e5e55c4999f3b528aecb2a0aad5dd9e31b8b4716 Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Thu, 24 Jul 2025 22:15:00 +0200 Subject: [PATCH] Switch InitialLayerOnlyImageSingletons to use SingletonTraits. --- .../genscavenge/PinnedObjectSupportImpl.java | 21 ++----- .../svm/core/graal/llvm/LLVMFeature.java | 7 ++- .../svm/core/posix/PosixLogHandler.java | 22 +++----- .../svm/core/posix/PosixStdErrWriter.java | 21 ++----- .../linux/LinuxProcessPropertiesSupport.java | 21 ++----- .../svm/core/posix/thread/PosixVMThreads.java | 5 ++ .../svm/core/windows/WindowsStdErrWriter.java | 21 ++----- .../core/c/CTypeConversionSupportImpl.java | 20 ++----- .../core/c/function/IsolateSupportImpl.java | 20 ++----- .../handles/ObjectHandlesSupportImpl.java | 31 ++++------- .../src/com/oracle/svm/core/heap/GCCause.java | 18 ++---- .../oracle/svm/core/heap/PhysicalMemory.java | 15 ++--- .../svm/core/heap/dump/HeapDumpMetadata.java | 18 ++---- .../svm/core/jdk/StringInternSupport.java | 18 ++---- .../svm/core/jdk/SystemInOutErrSupport.java | 15 ++--- .../InitialLayerOnlyImageSingleton.java | 49 ----------------- .../LayeredImageSingletonSupport.java | 7 ++- .../core/log/FunctionPointerLogHandler.java | 21 ++----- .../com/oracle/svm/core/thread/VMThreads.java | 23 +++----- .../core/threadlocal/VMThreadLocalInfos.java | 15 ++--- .../threadlocal/VMThreadLocalSupport.java | 16 ++---- .../oracle/svm/core/traits/BuiltinTraits.java | 19 +++++++ .../SingletonLayeredInstallationKind.java | 28 ++++++---- ...gletonLayeredInstallationKindSupplier.java | 2 +- .../stubs/AMD64StubForeignCallsFeature.java | 7 ++- .../hosted/ImageSingletonsSupportImpl.java | 55 +++++++++++++------ .../svm/hosted/OpenTypeWorldFeature.java | 6 +- .../oracle/svm/hosted/ProgressReporter.java | 7 ++- .../imagelayer/LoadImageSingletonFeature.java | 5 +- .../SVMImageLayerSingletonLoader.java | 2 +- .../imagelayer/SVMImageLayerWriter.java | 24 ++++---- .../SubstrateGraphBuilderPlugins.java | 22 ++++++-- .../thread/HostedJavaThreadsFeature.java | 6 +- 33 files changed, 245 insertions(+), 342 deletions(-) delete mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/InitialLayerOnlyImageSingleton.java diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/PinnedObjectSupportImpl.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/PinnedObjectSupportImpl.java index de67717bcd26..53da311c5200 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/PinnedObjectSupportImpl.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/PinnedObjectSupportImpl.java @@ -24,8 +24,6 @@ */ package com.oracle.svm.core.genscavenge; -import java.util.EnumSet; - import org.graalvm.nativeimage.PinnedObject; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -33,13 +31,16 @@ import com.oracle.svm.core.Uninterruptible; import com.oracle.svm.core.heap.AbstractPinnedObjectSupport; -import com.oracle.svm.core.layeredimagesingleton.InitialLayerOnlyImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; +import com.oracle.svm.core.traits.BuiltinTraits.AllAccess; +import com.oracle.svm.core.traits.BuiltinTraits.SingleLayer; +import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.InitialLayerOnly; +import com.oracle.svm.core.traits.SingletonTraits; import jdk.graal.compiler.nodes.NamedLocationIdentity; /** Support for pinning objects to a memory address with {@link PinnedObject}. */ -public final class PinnedObjectSupportImpl extends AbstractPinnedObjectSupport implements InitialLayerOnlyImageSingleton { +@SingletonTraits(access = AllAccess.class, layeredCallbacks = SingleLayer.class, layeredInstallationKind = InitialLayerOnly.class) +public final class PinnedObjectSupportImpl extends AbstractPinnedObjectSupport { @Platforms(Platform.HOSTED_ONLY.class) public PinnedObjectSupportImpl() { } @@ -66,14 +67,4 @@ private static void modifyPinnedObjectCount(Object object, int delta) { assert oldValue < Integer.MAX_VALUE; } - - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.ALL_ACCESS; - } - - @Override - public boolean accessibleInFutureLayers() { - return true; - } } 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 5048269c51e7..d4835860f28b 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 @@ -53,8 +53,9 @@ import com.oracle.svm.core.graal.snippets.NodeLoweringProvider; import com.oracle.svm.core.option.HostedOptionKey; import com.oracle.svm.core.snippets.ExceptionUnwind; -import com.oracle.svm.core.traits.BuiltinTraits; -import com.oracle.svm.core.traits.SingletonLayeredInstallationKind; +import com.oracle.svm.core.traits.BuiltinTraits.BuildtimeAccessOnly; +import com.oracle.svm.core.traits.BuiltinTraits.NoLayeredCallbacks; +import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.Disallowed; import com.oracle.svm.core.traits.SingletonTraits; import com.oracle.svm.core.util.UserError; import com.oracle.svm.hosted.FeatureImpl; @@ -82,7 +83,7 @@ */ @AutomaticallyRegisteredFeature @Platforms({Platform.LINUX.class, Platform.DARWIN.class}) -@SingletonTraits(access = BuiltinTraits.BuildtimeAccessOnly.class, layeredCallbacks = BuiltinTraits.NoLayeredCallbacks.class, layeredInstallationKind = SingletonLayeredInstallationKind.Disallowed.class) +@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Disallowed.class) public class LLVMFeature implements InternalFeature { @Override diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixLogHandler.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixLogHandler.java index 306919685743..b3de5749f4dc 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixLogHandler.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixLogHandler.java @@ -25,9 +25,7 @@ package com.oracle.svm.core.posix; import java.io.FileDescriptor; -import java.util.EnumSet; -import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; import org.graalvm.nativeimage.LogHandler; import org.graalvm.nativeimage.c.type.CCharPointer; import org.graalvm.word.UnsignedWord; @@ -36,10 +34,13 @@ import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; import com.oracle.svm.core.feature.InternalFeature; import com.oracle.svm.core.headers.LibC; -import com.oracle.svm.core.layeredimagesingleton.InitialLayerOnlyImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; +import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; import com.oracle.svm.core.log.Log; import com.oracle.svm.core.thread.VMThreads; +import com.oracle.svm.core.traits.BuiltinTraits.RuntimeAccessOnly; +import com.oracle.svm.core.traits.BuiltinTraits.SingleLayer; +import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.InitialLayerOnly; +import com.oracle.svm.core.traits.SingletonTraits; @AutomaticallyRegisteredFeature class PosixLogHandlerFeature implements InternalFeature { @@ -51,7 +52,8 @@ public void beforeAnalysis(BeforeAnalysisAccess access) { } } -public class PosixLogHandler implements LogHandler, InitialLayerOnlyImageSingleton { +@SingletonTraits(access = RuntimeAccessOnly.class, layeredCallbacks = SingleLayer.class, layeredInstallationKind = InitialLayerOnly.class) +public class PosixLogHandler implements LogHandler { @Override public void log(CCharPointer bytes, UnsignedWord length) { @@ -94,14 +96,4 @@ public void fatalError() { private static FileDescriptor getOutputFile() { return FileDescriptor.err; } - - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.RUNTIME_ACCESS_ONLY; - } - - @Override - public boolean accessibleInFutureLayers() { - return true; - } } diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixStdErrWriter.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixStdErrWriter.java index 2cc3d2b1ee51..b925fff1ae11 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixStdErrWriter.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixStdErrWriter.java @@ -26,8 +26,6 @@ import static com.oracle.svm.core.Uninterruptible.CALLED_FROM_UNINTERRUPTIBLE_CODE; -import java.util.EnumSet; - import org.graalvm.nativeimage.c.type.CCharPointer; import org.graalvm.word.Pointer; import org.graalvm.word.UnsignedWord; @@ -35,13 +33,16 @@ import com.oracle.svm.core.Uninterruptible; import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton; import com.oracle.svm.core.headers.LibC; -import com.oracle.svm.core.layeredimagesingleton.InitialLayerOnlyImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.core.log.StdErrWriter; +import com.oracle.svm.core.traits.BuiltinTraits.RuntimeAccessOnly; +import com.oracle.svm.core.traits.BuiltinTraits.SingleLayer; +import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.InitialLayerOnly; +import com.oracle.svm.core.traits.SingletonTraits; import com.oracle.svm.core.util.VMError; @AutomaticallyRegisteredImageSingleton(value = StdErrWriter.class) -class PosixStdErrWriter implements StdErrWriter, InitialLayerOnlyImageSingleton { +@SingletonTraits(access = RuntimeAccessOnly.class, layeredCallbacks = SingleLayer.class, layeredInstallationKind = InitialLayerOnly.class) +class PosixStdErrWriter implements StdErrWriter { private static final int STDERR_FD = 2; @Override @@ -70,14 +71,4 @@ public void flush() { LibC.setErrno(savedErrno); } } - - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.RUNTIME_ACCESS_ONLY; - } - - @Override - public boolean accessibleInFutureLayers() { - return true; - } } diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxProcessPropertiesSupport.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxProcessPropertiesSupport.java index 71aa74aa26f4..0b005a8d0d00 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxProcessPropertiesSupport.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxProcessPropertiesSupport.java @@ -24,31 +24,22 @@ */ package com.oracle.svm.core.posix.linux; -import java.util.EnumSet; - import org.graalvm.nativeimage.impl.ProcessPropertiesSupport; import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.InitialLayerOnlyImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.core.posix.PosixProcessPropertiesSupport; +import com.oracle.svm.core.traits.BuiltinTraits.RuntimeAccessOnly; +import com.oracle.svm.core.traits.BuiltinTraits.SingleLayer; +import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.InitialLayerOnly; +import com.oracle.svm.core.traits.SingletonTraits; @AutomaticallyRegisteredImageSingleton(ProcessPropertiesSupport.class) -public class LinuxProcessPropertiesSupport extends PosixProcessPropertiesSupport implements InitialLayerOnlyImageSingleton { +@SingletonTraits(access = RuntimeAccessOnly.class, layeredCallbacks = SingleLayer.class, layeredInstallationKind = InitialLayerOnly.class) +public class LinuxProcessPropertiesSupport extends PosixProcessPropertiesSupport { @Override public String getExecutableName() { final String exefileString = "/proc/self/exe"; return realpath(exefileString); } - - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.RUNTIME_ACCESS_ONLY; - } - - @Override - public boolean accessibleInFutureLayers() { - return true; - } } 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 3637d71383ba..abbfddca3280 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 @@ -47,12 +47,17 @@ import com.oracle.svm.core.posix.headers.darwin.DarwinPthread; import com.oracle.svm.core.posix.linux.LinuxLibCHelper; import com.oracle.svm.core.thread.VMThreads; +import com.oracle.svm.core.traits.BuiltinTraits.RuntimeAccessOnly; +import com.oracle.svm.core.traits.BuiltinTraits.SingleLayer; +import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.InitialLayerOnly; +import com.oracle.svm.core.traits.SingletonTraits; import com.oracle.svm.core.util.TimeUtils; import com.oracle.svm.core.util.VMError; import jdk.graal.compiler.word.Word; @AutomaticallyRegisteredImageSingleton(VMThreads.class) +@SingletonTraits(access = RuntimeAccessOnly.class, layeredCallbacks = SingleLayer.class, layeredInstallationKind = InitialLayerOnly.class) public final class PosixVMThreads extends VMThreads { @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) diff --git a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsStdErrWriter.java b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsStdErrWriter.java index 59d28a723ab5..2fdf47cfcb0a 100644 --- a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsStdErrWriter.java +++ b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsStdErrWriter.java @@ -26,22 +26,23 @@ import static com.oracle.svm.core.Uninterruptible.CALLED_FROM_UNINTERRUPTIBLE_CODE; -import java.util.EnumSet; - import org.graalvm.nativeimage.c.type.CCharPointer; import org.graalvm.word.UnsignedWord; import com.oracle.svm.core.Uninterruptible; import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.InitialLayerOnlyImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.core.log.StdErrWriter; +import com.oracle.svm.core.traits.BuiltinTraits.RuntimeAccessOnly; +import com.oracle.svm.core.traits.BuiltinTraits.SingleLayer; +import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.InitialLayerOnly; +import com.oracle.svm.core.traits.SingletonTraits; import com.oracle.svm.core.util.VMError; import com.oracle.svm.core.windows.headers.FileAPI; import com.oracle.svm.core.windows.headers.WinBase.HANDLE; @AutomaticallyRegisteredImageSingleton(value = StdErrWriter.class) -class WindowsStdErrWriter implements StdErrWriter, InitialLayerOnlyImageSingleton { +@SingletonTraits(access = RuntimeAccessOnly.class, layeredCallbacks = SingleLayer.class, layeredInstallationKind = InitialLayerOnly.class) +class WindowsStdErrWriter implements StdErrWriter { @Override @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true) public void log(CCharPointer bytes, UnsignedWord length) { @@ -57,16 +58,6 @@ public void flush() { WindowsUtils.flushUninterruptibly(getStdErrHandle()); } - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.RUNTIME_ACCESS_ONLY; - } - - @Override - public boolean accessibleInFutureLayers() { - return true; - } - @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true) private static HANDLE getStdErrHandle() { return FileAPI.NoTransition.GetStdHandle(FileAPI.STD_ERROR_HANDLE()); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/CTypeConversionSupportImpl.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/CTypeConversionSupportImpl.java index c5bda02ccb28..5cca13a0a04e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/CTypeConversionSupportImpl.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/CTypeConversionSupportImpl.java @@ -28,7 +28,6 @@ import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.Arrays; -import java.util.EnumSet; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.c.type.CCharPointer; @@ -45,13 +44,16 @@ import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton; import com.oracle.svm.core.handles.PrimitiveArrayView; import com.oracle.svm.core.jdk.DirectByteBufferUtil; -import com.oracle.svm.core.layeredimagesingleton.InitialLayerOnlyImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; +import com.oracle.svm.core.traits.BuiltinTraits.RuntimeAccessOnly; +import com.oracle.svm.core.traits.BuiltinTraits.SingleLayer; +import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.InitialLayerOnly; +import com.oracle.svm.core.traits.SingletonTraits; import jdk.graal.compiler.word.Word; @AutomaticallyRegisteredImageSingleton(CTypeConversionSupport.class) -class CTypeConversionSupportImpl implements CTypeConversionSupport, InitialLayerOnlyImageSingleton { +@SingletonTraits(access = RuntimeAccessOnly.class, layeredCallbacks = SingleLayer.class, layeredInstallationKind = InitialLayerOnly.class) +class CTypeConversionSupportImpl implements CTypeConversionSupport { static final CCharPointerHolder NULL_HOLDER = new CCharPointerHolder() { @Override @@ -193,16 +195,6 @@ public ByteBuffer asByteBuffer(PointerBase address, int size) { ByteBuffer byteBuffer = DirectByteBufferUtil.allocate(address.rawValue(), size); return byteBuffer.order(ConfigurationValues.getTarget().arch.getByteOrder()); } - - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.RUNTIME_ACCESS_ONLY; - } - - @Override - public boolean accessibleInFutureLayers() { - return true; - } } final class CCharPointerHolderImpl implements CCharPointerHolder { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/function/IsolateSupportImpl.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/function/IsolateSupportImpl.java index aeda7278340b..8880fe1bb60a 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/function/IsolateSupportImpl.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/function/IsolateSupportImpl.java @@ -24,7 +24,6 @@ */ package com.oracle.svm.core.c.function; -import java.util.EnumSet; import java.util.List; import org.graalvm.nativeimage.Isolate; @@ -41,18 +40,21 @@ import com.oracle.svm.core.c.function.CEntryPointNativeFunctions.IsolateThreadPointer; import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton; import com.oracle.svm.core.graal.stackvalue.UnsafeStackValue; -import com.oracle.svm.core.layeredimagesingleton.InitialLayerOnlyImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.core.memory.NativeMemory; import com.oracle.svm.core.nmt.NmtCategory; import com.oracle.svm.core.option.SubstrateOptionsParser; import com.oracle.svm.core.os.MemoryProtectionProvider; import com.oracle.svm.core.os.MemoryProtectionProvider.UnsupportedDomainException; +import com.oracle.svm.core.traits.BuiltinTraits.RuntimeAccessOnly; +import com.oracle.svm.core.traits.BuiltinTraits.SingleLayer; +import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.InitialLayerOnly; +import com.oracle.svm.core.traits.SingletonTraits; import jdk.graal.compiler.word.Word; @AutomaticallyRegisteredImageSingleton(IsolateSupport.class) -public final class IsolateSupportImpl implements IsolateSupport, InitialLayerOnlyImageSingleton { +@SingletonTraits(access = RuntimeAccessOnly.class, layeredCallbacks = SingleLayer.class, layeredInstallationKind = InitialLayerOnly.class) +public final class IsolateSupportImpl implements IsolateSupport { private static final String ISOLATES_DISABLED_MESSAGE = "Spawning of multiple isolates is disabled, use " + SubstrateOptionsParser.commandArgument(SubstrateOptions.SpawnIsolates, "+") + " option."; private static final String PROTECTION_DOMAIN_UNSUPPORTED_MESSAGE = "Protection domains are unavailable"; @@ -171,14 +173,4 @@ private static void throwOnError(int code) { throw new IsolateException(message); } } - - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.RUNTIME_ACCESS_ONLY; - } - - @Override - public boolean accessibleInFutureLayers() { - return true; - } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/handles/ObjectHandlesSupportImpl.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/handles/ObjectHandlesSupportImpl.java index 3a1e18bb0a36..f7c488d295df 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/handles/ObjectHandlesSupportImpl.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/handles/ObjectHandlesSupportImpl.java @@ -24,17 +24,23 @@ */ package com.oracle.svm.core.handles; -import java.util.EnumSet; - import org.graalvm.nativeimage.ObjectHandles; import org.graalvm.nativeimage.impl.ObjectHandlesSupport; import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.InitialLayerOnlyImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; +import com.oracle.svm.core.traits.BuiltinTraits.AllAccess; +import com.oracle.svm.core.traits.BuiltinTraits.SingleLayer; +import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.InitialLayerOnly; +import com.oracle.svm.core.traits.SingletonTraits; +/* + * Note in some cases object instances are accessed during code initialized at buildtime. + * However, when this is done, one must be very careful to ensure analysis sees all changes + * made to these objects. + */ @AutomaticallyRegisteredImageSingleton(ObjectHandlesSupport.class) -class ObjectHandlesSupportImpl implements ObjectHandlesSupport, InitialLayerOnlyImageSingleton { +@SingletonTraits(access = AllAccess.class, layeredCallbacks = SingleLayer.class, layeredInstallationKind = InitialLayerOnly.class) +class ObjectHandlesSupportImpl implements ObjectHandlesSupport { final ObjectHandlesImpl globalHandles = new ObjectHandlesImpl(); @Override @@ -46,19 +52,4 @@ public ObjectHandles getGlobalHandles() { public ObjectHandles createHandles() { return new ObjectHandlesImpl(); } - - @Override - public EnumSet getImageBuilderFlags() { - /* - * In some cases object instances are accessed during code initialized at buildtime. - * However, when this is done, one must be very careful to ensure analysis sees all changes - * made to these objects. - */ - return LayeredImageSingletonBuilderFlags.ALL_ACCESS; - } - - @Override - public boolean accessibleInFutureLayers() { - return true; - } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/GCCause.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/GCCause.java index cac994d73f34..2838c80c2fb5 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/GCCause.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/GCCause.java @@ -41,9 +41,12 @@ import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader; import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; -import com.oracle.svm.core.layeredimagesingleton.InitialLayerOnlyImageSingleton; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; +import com.oracle.svm.core.traits.BuiltinTraits.AllAccess; +import com.oracle.svm.core.traits.BuiltinTraits.SingleLayer; +import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.InitialLayerOnly; +import com.oracle.svm.core.traits.SingletonTraits; import com.oracle.svm.core.util.DuplicatedInNativeCode; import com.oracle.svm.core.util.ImageHeapList; import com.oracle.svm.core.util.VMError; @@ -97,7 +100,8 @@ public static void registerGCCause(GCCause cause) { } @AutomaticallyRegisteredImageSingleton -class GCCauseSupport implements InitialLayerOnlyImageSingleton { +@SingletonTraits(access = AllAccess.class, layeredCallbacks = SingleLayer.class, layeredInstallationKind = InitialLayerOnly.class) +class GCCauseSupport { final List gcCauses = ImageHeapList.create(GCCause.class, null); @Platforms(Platform.HOSTED_ONLY.class) @@ -121,16 +125,6 @@ void installGCCause(GCCause gcCause) { throw VMError.shouldNotReachHere("Two GCCause objects have the same id " + id + ": " + gcCause.getName() + ", " + existing.getName()); } } - - @Override - public boolean accessibleInFutureLayers() { - return true; - } - - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.ALL_ACCESS; - } } @AutomaticallyRegisteredFeature 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 834d9e0b968f..3201854670fd 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 @@ -25,7 +25,6 @@ package com.oracle.svm.core.heap; import java.lang.management.ManagementFactory; -import java.util.EnumSet; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; @@ -37,8 +36,10 @@ import com.oracle.svm.core.Uninterruptible; import com.oracle.svm.core.container.Container; import com.oracle.svm.core.container.OperatingSystem; -import com.oracle.svm.core.layeredimagesingleton.InitialLayerOnlyImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; +import com.oracle.svm.core.traits.BuiltinTraits.RuntimeAccessOnly; +import com.oracle.svm.core.traits.BuiltinTraits.SingleLayer; +import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.InitialLayerOnly; +import com.oracle.svm.core.traits.SingletonTraits; import com.oracle.svm.core.util.UnsignedUtils; import com.oracle.svm.core.util.VMError; import com.sun.management.OperatingSystemMXBean; @@ -51,7 +52,8 @@ public class PhysicalMemory { /** Implemented by operating-system specific code. */ - public interface PhysicalMemorySupport extends InitialLayerOnlyImageSingleton { + @SingletonTraits(access = RuntimeAccessOnly.class, layeredCallbacks = SingleLayer.class, layeredInstallationKind = InitialLayerOnly.class) + public interface PhysicalMemorySupport { /** Get the size of physical memory from the OS. */ UnsignedWord size(); @@ -66,11 +68,6 @@ public interface PhysicalMemorySupport extends InitialLayerOnlyImageSingleton { default long usedSize() { return -1L; } - - @Override - default EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.RUNTIME_ACCESS_ONLY; - } } private static final UnsignedWord UNSET_SENTINEL = UnsignedUtils.MAX_VALUE; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/dump/HeapDumpMetadata.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/dump/HeapDumpMetadata.java index 2a336309b924..30f847536fb5 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/dump/HeapDumpMetadata.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/dump/HeapDumpMetadata.java @@ -46,13 +46,16 @@ import com.oracle.svm.core.heap.ObjectVisitor; import com.oracle.svm.core.heap.UnknownObjectField; import com.oracle.svm.core.hub.DynamicHub; -import com.oracle.svm.core.layeredimagesingleton.InitialLayerOnlyImageSingleton; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonSupport; import com.oracle.svm.core.layeredimagesingleton.MultiLayeredImageSingleton; import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton; import com.oracle.svm.core.memory.NullableNativeMemory; import com.oracle.svm.core.nmt.NmtCategory; +import com.oracle.svm.core.traits.BuiltinTraits.RuntimeAccessOnly; +import com.oracle.svm.core.traits.BuiltinTraits.SingleLayer; +import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.InitialLayerOnly; +import com.oracle.svm.core.traits.SingletonTraits; import com.oracle.svm.core.util.coder.ByteStream; import com.oracle.svm.core.util.coder.ByteStreamAccess; import com.oracle.svm.core.util.coder.NativeCoder; @@ -101,7 +104,8 @@ * |----------------------------| * */ -public class HeapDumpMetadata implements InitialLayerOnlyImageSingleton { +@SingletonTraits(access = RuntimeAccessOnly.class, layeredCallbacks = SingleLayer.class, layeredInstallationKind = InitialLayerOnly.class) +public class HeapDumpMetadata { private final ComputeHubDataVisitor computeHubDataVisitor; private int fieldNameCount; @@ -322,16 +326,6 @@ static int computeFieldsDumpSize(FieldInfoPointer fields, int fieldCount) { return result; } - @Override - public boolean accessibleInFutureLayers() { - return true; - } - - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.RUNTIME_ACCESS_ONLY; - } - @RawStructure public interface ClassInfo extends PointerBase { @RawField diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/StringInternSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/StringInternSupport.java index 82b1c8e831b4..6179fc25ca50 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/StringInternSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/StringInternSupport.java @@ -45,12 +45,15 @@ import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader; import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; -import com.oracle.svm.core.layeredimagesingleton.InitialLayerOnlyImageSingleton; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonSupport; import com.oracle.svm.core.layeredimagesingleton.MultiLayeredImageSingleton; import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton; +import com.oracle.svm.core.traits.BuiltinTraits.RuntimeAccessOnly; +import com.oracle.svm.core.traits.BuiltinTraits.SingleLayer; +import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.InitialLayerOnly; +import com.oracle.svm.core.traits.SingletonTraits; import com.oracle.svm.util.ReflectionUtil; @AutomaticallyRegisteredImageSingleton @@ -187,7 +190,8 @@ public static Object createFromLoader(ImageSingletonLoader loader) { } @AutomaticallyRegisteredImageSingleton -class RuntimeInternedStrings implements InitialLayerOnlyImageSingleton { +@SingletonTraits(access = RuntimeAccessOnly.class, layeredCallbacks = SingleLayer.class, layeredInstallationKind = InitialLayerOnly.class) +class RuntimeInternedStrings { /** The String intern table at run time. */ final ConcurrentHashMap internedStrings = new ConcurrentHashMap<>(16, 0.75f, 1); @@ -195,16 +199,6 @@ class RuntimeInternedStrings implements InitialLayerOnlyImageSingleton { static ConcurrentHashMap getInternedStrings() { return ImageSingletons.lookup(RuntimeInternedStrings.class).internedStrings; } - - @Override - public boolean accessibleInFutureLayers() { - return true; - } - - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.RUNTIME_ACCESS_ONLY; - } } @AutomaticallyRegisteredImageSingleton diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SystemInOutErrSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SystemInOutErrSupport.java index fc7add09ee79..b83ce6899e79 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SystemInOutErrSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SystemInOutErrSupport.java @@ -32,7 +32,6 @@ import java.io.InputStream; import java.io.PrintStream; import java.io.UnsupportedEncodingException; -import java.util.EnumSet; import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; @@ -42,8 +41,10 @@ import org.graalvm.nativeimage.hosted.Feature; import com.oracle.svm.core.layeredimagesingleton.FeatureSingleton; -import com.oracle.svm.core.layeredimagesingleton.InitialLayerOnlyImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; +import com.oracle.svm.core.traits.BuiltinTraits.AllAccess; +import com.oracle.svm.core.traits.BuiltinTraits.SingleLayer; +import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.InitialLayerOnly; +import com.oracle.svm.core.traits.SingletonTraits; import com.oracle.svm.core.util.VMError; import jdk.graal.compiler.api.replacements.Fold; @@ -58,7 +59,8 @@ * This can be customized by calling {@link #setIn}, {@link #setOut}, and {@link #setErr} before the * static analysis starts, i.e., in a {@link Feature#beforeAnalysis} method. */ -public final class SystemInOutErrSupport implements InitialLayerOnlyImageSingleton { +@SingletonTraits(access = AllAccess.class, layeredCallbacks = SingleLayer.class, layeredInstallationKind = InitialLayerOnly.class) +public final class SystemInOutErrSupport { private final InputStream initialIn = new BufferedInputStream(new FileInputStream(FileDescriptor.in)); private InputStream in = initialIn; private PrintStream out = newPrintStream(new FileOutputStream(FileDescriptor.out), System.getProperty("sun.stdout.encoding")); @@ -143,11 +145,6 @@ public static void setErr(PrintStream err) { support.checkSealed(); support.err = Objects.requireNonNull(err); } - - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.ALL_ACCESS; - } } @SuppressWarnings("unused") diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/InitialLayerOnlyImageSingleton.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/InitialLayerOnlyImageSingleton.java deleted file mode 100644 index 2eca3250dbea..000000000000 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/InitialLayerOnlyImageSingleton.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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; - -import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; -import com.oracle.svm.core.util.VMError; - -public interface InitialLayerOnlyImageSingleton extends LayeredImageSingleton { - - @Override - default PersistFlags preparePersist(ImageSingletonWriter writer) { - VMError.guarantee(ImageLayerBuildingSupport.buildingInitialLayer(), "This singleton should only be installed in the initial layer"); - return PersistFlags.FORBIDDEN; - } - - /** - * When true is returned, runtime code within future layers can call - * {@link ImageSingletons#lookup} and the singleton will be constant folded into the code. In - * the future layers it will still not be possible to call {@link ImageSingletons#lookup} at - * build time. - */ - default boolean accessibleInFutureLayers() { - return false; - } -} 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 index 01a89b424a83..2a8977ebb3f8 100644 --- 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 @@ -25,11 +25,14 @@ package com.oracle.svm.core.layeredimagesingleton; import java.util.Collection; +import java.util.Set; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; +import com.oracle.svm.core.traits.SingletonLayeredInstallationKind; + import jdk.vm.ci.meta.JavaConstant; @Platforms(Platform.HOSTED_ONLY.class) @@ -49,7 +52,9 @@ static LayeredImageSingletonSupport singleton() { Collection> getMultiLayeredImageSingletonKeys(); - Collection> getFutureLayerAccessibleImageSingletonKeys(); + Set getSingletonsWithTrait(SingletonLayeredInstallationKind.InstallationKind kind); + + void forbidNewTraitInstallations(SingletonLayeredInstallationKind.InstallationKind kind); void freezeLayeredImageSingletonMetadata(); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/log/FunctionPointerLogHandler.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/log/FunctionPointerLogHandler.java index 777630176789..e2594c4f317f 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/log/FunctionPointerLogHandler.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/log/FunctionPointerLogHandler.java @@ -24,8 +24,6 @@ */ package com.oracle.svm.core.log; -import java.util.EnumSet; - import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.LogHandler; import org.graalvm.nativeimage.c.function.CFunctionPointer; @@ -41,14 +39,17 @@ import com.oracle.svm.core.c.CGlobalDataFactory; import com.oracle.svm.core.headers.LibC; import com.oracle.svm.core.heap.RestrictHeapAccess; -import com.oracle.svm.core.layeredimagesingleton.InitialLayerOnlyImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; +import com.oracle.svm.core.traits.BuiltinTraits.RuntimeAccessOnly; +import com.oracle.svm.core.traits.BuiltinTraits.SingleLayer; +import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.InitialLayerOnly; +import com.oracle.svm.core.traits.SingletonTraits; /** * A {@link LogHandler} that can use provided function pointers for each operation. If a function * pointer is missing, it forwards the operation to the delegate set in the constructor. */ -public class FunctionPointerLogHandler implements LogHandlerExtension, InitialLayerOnlyImageSingleton { +@SingletonTraits(access = RuntimeAccessOnly.class, layeredCallbacks = SingleLayer.class, layeredInstallationKind = InitialLayerOnly.class) +public class FunctionPointerLogHandler implements LogHandlerExtension { private static final CGlobalData LOG_OPTION = CGlobalDataFactory.createCString("_log"); private static final CGlobalData FATAL_LOG_OPTION = CGlobalDataFactory.createCString("_fatal_log"); private static final CGlobalData FLUSH_LOG_OPTION = CGlobalDataFactory.createCString("_flush_log"); @@ -189,14 +190,4 @@ public static void afterParsingJniVMOptions() { throw new IllegalArgumentException("The _log option cannot be null when _flush_log is non-null"); } } - - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.RUNTIME_ACCESS_ONLY; - } - - @Override - public boolean accessibleInFutureLayers() { - return true; - } } 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 78353dfe00ba..0abc693282a8 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 @@ -27,8 +27,6 @@ import static com.oracle.svm.core.Uninterruptible.CALLED_FROM_UNINTERRUPTIBLE_CODE; import static com.oracle.svm.core.graal.nodes.WriteCurrentVMThreadNode.writeCurrentVMThread; -import java.util.EnumSet; - import org.graalvm.nativeimage.CurrentIsolate; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Isolate; @@ -53,8 +51,6 @@ import com.oracle.svm.core.jdk.UninterruptibleUtils; import com.oracle.svm.core.jdk.UninterruptibleUtils.AtomicWord; import com.oracle.svm.core.layeredimagesingleton.FeatureSingleton; -import com.oracle.svm.core.layeredimagesingleton.InitialLayerOnlyImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.core.locks.VMCondition; import com.oracle.svm.core.locks.VMLockSupport; import com.oracle.svm.core.locks.VMMutex; @@ -69,6 +65,10 @@ import com.oracle.svm.core.threadlocal.FastThreadLocalInt; import com.oracle.svm.core.threadlocal.FastThreadLocalWord; import com.oracle.svm.core.threadlocal.VMThreadLocalSupport; +import com.oracle.svm.core.traits.BuiltinTraits.RuntimeAccessOnly; +import com.oracle.svm.core.traits.BuiltinTraits.SingleLayer; +import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.InitialLayerOnly; +import com.oracle.svm.core.traits.SingletonTraits; import com.oracle.svm.core.util.UnsignedUtils; import com.oracle.svm.core.util.VMError; @@ -84,7 +84,7 @@ /** * Utility methods for the manipulation and iteration of {@link IsolateThread}s. */ -public abstract class VMThreads implements InitialLayerOnlyImageSingleton { +public abstract class VMThreads { @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static VMThreads singleton() { @@ -737,11 +737,6 @@ public static boolean printLocationInfo(Log log, UnsignedWord value, boolean all return false; } - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.RUNTIME_ACCESS_ONLY; - } - private static class DetachAllExternallyStartedThreadsExceptCurrentOperation extends JavaVMOperation { DetachAllExternallyStartedThreadsExceptCurrentOperation() { super(VMOperationInfos.get(DetachAllExternallyStartedThreadsExceptCurrentOperation.class, "Detach all externally started threads except current", SystemEffect.SAFEPOINT)); @@ -1125,7 +1120,8 @@ public interface OSThreadHandle extends PointerBase { public interface OSThreadId extends PointerBase { } - public static class ThreadLookup implements InitialLayerOnlyImageSingleton { + @SingletonTraits(access = RuntimeAccessOnly.class, layeredCallbacks = SingleLayer.class, layeredInstallationKind = InitialLayerOnly.class) + public static class ThreadLookup { @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public ComparableWord getThreadIdentifier() { return VMThreads.singleton().getCurrentOSThreadId(); @@ -1135,11 +1131,6 @@ public ComparableWord getThreadIdentifier() { public boolean matchesThread(IsolateThread thread, ComparableWord identifier) { return OSThreadIdTL.get(thread).equal(identifier); } - - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.RUNTIME_ACCESS_ONLY; - } } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/VMThreadLocalInfos.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/VMThreadLocalInfos.java index 49811c460312..ae7d76b8924f 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/VMThreadLocalInfos.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/VMThreadLocalInfos.java @@ -27,7 +27,6 @@ import static com.oracle.svm.core.Uninterruptible.CALLED_FROM_UNINTERRUPTIBLE_CODE; import java.util.Collection; -import java.util.EnumSet; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.IsolateThread; @@ -42,14 +41,17 @@ import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton; import com.oracle.svm.core.heap.ReferenceAccess; import com.oracle.svm.core.heap.UnknownObjectField; -import com.oracle.svm.core.layeredimagesingleton.InitialLayerOnlyImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.core.log.Log; +import com.oracle.svm.core.traits.BuiltinTraits.AllAccess; +import com.oracle.svm.core.traits.BuiltinTraits.SingleLayer; +import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.InitialLayerOnly; +import com.oracle.svm.core.traits.SingletonTraits; import jdk.graal.compiler.word.Word; @AutomaticallyRegisteredImageSingleton -public class VMThreadLocalInfos implements InitialLayerOnlyImageSingleton { +@SingletonTraits(access = AllAccess.class, layeredCallbacks = SingleLayer.class, layeredInstallationKind = InitialLayerOnly.class) +public class VMThreadLocalInfos { /** * The {@link VMThreadLocalInfo} objects are scanned during analysis as soon as they are * discovered. After analysis, they are sorted and stored in the infos field. @@ -129,9 +131,4 @@ public static int getOffset(FastThreadLocal threadLocal) { } return -1; } - - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.ALL_ACCESS; - } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/VMThreadLocalSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/VMThreadLocalSupport.java index 095968f2ab42..9cf61f054532 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/VMThreadLocalSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/threadlocal/VMThreadLocalSupport.java @@ -24,8 +24,6 @@ */ package com.oracle.svm.core.threadlocal; -import java.util.EnumSet; - import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.IsolateThread; import org.graalvm.nativeimage.Platform; @@ -41,12 +39,15 @@ import com.oracle.svm.core.heap.ObjectReferenceVisitor; import com.oracle.svm.core.heap.UnknownObjectField; import com.oracle.svm.core.heap.UnknownPrimitiveField; -import com.oracle.svm.core.layeredimagesingleton.InitialLayerOnlyImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; +import com.oracle.svm.core.traits.BuiltinTraits.AllAccess; +import com.oracle.svm.core.traits.BuiltinTraits.SingleLayer; +import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.InitialLayerOnly; +import com.oracle.svm.core.traits.SingletonTraits; import jdk.graal.compiler.api.replacements.Fold; -public class VMThreadLocalSupport implements InitialLayerOnlyImageSingleton { +@SingletonTraits(access = AllAccess.class, layeredCallbacks = SingleLayer.class, layeredInstallationKind = InitialLayerOnly.class) +public class VMThreadLocalSupport { @UnknownPrimitiveField(availability = ReadyForCompilation.class) public int vmThreadSize = -1; @UnknownObjectField(availability = ReadyForCompilation.class) public byte[] vmThreadReferenceMapEncoding; @UnknownPrimitiveField(availability = ReadyForCompilation.class) public long vmThreadReferenceMapIndex = -1; @@ -80,9 +81,4 @@ public void walk(IsolateThread isolateThread, ObjectReferenceVisitor referenceVi InstanceReferenceMap referenceMap = InstanceReferenceMapDecoder.getReferenceMap(threadRefMapEncoding, vmThreadReferenceMapIndex); InstanceReferenceMapDecoder.walkReferences((Pointer) isolateThread, referenceMap, referenceVisitor, null); } - - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.ALL_ACCESS; - } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/traits/BuiltinTraits.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/traits/BuiltinTraits.java index 6e98e334d488..b191b1a45373 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/traits/BuiltinTraits.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/traits/BuiltinTraits.java @@ -91,6 +91,25 @@ public SingletonTrait getLayeredCallbacksTrait() { } } + /** + * Trait indicating nothing should be persisted for this singleton and that a singleton cannot + * be linked to this key in a subsequent image layer. This limits the singleton to being + * installed in a single layer. + */ + public static final SingletonTrait SINGLE_LAYER = new SingletonTrait(SingletonTraitKind.LAYERED_CALLBACKS, new SingletonLayeredCallbacks() { + @Override + public LayeredImageSingleton.PersistFlags doPersist(ImageSingletonWriter writer, Object singleton) { + return LayeredImageSingleton.PersistFlags.FORBIDDEN; + } + }); + + public static class SingleLayer extends SingletonLayeredCallbacksSupplier { + @Override + public SingletonTrait getLayeredCallbacksTrait() { + return SINGLE_LAYER; + } + } + /** * Trait indicating this singleton can be made more layer-aware in the future. See * {@link SingletonTraitKind#DUPLICABLE} for more information. diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/traits/SingletonLayeredInstallationKind.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/traits/SingletonLayeredInstallationKind.java index bd9c98e0c1d9..491ea9c2cc8d 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/traits/SingletonLayeredInstallationKind.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/traits/SingletonLayeredInstallationKind.java @@ -52,11 +52,6 @@ public enum InstallationKind { */ INDEPENDENT(EmptyMetadata.class), - /* - * GR-66793, GR-66794, GR-66795, : switch from using interfaces to traits for implementing - * the following behaviors. - */ - /** * This singleton can only be installed in the initial layer. All references to this * singleton in all code compiled across all layers refer to the singleton installed in the @@ -64,6 +59,11 @@ public enum InstallationKind { */ INITIAL_LAYER_ONLY(EmptyMetadata.class), + /* + * GR-66794, GR-66795, : switch from using interfaces to traits for implementing the + * following behaviors. + */ + /** * This singleton can only be installed in the app layer. All references to this singleton * in all code compiled across all layers refer to the singleton installed in the app layer. @@ -103,13 +103,9 @@ public SingletonLayeredInstallationKind(InstallationKind kind, Object metadata) VMError.guarantee(kind.metadataClass.isInstance(metadata)); } - public static void validate(SingletonTrait trait) { + public static InstallationKind getInstallationKind(SingletonTrait trait) { VMError.guarantee(trait.kind() == SingletonTraitKind.LAYERED_INSTALLATION_KIND); - SingletonLayeredInstallationKind behavior = (SingletonLayeredInstallationKind) trait.metadata(); - if (behavior.kind() == InstallationKind.DISALLOWED) { - throw VMError.shouldNotReachHere("This singleton cannot be added to this layer"); - - } + return ((SingletonLayeredInstallationKind) trait.metadata()).kind; } static final SingletonTrait DISALLOWED_TRAIT = new SingletonTrait(SingletonTraitKind.LAYERED_INSTALLATION_KIND, @@ -131,4 +127,14 @@ public SingletonTrait getLayeredInstallationKindTrait() { return INDEPENDENT_TRAIT; } } + + static final SingletonTrait INITIAL_LAYER_ONLY = new SingletonTrait(SingletonTraitKind.LAYERED_INSTALLATION_KIND, + new SingletonLayeredInstallationKind(InstallationKind.INITIAL_LAYER_ONLY, EmptyMetadata.EMPTY)); + + public static final class InitialLayerOnly extends SingletonLayeredInstallationKindSupplier { + @Override + public SingletonTrait getLayeredInstallationKindTrait() { + return INITIAL_LAYER_ONLY; + } + } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/traits/SingletonLayeredInstallationKindSupplier.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/traits/SingletonLayeredInstallationKindSupplier.java index 93f1b9698e1f..e75ef3757656 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/traits/SingletonLayeredInstallationKindSupplier.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/traits/SingletonLayeredInstallationKindSupplier.java @@ -29,6 +29,6 @@ * {@link SingletonTrait}. See {@link SingletonTraits} and * {@link SingletonTraitKind#LAYERED_INSTALLATION_KIND} for more information. */ -public abstract sealed class SingletonLayeredInstallationKindSupplier permits SingletonLayeredInstallationKind.Disallowed, SingletonLayeredInstallationKind.Independent { +public abstract sealed class SingletonLayeredInstallationKindSupplier permits SingletonLayeredInstallationKind.Disallowed, SingletonLayeredInstallationKind.Independent, SingletonLayeredInstallationKind.InitialLayerOnly { public abstract SingletonTrait getLayeredInstallationKindTrait(); } 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 96349cab9258..55c5e2fb52f1 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 @@ -38,8 +38,9 @@ import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; import com.oracle.svm.core.layeredimagesingleton.FeatureSingleton; import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton; -import com.oracle.svm.core.traits.BuiltinTraits; -import com.oracle.svm.core.traits.SingletonLayeredInstallationKind; +import com.oracle.svm.core.traits.BuiltinTraits.BuildtimeAccessOnly; +import com.oracle.svm.core.traits.BuiltinTraits.NoLayeredCallbacks; +import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.Independent; import com.oracle.svm.core.traits.SingletonTraits; import jdk.graal.compiler.replacements.StringLatin1InflateNode; @@ -74,7 +75,7 @@ @AutomaticallyRegisteredFeature @Platforms(AMD64.class) -@SingletonTraits(access = BuiltinTraits.BuildtimeAccessOnly.class, layeredCallbacks = BuiltinTraits.NoLayeredCallbacks.class, layeredInstallationKind = SingletonLayeredInstallationKind.Independent.class) +@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class) 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 b87cba89d2f8..08f80aa982da 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 @@ -27,11 +27,13 @@ import java.util.Collection; import java.util.Comparator; import java.util.EnumMap; +import java.util.EnumSet; import java.util.HashSet; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.impl.AnnotationExtractor; @@ -39,7 +41,6 @@ import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; import com.oracle.svm.core.layeredimagesingleton.ApplicationLayerOnlyImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.InitialLayerOnlyImageSingleton; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton.PersistFlags; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; @@ -91,13 +92,18 @@ public Collection> getMultiLayeredImageSingletonKeys() { } @Override - public Collection> getFutureLayerAccessibleImageSingletonKeys() { - return HostedManagement.getAndAssertExists().getFutureLayerAccessibleImageSingletonKeys(); + public void freezeLayeredImageSingletonMetadata() { + HostedManagement.getAndAssertExists().freezeLayeredImageSingletonMetadata(); } @Override - public void freezeLayeredImageSingletonMetadata() { - HostedManagement.getAndAssertExists().freezeLayeredImageSingletonMetadata(); + public Set getSingletonsWithTrait(SingletonLayeredInstallationKind.InstallationKind kind) { + return HostedManagement.getAndAssertExists().getSingletonsWithTrait(kind); + } + + @Override + public void forbidNewTraitInstallations(SingletonLayeredInstallationKind.InstallationKind kind) { + HostedManagement.getAndAssertExists().forbidNewTraitInstallations(kind); } @Override @@ -326,8 +332,14 @@ public static void persist() { private final Map, SingletonInfo> configObjects; private final Map singletonToTraitMap; + + /** + * At first, only + * {@link com.oracle.svm.core.traits.SingletonLayeredInstallationKind.InstallationKind#DISALLOWED} + * is forbidden. More forbidden kinds can be added via {@link #forbidNewTraitInstallations}. + */ + private final EnumSet forbiddenInstallationKinds = EnumSet.of(SingletonLayeredInstallationKind.InstallationKind.DISALLOWED); private Set> multiLayeredImageSingletonKeys; - private Set> futureLayerAccessibleImageSingletonKeys; private final boolean layeredBuild; private final AnnotationExtractor extractor; @@ -339,7 +351,6 @@ public HostedManagement(boolean layeredBuild, AnnotationExtractor extractor) { this.configObjects = new ConcurrentHashMap<>(); this.singletonToTraitMap = new ConcurrentIdentityHashMap<>(); this.multiLayeredImageSingletonKeys = ConcurrentHashMap.newKeySet(); - this.futureLayerAccessibleImageSingletonKeys = ConcurrentHashMap.newKeySet(); this.layeredBuild = layeredBuild; this.extractor = extractor; } @@ -392,7 +403,12 @@ private void addSingleton(Class key, Object value) { LayeredImageSingletonBuilderFlags.verifyImageBuilderFlags(value, SingletonAccess.getAccess(trait)); }); if (layeredBuild) { - traitMap.getTrait(SingletonTraitKind.LAYERED_INSTALLATION_KIND).ifPresent(SingletonLayeredInstallationKind::validate); + traitMap.getTrait(SingletonTraitKind.LAYERED_INSTALLATION_KIND).ifPresent(trait -> { + var kind = SingletonLayeredInstallationKind.getInstallationKind(trait); + if (forbiddenInstallationKinds.contains(kind)) { + throw VMError.shouldNotReachHere("Singleton with installation kind %s can no longer be added: %s", kind, value); + } + }); } } SingletonTraitMap candidateTraitMap = traitMap; @@ -421,10 +437,6 @@ private void addSingletonToMap(Class key, Object value, SingletonTraitMap tra multiLayeredImageSingletonKeys.add(key); } } - - if (singleton instanceof InitialLayerOnlyImageSingleton initial && initial.accessibleInFutureLayers()) { - futureLayerAccessibleImageSingletonKeys.add(key); - } } Object prevValue = configObjects.putIfAbsent(key, new SingletonInfo(value, traitMap)); @@ -438,13 +450,22 @@ Collection> getMultiLayeredImageSingletonKeys() { return multiLayeredImageSingletonKeys; } - Collection> getFutureLayerAccessibleImageSingletonKeys() { - return futureLayerAccessibleImageSingletonKeys; - } - void freezeLayeredImageSingletonMetadata() { multiLayeredImageSingletonKeys = Set.copyOf(multiLayeredImageSingletonKeys); - futureLayerAccessibleImageSingletonKeys = Set.copyOf(futureLayerAccessibleImageSingletonKeys); + } + + Set getSingletonsWithTrait(SingletonLayeredInstallationKind.InstallationKind kind) { + return configObjects.values().stream().filter(singletonInfo -> { + var optionalTrait = singletonInfo.traitMap().getTrait(SingletonTraitKind.LAYERED_INSTALLATION_KIND); + if (optionalTrait.orElse(null) instanceof SingletonTrait trait) { + return SingletonLayeredInstallationKind.getInstallationKind(trait) == kind; + } + return false; + }).map(SingletonInfo::singleton).collect(Collectors.toUnmodifiableSet()); + } + + void forbidNewTraitInstallations(SingletonLayeredInstallationKind.InstallationKind kind) { + forbiddenInstallationKinds.add(kind); } /** diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/OpenTypeWorldFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/OpenTypeWorldFeature.java index ee104e237178..9e4f78f37c17 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/OpenTypeWorldFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/OpenTypeWorldFeature.java @@ -46,10 +46,10 @@ import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; import com.oracle.svm.core.meta.SharedMethod; -import com.oracle.svm.core.traits.BuiltinTraits; +import com.oracle.svm.core.traits.BuiltinTraits.BuildtimeAccessOnly; import com.oracle.svm.core.traits.SingletonLayeredCallbacks; import com.oracle.svm.core.traits.SingletonLayeredCallbacksSupplier; -import com.oracle.svm.core.traits.SingletonLayeredInstallationKind; +import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.Independent; import com.oracle.svm.core.traits.SingletonTrait; import com.oracle.svm.core.traits.SingletonTraitKind; import com.oracle.svm.core.traits.SingletonTraits; @@ -264,7 +264,7 @@ static TypeCheckInfo getTypecheckInfo(SVMImageLayerLoader loader, HostedType hTy record TypeCheckInfo(boolean installed, int typeID, int numClassTypes, int numInterfaceTypes, int[] typecheckSlots) { } - @SingletonTraits(access = BuiltinTraits.BuildtimeAccessOnly.class, layeredCallbacks = LayeredCallbacks.class, layeredInstallationKind = SingletonLayeredInstallationKind.Independent.class) + @SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = LayeredCallbacks.class, layeredInstallationKind = Independent.class) private static final class LayerTypeCheckInfo { final int maxTypeID; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporter.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporter.java index 34bf77cbfe0b..0857ded57a97 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporter.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporter.java @@ -82,8 +82,9 @@ import com.oracle.svm.core.option.OptionUtils; import com.oracle.svm.core.option.RuntimeOptionKey; import com.oracle.svm.core.option.SubstrateOptionsParser; -import com.oracle.svm.core.traits.BuiltinTraits; -import com.oracle.svm.core.traits.SingletonLayeredInstallationKind; +import com.oracle.svm.core.traits.BuiltinTraits.BuildtimeAccessOnly; +import com.oracle.svm.core.traits.BuiltinTraits.NoLayeredCallbacks; +import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.Independent; import com.oracle.svm.core.traits.SingletonTraits; import com.oracle.svm.core.util.TimeUtils; import com.oracle.svm.core.util.VMError; @@ -109,7 +110,7 @@ import jdk.graal.compiler.options.OptionValues; import jdk.graal.compiler.util.json.JsonWriter; -@SingletonTraits(access = BuiltinTraits.BuildtimeAccessOnly.class, layeredCallbacks = BuiltinTraits.NoLayeredCallbacks.class, layeredInstallationKind = SingletonLayeredInstallationKind.Independent.class) +@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class) public class ProgressReporter { private static final int CHARACTERS_PER_LINE; private static final String HEADLINE_SEPARATOR; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LoadImageSingletonFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LoadImageSingletonFeature.java index 01d2e829d9a9..c6bf205913d4 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LoadImageSingletonFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LoadImageSingletonFeature.java @@ -68,6 +68,7 @@ import com.oracle.svm.core.layeredimagesingleton.MultiLayeredAllowNullEntries; import com.oracle.svm.core.layeredimagesingleton.MultiLayeredImageSingleton; import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton; +import com.oracle.svm.core.traits.SingletonLayeredInstallationKind; import com.oracle.svm.core.util.UserError; import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.FeatureImpl; @@ -194,6 +195,7 @@ public void processRegisteredSingletons(AnalysisUniverse universe) { loader = (SVMImageLayerLoader) universe.getImageLayerLoader(); LayeredImageSingletonSupport layeredImageSingletonSupport = LayeredImageSingletonSupport.singleton(); + layeredImageSingletonSupport.forbidNewTraitInstallations(SingletonLayeredInstallationKind.InstallationKind.INITIAL_LAYER_ONLY); layeredImageSingletonSupport.freezeLayeredImageSingletonMetadata(); Consumer multiLayerEmbeddedRootsRegistration = (objArray) -> { @@ -217,8 +219,7 @@ public void processRegisteredSingletons(AnalysisUniverse universe) { /* * Make sure all image singletons accessible in future layers are persisted. */ - for (Class key : layeredImageSingletonSupport.getFutureLayerAccessibleImageSingletonKeys()) { - var singleton = layeredImageSingletonSupport.lookup(key, true, false); + for (var singleton : layeredImageSingletonSupport.getSingletonsWithTrait(SingletonLayeredInstallationKind.InstallationKind.INITIAL_LAYER_ONLY)) { ImageHeapConstant constant = (ImageHeapConstant) universe.getSnippetReflection().forObject(singleton); SVMImageLayerSnapshotUtil.forcePersistConstant(constant); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerSingletonLoader.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerSingletonLoader.java index 972803710258..ddb1ba3349ac 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerSingletonLoader.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerSingletonLoader.java @@ -139,7 +139,7 @@ public JavaConstant loadInitialLayerOnlyImageSingleton(Class key) { if (constantId != -1) { return imageLayerBuildingSupport.getLoader().getOrCreateConstant(constantId); } - throw UserError.abort("Unable to load InitialLayerOnlyImageSingleton: %s. Please override accessibleInFutureLayers if you want this singleton to be reachable in future layers.", key); + throw UserError.abort("Unable to load InitialLayerOnlyImageSingleton: %s", key); } public Class lookupClass(boolean optional, String className) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerWriter.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerWriter.java index 106d404ab86a..a188ba628ae8 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerWriter.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerWriter.java @@ -104,8 +104,8 @@ import com.oracle.svm.core.hub.DynamicHub; import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader; import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; -import com.oracle.svm.core.layeredimagesingleton.InitialLayerOnlyImageSingleton; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonSupport; import com.oracle.svm.core.layeredimagesingleton.MultiLayeredImageSingleton; import com.oracle.svm.core.meta.MethodOffset; import com.oracle.svm.core.meta.MethodPointer; @@ -114,6 +114,7 @@ import com.oracle.svm.core.threadlocal.FastThreadLocal; import com.oracle.svm.core.traits.InjectedSingletonLayeredCallbacks; import com.oracle.svm.core.traits.SingletonLayeredCallbacks; +import com.oracle.svm.core.traits.SingletonLayeredInstallationKind; import com.oracle.svm.core.traits.SingletonTraitKind; import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.ImageSingletonsSupportImpl; @@ -201,7 +202,6 @@ public class SVMImageLayerWriter extends ImageLayerWriter { private final SharedLayerSnapshot.Builder snapshotBuilder = this.snapshotFileBuilder.initRoot(SharedLayerSnapshot.factory); private Map constantsMap; private final Map methodsMap = new ConcurrentHashMap<>(); - private final Map initialLayerOnlySingletonMap = new ConcurrentHashMap<>(); private final Map> polymorphicSignatureCallers = new ConcurrentHashMap<>(); private final GraphsOutput graphsOutput; private final boolean useSharedLayerGraphs; @@ -806,13 +806,6 @@ private void persistConstant(ImageHeapConstant imageHeapConstant, ConstantParent int identityHashCode = identityHashCodeProvider.identityHashCode(imageHeapConstant); builder.setIdentityHashCode(identityHashCode); - if (imageHeapConstant.isBackedByHostedObject() && InitialLayerOnlyImageSingleton.class.isAssignableFrom(type.getJavaClass())) { - InitialLayerOnlyImageSingleton singleton = aUniverse.getBigbang().getSnippetReflectionProvider().asObject(InitialLayerOnlyImageSingleton.class, imageHeapConstant.getHostedObject()); - if (singleton.accessibleInFutureLayers()) { - initialLayerOnlySingletonMap.put(singleton, id); - } - } - switch (imageHeapConstant) { case ImageHeapInstance imageHeapInstance -> { builder.initObject().setInstance(Void.VOID); @@ -1124,15 +1117,21 @@ public void writeImageSingletonInfo(List, ImageSingletonsSupp StructList.Builder singletonsBuilder = snapshotBuilder.initSingletonKeys(layeredImageSingletons.size()); Map singletonPersistInfoMap = new HashMap<>(); int nextID = 1; + Set initialLayerSingletons = LayeredImageSingletonSupport.singleton().getSingletonsWithTrait(SingletonLayeredInstallationKind.InstallationKind.INITIAL_LAYER_ONLY); for (int i = 0; i < layeredImageSingletons.size(); i++) { var singletonEntry = layeredImageSingletons.get(i); String key = singletonEntry.getKey().getName(); Object singleton = singletonEntry.getValue().singleton(); + boolean initialLayerOnly = initialLayerSingletons.contains(singleton); if (!singletonPersistInfoMap.containsKey(singleton)) { var writer = new ImageSingletonWriterImpl(snapshotBuilder, hUniverse); SingletonLayeredCallbacks action = (SingletonLayeredCallbacks) singletonEntry.getValue().traitMap().getTrait(SingletonTraitKind.LAYERED_CALLBACKS).get().metadata(); var flags = action.doPersist(writer, singleton); boolean persistData = flags == LayeredImageSingleton.PersistFlags.CREATE; + if (initialLayerOnly) { + VMError.guarantee(flags == LayeredImageSingleton.PersistFlags.FORBIDDEN, "InitialLayer Singleton's persist action must return %s %s", LayeredImageSingleton.PersistFlags.FORBIDDEN, + singleton); + } int id = -1; RecreateInfo recreateInfo = null; EconomicMap keyValueStore = null; @@ -1152,11 +1151,12 @@ public void writeImageSingletonInfo(List, ImageSingletonsSupp sb.setObjectId(info.id); sb.setPersistFlag(info.flags.ordinal()); int constantId = -1; - if (singleton instanceof InitialLayerOnlyImageSingleton initialLayerOnlyImageSingleton && initialLayerOnlyImageSingleton.accessibleInFutureLayers()) { - constantId = initialLayerOnlySingletonMap.getOrDefault(initialLayerOnlyImageSingleton, -1); + if (initialLayerOnly) { + ImageHeapConstant imageHeapConstant = (ImageHeapConstant) aUniverse.getSnippetReflection().forObject(singleton); + constantId = ImageHeapConstant.getConstantID(imageHeapConstant); } sb.setConstantId(constantId); - sb.setIsInitialLayerOnly(singleton instanceof InitialLayerOnlyImageSingleton); + sb.setIsInitialLayerOnly(initialLayerOnly); } var sortedByIDs = singletonPersistInfoMap.entrySet().stream() 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 8fe8e1024e89..7c9deb975da5 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 @@ -1168,14 +1168,19 @@ protected static long longValue(GraphBuilderContext b, ResolvedJavaMethod target } private static void registerVMConfigurationPlugins(InvocationPlugins plugins) { + // captured values to reduce the number of dynamic singleton lookups + boolean imageLayer = ImageLayerBuildingSupport.buildingImageLayer(); + boolean sharedLayer = ImageLayerBuildingSupport.buildingSharedLayer(); + boolean extensionLayer = ImageLayerBuildingSupport.buildingExtensionLayer(); + LayeredImageSingletonSupport layeredSingletonSupport = LayeredImageSingletonSupport.singleton(); + Registration r = new Registration(plugins, ImageSingletons.class); r.register(new RequiredInvocationPlugin("contains", Class.class) { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unused, ValueNode classNode) { Class key = constantObjectParameter(b, targetMethod, 0, Class.class, classNode); boolean result = ImageSingletons.contains(key); - if (!result && ImageLayerBuildingSupport.buildingImageLayer()) { - // GR-66793 add detection for initial layer only image singleton + if (!result && imageLayer) { if (ApplicationLayerOnlyImageSingleton.isAssignableFrom(key) || MultiLayeredImageSingleton.class.isAssignableFrom(key)) { /* * ApplicationLayerOnlyImageSingletons and the array representation of a @@ -1185,6 +1190,12 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec * created in the application layer or produce a buildtime error. */ result = true; + } else if (extensionLayer) { + /* + * Initial layer only image singletons are installed in the initial layer, + * but can be accessed from all extension layers. + */ + result = layeredSingletonSupport.isInitialLayerOnlyImageSingleton(key); } } b.addPush(JavaKind.Boolean, ConstantNode.forBoolean(result)); @@ -1196,10 +1207,9 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unused, ValueNode classNode) { Class key = constantObjectParameter(b, targetMethod, 0, Class.class, classNode); - var layeredSingletonSupport = LayeredImageSingletonSupport.singleton(); - if (ImageLayerBuildingSupport.buildingImageLayer()) { + if (imageLayer) { if (ApplicationLayerOnlyImageSingleton.isAssignableFrom(key) && - ImageLayerBuildingSupport.buildingSharedLayer()) { + sharedLayer) { /* * This singleton is only installed in the application layer heap. All other * layers looks refer to this singleton. @@ -1208,7 +1218,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec return true; } - if (ImageLayerBuildingSupport.buildingExtensionLayer() && layeredSingletonSupport.isInitialLayerOnlyImageSingleton(key)) { + if (extensionLayer && layeredSingletonSupport.isInitialLayerOnlyImageSingleton(key)) { /* * This singleton is only installed in the initial layer heap. When allowed, * all other layers lookups refer to this singleton. diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/HostedJavaThreadsFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/HostedJavaThreadsFeature.java index d04e7f22360c..7b2278e5aeee 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/HostedJavaThreadsFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/HostedJavaThreadsFeature.java @@ -41,10 +41,10 @@ import com.oracle.svm.core.thread.JavaThreads; import com.oracle.svm.core.thread.JavaThreadsFeature; import com.oracle.svm.core.thread.PlatformThreads; -import com.oracle.svm.core.traits.BuiltinTraits; +import com.oracle.svm.core.traits.BuiltinTraits.BuildtimeAccessOnly; import com.oracle.svm.core.traits.SingletonLayeredCallbacks; import com.oracle.svm.core.traits.SingletonLayeredCallbacksSupplier; -import com.oracle.svm.core.traits.SingletonLayeredInstallationKind; +import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.Independent; import com.oracle.svm.core.traits.SingletonTrait; import com.oracle.svm.core.traits.SingletonTraitKind; import com.oracle.svm.core.traits.SingletonTraits; @@ -246,7 +246,7 @@ synchronized void add(ThreadGroup g) { } @AutomaticallyRegisteredImageSingleton -@SingletonTraits(access = BuiltinTraits.BuildtimeAccessOnly.class, layeredCallbacks = HostedJavaThreadsMetadata.LayeredCallbacks.class, layeredInstallationKind = SingletonLayeredInstallationKind.Independent.class) +@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = HostedJavaThreadsMetadata.LayeredCallbacks.class, layeredInstallationKind = Independent.class) class HostedJavaThreadsMetadata { long maxThreadId; int maxAutonumber;