From 3e11e614d5073dd8f72fa72568c1730f079d2d43 Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Mon, 13 Jan 2025 15:08:53 +0100 Subject: [PATCH] Do not allow ImageSingletons.lookup to be called on MultiLayeredImageSingletons --- .../graal/GenScavengeGCFeature.java | 9 +- .../oracle/svm/core/code/CodeInfoTable.java | 26 ++-- .../oracle/svm/core/code/ImageCodeInfo.java | 2 +- .../core/code/RuntimeMetadataDecoderImpl.java | 3 +- .../core/code/RuntimeMetadataEncoding.java | 6 + .../svm/core/hub/ClassForNameSupport.java | 41 ++++-- .../svm/core/hub/DynamicHubSupport.java | 6 +- .../svm/core/jdk/JavaLangSubstitutions.java | 3 +- .../com/oracle/svm/core/jdk/Resources.java | 11 +- .../svm/core/jdk/StringInternSupport.java | 119 +++++++++++++----- .../jdk/localization/LocalizationSupport.java | 2 +- .../jni/access/JNIReflectionDictionary.java | 5 +- .../LayeredImageSingleton.java | 17 ++- .../LayeredImageSingletonSupport.java | 15 ++- .../MultiLayeredImageSingleton.java | 19 +-- .../NonLayeredImageSingletonFeature.java | 2 +- .../core/reflect/RuntimeMetadataDecoder.java | 3 + .../hotspot/libgraal/LibGraalFeature.java | 2 +- .../GraalGraphObjectReplacer.java | 2 +- .../oracle/svm/hosted/ClassLoaderFeature.java | 2 +- .../svm/hosted/EmbeddedResourceExporter.java | 2 +- .../com/oracle/svm/hosted/FeatureImpl.java | 2 +- .../svm/hosted/HeapBreakdownProvider.java | 4 +- .../hosted/ImageSingletonsSupportImpl.java | 11 +- .../svm/hosted/OpenTypeWorldFeature.java | 2 +- .../oracle/svm/hosted/ProgressReporter.java | 4 +- .../svm/hosted/ProgressReporterFeature.java | 2 +- .../oracle/svm/hosted/ResourcesFeature.java | 28 ++--- .../code/RuntimeMetadataEncoderImpl.java | 2 +- .../hosted/image/NativeImageCodeCache.java | 4 +- .../svm/hosted/image/NativeImageHeap.java | 4 +- .../hosted/image/ObjectGroupHistogram.java | 4 +- .../imagelayer/LoadImageSingletonFeature.java | 12 +- .../svm/hosted/jfr/JfrEventFeature.java | 2 +- .../svm/hosted/jni/JNIAccessFeature.java | 10 +- .../svm/hosted/meta/TypeCheckBuilder.java | 2 +- .../svm/hosted/meta/UniverseBuilder.java | 6 +- .../hosted/reflect/ReflectionDataBuilder.java | 2 +- .../svm/hosted/reflect/ReflectionFeature.java | 2 +- .../SubstrateGraphBuilderPlugins.java | 23 ++-- 40 files changed, 259 insertions(+), 164 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeGCFeature.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeGCFeature.java index 14d45bfd9f64..0fcee811d5d4 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeGCFeature.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeGCFeature.java @@ -61,6 +61,7 @@ import com.oracle.svm.core.jvmstat.PerfDataFeature; import com.oracle.svm.core.jvmstat.PerfDataHolder; import com.oracle.svm.core.jvmstat.PerfManager; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonSupport; import com.oracle.svm.core.os.CommittedMemoryProvider; import com.oracle.svm.core.os.OSCommittedMemoryProvider; @@ -132,19 +133,19 @@ public void beforeAnalysis(BeforeAnalysisAccess access) { access.registerAsUsed(Object[].class); } - private static ImageHeapInfo getImageHeapInfo() { - return ImageSingletons.lookup(ImageHeapInfo.class); + private static ImageHeapInfo getCurrentLayerImageHeapInfo() { + return LayeredImageSingletonSupport.singleton().lookup(ImageHeapInfo.class, false, true); } @Override public void afterAnalysis(AfterAnalysisAccess access) { - ImageHeapLayouter heapLayouter = new ChunkedImageHeapLayouter(getImageHeapInfo(), Heap.getHeap().getImageHeapOffsetInAddressSpace()); + ImageHeapLayouter heapLayouter = new ChunkedImageHeapLayouter(getCurrentLayerImageHeapInfo(), Heap.getHeap().getImageHeapOffsetInAddressSpace()); ImageSingletons.add(ImageHeapLayouter.class, heapLayouter); } @Override public void beforeCompilation(BeforeCompilationAccess access) { - access.registerAsImmutable(getImageHeapInfo()); + access.registerAsImmutable(getCurrentLayerImageHeapInfo()); } @Override diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfoTable.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfoTable.java index 458a250a6bfd..ccd85f946adc 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfoTable.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/CodeInfoTable.java @@ -27,8 +27,9 @@ import java.util.Arrays; import java.util.List; -import jdk.graal.compiler.word.Word; import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.function.CodePointer; import org.graalvm.nativeimage.hosted.Feature; import org.graalvm.word.Pointer; @@ -45,6 +46,7 @@ import com.oracle.svm.core.heap.RestrictHeapAccess; import com.oracle.svm.core.heap.RestrictHeapAccess.Access; import com.oracle.svm.core.heap.VMOperationInfos; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonSupport; import com.oracle.svm.core.layeredimagesingleton.MultiLayeredImageSingleton; import com.oracle.svm.core.log.Log; import com.oracle.svm.core.meta.SharedMethod; @@ -57,12 +59,13 @@ import jdk.graal.compiler.api.replacements.Fold; import jdk.graal.compiler.options.Option; +import jdk.graal.compiler.word.Word; import jdk.vm.ci.code.InstalledCode; /** - * Provides the main entry points to look up metadata for code, either {@link #getImageCodeCache() - * ahead-of-time compiled code in the native image} or {@link CodeInfoTable#getRuntimeCodeCache() - * code compiled at runtime}. + * Provides the main entry points to look up metadata for code, either + * {@link #getImageCodeCacheForLayer(int) ahead-of-time compiled code in the native image} or + * {@link CodeInfoTable#getRuntimeCodeCache() code compiled at runtime}. *

* Users of this class must take special care because code can be invalidated at arbitrary times and * their metadata can be freed, see notes on {@link CodeInfoAccess}. @@ -77,9 +80,14 @@ public static class Options { public static final HostedOptionKey CodeCacheCounters = new HostedOptionKey<>(false); } - @Fold - public static ImageCodeInfo getImageCodeCache() { - return ImageSingletons.lookup(ImageCodeInfo.class); + @Platforms(Platform.HOSTED_ONLY.class) + public static ImageCodeInfo getCurrentLayerImageCodeCache() { + return LayeredImageSingletonSupport.singleton().lookup(ImageCodeInfo.class, false, true); + } + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + public static ImageCodeInfo getImageCodeCacheForLayer(int layerNumber) { + return MultiLayeredImageSingleton.getForLayer(ImageCodeInfo.class, layerNumber); } @Fold @@ -90,7 +98,7 @@ public static RuntimeCodeCache getRuntimeCodeCache() { @Uninterruptible(reason = "Executes during isolate creation.") public static void prepareImageCodeInfo() { // Stored in this class because ImageCodeInfo is immutable - imageCodeInfo = getImageCodeCache().prepareCodeInfo(); + imageCodeInfo = ImageCodeInfo.prepareCodeInfo(); assert imageCodeInfo.notEqual(Word.zero()); } @@ -324,7 +332,7 @@ public void duringSetup(DuringSetupAccess access) { @Override public void afterCompilation(AfterCompilationAccess config) { - ImageCodeInfo imageInfo = CodeInfoTable.getImageCodeCache(); + ImageCodeInfo imageInfo = CodeInfoTable.getCurrentLayerImageCodeCache(); config.registerAsImmutable(imageInfo); config.registerAsImmutable(imageInfo.codeInfoIndex); config.registerAsImmutable(imageInfo.codeInfoEncodings); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/ImageCodeInfo.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/ImageCodeInfo.java index e109288fd855..b718b6ad560e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/ImageCodeInfo.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/ImageCodeInfo.java @@ -84,7 +84,7 @@ public class ImageCodeInfo implements MultiLayeredImageSingleton, UnsavedSinglet } @Uninterruptible(reason = "Executes during isolate creation.") - CodeInfo prepareCodeInfo() { + static CodeInfo prepareCodeInfo() { ImageCodeInfo[] imageCodeInfos = MultiLayeredImageSingleton.getAllLayers(ImageCodeInfo.class); ImageCodeInfoStorage[] runtimeCodeInfos = MultiLayeredImageSingleton.getAllLayers(ImageCodeInfoStorage.class); int size = imageCodeInfos.length; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/RuntimeMetadataDecoderImpl.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/RuntimeMetadataDecoderImpl.java index f2f3a4bdb9ed..c2024cc90723 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/RuntimeMetadataDecoderImpl.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/RuntimeMetadataDecoderImpl.java @@ -37,7 +37,6 @@ import java.util.List; import java.util.function.Function; -import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.impl.InternalPlatform; @@ -279,7 +278,7 @@ public boolean isNegative(int modifiers) { @Override public int getMetadataByteLength() { - return ImageSingletons.lookup(RuntimeMetadataEncoding.class).getEncoding().length; + return RuntimeMetadataEncoding.currentLayer().getEncoding().length; } public static boolean isErrorIndex(int index) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/RuntimeMetadataEncoding.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/RuntimeMetadataEncoding.java index 7ac7c635b684..a8180a022237 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/RuntimeMetadataEncoding.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/RuntimeMetadataEncoding.java @@ -34,6 +34,7 @@ import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton; import com.oracle.svm.core.heap.UnknownObjectField; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonSupport; import com.oracle.svm.core.layeredimagesingleton.MultiLayeredImageSingleton; import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton; @@ -51,6 +52,11 @@ public class RuntimeMetadataEncoding implements MultiLayeredImageSingleton, UnsavedSingleton { @UnknownObjectField(availability = AfterCompilation.class) private byte[] encoding; + @Platforms(Platform.HOSTED_ONLY.class) + public static RuntimeMetadataEncoding currentLayer() { + return LayeredImageSingletonSupport.singleton().lookup(RuntimeMetadataEncoding.class, false, true); + } + public byte[] getEncoding() { return encoding; } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/ClassForNameSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/ClassForNameSupport.java index b78b746918e3..18a05ad417a1 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/ClassForNameSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/ClassForNameSupport.java @@ -30,7 +30,6 @@ import java.util.Objects; import org.graalvm.collections.EconomicMap; -import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platform.HOSTED_ONLY; import org.graalvm.nativeimage.Platforms; @@ -40,6 +39,7 @@ import com.oracle.svm.core.configure.RuntimeConditionSet; import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonSupport; import com.oracle.svm.core.layeredimagesingleton.MultiLayeredImageSingleton; import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton; import com.oracle.svm.core.reflect.MissingReflectionRegistrationUtils; @@ -55,8 +55,13 @@ public void setLibGraalLoader(ClassLoader libGraalLoader) { this.libGraalLoader = libGraalLoader; } - public static ClassForNameSupport singleton() { - return ImageSingletons.lookup(ClassForNameSupport.class); + @Platforms(Platform.HOSTED_ONLY.class) + public static ClassForNameSupport currentLayer() { + return LayeredImageSingletonSupport.singleton().lookup(ClassForNameSupport.class, false, true); + } + + private static ClassForNameSupport[] layeredSingletons() { + return MultiLayeredImageSingleton.getAllLayers(ClassForNameSupport.class); } /** @@ -187,9 +192,13 @@ private static Class forName(String className, ClassLoader classLoader, boole if (className == null) { return null; } - ClassForNameSupport classForNameSupport = singleton(); - Object result = classForNameSupport.getSingletonData(classForNameSupport, MultiLayeredImageSingleton.getAllLayers(ClassForNameSupport.class), - singleton -> singleton.forName0(className, classLoader)); + Object result = null; + for (var singleton : layeredSingletons()) { + result = singleton.forName0(className, classLoader); + if (result != null) { + break; + } + } // Note: for non-predefined classes, we (currently) don't need to check the provided loader // TODO rewrite stack traces (GR-42813) if (result instanceof Class) { @@ -238,9 +247,13 @@ public int count() { public static RuntimeConditionSet getConditionFor(Class jClass) { Objects.requireNonNull(jClass); String jClassName = jClass.getName(); - ClassForNameSupport classForNameSupport = singleton(); - ConditionalRuntimeValue conditionalClass = classForNameSupport.getSingletonData(classForNameSupport, MultiLayeredImageSingleton.getAllLayers(ClassForNameSupport.class), - singleton -> singleton.knownClasses.get(jClassName)); + ConditionalRuntimeValue conditionalClass = null; + for (var singleton : layeredSingletons()) { + conditionalClass = singleton.knownClasses.get(jClassName); + if (conditionalClass != null) { + break; + } + } if (conditionalClass == null) { return RuntimeConditionSet.unmodifiableEmptySet(); } else { @@ -254,9 +267,13 @@ public static RuntimeConditionSet getConditionFor(Class jClass) { */ public static boolean canUnsafeInstantiateAsInstance(DynamicHub hub) { Class clazz = DynamicHub.toClass(hub); - ClassForNameSupport classForNameSupport = singleton(); - RuntimeConditionSet conditionSet = classForNameSupport.getSingletonData(classForNameSupport, MultiLayeredImageSingleton.getAllLayers(ClassForNameSupport.class), - singleton -> singleton.unsafeInstantiatedClasses.get(clazz)); + RuntimeConditionSet conditionSet = null; + for (var singleton : layeredSingletons()) { + conditionSet = singleton.unsafeInstantiatedClasses.get(clazz); + if (conditionSet != null) { + break; + } + } return conditionSet != null && conditionSet.satisfied(); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHubSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHubSupport.java index 661a7e8f88f2..2e713cec114e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHubSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHubSupport.java @@ -26,7 +26,6 @@ import java.util.EnumSet; -import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -39,6 +38,7 @@ import com.oracle.svm.core.heap.UnknownObjectField; import com.oracle.svm.core.heap.UnknownPrimitiveField; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonSupport; import com.oracle.svm.core.layeredimagesingleton.MultiLayeredImageSingleton; import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton; @@ -49,8 +49,8 @@ public final class DynamicHubSupport implements MultiLayeredImageSingleton, Unsa @UnknownObjectField(availability = AfterHostedUniverse.class) private byte[] referenceMapEncoding; @Platforms(Platform.HOSTED_ONLY.class) - public static DynamicHubSupport singleton() { - return ImageSingletons.lookup(DynamicHubSupport.class); + public static DynamicHubSupport currentLayer() { + return LayeredImageSingletonSupport.singleton().lookup(DynamicHubSupport.class, false, true); } @AlwaysInline("Performance") diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaLangSubstitutions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaLangSubstitutions.java index e748403a552d..a2ae1a35151e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaLangSubstitutions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaLangSubstitutions.java @@ -41,7 +41,6 @@ import java.util.function.BooleanSupplier; import java.util.stream.Stream; -import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.hosted.FieldValueTransformer; @@ -171,7 +170,7 @@ final class Target_java_lang_String { @Substitute public String intern() { String thisStr = SubstrateUtil.cast(this, String.class); - return ImageSingletons.lookup(StringInternSupport.class).intern(thisStr); + return StringInternSupport.intern(thisStr); } @AnnotateOriginal diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Resources.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Resources.java index b29510ca02f3..076605a2b065 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Resources.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Resources.java @@ -71,6 +71,7 @@ import com.oracle.svm.core.jdk.resources.CompressedGlobTrie.GlobTrieNode; import com.oracle.svm.core.jdk.resources.CompressedGlobTrie.GlobUtils; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonSupport; import com.oracle.svm.core.layeredimagesingleton.MultiLayeredImageSingleton; import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton; import com.oracle.svm.core.util.ImageHeapMap; @@ -94,8 +95,8 @@ public final class Resources implements MultiLayeredImageSingleton, UnsavedSingl * singleton otherwise */ @Platforms(Platform.HOSTED_ONLY.class) - public static Resources singleton() { - return ImageSingletons.lookup(Resources.class); + public static Resources currentLayer() { + return LayeredImageSingletonSupport.singleton().lookup(Resources.class, false, true); } /** @@ -202,7 +203,7 @@ public static ModuleResourceKey createStorageKey(Module module, String resourceN @Platforms(Platform.HOSTED_ONLY.class) public static Set getIncludedResourcesModules() { - return StreamSupport.stream(singleton().resources.getKeys().spliterator(), false) + return StreamSupport.stream(currentLayer().resources.getKeys().spliterator(), false) .map(ModuleResourceKey::module) .filter(Objects::nonNull) .map(Module::getName) @@ -255,7 +256,7 @@ private void addEntry(Module module, String resourceName, boolean isDirectory, b @Platforms(Platform.HOSTED_ONLY.class) public static void registerResource(String resourceName, InputStream is) { - singleton().registerResource(null, resourceName, is, true); + currentLayer().registerResource(null, resourceName, is, true); } @Platforms(Platform.HOSTED_ONLY.class) @@ -607,7 +608,7 @@ public void afterCompilation(AfterCompilationAccess access) { * of lazily initialized fields. Only the byte[] arrays themselves can be safely made * read-only. */ - for (ConditionalRuntimeValue entry : Resources.singleton().resources()) { + for (ConditionalRuntimeValue entry : Resources.currentLayer().resources()) { var unconditionalEntry = entry.getValueUnconditionally(); if (unconditionalEntry.hasData()) { for (byte[] resource : unconditionalEntry.getData()) { 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 9d42e499a978..88d1e14871c0 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 @@ -33,21 +33,28 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import com.oracle.svm.core.BuildPhaseProvider.AfterHeapLayout; +import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton; +import com.oracle.svm.core.feature.InternalFeature; import com.oracle.svm.core.heap.UnknownObjectField; import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader; import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; +import com.oracle.svm.core.layeredimagesingleton.InitialLayerOnlyImageSingleton; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonSupport; import com.oracle.svm.core.layeredimagesingleton.MultiLayeredImageSingleton; +import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton; import com.oracle.svm.util.ReflectionUtil; @AutomaticallyRegisteredImageSingleton -public final class StringInternSupport implements MultiLayeredImageSingleton { +public final class StringInternSupport implements LayeredImageSingleton { interface SetGenerator { Set generateSet(); @@ -55,24 +62,9 @@ interface SetGenerator { @Platforms(Platform.HOSTED_ONLY.class) public static Field getInternedStringsField() { - return ReflectionUtil.lookupField(StringInternSupport.class, "internedStrings"); + return ReflectionUtil.lookupField(RuntimeInternedStrings.class, "internedStrings"); } - /** The String intern table at run time. */ - private final ConcurrentHashMap internedStrings; - - /** - * The native image contains a lot of interned strings. All Java String literals, and all class - * names, are interned per Java specification. We don't want the memory overhead of an hash - * table entry, so we store them (sorted) in this String[] array. When a string is interned at - * run time, it is added to the real hash map, so we pay the (logarithmic) cost of the array - * access only once per string. - * - * The field is set late during image generation, so the value is not available during static - * analysis and compilation. - */ - @UnknownObjectField(availability = AfterHeapLayout.class) private String[] imageInternedStrings; - @Platforms(Platform.HOSTED_ONLY.class) private Object priorLayersInternedStrings; @Platforms(Platform.HOSTED_ONLY.class) private IdentityHashMap internedStringsIdentityMap; @@ -83,14 +75,13 @@ public StringInternSupport() { } private StringInternSupport(Object obj) { - this.internedStrings = new ConcurrentHashMap<>(16, 0.75f, 1); this.priorLayersInternedStrings = obj; } @Platforms(Platform.HOSTED_ONLY.class) - public void setImageInternedStrings(String[] newImageInternedStrings) { + public static void setImageInternedStrings(String[] newImageInternedStrings) { assert !ImageLayerBuildingSupport.buildingImageLayer(); - this.imageInternedStrings = newImageInternedStrings; + ImageInternedStrings.setImageInternedStrings(newImageInternedStrings); } @SuppressWarnings("unchecked") @@ -121,7 +112,7 @@ public String[] layeredSetImageInternedStrings(Set layerInternedStrings) Arrays.sort(currentLayerInternedStrings); - this.imageInternedStrings = currentLayerInternedStrings; + ImageInternedStrings.setImageInternedStrings(currentLayerInternedStrings); if (ImageLayerBuildingSupport.buildingSharedLayer()) { internedStringsIdentityMap = new IdentityHashMap<>(priorInternedStrings.size() + currentLayerInternedStrings.length); @@ -132,7 +123,7 @@ public String[] layeredSetImageInternedStrings(Set layerInternedStrings) Arrays.stream(currentLayerInternedStrings).forEach(internedString -> internedStringsIdentityMap.put(internedString, internedString)); } - return imageInternedStrings; + return currentLayerInternedStrings; } @Platforms(Platform.HOSTED_ONLY.class) @@ -141,8 +132,8 @@ public IdentityHashMap getInternedStringsIdentityMap() { return internedStringsIdentityMap; } - String intern(String str) { - String result = internedStrings.get(str); + static String intern(String str) { + String result = RuntimeInternedStrings.getInternedStrings().get(str); if (result != null) { return result; } else { @@ -150,27 +141,30 @@ String intern(String str) { } } - private String doIntern(String str) { + private static String doIntern(String str) { String result = str; - StringInternSupport[] layers = MultiLayeredImageSingleton.getAllLayers(StringInternSupport.class); - for (StringInternSupport layer : layers) { - String[] layerImageInternedStrings = layer.imageInternedStrings; + for (ImageInternedStrings layer : MultiLayeredImageSingleton.getAllLayers(ImageInternedStrings.class)) { + String[] layerImageInternedStrings = layer.getImageInternedStrings(); int imageIdx = Arrays.binarySearch(layerImageInternedStrings, str); if (imageIdx >= 0) { result = layerImageInternedStrings[imageIdx]; break; } } - String oldValue = internedStrings.putIfAbsent(result, result); + String oldValue = RuntimeInternedStrings.getInternedStrings().putIfAbsent(result, result); if (oldValue != null) { result = oldValue; } return result; } + public static Object getImageInternedStrings() { + return LayeredImageSingletonSupport.singleton().lookup(ImageInternedStrings.class, false, true); + } + @Override public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.ALL_ACCESS; + return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; } @Override @@ -191,3 +185,68 @@ public static Object createFromLoader(ImageSingletonLoader loader) { return new StringInternSupport(gen); } } + +@AutomaticallyRegisteredImageSingleton +class RuntimeInternedStrings implements InitialLayerOnlyImageSingleton { + + /** The String intern table at run time. */ + final ConcurrentHashMap internedStrings = new ConcurrentHashMap<>(16, 0.75f, 1); + + static ConcurrentHashMap getInternedStrings() { + return ImageSingletons.lookup(RuntimeInternedStrings.class).internedStrings; + } + + @Override + public EnumSet getImageBuilderFlags() { + return LayeredImageSingletonBuilderFlags.RUNTIME_ACCESS_ONLY; + } +} + +@AutomaticallyRegisteredImageSingleton +class ImageInternedStrings implements MultiLayeredImageSingleton, UnsavedSingleton { + + /** + * The native image contains a lot of interned strings. All Java String literals, and all class + * names, are interned per Java specification. We don't want the memory overhead of an hash + * table entry, so we store them (sorted) in this String[] array. When a string is interned at + * run time, it is added to the real hash map, so we pay the (logarithmic) cost of the array + * access only once per string. + * + * The field is set late during image generation, so the value is not available during static + * analysis and compilation. + */ + @UnknownObjectField(availability = AfterHeapLayout.class) private String[] imageInternedStrings; + + @Platforms(Platform.HOSTED_ONLY.class) + static void setImageInternedStrings(String[] newImageInternedStrings) { + var singleton = LayeredImageSingletonSupport.singleton().lookup(ImageInternedStrings.class, false, true); + singleton.imageInternedStrings = newImageInternedStrings; + } + + String[] getImageInternedStrings() { + return imageInternedStrings; + } + + @Override + public EnumSet getImageBuilderFlags() { + return LayeredImageSingletonBuilderFlags.ALL_ACCESS; + } +} + +/** + * Within layered images we must eagerly register {@link RuntimeInternedStrings#internedStrings} as + * accessed. This is because some builder code queries whether it exists and will otherwise omit + * required information from the build. + */ +@AutomaticallyRegisteredFeature +class LayeredStringInternFeature implements InternalFeature { + @Override + public boolean isInConfiguration(IsInConfigurationAccess access) { + return ImageLayerBuildingSupport.buildingImageLayer(); + } + + @Override + public void beforeAnalysis(BeforeAnalysisAccess access) { + access.registerAsAccessed(StringInternSupport.getInternedStringsField()); + } +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/LocalizationSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/LocalizationSupport.java index 5f400ef73cd4..e70cb02214d9 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/LocalizationSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/LocalizationSupport.java @@ -207,7 +207,7 @@ public void registerRequiredReflectionAndResourcesForBundleAndLocale(String base if (bundleClass != null) { registerNullaryConstructor(bundleClass); } - Resources.singleton().registerNegativeQuery(bundleWithLocale.replace('.', '/') + ".properties"); + Resources.currentLayer().registerNegativeQuery(bundleWithLocale.replace('.', '/') + ".properties"); if (jdkBundle) { String otherBundleName = Bundles.toOtherBundleName(baseName, bundleWithLocale, locale); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/access/JNIReflectionDictionary.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/access/JNIReflectionDictionary.java index ef632530708b..73d2ec7563bc 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/access/JNIReflectionDictionary.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/access/JNIReflectionDictionary.java @@ -48,6 +48,7 @@ import com.oracle.svm.core.jni.headers.JNIFieldId; import com.oracle.svm.core.jni.headers.JNIMethodId; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonSupport; import com.oracle.svm.core.layeredimagesingleton.MultiLayeredImageSingleton; import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton; import com.oracle.svm.core.log.Log; @@ -96,8 +97,8 @@ public static void create() { } @Platforms(HOSTED_ONLY.class) - public static JNIReflectionDictionary singleton() { - return ImageSingletons.lookup(JNIReflectionDictionary.class); + public static JNIReflectionDictionary currentLayer() { + return LayeredImageSingletonSupport.singleton().lookup(JNIReflectionDictionary.class, false, true); } private static JNIReflectionDictionary[] layeredSingletons() { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/LayeredImageSingleton.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/LayeredImageSingleton.java index e1c196b21477..df9f871ac55d 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/LayeredImageSingleton.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/LayeredImageSingleton.java @@ -41,15 +41,14 @@ * {@link ImageSingletons#lookup} calls refer to a single singleton which will be created in the * application layer. * - *
  • {@link MultiLayeredImageSingleton}: {@link ImageSingletons#lookup} calls continue to refer to - * the appropriate per layer image singleton, but there is also an additional method - * {@link MultiLayeredImageSingleton#getAllLayers} which returns an array with the image singletons - * corresponding to this key for all layers. The length of this array will always be the total - * number of layers. If a singleton corresponding to this key was not installed in a given layer - * (and this is allowed), then the array will contain null for the given index. See - * {@link MultiLayeredAllowNullEntries} for more details. Within the array, the singletons will be - * arranged so that index [0] corresponds to the singleton originating from the initial layer and - * index [length - 1] holds the singleton from the application layer. See + *
  • {@link MultiLayeredImageSingleton}: {@link ImageSingletons#lookup} should no longer be used. + * Instead, there is the method {@link MultiLayeredImageSingleton#getAllLayers} which returns an + * array with the image singletons corresponding to this key for all layers. The length of this + * array will always be the total number of layers. If a singleton corresponding to this key was not + * installed in a given layer (and this is allowed), then the array will contain null for the given + * index. See {@link MultiLayeredAllowNullEntries} for more details. Within the array, the + * singletons will be arranged so that index [0] corresponds to the singleton originating from the + * initial layer and index [length - 1] holds the singleton from the application layer. See * {@link ImageLayerBuildingSupport} for a description of the different layer names.
  • * * diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/LayeredImageSingletonSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/LayeredImageSingletonSupport.java index 4d5855c72419..3cfb2bd62da9 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/LayeredImageSingletonSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/LayeredImageSingletonSupport.java @@ -24,17 +24,26 @@ */ package com.oracle.svm.core.layeredimagesingleton; -import org.graalvm.nativeimage.ImageSingletons; - import java.util.Collection; +import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; + +@Platforms(Platform.HOSTED_ONLY.class) public interface LayeredImageSingletonSupport { static LayeredImageSingletonSupport singleton() { return ImageSingletons.lookup(LayeredImageSingletonSupport.class); } - T runtimeLookup(Class key); + /** + * This method is intended to be used in special situations during the building process to + * access singletons which (1) are only allowed to be accessed at runtime + * ({@link LayeredImageSingletonBuilderFlags#RUNTIME_ACCESS}) and/or (2) implement + * {@link MultiLayeredImageSingleton}. + */ + T lookup(Class key, boolean accessRuntimeOnly, boolean accessMultiLayer); Collection> getMultiLayeredImageSingletonKeys(); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/MultiLayeredImageSingleton.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/MultiLayeredImageSingleton.java index f70f14d06ca1..3326e89f18f9 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/MultiLayeredImageSingleton.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/MultiLayeredImageSingleton.java @@ -24,13 +24,12 @@ */ package com.oracle.svm.core.layeredimagesingleton; -import java.util.function.Function; - -import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; import com.oracle.svm.core.util.VMError; public interface MultiLayeredImageSingleton extends LayeredImageSingleton { + int UNKNOWN_LAYER_NUMBER = 0; + /** * Returns an array containing the image singletons installed for {@code key} within all layers. * See {@link LayeredImageSingleton} for full explanation. @@ -49,18 +48,4 @@ static T[] getAllLayers(Class key) { static T getForLayer(Class key, int index) { throw VMError.shouldNotReachHere("This can only be called during runtime"); } - - default U getSingletonData(T singleton, T[] singletons, Function getSingletonDataFunction) { - if (ImageLayerBuildingSupport.buildingImageLayer()) { - for (var layerSingleton : singletons) { - U result = getSingletonDataFunction.apply(layerSingleton); - if (result != null) { - return result; - } - } - return null; - } else { - return getSingletonDataFunction.apply(singleton); - } - } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/NonLayeredImageSingletonFeature.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/NonLayeredImageSingletonFeature.java index fa31b4a3ec90..0e48b8157f70 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/NonLayeredImageSingletonFeature.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/NonLayeredImageSingletonFeature.java @@ -67,7 +67,7 @@ public boolean isInConfiguration(Feature.IsInConfigurationAccess access) { @Override public void registerInvocationPlugins(Providers providers, GraphBuilderConfiguration.Plugins plugins, ParsingReason reason) { Function, Object> lookupMultiLayeredImageSingleton = (key) -> { - Object singleton = LayeredImageSingletonSupport.singleton().runtimeLookup(key); + Object singleton = LayeredImageSingletonSupport.singleton().lookup(key, true, true); boolean conditions = singleton.getClass().equals(key) && singleton instanceof MultiLayeredImageSingleton multiLayerSingleton && multiLayerSingleton.getImageBuilderFlags().contains(LayeredImageSingletonBuilderFlags.RUNTIME_ACCESS); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/RuntimeMetadataDecoder.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/RuntimeMetadataDecoder.java index 843bc490b14b..674055e7dac0 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/RuntimeMetadataDecoder.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/RuntimeMetadataDecoder.java @@ -32,6 +32,8 @@ import java.lang.reflect.RecordComponent; import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; import com.oracle.svm.core.hub.DynamicHub; @@ -70,6 +72,7 @@ public interface RuntimeMetadataDecoder { boolean isNegative(int modifiers); + @Platforms(Platform.HOSTED_ONLY.class) int getMetadataByteLength(); class ElementDescriptor { diff --git a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalFeature.java b/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalFeature.java index cbf743852801..6e80301d3a26 100644 --- a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalFeature.java +++ b/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalFeature.java @@ -186,7 +186,7 @@ public void afterRegistration(AfterRegistrationAccess access) { libGraalClassLoader = createHostedLibGraalClassLoader(access); loader = libGraalClassLoader.getClassLoader(); - ImageSingletons.lookup(ClassForNameSupport.class).setLibGraalLoader(loader); + ClassForNameSupport.currentLayer().setLibGraalLoader(loader); buildTimeClass = loadClassOrFail("jdk.graal.compiler.hotspot.libgraal.BuildTime"); diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/GraalGraphObjectReplacer.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/GraalGraphObjectReplacer.java index fdf914682b3c..5274351b5827 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/GraalGraphObjectReplacer.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/GraalGraphObjectReplacer.java @@ -133,7 +133,7 @@ public GraalGraphObjectReplacer(AnalysisUniverse aUniverse, SubstrateProviders s this.aUniverse = aUniverse; this.sProviders = sProviders; this.universeFactory = universeFactory; - this.imageCodeInfo = CodeInfoTable.getImageCodeCache(); + this.imageCodeInfo = CodeInfoTable.getCurrentLayerImageCodeCache(); this.stringTable = HostedStringDeduplication.singleton(); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ClassLoaderFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ClassLoaderFeature.java index 78ae580dd4b4..7547acc7b334 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ClassLoaderFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ClassLoaderFeature.java @@ -124,7 +124,7 @@ public void duringSetup(DuringSetupAccess access) { LibGraalClassLoaderBase libGraalLoader = ((DuringSetupAccessImpl) access).imageClassLoader.classLoaderSupport.getLibGraalLoader(); if (libGraalLoader != null) { ClassLoader libGraalClassLoader = libGraalLoader.getClassLoader(); - ClassForNameSupport.singleton().setLibGraalLoader(libGraalClassLoader); + ClassForNameSupport.currentLayer().setLibGraalLoader(libGraalClassLoader); ClassLoader runtimeLibGraalClassLoader = libGraalLoader.getRuntimeClassLoader(); if (runtimeLibGraalClassLoader != null) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/EmbeddedResourceExporter.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/EmbeddedResourceExporter.java index d406c63fc895..91fe00b77d9d 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/EmbeddedResourceExporter.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/EmbeddedResourceExporter.java @@ -99,7 +99,7 @@ private static List getResourceReportEntryList(ConcurrentHa } List resourceInfoList = new ArrayList<>(); - Resources.singleton().forEachResource((key, value) -> { + Resources.currentLayer().forEachResource((key, value) -> { Module module = key.module(); String resourceName = key.resource(); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/FeatureImpl.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/FeatureImpl.java index f08787c42a03..3632ffe75569 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/FeatureImpl.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/FeatureImpl.java @@ -366,7 +366,7 @@ public BeforeAnalysisAccessImpl(FeatureHandler featureHandler, ImageClassLoader this.nativeLibraries = nativeLibraries; this.concurrentReachabilityHandlers = SubstrateOptions.RunReachabilityHandlersConcurrently.getValue(bb.getOptions()); this.reachabilityHandler = concurrentReachabilityHandlers ? ConcurrentReachabilityHandler.singleton() : ReachabilityHandlerFeature.singleton(); - this.classForNameSupport = ClassForNameSupport.singleton(); + this.classForNameSupport = ClassForNameSupport.currentLayer(); } public NativeLibraries getNativeLibraries() { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HeapBreakdownProvider.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HeapBreakdownProvider.java index 9928f6235ae7..7e9ed3f0eb84 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HeapBreakdownProvider.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HeapBreakdownProvider.java @@ -150,7 +150,7 @@ protected void calculate(BeforeImageWriteAccessImpl access) { addEntry(entries, byteArrayEntry, new HeapBreakdownEntry(BYTE_ARRAY_PREFIX + "java.lang.String"), stringByteArrayTotalSize, stringByteArrayTotalCount); } /* Extract byte[] for code info. */ - List codeInfoByteArrayLengths = CodeInfoTable.getImageCodeCache().getTotalByteArrayLengths(); + List codeInfoByteArrayLengths = CodeInfoTable.getCurrentLayerImageCodeCache().getTotalByteArrayLengths(); long codeInfoSize = codeInfoByteArrayLengths.stream().map(l -> objectLayout.getArraySize(JavaKind.Byte, l, true)).reduce(0L, Long::sum); addEntry(entries, byteArrayEntry, new HeapBreakdownEntry(BYTE_ARRAY_PREFIX, "code metadata", "#glossary-code-metadata"), codeInfoSize, codeInfoByteArrayLengths.size()); /* Extract byte[] for metadata. */ @@ -165,7 +165,7 @@ protected void calculate(BeforeImageWriteAccessImpl access) { /* Extract byte[] for resources. */ long resourcesByteArraySize = 0; int resourcesByteArrayCount = 0; - for (ConditionalRuntimeValue resourceList : Resources.singleton().resources()) { + for (ConditionalRuntimeValue resourceList : Resources.currentLayer().resources()) { if (resourceList.getValueUnconditionally().hasData()) { for (byte[] resource : resourceList.getValueUnconditionally().getData()) { resourcesByteArraySize += objectLayout.getArraySize(JavaKind.Byte, resource.length, true); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageSingletonsSupportImpl.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageSingletonsSupportImpl.java index 2cb9a59b6476..3599c60c85fe 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageSingletonsSupportImpl.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageSingletonsSupportImpl.java @@ -56,12 +56,12 @@ public void add(Class key, T value) { @Override public T lookup(Class key) { - return HostedManagement.getAndAssertExists().doLookup(key, false); + return HostedManagement.getAndAssertExists().doLookup(key, false, false); } @Override - public T runtimeLookup(Class key) { - return HostedManagement.getAndAssertExists().doLookup(key, true); + public T lookup(Class key, boolean accessRuntimeOnly, boolean accessMultiLayer) { + return HostedManagement.getAndAssertExists().doLookup(key, accessRuntimeOnly, accessMultiLayer); } @Override @@ -249,7 +249,7 @@ void freezeMultiLayeredImageSingletons() { multiLayeredImageSingletonKeys = Set.copyOf(multiLayeredImageSingletonKeys); } - T doLookup(Class key, boolean stripRuntimeOnly) { + T doLookup(Class key, boolean stripRuntimeOnly, boolean allowMultiLayered) { checkKey(key); Object result = configObjects.get(key); if (result == null) { @@ -264,6 +264,9 @@ T doLookup(Class key, boolean stripRuntimeOnly) { result = wrapper.wrappedObject(); } + if (!allowMultiLayered && result instanceof MultiLayeredImageSingleton) { + throw UserError.abort("Forbidden lookup of MultiLayeredImageSingleton. Use LayeredImageSingletonSupport.lookup if really necessary. Key: %s, object %s", key, result); + } return key.cast(result); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/OpenTypeWorldFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/OpenTypeWorldFeature.java index cd8fb533cad7..666492ca80f4 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/OpenTypeWorldFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/OpenTypeWorldFeature.java @@ -220,7 +220,7 @@ public PersistFlags preparePersist(ImageSingletonWriter writer) { */ var typeIdentifierIds = identifierToTypeInfo.keySet().stream().sorted().toList(); writer.writeIntList("typeIdentifierIds", typeIdentifierIds); - writer.writeInt("maxTypeID", DynamicHubSupport.singleton().getMaxTypeId()); + writer.writeInt("maxTypeID", DynamicHubSupport.currentLayer().getMaxTypeId()); for (int identifierID : typeIdentifierIds) { var typeInfo = identifierToTypeInfo.get(identifierID); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporter.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporter.java index 9355e699419d..8a06dbf129b3 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporter.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporter.java @@ -521,7 +521,7 @@ private void printAnalysisStatistics(AnalysisUniverse universe, Collection EmbeddedResourcesInfo.singleton().declareResourceAsRegistered(module, resourcePath, uri.toString(), origin)); } } catch (IOException e) { - Resources.singleton().registerIOException(module, resourcePath, e, LinkAtBuildTimeSupport.singleton().packageOrClassAtBuildTime(resourcePath)); + Resources.currentLayer().registerIOException(module, resourcePath, e, LinkAtBuildTimeSupport.singleton().packageOrClassAtBuildTime(resourcePath)); } } @@ -344,7 +344,7 @@ private void processResourceFromClasspath(String resourcePath, Object origin) { boolean isDirectory = ResourcesUtils.resourceIsDirectory(url, fromJar); if (isDirectory) { String content = ResourcesUtils.getDirectoryContent(fromJar ? url.toString() : Paths.get(url.toURI()).toString(), fromJar); - Resources.singleton().registerDirectoryResource(null, resourcePath, content, fromJar); + Resources.currentLayer().registerDirectoryResource(null, resourcePath, content, fromJar); } else { InputStream is = url.openStream(); registerResource(null, resourcePath, fromJar, is); @@ -353,7 +353,7 @@ private void processResourceFromClasspath(String resourcePath, Object origin) { String source = ResourcesUtils.getResourceSource(url, resourcePath, fromJar); EmbeddedResourcesInfo.singleton().declareResourceAsRegistered(null, resourcePath, source, origin); } catch (IOException e) { - Resources.singleton().registerIOException(null, resourcePath, e, LinkAtBuildTimeSupport.singleton().packageOrClassAtBuildTime(resourcePath)); + Resources.currentLayer().registerIOException(null, resourcePath, e, LinkAtBuildTimeSupport.singleton().packageOrClassAtBuildTime(resourcePath)); return; } catch (URISyntaxException e) { throw VMError.shouldNotReachHere("resourceIsDirectory for resourcePath " + resourcePath + " failed", e); @@ -363,11 +363,11 @@ private void processResourceFromClasspath(String resourcePath, Object origin) { private void registerResource(Module module, String resourcePath, boolean fromJar, InputStream is) { if (is == null) { - Resources.singleton().registerNegativeQuery(module, resourcePath); + Resources.currentLayer().registerNegativeQuery(module, resourcePath); return; } - Resources.singleton().registerResource(module, resourcePath, is, fromJar); + Resources.currentLayer().registerResource(module, resourcePath, is, fromJar); try { is.close(); @@ -418,7 +418,7 @@ public void beforeAnalysis(BeforeAnalysisAccess a) { .stream() .map(entry -> new CompressedGlobTrie.GlobWithInfo<>(entry.pattern(), new ConditionWithOrigin(entry.condition(), entry.origin()))).toList(); GlobTrieNode trie = CompressedGlobTrie.CompressedGlobTrieBuilder.build(patternsWithInfo); - Resources.singleton().setResourcesTrieRoot(trie); + Resources.currentLayer().setResourcesTrieRoot(trie); /* * GR-58701: The SVM core is currently not included in the base layer of a Layered Image. @@ -564,7 +564,7 @@ public List isIncluded(Module module, String resourceName, private static List getConditionsFromGlobTrie(Module module, String resourceName) { String pattern = GlobUtils.transformToTriePath(resourceName, module == null ? "" : module.getName()); - List types = CompressedGlobTrie.getHostedOnlyContentIfMatched(Resources.singleton().getResourcesTrieRoot(), pattern); + List types = CompressedGlobTrie.getHostedOnlyContentIfMatched(Resources.currentLayer().getResourcesTrieRoot(), pattern); if (types == null) { return Collections.emptyList(); } @@ -586,17 +586,17 @@ public void addResourceConditionally(Module module, String resourceName, Configu @Override public void registerIOException(Module module, String resourceName, IOException e, boolean linkAtBuildTime) { - Resources.singleton().registerIOException(module, resourceName, e, linkAtBuildTime); + Resources.currentLayer().registerIOException(module, resourceName, e, linkAtBuildTime); } @Override public void registerNegativeQuery(Module module, String resourceName) { EmbeddedResourcesInfo.singleton().declareResourceAsRegistered(module, resourceName, "", ""); - Resources.singleton().registerNegativeQuery(module, resourceName); + Resources.currentLayer().registerNegativeQuery(module, resourceName); } public void registerIncludePattern(ConfigurationCondition condition, String module, String pattern) { - registerConditionalConfiguration(condition, cnd -> Resources.singleton().registerIncludePattern(cnd, module, pattern)); + registerConditionalConfiguration(condition, cnd -> Resources.currentLayer().registerIncludePattern(cnd, module, pattern)); } } @@ -648,7 +648,7 @@ public void afterAnalysis(AfterAnalysisAccess access) { } /* prepare resources GlobTrie for runtime */ - GlobTrieNode root = Resources.singleton().getResourcesTrieRoot(); + GlobTrieNode root = Resources.currentLayer().getResourcesTrieRoot(); CompressedGlobTrie.removeNodes(root, (conditionWithOrigin) -> !access.isReachable(conditionWithOrigin.condition().getType())); CompressedGlobTrie.finalize(root); } 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 79c3e7749295..2e03cb18df48 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 @@ -865,7 +865,7 @@ private static int addEncodedElement(UnsafeArrayTypeWriter buf, byte[] encoding) private static void install(UnsafeArrayTypeWriter encodingBuffer) { int encodingSize = TypeConversion.asS4(encodingBuffer.getBytesWritten()); byte[] dataEncoding = new byte[encodingSize]; - ImageSingletons.lookup(RuntimeMetadataEncoding.class).setEncoding(encodingBuffer.toArray(dataEncoding)); + RuntimeMetadataEncoding.currentLayer().setEncoding(encodingBuffer.toArray(dataEncoding)); } private static boolean anySet(int... indices) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageCodeCache.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageCodeCache.java index 80a6dbd63fea..349bc127e2f6 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageCodeCache.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageCodeCache.java @@ -49,7 +49,6 @@ import java.util.Set; import java.util.stream.Collectors; -import jdk.graal.compiler.word.Word; import org.graalvm.collections.Pair; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; @@ -114,6 +113,7 @@ import jdk.graal.compiler.core.common.type.CompressibleConstant; import jdk.graal.compiler.debug.DebugContext; import jdk.graal.compiler.options.Option; +import jdk.graal.compiler.word.Word; import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.code.BytecodePosition; import jdk.vm.ci.code.site.Call; @@ -529,7 +529,7 @@ protected void buildRuntimeMetadata(DebugContext debug, SnippetReflectionProvide protected HostedImageCodeInfo installCodeInfo(SnippetReflectionProvider snippetReflection, CFunctionPointer firstMethod, UnsignedWord codeSize, CodeInfoEncoder codeInfoEncoder, RuntimeMetadataEncoder runtimeMetadataEncoder, DeadlockWatchdog watchdog) { - HostedImageCodeInfo imageCodeInfo = CodeInfoTable.getImageCodeCache().getHostedImageCodeInfo(); + HostedImageCodeInfo imageCodeInfo = CodeInfoTable.getCurrentLayerImageCodeCache().getHostedImageCodeInfo(); codeInfoEncoder.encodeAllAndInstall(imageCodeInfo, new HostedInstantReferenceAdjuster(snippetReflection), watchdog::recordActivity); runtimeMetadataEncoder.encodeAllAndInstall(); imageCodeInfo.setCodeStart(firstMethod); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageHeap.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageHeap.java index 873876286db0..e00e523ed567 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageHeap.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageHeap.java @@ -232,7 +232,7 @@ public void addTrailingObjects() { processAddObjectWorklist(); HostedField hostedField = hMetaAccess.optionalLookupJavaField(StringInternSupport.getInternedStringsField()); - boolean usesInternedStrings = hostedField != null && hostedField.isAccessed(); + boolean usesInternedStrings = hostedField != null && hostedField.isReachable(); if (usesInternedStrings) { /* * Ensure that the hub of the String[] array (used for the interned objects) is written. @@ -257,7 +257,7 @@ public void addTrailingObjects() { } else { imageInternedStrings = internedStrings.keySet().toArray(new String[0]); Arrays.sort(imageInternedStrings); - ImageSingletons.lookup(StringInternSupport.class).setImageInternedStrings(imageInternedStrings); + StringInternSupport.setImageInternedStrings(imageInternedStrings); } /* Manually snapshot the interned strings array. */ aUniverse.getHeapScanner().rescanObject(imageInternedStrings, OtherReason.LATE_SCAN); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/ObjectGroupHistogram.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/ObjectGroupHistogram.java index c9b93c356121..5e14858adb30 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/ObjectGroupHistogram.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/ObjectGroupHistogram.java @@ -105,8 +105,8 @@ private void doPrint() { * order in which types are prcessed matters. */ processType(DynamicHub.class, "DynamicHub", true, null, ObjectGroupHistogram::filterDynamicHubField); - processObject(NonmovableArrays.getHostedArray(DynamicHubSupport.singleton().getReferenceMapEncoding()), "DynamicHub", true, null, null); - processObject(CodeInfoTable.getImageCodeCache(), "ImageCodeInfo", true, ObjectGroupHistogram::filterCodeInfoObjects, null); + processObject(NonmovableArrays.getHostedArray(DynamicHubSupport.currentLayer().getReferenceMapEncoding()), "DynamicHub", true, null, null); + processObject(CodeInfoTable.getCurrentLayerImageCodeCache(), "ImageCodeInfo", true, ObjectGroupHistogram::filterCodeInfoObjects, null); processObject(readTruffleRuntimeCompilationSupportField("graphEncoding"), "CompressedGraph", true, ObjectGroupHistogram::filterGraalSupportObjects, null); processObject(readTruffleRuntimeCompilationSupportField("graphObjects"), "CompressedGraph", true, ObjectGroupHistogram::filterGraalSupportObjects, null); 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 92b2aa2e4536..6b8699227754 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 @@ -207,7 +207,7 @@ public void processRegisteredSingletons(AnalysisUniverse universe) { * accessed via a multi-layer lookup in a subsequent layer, so they must be installed in * the heap. */ - Object[] multiLayeredSingletons = LayeredImageSingletonSupport.singleton().getMultiLayeredImageSingletonKeys().stream().map(layeredImageSingletonSupport::runtimeLookup).toArray(); + Object[] multiLayeredSingletons = layeredImageSingletonSupport.getMultiLayeredImageSingletonKeys().stream().map(key -> layeredImageSingletonSupport.lookup(key, true, true)).toArray(); if (multiLayeredSingletons.length != 0) { multiLayerEmbeddedRootsRegistration.accept(multiLayeredSingletons); } @@ -228,7 +228,7 @@ public void processRegisteredSingletons(AnalysisUniverse universe) { * ensure their types are part of the current analysis. */ Class key = slotInfo.keyClass(); - var singleton = layeredImageSingletonSupport.runtimeLookup(key); + var singleton = layeredImageSingletonSupport.lookup(key, true, false); assert singleton.getClass().equals(key) : String.format("We currently require %s to match their key. Key %s, Singleton: %s", ApplicationLayerOnlyImageSingleton.class, key, singleton); applicationLayerEmbeddedRoots.add(singleton); @@ -240,7 +240,7 @@ public void processRegisteredSingletons(AnalysisUniverse universe) { */ Class key = slotInfo.keyClass(); if (ImageSingletons.contains(key)) { - multiLayerEmbeddedRoots.add(layeredImageSingletonSupport.runtimeLookup(key)); + multiLayerEmbeddedRoots.add(layeredImageSingletonSupport.lookup(key, true, true)); } else { checkAllowNullEntries(key); } @@ -308,7 +308,7 @@ ImageHeapObjectArray createMultiLayerArray(Class key, AnalysisType arrayType, // next install current singleton if (ImageSingletons.contains(key)) { - var singleton = LayeredImageSingletonSupport.singleton().runtimeLookup(key); + var singleton = LayeredImageSingletonSupport.singleton().lookup(key, true, true); JavaConstant singletonConstant = snippetReflectionProvider.forObject(singleton); installElement.accept(singletonConstant, layerInfo.layerNumber); } @@ -356,7 +356,7 @@ private void addInitialObjects(NativeImageHeap heap, HostedUniverse hUniverse) { */ LayeredImageSingletonSupport layeredImageSingletonSupport = LayeredImageSingletonSupport.singleton(); for (var keyClass : layeredImageSingletonSupport.getMultiLayeredImageSingletonKeys()) { - var singleton = layeredImageSingletonSupport.runtimeLookup(keyClass); + var singleton = layeredImageSingletonSupport.lookup(keyClass, true, true); ImageHeapConstant singletonConstant = (ImageHeapConstant) hUniverse.getSnippetReflection().forObject(singleton); heap.addConstant(singletonConstant, false, addReason); int id = ImageHeapConstant.getConstantID(singletonConstant); @@ -373,7 +373,7 @@ private void addInitialObjects(NativeImageHeap heap, HostedUniverse hUniverse) { /* * Need to install the singleton. */ - var singleton = layeredImageSingletonSupport.runtimeLookup(slotInfo.keyClass()); + var singleton = layeredImageSingletonSupport.lookup(slotInfo.keyClass(), true, false); JavaConstant singletonConstant = hUniverse.getSnippetReflection().forObject(singleton); heap.addConstant(singletonConstant, false, addReason); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jfr/JfrEventFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jfr/JfrEventFeature.java index 89e5a0d46dfe..92b93efbbc55 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jfr/JfrEventFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jfr/JfrEventFeature.java @@ -117,7 +117,7 @@ public Object transform(Object receiver, Object originalValue) { @Override public void beforeCompilation(BeforeCompilationAccess a) { // Reserve slot 0 for error-catcher. - int mapSize = DynamicHubSupport.singleton().getMaxTypeId() + 1; + int mapSize = DynamicHubSupport.currentLayer().getMaxTypeId() + 1; // Create trace-ID map with fixed size. ImageSingletons.lookup(JfrTraceIdMap.class).initialize(mapSize); 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 f5171f57636b..082309f51dd3 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 @@ -393,7 +393,7 @@ public void duringAnalysis(DuringAnalysisAccess a) { }); newNegativeFieldLookups.clear(); - JNIReflectionDictionary.singleton().addLinkages(newLinkages); + JNIReflectionDictionary.currentLayer().addLinkages(newLinkages); newLinkages.clear(); access.requireAnalysisIteration(); @@ -406,7 +406,7 @@ private static JNIAccessibleClass addClass(Class classObj, DuringAnalysisAcce if (SubstitutionReflectivityFilter.shouldExclude(classObj, access.getMetaAccess(), access.getUniverse())) { return null; } - return JNIReflectionDictionary.singleton().addClassIfAbsent(classObj, c -> { + return JNIReflectionDictionary.currentLayer().addClassIfAbsent(classObj, c -> { AnalysisType analysisClass = access.getMetaAccess().lookupJavaType(classObj); if (analysisClass.isInterface() || (analysisClass.isInstanceClass() && analysisClass.isAbstract())) { analysisClass.registerAsReachable("is accessed via JNI"); @@ -418,7 +418,7 @@ private static JNIAccessibleClass addClass(Class classObj, DuringAnalysisAcce } private static void addNegativeClassLookup(String className) { - JNIReflectionDictionary.singleton().addNegativeClassLookupIfAbsent(className); + JNIReflectionDictionary.currentLayer().addNegativeClassLookupIfAbsent(className); } public void addMethod(Executable method, DuringAnalysisAccessImpl access) { @@ -532,7 +532,7 @@ public void afterAnalysis(AfterAnalysisAccess access) { int numClasses = 0; int numFields = 0; int numMethods = 0; - for (JNIAccessibleClass clazz : JNIReflectionDictionary.singleton().getClasses()) { + for (JNIAccessibleClass clazz : JNIReflectionDictionary.currentLayer().getClasses()) { numClasses++; var fieldsCursor = clazz.getFields(); while (fieldsCursor.advance()) { @@ -561,7 +561,7 @@ public void beforeCompilation(BeforeCompilationAccess a) { CompilationAccessImpl access = (CompilationAccessImpl) a; DynamicHubLayout dynamicHubLayout = DynamicHubLayout.singleton(); - for (JNIAccessibleClass clazz : JNIReflectionDictionary.singleton().getClasses()) { + for (JNIAccessibleClass clazz : JNIReflectionDictionary.currentLayer().getClasses()) { UnmodifiableMapCursor cursor = clazz.getFields(); while (cursor.advance()) { String name = (String) cursor.getKey(); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/TypeCheckBuilder.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/TypeCheckBuilder.java index d9531e8547be..a1f8b16f3b44 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/TypeCheckBuilder.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/TypeCheckBuilder.java @@ -465,7 +465,7 @@ public void buildTypeInformation(HostedUniverse hUniverse, int startingTypeID) { type.subTypes = subtypeMap.get(type).toArray(HostedType.EMPTY_ARRAY); } - DynamicHubSupport.singleton().setMaxTypeId(nextTypeID); + DynamicHubSupport.currentLayer().setMaxTypeId(nextTypeID); /* * Search through list in reverse order so that all of a type's subtypes are traversed diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/UniverseBuilder.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/UniverseBuilder.java index 3b763ee5cf20..5c854ef3afc1 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/UniverseBuilder.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/UniverseBuilder.java @@ -773,7 +773,7 @@ private void layoutStaticFields() { int nextObjectField = 0; @SuppressWarnings("unchecked") - List[] fieldsOfTypes = (List[]) new ArrayList[DynamicHubSupport.singleton().getMaxTypeId()]; + List[] fieldsOfTypes = (List[]) new ArrayList[DynamicHubSupport.currentLayer().getMaxTypeId()]; for (HostedField field : fields) { if (skipStaticField(field)) { @@ -820,7 +820,7 @@ private void layoutStaticFields() { @SuppressWarnings("unchecked") private void collectDeclaredMethods() { - List[] methodsOfType = (ArrayList[]) new ArrayList[DynamicHubSupport.singleton().getMaxTypeId()]; + List[] methodsOfType = (ArrayList[]) new ArrayList[DynamicHubSupport.currentLayer().getMaxTypeId()]; for (HostedMethod method : hUniverse.methods.values()) { int typeId = method.getDeclaringClass().getTypeID(); List list = methodsOfType[typeId]; @@ -860,7 +860,7 @@ private void buildHubs() { referenceMaps.put(type, referenceMap); referenceMapEncoder.add(referenceMap); } - DynamicHubSupport.singleton().setReferenceMapEncoding(referenceMapEncoder.encodeAll()); + DynamicHubSupport.currentLayer().setReferenceMapEncoding(referenceMapEncoder.encodeAll()); ObjectLayout ol = ConfigurationValues.getObjectLayout(); DynamicHubLayout dynamicHubLayout = DynamicHubLayout.singleton(); 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 a96a47e681a7..3e9e09ea28e8 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 @@ -160,7 +160,7 @@ record ConditionalTask(ConfigurationCondition condition, Consumer() : null; - classForNameSupport = ClassForNameSupport.singleton(); + classForNameSupport = ClassForNameSupport.currentLayer(); } public void duringSetup(AnalysisMetaAccess analysisMetaAccess, AnalysisUniverse analysisUniverse) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionFeature.java index 0d788afc7dad..01532dada7a8 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionFeature.java @@ -308,7 +308,7 @@ public void duringSetup(DuringSetupAccess a) { /* Primitive classes cannot be accessed through Class.forName() */ for (Class primitiveClass : PRIMITIVE_CLASSES) { - ClassForNameSupport.singleton().registerNegativeQuery(ConfigurationCondition.alwaysTrue(), primitiveClass.getName()); + ClassForNameSupport.currentLayer().registerNegativeQuery(ConfigurationCondition.alwaysTrue(), primitiveClass.getName()); } access.registerObjectReachableCallback(SubstrateAccessor.class, ReflectionFeature::onAccessorReachable); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java index 1bb561e5a132..1146afdfd859 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java @@ -1161,15 +1161,20 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec return true; } - Object singleton = LayeredImageSingletonSupport.singleton().runtimeLookup(key); - if (singleton instanceof LayeredImageSingleton layeredSingleton && !layeredSingleton.getImageBuilderFlags().contains(LayeredImageSingletonBuilderFlags.RUNTIME_ACCESS)) { - /* - * Runtime compilation installs many singletons into the image which are - * otherwise hosted only. Note the platform checks still apply and can be used - * to ensure certain singleton are not installed into the image. - */ - if (!RuntimeCompilation.isEnabled()) { - throw VMError.shouldNotReachHere("Layered image singleton without runtime access is in runtime graph: " + singleton); + Object singleton = LayeredImageSingletonSupport.singleton().lookup(key, true, true); + if (singleton instanceof LayeredImageSingleton layeredSingleton) { + if (!layeredSingleton.getImageBuilderFlags().contains(LayeredImageSingletonBuilderFlags.RUNTIME_ACCESS)) { + /* + * Runtime compilation installs many singletons into the image which are + * otherwise hosted only. Note the platform checks still apply and can be + * used to ensure certain singleton are not installed into the image. + */ + if (!RuntimeCompilation.isEnabled()) { + throw VMError.shouldNotReachHere("Layered image singleton without runtime access is in runtime graph: " + singleton); + } + } + if (layeredSingleton instanceof MultiLayeredImageSingleton) { + throw VMError.shouldNotReachHere("Forbidden lookup of MultiLayeredImageSingleton in runtime graph: " + singleton); } } b.addPush(JavaKind.Object, ConstantNode.forConstant(b.getSnippetReflection().forObject(singleton), b.getMetaAccess()));