Skip to content

Commit 39e0605

Browse files
Improve Crema with --exact-reachability-metadata
1 parent 1d34199 commit 39e0605

File tree

5 files changed

+76
-21
lines changed

5 files changed

+76
-21
lines changed

sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/ClassLoading.java

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,38 @@ public static ArbitraryClassLoadingScope allowArbitraryClassLoading() {
6969
if (!isSupported()) {
7070
throw new IllegalStateException("Runtime class loading is not supported. It must be enabled at build-time with -H:+RuntimeClassLoading.");
7171
}
72-
return new ArbitraryClassLoadingScope();
72+
return new RealArbitraryClassLoadingScope();
7373
}
7474

75-
public static final class ArbitraryClassLoadingScope implements AutoCloseable {
75+
/**
76+
* Conditionally opens a scope in which class loading is not constrained by the reflection
77+
* configuration. If {@code allowArbitraryClassLoading} is true, behaves like
78+
* {@link #allowArbitraryClassLoading()}. Otherwise, it has no effect.
79+
*
80+
* @throws IllegalStateException if class loading is not {@linkplain #isSupported() supported}
81+
* and {@code allowArbitraryClassLoading} is true.
82+
*
83+
* @see #allowArbitraryClassLoading()
84+
*/
85+
public static ArbitraryClassLoadingScope allowArbitraryClassLoading(boolean allowArbitraryClassLoading) {
86+
if (allowArbitraryClassLoading) {
87+
return allowArbitraryClassLoading();
88+
}
89+
return NoopScope.INSTANCE;
90+
}
91+
92+
public abstract static class ArbitraryClassLoadingScope implements AutoCloseable {
93+
private ArbitraryClassLoadingScope() {
94+
}
95+
96+
@Override
97+
public abstract void close();
98+
}
99+
100+
public static final class RealArbitraryClassLoadingScope extends ArbitraryClassLoadingScope {
76101
private boolean closed;
77102

78-
ArbitraryClassLoadingScope() {
103+
RealArbitraryClassLoadingScope() {
79104
if (!ImageInfo.inImageRuntimeCode()) {
80105
return;
81106
}
@@ -94,4 +119,12 @@ public void close() {
94119
ClassLoadingSupport.singleton().endIgnoreReflectionConfigurationScope();
95120
}
96121
}
122+
123+
private static final class NoopScope extends ArbitraryClassLoadingScope {
124+
private static final NoopScope INSTANCE = new NoopScope();
125+
126+
@Override
127+
public void close() {
128+
}
129+
}
97130
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/crema/CremaSupport.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@
3939
import com.oracle.svm.espresso.classfile.descriptors.Symbol;
4040
import com.oracle.svm.espresso.classfile.descriptors.Type;
4141

42-
import jdk.vm.ci.meta.JavaType;
4342
import jdk.vm.ci.meta.ResolvedJavaField;
4443
import jdk.vm.ci.meta.ResolvedJavaMethod;
4544
import jdk.vm.ci.meta.ResolvedJavaType;
45+
import jdk.vm.ci.meta.UnresolvedJavaType;
4646

4747
public interface CremaSupport {
4848
@Platforms(Platform.HOSTED_ONLY.class)
@@ -88,23 +88,23 @@ interface CremaDispatchTable {
8888

8989
Class<?> toClass(ResolvedJavaType resolvedJavaType);
9090

91-
default Class<?> resolveOrThrow(JavaType unresolvedJavaType, ResolvedJavaType accessingClass) {
91+
default Class<?> resolveOrThrow(UnresolvedJavaType unresolvedJavaType, ResolvedJavaType accessingClass) {
9292
ByteSequence type = ByteSequence.create(unresolvedJavaType.getName());
9393
Symbol<Type> symbolicType = SymbolsSupport.getTypes().getOrCreateValidType(type);
9494
return resolveOrThrow(symbolicType, accessingClass);
9595
}
9696

9797
Class<?> resolveOrThrow(Symbol<Type> type, ResolvedJavaType accessingClass);
9898

99-
default Class<?> resolveOrNull(JavaType unresolvedJavaType, ResolvedJavaType accessingClass) {
99+
default Class<?> resolveOrNull(UnresolvedJavaType unresolvedJavaType, ResolvedJavaType accessingClass) {
100100
ByteSequence type = ByteSequence.create(unresolvedJavaType.getName());
101101
Symbol<Type> symbolicType = SymbolsSupport.getTypes().getOrCreateValidType(type);
102102
return resolveOrNull(symbolicType, accessingClass);
103103
}
104104

105105
Class<?> resolveOrNull(Symbol<Type> type, ResolvedJavaType accessingClass);
106106

107-
default Class<?> findLoadedClass(JavaType unresolvedJavaType, ResolvedJavaType accessingClass) {
107+
default Class<?> findLoadedClass(UnresolvedJavaType unresolvedJavaType, ResolvedJavaType accessingClass) {
108108
ByteSequence type = ByteSequence.create(unresolvedJavaType.getName());
109109
Symbol<Type> symbolicType = SymbolsSupport.getTypes().getOrCreateValidType(type);
110110
return findLoadedClass(symbolicType, accessingClass);

substratevm/src/com.oracle.svm.interpreter.metadata/src/com/oracle/svm/interpreter/metadata/CremaResolvedJavaFieldImpl.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
*/
2525
package com.oracle.svm.interpreter.metadata;
2626

27+
import org.graalvm.nativeimage.impl.ClassLoading;
28+
2729
import com.oracle.svm.core.hub.DynamicHub;
2830
import com.oracle.svm.core.hub.crema.CremaResolvedJavaField;
2931
import com.oracle.svm.core.hub.crema.CremaSupport;
@@ -78,8 +80,10 @@ public JavaType getType() {
7880
@Override
7981
public InterpreterResolvedJavaType getResolvedType() {
8082
if (resolvedType == null) {
81-
Class<?> cls = CremaSupport.singleton().resolveOrThrow(getSymbolicType(), getDeclaringClass());
82-
resolvedType = (InterpreterResolvedJavaType) DynamicHub.fromClass(cls).getInterpreterType();
83+
try (var _ = ClassLoading.allowArbitraryClassLoading()) {
84+
Class<?> cls = CremaSupport.singleton().resolveOrThrow(getSymbolicType(), getDeclaringClass());
85+
resolvedType = (InterpreterResolvedJavaType) DynamicHub.fromClass(cls).getInterpreterType();
86+
}
8387
}
8488
return resolvedType;
8589
}

substratevm/src/com.oracle.svm.interpreter/src/com/oracle/svm/interpreter/CremaRuntimeAccess.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import java.lang.invoke.MethodHandle;
2828
import java.lang.invoke.MethodType;
2929

30+
import org.graalvm.nativeimage.impl.ClassLoading;
31+
3032
import com.oracle.svm.core.hub.DynamicHub;
3133
import com.oracle.svm.core.hub.crema.CremaSupport;
3234
import com.oracle.svm.core.hub.registry.SymbolsSupport;
@@ -94,9 +96,11 @@ public RuntimeException throwError(ErrorType errorType, String messageFormat, Ob
9496

9597
@Override
9698
public InterpreterResolvedObjectType lookupOrLoadType(Symbol<Type> type, InterpreterResolvedJavaType accessingClass) {
97-
Class<?> result = CremaSupport.singleton().resolveOrThrow(type, accessingClass);
98-
assert !result.isPrimitive();
99-
return (InterpreterResolvedObjectType) DynamicHub.fromClass(result).getInterpreterType();
99+
try (var _ = ClassLoading.allowArbitraryClassLoading()) {
100+
Class<?> result = CremaSupport.singleton().resolveOrThrow(type, accessingClass);
101+
assert !result.isPrimitive();
102+
return (InterpreterResolvedObjectType) DynamicHub.fromClass(result).getInterpreterType();
103+
}
100104
}
101105

102106
@Override

substratevm/src/com.oracle.svm.interpreter/src/com/oracle/svm/interpreter/RuntimeInterpreterConstantPool.java

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626

2727
import java.lang.invoke.MethodType;
2828

29+
import org.graalvm.nativeimage.impl.ClassLoading;
30+
31+
import com.oracle.svm.core.hub.DynamicHub;
2932
import com.oracle.svm.core.hub.crema.CremaSupport;
3033
import com.oracle.svm.core.hub.registry.SymbolsSupport;
3134
import com.oracle.svm.core.methodhandles.Target_java_lang_invoke_MethodHandleNatives;
@@ -137,32 +140,41 @@ private String resolveStringConstant(int stringIndex, @SuppressWarnings("unused"
137140
return string;
138141
}
139142

140-
private InterpreterResolvedJavaType resolveClassConstant(int classIndex, InterpreterResolvedJavaType accessingKlass) {
143+
private static InterpreterResolvedObjectType resolveObjectType(Symbol<Type> type, InterpreterResolvedObjectType accessingClass) {
144+
DynamicHub hub = DynamicHub.fromClass(CremaSupport.singleton().resolveOrThrow(type, accessingClass));
145+
assert !hub.isPrimitive();
146+
return (InterpreterResolvedObjectType) hub.getInterpreterType();
147+
}
148+
149+
private InterpreterResolvedJavaType resolveClassConstant(int classIndex, InterpreterResolvedObjectType accessingKlass) {
141150
assert accessingKlass != null;
142151
assert tagAt(classIndex) == Tag.CLASS;
143152

144153
Object entry = this.cachedEntries[classIndex];
145154
Symbol<Type> type = null;
146155

156+
boolean allowArbitraryClassLoading;
147157
if (entry == null) {
148158
// CP comes from dynamically loaded .class file.
149159
Symbol<Name> className = this.className(classIndex);
150160
type = SymbolsSupport.getTypes().fromClassNameEntry(className);
161+
allowArbitraryClassLoading = true;
151162
} else if (entry instanceof UnresolvedJavaType unresolvedJavaType) {
152163
Throwable cause = unresolvedJavaType.getCause();
153164
if (cause != null) {
154165
throw uncheckedThrow(cause);
155166
}
156167
// CP comes from build-time JVMCI type, derive type from UnresolvedJavaType.
157168
type = SymbolsSupport.getTypes().getOrCreateValidType(unresolvedJavaType.getName());
169+
allowArbitraryClassLoading = false;
158170
} else {
159171
throw VMError.shouldNotReachHere("Invalid cached CP entry, expected unresolved type, but got " + entry);
160172
}
161173

162174
assert type != null;
163175

164-
try {
165-
InterpreterResolvedObjectType result = CremaRuntimeAccess.getInstance().lookupOrLoadType(type, accessingKlass);
176+
try (var _ = ClassLoading.allowArbitraryClassLoading(allowArbitraryClassLoading)) {
177+
InterpreterResolvedObjectType result = resolveObjectType(type, accessingKlass);
166178
return result;
167179
} catch (LinkageError e) {
168180
// Comment from Hotspot:
@@ -201,7 +213,7 @@ private InterpreterResolvedJavaField resolveFieldRefConstant(int fieldIndex, Int
201213
Symbol<Type> holderType = SymbolsSupport.getTypes().getOrCreateValidType(unresolvedJavaField.getDeclaringClass().getName());
202214
assert !TypeSymbols.isPrimitive(holderType) && !TypeSymbols.isArray(holderType);
203215
// Perf. note: The holder is re-resolved every-time (never cached).
204-
holder = CremaRuntimeAccess.getInstance().lookupOrLoadType(holderType, accessingClass);
216+
holder = resolveObjectType(holderType, accessingClass);
205217
} else {
206218
throw VMError.shouldNotReachHere("Invalid cached CP entry, expected unresolved field, but got " + entry);
207219
}
@@ -237,7 +249,7 @@ private InterpreterResolvedJavaMethod resolveClassMethodRefConstant(int methodIn
237249
methodSignature = SymbolsSupport.getSignatures().getOrCreateValidSignature(unresolvedJavaMethod.getSignature().toMethodDescriptor());
238250
Symbol<Type> holderType = SymbolsSupport.getTypes().getOrCreateValidType(unresolvedJavaMethod.getDeclaringClass().getName());
239251
// Perf. note: The holder is re-resolved every-time (never cached).
240-
holder = CremaRuntimeAccess.getInstance().lookupOrLoadType(holderType, accessingClass);
252+
holder = resolveObjectType(holderType, accessingClass);
241253
} else {
242254
throw VMError.shouldNotReachHere("Invalid cached CP entry, expected unresolved method, but got " + entry);
243255
}
@@ -275,7 +287,7 @@ private InterpreterResolvedJavaMethod resolveInterfaceMethodRefConstant(int inte
275287
methodSignature = SymbolsSupport.getSignatures().getOrCreateValidSignature(unresolvedJavaMethod.getSignature().toMethodDescriptor());
276288
Symbol<Type> holderType = SymbolsSupport.getTypes().getOrCreateValidType(unresolvedJavaMethod.getDeclaringClass().getName());
277289
// Perf. note: The holder is re-resolved every-time (never cached).
278-
holder = CremaRuntimeAccess.getInstance().lookupOrLoadType(holderType, accessingClass);
290+
holder = resolveObjectType(holderType, accessingClass);
279291
} else {
280292
throw VMError.shouldNotReachHere("Invalid cached CP entry, expected unresolved method, but got " + entry);
281293
}
@@ -322,8 +334,10 @@ public static MethodType signatureToMethodType(Symbol<Type>[] signature, Interpr
322334
}
323335

324336
private static Class<?> resolveSymbolAndAccessCheck(InterpreterResolvedObjectType accessingClass, Symbol<Type> type) {
325-
Class<?> clazz = CremaSupport.singleton().resolveOrThrow(type, accessingClass);
326-
// GR-62339 check access
327-
return clazz;
337+
try (var _ = ClassLoading.allowArbitraryClassLoading()) {
338+
Class<?> clazz = CremaSupport.singleton().resolveOrThrow(type, accessingClass);
339+
// GR-62339 check access
340+
return clazz;
341+
}
328342
}
329343
}

0 commit comments

Comments
 (0)