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 456a8916be3d..de67717bcd26 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,6 +24,8 @@ */ 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; @@ -31,11 +33,13 @@ 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 jdk.graal.compiler.nodes.NamedLocationIdentity; /** Support for pinning objects to a memory address with {@link PinnedObject}. */ -public final class PinnedObjectSupportImpl extends AbstractPinnedObjectSupport { +public final class PinnedObjectSupportImpl extends AbstractPinnedObjectSupport implements InitialLayerOnlyImageSingleton { @Platforms(Platform.HOSTED_ONLY.class) public PinnedObjectSupportImpl() { } @@ -62,4 +66,14 @@ 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.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeGCFeature.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeGCFeature.java index b96a7087aad9..0ad525eaf17f 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeGCFeature.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeGCFeature.java @@ -28,7 +28,6 @@ import java.util.List; import java.util.Map; -import com.oracle.svm.core.jdk.SystemPropertiesSupport; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.hosted.Feature; import org.graalvm.nativeimage.impl.PinnedObjectSupport; @@ -60,7 +59,9 @@ import com.oracle.svm.core.heap.BarrierSetProvider; import com.oracle.svm.core.heap.Heap; import com.oracle.svm.core.image.ImageHeapLayouter; +import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; import com.oracle.svm.core.jdk.RuntimeSupportFeature; +import com.oracle.svm.core.jdk.SystemPropertiesSupport; import com.oracle.svm.core.jvmstat.PerfDataFeature; import com.oracle.svm.core.jvmstat.PerfDataHolder; import com.oracle.svm.core.jvmstat.PerfManager; @@ -100,7 +101,9 @@ public void duringSetup(DuringSetupAccess access) { ImageSingletons.add(Heap.class, new HeapImpl()); ImageSingletons.add(ImageHeapInfo.class, new ImageHeapInfo()); ImageSingletons.add(GCAllocationSupport.class, new GenScavengeAllocationSupport()); - ImageSingletons.add(PinnedObjectSupport.class, new PinnedObjectSupportImpl()); + if (ImageLayerBuildingSupport.firstImageBuild()) { + ImageSingletons.add(PinnedObjectSupport.class, new PinnedObjectSupportImpl()); + } if (ImageSingletons.contains(PerfManager.class)) { ImageSingletons.lookup(PerfManager.class).register(createPerfData()); 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 538464f404ed..306919685743 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,27 +25,33 @@ 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; import com.oracle.svm.core.SubstrateDiagnostics; +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.log.Log; import com.oracle.svm.core.thread.VMThreads; -import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; @AutomaticallyRegisteredFeature class PosixLogHandlerFeature implements InternalFeature { @Override public void beforeAnalysis(BeforeAnalysisAccess access) { - Log.finalizeDefaultLogHandler(new PosixLogHandler()); + if (ImageLayerBuildingSupport.firstImageBuild()) { + Log.finalizeDefaultLogHandler(new PosixLogHandler()); + } } } -public class PosixLogHandler implements LogHandler { +public class PosixLogHandler implements LogHandler, InitialLayerOnlyImageSingleton { @Override public void log(CCharPointer bytes, UnsignedWord length) { @@ -88,4 +94,14 @@ 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/linux/LinuxPhysicalMemorySupportImpl.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxPhysicalMemorySupportImpl.java index b776fa262c78..8b32b9257bd0 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxPhysicalMemorySupportImpl.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxPhysicalMemorySupportImpl.java @@ -31,7 +31,6 @@ import java.util.ArrayList; import java.util.List; -import jdk.graal.compiler.word.Word; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.word.UnsignedWord; @@ -40,9 +39,12 @@ import com.oracle.svm.core.feature.InternalFeature; import com.oracle.svm.core.heap.PhysicalMemory; import com.oracle.svm.core.heap.PhysicalMemory.PhysicalMemorySupport; +import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; import com.oracle.svm.core.posix.headers.Unistd; import com.oracle.svm.core.util.VMError; +import jdk.graal.compiler.word.Word; + public class LinuxPhysicalMemorySupportImpl implements PhysicalMemorySupport { private static final long K = 1024; @@ -121,7 +123,7 @@ private static long parseFirstNumber(String str) { class LinuxPhysicalMemorySupportFeature implements InternalFeature { @Override public void beforeAnalysis(BeforeAnalysisAccess access) { - if (!ImageSingletons.contains(PhysicalMemorySupport.class)) { + if (ImageLayerBuildingSupport.firstImageBuild() && !ImageSingletons.contains(PhysicalMemorySupport.class)) { ImageSingletons.add(PhysicalMemorySupport.class, new LinuxPhysicalMemorySupportImpl()); } } 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 bd1a005e7049..71aa74aa26f4 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,17 +24,31 @@ */ package com.oracle.svm.core.posix.linux; +import java.util.EnumSet; + import org.graalvm.nativeimage.impl.ProcessPropertiesSupport; -import com.oracle.svm.core.posix.PosixProcessPropertiesSupport; 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; @AutomaticallyRegisteredImageSingleton(ProcessPropertiesSupport.class) -public class LinuxProcessPropertiesSupport extends PosixProcessPropertiesSupport { +public class LinuxProcessPropertiesSupport extends PosixProcessPropertiesSupport implements InitialLayerOnlyImageSingleton { @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/src/com/oracle/svm/core/c/CTypeConversionSupportImpl.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/CTypeConversionSupportImpl.java index 28444296e3a9..c5bda02ccb28 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,8 +28,8 @@ import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.Arrays; +import java.util.EnumSet; -import jdk.graal.compiler.word.Word; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.c.type.CCharPointer; import org.graalvm.nativeimage.c.type.CCharPointerPointer; @@ -45,9 +45,13 @@ 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 jdk.graal.compiler.word.Word; @AutomaticallyRegisteredImageSingleton(CTypeConversionSupport.class) -class CTypeConversionSupportImpl implements CTypeConversionSupport { +class CTypeConversionSupportImpl implements CTypeConversionSupport, InitialLayerOnlyImageSingleton { static final CCharPointerHolder NULL_HOLDER = new CCharPointerHolder() { @Override @@ -189,6 +193,16 @@ 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 fb88cfbd710c..aeda7278340b 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,9 +24,9 @@ */ package com.oracle.svm.core.c.function; +import java.util.EnumSet; import java.util.List; -import jdk.graal.compiler.word.Word; import org.graalvm.nativeimage.Isolate; import org.graalvm.nativeimage.IsolateThread; import org.graalvm.nativeimage.Isolates.CreateIsolateParameters; @@ -41,14 +41,18 @@ 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 jdk.graal.compiler.word.Word; + @AutomaticallyRegisteredImageSingleton(IsolateSupport.class) -public final class IsolateSupportImpl implements IsolateSupport { +public final class IsolateSupportImpl implements IsolateSupport, InitialLayerOnlyImageSingleton { 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"; @@ -167,4 +171,14 @@ 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 4b0bfb68c827..3a1e18bb0a36 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,13 +24,17 @@ */ 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; @AutomaticallyRegisteredImageSingleton(ObjectHandlesSupport.class) -class ObjectHandlesSupportImpl implements ObjectHandlesSupport { +class ObjectHandlesSupportImpl implements ObjectHandlesSupport, InitialLayerOnlyImageSingleton { final ObjectHandlesImpl globalHandles = new ObjectHandlesImpl(); @Override @@ -42,4 +46,19 @@ 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/PhysicalMemory.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/PhysicalMemory.java index 69afe73a2299..95398213ea71 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,8 +25,8 @@ package com.oracle.svm.core.heap; import java.lang.management.ManagementFactory; +import java.util.EnumSet; -import jdk.graal.compiler.word.Word; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.word.UnsignedWord; @@ -36,18 +36,21 @@ 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.RuntimeOnlyImageSingleton; +import com.oracle.svm.core.layeredimagesingleton.InitialLayerOnlyImageSingleton; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.core.util.UnsignedUtils; import com.oracle.svm.core.util.VMError; import com.sun.management.OperatingSystemMXBean; +import jdk.graal.compiler.word.Word; + /** * Contains static methods to get configuration of physical memory. */ public class PhysicalMemory { /** Implemented by operating-system specific code. */ - public interface PhysicalMemorySupport extends RuntimeOnlyImageSingleton { + public interface PhysicalMemorySupport extends InitialLayerOnlyImageSingleton { /** Get the size of physical memory from the OS. */ UnsignedWord size(); @@ -62,6 +65,11 @@ public interface PhysicalMemorySupport extends RuntimeOnlyImageSingleton { 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/layeredimagesingleton/RuntimeOnlyImageSingleton.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/DuplicableImageSingleton.java similarity index 53% rename from substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/RuntimeOnlyImageSingleton.java rename to substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/DuplicableImageSingleton.java index dd477d96f28f..6da620076eef 100644 --- 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/DuplicableImageSingleton.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, 2025, 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 @@ -24,17 +24,19 @@ */ package com.oracle.svm.core.layeredimagesingleton; -import java.util.EnumSet; - -public interface RuntimeOnlyImageSingleton extends LayeredImageSingleton { - - @Override - default EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.RUNTIME_ACCESS_ONLY; - } - - @Override - default PersistFlags preparePersist(ImageSingletonWriter writer) { - return PersistFlags.NOTHING; - } +/** + * A Duplicable ImageSingleton can have multiple instances of the object installed in the Image Heap + * (at most one per a layer). The specific instance referred to from a given piece of code is + * dependent on the layer in which the code was installed in. + * + * It is expected that either the installed objects (1) have no instance fields or (2) have instance + * fields which have been made layer-aware through other means (e.g. using a layered ImageHeapMap). + * + * Note this is a temporary marker and eventually all instances of {@link DuplicableImageSingleton}s + * should be removed. This marker should only be used when there is not a correctness issue with + * installing multiple instances of the singleton. Instead, the marker indicates there is merely a + * performance/memory overhead due to having multiple copies of this singleton installed (via + * different layers) within the image heap. + */ +public interface DuplicableImageSingleton extends LayeredImageSingleton { } 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 b8500f885d41..a767c40f7875 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,6 +24,8 @@ */ 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; @@ -39,12 +41,14 @@ 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; /** * 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 { +public class FunctionPointerLogHandler implements LogHandlerExtension, InitialLayerOnlyImageSingleton { 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"); @@ -192,4 +196,14 @@ 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/option/RuntimeOptionParser.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/RuntimeOptionParser.java index 72629722813d..df99572d13f0 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/RuntimeOptionParser.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/RuntimeOptionParser.java @@ -25,6 +25,7 @@ package com.oracle.svm.core.option; import java.util.Arrays; +import java.util.EnumSet; import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Predicate; @@ -39,6 +40,9 @@ import com.oracle.svm.core.IsolateArgumentParser; import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.graal.RuntimeCompilation; +import com.oracle.svm.core.layeredimagesingleton.DuplicableImageSingleton; +import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.core.log.Log; import com.oracle.svm.core.properties.RuntimeSystemPropertyParser; import com.oracle.svm.core.util.ImageHeapMap; @@ -55,7 +59,7 @@ * There is no requirement to use this class, you can also implement your own option parsing and * then set the values of options manually. */ -public final class RuntimeOptionParser { +public final class RuntimeOptionParser implements DuplicableImageSingleton { /** * The suggested prefix for all VM options available in an application based on Substrate VM. @@ -220,4 +224,14 @@ public void parseOptionAtRuntime(String arg, String optionPrefix, BooleanOptionF public Iterable getDescriptors() { return options.getValues(); } + + @Override + public EnumSet getImageBuilderFlags() { + return LayeredImageSingletonBuilderFlags.ALL_ACCESS; + } + + @Override + public PersistFlags preparePersist(ImageSingletonWriter writer) { + return PersistFlags.NOTHING; + } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/proxy/DynamicProxySupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/proxy/DynamicProxySupport.java index 75ff23639307..e03f04449681 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/proxy/DynamicProxySupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/proxy/DynamicProxySupport.java @@ -27,6 +27,7 @@ import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import java.util.Arrays; +import java.util.EnumSet; import java.util.regex.Pattern; import org.graalvm.collections.EconomicMap; @@ -42,6 +43,9 @@ import com.oracle.svm.core.hub.PredefinedClassesSupport; import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; import com.oracle.svm.core.jdk.proxy.DynamicProxyRegistry; +import com.oracle.svm.core.layeredimagesingleton.DuplicableImageSingleton; +import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.core.reflect.MissingReflectionRegistrationUtils; import com.oracle.svm.core.util.ImageHeapMap; import com.oracle.svm.core.util.VMError; @@ -51,7 +55,7 @@ import jdk.graal.compiler.debug.GraalError; -public class DynamicProxySupport implements DynamicProxyRegistry { +public class DynamicProxySupport implements DynamicProxyRegistry, DuplicableImageSingleton { public static final Pattern PROXY_CLASS_NAME_PATTERN = Pattern.compile(".*\\$Proxy[0-9]+"); @@ -244,4 +248,14 @@ private static void describeLoaderChain(StringBuilder b, ClassLoader loader) { public static String proxyTypeDescriptor(String... interfaceNames) { return "Proxy[" + String.join(", ", interfaceNames) + "]"; } + + @Override + public EnumSet getImageBuilderFlags() { + return LayeredImageSingletonBuilderFlags.ALL_ACCESS; + } + + @Override + public PersistFlags preparePersist(ImageSingletonWriter writer) { + return PersistFlags.NOTHING; + } } 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 61f1a7d58069..a3f090dc5b40 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 @@ -26,6 +26,8 @@ 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; @@ -46,9 +48,12 @@ import com.oracle.svm.core.feature.InternalFeature; import com.oracle.svm.core.heap.Heap; import com.oracle.svm.core.heap.VMOperationInfos; +import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; 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.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; @@ -78,7 +83,7 @@ /** * Utility methods for the manipulation and iteration of {@link IsolateThread}s. */ -public abstract class VMThreads implements RuntimeOnlyImageSingleton { +public abstract class VMThreads implements InitialLayerOnlyImageSingleton { @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public static VMThreads singleton() { @@ -671,6 +676,11 @@ 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)); @@ -1054,7 +1064,7 @@ public interface OSThreadHandle extends PointerBase { public interface OSThreadId extends PointerBase { } - public static class ThreadLookup { + public static class ThreadLookup implements InitialLayerOnlyImageSingleton { @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public ComparableWord getThreadIdentifier() { return VMThreads.singleton().getCurrentOSThreadId(); @@ -1064,14 +1074,19 @@ 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; + } } } @AutomaticallyRegisteredFeature -class ThreadLookupFeature implements InternalFeature { +class ThreadLookupFeature implements InternalFeature, FeatureSingleton { @Override public void beforeAnalysis(BeforeAnalysisAccess access) { - if (!ImageSingletons.contains(VMThreads.ThreadLookup.class)) { + if (ImageLayerBuildingSupport.firstImageBuild() && !ImageSingletons.contains(VMThreads.ThreadLookup.class)) { ImageSingletons.add(VMThreads.ThreadLookup.class, new VMThreads.ThreadLookup()); } } 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 dd8b57146a21..6700ea038e4a 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 @@ -185,8 +185,15 @@ public static void clear() { singletonDuringImageBuild = null; } + private static Object stripRuntimeWrapper(Object singleton) { + if (singleton instanceof RuntimeOnlyWrapper r) { + return r.wrappedObject(); + } + return singleton; + } + public static void persist() { - var list = singletonDuringImageBuild.configObjects.entrySet().stream().filter(e -> e.getValue() instanceof LayeredImageSingleton || e.getValue() instanceof RuntimeOnlyWrapper) + var list = singletonDuringImageBuild.configObjects.entrySet().stream().filter(e -> stripRuntimeWrapper(e.getValue()) instanceof LayeredImageSingleton) .sorted(Comparator.comparing(e -> e.getKey().getName())) .toList(); HostedImageLayerBuildingSupport.singleton().getWriter().writeImageSingletonInfo(list); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/SubstrateAnnotationExtractor.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/SubstrateAnnotationExtractor.java index fcef1e995250..33c3f9765732 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/SubstrateAnnotationExtractor.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/SubstrateAnnotationExtractor.java @@ -36,6 +36,7 @@ import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; +import java.util.EnumSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -53,6 +54,9 @@ import com.oracle.graal.pointsto.meta.BaseLayerField; import com.oracle.graal.pointsto.meta.BaseLayerMethod; import com.oracle.graal.pointsto.meta.BaseLayerType; +import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.hosted.annotation.AnnotationMetadata.AnnotationExtractionError; import com.oracle.svm.util.ReflectionUtil; @@ -82,7 +86,7 @@ * never be used during Native Image generation because it initializes all annotation classes and * their dependencies. */ -public class SubstrateAnnotationExtractor implements AnnotationExtractor { +public class SubstrateAnnotationExtractor implements AnnotationExtractor, LayeredImageSingleton { private final Map, AnnotationValue[]> annotationCache = new ConcurrentHashMap<>(); private final Map declaredAnnotationCache = new ConcurrentHashMap<>(); private final Map parameterAnnotationCache = new ConcurrentHashMap<>(); @@ -473,4 +477,14 @@ private static AnnotatedElement findRoot(AnnotatedElement element) { throw new AnnotationExtractionError(element, e); } } + + @Override + public EnumSet getImageBuilderFlags() { + return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; + } + + @Override + public PersistFlags preparePersist(ImageSingletonWriter writer) { + return PersistFlags.NOTHING; + } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/CConstantValueSupportImpl.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/CConstantValueSupportImpl.java index e7412ebccbc9..c8af5b14fbfc 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/CConstantValueSupportImpl.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/CConstantValueSupportImpl.java @@ -25,6 +25,7 @@ package com.oracle.svm.hosted.c; import java.lang.annotation.Annotation; +import java.util.EnumSet; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -34,6 +35,9 @@ import org.graalvm.nativeimage.impl.CConstantValueSupport; import com.oracle.svm.core.c.enums.CEnumRuntimeData; +import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.c.info.ConstantInfo; import com.oracle.svm.hosted.c.info.EnumInfo; @@ -47,7 +51,7 @@ import jdk.vm.ci.meta.ResolvedJavaType; @Platforms(Platform.HOSTED_ONLY.class) -public final class CConstantValueSupportImpl implements CConstantValueSupport { +public final class CConstantValueSupportImpl implements CConstantValueSupport, LayeredImageSingleton { private final NativeLibraries nativeLibraries; private final MetaAccessProvider metaAccess; @@ -134,4 +138,14 @@ private ResolvedJavaMethod getAnnotatedMethod(Class declaringClass, String me } return method; } + + @Override + public EnumSet getImageBuilderFlags() { + return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; + } + + @Override + public PersistFlags preparePersist(ImageSingletonWriter writer) { + return PersistFlags.NOTHING; + } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jni/JNIAccessFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jni/JNIAccessFeature.java index 6db907d0b1b6..24ab5ff9f788 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jni/JNIAccessFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jni/JNIAccessFeature.java @@ -33,6 +33,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.EnumSet; import java.util.HashSet; import java.util.IdentityHashMap; import java.util.List; @@ -77,6 +78,9 @@ import com.oracle.svm.core.jni.access.JNIAccessibleMethodDescriptor; import com.oracle.svm.core.jni.access.JNINativeLinkage; import com.oracle.svm.core.jni.access.JNIReflectionDictionary; +import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.core.layeredimagesingleton.MultiLayeredImageSingleton; import com.oracle.svm.core.meta.MethodPointer; import com.oracle.svm.core.option.HostedOptionKey; @@ -219,7 +223,7 @@ public void afterRegistration(AfterRegistrationAccess arg) { } private final class JNIRuntimeAccessibilitySupportImpl extends ConditionalConfigurationRegistry - implements RuntimeJNIAccessSupport { + implements RuntimeJNIAccessSupport, LayeredImageSingleton { @Override public void register(ConfigurationCondition condition, boolean unsafeAllocated, Class clazz) { @@ -287,6 +291,16 @@ public void registerConstructorLookup(ConfigurationCondition condition, Class newNegativeMethodLookups.computeIfAbsent(declaringClass, (clazz) -> new HashSet<>()).add(Pair.create("", parameterTypes)); } } + + @Override + public EnumSet getImageBuilderFlags() { + return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; + } + + @Override + public PersistFlags preparePersist(ImageSingletonWriter writer) { + return PersistFlags.NOTHING; + } } @Override