Skip to content

Commit 7ddf775

Browse files
committed
Adapt reflection for multiple layers
1 parent 71179a7 commit 7ddf775

File tree

10 files changed

+256
-124
lines changed

10 files changed

+256
-124
lines changed

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
import com.oracle.svm.core.heap.RestrictHeapAccess;
4646
import com.oracle.svm.core.heap.RestrictHeapAccess.Access;
4747
import com.oracle.svm.core.heap.VMOperationInfos;
48+
import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport;
49+
import com.oracle.svm.core.layeredimagesingleton.MultiLayeredImageSingleton;
4850
import com.oracle.svm.core.log.Log;
4951
import com.oracle.svm.core.meta.SharedMethod;
5052
import com.oracle.svm.core.option.HostedOptionKey;
@@ -99,6 +101,17 @@ public static CodeInfo getFirstImageCodeInfo() {
99101
return imageCodeInfo;
100102
}
101103

104+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
105+
public static CodeInfo getFirstImageCodeInfo(int layerNumber) {
106+
if (ImageLayerBuildingSupport.buildingImageLayer()) {
107+
ImageCodeInfoStorage[] runtimeCodeInfos = MultiLayeredImageSingleton.getAllLayers(ImageCodeInfoStorage.class);
108+
return runtimeCodeInfos[layerNumber].getData();
109+
} else {
110+
assert layerNumber == 0;
111+
return imageCodeInfo;
112+
}
113+
}
114+
102115
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
103116
public static CodeInfo getImageCodeInfo(CodePointer ip) {
104117
CodeInfo info = lookupImageCodeInfo(ip);

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

Lines changed: 113 additions & 81 deletions
Large diffs are not rendered by default.

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,18 @@
2424
*/
2525
package com.oracle.svm.core.code;
2626

27+
import java.util.EnumSet;
28+
2729
import org.graalvm.nativeimage.Platform;
2830
import org.graalvm.nativeimage.Platforms;
2931

3032
import com.oracle.svm.core.BuildPhaseProvider.AfterCompilation;
3133
import com.oracle.svm.core.code.RuntimeMetadataDecoderImpl.MetadataAccessorImpl;
3234
import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton;
3335
import com.oracle.svm.core.heap.UnknownObjectField;
36+
import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags;
37+
import com.oracle.svm.core.layeredimagesingleton.MultiLayeredImageSingleton;
38+
import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton;
3439

3540
/**
3641
* Stores the encoding of all runtime metadata.
@@ -43,7 +48,7 @@
4348
* we would need an index to locate all relevant runtime metadata of an entity from all layers.
4449
*/
4550
@AutomaticallyRegisteredImageSingleton
46-
public class RuntimeMetadataEncoding {
51+
public class RuntimeMetadataEncoding implements MultiLayeredImageSingleton, UnsavedSingleton {
4752
@UnknownObjectField(availability = AfterCompilation.class) private byte[] encoding;
4853

4954
public byte[] getEncoding() {
@@ -54,4 +59,9 @@ public byte[] getEncoding() {
5459
public void setEncoding(byte[] encoding) {
5560
this.encoding = encoding;
5661
}
62+
63+
@Override
64+
public EnumSet<LayeredImageSingletonBuilderFlags> getImageBuilderFlags() {
65+
return LayeredImageSingletonBuilderFlags.ALL_ACCESS;
66+
}
5767
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/ClassForNameSupport.java

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
import static com.oracle.svm.core.MissingRegistrationUtils.throwMissingRegistrationErrors;
2828

29+
import java.util.EnumSet;
2930
import java.util.Objects;
3031

3132
import org.graalvm.collections.EconomicMap;
@@ -37,12 +38,15 @@
3738
import com.oracle.svm.core.configure.ConditionalRuntimeValue;
3839
import com.oracle.svm.core.configure.RuntimeConditionSet;
3940
import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton;
41+
import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags;
42+
import com.oracle.svm.core.layeredimagesingleton.MultiLayeredImageSingleton;
43+
import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton;
4044
import com.oracle.svm.core.reflect.MissingReflectionRegistrationUtils;
4145
import com.oracle.svm.core.util.ImageHeapMap;
4246
import com.oracle.svm.core.util.VMError;
4347

4448
@AutomaticallyRegisteredImageSingleton
45-
public final class ClassForNameSupport {
49+
public final class ClassForNameSupport implements MultiLayeredImageSingleton, UnsavedSingleton {
4650

4751
public static ClassForNameSupport singleton() {
4852
return ImageSingletons.lookup(ClassForNameSupport.class);
@@ -159,22 +163,43 @@ private void updateCondition(ConfigurationCondition condition, String className,
159163
}
160164
}
161165

162-
public Class<?> forNameOrNull(String className, ClassLoader classLoader) {
166+
public static Class<?> forNameOrNull(String className, ClassLoader classLoader) {
163167
try {
164168
return forName(className, classLoader, true);
165169
} catch (ClassNotFoundException e) {
166170
throw VMError.shouldNotReachHere("ClassForNameSupport#forNameOrNull should not throw", e);
167171
}
168172
}
169173

170-
public Class<?> forName(String className, ClassLoader classLoader) throws ClassNotFoundException {
174+
public static Class<?> forName(String className, ClassLoader classLoader) throws ClassNotFoundException {
171175
return forName(className, classLoader, false);
172176
}
173177

174-
private Class<?> forName(String className, ClassLoader classLoader, boolean returnNullOnException) throws ClassNotFoundException {
178+
private static Class<?> forName(String className, ClassLoader classLoader, boolean returnNullOnException) throws ClassNotFoundException {
175179
if (className == null) {
176180
return null;
177181
}
182+
ClassForNameSupport classForNameSupport = singleton();
183+
Object result = classForNameSupport.getSingletonDataThrowing(classForNameSupport, MultiLayeredImageSingleton.getAllLayers(ClassForNameSupport.class),
184+
singleton -> singleton.forName0(className, classLoader, returnNullOnException));
185+
if (result instanceof Class<?>) {
186+
return (Class<?>) result;
187+
} else if (result instanceof Throwable) {
188+
return null;
189+
} else {
190+
if (throwMissingRegistrationErrors()) {
191+
MissingReflectionRegistrationUtils.forClass(className);
192+
}
193+
194+
if (returnNullOnException) {
195+
return null;
196+
} else {
197+
throw new ClassNotFoundException(className);
198+
}
199+
}
200+
}
201+
202+
private Object forName0(String className, ClassLoader classLoader, boolean returnNullOnException) throws ClassNotFoundException {
178203
var conditional = knownClasses.get(className);
179204
Object result = conditional == null ? null : conditional.getValue();
180205
if (result == NEGATIVE_QUERY || className.endsWith("[]")) {
@@ -187,10 +212,10 @@ private Class<?> forName(String className, ClassLoader classLoader, boolean retu
187212
// Note: for non-predefined classes, we (currently) don't need to check the provided loader
188213
// TODO rewrite stack traces (GR-42813)
189214
if (result instanceof Class<?>) {
190-
return (Class<?>) result;
215+
return result;
191216
} else if (result instanceof Throwable) {
192217
if (returnNullOnException) {
193-
return null;
218+
return result;
194219
}
195220

196221
if (result instanceof Error) {
@@ -199,15 +224,7 @@ private Class<?> forName(String className, ClassLoader classLoader, boolean retu
199224
throw (ClassNotFoundException) result;
200225
}
201226
} else if (result == null) {
202-
if (throwMissingRegistrationErrors()) {
203-
MissingReflectionRegistrationUtils.forClass(className);
204-
}
205-
206-
if (returnNullOnException) {
207-
return null;
208-
} else {
209-
throw new ClassNotFoundException(className);
210-
}
227+
return null;
211228
}
212229
throw VMError.shouldNotReachHere("Class.forName result should be Class, ClassNotFoundException or Error: " + result);
213230
}
@@ -216,9 +233,12 @@ public int count() {
216233
return knownClasses.size();
217234
}
218235

219-
public RuntimeConditionSet getConditionFor(Class<?> jClass) {
236+
public static RuntimeConditionSet getConditionFor(Class<?> jClass) {
220237
Objects.requireNonNull(jClass);
221-
ConditionalRuntimeValue<Object> conditionalClass = knownClasses.get(jClass.getName());
238+
String jClassName = jClass.getName();
239+
ClassForNameSupport classForNameSupport = singleton();
240+
ConditionalRuntimeValue<Object> conditionalClass = classForNameSupport.getSingletonData(classForNameSupport, MultiLayeredImageSingleton.getAllLayers(ClassForNameSupport.class),
241+
singleton -> singleton.knownClasses.get(jClassName));
222242
if (conditionalClass == null) {
223243
return RuntimeConditionSet.unmodifiableEmptySet();
224244
} else {
@@ -230,8 +250,16 @@ public RuntimeConditionSet getConditionFor(Class<?> jClass) {
230250
* Checks whether {@code hub} can be instantiated with {@code Unsafe.allocateInstance}. Note
231251
* that arrays can't be instantiated and this function will always return false for array types.
232252
*/
233-
public boolean canUnsafeInstantiateAsInstance(DynamicHub hub) {
234-
var conditionSet = unsafeInstantiatedClasses.get(DynamicHub.toClass(hub));
253+
public static boolean canUnsafeInstantiateAsInstance(DynamicHub hub) {
254+
Class<?> clazz = DynamicHub.toClass(hub);
255+
ClassForNameSupport classForNameSupport = singleton();
256+
RuntimeConditionSet conditionSet = classForNameSupport.getSingletonData(classForNameSupport, MultiLayeredImageSingleton.getAllLayers(ClassForNameSupport.class),
257+
singleton -> singleton.unsafeInstantiatedClasses.get(clazz));
235258
return conditionSet != null && conditionSet.satisfied();
236259
}
260+
261+
@Override
262+
public EnumSet<LayeredImageSingletonBuilderFlags> getImageBuilderFlags() {
263+
return LayeredImageSingletonBuilderFlags.ALL_ACCESS;
264+
}
237265
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -762,7 +762,7 @@ public boolean canUnsafeInstantiateAsInstanceFastPath() {
762762
}
763763

764764
public boolean canUnsafeInstantiateAsInstanceSlowPath() {
765-
if (ClassForNameSupport.singleton().canUnsafeInstantiateAsInstance(this)) {
765+
if (ClassForNameSupport.canUnsafeInstantiateAsInstance(this)) {
766766
companion.setUnsafeAllocate();
767767
return true;
768768
} else {
@@ -1110,7 +1110,7 @@ private Field[] getFields() {
11101110
}
11111111

11121112
private RuntimeConditionSet getConditions() {
1113-
return ClassForNameSupport.singleton().getConditionFor(DynamicHub.toClass(this));
1113+
return ClassForNameSupport.getConditionFor(DynamicHub.toClass(this));
11141114
}
11151115

11161116
@Substitute
@@ -1498,7 +1498,7 @@ private static Class<?> forName(String name, boolean initialize, ClassLoader loa
14981498
}
14991499
Class<?> result;
15001500
try {
1501-
result = ClassForNameSupport.singleton().forName(name, loader);
1501+
result = ClassForNameSupport.forName(name, loader);
15021502
} catch (ClassNotFoundException e) {
15031503
if (loader != null && PredefinedClassesSupport.hasBytecodeClasses()) {
15041504
result = loader.loadClass(name); // may throw
@@ -1577,7 +1577,7 @@ public Object[] getSigners() {
15771577
if (hubMetadata == null || hubMetadata.signersEncodingIndex == NO_DATA) {
15781578
return null;
15791579
}
1580-
return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseObjects(hubMetadata.signersEncodingIndex);
1580+
return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseObjects(hubMetadata.signersEncodingIndex, this);
15811581
}
15821582

15831583
@Substitute
@@ -1725,7 +1725,7 @@ private Object[] getEnclosingMethod0() {
17251725
if (hubMetadata == null || hubMetadata.enclosingMethodInfoIndex == NO_DATA) {
17261726
return null;
17271727
}
1728-
Object[] enclosingMethod = ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseEnclosingMethod(hubMetadata.enclosingMethodInfoIndex);
1728+
Object[] enclosingMethod = ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseEnclosingMethod(hubMetadata.enclosingMethodInfoIndex, this);
17291729
if (enclosingMethod != null) {
17301730
PredefinedClassesSupport.throwIfUnresolvable((Class<?>) enclosingMethod[0], getClassLoader0());
17311731
}
@@ -1761,15 +1761,15 @@ byte[] getRawAnnotations() {
17611761
if (hubMetadata == null || hubMetadata.annotationsIndex == NO_DATA) {
17621762
return null;
17631763
}
1764-
return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseByteArray(hubMetadata.annotationsIndex);
1764+
return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseByteArray(hubMetadata.annotationsIndex, this);
17651765
}
17661766

17671767
@Substitute
17681768
byte[] getRawTypeAnnotations() {
17691769
if (hubMetadata == null || hubMetadata.typeAnnotationsIndex == NO_DATA) {
17701770
return null;
17711771
}
1772-
return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseByteArray(hubMetadata.typeAnnotationsIndex);
1772+
return ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseByteArray(hubMetadata.typeAnnotationsIndex, this);
17731773
}
17741774

17751775
@Substitute
@@ -1806,7 +1806,7 @@ private Class<?>[] getDeclaredClasses0() {
18061806
if (hubMetadata == null || hubMetadata.classesEncodingIndex == NO_DATA) {
18071807
return new Class<?>[0];
18081808
}
1809-
Class<?>[] declaredClasses = ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseClasses(hubMetadata.classesEncodingIndex);
1809+
Class<?>[] declaredClasses = ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseClasses(hubMetadata.classesEncodingIndex, this);
18101810
for (Class<?> clazz : declaredClasses) {
18111811
PredefinedClassesSupport.throwIfUnresolvable(clazz, getClassLoader0());
18121812
}
@@ -1825,7 +1825,7 @@ private Class<?>[] getNestMembers0() {
18251825
if (hubMetadata == null || hubMetadata.nestMembersEncodingIndex == NO_DATA) {
18261826
return new Class<?>[]{DynamicHub.toClass(this)};
18271827
}
1828-
Class<?>[] nestMembers = ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseClasses(hubMetadata.nestMembersEncodingIndex);
1828+
Class<?>[] nestMembers = ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseClasses(hubMetadata.nestMembersEncodingIndex, this);
18291829
for (Class<?> clazz : nestMembers) {
18301830
PredefinedClassesSupport.throwIfUnresolvable(clazz, getClassLoader0());
18311831
}
@@ -1877,7 +1877,7 @@ private Class<?>[] getPermittedSubclasses0() {
18771877
if (hubMetadata == null || hubMetadata.permittedSubclassesEncodingIndex == NO_DATA) {
18781878
return new Class<?>[0];
18791879
}
1880-
Class<?>[] permittedSubclasses = ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseClasses(hubMetadata.permittedSubclassesEncodingIndex);
1880+
Class<?>[] permittedSubclasses = ImageSingletons.lookup(RuntimeMetadataDecoder.class).parseClasses(hubMetadata.permittedSubclassesEncodingIndex, this);
18811881
for (Class<?> clazz : permittedSubclasses) {
18821882
PredefinedClassesSupport.throwIfUnresolvable(clazz, getClassLoader0());
18831883
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaLangSubstitutions.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -649,14 +649,14 @@ public static Stream<Package> packages() {
649649

650650
@Substitute
651651
private static Class<?> loadClassOrNull(String name) {
652-
return ClassForNameSupport.singleton().forNameOrNull(name, null);
652+
return ClassForNameSupport.forNameOrNull(name, null);
653653
}
654654

655655
@SuppressWarnings("unused")
656656
@Substitute
657657
private static Class<?> loadClass(Module module, String name) {
658658
/* The module system is not supported for now, therefore the module parameter is ignored. */
659-
return ClassForNameSupport.singleton().forNameOrNull(name, null);
659+
return ClassForNameSupport.forNameOrNull(name, null);
660660
}
661661

662662
@SuppressWarnings("unused")

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_java_lang_ClassLoader.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ Class<?> loadClass(Module module, String name) {
165165
@Substitute //
166166
@SuppressWarnings({"unused"}) //
167167
private Class<?> findLoadedClass0(String name) {
168-
return ClassForNameSupport.singleton().forNameOrNull(name, SubstrateUtil.cast(this, ClassLoader.class));
168+
return ClassForNameSupport.forNameOrNull(name, SubstrateUtil.cast(this, ClassLoader.class));
169169
}
170170

171171
/**

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

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

27+
import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport;
2728
import com.oracle.svm.core.util.VMError;
2829

2930
public interface MultiLayeredImageSingleton extends LayeredImageSingleton {
@@ -36,4 +37,31 @@ public interface MultiLayeredImageSingleton extends LayeredImageSingleton {
3637
static <T extends MultiLayeredImageSingleton> T[] getAllLayers(Class<T> key) {
3738
throw VMError.shouldNotReachHere("This can only be called during runtime");
3839
}
40+
41+
interface ThrowingFunction<T, U, V extends Throwable> {
42+
U apply(T t) throws V;
43+
}
44+
45+
default <T extends MultiLayeredImageSingleton, U, V extends Throwable> U getSingletonData(T singleton, T[] singletons, ThrowingFunction<T, U, V> getSingletonDataFunction) {
46+
try {
47+
return getSingletonDataThrowing(singleton, singletons, getSingletonDataFunction);
48+
} catch (Throwable e) {
49+
throw VMError.shouldNotReachHere("The function threw an unexpected exception", e);
50+
}
51+
}
52+
53+
default <T extends MultiLayeredImageSingleton, U, V extends Throwable> U getSingletonDataThrowing(T singleton, T[] singletons, ThrowingFunction<T, U, V> getSingletonDataFunction)
54+
throws V {
55+
if (ImageLayerBuildingSupport.buildingImageLayer()) {
56+
for (var layerSingleton : singletons) {
57+
U result = getSingletonDataFunction.apply(layerSingleton);
58+
if (result != null) {
59+
return result;
60+
}
61+
}
62+
return null;
63+
} else {
64+
return getSingletonDataFunction.apply(singleton);
65+
}
66+
}
3967
}

0 commit comments

Comments
 (0)