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