diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfoEncoder.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfoEncoder.java index 748aa75fb67a..dfa4ca73f8b0 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfoEncoder.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfoEncoder.java @@ -28,7 +28,6 @@ import static com.oracle.svm.core.util.VMError.shouldNotReachHereUnexpectedInput; import java.util.BitSet; -import java.util.EnumSet; import java.util.Objects; import java.util.TreeMap; import java.util.function.Consumer; @@ -70,12 +69,18 @@ import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader; import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.core.meta.SharedField; import com.oracle.svm.core.meta.SharedMethod; import com.oracle.svm.core.meta.SharedType; import com.oracle.svm.core.nmt.NmtCategory; import com.oracle.svm.core.option.HostedOptionKey; +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.ByteArrayReader; import com.oracle.svm.core.util.Counter; import com.oracle.svm.core.util.VMError; @@ -909,7 +914,8 @@ private static ValueInfo findActualValue(ValueInfo[] actualObject, UnsignedWord } @AutomaticallyRegisteredImageSingleton(onlyWith = BuildingImageLayerPredicate.class) -class MethodTableFirstIDTracker implements LayeredImageSingleton { +@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = MethodTableFirstIDTracker.LayeredCallbacks.class, layeredInstallationKind = Independent.class) +class MethodTableFirstIDTracker { public final int startingID; public int nextStartingId = -1; @@ -925,21 +931,31 @@ private MethodTableFirstIDTracker(int id) { startingID = id; } - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; - } + static class LayeredCallbacks extends SingletonLayeredCallbacksSupplier { + @Override + public SingletonTrait getLayeredCallbacksTrait() { + return new SingletonTrait(SingletonTraitKind.LAYERED_CALLBACKS, new SingletonLayeredCallbacks() { + @Override + public LayeredImageSingleton.PersistFlags doPersist(ImageSingletonWriter writer, MethodTableFirstIDTracker singleton) { + int nextStartingId = singleton.nextStartingId; + assert nextStartingId > 0 : nextStartingId; + writer.writeInt("startingID", nextStartingId); + return LayeredImageSingleton.PersistFlags.CREATE; + } - @Override - public PersistFlags preparePersist(ImageSingletonWriter writer) { - assert nextStartingId > 0 : nextStartingId; - writer.writeInt("startingID", nextStartingId); - return PersistFlags.CREATE; + @Override + public Class> getSingletonInstantiator() { + return SingletonInstantiator.class; + } + }); + } } - @SuppressWarnings("unused") - public static Object createFromLoader(ImageSingletonLoader loader) { - return new MethodTableFirstIDTracker(loader.readInt("startingID")); + static class SingletonInstantiator implements SingletonLayeredCallbacks.LayeredSingletonInstantiator { + @Override + public MethodTableFirstIDTracker createFromLoader(ImageSingletonLoader loader) { + return new MethodTableFirstIDTracker(loader.readInt("startingID")); + } } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/KnownOffsets.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/KnownOffsets.java index 3e1eed3ce325..6efb14a46295 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/KnownOffsets.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/KnownOffsets.java @@ -26,7 +26,6 @@ import java.lang.reflect.Field; import java.util.Arrays; -import java.util.EnumSet; import java.util.function.Predicate; import org.graalvm.nativeimage.ImageSingletons; @@ -40,7 +39,13 @@ import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader; import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; +import com.oracle.svm.core.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 jdk.graal.compiler.api.replacements.Fold; @@ -157,28 +162,38 @@ public int getImageCodeInfoCodeStartOffset() { return imageCodeInfoCodeStartOffset; } - static class PriorKnownOffsets implements LayeredImageSingleton { + @SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = PriorKnownOffsets.LayeredCallbacks.class, layeredInstallationKind = Independent.class) + static class PriorKnownOffsets { final int[] priorValues; PriorKnownOffsets(int[] priorValues) { this.priorValues = priorValues; } - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; - } - - @Override - public PersistFlags preparePersist(ImageSingletonWriter writer) { - writer.writeIntList("priorValues", Arrays.stream(priorValues).boxed().toList()); - return PersistFlags.CREATE; + static class LayeredCallbacks extends SingletonLayeredCallbacksSupplier { + @Override + public SingletonTrait getLayeredCallbacksTrait() { + return new SingletonTrait(SingletonTraitKind.LAYERED_CALLBACKS, new SingletonLayeredCallbacks() { + @Override + public LayeredImageSingleton.PersistFlags doPersist(ImageSingletonWriter writer, PriorKnownOffsets singleton) { + writer.writeIntList("priorValues", Arrays.stream(singleton.priorValues).boxed().toList()); + return LayeredImageSingleton.PersistFlags.CREATE; + } + + @Override + public Class> getSingletonInstantiator() { + return SingletonInstantiator.class; + } + }); + } } - @SuppressWarnings("unused") - public static Object createFromLoader(ImageSingletonLoader loader) { - int[] priorValues = loader.readIntList("priorValues").stream().mapToInt(e -> e).toArray(); - return new PriorKnownOffsets(priorValues); + static class SingletonInstantiator implements SingletonLayeredCallbacks.LayeredSingletonInstantiator { + @Override + public PriorKnownOffsets createFromLoader(ImageSingletonLoader loader) { + int[] priorValues = loader.readIntList("priorValues").stream().mapToInt(e -> e).toArray(); + return new PriorKnownOffsets(priorValues); + } } } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/imagelayer/ImageLayerSection.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/imagelayer/ImageLayerSection.java index 1af4ad26afb5..dc88c7a85441 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/imagelayer/ImageLayerSection.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/imagelayer/ImageLayerSection.java @@ -29,7 +29,6 @@ import org.graalvm.word.Pointer; import com.oracle.svm.core.c.CGlobalData; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; import jdk.graal.compiler.api.replacements.Fold; @@ -38,7 +37,7 @@ * contains the addresses of various important locations and information about values to patch at * runtime. See {@code ImageLayerSectionFeature} for details. */ -public abstract class ImageLayerSection implements LayeredImageSingleton { +public abstract class ImageLayerSection { protected final CGlobalData initialSectionStart; protected final CGlobalData cachedImageFDs; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/LayeredModuleSingleton.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/LayeredModuleSingleton.java index eb9eaa626065..c37918a8fe1a 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/LayeredModuleSingleton.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/LayeredModuleSingleton.java @@ -34,7 +34,6 @@ import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; import com.oracle.svm.core.util.UserError; /** @@ -42,7 +41,7 @@ * from all image layers. */ @Platforms(Platform.HOSTED_ONLY.class) -public abstract class LayeredModuleSingleton implements LayeredImageSingleton { +public abstract class LayeredModuleSingleton { public static final String ALL_UNNAMED_MODULE_NAME = "native-image-all-unnamed"; public static final String EVERYONE_MODULE_NAME = "native-image-everyone"; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/StringInternSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/StringInternSupport.java index 5f96fc250bc1..68036355bdd1 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/StringInternSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/StringInternSupport.java @@ -27,7 +27,6 @@ import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; -import java.util.EnumSet; import java.util.IdentityHashMap; import java.util.List; import java.util.Set; @@ -46,20 +45,26 @@ import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader; import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonSupport; import com.oracle.svm.core.layeredimagesingleton.MultiLayeredImageSingleton; import com.oracle.svm.core.traits.BuiltinTraits.AllAccess; +import com.oracle.svm.core.traits.BuiltinTraits.BuildtimeAccessOnly; import com.oracle.svm.core.traits.BuiltinTraits.NoLayeredCallbacks; import com.oracle.svm.core.traits.BuiltinTraits.RuntimeAccessOnly; import com.oracle.svm.core.traits.BuiltinTraits.SingleLayer; +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.SingletonLayeredInstallationKind.InitialLayerOnly; import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.MultiLayer; +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.ReflectionUtil; @AutomaticallyRegisteredImageSingleton -public final class StringInternSupport implements LayeredImageSingleton { +@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = StringInternSupport.LayeredCallbacks.class, layeredInstallationKind = Independent.class) +public final class StringInternSupport { interface SetGenerator { Set generateSet(); @@ -76,11 +81,7 @@ public static Field getInternedStringsField() { @Platforms(Platform.HOSTED_ONLY.class) public StringInternSupport() { - this(Set.of()); - } - - private StringInternSupport(Object obj) { - this.priorLayersInternedStrings = obj; + this.priorLayersInternedStrings = Set.of(); } @Platforms(Platform.HOSTED_ONLY.class) @@ -167,27 +168,27 @@ public static Object getImageInternedStrings() { return LayeredImageSingletonSupport.singleton().lookup(ImageInternedStrings.class, false, true); } - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; - } + static class LayeredCallbacks extends SingletonLayeredCallbacksSupplier { + @Override + public SingletonTrait getLayeredCallbacksTrait() { + return new SingletonTrait(SingletonTraitKind.LAYERED_CALLBACKS, new SingletonLayeredCallbacks() { + @Override + public LayeredImageSingleton.PersistFlags doPersist(ImageSingletonWriter writer, StringInternSupport singleton) { + // This can be switched to use constant ids in the future + List newPriorInternedStrings = new ArrayList<>(singleton.internedStringsIdentityMap.size()); - @Override - public PersistFlags preparePersist(ImageSingletonWriter writer) { - // This can be switched to use constant ids in the future - List newPriorInternedStrings = new ArrayList<>(internedStringsIdentityMap.size()); + newPriorInternedStrings.addAll(singleton.internedStringsIdentityMap.keySet()); - newPriorInternedStrings.addAll(internedStringsIdentityMap.keySet()); + writer.writeStringList("internedStrings", newPriorInternedStrings); + return LayeredImageSingleton.PersistFlags.CALLBACK_ON_REGISTRATION; + } - writer.writeStringList("internedStrings", newPriorInternedStrings); - return PersistFlags.CREATE; - } - - @SuppressWarnings("unused") - public static Object createFromLoader(ImageSingletonLoader loader) { - SetGenerator gen = (() -> Set.of(loader.readStringList("internedStrings").toArray(new String[0]))); - - return new StringInternSupport(gen); + @Override + public void onSingletonRegistration(ImageSingletonLoader loader, StringInternSupport singleton) { + singleton.priorLayersInternedStrings = (SetGenerator) (() -> Set.of(loader.readStringList("internedStrings").toArray(new String[0]))); + } + }); + } } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/LayeredHostedImageHeapMapCollector.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/LayeredHostedImageHeapMapCollector.java index a584de6accbc..af785eee9a85 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/LayeredHostedImageHeapMapCollector.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/LayeredHostedImageHeapMapCollector.java @@ -25,7 +25,6 @@ package com.oracle.svm.core.util; import java.util.ArrayList; -import java.util.EnumSet; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -38,7 +37,13 @@ import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader; import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; +import com.oracle.svm.core.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.ImageHeapMap.HostedImageHeapMap; /** @@ -50,7 +55,8 @@ * {@code ImageHeapCollectionFeature#allMaps} to ensure it is always rescanned and reachable. */ @Platforms(Platform.HOSTED_ONLY.class) -public class LayeredHostedImageHeapMapCollector implements LayeredImageSingleton { +@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = LayeredHostedImageHeapMapCollector.LayeredCallbacks.class, layeredInstallationKind = Independent.class) +public class LayeredHostedImageHeapMapCollector { /** * Map keys of maps reachable in the current layer. */ @@ -92,24 +98,36 @@ public void registerPreviousLayerHostedImageHeapMap(HostedImageHeapMap hos return previousLayerReachableMaps; } - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; - } + static class LayeredCallbacks extends SingletonLayeredCallbacksSupplier { + + @Override + public SingletonTrait getLayeredCallbacksTrait() { + return new SingletonTrait(SingletonTraitKind.LAYERED_CALLBACKS, new SingletonLayeredCallbacks() { + + @Override + public LayeredImageSingleton.PersistFlags doPersist(ImageSingletonWriter writer, LayeredHostedImageHeapMapCollector singleton) { + Set reachableMapKeys = new HashSet<>(singleton.currentLayerReachableMapsKeys); + if (singleton.previousLayerReachableMapKeys != null) { + reachableMapKeys.addAll(singleton.previousLayerReachableMapKeys); + } + writer.writeStringList("reachableMapKeys", reachableMapKeys.stream().toList()); + return LayeredImageSingleton.PersistFlags.CREATE; + } - @Override - public PersistFlags preparePersist(ImageSingletonWriter writer) { - Set reachableMapKeys = new HashSet<>(currentLayerReachableMapsKeys); - if (previousLayerReachableMapKeys != null) { - reachableMapKeys.addAll(previousLayerReachableMapKeys); + @Override + public Class> getSingletonInstantiator() { + return SingletonInstantiator.class; + } + }); } - writer.writeStringList("reachableMapKeys", reachableMapKeys.stream().toList()); - return PersistFlags.CREATE; } - @SuppressWarnings("unused") - public static Object createFromLoader(ImageSingletonLoader loader) { - List previousLayerReachableMapKeys = loader.readStringList("reachableMapKeys"); - return new LayeredHostedImageHeapMapCollector(previousLayerReachableMapKeys); + static class SingletonInstantiator implements SingletonLayeredCallbacks.LayeredSingletonInstantiator { + + @Override + public LayeredHostedImageHeapMapCollector createFromLoader(ImageSingletonLoader loader) { + List previousLayerReachableMapKeys = loader.readStringList("reachableMapKeys"); + return new LayeredHostedImageHeapMapCollector(previousLayerReachableMapKeys); + } } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedLayeredModuleSingleton.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedLayeredModuleSingleton.java index 38326f8d48b9..4cee16a126e3 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedLayeredModuleSingleton.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedLayeredModuleSingleton.java @@ -24,7 +24,6 @@ */ package com.oracle.svm.hosted; -import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -35,7 +34,14 @@ import com.oracle.svm.core.jdk.LayeredModuleSingleton; import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader; import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; +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.hosted.imagelayer.CapnProtoAdapters; import com.oracle.svm.hosted.imagelayer.SVMImageLayerSingletonLoader; import com.oracle.svm.hosted.imagelayer.SVMImageLayerWriter; @@ -43,6 +49,7 @@ import com.oracle.svm.shaded.org.capnproto.StructList; @AutomaticallyRegisteredImageSingleton(value = LayeredModuleSingleton.class, onlyWith = BuildingInitialLayerPredicate.class) +@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = HostedLayeredModuleSingleton.LayeredCallbacks.class, layeredInstallationKind = Independent.class) public class HostedLayeredModuleSingleton extends LayeredModuleSingleton { public HostedLayeredModuleSingleton() { super(); @@ -52,61 +59,72 @@ public HostedLayeredModuleSingleton(Map>> module super(moduleOpenPackages, moduleExportedPackages); } - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; - } - - @Override - public PersistFlags preparePersist(ImageSingletonWriter writer) { - SVMImageLayerWriter.ImageSingletonWriterImpl writerImpl = (SVMImageLayerWriter.ImageSingletonWriterImpl) writer; - var builder = writerImpl.getSnapshotBuilder().initLayeredModule(); - persistModulePackages(builder.initOpenModulePackages(moduleOpenPackages.size()), moduleOpenPackages); - persistModulePackages(builder.initExportedModulePackages(moduleExportedPackages.size()), moduleExportedPackages); - return PersistFlags.CREATE; - } - - private static void persistModulePackages(StructList.Builder modulePackagesBuilder, Map>> modulePackages) { - int i = 0; - for (var entry : modulePackages.entrySet()) { - var entryBuilder = modulePackagesBuilder.get(i); - entryBuilder.setModuleKey(entry.getKey()); - Map> value = entry.getValue(); - var packagesBuilder = entryBuilder.initPackages(value.size()); - int j = 0; - for (var packageEntry : value.entrySet()) { - var packageEntryBuilder = packagesBuilder.get(j); - packageEntryBuilder.setPackageKey(packageEntry.getKey()); - SVMImageLayerWriter.initStringList(packageEntryBuilder::initModules, packageEntry.getValue().stream()); - j++; + static class LayeredCallbacks extends SingletonLayeredCallbacksSupplier { + private static void persistModulePackages(StructList.Builder modulePackagesBuilder, Map>> modulePackages) { + int i = 0; + for (var entry : modulePackages.entrySet()) { + var entryBuilder = modulePackagesBuilder.get(i); + entryBuilder.setModuleKey(entry.getKey()); + Map> value = entry.getValue(); + var packagesBuilder = entryBuilder.initPackages(value.size()); + int j = 0; + for (var packageEntry : value.entrySet()) { + var packageEntryBuilder = packagesBuilder.get(j); + packageEntryBuilder.setPackageKey(packageEntry.getKey()); + SVMImageLayerWriter.initStringList(packageEntryBuilder::initModules, packageEntry.getValue().stream()); + j++; + } + i++; } - i++; } - } - public static Object createFromLoader(ImageSingletonLoader loader) { - SVMImageLayerSingletonLoader.ImageSingletonLoaderImpl loaderImpl = (SVMImageLayerSingletonLoader.ImageSingletonLoaderImpl) loader; - var reader = loaderImpl.getSnapshotReader().getLayeredModule(); + @Override + public SingletonTrait getLayeredCallbacksTrait() { + return new SingletonTrait(SingletonTraitKind.LAYERED_CALLBACKS, new SingletonLayeredCallbacks() { - Map>> moduleOpenPackages = getModulePackages(reader.getOpenModulePackages()); - Map>> moduleExportedPackages = getModulePackages(reader.getExportedModulePackages()); + @Override + public LayeredImageSingleton.PersistFlags doPersist(ImageSingletonWriter writer, HostedLayeredModuleSingleton singleton) { + SVMImageLayerWriter.ImageSingletonWriterImpl writerImpl = (SVMImageLayerWriter.ImageSingletonWriterImpl) writer; + var builder = writerImpl.getSnapshotBuilder().initLayeredModule(); + persistModulePackages(builder.initOpenModulePackages(singleton.moduleOpenPackages.size()), singleton.moduleOpenPackages); + persistModulePackages(builder.initExportedModulePackages(singleton.moduleExportedPackages.size()), singleton.moduleExportedPackages); + return LayeredImageSingleton.PersistFlags.CREATE; + } - return new HostedLayeredModuleSingleton(moduleOpenPackages, moduleExportedPackages); + @Override + public Class> getSingletonInstantiator() { + return SingletonInstantiator.class; + } + }); + } } - private static Map>> getModulePackages(StructList.Reader modulePackagesReader) { - Map>> modulePackages = new HashMap<>(); - for (int i = 0; i < modulePackagesReader.size(); ++i) { - var entryReader = modulePackagesReader.get(i); - var packagesReader = entryReader.getPackages(); - Map> packages = new HashMap<>(); - for (int j = 0; j < packagesReader.size(); ++j) { - var packageEntryReader = packagesReader.get(j); - Set modules = CapnProtoAdapters.toCollection(packageEntryReader.getModules(), HashSet::new); - packages.put(packageEntryReader.getPackageKey().toString(), modules); + static class SingletonInstantiator implements SingletonLayeredCallbacks.LayeredSingletonInstantiator { + private static Map>> getModulePackages(StructList.Reader modulePackagesReader) { + Map>> modulePackages = new HashMap<>(); + for (int i = 0; i < modulePackagesReader.size(); ++i) { + var entryReader = modulePackagesReader.get(i); + var packagesReader = entryReader.getPackages(); + Map> packages = new HashMap<>(); + for (int j = 0; j < packagesReader.size(); ++j) { + var packageEntryReader = packagesReader.get(j); + Set modules = CapnProtoAdapters.toCollection(packageEntryReader.getModules(), HashSet::new); + packages.put(packageEntryReader.getPackageKey().toString(), modules); + } + modulePackages.put(entryReader.getModuleKey().toString(), packages); } - modulePackages.put(entryReader.getModuleKey().toString(), packages); + return modulePackages; + } + + @Override + public HostedLayeredModuleSingleton createFromLoader(ImageSingletonLoader loader) { + SVMImageLayerSingletonLoader.ImageSingletonLoaderImpl loaderImpl = (SVMImageLayerSingletonLoader.ImageSingletonLoaderImpl) loader; + var reader = loaderImpl.getSnapshotReader().getLayeredModule(); + + Map>> moduleOpenPackages = getModulePackages(reader.getOpenModulePackages()); + Map>> moduleExportedPackages = getModulePackages(reader.getExportedModulePackages()); + + return new HostedLayeredModuleSingleton(moduleOpenPackages, moduleExportedPackages); } - return modulePackages; } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SharedLayerBootLayerModulesSingleton.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SharedLayerBootLayerModulesSingleton.java index 8f90e72bd556..3da35b692430 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SharedLayerBootLayerModulesSingleton.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SharedLayerBootLayerModulesSingleton.java @@ -26,11 +26,9 @@ import java.util.ArrayList; import java.util.Collection; -import java.util.EnumSet; import java.util.List; import java.util.stream.Stream; -import com.oracle.svm.hosted.imagelayer.CapnProtoAdapters; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -40,13 +38,21 @@ import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader; import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; +import com.oracle.svm.core.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.hosted.imagelayer.CapnProtoAdapters; import com.oracle.svm.hosted.imagelayer.SVMImageLayerSingletonLoader; import com.oracle.svm.hosted.imagelayer.SVMImageLayerWriter; @Platforms(Platform.HOSTED_ONLY.class) @AutomaticallyRegisteredImageSingleton(onlyWith = BuildingInitialLayerPredicate.class) -public class SharedLayerBootLayerModulesSingleton implements LayeredImageSingleton { +@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = SharedLayerBootLayerModulesSingleton.LayeredCallbacks.class, layeredInstallationKind = Independent.class) +public class SharedLayerBootLayerModulesSingleton { private final Collection sharedBootLayerModules; private ModuleLayer bootLayer; @@ -70,29 +76,40 @@ public Collection getSharedBootLayerModules() { return sharedBootLayerModules; } - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; - } + static class LayeredCallbacks extends SingletonLayeredCallbacksSupplier { - @Override - public PersistFlags preparePersist(ImageSingletonWriter writer) { - SVMImageLayerWriter.ImageSingletonWriterImpl writerImpl = (SVMImageLayerWriter.ImageSingletonWriterImpl) writer; - Stream moduleNames = bootLayer.modules().stream().map(Module::getName); + @Override + public SingletonTrait getLayeredCallbacksTrait() { + return new SingletonTrait(SingletonTraitKind.LAYERED_CALLBACKS, new SingletonLayeredCallbacks() { - if (sharedBootLayerModules != null) { - moduleNames = Stream.concat(moduleNames, sharedBootLayerModules.stream()); - } + @Override + public LayeredImageSingleton.PersistFlags doPersist(ImageSingletonWriter writer, SharedLayerBootLayerModulesSingleton singleton) { + SVMImageLayerWriter.ImageSingletonWriterImpl writerImpl = (SVMImageLayerWriter.ImageSingletonWriterImpl) writer; + Stream moduleNames = singleton.bootLayer.modules().stream().map(Module::getName); - SVMImageLayerWriter.initStringList(writerImpl.getSnapshotBuilder()::initSharedLayerBootLayerModules, moduleNames); + if (singleton.sharedBootLayerModules != null) { + moduleNames = Stream.concat(moduleNames, singleton.sharedBootLayerModules.stream()); + } - return PersistFlags.CREATE; + SVMImageLayerWriter.initStringList(writerImpl.getSnapshotBuilder()::initSharedLayerBootLayerModules, moduleNames); + + return LayeredImageSingleton.PersistFlags.CREATE; + } + + @Override + public Class> getSingletonInstantiator() { + return SingletonInstantiator.class; + } + }); + } } - @SuppressWarnings("unused") - public static Object createFromLoader(ImageSingletonLoader loader) { - SVMImageLayerSingletonLoader.ImageSingletonLoaderImpl loaderImpl = (SVMImageLayerSingletonLoader.ImageSingletonLoaderImpl) loader; - List moduleNames = CapnProtoAdapters.toCollection(loaderImpl.getSnapshotReader().getSharedLayerBootLayerModules(), ArrayList::new); - return new SharedLayerBootLayerModulesSingleton(moduleNames); + static class SingletonInstantiator implements SingletonLayeredCallbacks.LayeredSingletonInstantiator { + @Override + public SharedLayerBootLayerModulesSingleton createFromLoader(ImageSingletonLoader loader) { + SVMImageLayerSingletonLoader.ImageSingletonLoaderImpl loaderImpl = (SVMImageLayerSingletonLoader.ImageSingletonLoaderImpl) loader; + List moduleNames = CapnProtoAdapters.toCollection(loaderImpl.getSnapshotReader().getSharedLayerBootLayerModules(), ArrayList::new); + return new SharedLayerBootLayerModulesSingleton(moduleNames); + } } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/SubstrateAnnotationExtractor.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/SubstrateAnnotationExtractor.java index c03c1f58c5ab..57c24ed7b38e 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/SubstrateAnnotationExtractor.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/SubstrateAnnotationExtractor.java @@ -37,7 +37,6 @@ import java.lang.reflect.RecordComponent; import java.nio.BufferUnderflowException; import java.util.Collection; -import java.util.EnumSet; import java.util.List; import java.util.Map; import java.util.Objects; @@ -51,9 +50,10 @@ import com.oracle.graal.pointsto.infrastructure.WrappedElement; import com.oracle.graal.pointsto.meta.BaseLayerElement; import com.oracle.graal.pointsto.util.GraalAccess; -import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; +import com.oracle.svm.core.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.ReflectionUtil; import jdk.graal.compiler.annotation.AnnotationValue; @@ -84,7 +84,8 @@ * never be used during Native Image generation because it initializes all annotation classes and * their dependencies. */ -public class SubstrateAnnotationExtractor implements AnnotationExtractor, LayeredImageSingleton { +@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class) +public class SubstrateAnnotationExtractor implements AnnotationExtractor { private final Map> annotationCache = new ConcurrentHashMap<>(); private final Map> declaredAnnotationCache = new ConcurrentHashMap<>(); private final Map>> parameterAnnotationCache = new ConcurrentHashMap<>(); @@ -560,14 +561,4 @@ private static AnnotatedElement unwrap(AnnotatedElement element) { } return cur; } - - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; - } - - @Override - public PersistFlags preparePersist(ImageSingletonWriter writer) { - return PersistFlags.NOTHING; - } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/CConstantValueSupportImpl.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/CConstantValueSupportImpl.java index c8af5b14fbfc..3cb28c01587f 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/CConstantValueSupportImpl.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/CConstantValueSupportImpl.java @@ -25,7 +25,6 @@ package com.oracle.svm.hosted.c; import java.lang.annotation.Annotation; -import java.util.EnumSet; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -35,9 +34,10 @@ import org.graalvm.nativeimage.impl.CConstantValueSupport; import com.oracle.svm.core.c.enums.CEnumRuntimeData; -import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; +import com.oracle.svm.core.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.c.info.ConstantInfo; import com.oracle.svm.hosted.c.info.EnumInfo; @@ -51,7 +51,8 @@ import jdk.vm.ci.meta.ResolvedJavaType; @Platforms(Platform.HOSTED_ONLY.class) -public final class CConstantValueSupportImpl implements CConstantValueSupport, LayeredImageSingleton { +@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class) +public final class CConstantValueSupportImpl implements CConstantValueSupport { private final NativeLibraries nativeLibraries; private final MetaAccessProvider metaAccess; @@ -138,14 +139,4 @@ private ResolvedJavaMethod getAnnotatedMethod(Class declaringClass, String me } return method; } - - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; - } - - @Override - public PersistFlags preparePersist(ImageSingletonWriter writer) { - return PersistFlags.NOTHING; - } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/RuntimeMetadataEncoderImpl.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/RuntimeMetadataEncoderImpl.java index fcabf1be442c..0305001fd229 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 @@ -57,7 +57,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; -import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -93,10 +92,16 @@ import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader; import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.core.meta.SharedField; import com.oracle.svm.core.reflect.target.EncodedRuntimeMetadataSupplier; 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.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.ByteArrayReader; import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.image.NativeImageCodeCache.ReflectionMetadataEncoderFactory; @@ -1238,7 +1243,8 @@ Constructor[] getDeclaredConstructors(Object obj) { * This singleton keeps track of the methods and fields registered for reflection across layers * and ensure they are only registered once. */ - private static final class LayeredRuntimeMetadataSingleton implements LayeredImageSingleton { + @SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = LayeredRuntimeMetadataSingleton.LayeredCallbacks.class, layeredInstallationKind = Independent.class) + private static final class LayeredRuntimeMetadataSingleton { /** * The methods registered in previous layers. The key is the {@link AnalysisMethod} id and * the value is {@link AccessibleObjectMetadata#complete} of the corresponding metadata. A @@ -1316,69 +1322,80 @@ public boolean shouldRegisterField(Object field, AnalysisMetaAccess metaAccess, } } - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; - } + static class LayeredCallbacks extends SingletonLayeredCallbacksSupplier { - @Override - public PersistFlags preparePersist(ImageSingletonWriter writer) { - SVMImageLayerWriter.ImageSingletonWriterImpl writerImpl = (SVMImageLayerWriter.ImageSingletonWriterImpl) writer; - var builder = writerImpl.getSnapshotBuilder().getLayeredRuntimeMetadataSingleton(); + private static void persistRegisteredElements(Map registeredElements, Map previousLayerRegisteredElements, + IntFunction elementBuilderSupplier, IntFunction elementStatesBuilderSupplier) { + List elements = new ArrayList<>(); + List elementStates = new ArrayList<>(); - persistRegisteredElements(registeredMethods, previousLayerRegisteredMethods, builder::initMethods, builder::initMethodStates); - persistRegisteredElements(registeredFields, previousLayerRegisteredFields, builder::initFields, builder::initFieldStates); - - return PersistFlags.CREATE; - } + for (var entry : registeredElements.entrySet()) { + elements.add(entry.getKey()); + elementStates.add(entry.getValue()); + } - private static void persistRegisteredElements(Map registeredElements, Map previousLayerRegisteredElements, - IntFunction elementBuilderSupplier, IntFunction elementStatesBuilderSupplier) { - List elements = new ArrayList<>(); - List elementStates = new ArrayList<>(); + for (var entry : previousLayerRegisteredElements.entrySet()) { + if (!elements.contains(entry.getKey())) { + /* + * If complete metadata overwrites incomplete metadata from a previous + * layer, the previous layer map entry needs to be skipped to register the + * new entry for extension layers. + */ + elements.add(entry.getKey()); + elementStates.add(entry.getValue()); + } + } - for (var entry : registeredElements.entrySet()) { - elements.add(entry.getKey()); - elementStates.add(entry.getValue()); - } + SVMImageLayerWriter.initInts(elementBuilderSupplier, elements.stream().mapToInt(i -> i)); - for (var entry : previousLayerRegisteredElements.entrySet()) { - if (!elements.contains(entry.getKey())) { - /* - * If complete metadata overwrites incomplete metadata from a previous layer, - * the previous layer map entry needs to be skipped to register the new entry - * for extension layers. - */ - elements.add(entry.getKey()); - elementStates.add(entry.getValue()); + PrimitiveList.Boolean.Builder elementStatesBuilder = elementStatesBuilderSupplier.apply(elementStates.size()); + for (int i = 0; i < elementStates.size(); ++i) { + elementStatesBuilder.set(i, elementStates.get(i)); } } - SVMImageLayerWriter.initInts(elementBuilderSupplier, elements.stream().mapToInt(i -> i)); + @Override + public SingletonTrait getLayeredCallbacksTrait() { + return new SingletonTrait(SingletonTraitKind.LAYERED_CALLBACKS, new SingletonLayeredCallbacks() { + + @Override + public LayeredImageSingleton.PersistFlags doPersist(ImageSingletonWriter writer, LayeredRuntimeMetadataSingleton singleton) { + SVMImageLayerWriter.ImageSingletonWriterImpl writerImpl = (SVMImageLayerWriter.ImageSingletonWriterImpl) writer; + var builder = writerImpl.getSnapshotBuilder().getLayeredRuntimeMetadataSingleton(); + + persistRegisteredElements(singleton.registeredMethods, singleton.previousLayerRegisteredMethods, builder::initMethods, builder::initMethodStates); + persistRegisteredElements(singleton.registeredFields, singleton.previousLayerRegisteredFields, builder::initFields, builder::initFieldStates); - PrimitiveList.Boolean.Builder elementStatesBuilder = elementStatesBuilderSupplier.apply(elementStates.size()); - for (int i = 0; i < elementStates.size(); ++i) { - elementStatesBuilder.set(i, elementStates.get(i)); + return LayeredImageSingleton.PersistFlags.CREATE; + } + + @Override + public Class> getSingletonInstantiator() { + return SingletonInstantiator.class; + } + }); } } - @SuppressWarnings("unused") - public static Object createFromLoader(ImageSingletonLoader loader) { - SVMImageLayerSingletonLoader.ImageSingletonLoaderImpl loaderImpl = (SVMImageLayerSingletonLoader.ImageSingletonLoaderImpl) loader; - var reader = loaderImpl.getSnapshotReader().getLayeredRuntimeMetadataSingleton(); + static class SingletonInstantiator implements SingletonLayeredCallbacks.LayeredSingletonInstantiator { + private static Map getPreviousRegisteredElements(PrimitiveList.Int.Reader elementsReader, PrimitiveList.Boolean.Reader statesReader) { + Map registeredElements = new HashMap<>(); + for (int i = 0; i < elementsReader.size(); ++i) { + registeredElements.put(elementsReader.get(i), statesReader.get(i)); + } + return registeredElements; + } - Map previousLayerRegisteredMethods = getPreviousRegisteredElements(reader.getMethods(), reader.getMethodStates()); - Map previousLayerRegisteredFields = getPreviousRegisteredElements(reader.getFields(), reader.getFieldStates()); + @Override + public LayeredRuntimeMetadataSingleton createFromLoader(ImageSingletonLoader loader) { + SVMImageLayerSingletonLoader.ImageSingletonLoaderImpl loaderImpl = (SVMImageLayerSingletonLoader.ImageSingletonLoaderImpl) loader; + var reader = loaderImpl.getSnapshotReader().getLayeredRuntimeMetadataSingleton(); - return new LayeredRuntimeMetadataSingleton(previousLayerRegisteredMethods, previousLayerRegisteredFields); - } + Map previousLayerRegisteredMethods = getPreviousRegisteredElements(reader.getMethods(), reader.getMethodStates()); + Map previousLayerRegisteredFields = getPreviousRegisteredElements(reader.getFields(), reader.getFieldStates()); - private static Map getPreviousRegisteredElements(PrimitiveList.Int.Reader elementsReader, PrimitiveList.Boolean.Reader statesReader) { - Map registeredElements = new HashMap<>(); - for (int i = 0; i < elementsReader.size(); ++i) { - registeredElements.put(elementsReader.get(i), statesReader.get(i)); + return new LayeredRuntimeMetadataSingleton(previousLayerRegisteredMethods, previousLayerRegisteredFields); } - return registeredElements; } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/fieldfolding/StaticFinalFieldFoldingFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/fieldfolding/StaticFinalFieldFoldingFeature.java index a120c0f3de91..48ec54584c9f 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/fieldfolding/StaticFinalFieldFoldingFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/fieldfolding/StaticFinalFieldFoldingFeature.java @@ -26,7 +26,6 @@ import java.util.ArrayList; import java.util.Comparator; -import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -50,9 +49,15 @@ import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader; import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.core.option.HostedOptionKey; import com.oracle.svm.core.option.SubstrateOptionsParser; +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.UserError; import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.FeatureImpl.BeforeAnalysisAccessImpl; @@ -420,7 +425,8 @@ static boolean isAllowedTargetMethod(ResolvedJavaMethod method) { } } -class StaticFinalFieldFoldingSingleton implements LayeredImageSingleton { +@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = StaticFinalFieldFoldingSingleton.LayeredCallbacks.class, layeredInstallationKind = Independent.class) +class StaticFinalFieldFoldingSingleton { /** * Folded field values after stage {@link Stage#BYTECODE_PARSED}. @@ -483,62 +489,72 @@ public Integer getFieldCheckIndex(AnalysisField field) { return fieldCheckIndexMap.get(field); } - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; - } + static class LayeredCallbacks extends SingletonLayeredCallbacksSupplier { + @Override + public SingletonTrait getLayeredCallbacksTrait() { + return new SingletonTrait(SingletonTraitKind.LAYERED_CALLBACKS, new SingletonLayeredCallbacks() { + @Override + public LayeredImageSingleton.PersistFlags doPersist(ImageSingletonWriter writer, StaticFinalFieldFoldingSingleton singleton) { + var snapshotWriter = ((SVMImageLayerWriter.ImageSingletonWriterImpl) writer).getSnapshotBuilder(); + SVMImageLayerWriter imageLayerWriter = HostedImageLayerBuildingSupport.singleton().getWriter(); + + List fields = new ArrayList<>(); + List fieldCheckIndexes = new ArrayList<>(); + List fieldInitializationStatusList = new ArrayList<>(); + List bytecodeParsedFoldedFieldValuesList = new ArrayList<>(); + List afterParsingHooksDoneFoldedFieldValuesList = new ArrayList<>(); + for (var entry : singleton.fieldCheckIndexMap.entrySet()) { + fields.add(entry.getKey().getId()); + fieldCheckIndexes.add(entry.getValue()); + fieldInitializationStatusList.add(singleton.fieldInitializationStatus[entry.getValue()]); + bytecodeParsedFoldedFieldValuesList.add(singleton.bytecodeParsedFoldedFieldValues.get(entry.getKey())); + afterParsingHooksDoneFoldedFieldValuesList.add(singleton.afterParsingHooksDoneFoldedFieldValues.get(entry.getKey())); + } - @Override - public PersistFlags preparePersist(ImageSingletonWriter writer) { - var snapshotWriter = ((SVMImageLayerWriter.ImageSingletonWriterImpl) writer).getSnapshotBuilder(); - SVMImageLayerWriter imageLayerWriter = HostedImageLayerBuildingSupport.singleton().getWriter(); - - List fields = new ArrayList<>(); - List fieldCheckIndexes = new ArrayList<>(); - List fieldInitializationStatusList = new ArrayList<>(); - List bytecodeParsedFoldedFieldValuesList = new ArrayList<>(); - List afterParsingHooksDoneFoldedFieldValuesList = new ArrayList<>(); - for (var entry : fieldCheckIndexMap.entrySet()) { - fields.add(entry.getKey().getId()); - fieldCheckIndexes.add(entry.getValue()); - fieldInitializationStatusList.add(fieldInitializationStatus[entry.getValue()]); - bytecodeParsedFoldedFieldValuesList.add(bytecodeParsedFoldedFieldValues.get(entry.getKey())); - afterParsingHooksDoneFoldedFieldValuesList.add(afterParsingHooksDoneFoldedFieldValues.get(entry.getKey())); - } + var staticFinalFieldFoldingSingleton = snapshotWriter.initStaticFinalFieldFoldingSingleton(); + var fieldsBuilder = staticFinalFieldFoldingSingleton.initFields(fields.size()); + var fieldCheckIndexesBuilder = staticFinalFieldFoldingSingleton.initFieldCheckIndexes(fieldCheckIndexes.size()); + var fieldInitializationStatusListBuilder = staticFinalFieldFoldingSingleton.initFieldInitializationStatusList(fieldInitializationStatusList.size()); + var bytecodeParsedFoldedFieldValuesListBuilder = staticFinalFieldFoldingSingleton.initBytecodeParsedFoldedFieldValues(bytecodeParsedFoldedFieldValuesList.size()); + var afterParsingHooksDoneFoldedFieldValuesListBuilder = staticFinalFieldFoldingSingleton + .initAfterParsingHooksDoneFoldedFieldValues(afterParsingHooksDoneFoldedFieldValuesList.size()); + for (int i = 0; i < fields.size(); ++i) { + fieldsBuilder.set(i, fields.get(i)); + fieldCheckIndexesBuilder.set(i, fieldCheckIndexes.get(i)); + fieldInitializationStatusListBuilder.set(i, fieldInitializationStatusList.get(i)); + imageLayerWriter.writeConstant(bytecodeParsedFoldedFieldValuesList.get(i), bytecodeParsedFoldedFieldValuesListBuilder.get(i)); + imageLayerWriter.writeConstant(afterParsingHooksDoneFoldedFieldValuesList.get(i), afterParsingHooksDoneFoldedFieldValuesListBuilder.get(i)); + } - var staticFinalFieldFoldingSingleton = snapshotWriter.initStaticFinalFieldFoldingSingleton(); - var fieldsBuilder = staticFinalFieldFoldingSingleton.initFields(fields.size()); - var fieldCheckIndexesBuilder = staticFinalFieldFoldingSingleton.initFieldCheckIndexes(fieldCheckIndexes.size()); - var fieldInitializationStatusListBuilder = staticFinalFieldFoldingSingleton.initFieldInitializationStatusList(fieldInitializationStatusList.size()); - var bytecodeParsedFoldedFieldValuesListBuilder = staticFinalFieldFoldingSingleton.initBytecodeParsedFoldedFieldValues(bytecodeParsedFoldedFieldValuesList.size()); - var afterParsingHooksDoneFoldedFieldValuesListBuilder = staticFinalFieldFoldingSingleton.initAfterParsingHooksDoneFoldedFieldValues(afterParsingHooksDoneFoldedFieldValuesList.size()); - for (int i = 0; i < fields.size(); ++i) { - fieldsBuilder.set(i, fields.get(i)); - fieldCheckIndexesBuilder.set(i, fieldCheckIndexes.get(i)); - fieldInitializationStatusListBuilder.set(i, fieldInitializationStatusList.get(i)); - imageLayerWriter.writeConstant(bytecodeParsedFoldedFieldValuesList.get(i), bytecodeParsedFoldedFieldValuesListBuilder.get(i)); - imageLayerWriter.writeConstant(afterParsingHooksDoneFoldedFieldValuesList.get(i), afterParsingHooksDoneFoldedFieldValuesListBuilder.get(i)); - } + return LayeredImageSingleton.PersistFlags.CREATE; + } - return PersistFlags.CREATE; - } + @Override + public Class> getSingletonInstantiator() { + return SingletonInstantiator.class; + } + }); + } - @SuppressWarnings("unused") - public static Object createFromLoader(ImageSingletonLoader loader) { - var snapshotReader = ((SVMImageLayerSingletonLoader.ImageSingletonLoaderImpl) loader).getSnapshotReader(); - - var staticFinalFieldFoldingSingleton = snapshotReader.getStaticFinalFieldFoldingSingleton(); - var fields = staticFinalFieldFoldingSingleton.getFields(); - var fieldCheckIndexes = staticFinalFieldFoldingSingleton.getFieldCheckIndexes(); - var fieldInitializationStatusList = staticFinalFieldFoldingSingleton.getFieldInitializationStatusList(); - var bytecodeParsedFoldedFieldValuesList = staticFinalFieldFoldingSingleton.getBytecodeParsedFoldedFieldValues(); - var afterParsingHooksDoneFoldedFieldValuesList = staticFinalFieldFoldingSingleton.getAfterParsingHooksDoneFoldedFieldValues(); - - Map baseLayerFieldFoldingInfos = new HashMap<>(); - for (int i = 0; i < fields.size(); ++i) { - baseLayerFieldFoldingInfos.put(fields.get(i), new PriorLayerFinalFieldFoldingInfo(SVMImageLayerLoader.getConstant(bytecodeParsedFoldedFieldValuesList.get(i)), - SVMImageLayerLoader.getConstant(afterParsingHooksDoneFoldedFieldValuesList.get(i)), fieldCheckIndexes.get(i), fieldInitializationStatusList.get(i))); + static class SingletonInstantiator implements SingletonLayeredCallbacks.LayeredSingletonInstantiator { + @Override + public StaticFinalFieldFoldingSingleton createFromLoader(ImageSingletonLoader loader) { + var snapshotReader = ((SVMImageLayerSingletonLoader.ImageSingletonLoaderImpl) loader).getSnapshotReader(); + + var staticFinalFieldFoldingSingleton = snapshotReader.getStaticFinalFieldFoldingSingleton(); + var fields = staticFinalFieldFoldingSingleton.getFields(); + var fieldCheckIndexes = staticFinalFieldFoldingSingleton.getFieldCheckIndexes(); + var fieldInitializationStatusList = staticFinalFieldFoldingSingleton.getFieldInitializationStatusList(); + var bytecodeParsedFoldedFieldValuesList = staticFinalFieldFoldingSingleton.getBytecodeParsedFoldedFieldValues(); + var afterParsingHooksDoneFoldedFieldValuesList = staticFinalFieldFoldingSingleton.getAfterParsingHooksDoneFoldedFieldValues(); + + Map baseLayerFieldFoldingInfos = new HashMap<>(); + for (int i = 0; i < fields.size(); ++i) { + baseLayerFieldFoldingInfos.put(fields.get(i), new PriorLayerFinalFieldFoldingInfo(SVMImageLayerLoader.getConstant(bytecodeParsedFoldedFieldValuesList.get(i)), + SVMImageLayerLoader.getConstant(afterParsingHooksDoneFoldedFieldValuesList.get(i)), fieldCheckIndexes.get(i), fieldInitializationStatusList.get(i))); + } + return new StaticFinalFieldFoldingSingleton(baseLayerFieldFoldingInfos); + } } - return new StaticFinalFieldFoldingSingleton(baseLayerFieldFoldingInfos); } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/heap/HeapDumpFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/heap/HeapDumpFeature.java index 69e52fae31cf..8bd57b549710 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/heap/HeapDumpFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/heap/HeapDumpFeature.java @@ -30,7 +30,6 @@ import java.util.Collection; import java.util.Collections; import java.util.Comparator; -import java.util.EnumSet; import java.util.List; import org.graalvm.collections.EconomicMap; @@ -58,9 +57,15 @@ import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader; import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.core.meta.SharedField; import com.oracle.svm.core.meta.SharedType; +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.ByteArrayReader; import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.FeatureImpl; @@ -289,7 +294,8 @@ private static HProfType getType(SharedField field) { } @AutomaticallyRegisteredImageSingleton(onlyWith = BuildingImageLayerPredicate.class) -class LayeredHeapDumpEncodedTypesTracker implements LayeredImageSingleton { +@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = LayeredHeapDumpEncodedTypesTracker.LayeredCallbacks.class, layeredInstallationKind = Independent.class) +class LayeredHeapDumpEncodedTypesTracker { private List encodedFieldNames; private final List priorFieldNames; @@ -309,20 +315,30 @@ public List getPriorFieldNames() { return priorFieldNames; } - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; - } + static class LayeredCallbacks extends SingletonLayeredCallbacksSupplier { - @Override - public PersistFlags preparePersist(ImageSingletonWriter writer) { - writer.writeStringList("encodedFieldNames", encodedFieldNames); - return PersistFlags.CREATE; + @Override + public SingletonTrait getLayeredCallbacksTrait() { + return new SingletonTrait(SingletonTraitKind.LAYERED_CALLBACKS, new SingletonLayeredCallbacks() { + @Override + public LayeredImageSingleton.PersistFlags doPersist(ImageSingletonWriter writer, LayeredHeapDumpEncodedTypesTracker singleton) { + writer.writeStringList("encodedFieldNames", singleton.encodedFieldNames); + return LayeredImageSingleton.PersistFlags.CREATE; + } + + @Override + public Class> getSingletonInstantiator() { + return SingletonInstantiator.class; + } + }); + } } - @SuppressWarnings("unused") - public static Object createFromLoader(ImageSingletonLoader loader) { - List encodedFieldNames = Collections.unmodifiableList(loader.readStringList("encodedFieldNames")); - return new LayeredHeapDumpEncodedTypesTracker(encodedFieldNames); + static class SingletonInstantiator implements SingletonLayeredCallbacks.LayeredSingletonInstantiator { + @Override + public LayeredHeapDumpEncodedTypesTracker createFromLoader(ImageSingletonLoader loader) { + List encodedFieldNames = Collections.unmodifiableList(loader.readStringList("encodedFieldNames")); + return new LayeredHeapDumpEncodedTypesTracker(encodedFieldNames); + } } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/CrossLayerConstantRegistryFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/CrossLayerConstantRegistryFeature.java index faef89ac4373..b664b67cb683 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/CrossLayerConstantRegistryFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/CrossLayerConstantRegistryFeature.java @@ -28,7 +28,6 @@ import static com.oracle.svm.hosted.imagelayer.CrossLayerConstantRegistryFeature.NULL_CONSTANT_ID; import java.util.ArrayList; -import java.util.EnumSet; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -49,7 +48,13 @@ import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader; import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; +import com.oracle.svm.core.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.ObservableImageHeapMapProvider; import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.FeatureImpl; @@ -94,12 +99,8 @@ public boolean isInConfiguration(IsInConfigurationAccess access) { @Override public void afterRegistration(AfterRegistrationAccess access) { - if (ImageLayerBuildingSupport.buildingInitialLayer()) { - tracker = new ImageLayerIdTrackingSingleton(); - ImageSingletons.add(ImageLayerIdTrackingSingleton.class, tracker); - } else { - tracker = ImageSingletons.lookup(ImageLayerIdTrackingSingleton.class); - } + tracker = new ImageLayerIdTrackingSingleton(); + ImageSingletons.add(ImageLayerIdTrackingSingleton.class, tracker); if (ImageLayerBuildingSupport.buildingSharedLayer()) { constantCandidates = new ConcurrentHashMap<>(); @@ -415,7 +416,8 @@ public int[] getRelocationPatches() { } -class ImageLayerIdTrackingSingleton implements LayeredImageSingleton { +@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = ImageLayerIdTrackingSingleton.LayeredCallbacks.class, layeredInstallationKind = Independent.class) +class ImageLayerIdTrackingSingleton { private final Map keyToTrackingInfoMap = new HashMap<>(); final Map> futureKeyToPatchingOffsetsMap = new ConcurrentHashMap<>(); @@ -464,81 +466,80 @@ void registerPatchSite(String futureKey, int heapIndex) { indexes.add(heapIndex); } - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; - } - - private static String futureKeyPatchKey(String key) { - return String.format("futureOffsetPatches:%s", key); - } + static class LayeredCallbacks extends SingletonLayeredCallbacksSupplier { - @Override - public PersistFlags preparePersist(ImageSingletonWriter writer) { - ArrayList priorKeys = new ArrayList<>(); - ArrayList priorIds = new ArrayList<>(); - ArrayList futureKeys = new ArrayList<>(); - ArrayList futureStates = new ArrayList<>(); - ArrayList futureLoaderIds = new ArrayList<>(); - ArrayList futureOffsets = new ArrayList<>(); - - for (var entry : keyToTrackingInfoMap.entrySet()) { - String key = entry.getKey(); - TrackingInfo trackingInfo = entry.getValue(); - if (trackingInfo instanceof PriorTrackingInfo prior) { - priorKeys.add(key); - priorIds.add(prior.constantId()); - } else { - FutureTrackingInfo future = (FutureTrackingInfo) trackingInfo; - futureKeys.add(key); - futureStates.add(future.state().ordinal()); - futureLoaderIds.add(future.loaderId()); - if (future.state() == FutureTrackingInfo.State.Final) { - futureOffsets.add(future.offset()); + @Override + public SingletonTrait getLayeredCallbacksTrait() { + return new SingletonTrait(SingletonTraitKind.LAYERED_CALLBACKS, new SingletonLayeredCallbacks() { + private static String futureKeyPatchKey(String key) { + return String.format("futureOffsetPatches:%s", key); } - writer.writeIntList(futureKeyPatchKey(key), futureKeyToPatchingOffsetsMap.getOrDefault(key, List.of())); - } - } - - writer.writeStringList("priorKeys", priorKeys); - writer.writeIntList("priorIds", priorIds); + @Override + public LayeredImageSingleton.PersistFlags doPersist(ImageSingletonWriter writer, ImageLayerIdTrackingSingleton singleton) { + ArrayList priorKeys = new ArrayList<>(); + ArrayList priorIds = new ArrayList<>(); + ArrayList futureKeys = new ArrayList<>(); + ArrayList futureStates = new ArrayList<>(); + ArrayList futureLoaderIds = new ArrayList<>(); + ArrayList futureOffsets = new ArrayList<>(); + + for (var entry : singleton.keyToTrackingInfoMap.entrySet()) { + String key = entry.getKey(); + TrackingInfo trackingInfo = entry.getValue(); + if (trackingInfo instanceof PriorTrackingInfo prior) { + priorKeys.add(key); + priorIds.add(prior.constantId()); + } else { + FutureTrackingInfo future = (FutureTrackingInfo) trackingInfo; + futureKeys.add(key); + futureStates.add(future.state().ordinal()); + futureLoaderIds.add(future.loaderId()); + if (future.state() == FutureTrackingInfo.State.Final) { + futureOffsets.add(future.offset()); + } + + writer.writeIntList(futureKeyPatchKey(key), singleton.futureKeyToPatchingOffsetsMap.getOrDefault(key, List.of())); + } + } - writer.writeStringList("futureKeys", futureKeys); - writer.writeIntList("futureStates", futureStates); - writer.writeIntList("futureLoaderIds", futureLoaderIds); - writer.writeIntList("futureOffsets", futureOffsets); + writer.writeStringList("priorKeys", priorKeys); + writer.writeIntList("priorIds", priorIds); - return PersistFlags.CREATE; - } + writer.writeStringList("futureKeys", futureKeys); + writer.writeIntList("futureStates", futureStates); + writer.writeIntList("futureLoaderIds", futureLoaderIds); + writer.writeIntList("futureOffsets", futureOffsets); - @SuppressWarnings("unused") - public static Object createFromLoader(ImageSingletonLoader loader) { - var tracker = new ImageLayerIdTrackingSingleton(); + return LayeredImageSingleton.PersistFlags.CALLBACK_ON_REGISTRATION; + } - Iterator priorKeys = loader.readStringList("priorKeys").iterator(); - Iterator priorIds = loader.readIntList("priorIds").iterator(); + @Override + public void onSingletonRegistration(ImageSingletonLoader loader, ImageLayerIdTrackingSingleton singleton) { + Iterator priorKeys = loader.readStringList("priorKeys").iterator(); + Iterator priorIds = loader.readIntList("priorIds").iterator(); - while (priorKeys.hasNext()) { - tracker.registerPriorTrackingInfo(priorKeys.next(), priorIds.next()); - } + while (priorKeys.hasNext()) { + singleton.registerPriorTrackingInfo(priorKeys.next(), priorIds.next()); + } - Iterator futureKeys = loader.readStringList("futureKeys").iterator(); - Iterator futureStates = loader.readIntList("futureStates").iterator(); - Iterator futureLoaderIds = loader.readIntList("futureLoaderIds").iterator(); - Iterator futureOffsets = loader.readIntList("futureOffsets").iterator(); - while (futureKeys.hasNext()) { - String key = futureKeys.next(); - FutureTrackingInfo.State state = FutureTrackingInfo.State.values()[futureStates.next()]; - int loaderId = futureLoaderIds.next(); - int offset = state == FutureTrackingInfo.State.Final ? futureOffsets.next() : INVALID; - tracker.registerFutureTrackingInfo(new FutureTrackingInfo(key, state, loaderId, offset)); - - List offsetsToPatch = loader.readIntList(futureKeyPatchKey(key)); - offsetsToPatch.forEach(heapOffset -> tracker.registerPatchSite(key, heapOffset)); + Iterator futureKeys = loader.readStringList("futureKeys").iterator(); + Iterator futureStates = loader.readIntList("futureStates").iterator(); + Iterator futureLoaderIds = loader.readIntList("futureLoaderIds").iterator(); + Iterator futureOffsets = loader.readIntList("futureOffsets").iterator(); + while (futureKeys.hasNext()) { + String key = futureKeys.next(); + FutureTrackingInfo.State state = FutureTrackingInfo.State.values()[futureStates.next()]; + int loaderId = futureLoaderIds.next(); + int offset = state == FutureTrackingInfo.State.Final ? futureOffsets.next() : INVALID; + singleton.registerFutureTrackingInfo(new FutureTrackingInfo(key, state, loaderId, offset)); + + List offsetsToPatch = loader.readIntList(futureKeyPatchKey(key)); + offsetsToPatch.forEach(heapOffset -> singleton.registerPatchSite(key, heapOffset)); + } + } + }); } - - return tracker; } } 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 a14815b49dae..5331aaf47804 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 @@ -28,7 +28,6 @@ import java.util.ArrayList; import java.util.Collections; -import java.util.EnumSet; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -52,8 +51,14 @@ import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader; import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.core.meta.SharedMethod; +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.c.CGlobalDataFeature; import com.oracle.svm.hosted.image.NativeImage; @@ -61,7 +66,8 @@ import com.oracle.svm.hosted.meta.HostedMethodNameFactory.MethodNameInfo; @AutomaticallyRegisteredImageSingleton(value = DynamicImageLayerInfo.class, onlyWith = BuildingImageLayerPredicate.class) -public class HostedDynamicLayerInfo extends DynamicImageLayerInfo implements LayeredImageSingleton { +@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = HostedDynamicLayerInfo.LayeredCallbacks.class, layeredInstallationKind = Independent.class) +public class HostedDynamicLayerInfo extends DynamicImageLayerInfo { private final CGlobalData cGlobalData; private final Set priorLayerMethodSymbols = new HashSet<>(); private final List libNames; @@ -220,67 +226,76 @@ public Set getPreviousLayerDelayedMethodIds() { } @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; + public int getPreviousMaxTypeId() { + SVMImageLayerLoader loader = HostedImageLayerBuildingSupport.singleton().getLoader(); + return loader.getMaxTypeId(); } @Override - public PersistFlags preparePersist(ImageSingletonWriter writer) { - /* - * When there are multiple shared layers we will need to store the starting code offset of - * each layer. - */ - assert ImageLayerBuildingSupport.buildingInitialLayer() : "This code must be adjusted to support multiple shared layers"; - - /* - * First write out next layer number. - */ - var snapshotBuilder = ((SVMImageLayerWriter.ImageSingletonWriterImpl) writer).getSnapshotBuilder(); - snapshotBuilder.setNextLayerNumber(nextLayerNumber); - - /* - * Next write the start of the code section - */ - writer.writeString("codeSectionStartSymbol", NativeImage.getTextSectionStartSymbol()); - - writer.writeStringList("libNames", libNames); - - Set nextLayerDelayedMethodSymbols = new HashSet<>(previousLayerDelayedMethodSymbols); - nextLayerDelayedMethodSymbols.addAll(delayedMethodSymbols.keySet()); - writer.writeStringList("delayedMethodSymbols", nextLayerDelayedMethodSymbols.stream().toList()); - - Set nextLayerDelayedMethodIds = new HashSet<>(previousLayerDelayedMethodIds); - nextLayerDelayedMethodIds.addAll(delayedMethodIds); - writer.writeIntList("delayedMethodIds", nextLayerDelayedMethodIds.stream().toList()); - - return PersistFlags.CREATE; + public long getPreviousImageHeapEndOffset() { + SVMImageLayerLoader loader = HostedImageLayerBuildingSupport.singleton().getLoader(); + return loader.getImageHeapEndOffset(); } - @SuppressWarnings("unused") - public static Object createFromLoader(ImageSingletonLoader loader) { + static class LayeredCallbacks extends SingletonLayeredCallbacksSupplier { + + @Override + public SingletonTrait getLayeredCallbacksTrait() { + return new SingletonTrait(SingletonTraitKind.LAYERED_CALLBACKS, new SingletonLayeredCallbacks() { + @Override + public LayeredImageSingleton.PersistFlags doPersist(ImageSingletonWriter writer, HostedDynamicLayerInfo singleton) { + /* + * When there are multiple shared layers we will need to store the starting code + * offset of each layer. + */ + assert ImageLayerBuildingSupport.buildingInitialLayer() : "This code must be adjusted to support multiple shared layers"; + + /* + * First write out next layer number. + */ + var snapshotBuilder = ((SVMImageLayerWriter.ImageSingletonWriterImpl) writer).getSnapshotBuilder(); + snapshotBuilder.setNextLayerNumber(singleton.nextLayerNumber); + + /* + * Next write the start of the code section + */ + writer.writeString("codeSectionStartSymbol", NativeImage.getTextSectionStartSymbol()); + + writer.writeStringList("libNames", singleton.libNames); + + Set nextLayerDelayedMethodSymbols = new HashSet<>(singleton.previousLayerDelayedMethodSymbols); + nextLayerDelayedMethodSymbols.addAll(singleton.delayedMethodSymbols.keySet()); + writer.writeStringList("delayedMethodSymbols", nextLayerDelayedMethodSymbols.stream().toList()); + + Set nextLayerDelayedMethodIds = new HashSet<>(singleton.previousLayerDelayedMethodIds); + nextLayerDelayedMethodIds.addAll(singleton.delayedMethodIds); + writer.writeIntList("delayedMethodIds", nextLayerDelayedMethodIds.stream().toList()); + + return LayeredImageSingleton.PersistFlags.CREATE; + } + + @Override + public Class> getSingletonInstantiator() { + return SingletonInstantiator.class; + } + }); + } + } - var snapshotReader = ((SVMImageLayerSingletonLoader.ImageSingletonLoaderImpl) loader).getSnapshotReader(); - int layerNumber = snapshotReader.getNextLayerNumber(); + static class SingletonInstantiator implements SingletonLayeredCallbacks.LayeredSingletonInstantiator { + @Override + public HostedDynamicLayerInfo createFromLoader(ImageSingletonLoader loader) { + var snapshotReader = ((SVMImageLayerSingletonLoader.ImageSingletonLoaderImpl) loader).getSnapshotReader(); + int layerNumber = snapshotReader.getNextLayerNumber(); - String codeSectionStartSymbol = loader.readString("codeSectionStartSymbol"); + String codeSectionStartSymbol = loader.readString("codeSectionStartSymbol"); - var libNames = loader.readStringList("libNames"); + var libNames = loader.readStringList("libNames"); - var previousLayerDelayedMethodSymbols = loader.readStringList("delayedMethodSymbols").stream().collect(Collectors.toUnmodifiableSet()); - var previousLayerDelayedMethodIds = loader.readIntList("delayedMethodIds").stream().collect(Collectors.toUnmodifiableSet()); + var previousLayerDelayedMethodSymbols = loader.readStringList("delayedMethodSymbols").stream().collect(Collectors.toUnmodifiableSet()); + var previousLayerDelayedMethodIds = loader.readIntList("delayedMethodIds").stream().collect(Collectors.toUnmodifiableSet()); - return new HostedDynamicLayerInfo(layerNumber, codeSectionStartSymbol, libNames, previousLayerDelayedMethodSymbols, previousLayerDelayedMethodIds); - } - - @Override - public int getPreviousMaxTypeId() { - SVMImageLayerLoader loader = HostedImageLayerBuildingSupport.singleton().getLoader(); - return loader.getMaxTypeId(); - } - - @Override - public long getPreviousImageHeapEndOffset() { - SVMImageLayerLoader loader = HostedImageLayerBuildingSupport.singleton().getLoader(); - return loader.getImageHeapEndOffset(); + return new HostedDynamicLayerInfo(layerNumber, codeSectionStartSymbol, libNames, previousLayerDelayedMethodSymbols, previousLayerDelayedMethodIds); + } } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/ImageLayerSectionFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/ImageLayerSectionFeature.java index 36cb6d7f5590..fa81a98c9d20 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/ImageLayerSectionFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/ImageLayerSectionFeature.java @@ -30,7 +30,6 @@ import java.nio.ByteOrder; import java.util.Arrays; import java.util.BitSet; -import java.util.EnumSet; import java.util.List; import java.util.Map; @@ -56,8 +55,11 @@ import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; import com.oracle.svm.core.imagelayer.ImageLayerSection; import com.oracle.svm.core.layeredimagesingleton.FeatureSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton; +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 com.oracle.svm.hosted.c.AppLayerCGlobalTracking; import com.oracle.svm.hosted.c.CGlobalDataFeature; @@ -356,7 +358,8 @@ private static void putBitmap(ByteBuffer buffer, BitSet bitset) { buffer.position(buffer.position() + longsCount * Long.BYTES); } - private static class ImageLayerSectionImpl extends ImageLayerSection implements UnsavedSingleton { + @SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class) + private static class ImageLayerSectionImpl extends ImageLayerSection { ImageLayerSectionImpl(CGlobalData initialSectionStart, CGlobalData cachedImageFDs, CGlobalData cachedImageHeapOffsets, CGlobalData cachedImageHeapRelocations) { @@ -380,10 +383,5 @@ public int getEntryOffsetInternal(SectionEntries entry) { case FIRST_SINGLETON -> FIRST_SINGLETON_OFFSET; }; } - - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; - } } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LayeredStaticFieldSupport.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LayeredStaticFieldSupport.java index 627dc54aef7d..b722e3f7b6be 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LayeredStaticFieldSupport.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LayeredStaticFieldSupport.java @@ -28,7 +28,6 @@ import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collections; -import java.util.EnumSet; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -56,8 +55,14 @@ import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader; import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.core.layeredimagesingleton.MultiLayeredImageSingleton; +import com.oracle.svm.core.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.FeatureImpl; import com.oracle.svm.hosted.meta.HostedField; @@ -77,7 +82,8 @@ * layer. */ @AutomaticallyRegisteredImageSingleton(value = LayeredClassInitialization.class, onlyWith = BuildingImageLayerPredicate.class) -public class LayeredStaticFieldSupport extends LayeredClassInitialization implements LayeredImageSingleton { +@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = LayeredStaticFieldSupport.LayeredCallbacks.class, layeredInstallationKind = Independent.class) +public class LayeredStaticFieldSupport extends LayeredClassInitialization { /** * In the initial layer, this refers to fields which must wait until the app layer to be * installed. @@ -397,45 +403,55 @@ void loadAllAppLayerFields() { appLayerFields.forEach(LayeredStaticFieldSupport::getAnalysisField); } - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; - } - - @Override - public PersistFlags preparePersist(ImageSingletonWriter writer) { - writer.writeInt("appLayerPrimitiveFieldStartingOffset", appLayerStaticFieldOffsets.nextPrimitiveField); - writer.writeInt("appLayerObjectFieldStartingOffset", appLayerStaticFieldOffsets.nextObjectField); - - HostedUniverse hUniverse = ((SVMImageLayerWriter.ImageSingletonWriterImpl) writer).getHostedUniverse(); - List knownLocations = new ArrayList<>(); - appLayerFields.forEach(obj -> { - AnalysisField aField = getAnalysisField(obj); - HostedField hField = hUniverse.lookup(aField); - if (hField.hasLocation()) { - assert getAssignmentStatus(aField) == LayerAssignmentStatus.APP_LAYER_DEFERRED; - knownLocations.add(aField.getId()); - } - }); - - writer.writeIntList("appLayerFieldsWithKnownLocations", knownLocations); + static class LayeredCallbacks extends SingletonLayeredCallbacksSupplier { + + @Override + public SingletonTrait getLayeredCallbacksTrait() { + return new SingletonTrait(SingletonTraitKind.LAYERED_CALLBACKS, new SingletonLayeredCallbacks() { + @Override + public LayeredImageSingleton.PersistFlags doPersist(ImageSingletonWriter writer, LayeredStaticFieldSupport singleton) { + writer.writeInt("appLayerPrimitiveFieldStartingOffset", singleton.appLayerStaticFieldOffsets.nextPrimitiveField); + writer.writeInt("appLayerObjectFieldStartingOffset", singleton.appLayerStaticFieldOffsets.nextObjectField); + + HostedUniverse hUniverse = ((SVMImageLayerWriter.ImageSingletonWriterImpl) writer).getHostedUniverse(); + List knownLocations = new ArrayList<>(); + singleton.appLayerFields.forEach(obj -> { + AnalysisField aField = getAnalysisField(obj); + HostedField hField = hUniverse.lookup(aField); + if (hField.hasLocation()) { + assert singleton.getAssignmentStatus(aField) == LayerAssignmentStatus.APP_LAYER_DEFERRED; + knownLocations.add(aField.getId()); + } + }); + + writer.writeIntList("appLayerFieldsWithKnownLocations", knownLocations); + + return LayeredImageSingleton.PersistFlags.CREATE; + } - return PersistFlags.CREATE; + @Override + public Class> getSingletonInstantiator() { + return SingletonInstantiator.class; + } + }); + } } - @SuppressWarnings("unused") - public static Object createFromLoader(ImageSingletonLoader loader) { + static class SingletonInstantiator implements SingletonLayeredCallbacks.LayeredSingletonInstantiator { - Set appLayerFieldsWithKnownLocations = new HashSet<>(); - for (int id : loader.readIntList("appLayerFieldsWithKnownLocations")) { - Supplier aFieldSupplier = () -> HostedImageLayerBuildingSupport.singleton().getLoader().getAnalysisFieldForBaseLayerId(id); - appLayerFieldsWithKnownLocations.add(aFieldSupplier); - } + @Override + public LayeredStaticFieldSupport createFromLoader(ImageSingletonLoader loader) { + Set appLayerFieldsWithKnownLocations = new HashSet<>(); + for (int id : loader.readIntList("appLayerFieldsWithKnownLocations")) { + Supplier aFieldSupplier = () -> HostedImageLayerBuildingSupport.singleton().getLoader().getAnalysisFieldForBaseLayerId(id); + appLayerFieldsWithKnownLocations.add(aFieldSupplier); + } - var appLayerStaticFieldsOffsets = new UniverseBuilder.StaticFieldOffsets(); - appLayerStaticFieldsOffsets.nextPrimitiveField = loader.readInt("appLayerPrimitiveFieldStartingOffset"); - appLayerStaticFieldsOffsets.nextObjectField = loader.readInt("appLayerObjectFieldStartingOffset"); - return new LayeredStaticFieldSupport(Collections.unmodifiableSet(appLayerFieldsWithKnownLocations), appLayerStaticFieldsOffsets); + var appLayerStaticFieldsOffsets = new UniverseBuilder.StaticFieldOffsets(); + appLayerStaticFieldsOffsets.nextPrimitiveField = loader.readInt("appLayerPrimitiveFieldStartingOffset"); + appLayerStaticFieldsOffsets.nextObjectField = loader.readInt("appLayerObjectFieldStartingOffset"); + return new LayeredStaticFieldSupport(Collections.unmodifiableSet(appLayerFieldsWithKnownLocations), appLayerStaticFieldsOffsets); + } } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LoadImageSingletonFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LoadImageSingletonFeature.java index b7c68a923562..6145fe51f42d 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LoadImageSingletonFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LoadImageSingletonFeature.java @@ -29,7 +29,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; -import java.util.EnumSet; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -61,12 +60,18 @@ import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader; import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonSupport; import com.oracle.svm.core.layeredimagesingleton.MultiLayeredAllowNullEntries; import com.oracle.svm.core.layeredimagesingleton.MultiLayeredImageSingleton; import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton; +import com.oracle.svm.core.traits.BuiltinTraits.BuildtimeAccessOnly; +import com.oracle.svm.core.traits.SingletonLayeredCallbacks; +import com.oracle.svm.core.traits.SingletonLayeredCallbacksSupplier; import com.oracle.svm.core.traits.SingletonLayeredInstallationKind; +import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.Independent; +import com.oracle.svm.core.traits.SingletonTrait; +import com.oracle.svm.core.traits.SingletonTraitKind; +import com.oracle.svm.core.traits.SingletonTraits; import com.oracle.svm.core.util.UserError; import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.FeatureImpl; @@ -463,7 +468,8 @@ public int hashCode() { } } -class CrossLayerSingletonMappingInfo extends LoadImageSingletonFactory implements LayeredImageSingleton { +@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = CrossLayerSingletonMappingInfo.LayeredCallbacks.class, layeredInstallationKind = Independent.class) +class CrossLayerSingletonMappingInfo extends LoadImageSingletonFactory { /** * Map of slot infos created in prior layers. */ @@ -494,11 +500,6 @@ class CrossLayerSingletonMappingInfo extends LoadImageSingletonFactory implement CGlobalData singletonTableStart; int referenceSize = 0; - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; - } - CrossLayerSingletonMappingInfo() { priorKeyToSlotInfoMap = Map.of(); priorKeyToSingletonObjectIDsMap = Map.of(); @@ -616,101 +617,117 @@ private static String getKeyClassName(Class clazz) { return clazz.getName(); } - @Override - public PersistFlags preparePersist(ImageSingletonWriter writer) { - /* - * Write out all relevant information. - */ - List keyClasses = new ArrayList<>(); - List slotAssignments = new ArrayList<>(); - List slotKinds = new ArrayList<>(); + static class LayeredCallbacks extends SingletonLayeredCallbacksSupplier { - /* - * Write out information about the assigned slots - */ - for (var info : currentKeyToSlotInfoMap.values()) { - String keyName = getKeyClassName(info.keyClass()); + @Override + public SingletonTrait getLayeredCallbacksTrait() { + return new SingletonTrait(SingletonTraitKind.LAYERED_CALLBACKS, new SingletonLayeredCallbacks() { - keyClasses.add(keyName); - slotAssignments.add(info.slotNum()); - slotKinds.add(info.recordKind().name()); - } + @Override + public LayeredImageSingleton.PersistFlags doPersist(ImageSingletonWriter writer, CrossLayerSingletonMappingInfo singleton) { + /* + * Write out all relevant information. + */ + List keyClasses = new ArrayList<>(); + List slotAssignments = new ArrayList<>(); + List slotKinds = new ArrayList<>(); - writer.writeStringList("keyClasses", keyClasses); - writer.writeIntList("slotAssignments", slotAssignments); - writer.writeStringList("slotKinds", slotKinds); + /* + * Write out information about the assigned slots + */ + for (var info : singleton.currentKeyToSlotInfoMap.values()) { + String keyName = getKeyClassName(info.keyClass()); - /* - * Write out all multi-layered image singletons seen. - */ + keyClasses.add(keyName); + slotAssignments.add(info.slotNum()); + slotKinds.add(info.recordKind().name()); + } - Map, List> currentKeyToSingletonObjectIDsMap = new HashMap<>(priorKeyToSingletonObjectIDsMap); - for (var keyClass : LayeredImageSingletonSupport.singleton().getKeysWithTrait(SingletonLayeredInstallationKind.InstallationKind.MULTI_LAYER)) { - Integer id = layerKeyToObjectIDMap.get(keyClass); - assert id != null : "Missing multiLayerKey " + keyClass; - currentKeyToSingletonObjectIDsMap.compute(keyClass, (_, v) -> { - if (v == null) { - return List.of(id); - } else { - // don't want to affect the list created before - var newList = new ArrayList<>(v); - newList.add(id); - return newList; - } - }); - } + writer.writeStringList("keyClasses", keyClasses); + writer.writeIntList("slotAssignments", slotAssignments); + writer.writeStringList("slotKinds", slotKinds); - List multiLayerKeyNames = new ArrayList<>(); - List multiLayerKeyClasses = new ArrayList<>(); - int count = 0; - for (var entry : currentKeyToSingletonObjectIDsMap.entrySet()) { - String keyClassName = getKeyClassName(entry.getKey()); + /* + * Write out all multi-layered image singletons seen. + */ - String idListKey = String.format("priorObjectIds-%s", count++); - writer.writeIntList(idListKey, entry.getValue()); + Map, List> currentKeyToSingletonObjectIDsMap = new HashMap<>(singleton.priorKeyToSingletonObjectIDsMap); + for (var keyClass : LayeredImageSingletonSupport.singleton().getKeysWithTrait(SingletonLayeredInstallationKind.InstallationKind.MULTI_LAYER)) { + Integer id = singleton.layerKeyToObjectIDMap.get(keyClass); + assert id != null : "Missing multiLayerKey " + keyClass; + currentKeyToSingletonObjectIDsMap.compute(keyClass, (_, v) -> { + if (v == null) { + return List.of(id); + } else { + // don't want to affect the list created before + var newList = new ArrayList<>(v); + newList.add(id); + return newList; + } + }); + } - multiLayerKeyNames.add(idListKey); - multiLayerKeyClasses.add(keyClassName); - } + List multiLayerKeyNames = new ArrayList<>(); + List multiLayerKeyClasses = new ArrayList<>(); + int count = 0; + for (var entry : currentKeyToSingletonObjectIDsMap.entrySet()) { + String keyClassName = getKeyClassName(entry.getKey()); + + String idListKey = String.format("priorObjectIds-%s", count++); + writer.writeIntList(idListKey, entry.getValue()); - writer.writeStringList("multiLayerClassNames", multiLayerKeyClasses); - writer.writeStringList("multiLayerKeyNames", multiLayerKeyNames); + multiLayerKeyNames.add(idListKey); + multiLayerKeyClasses.add(keyClassName); + } + + writer.writeStringList("multiLayerClassNames", multiLayerKeyClasses); + writer.writeStringList("multiLayerKeyNames", multiLayerKeyNames); + + return LayeredImageSingleton.PersistFlags.CREATE; + } - return PersistFlags.CREATE; + @Override + public Class> getSingletonInstantiator() { + return SingletonInstantiator.class; + } + }); + } } - @SuppressWarnings("unused") - public static Object createFromLoader(ImageSingletonLoader loader) { - SVMImageLayerSingletonLoader imageLayerLoader = HostedImageLayerBuildingSupport.singleton().getSingletonLoader(); - Iterator keyClasses = loader.readStringList("keyClasses").iterator(); - Iterator slotAssignments = loader.readIntList("slotAssignments").iterator(); - Iterator slotKinds = loader.readStringList("slotKinds").iterator(); + static class SingletonInstantiator implements SingletonLayeredCallbacks.LayeredSingletonInstantiator { + @Override + public CrossLayerSingletonMappingInfo createFromLoader(ImageSingletonLoader loader) { + SVMImageLayerSingletonLoader imageLayerLoader = HostedImageLayerBuildingSupport.singleton().getSingletonLoader(); + Iterator keyClasses = loader.readStringList("keyClasses").iterator(); + Iterator slotAssignments = loader.readIntList("slotAssignments").iterator(); + Iterator slotKinds = loader.readStringList("slotKinds").iterator(); - Map, SlotInfo> keyClassToSlotInfoMap = new HashMap<>(); + Map, SlotInfo> keyClassToSlotInfoMap = new HashMap<>(); - while (keyClasses.hasNext()) { - String keyName = keyClasses.next(); - Class keyClass = imageLayerLoader.lookupClass(false, keyName); - int slotAssignment = slotAssignments.next(); - SlotRecordKind slotKind = SlotRecordKind.valueOf(slotKinds.next()); + while (keyClasses.hasNext()) { + String keyName = keyClasses.next(); + Class keyClass = imageLayerLoader.lookupClass(false, keyName); + int slotAssignment = slotAssignments.next(); + SlotRecordKind slotKind = SlotRecordKind.valueOf(slotKinds.next()); - Object previous = keyClassToSlotInfoMap.put(keyClass, new SlotInfo(keyClass, slotAssignment, slotKind)); - assert previous == null : previous; - } + Object previous = keyClassToSlotInfoMap.put(keyClass, new SlotInfo(keyClass, slotAssignment, slotKind)); + assert previous == null : previous; + } - Map, List> keyClassToObjectIDListMap = new HashMap<>(); - keyClasses = loader.readStringList("multiLayerClassNames").iterator(); - Iterator idKeyNames = loader.readStringList("multiLayerKeyNames").iterator(); - while (keyClasses.hasNext()) { - String keyClassName = keyClasses.next(); - Class keyClass = imageLayerLoader.lookupClass(false, keyClassName); - String idKeyName = idKeyNames.next(); - var list = loader.readIntList(idKeyName); - assert list != null; - Object previous = keyClassToObjectIDListMap.put(keyClass, list); - assert previous == null; - } + Map, List> keyClassToObjectIDListMap = new HashMap<>(); + keyClasses = loader.readStringList("multiLayerClassNames").iterator(); + Iterator idKeyNames = loader.readStringList("multiLayerKeyNames").iterator(); + while (keyClasses.hasNext()) { + String keyClassName = keyClasses.next(); + Class keyClass = imageLayerLoader.lookupClass(false, keyClassName); + String idKeyName = idKeyNames.next(); + var list = loader.readIntList(idKeyName); + assert list != null; + Object previous = keyClassToObjectIDListMap.put(keyClass, list); + assert previous == null; + } - return new CrossLayerSingletonMappingInfo(Map.copyOf(keyClassToSlotInfoMap), Map.copyOf(keyClassToObjectIDListMap)); + return new CrossLayerSingletonMappingInfo(Map.copyOf(keyClassToSlotInfoMap), Map.copyOf(keyClassToObjectIDListMap)); + } } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/HostedClassLoaderPackageManagement.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/HostedClassLoaderPackageManagement.java index 63e1b2ef02ca..e279b4a5fcb9 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/HostedClassLoaderPackageManagement.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/HostedClassLoaderPackageManagement.java @@ -26,7 +26,6 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.util.EnumSet; import java.util.List; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -46,8 +45,14 @@ import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader; import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.core.reflect.serialize.SerializationSupport; +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.BootLoaderSupport; import com.oracle.svm.hosted.ClassLoaderFeature; @@ -80,7 +85,8 @@ * system class loader to have new packages registered. */ @AutomaticallyRegisteredImageSingleton -public class HostedClassLoaderPackageManagement implements LayeredImageSingleton { +@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = HostedClassLoaderPackageManagement.LayeredCallbacks.class, layeredInstallationKind = Independent.class) +public class HostedClassLoaderPackageManagement { private static final String APP_KEY = "AppPackageNames"; private static final String PLATFORM_KEY = "PlatformPackageNames"; @@ -305,9 +311,21 @@ public void initialize(ClassLoader newAppClassLoader, CrossLayerConstantRegistry registry = newRegistry; } - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; + static class LayeredCallbacks extends SingletonLayeredCallbacksSupplier { + @Override + public SingletonTrait getLayeredCallbacksTrait() { + return new SingletonTrait(SingletonTraitKind.LAYERED_CALLBACKS, new SingletonLayeredCallbacks() { + @Override + public LayeredImageSingleton.PersistFlags doPersist(ImageSingletonWriter writer, HostedClassLoaderPackageManagement singleton) { + return singleton.preparePersist(writer); + } + + @Override + public Class> getSingletonInstantiator() { + return SingletonInstantiator.class; + } + }); + } } private List collectPackageNames(ClassLoader classLoader, Set priorPackageNames) { @@ -323,21 +341,22 @@ private List collectPackageNames(ClassLoader classLoader, Set pr } } - @Override - public LayeredImageSingleton.PersistFlags preparePersist(ImageSingletonWriter writer) { + private LayeredImageSingleton.PersistFlags preparePersist(ImageSingletonWriter writer) { writer.writeStringList(APP_KEY, collectPackageNames(appClassLoader, priorAppPackageNames)); writer.writeStringList(PLATFORM_KEY, collectPackageNames(platformClassLoader, priorPlatformPackageNames)); writer.writeStringList(BOOT_KEY, collectPackageNames(bootClassLoader, priorBootPackageNames)); - return PersistFlags.CREATE; + return LayeredImageSingleton.PersistFlags.CREATE; } - @SuppressWarnings("unused") - public static Object createFromLoader(ImageSingletonLoader loader) { - var appSet = loader.readStringList(APP_KEY).stream().collect(Collectors.toUnmodifiableSet()); - var platformSet = loader.readStringList(PLATFORM_KEY).stream().collect(Collectors.toUnmodifiableSet()); - var bootSet = loader.readStringList(BOOT_KEY).stream().collect(Collectors.toUnmodifiableSet()); + static class SingletonInstantiator implements SingletonLayeredCallbacks.LayeredSingletonInstantiator { + @Override + public HostedClassLoaderPackageManagement createFromLoader(ImageSingletonLoader loader) { + var appSet = loader.readStringList(APP_KEY).stream().collect(Collectors.toUnmodifiableSet()); + var platformSet = loader.readStringList(PLATFORM_KEY).stream().collect(Collectors.toUnmodifiableSet()); + var bootSet = loader.readStringList(BOOT_KEY).stream().collect(Collectors.toUnmodifiableSet()); - return new HostedClassLoaderPackageManagement(appSet, platformSet, bootSet); + return new HostedClassLoaderPackageManagement(appSet, platformSet, bootSet); + } } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationSupport.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationSupport.java index bc9c7581a437..c1be71f16f2b 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationSupport.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationSupport.java @@ -33,7 +33,6 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; -import java.util.EnumSet; import java.util.List; import java.util.SortedMap; import java.util.SortedSet; @@ -57,12 +56,15 @@ import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader; import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.core.option.HostedOptionKey; 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; +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.InterruptImageBuilding; import com.oracle.svm.core.util.VMError; @@ -111,12 +113,8 @@ public static JNIRegistrationSupport singleton() { @Override public void afterRegistration(AfterRegistrationAccess access) { - if (ImageLayerBuildingSupport.firstImageBuild()) { - jniRegistrationSupportSingleton = new JNIRegistrationSupportSingleton(); - ImageSingletons.add(JNIRegistrationSupportSingleton.class, jniRegistrationSupportSingleton); - } else { - jniRegistrationSupportSingleton = JNIRegistrationSupportSingleton.singleton(); - } + jniRegistrationSupportSingleton = new JNIRegistrationSupportSingleton(); + ImageSingletons.add(JNIRegistrationSupportSingleton.class, jniRegistrationSupportSingleton); } @Override @@ -372,32 +370,29 @@ private Path getImageImportLib() { return importLib; } - private static final class JNIRegistrationSupportSingleton implements LayeredImageSingleton { + @SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = JNIRegistrationSupportSingleton.LayeredCallbacks.class, layeredInstallationKind = Independent.class) + private static final class JNIRegistrationSupportSingleton { private final List currentLayerRegisteredLibraries = new CopyOnWriteArrayList<>(); private final List prevLayerRegisteredLibraries = new ArrayList<>(); - public static JNIRegistrationSupportSingleton singleton() { - return ImageSingletons.lookup(JNIRegistrationSupportSingleton.class); - } - - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; - } - - @Override - public PersistFlags preparePersist(ImageSingletonWriter writer) { - var snapshotWriter = ((SVMImageLayerWriter.ImageSingletonWriterImpl) writer).getSnapshotBuilder(); - SVMImageLayerWriter.initStringList(snapshotWriter::initRegisteredJNILibraries, currentLayerRegisteredLibraries.stream()); - return PersistFlags.CREATE; - } - - @SuppressWarnings("unused") - public static Object createFromLoader(ImageSingletonLoader loader) { - JNIRegistrationSupportSingleton singleton = new JNIRegistrationSupportSingleton(); - var snapshotReader = ((SVMImageLayerSingletonLoader.ImageSingletonLoaderImpl) loader).getSnapshotReader(); - CapnProtoAdapters.forEach(snapshotReader.getRegisteredJNILibraries(), singleton.prevLayerRegisteredLibraries::add); - return singleton; + static class LayeredCallbacks extends SingletonLayeredCallbacksSupplier { + @Override + public SingletonTrait getLayeredCallbacksTrait() { + return new SingletonTrait(SingletonTraitKind.LAYERED_CALLBACKS, new SingletonLayeredCallbacks() { + @Override + public LayeredImageSingleton.PersistFlags doPersist(ImageSingletonWriter writer, JNIRegistrationSupportSingleton singleton) { + var snapshotWriter = ((SVMImageLayerWriter.ImageSingletonWriterImpl) writer).getSnapshotBuilder(); + SVMImageLayerWriter.initStringList(snapshotWriter::initRegisteredJNILibraries, singleton.currentLayerRegisteredLibraries.stream()); + return LayeredImageSingleton.PersistFlags.CALLBACK_ON_REGISTRATION; + } + + @Override + public void onSingletonRegistration(ImageSingletonLoader loader, JNIRegistrationSupportSingleton singleton) { + var snapshotReader = ((SVMImageLayerSingletonLoader.ImageSingletonLoaderImpl) loader).getSnapshotReader(); + CapnProtoAdapters.forEach(snapshotReader.getRegisteredJNILibraries(), singleton.prevLayerRegisteredLibraries::add); + } + }); + } } } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jni/JNIAccessFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jni/JNIAccessFeature.java index 8a766087fa49..b0d266768675 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jni/JNIAccessFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jni/JNIAccessFeature.java @@ -31,7 +31,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.EnumSet; import java.util.HashSet; import java.util.IdentityHashMap; import java.util.List; @@ -76,12 +75,13 @@ import com.oracle.svm.core.jni.access.JNIAccessibleMethodDescriptor; import com.oracle.svm.core.jni.access.JNINativeLinkage; import com.oracle.svm.core.jni.access.JNIReflectionDictionary; -import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.core.layeredimagesingleton.MultiLayeredImageSingleton; import com.oracle.svm.core.meta.MethodPointer; import com.oracle.svm.core.option.HostedOptionKey; +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.hosted.ConditionalConfigurationRegistry; @@ -220,8 +220,9 @@ public void afterRegistration(AfterRegistrationAccess arg) { reflectivityFilter = SubstitutionReflectivityFilter.singleton(); } + @SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class) private final class JNIRuntimeAccessibilitySupportImpl extends ConditionalConfigurationRegistry - implements RuntimeJNIAccessSupport, LayeredImageSingleton { + implements RuntimeJNIAccessSupport { @Override public void register(AccessCondition condition, boolean unsafeAllocated, Class clazz) { @@ -290,16 +291,6 @@ public void registerConstructorLookup(AccessCondition condition, Class declar newNegativeMethodLookups.computeIfAbsent(declaringClass, _ -> new HashSet<>()).add(Pair.create("", parameterTypes)); } } - - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; - } - - @Override - public PersistFlags preparePersist(ImageSingletonWriter writer) { - return PersistFlags.NOTHING; - } } @Override diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionDataBuilder.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionDataBuilder.java index d06baed4aadf..57c175fd083d 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionDataBuilder.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionDataBuilder.java @@ -59,7 +59,6 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -73,7 +72,6 @@ import java.util.function.Function; import java.util.stream.Collectors; -import com.oracle.svm.hosted.DeadlockWatchdog; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.dynamicaccess.AccessCondition; import org.graalvm.nativeimage.hosted.RuntimeProxyCreation; @@ -103,12 +101,19 @@ import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader; import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.core.reflect.SubstrateAccessor; import com.oracle.svm.core.reflect.target.ReflectionSubstitutionSupport; +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.ClassLoaderFeature; import com.oracle.svm.hosted.ConditionalConfigurationRegistry; +import com.oracle.svm.hosted.DeadlockWatchdog; import com.oracle.svm.hosted.FeatureImpl.BeforeAnalysisAccessImpl; import com.oracle.svm.hosted.LinkAtBuildTimeSupport; import com.oracle.svm.hosted.annotation.SubstrateAnnotationExtractor; @@ -1451,7 +1456,8 @@ public static void registerField(ReflectionDataBuilder reflectionDataBuilder, bo } @AutomaticallyRegisteredImageSingleton(onlyWith = BuildingImageLayerPredicate.class) - public static class LayeredReflectionDataBuilder implements LayeredImageSingleton { + @SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = LayeredReflectionDataBuilder.LayeredCallbacks.class, layeredInstallationKind = Independent.class) + public static class LayeredReflectionDataBuilder { public static final String METHODS = "methods"; public static final String FIELDS = "fields"; public static final String REFLECTION_DATA_BUILDER = "reflection data builder"; @@ -1496,51 +1502,62 @@ private static boolean isElementRegistered(Map> previousLa return false; } - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; + private static String getClassesKeyName(String element) { + return REFLECTION_DATA_BUILDER_CLASSES + " " + element; } - @Override - public PersistFlags preparePersist(ImageSingletonWriter writer) { - ReflectionDataBuilder reflectionDataBuilder = (ReflectionDataBuilder) ImageSingletons.lookup(RuntimeReflectionSupport.class); - persistRegisteredElements(writer, reflectionDataBuilder.registeredMethods, AnalysisMethod::getId, METHODS); - persistRegisteredElements(writer, reflectionDataBuilder.registeredFields, AnalysisField::getId, FIELDS); - return PersistFlags.CREATE; - } - - private static void persistRegisteredElements(ImageSingletonWriter writer, Map> registeredElements, Function getId, String element) { - List classes = new ArrayList<>(); - for (var entry : registeredElements.entrySet()) { - classes.add(entry.getKey().getId()); - writer.writeIntList(getElementKeyName(element, entry.getKey().getId()), entry.getValue().keySet().stream().map(getId).toList()); - } - writer.writeIntList(getClassesKeyName(element), classes); + private static String getElementKeyName(String element, int typeId) { + return REFLECTION_DATA_BUILDER + " " + element + " " + typeId; } - @SuppressWarnings("unused") - public static Object createFromLoader(ImageSingletonLoader loader) { - var previousLayerRegisteredMethods = loadRegisteredElements(loader, METHODS); - var previousLayerRegisteredFields = loadRegisteredElements(loader, FIELDS); - return new LayeredReflectionDataBuilder(previousLayerRegisteredMethods, previousLayerRegisteredFields); - } + static class LayeredCallbacks extends SingletonLayeredCallbacksSupplier { + + @Override + public SingletonTrait getLayeredCallbacksTrait() { + return new SingletonTrait(SingletonTraitKind.LAYERED_CALLBACKS, new SingletonLayeredCallbacks() { + private static void persistRegisteredElements(ImageSingletonWriter writer, Map> registeredElements, Function getId, String element) { + List classes = new ArrayList<>(); + for (var entry : registeredElements.entrySet()) { + classes.add(entry.getKey().getId()); + writer.writeIntList(getElementKeyName(element, entry.getKey().getId()), entry.getValue().keySet().stream().map(getId).toList()); + } + writer.writeIntList(getClassesKeyName(element), classes); + } + + @Override + public LayeredImageSingleton.PersistFlags doPersist(ImageSingletonWriter writer, LayeredReflectionDataBuilder singleton) { + ReflectionDataBuilder reflectionDataBuilder = (ReflectionDataBuilder) ImageSingletons.lookup(RuntimeReflectionSupport.class); + persistRegisteredElements(writer, reflectionDataBuilder.registeredMethods, AnalysisMethod::getId, METHODS); + persistRegisteredElements(writer, reflectionDataBuilder.registeredFields, AnalysisField::getId, FIELDS); + return LayeredImageSingleton.PersistFlags.CREATE; + } - private static Map> loadRegisteredElements(ImageSingletonLoader loader, String element) { - Map> previousLayerRegisteredElements = new HashMap<>(); - var classes = loader.readIntList(getClassesKeyName(element)); - for (int key : classes) { - var elements = loader.readIntList(getElementKeyName(element, key)).stream().collect(Collectors.toUnmodifiableSet()); - previousLayerRegisteredElements.put(key, elements); + @Override + public Class> getSingletonInstantiator() { + return SingletonInstantiator.class; + } + }); } - return Collections.unmodifiableMap(previousLayerRegisteredElements); - } - private static String getClassesKeyName(String element) { - return REFLECTION_DATA_BUILDER_CLASSES + " " + element; - } + static class SingletonInstantiator implements SingletonLayeredCallbacks.LayeredSingletonInstantiator { - private static String getElementKeyName(String element, int typeId) { - return REFLECTION_DATA_BUILDER + " " + element + " " + typeId; + private static Map> loadRegisteredElements(ImageSingletonLoader loader, String element) { + Map> previousLayerRegisteredElements = new HashMap<>(); + var classes = loader.readIntList(getClassesKeyName(element)); + for (int key : classes) { + var elements = loader.readIntList(getElementKeyName(element, key)).stream().collect(Collectors.toUnmodifiableSet()); + previousLayerRegisteredElements.put(key, elements); + } + return Collections.unmodifiableMap(previousLayerRegisteredElements); + } + + @Override + public LayeredReflectionDataBuilder createFromLoader(ImageSingletonLoader loader) { + var previousLayerRegisteredMethods = loadRegisteredElements(loader, METHODS); + var previousLayerRegisteredFields = loadRegisteredElements(loader, FIELDS); + return new LayeredReflectionDataBuilder(previousLayerRegisteredMethods, previousLayerRegisteredFields); + } + } } } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/LayeredVMThreadLocalCollector.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/LayeredVMThreadLocalCollector.java index 9975c70bff3d..cef3c2668846 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/LayeredVMThreadLocalCollector.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/LayeredVMThreadLocalCollector.java @@ -38,6 +38,13 @@ import com.oracle.svm.core.threadlocal.VMThreadLocalInfo; import com.oracle.svm.core.threadlocal.VMThreadLocalInfos; import com.oracle.svm.core.threadlocal.VMThreadLocalSupport; +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 jdk.graal.compiler.debug.Assertions; @@ -52,7 +59,8 @@ * multi-layered singleton and also {@link VMThreadLocalSupport} to likely be an application layer * only image singleton. */ -public class LayeredVMThreadLocalCollector extends VMThreadLocalCollector implements LayeredImageSingleton { +@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = LayeredVMThreadLocalCollector.LayeredCallbacks.class, layeredInstallationKind = Independent.class) +public class LayeredVMThreadLocalCollector extends VMThreadLocalCollector { record ThreadInfo(int size, int offset) { @@ -117,60 +125,76 @@ public int getOffset(FastThreadLocal threadLocal) { } } - @Override - public PersistFlags preparePersist(ImageSingletonWriter writer) { - /* - * Store the (name, offset, size) tuple of all thread locals. - */ - List threadLocalNames = new ArrayList<>(); - List threadLocalOffsets = new ArrayList<>(); - List threadLocalSizes = new ArrayList<>(); - if (initialLayer) { - for (var threadLocal : getSortedThreadLocalInfos()) { - threadLocalNames.add(threadLocal.name); - threadLocalOffsets.add(threadLocal.offset); - threadLocalSizes.add(threadLocal.sizeInBytes); - } - } else { - for (var entry : threadLocalAssignmentMap.entrySet()) { - threadLocalNames.add(entry.getKey()); - threadLocalOffsets.add(entry.getValue().offset()); - threadLocalSizes.add(entry.getValue().size()); - } + static class LayeredCallbacks extends SingletonLayeredCallbacksSupplier { + @Override + public SingletonTrait getLayeredCallbacksTrait() { + return new SingletonTrait(SingletonTraitKind.LAYERED_CALLBACKS, new SingletonLayeredCallbacks() { + + @Override + public LayeredImageSingleton.PersistFlags doPersist(ImageSingletonWriter writer, LayeredVMThreadLocalCollector singleton) { + /* + * Store the (name, offset, size) tuple of all thread locals. + */ + List threadLocalNames = new ArrayList<>(); + List threadLocalOffsets = new ArrayList<>(); + List threadLocalSizes = new ArrayList<>(); + if (singleton.initialLayer) { + for (var threadLocal : singleton.getSortedThreadLocalInfos()) { + threadLocalNames.add(threadLocal.name); + threadLocalOffsets.add(threadLocal.offset); + threadLocalSizes.add(threadLocal.sizeInBytes); + } + } else { + for (var entry : singleton.threadLocalAssignmentMap.entrySet()) { + threadLocalNames.add(entry.getKey()); + threadLocalOffsets.add(entry.getValue().offset()); + threadLocalSizes.add(entry.getValue().size()); + } + } + + writer.writeStringList("threadLocalNames", threadLocalNames); + writer.writeIntList("threadLocalOffsets", threadLocalOffsets); + writer.writeIntList("threadLocalSizes", threadLocalSizes); + + /* + * Note while it is not strictly necessary to store nextOffset at the moment, if + * in the future we allow multiple layers to define thread locals then this + * information will need to be propagated. + */ + writer.writeInt("nextOffset", singleton.nextOffset); + return LayeredImageSingleton.PersistFlags.CREATE; + } + + @Override + public Class> getSingletonInstantiator() { + return SingletonInstantiator.class; + } + }); } - - writer.writeStringList("threadLocalNames", threadLocalNames); - writer.writeIntList("threadLocalOffsets", threadLocalOffsets); - writer.writeIntList("threadLocalSizes", threadLocalSizes); - - /* - * Note while it is not strictly necessary to store nextOffset at the moment, if in the - * future we allow multiple layers to define thread locals then this information will need - * to be propagated. - */ - writer.writeInt("nextOffset", nextOffset); - return PersistFlags.CREATE; } - @SuppressWarnings("unused") - public static Object createFromLoader(ImageSingletonLoader loader) { - /* - * Load the (name, offset, size) tuple of all thread locals. - */ - HashMap threadLocalAssignmentMap = new HashMap<>(); - Iterator threadLocalNames = loader.readStringList("threadLocalNames").iterator(); - Iterator threadLocalOffsets = loader.readIntList("threadLocalOffsets").iterator(); - Iterator threadLocalSizes = loader.readIntList("threadLocalSizes").iterator(); - - while (threadLocalNames.hasNext()) { - String threadLocalName = threadLocalNames.next(); - int threadLocalOffset = threadLocalOffsets.next(); - int threadLocalSize = threadLocalSizes.next(); - - var previous = threadLocalAssignmentMap.put(threadLocalName, new ThreadInfo(threadLocalSize, threadLocalOffset)); - assert previous == null : previous; - } + static class SingletonInstantiator implements SingletonLayeredCallbacks.LayeredSingletonInstantiator { + + @Override + public LayeredVMThreadLocalCollector createFromLoader(ImageSingletonLoader loader) { + /* + * Load the (name, offset, size) tuple of all thread locals. + */ + HashMap threadLocalAssignmentMap = new HashMap<>(); + Iterator threadLocalNames = loader.readStringList("threadLocalNames").iterator(); + Iterator threadLocalOffsets = loader.readIntList("threadLocalOffsets").iterator(); + Iterator threadLocalSizes = loader.readIntList("threadLocalSizes").iterator(); + + while (threadLocalNames.hasNext()) { + String threadLocalName = threadLocalNames.next(); + int threadLocalOffset = threadLocalOffsets.next(); + int threadLocalSize = threadLocalSizes.next(); + + var previous = threadLocalAssignmentMap.put(threadLocalName, new ThreadInfo(threadLocalSize, threadLocalOffset)); + assert previous == null : previous; + } - return new LayeredVMThreadLocalCollector(Map.copyOf(threadLocalAssignmentMap), loader.readInt("nextOffset")); + return new LayeredVMThreadLocalCollector(Map.copyOf(threadLocalAssignmentMap), loader.readInt("nextOffset")); + } } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/VMThreadLocalCollector.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/VMThreadLocalCollector.java index b5b498ab702c..ae62cb8b84c1 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/VMThreadLocalCollector.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/thread/VMThreadLocalCollector.java @@ -27,7 +27,6 @@ import static com.oracle.svm.core.util.VMError.shouldNotReachHere; import java.util.ArrayList; -import java.util.EnumSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -36,12 +35,13 @@ import com.oracle.svm.core.config.ConfigurationValues; import com.oracle.svm.core.heap.SubstrateReferenceMap; -import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.core.option.HostedOptionKey; import com.oracle.svm.core.threadlocal.FastThreadLocal; import com.oracle.svm.core.threadlocal.VMThreadLocalInfo; +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.ObservableImageHeapMapProvider; import com.oracle.svm.core.util.VMError; @@ -54,7 +54,8 @@ /** * Collects all {@link FastThreadLocal} instances that are actually used by the application. */ -public class VMThreadLocalCollector implements Function, LayeredImageSingleton { +@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = NoLayeredCallbacks.class, layeredInstallationKind = Independent.class) +public class VMThreadLocalCollector implements Function { public static class Options { @Option(help = "Ensure all create ThreadLocals have unique names")// @@ -227,14 +228,4 @@ private static ValueNode unPi(ValueNode n) { } return cur; } - - @Override - public final EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; - } - - @Override - public PersistFlags preparePersist(ImageSingletonWriter writer) { - return PersistFlags.NOTHING; - } }