Skip to content

Commit 4e691ab

Browse files
committed
[GR-55552] Layered Micronaut Hello World
PullRequest: graal/18329
2 parents 8a88c44 + ffa764a commit 4e691ab

File tree

10 files changed

+95
-22
lines changed

10 files changed

+95
-22
lines changed

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageLayerLoader.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import static com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil.ARGUMENT_IDS_TAG;
3030
import static com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil.ARRAY_TAG;
3131
import static com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil.CAN_BE_STATICALLY_BOUND_TAG;
32+
import static com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil.CLASS_INIT_NAME;
3233
import static com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil.CLASS_JAVA_NAME_TAG;
3334
import static com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil.CLASS_NAME_TAG;
3435
import static com.oracle.graal.pointsto.heap.ImageLayerSnapshotUtil.CODE_SIZE_TAG;
@@ -700,6 +701,8 @@ private void loadMethod(EconomicMap<String, Object> methodData) {
700701

701702
if (name.equals(CONSTRUCTOR_NAME)) {
702703
type.findConstructor(signature);
704+
} else if (name.equals(CLASS_INIT_NAME)) {
705+
type.getClassInitializer();
703706
} else {
704707
type.findMethod(name, signature);
705708
}
@@ -905,7 +908,13 @@ private void loadField(FieldIdentifier fieldIdentifier, EconomicMap<String, Obje
905908
clazz = declaringClass.getJavaClass();
906909
}
907910

908-
Field field = ReflectionUtil.lookupField(true, clazz, fieldIdentifier.name);
911+
Field field;
912+
try {
913+
field = ReflectionUtil.lookupField(true, clazz, fieldIdentifier.name);
914+
} catch (Throwable e) {
915+
field = null;
916+
}
917+
909918
if (field == null) {
910919
AnalysisType type = getAnalysisType(get(fieldData, FIELD_TYPE_TAG));
911920
BaseLayerField baseLayerField = new BaseLayerField(get(fieldData, ID_TAG), fieldIdentifier.name, declaringClass, type, get(fieldData, IS_INTERNAL_TAG), get(fieldData, MODIFIERS_TAG),

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageLayerSnapshotUtil.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ public class ImageLayerSnapshotUtil {
5353
public static final String FILE_EXTENSION = ".json";
5454

5555
public static final String CONSTRUCTOR_NAME = "<init>";
56+
public static final String CLASS_INIT_NAME = "<clinit>";
5657

5758
public static final String PERSISTED = "persisted";
5859

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,9 @@ protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, Boolean o
139139
@BundleMember(role = Role.Input) //
140140
public static final HostedOptionKey<AccumulatingLocatableMultiOptionValue.Paths> LayerUse = new HostedOptionKey<>(AccumulatingLocatableMultiOptionValue.Paths.build());
141141

142+
@Option(help = "Mark singleton as application layer only")//
143+
public static final HostedOptionKey<AccumulatingLocatableMultiOptionValue.Strings> ApplicationLayerOnlySingletons = new HostedOptionKey<>(AccumulatingLocatableMultiOptionValue.Strings.build());
144+
142145
@APIOption(name = "libc")//
143146
@Option(help = "Selects the libc implementation to use. Available implementations: glibc, musl, bionic")//
144147
public static final HostedOptionKey<String> UseLibC = new HostedOptionKey<>(null) {

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/ApplicationLayerOnlyImageSingleton.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,36 @@
2424
*/
2525
package com.oracle.svm.core.layeredimagesingleton;
2626

27+
import org.graalvm.nativeimage.ImageSingletons;
28+
29+
import com.oracle.svm.core.SubstrateOptions;
30+
import com.oracle.svm.core.option.HostedOptionValues;
31+
2732
/**
2833
* Identifies a singleton for which all lookups refer to a single singleton which will be created in
2934
* the application layer. See {@link LayeredImageSingleton} for full explanation.
3035
*/
3136
public interface ApplicationLayerOnlyImageSingleton extends LayeredImageSingleton {
37+
38+
static boolean isSingletonInstanceOf(Object singleton) {
39+
if (singleton instanceof ApplicationLayerOnlyImageSingleton) {
40+
return true;
41+
}
42+
if (ImageSingletons.contains(HostedOptionValues.class)) {
43+
return SubstrateOptions.ApplicationLayerOnlySingletons.getValue().contains(singleton.getClass().getName());
44+
}
45+
46+
return false;
47+
}
48+
49+
static boolean isAssignableFrom(Class<?> klass) {
50+
if (ApplicationLayerOnlyImageSingleton.class.isAssignableFrom(klass)) {
51+
return true;
52+
}
53+
if (ImageSingletons.contains(HostedOptionValues.class)) {
54+
return SubstrateOptions.ApplicationLayerOnlySingletons.getValue().contains(klass.getName());
55+
}
56+
57+
return false;
58+
}
3259
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/LayeredImageSingletonBuilderFlags.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,13 @@ public static boolean verifyImageBuilderFlags(LayeredImageSingleton singleton) {
6565
assert flags.equals(EnumSet.of(UNSUPPORTED)) : "Unsupported should be the only flag set " + flags;
6666
}
6767

68-
if (singleton instanceof MultiLayeredImageSingleton || singleton instanceof ApplicationLayerOnlyImageSingleton) {
68+
if (singleton instanceof MultiLayeredImageSingleton || ApplicationLayerOnlyImageSingleton.isSingletonInstanceOf(singleton)) {
6969
assert flags.contains(RUNTIME_ACCESS) : String.format("%s must be set when implementing either %s or %s: %s", RUNTIME_ACCESS, MultiLayeredImageSingleton.class,
7070
ApplicationLayerOnlyImageSingleton.class, singleton);
7171
}
7272

73-
assert !(singleton instanceof MultiLayeredImageSingleton && singleton instanceof ApplicationLayerOnlyImageSingleton) : String.format("%s can only implement one of %s or %s", singleton,
73+
assert !(singleton instanceof MultiLayeredImageSingleton && ApplicationLayerOnlyImageSingleton.isSingletonInstanceOf(singleton)) : String.format("%s can only implement one of %s or %s",
74+
singleton,
7475
MultiLayeredImageSingleton.class, ApplicationLayerOnlyImageSingleton.class);
7576

7677
return true;

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageSingletonsSupportImpl.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -210,17 +210,17 @@ private void doAddInternal(Class<?> key, Object value) {
210210
throw UserError.abort("Unsupported image singleton is being installed %s %s", key.getTypeName(), singleton);
211211
}
212212

213-
if (singleton instanceof MultiLayeredImageSingleton || singleton instanceof ApplicationLayerOnlyImageSingleton) {
213+
if (singleton instanceof MultiLayeredImageSingleton || ApplicationLayerOnlyImageSingleton.isSingletonInstanceOf(singleton)) {
214214

215215
if (!key.equals(singleton.getClass())) {
216216
throw UserError.abort("The implementation class must be the same as the key class. key: %s, singleton: %s", key, singleton);
217217
}
218218

219-
if (singleton instanceof MultiLayeredImageSingleton && singleton instanceof ApplicationLayerOnlyImageSingleton) {
219+
if (singleton instanceof MultiLayeredImageSingleton && ApplicationLayerOnlyImageSingleton.isSingletonInstanceOf(singleton)) {
220220
throw UserError.abort("Singleton cannot implement both %s and %s. singleton: %s", MultiLayeredImageSingleton.class, ApplicationLayerOnlyImageSingleton.class, singleton);
221221
}
222222

223-
if (singleton instanceof ApplicationLayerOnlyImageSingleton && !ImageLayerBuildingSupport.lastImageBuild()) {
223+
if (ApplicationLayerOnlyImageSingleton.isSingletonInstanceOf(singleton) && !ImageLayerBuildingSupport.lastImageBuild()) {
224224
throw UserError.abort("Application layer only image singleton can only be installed in the final layer: %s", singleton);
225225
}
226226

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@
241241
import com.oracle.svm.hosted.image.NativeImageCodeCacheFactory;
242242
import com.oracle.svm.hosted.image.NativeImageHeap;
243243
import com.oracle.svm.hosted.imagelayer.HostedImageLayerBuildingSupport;
244+
import com.oracle.svm.hosted.imagelayer.LoadImageSingletonFeature;
244245
import com.oracle.svm.hosted.jdk.localization.LocalizationFeature;
245246
import com.oracle.svm.hosted.meta.HostedConstantReflectionProvider;
246247
import com.oracle.svm.hosted.meta.HostedField;
@@ -826,6 +827,9 @@ protected boolean runPointsToAnalysis(String imageName, OptionValues options, De
826827
featureHandler.forEachFeature(feature -> feature.beforeAnalysis(config));
827828
ServiceCatalogSupport.singleton().seal();
828829
bb.getHostVM().getClassInitializationSupport().setConfigurationSealed(true);
830+
if (ImageLayerBuildingSupport.buildingImageLayer()) {
831+
ImageSingletons.lookup(LoadImageSingletonFeature.class).processRegisteredSingletons(aUniverse);
832+
}
829833
}
830834

831835
try (ReporterClosable c = ProgressReporter.singleton().printAnalysis(bb.getUniverse(), nativeLibraries.getLibraries())) {

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ResourcesFeature.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
import com.oracle.svm.core.util.VMError;
9292
import com.oracle.svm.hosted.classinitialization.ClassInitializationSupport;
9393
import com.oracle.svm.hosted.config.ConfigurationParserUtils;
94+
import com.oracle.svm.hosted.imagelayer.HostedImageLayerBuildingSupport;
9495
import com.oracle.svm.hosted.jdk.localization.LocalizationFeature;
9596
import com.oracle.svm.hosted.reflect.NativeImageConditionResolver;
9697
import com.oracle.svm.hosted.snippets.SubstrateGraphBuilderPlugins;
@@ -393,9 +394,10 @@ protected boolean collectEmbeddedResourcesInfo() {
393394
}
394395

395396
@Override
396-
public void beforeAnalysis(BeforeAnalysisAccess access) {
397+
public void beforeAnalysis(BeforeAnalysisAccess a) {
398+
FeatureImpl.BeforeAnalysisAccessImpl access = (FeatureImpl.BeforeAnalysisAccessImpl) a;
397399
/* load and parse resource configuration files */
398-
ConfigurationConditionResolver<ConfigurationCondition> conditionResolver = new NativeImageConditionResolver(((FeatureImpl.BeforeAnalysisAccessImpl) access).getImageClassLoader(),
400+
ConfigurationConditionResolver<ConfigurationCondition> conditionResolver = new NativeImageConditionResolver(access.getImageClassLoader(),
399401
ClassInitializationSupport.singleton());
400402

401403
ResourceConfigurationParser<ConfigurationCondition> parser = ResourceConfigurationParser.create(true, conditionResolver, ResourcesRegistry.singleton(),
@@ -415,6 +417,21 @@ public void beforeAnalysis(BeforeAnalysisAccess access) {
415417
GlobTrieNode<ConditionWithOrigin> trie = CompressedGlobTrie.CompressedGlobTrieBuilder.build(patternsWithInfo);
416418
Resources.singleton().setResourcesTrieRoot(trie);
417419

420+
/*
421+
* GR-58701: The SVM core is currently not included in the base layer of a Layered Image.
422+
* Those specific types can be reachable from Resources#resourcesTrieRoot, but they can be
423+
* missed by the analysis because the GlobTrieNode#children field is only available after
424+
* analysis and the only reference to those types is with ThrowMissingRegistrationErrors
425+
* enabled. Until a clear SVM core separation is created and included in the base layer,
426+
* those types should be manually registered as instantiated before the analysis.
427+
*/
428+
if (HostedImageLayerBuildingSupport.buildingSharedLayer()) {
429+
String reason = "Included in the base image";
430+
access.getMetaAccess().lookupJavaType(ReflectionUtil.lookupClass(false, "com.oracle.svm.core.jdk.resources.CompressedGlobTrie.LiteralNode")).registerAsInstantiated(reason);
431+
access.getMetaAccess().lookupJavaType(ReflectionUtil.lookupClass(false, "com.oracle.svm.core.jdk.resources.CompressedGlobTrie.DoubleStarNode")).registerAsInstantiated(reason);
432+
access.getMetaAccess().lookupJavaType(ReflectionUtil.lookupClass(false, "com.oracle.svm.core.jdk.resources.CompressedGlobTrie.StarTrieNode")).registerAsInstantiated(reason);
433+
}
434+
418435
/* prepare regex patterns for resource registration */
419436
resourcePatternWorkSet.addAll(Options.IncludeResources.getValue()
420437
.getValuesWithOrigins()

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LoadImageSingletonFeature.java

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@
4343

4444
import com.oracle.graal.pointsto.heap.ImageHeapConstant;
4545
import com.oracle.graal.pointsto.heap.ImageHeapObjectArray;
46+
import com.oracle.graal.pointsto.meta.AnalysisMetaAccess;
4647
import com.oracle.graal.pointsto.meta.AnalysisType;
48+
import com.oracle.graal.pointsto.meta.AnalysisUniverse;
4749
import com.oracle.svm.core.ParsingReason;
4850
import com.oracle.svm.core.c.CGlobalData;
4951
import com.oracle.svm.core.c.CGlobalDataFactory;
@@ -148,18 +150,26 @@ public void duringSetup(DuringSetupAccess access) {
148150
LayeredImageHeapObjectAdder.singleton().registerObjectAdder(this::addInitialObjects);
149151
}
150152

151-
@Override
152-
public void beforeAnalysis(BeforeAnalysisAccess access) {
153-
var config = (FeatureImpl.BeforeAnalysisAccessImpl) access;
154-
loader = (SVMImageLayerLoader) config.getUniverse().getImageLayerLoader();
153+
/**
154+
* This method needs to be called after all image singletons are registered. Currently, some
155+
* singletons are registered in
156+
* {@link org.graalvm.nativeimage.hosted.Feature#beforeAnalysis(BeforeAnalysisAccess)}, but the
157+
* singleton registration might get restricted to only
158+
* {@link org.graalvm.nativeimage.hosted.Feature#duringSetup(DuringSetupAccess)} or before. In
159+
* this case, this method should override
160+
* {@link org.graalvm.nativeimage.hosted.Feature#beforeAnalysis(BeforeAnalysisAccess)}.
161+
*/
162+
public void processRegisteredSingletons(AnalysisUniverse universe) {
163+
AnalysisMetaAccess metaAccess = universe.getBigbang().getMetaAccess();
164+
loader = (SVMImageLayerLoader) universe.getImageLayerLoader();
155165

156166
LayeredImageSingletonSupport layeredImageSingletonSupport = LayeredImageSingletonSupport.singleton();
157167
layeredImageSingletonSupport.freezeMultiLayeredImageSingletons();
158168

159169
Consumer<Object[]> multiLayerEmbeddedRootsRegistration = (objArray) -> {
160-
var method = config.getMetaAccess().lookupJavaMethod(ReflectionUtil.lookupMethod(MultiLayeredImageSingleton.class, "getAllLayers", Class.class));
161-
var javaConstant = config.getUniverse().getSnippetReflection().forObject(objArray);
162-
config.getUniverse().registerEmbeddedRoot(javaConstant, new BytecodePosition(null, method, BytecodeFrame.UNKNOWN_BCI));
170+
var method = metaAccess.lookupJavaMethod(ReflectionUtil.lookupMethod(MultiLayeredImageSingleton.class, "getAllLayers", Class.class));
171+
var javaConstant = universe.getSnippetReflection().forObject(objArray);
172+
universe.registerEmbeddedRoot(javaConstant, new BytecodePosition(null, method, BytecodeFrame.UNKNOWN_BCI));
163173
};
164174

165175
if (ImageLayerBuildingSupport.buildingSharedLayer()) {
@@ -208,13 +218,13 @@ public void beforeAnalysis(BeforeAnalysisAccess access) {
208218
* Within the application layer there will be an array created to hold all
209219
* multi-layered image singletons. We must record this type is in the heap.
210220
*/
211-
config.registerAsInHeap(slotInfo.keyClass().arrayType());
221+
metaAccess.lookupJavaType(slotInfo.keyClass().arrayType()).registerAsInstantiated("Array holding multi-layered image singletons");
212222
if (!getCrossLayerSingletonMappingInfo().getPriorLayerObjectIDs(slotInfo.keyClass()).isEmpty()) {
213223
/*
214224
* We also must ensure the type is registered as instantiated in this
215225
* heap if we know the array will refer to a prior object.
216226
*/
217-
config.registerAsInHeap(slotInfo.keyClass());
227+
metaAccess.lookupJavaType(slotInfo.keyClass()).registerAsInstantiated("Refers to a prior singleton");
218228
}
219229
/*
220230
* GR-55294: The constants have to be created before the end of the analysis
@@ -228,9 +238,9 @@ public void beforeAnalysis(BeforeAnalysisAccess access) {
228238
}
229239

230240
if (!applicationLayerEmbeddedRoots.isEmpty()) {
231-
var method = config.getMetaAccess().lookupJavaMethod(ReflectionUtil.lookupMethod(ImageSingletons.class, "lookup", Class.class));
232-
var javaConstant = config.getUniverse().getSnippetReflection().forObject(applicationLayerEmbeddedRoots.toArray());
233-
config.getUniverse().registerEmbeddedRoot(javaConstant, new BytecodePosition(null, method, BytecodeFrame.UNKNOWN_BCI));
241+
var method = metaAccess.lookupJavaMethod(ReflectionUtil.lookupMethod(ImageSingletons.class, "lookup", Class.class));
242+
var javaConstant = universe.getSnippetReflection().forObject(applicationLayerEmbeddedRoots.toArray());
243+
universe.registerEmbeddedRoot(javaConstant, new BytecodePosition(null, method, BytecodeFrame.UNKNOWN_BCI));
234244
}
235245

236246
if (!multiLayerEmbeddedRoots.isEmpty()) {

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1131,7 +1131,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec
11311131
Class<?> key = constantObjectParameter(b, targetMethod, 0, Class.class, classNode);
11321132
boolean result = ImageSingletons.contains(key);
11331133
if (!result && ImageLayerBuildingSupport.buildingImageLayer()) {
1134-
if (ApplicationLayerOnlyImageSingleton.class.isAssignableFrom(key) || MultiLayeredImageSingleton.class.isAssignableFrom(key)) {
1134+
if (ApplicationLayerOnlyImageSingleton.isAssignableFrom(key) || MultiLayeredImageSingleton.class.isAssignableFrom(key)) {
11351135
/*
11361136
* ApplicationLayerOnlyImageSingletons and the array representation of a
11371137
* MultiLayeredImageSingleton will only be created in the final layer.
@@ -1151,7 +1151,8 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec
11511151
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unused, ValueNode classNode) {
11521152
Class<?> key = constantObjectParameter(b, targetMethod, 0, Class.class, classNode);
11531153

1154-
if (ApplicationLayerOnlyImageSingleton.class.isAssignableFrom(key) && ImageLayerBuildingSupport.buildingSharedLayer()) {
1154+
if (ApplicationLayerOnlyImageSingleton.isAssignableFrom(key) &&
1155+
ImageLayerBuildingSupport.buildingSharedLayer()) {
11551156
/*
11561157
* This singleton is only installed in the application layer heap. All other
11571158
* layers looks refer to this singleton.

0 commit comments

Comments
 (0)