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> getSingletonInstantiator() { - return SingletonInstantiator.class; - } - }); + @Override + public Class> 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> getSingletonInstantiator() { - return SingletonInstantiator.class; - } - }); + @Override + public Class> 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 { /**