Skip to content

Commit 296016f

Browse files
CremaSupport: improve type resolution
* Allow resolving array types * Add methods for resolving symbols directly
1 parent 93190ed commit 296016f

File tree

3 files changed

+87
-59
lines changed

3 files changed

+87
-59
lines changed

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

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,11 @@
3131
import org.graalvm.nativeimage.Platforms;
3232

3333
import com.oracle.svm.core.hub.DynamicHub;
34+
import com.oracle.svm.core.hub.registry.SymbolsSupport;
3435
import com.oracle.svm.espresso.classfile.ParserKlass;
36+
import com.oracle.svm.espresso.classfile.descriptors.ByteSequence;
37+
import com.oracle.svm.espresso.classfile.descriptors.Symbol;
38+
import com.oracle.svm.espresso.classfile.descriptors.Type;
3539

3640
import jdk.vm.ci.meta.JavaType;
3741
import jdk.vm.ci.meta.ResolvedJavaMethod;
@@ -63,11 +67,29 @@ interface CremaDispatchTable {
6367

6468
Class<?> toClass(ResolvedJavaType resolvedJavaType);
6569

66-
Class<?> resolveOrThrow(JavaType unresolvedJavaType, ResolvedJavaType accessingClass);
70+
default Class<?> resolveOrThrow(JavaType unresolvedJavaType, ResolvedJavaType accessingClass) {
71+
ByteSequence type = ByteSequence.create(unresolvedJavaType.getName());
72+
Symbol<Type> symbolicType = SymbolsSupport.getTypes().getOrCreateValidType(type);
73+
return resolveOrThrow(symbolicType, accessingClass);
74+
}
75+
76+
Class<?> resolveOrThrow(Symbol<Type> type, ResolvedJavaType accessingClass);
77+
78+
default Class<?> resolveOrNull(JavaType unresolvedJavaType, ResolvedJavaType accessingClass) {
79+
ByteSequence type = ByteSequence.create(unresolvedJavaType.getName());
80+
Symbol<Type> symbolicType = SymbolsSupport.getTypes().getOrCreateValidType(type);
81+
return resolveOrNull(symbolicType, accessingClass);
82+
}
83+
84+
Class<?> resolveOrNull(Symbol<Type> type, ResolvedJavaType accessingClass);
6785

68-
Class<?> resolveOrNull(JavaType unresolvedJavaType, ResolvedJavaType accessingClass);
86+
default Class<?> findLoadedClass(JavaType unresolvedJavaType, ResolvedJavaType accessingClass) {
87+
ByteSequence type = ByteSequence.create(unresolvedJavaType.getName());
88+
Symbol<Type> symbolicType = SymbolsSupport.getTypes().getOrCreateValidType(type);
89+
return findLoadedClass(symbolicType, accessingClass);
90+
}
6991

70-
Class<?> findLoadedClass(JavaType unresolvedJavaType, ResolvedJavaType accessingClass);
92+
Class<?> findLoadedClass(Symbol<Type> type, ResolvedJavaType accessingClass);
7193

7294
Object getStaticStorage(Class<?> cls, boolean primitives, int layerNum);
7395

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

Lines changed: 4 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
import java.lang.invoke.MethodType;
2929

3030
import com.oracle.svm.core.hub.DynamicHub;
31-
import com.oracle.svm.core.hub.registry.ClassRegistries;
31+
import com.oracle.svm.core.hub.crema.CremaSupport;
3232
import com.oracle.svm.core.hub.registry.SymbolsSupport;
3333
import com.oracle.svm.core.util.VMError;
3434
import com.oracle.svm.espresso.classfile.JavaVersion;
@@ -92,37 +92,11 @@ public RuntimeException throwError(ErrorType errorType, String messageFormat, Ob
9292
throw fatal(message);
9393
}
9494

95-
private static String toClassForName(Symbol<Type> type) {
96-
String typeString = type.toString();
97-
if (TypeSymbols.isArray(type)) {
98-
return typeString.replace('/', '.');
99-
}
100-
// Primitives cannot be resolved via Class.forName, but provide name for completeness.
101-
if (TypeSymbols.isPrimitive(type)) {
102-
// I -> int
103-
// Z -> boolean
104-
// ...
105-
return TypeSymbols.getJavaKind(type).toJavaClass().getName();
106-
}
107-
assert typeString.startsWith("L") && typeString.endsWith(";");
108-
return typeString.substring(1, typeString.length() - 1); // drop L and ;
109-
}
110-
111-
@SuppressWarnings("unchecked")
112-
public static <T extends Throwable> RuntimeException uncheckedThrow(Throwable t) throws T {
113-
throw (T) t;
114-
}
115-
11695
@Override
11796
public InterpreterResolvedObjectType lookupOrLoadType(Symbol<Type> type, InterpreterResolvedJavaType accessingClass) {
118-
String className = toClassForName(type);
119-
try {
120-
Class<?> result = ClassRegistries.forName(className, accessingClass.getJavaClass().getClassLoader());
121-
assert !result.isPrimitive();
122-
return (InterpreterResolvedObjectType) DynamicHub.fromClass(result).getInterpreterType();
123-
} catch (ClassNotFoundException e) {
124-
throw uncheckedThrow(e);
125-
}
97+
Class<?> result = CremaSupport.singleton().resolveOrThrow(type, accessingClass);
98+
assert !result.isPrimitive();
99+
return (InterpreterResolvedObjectType) DynamicHub.fromClass(result).getInterpreterType();
126100
}
127101

128102
@Override

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

Lines changed: 58 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -52,18 +52,20 @@
5252
import com.oracle.svm.core.hub.registry.ClassRegistries;
5353
import com.oracle.svm.core.hub.registry.SymbolsSupport;
5454
import com.oracle.svm.core.meta.MethodPointer;
55+
import com.oracle.svm.core.util.VMError;
5556
import com.oracle.svm.espresso.classfile.ConstantPool;
57+
import com.oracle.svm.espresso.classfile.JavaKind;
5658
import com.oracle.svm.espresso.classfile.ParserField;
5759
import com.oracle.svm.espresso.classfile.ParserKlass;
5860
import com.oracle.svm.espresso.classfile.ParserMethod;
5961
import com.oracle.svm.espresso.classfile.attributes.Attribute;
6062
import com.oracle.svm.espresso.classfile.attributes.ConstantValueAttribute;
61-
import com.oracle.svm.espresso.classfile.descriptors.ByteSequence;
6263
import com.oracle.svm.espresso.classfile.descriptors.Name;
6364
import com.oracle.svm.espresso.classfile.descriptors.ParserSymbols;
6465
import com.oracle.svm.espresso.classfile.descriptors.Signature;
6566
import com.oracle.svm.espresso.classfile.descriptors.Symbol;
6667
import com.oracle.svm.espresso.classfile.descriptors.Type;
68+
import com.oracle.svm.espresso.classfile.descriptors.TypeSymbols;
6769
import com.oracle.svm.espresso.shared.vtable.MethodTableException;
6870
import com.oracle.svm.espresso.shared.vtable.PartialMethod;
6971
import com.oracle.svm.espresso.shared.vtable.PartialType;
@@ -80,7 +82,6 @@
8082
import com.oracle.svm.interpreter.metadata.InterpreterResolvedObjectType;
8183

8284
import jdk.graal.compiler.word.Word;
83-
import jdk.vm.ci.meta.JavaType;
8485
import jdk.vm.ci.meta.ResolvedJavaField;
8586
import jdk.vm.ci.meta.ResolvedJavaMethod;
8687
import jdk.vm.ci.meta.ResolvedJavaType;
@@ -638,50 +639,81 @@ public Class<?> toClass(ResolvedJavaType resolvedJavaType) {
638639
}
639640

640641
@Override
641-
public Class<?> resolveOrThrow(JavaType unresolvedJavaType, ResolvedJavaType accessingClass) {
642+
public Class<?> resolveOrThrow(Symbol<Type> type, ResolvedJavaType accessingClass) {
643+
int arrayDimensions = TypeSymbols.getArrayDimensions(type);
644+
Symbol<Type> elementalType;
645+
if (arrayDimensions == 0) {
646+
elementalType = type;
647+
} else {
648+
elementalType = SymbolsSupport.getTypes().getOrCreateValidType(type.subSequence(arrayDimensions));
649+
}
642650
try {
643-
Class<?> result = loadClass(unresolvedJavaType, (InterpreterResolvedJavaType) accessingClass);
651+
Class<?> result = loadClass(elementalType, (InterpreterResolvedJavaType) accessingClass);
644652
if (result == null) {
645-
throw new NoClassDefFoundError(getTypeName(unresolvedJavaType));
646-
} else {
647-
return result;
653+
throw new NoClassDefFoundError(elementalType.toString());
654+
}
655+
if (arrayDimensions > 0) {
656+
while (arrayDimensions-- > 0) {
657+
result = DynamicHub.toClass(DynamicHub.fromClass(result).arrayType());
658+
}
648659
}
660+
return result;
649661
} catch (ClassNotFoundException e) {
650-
NoClassDefFoundError error = new NoClassDefFoundError(getTypeName(unresolvedJavaType));
662+
NoClassDefFoundError error = new NoClassDefFoundError(elementalType.toString());
651663
error.initCause(e);
652664
throw error;
653665
}
654666
}
655667

656-
private static String getTypeName(JavaType unresolvedJavaType) {
657-
assert unresolvedJavaType.getElementalType().getName().startsWith("L");
658-
659-
String internalName = unresolvedJavaType.getElementalType().getName();
660-
return internalName.substring(1, internalName.length() - 1);
661-
}
662-
663668
@Override
664-
public Class<?> resolveOrNull(JavaType unresolvedJavaType, ResolvedJavaType accessingClass) {
669+
public Class<?> resolveOrNull(Symbol<Type> type, ResolvedJavaType accessingClass) {
670+
int arrayDimensions = TypeSymbols.getArrayDimensions(type);
671+
Symbol<Type> elementalType;
672+
if (arrayDimensions == 0) {
673+
elementalType = type;
674+
} else {
675+
elementalType = SymbolsSupport.getTypes().getOrCreateValidType(type.subSequence(arrayDimensions));
676+
}
665677
try {
666-
return loadClass(unresolvedJavaType, (InterpreterResolvedJavaType) accessingClass);
678+
Class<?> result = loadClass(elementalType, (InterpreterResolvedJavaType) accessingClass);
679+
if (result == null) {
680+
return null;
681+
}
682+
if (arrayDimensions > 0) {
683+
while (arrayDimensions-- > 0) {
684+
result = DynamicHub.toClass(DynamicHub.fromClass(result).arrayType());
685+
}
686+
}
687+
return result;
667688
} catch (ClassNotFoundException e) {
668689
return null;
669690
}
670691
}
671692

672-
private static Class<?> loadClass(JavaType unresolvedJavaType, InterpreterResolvedJavaType accessingClass) throws ClassNotFoundException {
673-
ByteSequence type = ByteSequence.create(unresolvedJavaType.getName());
674-
Symbol<Type> symbolicType = SymbolsSupport.getTypes().getOrCreateValidType(type);
675-
AbstractClassRegistry registry = ClassRegistries.singleton().getRegistry(accessingClass.getJavaClass().getClassLoader());
676-
return registry.loadClass(symbolicType);
693+
private static Class<?> loadClass(Symbol<Type> type, InterpreterResolvedJavaType accessingClass) throws ClassNotFoundException {
694+
JavaKind kind = TypeSymbols.getJavaKind(type);
695+
return switch (kind) {
696+
case Object -> {
697+
AbstractClassRegistry registry = ClassRegistries.singleton().getRegistry(accessingClass.getJavaClass().getClassLoader());
698+
yield registry.loadClass(type);
699+
}
700+
case Boolean -> boolean.class;
701+
case Byte -> byte.class;
702+
case Short -> short.class;
703+
case Char -> char.class;
704+
case Int -> int.class;
705+
case Long -> long.class;
706+
case Float -> float.class;
707+
case Double -> double.class;
708+
case Void -> void.class;
709+
default -> throw VMError.shouldNotReachHere(kind.toString());
710+
};
677711
}
678712

679713
@Override
680-
public Class<?> findLoadedClass(JavaType unresolvedJavaType, ResolvedJavaType accessingClass) {
681-
ByteSequence type = ByteSequence.create(unresolvedJavaType.getName());
682-
Symbol<Type> symbolicType = SymbolsSupport.getTypes().getOrCreateValidType(type);
714+
public Class<?> findLoadedClass(Symbol<Type> type, ResolvedJavaType accessingClass) {
683715
AbstractClassRegistry registry = ClassRegistries.singleton().getRegistry(((InterpreterResolvedJavaType) accessingClass).getJavaClass().getClassLoader());
684-
return registry.findLoadedClass(symbolicType);
716+
return registry.findLoadedClass(type);
685717
}
686718

687719
@Override

0 commit comments

Comments
 (0)