1 /*
2 * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package jdk.incubator.code.dialect.java.impl;
26
27 import jdk.incubator.code.CodeType;
28 import jdk.incubator.code.dialect.core.FunctionType;
29 import jdk.incubator.code.dialect.java.FieldRef;
30 import jdk.incubator.code.dialect.java.JavaOp.InvokeOp.InvokeKind;
31 import jdk.incubator.code.dialect.java.JavaType;
32 import jdk.incubator.code.dialect.java.MethodRef;
33
34 import java.lang.constant.Constable;
35 import java.lang.invoke.MethodHandle;
36 import java.lang.invoke.MethodHandles;
37 import java.lang.invoke.MethodHandles.Lookup;
38 import java.lang.invoke.MethodType;
39 import java.lang.invoke.TypeDescriptor;
40 import java.lang.invoke.VarHandle;
41 import java.util.function.Supplier;
42
43 public class ResolutionHelper {
44 interface HandleResolver<X extends Constable, T extends TypeDescriptor> {
45 X resolve(Lookup lookup, Class<?> refc, String name, T type) throws ReflectiveOperationException;
46
47 HandleResolver<MethodHandle, MethodType> FIND_STATIC = MethodHandles.Lookup::findStatic;
48 HandleResolver<MethodHandle, MethodType> FIND_VIRTUAL = MethodHandles.Lookup::findVirtual;
49 HandleResolver<MethodHandle, MethodType> FIND_SPECIAL = (l, refc, name, type) -> l.findSpecial(refc, name, type, l.lookupClass());
50 HandleResolver<MethodHandle, MethodType> FIND_CONSTRUCTOR = (l, refc, name, type) -> l.findConstructor(refc, type);
51 HandleResolver<MethodHandle, Class<?>> FIND_STATIC_GETTER = MethodHandles.Lookup::findStaticGetter;
52 HandleResolver<MethodHandle, Class<?>> FIND_GETTER = MethodHandles.Lookup::findGetter;
53 HandleResolver<VarHandle, Class<?>> FIND_STATIC_VARHANDLE = MethodHandles.Lookup::findStaticVarHandle;
54 HandleResolver<VarHandle, Class<?>> FIND_VARHANDLE = MethodHandles.Lookup::findVarHandle;
55 }
56
57 sealed interface Result<H extends Constable> {
58 H handle() throws ReflectiveOperationException;
59
60 default Result<H> orElse(Supplier<Result<H>> resultSupplier) {
61 if (this instanceof Success<?>) return this;
62 else return resultSupplier.get();
63 }
64 }
65 record Success<H extends Constable>(H handle) implements Result<H> { }
66 record Failure<H extends Constable>(ReflectiveOperationException error) implements Result<H> {
67 @Override
68 public H handle() throws ReflectiveOperationException {
69 throw error;
70 }
71 }
72
73 static <Z extends Constable, T extends TypeDescriptor> Result<Z> resolveHandle(HandleResolver<Z, T> resolver, MethodHandles.Lookup l, Class<?> refc, String name, T type) {
74 try {
75 Z res = resolver.resolve(l, refc, name, type);
76 return new Success<>(res);
77 } catch (ReflectiveOperationException ex) {
78 return new Failure<>(ex);
79 }
80 }
81
82 static MethodType toMethodType(MethodHandles.Lookup l, FunctionType ft) throws ReflectiveOperationException {
83 try {
84 return MethodType.fromMethodDescriptorString(MethodRef.toNominalDescriptor(ft).descriptorString(),
85 l.lookupClass().getClassLoader());
86 } catch (TypeNotPresentException ex) {
87 throw (ClassNotFoundException) ex.getCause();
88 }
89 }
90
91 // public API
92
93 public static Class<?> resolveClass(MethodHandles.Lookup l, CodeType t) throws ReflectiveOperationException {
94 if (t instanceof JavaType jt) {
95 return (Class<?>)jt.erasure().resolve(l);
96 } else {
97 throw new UnsupportedOperationException();
98 }
99 }
100
101 public static MethodType resolveMethodType(MethodHandles.Lookup l, FunctionType ft) throws ReflectiveOperationException {
102 return MethodRef.toNominalDescriptor(ft)
103 .resolveConstantDesc(l);
104 }
105
106 public static MethodHandle resolveMethod(MethodHandles.Lookup l, MethodRef methodRef, InvokeKind kind) throws ReflectiveOperationException {
107 Class<?> refC = resolveClass(l, methodRef.refType());
108 MethodType mt = toMethodType(l, methodRef.signature());
109 HandleResolver<MethodHandle, MethodType> resolver = switch (kind) {
110 case INSTANCE -> HandleResolver.FIND_VIRTUAL;
111 case STATIC -> HandleResolver.FIND_STATIC;
112 case SUPER -> HandleResolver.FIND_SPECIAL;
113 };
114 return resolveHandle(resolver, l, refC, methodRef.name(), mt).handle();
115 }
116
117 public static MethodHandle resolveMethod(MethodHandles.Lookup l, MethodRef methodRef) throws ReflectiveOperationException {
118 Class<?> refC = resolveClass(l, methodRef.refType());
119 MethodType mt = toMethodType(l, methodRef.signature());
120 return resolveHandle(HandleResolver.FIND_STATIC, l, refC, methodRef.name(), mt)
121 .orElse(() -> resolveHandle(HandleResolver.FIND_VIRTUAL, l, refC, methodRef.name(), mt))
122 .handle();
123 }
124
125 public static MethodHandle resolveFieldGetter(MethodHandles.Lookup l, FieldRef fieldRef) throws ReflectiveOperationException {
126 Class<?> refC = resolveClass(l, fieldRef.refType());
127 Class<?> ft = resolveClass(l, fieldRef.type());
128 return resolveHandle(HandleResolver.FIND_STATIC_GETTER, l, refC, fieldRef.name(), ft)
129 .orElse(() -> resolveHandle(HandleResolver.FIND_GETTER, l, refC, fieldRef.name(), ft))
130 .handle();
131 }
132
133 public static VarHandle resolveFieldHandle(MethodHandles.Lookup l, FieldRef fieldRef) throws ReflectiveOperationException {
134 Class<?> refC = resolveClass(l, fieldRef.refType());
135 Class<?> ft = resolveClass(l, fieldRef.type());
136 return resolveHandle(HandleResolver.FIND_STATIC_VARHANDLE, l, refC, fieldRef.name(), ft)
137 .orElse(() -> resolveHandle(HandleResolver.FIND_VARHANDLE, l, refC, fieldRef.name(), ft))
138 .handle();
139 }
140
141 public static MethodHandle resolveConstructor(MethodHandles.Lookup l, Class<?> refc, MethodType type) throws ReflectiveOperationException {
142 return resolveHandle(HandleResolver.FIND_CONSTRUCTOR, l, refc, null, type).handle();
143 }
144 }