1 package jdk.incubator.code.dialect.java.impl;
2
3 import jdk.incubator.code.CodeType;
4 import jdk.incubator.code.dialect.core.FunctionType;
5 import jdk.incubator.code.dialect.java.FieldRef;
6 import jdk.incubator.code.dialect.java.JavaOp.InvokeOp.InvokeKind;
7 import jdk.incubator.code.dialect.java.JavaType;
8 import jdk.incubator.code.dialect.java.MethodRef;
9
10 import java.lang.constant.Constable;
11 import java.lang.invoke.MethodHandle;
12 import java.lang.invoke.MethodHandles;
13 import java.lang.invoke.MethodHandles.Lookup;
14 import java.lang.invoke.MethodType;
15 import java.lang.invoke.TypeDescriptor;
16 import java.lang.invoke.VarHandle;
17 import java.util.function.Supplier;
18
19 public class ResolutionHelper {
20 interface HandleResolver<X extends Constable, T extends TypeDescriptor> {
21 X resolve(Lookup lookup, Class<?> refc, String name, T type) throws ReflectiveOperationException;
22
23 HandleResolver<MethodHandle, MethodType> FIND_STATIC = MethodHandles.Lookup::findStatic;
24 HandleResolver<MethodHandle, MethodType> FIND_VIRTUAL = MethodHandles.Lookup::findVirtual;
25 HandleResolver<MethodHandle, MethodType> FIND_SPECIAL = (l, refc, name, type) -> l.findSpecial(refc, name, type, l.lookupClass());
26 HandleResolver<MethodHandle, MethodType> FIND_CONSTRUCTOR = (l, refc, name, type) -> l.findConstructor(refc, type);
27 HandleResolver<MethodHandle, Class<?>> FIND_STATIC_GETTER = MethodHandles.Lookup::findStaticGetter;
28 HandleResolver<MethodHandle, Class<?>> FIND_GETTER = MethodHandles.Lookup::findGetter;
29 HandleResolver<VarHandle, Class<?>> FIND_STATIC_VARHANDLE = MethodHandles.Lookup::findStaticVarHandle;
30 HandleResolver<VarHandle, Class<?>> FIND_VARHANDLE = MethodHandles.Lookup::findVarHandle;
31 }
32
33 sealed interface Result<H extends Constable> {
34 H handle() throws ReflectiveOperationException;
35
36 default Result<H> orElse(Supplier<Result<H>> resultSupplier) {
37 if (this instanceof Success<?>) return this;
38 else return resultSupplier.get();
39 }
40 }
41 record Success<H extends Constable>(H handle) implements Result<H> { }
42 record Failure<H extends Constable>(ReflectiveOperationException error) implements Result<H> {
43 @Override
44 public H handle() throws ReflectiveOperationException {
45 throw error;
46 }
47 }
48
49 static <Z extends Constable, T extends TypeDescriptor> Result<Z> resolveHandle(HandleResolver<Z, T> resolver, MethodHandles.Lookup l, Class<?> refc, String name, T type) {
50 try {
51 Z res = resolver.resolve(l, refc, name, type);
52 return new Success<>(res);
53 } catch (ReflectiveOperationException ex) {
54 return new Failure<>(ex);
55 }
56 }
57
58 // public API
59
60 public static Class<?> resolveClass(MethodHandles.Lookup l, CodeType t) throws ReflectiveOperationException {
61 if (t instanceof JavaType jt) {
62 return (Class<?>)jt.erasure().resolve(l);
63 } else {
64 throw new UnsupportedOperationException();
65 }
66 }
67
68 public static MethodType resolveMethodType(MethodHandles.Lookup l, FunctionType ft) throws ReflectiveOperationException {
69 return MethodRef.toNominalDescriptor(ft)
70 .resolveConstantDesc(l);
71 }
72
73 public static MethodHandle resolveMethod(MethodHandles.Lookup l, MethodRef methodRef, InvokeKind kind) throws ReflectiveOperationException {
74 Class<?> refC = resolveClass(l, methodRef.refType());
75 MethodType mt = resolveMethodType(l, methodRef.signature());
76 HandleResolver<MethodHandle, MethodType> resolver = switch (kind) {
77 case INSTANCE -> HandleResolver.FIND_VIRTUAL;
78 case STATIC -> HandleResolver.FIND_STATIC;
79 case SUPER -> HandleResolver.FIND_SPECIAL;
80 };
81 return resolveHandle(resolver, l, refC, methodRef.name(), mt).handle();
82 }
83
84 public static MethodHandle resolveMethod(MethodHandles.Lookup l, MethodRef methodRef) throws ReflectiveOperationException {
85 Class<?> refC = resolveClass(l, methodRef.refType());
86 MethodType mt = resolveMethodType(l, methodRef.signature());
87 return resolveHandle(HandleResolver.FIND_STATIC, l, refC, methodRef.name(), mt)
88 .orElse(() -> resolveHandle(HandleResolver.FIND_VIRTUAL, l, refC, methodRef.name(), mt))
89 .handle();
90 }
91
92 public static MethodHandle resolveFieldGetter(MethodHandles.Lookup l, FieldRef fieldRef) throws ReflectiveOperationException {
93 Class<?> refC = resolveClass(l, fieldRef.refType());
94 Class<?> ft = resolveClass(l, fieldRef.type());
95 return resolveHandle(HandleResolver.FIND_STATIC_GETTER, l, refC, fieldRef.name(), ft)
96 .orElse(() -> resolveHandle(HandleResolver.FIND_GETTER, l, refC, fieldRef.name(), ft))
97 .handle();
98 }
99
100 public static VarHandle resolveFieldHandle(MethodHandles.Lookup l, FieldRef fieldRef) throws ReflectiveOperationException {
101 Class<?> refC = resolveClass(l, fieldRef.refType());
102 Class<?> ft = resolveClass(l, fieldRef.type());
103 return resolveHandle(HandleResolver.FIND_STATIC_VARHANDLE, l, refC, fieldRef.name(), ft)
104 .orElse(() -> resolveHandle(HandleResolver.FIND_VARHANDLE, l, refC, fieldRef.name(), ft))
105 .handle();
106 }
107
108 public static MethodHandle resolveConstructor(MethodHandles.Lookup l, Class<?> refc, MethodType type) throws ReflectiveOperationException {
109 return resolveHandle(HandleResolver.FIND_CONSTRUCTOR, l, refc, null, type).handle();
110 }
111 }