Skip to content

Commit 145a4f2

Browse files
committed
[GR-55502] Add support for calling MultiLayeredImageSingleton.getAllLayers from traditional builds.
PullRequest: graal/18307
2 parents 714e550 + 82b1a20 commit 145a4f2

File tree

5 files changed

+116
-24
lines changed

5 files changed

+116
-24
lines changed

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/ImageCodeInfo.java

+11-20
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
import com.oracle.svm.core.c.NonmovableObjectArray;
4242
import com.oracle.svm.core.heap.UnknownObjectField;
4343
import com.oracle.svm.core.heap.UnknownPrimitiveField;
44-
import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport;
4544
import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags;
4645
import com.oracle.svm.core.layeredimagesingleton.MultiLayeredImageSingleton;
4746
import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton;
@@ -87,27 +86,21 @@ public class ImageCodeInfo implements MultiLayeredImageSingleton, UnsavedSinglet
8786

8887
@Uninterruptible(reason = "Executes during isolate creation.")
8988
CodeInfo prepareCodeInfo() {
90-
if (!ImageLayerBuildingSupport.buildingImageLayer()) {
91-
ImageCodeInfo imageCodeInfo = CodeInfoTable.getImageCodeCache();
92-
CodeInfoImpl codeInfo = ImageCodeInfoStorage.get();
93-
return ImageCodeInfo.prepareCodeInfo0(imageCodeInfo, codeInfo, WordFactory.nullPointer());
94-
} else {
95-
ImageCodeInfo[] imageCodeInfos = MultiLayeredImageSingleton.getAllLayers(ImageCodeInfo.class);
96-
ImageCodeInfoStorage[] runtimeCodeInfos = MultiLayeredImageSingleton.getAllLayers(ImageCodeInfoStorage.class);
97-
int size = imageCodeInfos.length;
98-
for (int i = 0; i < size; i++) {
99-
ImageCodeInfo imageCodeInfo = imageCodeInfos[i];
100-
CodeInfoImpl codeInfoImpl = runtimeCodeInfos[i].getData();
101-
CodeInfoImpl nextCodeInfoImpl = i + 1 < size ? runtimeCodeInfos[i + 1].getData() : WordFactory.nullPointer();
102-
103-
ImageCodeInfo.prepareCodeInfo0(imageCodeInfo, codeInfoImpl, nextCodeInfoImpl);
104-
}
105-
return runtimeCodeInfos[0].getData();
89+
ImageCodeInfo[] imageCodeInfos = MultiLayeredImageSingleton.getAllLayers(ImageCodeInfo.class);
90+
ImageCodeInfoStorage[] runtimeCodeInfos = MultiLayeredImageSingleton.getAllLayers(ImageCodeInfoStorage.class);
91+
int size = imageCodeInfos.length;
92+
for (int i = 0; i < size; i++) {
93+
ImageCodeInfo imageCodeInfo = imageCodeInfos[i];
94+
CodeInfoImpl codeInfoImpl = runtimeCodeInfos[i].getData();
95+
CodeInfoImpl nextCodeInfoImpl = i + 1 < size ? runtimeCodeInfos[i + 1].getData() : WordFactory.nullPointer();
96+
97+
ImageCodeInfo.prepareCodeInfo0(imageCodeInfo, codeInfoImpl, nextCodeInfoImpl);
10698
}
99+
return runtimeCodeInfos[0].getData();
107100
}
108101

109102
@Uninterruptible(reason = "Executes during isolate creation.")
110-
private static CodeInfo prepareCodeInfo0(ImageCodeInfo imageCodeInfo, CodeInfoImpl infoImpl, CodeInfo next) {
103+
private static void prepareCodeInfo0(ImageCodeInfo imageCodeInfo, CodeInfoImpl infoImpl, CodeInfo next) {
111104
assert infoImpl.getCodeStart().isNull() : "already initialized";
112105

113106
infoImpl.setObjectFields(NonmovableArrays.fromImageHeap(imageCodeInfo.objectFields));
@@ -128,8 +121,6 @@ private static CodeInfo prepareCodeInfo0(ImageCodeInfo imageCodeInfo, CodeInfoIm
128121
infoImpl.setMethodTableFirstId(imageCodeInfo.methodTableFirstId);
129122
infoImpl.setIsAOTImageCode(true);
130123
infoImpl.setNextImageCodeInfo(next);
131-
132-
return infoImpl;
133124
}
134125

135126
/**

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

+4
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,9 @@
2424
*/
2525
package com.oracle.svm.core.layeredimagesingleton;
2626

27+
/**
28+
* Identifies a singleton for which all lookups refer to a single singleton which will be created in
29+
* the application layer. See {@link LayeredImageSingleton} for full explanation.
30+
*/
2731
public interface ApplicationLayerOnlyImageSingleton extends LayeredImageSingleton {
2832
}

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

+10-4
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,18 @@
4242
* <li>{@link MultiLayeredImageSingleton}: {@link ImageSingletons#lookup} calls continue to refer to
4343
* the appropriate per layer image singleton, but there is also an additional method
4444
* {@link MultiLayeredImageSingleton#getAllLayers} which returns an array with the image singletons
45-
* corresponding to this key in all layers they were created.</li>
45+
* corresponding to this key in all layers they were created. The length of this array will vary
46+
* from [0, total #layers], based on the number of layers singletons were installed in (i.e., it is
47+
* not required for the singleton to be installed in all layers). Within the array, the singletons
48+
* will be arranged so that index [0] corresponds to the singleton originating from the oldest layer
49+
* in which the singleton was installed and index [length - 1] holds the singleton from the newest
50+
* layer.</li>
4651
* </ul>
4752
*
48-
* Note the unique behavior of {@link ApplicationLayerOnlyImageSingleton} and
49-
* {@link MultiLayeredImageSingleton} apply only when building a layered image. During a traditional
50-
* build these flags do not have an impact.
53+
* Note the unique behavior of {@link ApplicationLayerOnlyImageSingleton} applies only when building
54+
* a layered image. Calling {@link MultiLayeredImageSingleton#getAllLayers} during a traditional
55+
* build requires the singleton to be installed in the build and will return an array of length 1
56+
* containing that singleton.
5157
*
5258
* Currently, when using these special singleton types there are additional restrictions:
5359
*

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

+4
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@
2828

2929
public interface MultiLayeredImageSingleton extends LayeredImageSingleton {
3030

31+
/**
32+
* Returns an array containing the image singletons installed for {@code key} within all layers.
33+
* See {@link LayeredImageSingleton} for full explanation.
34+
*/
3135
@SuppressWarnings("unused")
3236
static <T extends MultiLayeredImageSingleton> T[] getAllLayers(Class<T> key) {
3337
throw VMError.shouldNotReachHere("This can only be called during runtime");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
* Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.oracle.svm.core.layeredimagesingleton;
26+
27+
import java.lang.reflect.Array;
28+
import java.util.concurrent.ConcurrentHashMap;
29+
30+
import org.graalvm.nativeimage.hosted.Feature;
31+
32+
import com.oracle.svm.core.ParsingReason;
33+
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
34+
import com.oracle.svm.core.feature.InternalFeature;
35+
import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport;
36+
import com.oracle.svm.core.util.VMError;
37+
38+
import jdk.graal.compiler.nodes.ConstantNode;
39+
import jdk.graal.compiler.nodes.ValueNode;
40+
import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
41+
import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderContext;
42+
import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugin;
43+
import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugins;
44+
import jdk.graal.compiler.phases.util.Providers;
45+
import jdk.vm.ci.meta.JavaKind;
46+
import jdk.vm.ci.meta.ResolvedJavaMethod;
47+
48+
/**
49+
* Adds support for layered image singleton features within traditional builds.
50+
*/
51+
@AutomaticallyRegisteredFeature
52+
public class NonLayeredImageSingletonFeature implements InternalFeature, FeatureSingleton {
53+
54+
ConcurrentHashMap<Class<?>, Object> multiLayeredArrays = new ConcurrentHashMap<>();
55+
56+
@Override
57+
public boolean isInConfiguration(Feature.IsInConfigurationAccess access) {
58+
return !ImageLayerBuildingSupport.buildingImageLayer();
59+
}
60+
61+
@Override
62+
public void registerInvocationPlugins(Providers providers, GraphBuilderConfiguration.Plugins plugins, ParsingReason reason) {
63+
InvocationPlugins.Registration r = new InvocationPlugins.Registration(plugins.getInvocationPlugins(), MultiLayeredImageSingleton.class);
64+
r.register(new InvocationPlugin.RequiredInvocationPlugin("getAllLayers", Class.class) {
65+
66+
@Override
67+
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unused, ValueNode classNode) {
68+
Class<?> key = b.getSnippetReflection().asObject(Class.class, classNode.asJavaConstant());
69+
70+
Object singleton = LayeredImageSingletonSupport.singleton().runtimeLookup(key);
71+
boolean conditions = singleton.getClass().equals(key) &&
72+
singleton instanceof MultiLayeredImageSingleton multiLayerSingleton &&
73+
multiLayerSingleton.getImageBuilderFlags().contains(LayeredImageSingletonBuilderFlags.RUNTIME_ACCESS);
74+
VMError.guarantee(conditions, "Illegal singleton %s", singleton);
75+
76+
var multiLayeredArray = multiLayeredArrays.computeIfAbsent(key, k -> {
77+
var result = Array.newInstance(k, 1);
78+
Array.set(result, 0, singleton);
79+
return result;
80+
});
81+
82+
b.addPush(JavaKind.Object, ConstantNode.forConstant(b.getSnippetReflection().forObject(multiLayeredArray), b.getMetaAccess()));
83+
return true;
84+
}
85+
});
86+
}
87+
}

0 commit comments

Comments
 (0)