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 // public API
83
84 public static Class<?> resolveClass(MethodHandles.Lookup l, CodeType t) throws ReflectiveOperationException {
85 if (t instanceof JavaType jt) {
86 return (Class<?>)jt.erasure().resolve(l);
87 } else {
88 throw new UnsupportedOperationException();
89 }
90 }
91
92 public static MethodType resolveMethodType(MethodHandles.Lookup l, FunctionType ft) throws ReflectiveOperationException {
93 return MethodRef.toNominalDescriptor(ft)
94 .resolveConstantDesc(l);
95 }
96
97 public static MethodHandle resolveMethod(MethodHandles.Lookup l, MethodRef methodRef, InvokeKind kind) throws ReflectiveOperationException {
98 Class<?> refC = resolveClass(l, methodRef.refType());
99 MethodType mt = resolveMethodType(l, methodRef.signature());
100 HandleResolver<MethodHandle, MethodType> resolver = switch (kind) {
101 case INSTANCE -> HandleResolver.FIND_VIRTUAL;
102 case STATIC -> HandleResolver.FIND_STATIC;
103 case SUPER -> HandleResolver.FIND_SPECIAL;
104 };
105 return resolveHandle(resolver, l, refC, methodRef.name(), mt).handle();
106 }
107
108 public static MethodHandle resolveMethod(MethodHandles.Lookup l, MethodRef methodRef) throws ReflectiveOperationException {
109 Class<?> refC = resolveClass(l, methodRef.refType());
110 MethodType mt = resolveMethodType(l, methodRef.signature());
111 return resolveHandle(HandleResolver.FIND_STATIC, l, refC, methodRef.name(), mt)
112 .orElse(() -> resolveHandle(HandleResolver.FIND_VIRTUAL, l, refC, methodRef.name(), mt))
113 .handle();
114 }
115
116 public static MethodHandle resolveFieldGetter(MethodHandles.Lookup l, FieldRef fieldRef) throws ReflectiveOperationException {
117 Class<?> refC = resolveClass(l, fieldRef.refType());
118 Class<?> ft = resolveClass(l, fieldRef.type());
119 return resolveHandle(HandleResolver.FIND_STATIC_GETTER, l, refC, fieldRef.name(), ft)
120 .orElse(() -> resolveHandle(HandleResolver.FIND_GETTER, l, refC, fieldRef.name(), ft))
121 .handle();
122 }
123
124 public static VarHandle resolveFieldHandle(MethodHandles.Lookup l, FieldRef fieldRef) throws ReflectiveOperationException {
125 Class<?> refC = resolveClass(l, fieldRef.refType());
126 Class<?> ft = resolveClass(l, fieldRef.type());
127 return resolveHandle(HandleResolver.FIND_STATIC_VARHANDLE, l, refC, fieldRef.name(), ft)
128 .orElse(() -> resolveHandle(HandleResolver.FIND_VARHANDLE, l, refC, fieldRef.name(), ft))
129 .handle();
130 }
131
132 public static MethodHandle resolveConstructor(MethodHandles.Lookup l, Class<?> refc, MethodType type) throws ReflectiveOperationException {
133 return resolveHandle(HandleResolver.FIND_CONSTRUCTOR, l, refc, null, type).handle();
134 }
135 }