diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ChunkedImageHeapLayouter.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ChunkedImageHeapLayouter.java
index dca318c675d3..106ad882e45b 100644
--- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ChunkedImageHeapLayouter.java
+++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ChunkedImageHeapLayouter.java
@@ -43,12 +43,17 @@
import com.oracle.svm.core.image.ImageHeapLayouter;
import com.oracle.svm.core.image.ImageHeapObject;
import com.oracle.svm.core.option.SubstrateOptionsParser;
+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.UserError;
import com.oracle.svm.core.util.VMError;
import com.oracle.svm.util.JVMCIReflectionUtil;
import jdk.graal.compiler.core.common.NumUtil;
+@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class)
public class ChunkedImageHeapLayouter implements ImageHeapLayouter {
/** A partition holding read-only objects. */
private static final int ALIGNED_READ_ONLY_REGULAR = 0;
diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/metaspace/MetaspaceImpl.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/metaspace/MetaspaceImpl.java
index 8beab67775a4..5213ff57bd5f 100644
--- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/metaspace/MetaspaceImpl.java
+++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/metaspace/MetaspaceImpl.java
@@ -45,6 +45,10 @@
import com.oracle.svm.core.log.Log;
import com.oracle.svm.core.metaspace.Metaspace;
import com.oracle.svm.core.thread.VMOperation;
+import com.oracle.svm.core.traits.BuiltinTraits.AllAccess;
+import com.oracle.svm.core.traits.BuiltinTraits.NoLayeredCallbacks;
+import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.Disallowed;
+import com.oracle.svm.core.traits.SingletonTraits;
import jdk.graal.compiler.api.replacements.Fold;
import jdk.graal.compiler.word.Word;
@@ -56,7 +60,11 @@
* {@link FirstObjectTable}, similar to the writable part of the image heap. The chunks are managed
* in a single "To"-{@link Space}, which ensures that the GC doesn't try to move or promote the
* objects.
+ *
+ * This singleton is not fully layer aware because the {@link MetaspaceImpl#space} should be either
+ * always relinked or properly duplicated for each layer.
*/
+@SingletonTraits(access = AllAccess.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Disallowed.class)
public class MetaspaceImpl implements Metaspace {
private final Space space = new Space("Metaspace", "M", true, getAge());
private final ChunkedMetaspaceMemory memory = new ChunkedMetaspaceMemory(space);
diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixLoadAverageSupport.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixLoadAverageSupport.java
index 797275fce703..67e49615fdc5 100644
--- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixLoadAverageSupport.java
+++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixLoadAverageSupport.java
@@ -24,12 +24,17 @@
*/
package com.oracle.svm.core.posix;
-import com.oracle.svm.core.jdk.LoadAverageSupport;
-import com.oracle.svm.core.posix.headers.Stdlib;
import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton;
import com.oracle.svm.core.handles.PrimitiveArrayView;
+import com.oracle.svm.core.jdk.LoadAverageSupport;
+import com.oracle.svm.core.posix.headers.Stdlib;
+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(LoadAverageSupport.class)
+@SingletonTraits(access = RuntimeAccessOnly.class, layeredCallbacks = SingleLayer.class, layeredInstallationKind = InitialLayerOnly.class)
class PosixLoadAverageSupport implements LoadAverageSupport {
@Override
public int getLoadAverage(double[] loadavg, int nelems) {
diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixRawFileOperationSupport.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixRawFileOperationSupport.java
index de750d606c2f..3957c9602005 100644
--- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixRawFileOperationSupport.java
+++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixRawFileOperationSupport.java
@@ -27,8 +27,6 @@
import java.io.File;
import java.nio.ByteOrder;
-import com.oracle.svm.core.jdk.SystemPropertiesSupport;
-import jdk.graal.compiler.word.Word;
import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
@@ -41,13 +39,21 @@
import com.oracle.svm.core.Uninterruptible;
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
import com.oracle.svm.core.feature.InternalFeature;
+import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport;
+import com.oracle.svm.core.jdk.SystemPropertiesSupport;
import com.oracle.svm.core.memory.UntrackedNullableNativeMemory;
import com.oracle.svm.core.os.AbstractRawFileOperationSupport;
import com.oracle.svm.core.os.AbstractRawFileOperationSupport.RawFileOperationSupportHolder;
import com.oracle.svm.core.posix.headers.Fcntl;
import com.oracle.svm.core.posix.headers.Unistd;
+import com.oracle.svm.core.traits.BuiltinTraits.BuildtimeAccessOnly;
+import com.oracle.svm.core.traits.BuiltinTraits.SingleLayer;
+import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.Independent;
+import com.oracle.svm.core.traits.SingletonTraits;
import com.oracle.svm.core.util.VMError;
+import jdk.graal.compiler.word.Word;
+
public class PosixRawFileOperationSupport extends AbstractRawFileOperationSupport {
@Platforms(Platform.HOSTED_ONLY.class)
public PosixRawFileOperationSupport(boolean useNativeByteOrder) {
@@ -200,8 +206,14 @@ private static int parseMode(FileAccessMode mode) {
}
}
+@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = SingleLayer.class, layeredInstallationKind = Independent.class)
@AutomaticallyRegisteredFeature
class PosixRawFileOperationFeature implements InternalFeature {
+ @Override
+ public boolean isInConfiguration(IsInConfigurationAccess access) {
+ return ImageLayerBuildingSupport.firstImageBuild();
+ }
+
@Override
public void afterRegistration(AfterRegistrationAccess access) {
ByteOrder nativeByteOrder = ByteOrder.nativeOrder();
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/CPUFeatureAccessImpl.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/CPUFeatureAccessImpl.java
index 70226c74f38b..c2565e644fc8 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/CPUFeatureAccessImpl.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/CPUFeatureAccessImpl.java
@@ -24,10 +24,11 @@
*/
package com.oracle.svm.core;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;
-import jdk.graal.compiler.debug.GraalError;
import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
@@ -36,8 +37,17 @@
import com.oracle.svm.core.c.CGlobalData;
import com.oracle.svm.core.c.CGlobalDataFactory;
+import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader;
+import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter;
+import com.oracle.svm.core.layeredimagesingleton.LayeredPersistFlags;
+import com.oracle.svm.core.traits.SingletonLayeredCallbacks;
+import com.oracle.svm.core.traits.SingletonLayeredCallbacksSupplier;
+import com.oracle.svm.core.traits.SingletonTrait;
+import com.oracle.svm.core.traits.SingletonTraitKind;
import com.oracle.svm.core.util.VMError;
+import jdk.graal.compiler.debug.GraalError;
+
public abstract class CPUFeatureAccessImpl implements CPUFeatureAccess {
private final EnumSet> buildtimeCPUFeatures;
@@ -118,4 +128,52 @@ protected boolean isFeaturePresent(Enum> feature, Pointer cpuFeatures, List() {
+ @Override
+ public LayeredPersistFlags doPersist(ImageSingletonWriter writer, CPUFeatureAccessImpl singleton) {
+ writer.writeStringList(BUILDTIME_CPU_FEATURES, getCPUFeaturesList(singleton));
+ writer.writeString(CPU_FEATURE_ERROR_MESSAGE, new String(singleton.cpuFeatureErrorMessage, StandardCharsets.ISO_8859_1));
+ writer.writeString(BUILDTIME_FEATURE_MASK, new String(singleton.buildtimeFeatureMask, StandardCharsets.ISO_8859_1));
+ writer.writeIntList(CPU_FEATURE_ENUM_TO_STRUCT_OFFSETS, Arrays.stream(singleton.cpuFeatureEnumToStructOffsets).boxed().toList());
+ return LayeredPersistFlags.CALLBACK_ON_REGISTRATION;
+ }
+
+ @Override
+ public void onSingletonRegistration(ImageSingletonLoader loader, CPUFeatureAccessImpl singleton) {
+ List previousLayerBuildtimeCPUFeatures = loader.readStringList(BUILDTIME_CPU_FEATURES);
+ List currentLayerBuildtimeCPUFeatures = getCPUFeaturesList(singleton);
+ VMError.guarantee(previousLayerBuildtimeCPUFeatures.equals(currentLayerBuildtimeCPUFeatures),
+ "The buildtime CPU Features should be consistent across layers. The previous layer CPU Features were %s, but the current layer are %s",
+ previousLayerBuildtimeCPUFeatures, currentLayerBuildtimeCPUFeatures);
+
+ byte[] previousLayerCpuFeatureErrorMessage = loader.readString(CPU_FEATURE_ERROR_MESSAGE).getBytes(StandardCharsets.ISO_8859_1);
+ VMError.guarantee(Arrays.equals(singleton.cpuFeatureErrorMessage, previousLayerCpuFeatureErrorMessage), "Previous layer CPU Feature error message was %s, but current layer is %s",
+ Arrays.toString(previousLayerCpuFeatureErrorMessage), Arrays.toString(singleton.cpuFeatureErrorMessage));
+
+ byte[] previousLayerBuildtimeFeatureMask = loader.readString(BUILDTIME_FEATURE_MASK).getBytes(StandardCharsets.ISO_8859_1);
+ VMError.guarantee(Arrays.equals(singleton.buildtimeFeatureMask, previousLayerBuildtimeFeatureMask), "Previous layer buildtime Feature mask was %s, but current layer is %s",
+ Arrays.toString(previousLayerBuildtimeFeatureMask), Arrays.toString(singleton.buildtimeFeatureMask));
+
+ int[] previousLayerCpuFeatureEnumToStructOffsets = loader.readIntList(CPU_FEATURE_ENUM_TO_STRUCT_OFFSETS).stream().mapToInt(Integer::intValue).toArray();
+ VMError.guarantee(Arrays.equals(singleton.cpuFeatureEnumToStructOffsets, previousLayerCpuFeatureEnumToStructOffsets),
+ "Previous CPU Feature enum to struct offsets was %s, but current layer is %s",
+ Arrays.toString(previousLayerCpuFeatureEnumToStructOffsets), Arrays.toString(singleton.cpuFeatureEnumToStructOffsets));
+ }
+ };
+ return new SingletonTrait(SingletonTraitKind.LAYERED_CALLBACKS, action);
+ }
+
+ private static List getCPUFeaturesList(CPUFeatureAccessImpl cpuFeatureAccess) {
+ return cpuFeatureAccess.buildtimeCPUFeatures.stream().map(Enum::toString).toList();
+ }
+ }
}
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/IsolateArgumentParser.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/IsolateArgumentParser.java
index 5fbb27a1b13b..f46d88cb3e7c 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/IsolateArgumentParser.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/IsolateArgumentParser.java
@@ -658,7 +658,7 @@ public static boolean isNumeric(byte optionValueType) {
*/
@Platforms(Platform.HOSTED_ONLY.class)
@AutomaticallyRegisteredImageSingleton(onlyWith = BuildingImageLayerPredicate.class)
- @SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = LayeredCallbacks.class, layeredInstallationKind = Independent.class)
+ @SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = LayeredOptionInfo.LayeredCallbacks.class, layeredInstallationKind = Independent.class)
static class LayeredOptionInfo {
private static final int UNSET = -1;
final int numOptions;
@@ -688,30 +688,30 @@ List getOptionNames() {
Objects.requireNonNull(optionNames);
return optionNames;
}
- }
- static class LayeredCallbacks extends SingletonLayeredCallbacksSupplier {
+ static class LayeredCallbacks extends SingletonLayeredCallbacksSupplier {
- @Override
- public SingletonTrait getLayeredCallbacksTrait() {
- return new SingletonTrait(SingletonTraitKind.LAYERED_CALLBACKS, new SingletonLayeredCallbacks() {
- @Override
- public LayeredPersistFlags doPersist(ImageSingletonWriter writer, LayeredOptionInfo singleton) {
- if (ImageLayerBuildingSupport.firstImageBuild()) {
- writer.writeInt("numOptions", IsolateArgumentParser.getOptionCount());
- writer.writeStringList("optionNames", IsolateArgumentParser.getOptions().stream().map(OptionKey::getName).toList());
- } else {
- writer.writeInt("numOptions", singleton.getNumOptions());
- writer.writeStringList("optionNames", singleton.optionNames);
+ @Override
+ public SingletonTrait getLayeredCallbacksTrait() {
+ return new SingletonTrait(SingletonTraitKind.LAYERED_CALLBACKS, new SingletonLayeredCallbacks() {
+ @Override
+ public LayeredPersistFlags doPersist(ImageSingletonWriter writer, LayeredOptionInfo singleton) {
+ if (ImageLayerBuildingSupport.firstImageBuild()) {
+ writer.writeInt("numOptions", IsolateArgumentParser.getOptionCount());
+ writer.writeStringList("optionNames", IsolateArgumentParser.getOptions().stream().map(OptionKey::getName).toList());
+ } else {
+ writer.writeInt("numOptions", singleton.getNumOptions());
+ writer.writeStringList("optionNames", singleton.optionNames);
+ }
+ return LayeredPersistFlags.CREATE;
}
- return LayeredPersistFlags.CREATE;
- }
- @Override
- public Class extends SingletonLayeredCallbacks.LayeredSingletonInstantiator>> getSingletonInstantiator() {
- return SingletonInstantiator.class;
- }
- });
+ @Override
+ public Class extends SingletonLayeredCallbacks.LayeredSingletonInstantiator>> getSingletonInstantiator() {
+ return SingletonInstantiator.class;
+ }
+ });
+ }
}
}
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java
index 55e2b8e26661..104ade834f48 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java
@@ -651,6 +651,7 @@ public static int maxJavaStackTraceDepth() {
@Option(help = "Force no direct relocations to be present in the text section of the generated image", type = OptionType.Debug) //
public static final HostedOptionKey NoDirectRelocationsInText = new HostedOptionKey<>(true);
+ @LayerVerifiedOption(kind = Kind.Changed, severity = Severity.Error)//
@Option(help = "Support multiple isolates.", deprecated = true, deprecationMessage = "This option disables a major feature of GraalVM Native Image and will be removed in a future release") //
public static final HostedOptionKey SpawnIsolates = new HostedOptionKey<>(true);
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/aarch64/AArch64CPUFeatureAccess.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/aarch64/AArch64CPUFeatureAccess.java
index ee08917b9475..9fc5b16a1ed9 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/aarch64/AArch64CPUFeatureAccess.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/aarch64/AArch64CPUFeatureAccess.java
@@ -36,12 +36,17 @@
import com.oracle.svm.core.Uninterruptible;
import com.oracle.svm.core.UnmanagedMemoryUtil;
import com.oracle.svm.core.graal.stackvalue.UnsafeStackValue;
+import com.oracle.svm.core.traits.BuiltinTraits.AllAccess;
+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.VMError;
import jdk.graal.compiler.nodes.spi.LoweringProvider;
import jdk.vm.ci.aarch64.AArch64;
import jdk.vm.ci.code.Architecture;
+@SingletonTraits(access = AllAccess.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Disallowed.class)
public class AArch64CPUFeatureAccess extends CPUFeatureAccessImpl {
@Platforms(Platform.HOSTED_ONLY.class)
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/amd64/AMD64CPUFeatureAccess.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/amd64/AMD64CPUFeatureAccess.java
index f8b691760b23..493f2c95dc36 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/amd64/AMD64CPUFeatureAccess.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/amd64/AMD64CPUFeatureAccess.java
@@ -39,6 +39,11 @@
import com.oracle.svm.core.UnmanagedMemoryUtil;
import com.oracle.svm.core.graal.stackvalue.UnsafeStackValue;
import com.oracle.svm.core.jdk.JVMCISubstitutions;
+import com.oracle.svm.core.traits.BuiltinTraits.AllAccess;
+import com.oracle.svm.core.traits.BuiltinTraits.Duplicable;
+import com.oracle.svm.core.traits.BuiltinTraits.PartiallyLayerAware;
+import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.Independent;
+import com.oracle.svm.core.traits.SingletonTraits;
import com.oracle.svm.core.util.VMError;
import jdk.graal.compiler.nodes.spi.LoweringProvider;
@@ -48,6 +53,13 @@
import jdk.vm.ci.amd64.AMD64Kind;
import jdk.vm.ci.code.Architecture;
+/**
+ * This singleton should be converted to a multi layer singleton or an application layer only
+ * singleton. It is currently too strict, as different CPUFeatures are allowed in different layers,
+ * but at runtime, all the CPUFeatures used during all builds need to be supported.
+ */
+@SingletonTraits(access = AllAccess.class, layeredCallbacks = CPUFeatureAccessImpl.LayeredCallbacks.class, layeredInstallationKind = Independent.class, other = {Duplicable.class,
+ PartiallyLayerAware.class})
public class AMD64CPUFeatureAccess extends CPUFeatureAccessImpl {
@Platforms(Platform.HOSTED_ONLY.class)
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/locale/LocaleSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/locale/LocaleSupport.java
index 8954f084003c..2aa17a37ef08 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/locale/LocaleSupport.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/locale/LocaleSupport.java
@@ -36,7 +36,6 @@
import com.oracle.svm.core.Uninterruptible;
import com.oracle.svm.core.c.CGlobalData;
import com.oracle.svm.core.c.CGlobalDataFactory;
-import com.oracle.svm.core.c.locale.LocaleSupport.LayeredCallbacks;
import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton;
import com.oracle.svm.core.headers.LibC;
import com.oracle.svm.core.jdk.SystemPropertiesSupport;
@@ -72,7 +71,7 @@
* Note that the JavaDoc of {@link java.util.Locale} explains commonly used terms such as script,
* display, format, variant, and extensions.
*/
-@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = LayeredCallbacks.class, layeredInstallationKind = Independent.class)
+@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = LocaleSupport.LayeredCallbacks.class, layeredInstallationKind = Independent.class)
@AutomaticallyRegisteredImageSingleton
public class LocaleSupport {
private static final String LOCALE = "locale";
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/config/ObjectLayout.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/config/ObjectLayout.java
index caee168b36ad..d0deac23b20f 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/config/ObjectLayout.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/config/ObjectLayout.java
@@ -37,7 +37,6 @@
import com.oracle.svm.core.SubstrateTargetDescription;
import com.oracle.svm.core.Uninterruptible;
-import com.oracle.svm.core.config.ObjectLayout.LayeredCallbacks;
import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader;
import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter;
import com.oracle.svm.core.layeredimagesingleton.LayeredPersistFlags;
@@ -83,7 +82,7 @@
* See this classes instantiation sites (such as {@code HostedConfiguration#createObjectLayout}) for
* more details on the exact object layout for a given configuration.
*/
-@SingletonTraits(access = AllAccess.class, layeredCallbacks = LayeredCallbacks.class, layeredInstallationKind = Independent.class)
+@SingletonTraits(access = AllAccess.class, layeredCallbacks = ObjectLayout.LayeredCallbacks.class, layeredInstallationKind = Independent.class)
public final class ObjectLayout {
private final SubstrateTargetDescription target;
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/ReferenceAccessFeature.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/ReferenceAccessFeature.java
index c91dc4269ee3..6515a881bdc8 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/ReferenceAccessFeature.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/ReferenceAccessFeature.java
@@ -28,7 +28,12 @@
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
import com.oracle.svm.core.feature.InternalFeature;
+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;
+@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class)
@AutomaticallyRegisteredFeature
public class ReferenceAccessFeature implements InternalFeature {
@Override
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/ReferenceAccessImpl.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/ReferenceAccessImpl.java
index a1c4f1c4be95..3d27bf634a08 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/ReferenceAccessImpl.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/ReferenceAccessImpl.java
@@ -34,6 +34,10 @@
import com.oracle.svm.core.SubstrateOptions;
import com.oracle.svm.core.Uninterruptible;
import com.oracle.svm.core.config.ConfigurationValues;
+import com.oracle.svm.core.traits.BuiltinTraits.AllAccess;
+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.api.replacements.Fold;
import jdk.graal.compiler.core.common.CompressEncoding;
@@ -41,6 +45,7 @@
import jdk.graal.compiler.word.ObjectAccess;
import jdk.graal.compiler.word.Word;
+@SingletonTraits(access = AllAccess.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class)
public class ReferenceAccessImpl implements ReferenceAccess {
@Platforms(Platform.HOSTED_ONLY.class)
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/dump/HeapDumpSupportImpl.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/dump/HeapDumpSupportImpl.java
index 55d6992bda30..9a5300c1f18c 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/dump/HeapDumpSupportImpl.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/dump/HeapDumpSupportImpl.java
@@ -58,7 +58,6 @@
import com.oracle.svm.core.traits.SingletonTraits;
import com.oracle.svm.core.util.TimeUtils;
-import jdk.graal.compiler.api.replacements.Fold;
import jdk.graal.compiler.word.Word;
@SingletonTraits(access = AllAccess.class, layeredCallbacks = SingleLayer.class, layeredInstallationKind = InitialLayerOnly.class)
@@ -173,7 +172,6 @@ public void writeHeapTo(RawFileDescriptor fd, boolean gcBefore) throws IOExcepti
}
}
- @Fold
static RawFileOperationSupport getFileSupport() {
return RawFileOperationSupport.bigEndian();
}
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/dump/HeapDumpWriter.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/dump/HeapDumpWriter.java
index 1044df9d7df7..427639f66dc6 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/dump/HeapDumpWriter.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/dump/HeapDumpWriter.java
@@ -1152,7 +1152,6 @@ private void handleError(boolean success) {
}
}
- @Fold
static BufferedFileOperationSupport file() {
return BufferedFileOperationSupport.bigEndian();
}
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/ClassValueSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/ClassValueSupport.java
index aed7ab464c31..37912e5690e2 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/ClassValueSupport.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/ClassValueSupport.java
@@ -24,12 +24,24 @@
*/
package com.oracle.svm.core.jdk;
-import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton;
-import org.graalvm.nativeimage.ImageSingletons;
-
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import org.graalvm.nativeimage.ImageSingletons;
+
+import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton;
+import com.oracle.svm.core.traits.BuiltinTraits.BuildtimeAccessOnly;
+import com.oracle.svm.core.traits.BuiltinTraits.NoLayeredCallbacks;
+import com.oracle.svm.core.traits.BuiltinTraits.PartiallyLayerAware;
+import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.Independent;
+import com.oracle.svm.core.traits.SingletonTraits;
+
+/**
+ * The {@link ClassValueSupport#values} map would need to be repopulated in extension layer to
+ * ensure that the values returned are consistent across layers. However, class values should not
+ * change across layers, so this only results in some duplication.
+ */
+@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class, other = PartiallyLayerAware.class)
@AutomaticallyRegisteredImageSingleton
public final class ClassValueSupport {
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/RecomputedFields.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/RecomputedFields.java
index 721b4867c78e..e347d2a1d2fb 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/RecomputedFields.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/RecomputedFields.java
@@ -35,6 +35,10 @@
import java.nio.charset.CharsetDecoder;
import java.util.concurrent.ForkJoinPool;
+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 org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.nativeimage.impl.InternalPlatform;
@@ -189,6 +193,7 @@ final class Target_java_util_concurrent_atomic_AtomicLongFieldUpdater_CASUpdater
@AutomaticallyRegisteredFeature
@Platforms(InternalPlatform.NATIVE_ONLY.class)
+@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class)
class InnocuousForkJoinWorkerThreadFeature implements InternalFeature {
@Override
public void duringSetup(DuringSetupAccess access) {
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrChunkFileWriter.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrChunkFileWriter.java
index 85e807666fed..cd0faa30d0b8 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrChunkFileWriter.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrChunkFileWriter.java
@@ -24,6 +24,7 @@
*/
package com.oracle.svm.core.jfr;
+import static com.oracle.svm.core.Uninterruptible.CALLED_FROM_UNINTERRUPTIBLE_CODE;
import static com.oracle.svm.core.jfr.JfrThreadLocal.getJavaBufferList;
import static com.oracle.svm.core.jfr.JfrThreadLocal.getNativeBufferList;
@@ -52,7 +53,6 @@
import com.oracle.svm.core.thread.VMOperationControl;
import com.oracle.svm.core.thread.VMThreads;
-import jdk.graal.compiler.api.replacements.Fold;
import jdk.graal.compiler.core.common.NumUtil;
import jdk.graal.compiler.word.Word;
@@ -514,7 +514,7 @@ public void writeCompressedLong(long value) {
getFileSupport().writeByte(fd, (byte) (v >>> 7)); // 56-63, last byte as is.
}
- @Fold
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
static RawFileOperationSupport getFileSupport() {
return RawFileOperationSupport.bigEndian();
}
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/functions/JNIFunctionTables.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/functions/JNIFunctionTables.java
index eb12756017d6..c4dcf67a7fd3 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/functions/JNIFunctionTables.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/functions/JNIFunctionTables.java
@@ -44,6 +44,10 @@
import com.oracle.svm.core.jni.headers.JNIInvokeInterface;
import com.oracle.svm.core.jni.headers.JNIJavaVM;
import com.oracle.svm.core.jni.headers.JNINativeInterface;
+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.word.Word;
@@ -52,6 +56,7 @@
/**
* Performs the initialization of the JNI function table structures at runtime.
*/
+@SingletonTraits(access = AllAccess.class, layeredCallbacks = SingleLayer.class, layeredInstallationKind = InitialLayerOnly.class)
public final class JNIFunctionTables {
public static void create() {
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/metaspace/NoMetaspace.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/metaspace/NoMetaspace.java
index 3433bfe164e9..036b0b4f5c3a 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/metaspace/NoMetaspace.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/metaspace/NoMetaspace.java
@@ -31,8 +31,13 @@
import com.oracle.svm.core.Uninterruptible;
import com.oracle.svm.core.heap.ObjectVisitor;
import com.oracle.svm.core.hub.DynamicHub;
+import com.oracle.svm.core.traits.BuiltinTraits.AllAccess;
+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.VMError;
+@SingletonTraits(access = AllAccess.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class)
public final class NoMetaspace implements Metaspace {
@Override
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/HostedOptionValues.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/HostedOptionValues.java
index e8233649a677..27b0687d3759 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/HostedOptionValues.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/option/HostedOptionValues.java
@@ -25,15 +25,22 @@
package com.oracle.svm.core.option;
import org.graalvm.collections.EconomicMap;
+import org.graalvm.nativeimage.ImageSingletons;
+
+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.options.OptionKey;
import jdk.graal.compiler.options.OptionValues;
-import org.graalvm.nativeimage.ImageSingletons;
/**
* The singleton holder of hosted options.
*
* @see com.oracle.svm.core.option
*/
+@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class)
public class HostedOptionValues extends OptionValues {
public HostedOptionValues(EconomicMap, Object> values) {
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/AbstractRawFileOperationSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/AbstractRawFileOperationSupport.java
index e3434db566b3..1e8f00a62718 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/AbstractRawFileOperationSupport.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/AbstractRawFileOperationSupport.java
@@ -24,6 +24,8 @@
*/
package com.oracle.svm.core.os;
+import static com.oracle.svm.core.Uninterruptible.CALLED_FROM_UNINTERRUPTIBLE_CODE;
+
import java.io.File;
import org.graalvm.nativeimage.ImageSingletons;
@@ -37,8 +39,11 @@
import com.oracle.svm.core.hub.DynamicHub;
import com.oracle.svm.core.hub.LayoutEncoding;
import com.oracle.svm.core.snippets.KnownIntrinsics;
+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.api.replacements.Fold;
import jdk.graal.compiler.word.Word;
public abstract class AbstractRawFileOperationSupport implements RawFileOperationSupport {
@@ -69,13 +74,13 @@ public boolean write(RawFileDescriptor fd, byte[] data) {
}
@Override
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public boolean writeBoolean(RawFileDescriptor fd, boolean data) {
return writeByte(fd, (byte) (data ? 1 : 0));
}
@Override
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public boolean writeByte(RawFileDescriptor fd, byte data) {
int sizeInBytes = Byte.BYTES;
Pointer dataPtr = StackValue.get(sizeInBytes);
@@ -84,7 +89,7 @@ public boolean writeByte(RawFileDescriptor fd, byte data) {
}
@Override
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public boolean writeShort(RawFileDescriptor fd, short data) {
int sizeInBytes = Short.BYTES;
Pointer dataPtr = StackValue.get(sizeInBytes);
@@ -93,7 +98,7 @@ public boolean writeShort(RawFileDescriptor fd, short data) {
}
@Override
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public boolean writeChar(RawFileDescriptor fd, char data) {
int sizeInBytes = Character.BYTES;
Pointer dataPtr = StackValue.get(sizeInBytes);
@@ -102,7 +107,7 @@ public boolean writeChar(RawFileDescriptor fd, char data) {
}
@Override
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public boolean writeInt(RawFileDescriptor fd, int data) {
int sizeInBytes = Integer.BYTES;
Pointer dataPtr = StackValue.get(sizeInBytes);
@@ -111,7 +116,7 @@ public boolean writeInt(RawFileDescriptor fd, int data) {
}
@Override
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public boolean writeLong(RawFileDescriptor fd, long data) {
int sizeInBytes = Long.BYTES;
Pointer dataPtr = StackValue.get(sizeInBytes);
@@ -120,17 +125,18 @@ public boolean writeLong(RawFileDescriptor fd, long data) {
}
@Override
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public boolean writeFloat(RawFileDescriptor fd, float data) {
return writeInt(fd, Float.floatToIntBits(data));
}
@Override
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public boolean writeDouble(RawFileDescriptor fd, double data) {
return writeLong(fd, Double.doubleToLongBits(data));
}
+ @SingletonTraits(access = RuntimeAccessOnly.class, layeredCallbacks = SingleLayer.class, layeredInstallationKind = InitialLayerOnly.class)
public static class RawFileOperationSupportHolder {
private final RawFileOperationSupport littleEndian;
private final RawFileOperationSupport bigEndian;
@@ -143,22 +149,21 @@ public RawFileOperationSupportHolder(RawFileOperationSupport littleEndian, RawFi
this.nativeOrder = nativeOrder;
}
- @Fold
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
static RawFileOperationSupportHolder singleton() {
return ImageSingletons.lookup(RawFileOperationSupportHolder.class);
}
- @Fold
public static RawFileOperationSupport getLittleEndian() {
return singleton().littleEndian;
}
- @Fold
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public static RawFileOperationSupport getBigEndian() {
return singleton().bigEndian;
}
- @Fold
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public static RawFileOperationSupport getNativeByteOrder() {
return singleton().nativeOrder;
}
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/BufferedFileOperationSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/BufferedFileOperationSupport.java
index 1402ed1d63d0..99052dc2c490 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/BufferedFileOperationSupport.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/BufferedFileOperationSupport.java
@@ -24,6 +24,8 @@
*/
package com.oracle.svm.core.os;
+import static com.oracle.svm.core.Uninterruptible.CALLED_FROM_UNINTERRUPTIBLE_CODE;
+
import java.nio.ByteOrder;
import org.graalvm.nativeimage.ImageSingletons;
@@ -42,6 +44,7 @@
import com.oracle.svm.core.feature.InternalFeature;
import com.oracle.svm.core.hub.DynamicHub;
import com.oracle.svm.core.hub.LayoutEncoding;
+import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport;
import com.oracle.svm.core.jdk.UninterruptibleUtils;
import com.oracle.svm.core.jdk.UninterruptibleUtils.CharReplacer;
import com.oracle.svm.core.memory.NullableNativeMemory;
@@ -49,8 +52,13 @@
import com.oracle.svm.core.os.BufferedFileOperationSupport.BufferedFileOperationSupportHolder;
import com.oracle.svm.core.os.RawFileOperationSupport.RawFileDescriptor;
import com.oracle.svm.core.snippets.KnownIntrinsics;
+import com.oracle.svm.core.traits.BuiltinTraits.BuildtimeAccessOnly;
+import com.oracle.svm.core.traits.BuiltinTraits.RuntimeAccessOnly;
+import com.oracle.svm.core.traits.BuiltinTraits.SingleLayer;
+import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.Independent;
+import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.InitialLayerOnly;
+import com.oracle.svm.core.traits.SingletonTraits;
-import jdk.graal.compiler.api.replacements.Fold;
import jdk.graal.compiler.word.Word;
/**
@@ -61,7 +69,6 @@ public class BufferedFileOperationSupport {
/**
* Returns a {@link BufferedFileOperationSupport} singleton that uses little endian byte order.
*/
- @Fold
public static BufferedFileOperationSupport littleEndian() {
return BufferedFileOperationSupportHolder.singleton().littleEndian;
}
@@ -69,7 +76,6 @@ public static BufferedFileOperationSupport littleEndian() {
/**
* Returns a {@link BufferedFileOperationSupport} singleton that uses big endian byte order.
*/
- @Fold
public static BufferedFileOperationSupport bigEndian() {
return BufferedFileOperationSupportHolder.singleton().bigEndian;
}
@@ -78,7 +84,6 @@ public static BufferedFileOperationSupport bigEndian() {
* Returns a {@link BufferedFileOperationSupport} singleton that uses the native byte order of
* the underlying architecture.
*/
- @Fold
public static BufferedFileOperationSupport nativeByteOrder() {
return BufferedFileOperationSupportHolder.singleton().nativeOrder;
}
@@ -100,7 +105,7 @@ protected BufferedFileOperationSupport(boolean useNativeByteOrder) {
* {@link RawFileOperationSupport#isValid valid} and if the allocation was successful.
* Returns a null pointer otherwise.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public BufferedFile allocate(RawFileDescriptor fd, NmtCategory nmtCategory) {
if (!rawFiles().isValid(fd)) {
return Word.nullPointer();
@@ -127,7 +132,7 @@ public BufferedFile allocate(RawFileDescriptor fd, NmtCategory nmtCategory) {
* Free the {@link BufferedFile} and its corresponding buffer. Be aware that this operation does
* neither flush pending data nor close the underlying {@link RawFileDescriptor}.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public void free(BufferedFile f) {
NullableNativeMemory.free(f);
}
@@ -138,7 +143,7 @@ public void free(BufferedFile f) {
* @return true if the data was flushed successful or there was no pending data that needed
* flushing.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public boolean flush(BufferedFile f) {
int unflushed = getUnflushedDataSize(f);
if (unflushed == 0) {
@@ -160,7 +165,7 @@ public boolean flush(BufferedFile f) {
* @return If the operation is successful, it returns the current file position. Otherwise, it
* returns a value less than 0.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public long position(BufferedFile f) {
return f.getFilePosition() + getUnflushedDataSize(f);
}
@@ -171,7 +176,7 @@ public long position(BufferedFile f) {
*
* @return true if the file position was updated to the given value, false otherwise.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public boolean seek(BufferedFile f, long position) {
if (position >= 0 && flush(f) && rawFiles().seek(f.getFileDescriptor(), position)) {
f.setFilePosition(position);
@@ -185,7 +190,7 @@ public boolean seek(BufferedFile f, long position) {
*
* @return true if the data was written, false otherwise.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public boolean write(BufferedFile f, Pointer data, UnsignedWord size) {
/* Large data is written directly to the file without any buffering. */
if (size.aboveOrEqual(LARGE_DATA_THRESHOLD)) {
@@ -228,7 +233,7 @@ public boolean write(BufferedFile f, byte[] data) {
*
* @return true if the data was written, false otherwise.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public boolean writeBoolean(BufferedFile f, boolean data) {
return writeByte(f, (byte) (data ? 1 : 0));
}
@@ -238,7 +243,7 @@ public boolean writeBoolean(BufferedFile f, boolean data) {
*
* @return true if the data was written, false otherwise.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public boolean writeByte(BufferedFile f, byte data) {
if (!ensureBufferSpace(f, Byte.BYTES)) {
return false;
@@ -256,7 +261,7 @@ public boolean writeByte(BufferedFile f, byte data) {
*
* @return true if the data was written, false otherwise.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public boolean writeShort(BufferedFile f, short data) {
if (!ensureBufferSpace(f, Short.BYTES)) {
return false;
@@ -274,7 +279,7 @@ public boolean writeShort(BufferedFile f, short data) {
*
* @return true if the data was written, false otherwise.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public boolean writeChar(BufferedFile f, char data) {
if (!ensureBufferSpace(f, Character.BYTES)) {
return false;
@@ -292,7 +297,7 @@ public boolean writeChar(BufferedFile f, char data) {
*
* @return true if the data was written, false otherwise.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public boolean writeInt(BufferedFile f, int data) {
if (!ensureBufferSpace(f, Integer.BYTES)) {
return false;
@@ -310,7 +315,7 @@ public boolean writeInt(BufferedFile f, int data) {
*
* @return true if the v was written, false otherwise.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public boolean writeLong(BufferedFile f, long v) {
if (!ensureBufferSpace(f, Long.BYTES)) {
return false;
@@ -328,7 +333,7 @@ public boolean writeLong(BufferedFile f, long v) {
*
* @return true if the data was written, false otherwise.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public boolean writeFloat(BufferedFile f, float v) {
return writeInt(f, Float.floatToIntBits(v));
}
@@ -339,12 +344,12 @@ public boolean writeFloat(BufferedFile f, float v) {
*
* @return true if the data was written, false otherwise.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public boolean writeDouble(BufferedFile f, double v) {
return writeLong(f, Double.doubleToLongBits(v));
}
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public boolean writeUTF8(BufferedFile f, String string) {
return writeUTF8(f, string, null);
}
@@ -355,7 +360,7 @@ public boolean writeUTF8(BufferedFile f, String string) {
*
* @return true if the data was written, false otherwise.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public boolean writeUTF8(BufferedFile f, String string, CharReplacer replacer) {
boolean success = true;
for (int index = 0; index < string.length() && success; index++) {
@@ -368,7 +373,7 @@ public boolean writeUTF8(BufferedFile f, String string, CharReplacer replacer) {
return success;
}
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
private boolean writeUTF8(BufferedFile f, char c) {
boolean success;
if (c <= 0x007F) {
@@ -384,19 +389,19 @@ private boolean writeUTF8(BufferedFile f, char c) {
return success;
}
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public int getUnflushedDataSize(BufferedFile f) {
UnsignedWord result = f.getBufferPos().subtract(getBufferStart(f));
assert result.belowOrEqual(BUFFER_SIZE);
return (int) result.rawValue();
}
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
private static Pointer getBufferStart(BufferedFile f) {
return ((Pointer) f).add(SizeOf.unsigned(BufferedFile.class));
}
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
private boolean ensureBufferSpace(BufferedFile f, int size) {
assert size <= BUFFER_SIZE : "only called for small data";
if (getUnflushedDataSize(f) + size >= BUFFER_SIZE) {
@@ -405,7 +410,7 @@ private boolean ensureBufferSpace(BufferedFile f, int size) {
return true;
}
- @Fold
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
static RawFileOperationSupport rawFiles() {
/* The byte order does not matter because we only use byte-order-independent methods. */
return RawFileOperationSupport.nativeByteOrder();
@@ -432,6 +437,7 @@ public interface BufferedFile extends PointerBase {
void setFilePosition(long value);
}
+ @SingletonTraits(access = RuntimeAccessOnly.class, layeredCallbacks = SingleLayer.class, layeredInstallationKind = InitialLayerOnly.class)
public static class BufferedFileOperationSupportHolder {
private final BufferedFileOperationSupport littleEndian;
private final BufferedFileOperationSupport bigEndian;
@@ -447,15 +453,20 @@ public BufferedFileOperationSupportHolder() {
this.nativeOrder = nativeByteOrder == ByteOrder.LITTLE_ENDIAN ? littleEndian : bigEndian;
}
- @Fold
static BufferedFileOperationSupportHolder singleton() {
return ImageSingletons.lookup(BufferedFileOperationSupportHolder.class);
}
}
}
+@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = SingleLayer.class, layeredInstallationKind = Independent.class)
@AutomaticallyRegisteredFeature
class BufferedFileOperationFeature implements InternalFeature {
+ @Override
+ public boolean isInConfiguration(IsInConfigurationAccess access) {
+ return ImageLayerBuildingSupport.firstImageBuild();
+ }
+
@Override
public void beforeAnalysis(BeforeAnalysisAccess access) {
if (RawFileOperationSupport.isPresent()) {
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/RawFileOperationSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/RawFileOperationSupport.java
index aa2623de0fe1..7cb69db00faf 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/RawFileOperationSupport.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/os/RawFileOperationSupport.java
@@ -24,6 +24,8 @@
*/
package com.oracle.svm.core.os;
+import static com.oracle.svm.core.Uninterruptible.CALLED_FROM_UNINTERRUPTIBLE_CODE;
+
import java.io.File;
import org.graalvm.nativeimage.ImageSingletons;
@@ -36,14 +38,11 @@
import com.oracle.svm.core.memory.UntrackedNullableNativeMemory;
import com.oracle.svm.core.os.AbstractRawFileOperationSupport.RawFileOperationSupportHolder;
-import jdk.graal.compiler.api.replacements.Fold;
-
/**
* Provides unbuffered, OS-independent operations on files. Most of the code is implemented in a way
* that it can be used from uninterruptible code.
*/
public interface RawFileOperationSupport {
- @Fold
static boolean isPresent() {
return ImageSingletons.contains(RawFileOperationSupportHolder.class);
}
@@ -51,7 +50,6 @@ static boolean isPresent() {
/**
* Returns a {@link RawFileOperationSupport} singleton that uses little endian byte order.
*/
- @Fold
static RawFileOperationSupport littleEndian() {
return RawFileOperationSupportHolder.getLittleEndian();
}
@@ -59,7 +57,7 @@ static RawFileOperationSupport littleEndian() {
/**
* Returns a {@link RawFileOperationSupport} singleton that uses big endian byte order.
*/
- @Fold
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
static RawFileOperationSupport bigEndian() {
return RawFileOperationSupportHolder.getBigEndian();
}
@@ -68,7 +66,7 @@ static RawFileOperationSupport bigEndian() {
* Returns a {@link RawFileOperationSupport} singleton that uses the native byte order of the
* underlying architecture.
*/
- @Fold
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
static RawFileOperationSupport nativeByteOrder() {
return RawFileOperationSupportHolder.getNativeByteOrder();
}
@@ -107,7 +105,7 @@ static RawFileOperationSupport nativeByteOrder() {
* @return If the operation is successful, it returns the file descriptor. Otherwise, it returns
* a value where {@link #isValid} will return false.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
RawFileDescriptor create(CCharPointer path, FileCreationMode creationMode, FileAccessMode accessMode);
/** Returns the path to the platform-specific temporary directory. */
@@ -135,7 +133,7 @@ static RawFileOperationSupport nativeByteOrder() {
* @return If the operation is successful, it returns the file descriptor. Otherwise, it returns
* a value where {@link #isValid} will return false.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
RawFileDescriptor open(CCharPointer path, FileAccessMode accessMode);
/**
@@ -143,7 +141,7 @@ static RawFileOperationSupport nativeByteOrder() {
*
* @return true if the file descriptor is valid, false otherwise.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
boolean isValid(RawFileDescriptor fd);
/**
@@ -151,7 +149,7 @@ static RawFileOperationSupport nativeByteOrder() {
*
* @return true if the file descriptor was closed by the call, false otherwise.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
boolean close(RawFileDescriptor fd);
/**
@@ -160,7 +158,7 @@ static RawFileOperationSupport nativeByteOrder() {
* @return If the operation is successful, it returns the size of the file. Otherwise, it
* returns a value less than 0.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
long size(RawFileDescriptor fd);
/**
@@ -169,7 +167,7 @@ static RawFileOperationSupport nativeByteOrder() {
* @return If the operation is successful, it returns the current file position. Otherwise, it
* returns a value less than 0.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
long position(RawFileDescriptor fd);
/**
@@ -177,7 +175,7 @@ static RawFileOperationSupport nativeByteOrder() {
*
* @return true if the file position was updated to the given value, false otherwise.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
boolean seek(RawFileDescriptor fd, long position);
/**
@@ -185,7 +183,7 @@ static RawFileOperationSupport nativeByteOrder() {
*
* @return true if the data was written, false otherwise.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
boolean write(RawFileDescriptor fd, Pointer data, UnsignedWord size);
/**
@@ -201,7 +199,7 @@ static RawFileOperationSupport nativeByteOrder() {
*
* @return true if the data was written, false otherwise.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
boolean writeBoolean(RawFileDescriptor fd, boolean data);
/**
@@ -209,7 +207,7 @@ static RawFileOperationSupport nativeByteOrder() {
*
* @return true if the data was written, false otherwise.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
boolean writeByte(RawFileDescriptor fd, byte data);
/**
@@ -218,7 +216,7 @@ static RawFileOperationSupport nativeByteOrder() {
*
* @return true if the data was written, false otherwise.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
boolean writeShort(RawFileDescriptor fd, short data);
/**
@@ -227,7 +225,7 @@ static RawFileOperationSupport nativeByteOrder() {
*
* @return true if the data was written, false otherwise.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
boolean writeChar(RawFileDescriptor fd, char data);
/**
@@ -236,7 +234,7 @@ static RawFileOperationSupport nativeByteOrder() {
*
* @return true if the data was written, false otherwise.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
boolean writeInt(RawFileDescriptor fd, int data);
/**
@@ -245,7 +243,7 @@ static RawFileOperationSupport nativeByteOrder() {
*
* @return true if the data was written, false otherwise.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
boolean writeLong(RawFileDescriptor fd, long data);
/**
@@ -254,7 +252,7 @@ static RawFileOperationSupport nativeByteOrder() {
*
* @return true if the data was written, false otherwise.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
boolean writeFloat(RawFileDescriptor fd, float data);
/**
@@ -263,7 +261,7 @@ static RawFileOperationSupport nativeByteOrder() {
*
* @return true if the data was written, false otherwise.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
boolean writeDouble(RawFileDescriptor fd, double data);
/**
@@ -273,7 +271,7 @@ static RawFileOperationSupport nativeByteOrder() {
* @return If the operation is successful, it returns the number of read bytes. Otherwise, it
* returns a negative value.
*/
- @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
+ @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
long read(RawFileDescriptor fd, Pointer buffer, UnsignedWord bufferSize);
/**
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/riscv64/RISCV64CPUFeatureAccess.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/riscv64/RISCV64CPUFeatureAccess.java
index 61abb81a160a..588916093afc 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/riscv64/RISCV64CPUFeatureAccess.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/riscv64/RISCV64CPUFeatureAccess.java
@@ -36,12 +36,17 @@
import com.oracle.svm.core.Uninterruptible;
import com.oracle.svm.core.UnmanagedMemoryUtil;
import com.oracle.svm.core.graal.stackvalue.UnsafeStackValue;
+import com.oracle.svm.core.traits.BuiltinTraits.AllAccess;
+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.VMError;
import jdk.graal.compiler.nodes.spi.LoweringProvider;
import jdk.vm.ci.code.Architecture;
import jdk.vm.ci.riscv64.RISCV64;
+@SingletonTraits(access = AllAccess.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Disallowed.class)
public class RISCV64CPUFeatureAccess extends CPUFeatureAccessImpl {
@Platforms(Platform.HOSTED_ONLY.class)
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ContinuationsFeature.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ContinuationsFeature.java
index 7d916e4d1f2d..6a149b4de817 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ContinuationsFeature.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ContinuationsFeature.java
@@ -43,7 +43,6 @@
import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader;
import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter;
import com.oracle.svm.core.layeredimagesingleton.LayeredPersistFlags;
-import com.oracle.svm.core.thread.ContinuationsFeature.LayeredCallbacks;
import com.oracle.svm.core.traits.BuiltinTraits.BuildtimeAccessOnly;
import com.oracle.svm.core.traits.SingletonLayeredCallbacks;
import com.oracle.svm.core.traits.SingletonLayeredCallbacksSupplier;
@@ -55,7 +54,7 @@
import com.oracle.svm.core.util.VMError;
import com.oracle.svm.util.ReflectionUtil;
-@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = LayeredCallbacks.class, layeredInstallationKind = Independent.class)
+@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = ContinuationsFeature.LayeredCallbacks.class, layeredInstallationKind = Independent.class)
@AutomaticallyRegisteredFeature
public class ContinuationsFeature implements InternalFeature {
private boolean supported;
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/AnalyzeJavaHomeAccessFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/AnalyzeJavaHomeAccessFeature.java
index f32cf8ce3334..69490cf8f6c5 100644
--- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/AnalyzeJavaHomeAccessFeature.java
+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/AnalyzeJavaHomeAccessFeature.java
@@ -24,21 +24,34 @@
*/
package com.oracle.svm.hosted;
-import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
-import com.oracle.svm.core.feature.InternalFeature;
-import com.oracle.svm.util.LogUtils;
-import org.graalvm.nativeimage.ImageSingletons;
-
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.ConcurrentSkipListMap;
+import org.graalvm.nativeimage.ImageSingletons;
+
+import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
+import com.oracle.svm.core.feature.InternalFeature;
+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.LayeredPersistFlags;
+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.Independent;
+import com.oracle.svm.core.traits.SingletonTrait;
+import com.oracle.svm.core.traits.SingletonTraitKind;
+import com.oracle.svm.core.traits.SingletonTraits;
+import com.oracle.svm.util.LogUtils;
+
/**
* This feature collects System.getProperty("java.home") usage information from the
* {@link com.oracle.svm.hosted.phases.AnalyzeJavaHomeAccessPhase} and logs it in the image-build
* output.
*/
@AutomaticallyRegisteredFeature
+@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = AnalyzeJavaHomeAccessFeature.LayeredCallbacks.class, layeredInstallationKind = Independent.class)
public class AnalyzeJavaHomeAccessFeature implements InternalFeature {
private boolean javaHomeUsed = false;
private Set javaHomeUsageLocations = Collections.newSetFromMap(new ConcurrentSkipListMap<>());
@@ -59,15 +72,36 @@ public void addJavaHomeUsageLocation(String location) {
javaHomeUsageLocations.add(location);
}
- public void printJavaHomeUsageLocations() {
+ @Override
+ public void beforeCompilation(BeforeCompilationAccess access) {
for (String location : javaHomeUsageLocations) {
LogUtils.warning("System.getProperty(\"java.home\") detected at " + location);
}
- javaHomeUsageLocations.clear();
+ if (!ImageLayerBuildingSupport.buildingSharedLayer()) {
+ javaHomeUsageLocations = null;
+ }
}
- @Override
- public void beforeCompilation(BeforeCompilationAccess access) {
- AnalyzeJavaHomeAccessFeature.instance().printJavaHomeUsageLocations();
+ static class LayeredCallbacks extends SingletonLayeredCallbacksSupplier {
+ private static final String JAVA_HOME_USED = "javaHomeUsed";
+ private static final String JAVA_HOME_USAGE_LOCATIONS = "javaHomeUsageLocations";
+
+ @Override
+ public SingletonTrait getLayeredCallbacksTrait() {
+ return new SingletonTrait(SingletonTraitKind.LAYERED_CALLBACKS, new SingletonLayeredCallbacks() {
+ @Override
+ public LayeredPersistFlags doPersist(ImageSingletonWriter writer, AnalyzeJavaHomeAccessFeature singleton) {
+ writer.writeInt(JAVA_HOME_USED, singleton.javaHomeUsed ? 1 : 0);
+ writer.writeStringList(JAVA_HOME_USAGE_LOCATIONS, singleton.javaHomeUsageLocations.stream().toList());
+ return LayeredPersistFlags.CALLBACK_ON_REGISTRATION;
+ }
+
+ @Override
+ public void onSingletonRegistration(ImageSingletonLoader loader, AnalyzeJavaHomeAccessFeature singleton) {
+ singleton.javaHomeUsed = loader.readInt(JAVA_HOME_USED) == 1;
+ singleton.javaHomeUsageLocations.addAll(loader.readStringList(JAVA_HOME_USAGE_LOCATIONS));
+ }
+ });
+ }
}
}
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ApplicationModules.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ApplicationModules.java
index 30ff07198def..fed457be028e 100644
--- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ApplicationModules.java
+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ApplicationModules.java
@@ -26,10 +26,11 @@
import java.util.Set;
-import jdk.graal.compiler.api.replacements.Fold;
import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.hosted.Feature;
+import jdk.graal.compiler.api.replacements.Fold;
+
/**
* Returns the names of the application modules.
*/
@@ -37,7 +38,7 @@ public interface ApplicationModules {
/**
* Returns the application module names as defined by {@link Module#getName}.
*/
- Set getNames();
+ Set names();
/**
* The singleton instance is made available during {@link Feature#afterAnalysis} by the
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/BuildDirectoryProviderImpl.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/BuildDirectoryProviderImpl.java
index 9e91c2bac132..cbcc25d79c50 100644
--- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/BuildDirectoryProviderImpl.java
+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/BuildDirectoryProviderImpl.java
@@ -31,9 +31,14 @@
import com.oracle.svm.core.BuildDirectoryProvider;
import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton;
+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;
@Platforms(Platform.HOSTED_ONLY.class)
@AutomaticallyRegisteredImageSingleton(BuildDirectoryProvider.class)
+@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class)
public class BuildDirectoryProviderImpl implements BuildDirectoryProvider {
@Override
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ClassValueFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ClassValueFeature.java
index f7dd943a192f..bb7ed762ca09 100644
--- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ClassValueFeature.java
+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ClassValueFeature.java
@@ -34,13 +34,20 @@
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
import com.oracle.svm.core.feature.InternalFeature;
import com.oracle.svm.core.jdk.ClassValueSupport;
+import com.oracle.svm.core.traits.BuiltinTraits.BuildtimeAccessOnly;
+import com.oracle.svm.core.traits.BuiltinTraits.NoLayeredCallbacks;
+import com.oracle.svm.core.traits.BuiltinTraits.PartiallyLayerAware;
+import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.Independent;
+import com.oracle.svm.core.traits.SingletonTraits;
import com.oracle.svm.core.util.VMError;
import com.oracle.svm.util.ReflectionUtil;
import org.graalvm.collections.EconomicSet;
/**
* This feature reads ClassValues created by the hosted environment and stores them into the image.
+ * See {@link ClassValueSupport}.
*/
+@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class, other = PartiallyLayerAware.class)
@AutomaticallyRegisteredFeature
public final class ClassValueFeature implements InternalFeature {
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/EmbeddedResourcesInfo.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/EmbeddedResourcesInfo.java
index d8667284e292..3773e510427a 100644
--- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/EmbeddedResourcesInfo.java
+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/EmbeddedResourcesInfo.java
@@ -33,8 +33,13 @@
import org.graalvm.nativeimage.Platforms;
import com.oracle.svm.core.jdk.Resources;
+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;
@Platforms(Platform.HOSTED_ONLY.class)
+@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class)
public class EmbeddedResourcesInfo {
record SourceAndOrigin(String source, Object origin) {
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/LinkAtBuildTimeSupport.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/LinkAtBuildTimeSupport.java
index 2bd671e128c0..60912025dd4e 100644
--- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/LinkAtBuildTimeSupport.java
+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/LinkAtBuildTimeSupport.java
@@ -36,11 +36,16 @@
import com.oracle.svm.core.option.HostedOptionKey;
import com.oracle.svm.core.option.OptionClassFilter;
import com.oracle.svm.core.option.OptionOrigin;
+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.util.OriginalClassProvider;
import jdk.graal.compiler.options.Option;
import jdk.vm.ci.meta.ResolvedJavaType;
+@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class)
public final class LinkAtBuildTimeSupport {
public static final class Options {
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ModuleLayerFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ModuleLayerFeature.java
index 480724c765af..12b3da64387a 100644
--- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ModuleLayerFeature.java
+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ModuleLayerFeature.java
@@ -80,6 +80,10 @@
import com.oracle.svm.core.jdk.Resources;
import com.oracle.svm.core.jdk.RuntimeClassLoaderValueSupport;
import com.oracle.svm.core.jdk.RuntimeModuleSupport;
+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.HostedSubstrateUtil;
import com.oracle.svm.core.util.VMError;
import com.oracle.svm.hosted.FeatureImpl.AfterAnalysisAccessImpl;
@@ -622,7 +626,7 @@ private void replicateVisibilityModifications(ModuleLayer runtimeBootLayer, Afte
Set analysisReachableUnnamedModules) {
List applicationModules = findApplicationModules(runtimeBootLayer, cl.applicationModulePath());
Set applicationModuleNames = applicationModules.stream().map(Module::getName).collect(Collectors.toUnmodifiableSet());
- ImageSingletons.add(ApplicationModules.class, () -> applicationModuleNames);
+ ImageSingletons.add(ApplicationModules.class, new ApplicationModuleImpl(applicationModuleNames));
Map namedModulePairs = analysisReachableNamedModules
.stream()
@@ -1457,4 +1461,9 @@ public Object transform(Object receiver, Object originalValue) {
}
}
}
+
+ @SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class)
+ public record ApplicationModuleImpl(Set names) implements ApplicationModules {
+ }
+
}
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 17acc7dec723..f306140151d2 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
@@ -333,7 +333,7 @@ static TypeCheckInfo getTypecheckInfo(SVMImageLayerLoader loader, HostedType hTy
record TypeCheckInfo(boolean installed, int typeID, int interfaceID, int numClassTypes, int numInterfaceTypes, int[] typecheckSlots) {
}
- @SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = LayeredCallbacks.class, layeredInstallationKind = Independent.class)
+ @SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = LayerTypeCheckInfo.LayeredCallbacks.class, layeredInstallationKind = Independent.class)
private static final class LayerTypeCheckInfo {
final int maxTypeID;
final int maxInterfaceID;
@@ -354,32 +354,32 @@ public TypeCheckBuilder.StartingTypeIDs loadTypeID(Collection types)
return new TypeCheckBuilder.StartingTypeIDs(maxTypeID, maxInterfaceID);
}
- }
- static class LayeredCallbacks extends SingletonLayeredCallbacksSupplier {
- @Override
- public SingletonTrait getLayeredCallbacksTrait() {
- return new SingletonTrait(SingletonTraitKind.LAYERED_CALLBACKS, new SingletonLayeredCallbacks<>() {
- @Override
- public LayeredPersistFlags doPersist(ImageSingletonWriter writer, Object singleton) {
- writer.writeInt("maxTypeID", DynamicHubSupport.currentLayer().getMaxTypeId());
- writer.writeInt("maxInterfaceID", DynamicHubSupport.currentLayer().getMaxInterfaceId());
+ static class LayeredCallbacks extends SingletonLayeredCallbacksSupplier {
+ @Override
+ public SingletonTrait getLayeredCallbacksTrait() {
+ return new SingletonTrait(SingletonTraitKind.LAYERED_CALLBACKS, new SingletonLayeredCallbacks<>() {
+ @Override
+ public LayeredPersistFlags doPersist(ImageSingletonWriter writer, Object singleton) {
+ writer.writeInt("maxTypeID", DynamicHubSupport.currentLayer().getMaxTypeId());
+ writer.writeInt("maxInterfaceID", DynamicHubSupport.currentLayer().getMaxInterfaceId());
- return LayeredPersistFlags.CREATE;
- }
+ return LayeredPersistFlags.CREATE;
+ }
- @Override
- public Class extends LayeredSingletonInstantiator>> getSingletonInstantiator() {
- return SingletonInstantiator.class;
- }
- });
+ @Override
+ public Class extends LayeredSingletonInstantiator>> getSingletonInstantiator() {
+ return SingletonInstantiator.class;
+ }
+ });
+ }
}
- }
- static class SingletonInstantiator implements SingletonLayeredCallbacks.LayeredSingletonInstantiator {
- @Override
- public LayerTypeCheckInfo createFromLoader(ImageSingletonLoader loader) {
- return new LayerTypeCheckInfo(loader.readInt("maxTypeID"), loader.readInt("maxInterfaceID"));
+ static class SingletonInstantiator implements SingletonLayeredCallbacks.LayeredSingletonInstantiator {
+ @Override
+ public LayerTypeCheckInfo createFromLoader(ImageSingletonLoader loader) {
+ return new LayerTypeCheckInfo(loader.readInt("maxTypeID"), loader.readInt("maxInterfaceID"));
+ }
}
}
}
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CEntryPointCallStubSupport.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CEntryPointCallStubSupport.java
index fe565eef9653..0af9a246b1c2 100644
--- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CEntryPointCallStubSupport.java
+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CEntryPointCallStubSupport.java
@@ -40,10 +40,22 @@
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
import com.oracle.svm.core.feature.InternalFeature;
import com.oracle.svm.core.meta.MethodPointer;
+import com.oracle.svm.core.traits.BuiltinTraits.BuildtimeAccessOnly;
+import com.oracle.svm.core.traits.BuiltinTraits.NoLayeredCallbacks;
+import com.oracle.svm.core.traits.BuiltinTraits.PartiallyLayerAware;
+import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.Independent;
+import com.oracle.svm.core.traits.SingletonTraits;
import com.oracle.svm.hosted.FeatureImpl.DuringSetupAccessImpl;
import jdk.vm.ci.meta.ResolvedJavaType;
+/**
+ * This singleton is made layer aware automatically by the matching of
+ * {@link CEntryPointCallStubMethod} across layers with their analysis id. However, the
+ * {@link CEntryPointCallStubSupport#cFunctionPointerCache} is currently duplicated across layers as
+ * we cannot reload the {@link BoxedRelocatedPointer} across layers.
+ */
+@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class, other = PartiallyLayerAware.class)
public final class CEntryPointCallStubSupport {
public static CEntryPointCallStubSupport singleton() {
return ImageSingletons.lookup(CEntryPointCallStubSupport.class);
@@ -118,6 +130,7 @@ public BoxedRelocatedPointer getBoxedRelocatedPointer(CFunctionPointer cFunction
}
@AutomaticallyRegisteredFeature
+@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class)
class CEntryPointCallStubFeature implements InternalFeature {
@Override
public void duringSetup(DuringSetupAccess arg) {
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/DefaultCodeSectionLayouter.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/DefaultCodeSectionLayouter.java
index 0b3b61de9bca..b0221fe87309 100644
--- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/DefaultCodeSectionLayouter.java
+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/DefaultCodeSectionLayouter.java
@@ -27,9 +27,15 @@
import java.util.List;
import java.util.Map;
+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.hosted.meta.HostedMethod;
+
import jdk.graal.compiler.code.CompilationResult;
+@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class)
public class DefaultCodeSectionLayouter implements CodeSectionLayouter {
@Override
public List layout(Map compilations) {
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/RuntimeMetadataEncoderImpl.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/RuntimeMetadataEncoderImpl.java
index 2f2608286eaf..ab05b03831d0 100644
--- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/RuntimeMetadataEncoderImpl.java
+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/RuntimeMetadataEncoderImpl.java
@@ -97,6 +97,7 @@
import com.oracle.svm.core.reflect.target.Target_jdk_internal_reflect_ConstantPool;
import com.oracle.svm.core.traits.BuiltinTraits.BuildtimeAccessOnly;
import com.oracle.svm.core.traits.BuiltinTraits.NoLayeredCallbacks;
+import com.oracle.svm.core.traits.BuiltinTraits.PartiallyLayerAware;
import com.oracle.svm.core.traits.SingletonLayeredCallbacks;
import com.oracle.svm.core.traits.SingletonLayeredCallbacksSupplier;
import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.Independent;
@@ -1375,7 +1376,12 @@ public LayeredRuntimeMetadataSingleton createFromLoader(ImageSingletonLoader loa
/**
* Container for data required in later phases. Cleaner separation, rest of
* RuntimeMetadataEncoderImpl can be cleaned after encoding.
+ *
+ * GR-71595: This class does not need to have a particular behavior for Layered Image, as it
+ * only holds the data produced by RuntimeMetadataEncoderImpl. However, the data needs to be
+ * checked across layers to ensure it is consistent.
*/
+ @SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class, other = PartiallyLayerAware.class)
record EncodedRuntimeMetadataSupplierImpl(Map annotationsEncodings,
Map parameterAnnotationsEncodings,
Map annotationDefaultEncodings,
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SortByMethodNameCodeSectionLayouter.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SortByMethodNameCodeSectionLayouter.java
index 5b379dd86d4b..375a75e5c304 100644
--- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SortByMethodNameCodeSectionLayouter.java
+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SortByMethodNameCodeSectionLayouter.java
@@ -28,10 +28,15 @@
import java.util.List;
import java.util.Map;
+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.hosted.meta.HostedMethod;
import jdk.graal.compiler.code.CompilationResult;
+@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class)
public class SortByMethodNameCodeSectionLayouter implements CodeSectionLayouter {
@Override
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/UninterruptibleAnnotationChecker.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/UninterruptibleAnnotationChecker.java
index 9792c36b8545..df4b508f3474 100644
--- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/UninterruptibleAnnotationChecker.java
+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/UninterruptibleAnnotationChecker.java
@@ -37,6 +37,10 @@
import com.oracle.svm.core.classinitialization.EnsureClassInitializedNode;
import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton;
import com.oracle.svm.core.option.HostedOptionKey;
+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.VMError;
import com.oracle.svm.hosted.meta.HostedMethod;
import com.oracle.svm.util.AnnotationUtil;
@@ -54,6 +58,7 @@
import jdk.vm.ci.meta.ResolvedJavaMethod;
/** Checks that {@linkplain Uninterruptible} has been used consistently. */
+@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class)
@AutomaticallyRegisteredImageSingleton
public final class UninterruptibleAnnotationChecker {
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/config/DynamicHubLayout.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/config/DynamicHubLayout.java
index 3c29d05946fb..1491d835d9f1 100644
--- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/config/DynamicHubLayout.java
+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/config/DynamicHubLayout.java
@@ -36,7 +36,19 @@
import com.oracle.svm.core.hub.HubType;
import com.oracle.svm.core.hub.Hybrid;
import com.oracle.svm.core.hub.LayoutEncoding;
+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.LayeredPersistFlags;
import com.oracle.svm.core.monitor.MultiThreadedMonitorSupport;
+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.Independent;
+import com.oracle.svm.core.traits.SingletonTrait;
+import com.oracle.svm.core.traits.SingletonTraitKind;
+import com.oracle.svm.core.traits.SingletonTraits;
+import com.oracle.svm.core.util.VMError;
import com.oracle.svm.hosted.meta.HostedField;
import com.oracle.svm.hosted.meta.HostedInstanceClass;
import com.oracle.svm.hosted.meta.HostedType;
@@ -77,6 +89,7 @@
* Like {@link Hybrid} objects, DynamicHubs have an instance {@link HubType}, but a
* {@link LayoutEncoding} like an array (see the javadoc for {@link Hybrid}).
*/
+@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = DynamicHubLayout.LayeredCallbacks.class, layeredInstallationKind = Independent.class)
public class DynamicHubLayout {
private final ObjectLayout layout;
@@ -89,12 +102,18 @@ public class DynamicHubLayout {
public final JavaKind vTableSlotStorageKind;
private final Set ignoredFields;
- /*
+ /**
* This is calculated lazily, as it requires the dynamicHub's instance fields to be finalized
* before being calculated.
*/
private int vTableOffset;
+ /**
+ * The vTableOffset from the previous layer that is used to ensure that the vTableOffset is
+ * consistent across layers.
+ */
+ private int previousLayerVTableOffset;
+
/**
* See {@code HostedConfiguration#DynamicHubLayout} for the exact initialization values.
*/
@@ -159,6 +178,9 @@ public int getVTableLengthOffset() {
public int vTableOffset() {
if (vTableOffset == 0) {
vTableOffset = NumUtil.roundUp(dynamicHubType.getAfterFieldsOffset(), vTableSlotSize);
+ if (ImageLayerBuildingSupport.buildingExtensionLayer()) {
+ VMError.guarantee(vTableOffset == previousLayerVTableOffset, "Previous layer vTableOffset was %d, but current is %d", previousLayerVTableOffset, vTableOffset);
+ }
}
return vTableOffset;
}
@@ -170,4 +192,46 @@ public long getTotalSize(int vtableLength) {
public long getIdentityHashOffset(int vTableLength) {
return layout.getArrayIdentityHashOffset(getVTableSlotOffset(vTableLength));
}
+
+ static class LayeredCallbacks extends SingletonLayeredCallbacksSupplier {
+
+ public static final String CLOSED_TYPE_WORLD_TYPE_CHECK_SLOTS_OFFSET = "closedTypeWorldTypeCheckSlotsOffset";
+ public static final String CLOSED_TYPE_WORLD_TYPE_CHECK_SLOT_SIZE = "closedTypeWorldTypeCheckSlotSize";
+ public static final String V_TABLE_SLOT_SIZE = "vTableSlotSize";
+ public static final String V_TABLE_OFFSET = "vTableOffset";
+
+ @Override
+ public SingletonTrait getLayeredCallbacksTrait() {
+ var action = new SingletonLayeredCallbacks() {
+ @Override
+ public LayeredPersistFlags doPersist(ImageSingletonWriter writer, DynamicHubLayout singleton) {
+ writer.writeInt(CLOSED_TYPE_WORLD_TYPE_CHECK_SLOTS_OFFSET, singleton.closedTypeWorldTypeCheckSlotsOffset);
+ writer.writeInt(CLOSED_TYPE_WORLD_TYPE_CHECK_SLOT_SIZE, singleton.closedTypeWorldTypeCheckSlotSize);
+ writer.writeInt(V_TABLE_SLOT_SIZE, singleton.vTableSlotSize);
+ writer.writeInt(V_TABLE_OFFSET, singleton.vTableOffset);
+ return LayeredPersistFlags.CALLBACK_ON_REGISTRATION;
+ }
+
+ @Override
+ public void onSingletonRegistration(ImageSingletonLoader loader, DynamicHubLayout singleton) {
+ int previousLayerClosedTypeWorldTypeCheckSlotsOffset = loader.readInt(CLOSED_TYPE_WORLD_TYPE_CHECK_SLOTS_OFFSET);
+ VMError.guarantee(singleton.closedTypeWorldTypeCheckSlotsOffset == previousLayerClosedTypeWorldTypeCheckSlotsOffset,
+ "Previous layer closedTypeWorldTypeCheckSlotsOffset was %d but current is %d", previousLayerClosedTypeWorldTypeCheckSlotsOffset,
+ singleton.closedTypeWorldTypeCheckSlotsOffset);
+
+ int previousLayerClosedTypeWorldTypeCheckSlotSize = loader.readInt(CLOSED_TYPE_WORLD_TYPE_CHECK_SLOT_SIZE);
+ VMError.guarantee(singleton.closedTypeWorldTypeCheckSlotSize == previousLayerClosedTypeWorldTypeCheckSlotSize,
+ "Previous layer closedTypeWorldTypeCheckSlotSize was %d but current is %d", previousLayerClosedTypeWorldTypeCheckSlotSize,
+ singleton.closedTypeWorldTypeCheckSlotSize);
+
+ int previousLayerVTableSlotSize = loader.readInt(V_TABLE_SLOT_SIZE);
+ VMError.guarantee(singleton.vTableSlotSize == previousLayerVTableSlotSize,
+ "Previous layer vTableSlotSize was %d but current is %d", previousLayerVTableSlotSize, singleton.vTableSlotSize);
+
+ singleton.previousLayerVTableOffset = loader.readInt(V_TABLE_OFFSET);
+ }
+ };
+ return new SingletonTrait(SingletonTraitKind.LAYERED_CALLBACKS, action);
+ }
+ }
}
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/heap/ObservableImageHeapMapProviderImpl.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/heap/ObservableImageHeapMapProviderImpl.java
index f6b5e0148ae9..209f9a2063da 100644
--- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/heap/ObservableImageHeapMapProviderImpl.java
+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/heap/ObservableImageHeapMapProviderImpl.java
@@ -42,6 +42,7 @@
import com.oracle.svm.hosted.FeatureImpl.BeforeAnalysisAccessImpl;
import com.oracle.svm.hosted.util.ObservableMap;
+@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class)
public class ObservableImageHeapMapProviderImpl implements ObservableImageHeapMapProvider {
ScanReason scanReason = new OtherReason("Manual value rescan triggered from " + ObservableImageHeapMapProviderImpl.class);
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/HostedDynamicLayerInfo.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/HostedDynamicLayerInfo.java
index 0f6d296adeaa..4605eec22104 100644
--- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/HostedDynamicLayerInfo.java
+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/HostedDynamicLayerInfo.java
@@ -35,7 +35,6 @@
import java.util.stream.Collectors;
import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.UnmodifiableEconomicSet;
import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.word.PointerBase;
@@ -158,20 +157,6 @@ public static MethodNameInfo loadMethodNameInfo(AnalysisMethod aMethod) {
}
}
- public UnmodifiableEconomicSet getReservedNames() {
- /*
- * Note we only need to ensure method names for persisted analysis methods are reserved.
- */
- EconomicSet reservedNames = EconomicSet.create();
- var methods = HostedImageLayerBuildingSupport.singleton().getLoader().getHostedMethods();
- for (var methodData : methods) {
- if (methodData.getMethodId() != LayeredDispatchTableFeature.PriorDispatchMethod.UNPERSISTED_METHOD_ID) {
- reservedNames.add(methodData.getHostedMethodUniqueName().toString());
- }
- }
- return reservedNames;
- }
-
public void registerHostedMethod(HostedMethod hMethod) {
assert !BuildPhaseProvider.isHostedUniverseBuilt();
AnalysisMethod aMethod = hMethod.getWrapped();
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/ImageHeapRelocatableConstantFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/ImageHeapRelocatableConstantFeature.java
index 22704256f455..a93d825b8aac 100644
--- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/ImageHeapRelocatableConstantFeature.java
+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/ImageHeapRelocatableConstantFeature.java
@@ -39,6 +39,10 @@
import com.oracle.svm.core.graal.nodes.SubstrateNarrowOopStamp;
import com.oracle.svm.core.heap.ReferenceAccess;
import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport;
+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.hosted.FeatureImpl;
import jdk.graal.compiler.core.common.memory.BarrierType;
@@ -63,6 +67,7 @@
* the accesses are converted to loads from {@link #finalizedImageHeapRelocatableConstantsArray}.
*/
@AutomaticallyRegisteredFeature
+@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class)
public class ImageHeapRelocatableConstantFeature extends ImageHeapRelocatableConstantSupport implements InternalFeature {
final Map constantToInfoMap = new ConcurrentHashMap<>();
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LayeredDispatchTableFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LayeredDispatchTableFeature.java
index 28f93afbd01a..1b2391ec6e33 100644
--- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LayeredDispatchTableFeature.java
+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LayeredDispatchTableFeature.java
@@ -782,7 +782,7 @@ record PriorDispatchSlot(
* not always possible to match on method id. When it is not possible, we store
* {@link PriorDispatchMethod#UNPERSISTED_METHOD_ID} as the value.
*/
- record PriorDispatchMethod(int methodId, String symbolName, int vtableIndex, boolean isVirtualCallTarget) {
- static final int UNPERSISTED_METHOD_ID = -1;
+ public record PriorDispatchMethod(int methodId, String symbolName, int vtableIndex, boolean isVirtualCallTarget) {
+ public static final int UNPERSISTED_METHOD_ID = -1;
}
}
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jni/JNIFunctionTablesFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jni/JNIFunctionTablesFeature.java
index 25bc0f6d8416..3718ea96d390 100644
--- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jni/JNIFunctionTablesFeature.java
+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jni/JNIFunctionTablesFeature.java
@@ -29,7 +29,6 @@
import java.util.List;
import java.util.stream.Stream;
-import com.oracle.svm.util.AnnotationUtil;
import org.graalvm.nativeimage.c.function.CEntryPoint;
import org.graalvm.nativeimage.c.function.CFunctionPointer;
import org.graalvm.nativeimage.hosted.Feature;
@@ -38,6 +37,7 @@
import com.oracle.graal.pointsto.meta.AnalysisMethod;
import com.oracle.graal.pointsto.meta.AnalysisType;
import com.oracle.svm.core.SubstrateOptions;
+import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport;
import com.oracle.svm.core.jni.CallVariant;
import com.oracle.svm.core.jni.functions.JNIFunctionTables;
import com.oracle.svm.core.jni.functions.JNIFunctions;
@@ -47,6 +47,10 @@
import com.oracle.svm.core.jni.headers.JNIInvokeInterface;
import com.oracle.svm.core.jni.headers.JNINativeInterface;
import com.oracle.svm.core.meta.MethodPointer;
+import com.oracle.svm.core.traits.BuiltinTraits.BuildtimeAccessOnly;
+import com.oracle.svm.core.traits.BuiltinTraits.SingleLayer;
+import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.Independent;
+import com.oracle.svm.core.traits.SingletonTraits;
import com.oracle.svm.core.util.VMError;
import com.oracle.svm.hosted.FeatureImpl.BeforeAnalysisAccessImpl;
import com.oracle.svm.hosted.FeatureImpl.BeforeCompilationAccessImpl;
@@ -59,6 +63,7 @@
import com.oracle.svm.hosted.code.CEntryPointData;
import com.oracle.svm.hosted.meta.HostedMethod;
import com.oracle.svm.hosted.meta.HostedType;
+import com.oracle.svm.util.AnnotationUtil;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.MetaAccessProvider;
@@ -68,6 +73,7 @@
* Prepares the initialization of the JNI function table structures at image generation time,
* creating and registering methods that implement JNI functions as necessary.
*/
+@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = SingleLayer.class, layeredInstallationKind = Independent.class)
public class JNIFunctionTablesFeature implements Feature {
private final EnumSet jniKinds = EnumSet.of(JavaKind.Object, JavaKind.Boolean, JavaKind.Byte, JavaKind.Char,
@@ -91,6 +97,11 @@ public class JNIFunctionTablesFeature implements Feature {
*/
private StructInfo invokeInterfaceMetadata;
+ @Override
+ public boolean isInConfiguration(IsInConfigurationAccess access) {
+ return ImageLayerBuildingSupport.firstImageBuild();
+ }
+
@Override
public List> getRequiredFeatures() {
return Arrays.asList(JNIAccessFeature.class);
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedMethodNameFactory.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedMethodNameFactory.java
index 96f748ea1955..8ac0ae80f867 100644
--- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedMethodNameFactory.java
+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedMethodNameFactory.java
@@ -28,6 +28,7 @@
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import org.graalvm.collections.EconomicSet;
import org.graalvm.collections.UnmodifiableEconomicSet;
import org.graalvm.nativeimage.ImageSingletons;
@@ -36,11 +37,24 @@
import com.oracle.svm.core.feature.InternalFeature;
import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport;
import com.oracle.svm.core.imagelayer.LayeredImageOptions;
+import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader;
+import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter;
+import com.oracle.svm.core.layeredimagesingleton.LayeredPersistFlags;
+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.Independent;
+import com.oracle.svm.core.traits.SingletonTrait;
+import com.oracle.svm.core.traits.SingletonTraitKind;
+import com.oracle.svm.core.traits.SingletonTraits;
import com.oracle.svm.core.util.VMError;
import com.oracle.svm.hosted.imagelayer.HostedDynamicLayerInfo;
+import com.oracle.svm.hosted.imagelayer.LayeredDispatchTableFeature;
+import com.oracle.svm.hosted.imagelayer.SVMImageLayerSingletonLoader;
import com.oracle.svm.util.LogUtils;
@AutomaticallyRegisteredFeature
+@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = HostedMethodNameFactory.LayeredCallbacks.class, layeredInstallationKind = Independent.class)
public class HostedMethodNameFactory implements InternalFeature {
private Map methodNameCount = new ConcurrentHashMap<>();
private Set uniqueShortNames = ConcurrentHashMap.newKeySet();
@@ -101,15 +115,39 @@ MethodNameInfo createNames(NameGenerator generator, AnalysisMethod aMethod) {
return result;
}
- @Override
- public void afterAnalysis(AfterAnalysisAccess access) {
- reservedUniqueShortNames = buildingExtensionLayer ? HostedDynamicLayerInfo.singleton().getReservedNames() : null;
- }
-
@Override
public void afterCompilation(AfterCompilationAccess access) {
methodNameCount = null;
uniqueShortNames = null;
reservedUniqueShortNames = null;
}
+
+ public static class LayeredCallbacks extends SingletonLayeredCallbacksSupplier {
+ @Override
+ public SingletonTrait getLayeredCallbacksTrait() {
+ var action = new SingletonLayeredCallbacks() {
+ @Override
+ public LayeredPersistFlags doPersist(ImageSingletonWriter writer, HostedMethodNameFactory singleton) {
+ return LayeredPersistFlags.CALLBACK_ON_REGISTRATION;
+ }
+
+ @Override
+ public void onSingletonRegistration(ImageSingletonLoader loader, HostedMethodNameFactory singleton) {
+ /*
+ * Note we only need to ensure method names for persisted analysis methods are
+ * reserved.
+ */
+ EconomicSet reservedNames = EconomicSet.create();
+ var methods = ((SVMImageLayerSingletonLoader.ImageSingletonLoaderImpl) loader).getSnapshotReader().getHostedMethods();
+ for (var methodData : methods) {
+ if (methodData.getMethodId() != LayeredDispatchTableFeature.PriorDispatchMethod.UNPERSISTED_METHOD_ID) {
+ reservedNames.add(methodData.getHostedMethodUniqueName().toString());
+ }
+ }
+ singleton.reservedUniqueShortNames = reservedNames;
+ }
+ };
+ return new SingletonTrait(SingletonTraitKind.LAYERED_CALLBACKS, action);
+ }
+ }
}
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/MaterializedConstantFields.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/MaterializedConstantFields.java
index acaa6c7549ca..c54182dc4707 100644
--- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/MaterializedConstantFields.java
+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/MaterializedConstantFields.java
@@ -31,53 +31,70 @@
import org.graalvm.nativeimage.ImageSingletons;
import com.oracle.graal.pointsto.meta.AnalysisField;
-import com.oracle.svm.core.feature.InternalFeature;
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
+import com.oracle.svm.core.feature.InternalFeature;
+import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader;
+import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter;
+import com.oracle.svm.core.layeredimagesingleton.LayeredPersistFlags;
+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.Independent;
+import com.oracle.svm.core.traits.SingletonTrait;
+import com.oracle.svm.core.traits.SingletonTraitKind;
+import com.oracle.svm.core.traits.SingletonTraits;
/**
* Tracks fields with constant values which could be inlined, but which must exist in memory -- for
* example, when they might be accessed via JNI.
*/
-public class MaterializedConstantFields {
- static void initialize() {
- ImageSingletons.add(MaterializedConstantFields.class, new MaterializedConstantFields());
- }
+@AutomaticallyRegisteredFeature
+@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = MaterializedConstantFields.LayeredCallbacks.class, layeredInstallationKind = Independent.class)
+public class MaterializedConstantFields implements InternalFeature {
+ private final Set fields = Collections.newSetFromMap(new ConcurrentHashMap<>());
+ private boolean sealed = false;
public static MaterializedConstantFields singleton() {
return ImageSingletons.lookup(MaterializedConstantFields.class);
}
- private final Set fields = Collections.newSetFromMap(new ConcurrentHashMap<>());
- private boolean sealed = false;
+ @Override
+ public void beforeCompilation(BeforeCompilationAccess access) {
+ sealed = true;
+ }
public void register(AnalysisField field) {
assert field.isStatic() : "Only required for static final fields: " + field;
assert field.isAccessed() : "Field must be accessed as read: " + field;
assert !sealed : "Already sealed: " + field;
- fields.add(field);
+ fields.add(field.getId());
}
public boolean contains(AnalysisField field) {
if (field.isStatic()) {
- return fields.contains(field);
+ return fields.contains(field.getId());
}
return false;
}
- void seal() {
- sealed = true;
- }
-}
+ public static class LayeredCallbacks extends SingletonLayeredCallbacksSupplier {
+ private static final String FIELDS = "fields";
-@AutomaticallyRegisteredFeature
-class MaterializedConstantFieldsFeature implements InternalFeature {
- @Override
- public void afterRegistration(AfterRegistrationAccess access) {
- MaterializedConstantFields.initialize();
- }
+ @Override
+ public SingletonTrait getLayeredCallbacksTrait() {
+ var action = new SingletonLayeredCallbacks() {
+ @Override
+ public LayeredPersistFlags doPersist(ImageSingletonWriter writer, MaterializedConstantFields singleton) {
+ writer.writeIntList(FIELDS, singleton.fields.stream().toList());
+ return LayeredPersistFlags.CALLBACK_ON_REGISTRATION;
+ }
- @Override
- public void beforeCompilation(BeforeCompilationAccess access) {
- MaterializedConstantFields.singleton().seal();
+ @Override
+ public void onSingletonRegistration(ImageSingletonLoader loader, MaterializedConstantFields singleton) {
+ singleton.fields.addAll(loader.readIntList(FIELDS));
+ }
+ };
+ return new SingletonTrait(SingletonTraitKind.LAYERED_CALLBACKS, action);
+ }
}
}
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/CInterfaceEnumTool.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/CInterfaceEnumTool.java
index 16f4d8173607..f5d86c1a9f21 100644
--- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/CInterfaceEnumTool.java
+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/CInterfaceEnumTool.java
@@ -41,6 +41,10 @@
import com.oracle.svm.core.c.enums.CEnumRuntimeData;
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
import com.oracle.svm.core.feature.InternalFeature;
+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.VMError;
import com.oracle.svm.hosted.FeatureImpl.BeforeAnalysisAccessImpl;
import com.oracle.svm.hosted.c.info.EnumInfo;
@@ -88,6 +92,7 @@
* annotated methods. So, for implicit conversion, only the type of the C enum is relevant and the
* semantics are similar to reading/writing a C value.
*/
+@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class)
public class CInterfaceEnumTool {
interface CallTargetFactory {
MethodCallTargetNode createMethodCallTarget(InvokeKind invokeKind, AnalysisMethod targetMethod, ValueNode[] args, StampPair returnStamp, int bci);
@@ -237,6 +242,7 @@ public static AnalysisType getCEnumValueType(EnumInfo enumInfo, AnalysisMetaAcce
}
}
+@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class)
@AutomaticallyRegisteredFeature
class CInterfaceEnumToolFeature implements InternalFeature {
@Override
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/EnumSwitchPlugin.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/EnumSwitchPlugin.java
index a29c9acaf9c9..ac28a7c38884 100644
--- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/EnumSwitchPlugin.java
+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/EnumSwitchPlugin.java
@@ -52,7 +52,6 @@
import com.oracle.svm.core.util.VMError;
import com.oracle.svm.hosted.FeatureImpl.DuringSetupAccessImpl;
import com.oracle.svm.hosted.code.SubstrateCompilationDirectives;
-import com.oracle.svm.hosted.phases.EnumSwitchFeature.LayeredCallbacks;
import com.oracle.svm.util.ReflectionUtil;
import jdk.graal.compiler.debug.GraalError;
@@ -133,7 +132,7 @@ public boolean handleInvoke(GraphBuilderContext b, ResolvedJavaMethod m, ValueNo
}
@AutomaticallyRegisteredFeature
-@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = LayeredCallbacks.class, layeredInstallationKind = Independent.class)
+@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = EnumSwitchFeature.LayeredCallbacks.class, layeredInstallationKind = Independent.class)
final class EnumSwitchFeature implements InternalFeature {
private static final String METHODS_ID = "methodsId";
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/util/HostedSubstrateUtilDefaultImpl.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/util/HostedSubstrateUtilDefaultImpl.java
index f08d656a0de6..715185fe226d 100644
--- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/util/HostedSubstrateUtilDefaultImpl.java
+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/util/HostedSubstrateUtilDefaultImpl.java
@@ -25,9 +25,14 @@
package com.oracle.svm.hosted.util;
import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton;
+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.HostedSubstrateUtil;
import com.oracle.svm.hosted.ClassLoaderFeature;
+@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class)
@AutomaticallyRegisteredImageSingleton(value = HostedSubstrateUtil.class)
public class HostedSubstrateUtilDefaultImpl implements HostedSubstrateUtil {
diff --git a/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/wasmgc/image/WasmGCHeapLayouter.java b/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/wasmgc/image/WasmGCHeapLayouter.java
index fe16f9cea54b..3601e73acc76 100644
--- a/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/wasmgc/image/WasmGCHeapLayouter.java
+++ b/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/wasmgc/image/WasmGCHeapLayouter.java
@@ -33,6 +33,10 @@
import com.oracle.svm.core.image.ImageHeapLayouter;
import com.oracle.svm.core.image.ImageHeapObject;
import com.oracle.svm.core.image.ImageHeapPartition;
+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.VMError;
import com.oracle.svm.hosted.webimage.wasmgc.codegen.WasmGCHeapWriter;
@@ -45,6 +49,7 @@
* @see WasmGCPartition
* @see WasmGCHeapWriter
*/
+@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class)
public class WasmGCHeapLayouter implements ImageHeapLayouter {
/**