1 /* 2 * Copyright (c) 2024, 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 26 package java.lang.reflect.code.type; 27 28 import java.lang.constant.ClassDesc; 29 import java.lang.constant.MethodTypeDesc; 30 import java.lang.reflect.code.op.CoreOp; 31 import java.lang.reflect.code.type.impl.MethodRefImpl; 32 import java.lang.invoke.MethodHandle; 33 import java.lang.invoke.MethodHandles; 34 import java.lang.invoke.MethodType; 35 import java.lang.reflect.Executable; 36 import java.lang.reflect.Method; 37 import java.lang.reflect.code.TypeElement; 38 import java.util.List; 39 import java.util.Optional; 40 41 import static java.lang.reflect.code.type.FunctionType.functionType; 42 43 /** 44 * The symbolic reference to a Java method. 45 */ 46 // @@@ require invoke kind: 47 // special, static, virtual 48 // interface_special, interface_static, interface_virtual 49 // Otherwise it is not possible to generate correct bytecode invoke instruction with 50 // a symbolic reference to a method or an interface method, specifically a 51 // constant pool entry of CONSTANT_Methodref_info or CONSTANT_InterfaceMethodref_info. 52 // 53 // We can infer the kind, if we can resolve the types and lookup the declared method 54 public sealed interface MethodRef extends TypeVarRef.Owner permits MethodRefImpl { 55 56 TypeElement refType(); 57 58 String name(); 59 60 FunctionType type(); 61 62 // Resolutions and model access 63 64 Executable resolveToMember(MethodHandles.Lookup l) throws ReflectiveOperationException; 65 66 MethodHandle resolveToHandle(MethodHandles.Lookup l) throws ReflectiveOperationException; 67 68 Optional<CoreOp.FuncOp> codeModel(MethodHandles.Lookup l) throws ReflectiveOperationException; 69 70 // Factories 71 72 static MethodRef method(Executable e) { 73 return method(e.getDeclaringClass(), e.getName(), 74 e instanceof Method m ? m.getReturnType() : e.getDeclaringClass(), 75 e.getParameterTypes()); 76 } 77 78 static MethodRef method(Class<?> refType, String name, MethodType mt) { 79 return method(refType, name, mt.returnType(), mt.parameterList()); 80 } 81 82 static MethodRef method(Class<?> refType, String name, Class<?> retType, Class<?>... params) { 83 return method(refType, name, retType, List.of(params)); 84 } 85 86 static MethodRef method(Class<?> refType, String name, Class<?> retType, List<Class<?>> params) { 87 return method(JavaType.type(refType), name, JavaType.type(retType), params.stream().map(JavaType::type).toList()); 88 } 89 90 91 static MethodRef method(TypeElement refType, String name, FunctionType type) { 92 return new MethodRefImpl(refType, name, type); 93 } 94 95 static MethodRef method(TypeElement refType, String name, TypeElement retType, TypeElement... params) { 96 return method(refType, name, functionType(retType, params)); 97 } 98 99 static MethodRef method(TypeElement refType, String name, TypeElement retType, List<? extends TypeElement> params) { 100 return method(refType, name, functionType(retType, params)); 101 } 102 103 // Copied code in jdk.compiler module throws UOE 104 static MethodRef ofString(String s) { 105 /*__throw new UnsupportedOperationException();__*/ return java.lang.reflect.code.parser.impl.DescParser.parseMethodRef(s); 106 } 107 108 109 // MethodTypeDesc factories 110 // @@@ Where else to place them? 111 112 static FunctionType ofNominalDescriptor(MethodTypeDesc d) { 113 return FunctionType.functionType( 114 JavaType.type(d.returnType()), 115 d.parameterList().stream().map(JavaType::type).toList()); 116 } 117 118 static MethodTypeDesc toNominalDescriptor(FunctionType t) { 119 return MethodTypeDesc.of( 120 toClassDesc(t.returnType()), 121 t.parameterTypes().stream().map(MethodRef::toClassDesc).toList()); 122 } 123 124 private static ClassDesc toClassDesc(TypeElement e) { 125 if (!(e instanceof JavaType jt)) { 126 throw new IllegalArgumentException(); 127 } 128 129 return jt.toNominalDescriptor(); 130 } 131 }