1 /*
  2  * Copyright (c) 2018, 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 java.lang.constant;
 26 
 27 import java.lang.invoke.MethodHandle;
 28 import java.lang.invoke.MethodHandleInfo;
 29 import java.util.OptionalInt;
 30 import java.util.stream.Stream;
 31 
 32 import jdk.internal.vm.annotation.Stable;
 33 
 34 import static java.lang.invoke.MethodHandleInfo.REF_getField;
 35 import static java.lang.invoke.MethodHandleInfo.REF_getStatic;
 36 import static java.lang.invoke.MethodHandleInfo.REF_invokeInterface;
 37 import static java.lang.invoke.MethodHandleInfo.REF_invokeSpecial;
 38 import static java.lang.invoke.MethodHandleInfo.REF_invokeStatic;
 39 import static java.lang.invoke.MethodHandleInfo.REF_invokeVirtual;
 40 import static java.lang.invoke.MethodHandleInfo.REF_newInvokeSpecial;
 41 import static java.lang.invoke.MethodHandleInfo.REF_putField;
 42 import static java.lang.invoke.MethodHandleInfo.REF_putStatic;
 43 
 44 /**
 45  * A <a href="package-summary.html#nominal">nominal descriptor</a> for a direct
 46  * {@link MethodHandle}.  A {@linkplain DirectMethodHandleDesc} corresponds to
 47  * a {@code Constant_MethodHandle_info} entry in the constant pool of a classfile.
 48  *
 49  * @since 12
 50  */
 51 public sealed interface DirectMethodHandleDesc
 52         extends MethodHandleDesc
 53         permits DirectMethodHandleDescImpl {
 54     /**
 55      * Kinds of method handles that can be described with {@linkplain DirectMethodHandleDesc}.
 56      *
 57      * @since 12
 58      */
 59     enum Kind {
 60         /** A method handle for a method invoked as with {@code invokestatic} */
 61         STATIC(REF_invokeStatic),
 62         /** A method handle for a method invoked as with {@code invokestatic} */
 63         INTERFACE_STATIC(REF_invokeStatic, true),
 64         /** A method handle for a method invoked as with {@code invokevirtual} */
 65         VIRTUAL(REF_invokeVirtual),
 66         /** A method handle for a method invoked as with {@code invokeinterface} */
 67         INTERFACE_VIRTUAL(REF_invokeInterface, true),
 68         /** A method handle for a method invoked as with {@code invokespecial} */
 69         SPECIAL(REF_invokeSpecial),
 70         /** A method handle for an interface method invoked as with {@code invokespecial} */
 71         INTERFACE_SPECIAL(REF_invokeSpecial, true),
 72         /** A method handle for a constructor */
 73         CONSTRUCTOR(REF_newInvokeSpecial),
 74         /** A method handle for a read accessor for an instance field  */
 75         GETTER(REF_getField),
 76         /** A method handle for a write accessor for an instance field  */
 77         SETTER(REF_putField),
 78         /** A method handle for a read accessor for a static field  */
 79         STATIC_GETTER(REF_getStatic),
 80         /** A method handle for a write accessor for a static field  */
 81         STATIC_SETTER(REF_putStatic);
 82 
 83         /** The corresponding {@code refKind} value for this kind of method handle,
 84          * as defined by {@link MethodHandleInfo}
 85          */
 86         public final int refKind;
 87 
 88         /** Is this an interface
 89          */
 90         public final boolean isInterface;
 91         Kind(int refKind) {
 92             this(refKind, false);
 93         }
 94 
 95         Kind(int refKind, boolean isInterface) { this.refKind = refKind; this.isInterface = isInterface; }
 96 
 97         /**
 98          * Returns the enumeration member with the given {@code refKind} field.
 99          * Behaves as if {@code valueOf(refKind, false)}.  As a special case,
100          * if {@code refKind} is {@code REF_invokeInterface} (9) then the
101          * {@code isInterface} field will be true.
102          *
103          * @param refKind refKind of desired member
104          * @return the matching enumeration member
105          * @throws IllegalArgumentException if there is no such member
106          */
107         public static Kind valueOf(int refKind) {
108             return valueOf(refKind, refKind == REF_invokeInterface);
109         }
110 
111         /**
112          * Returns the enumeration member with the given the {@code refKind} and
113          * {@code isInterface} arguments.
114          * For most values of {@code refKind} there is an exact match regardless of the value of {@code isInterface}.
115          * These are:
116          * <UL>
117          *     <LI>{@code REF_invokeVirtual} which matches to {@code VIRTUAL}
118          *     <LI>{@code REF_invokeInterface} which matches to {@code INTERFACE_VIRTUAL}
119          *     <LI>{@code REF_newInvokeSpecial} which matches to {@code CONSTRUCTOR}
120          *     <LI>{@code REF_getField} which matches to {@code GETTER}
121          *     <LI>{@code REF_putField} which matches to {@code SETTER}
122          *     <LI>{@code REF_getStatic} which matches to {@code STATIC_GETTER}
123          *     <LI>{@code REF_putStatic} which matches to {@code STATIC_SETTER}
124          * </UL>
125          * As for the rest, the returned kind will depend on the value (false or true accordingly) of {@code isInterface}:
126          * <UL>
127          *     <LI>{@code REF_invokeStatic} which matches to {@code STATIC} or {@code INTERFACE_STATIC}
128          *     <LI>{@code REF_invokeSpecial} which matches to {@code SPECIAL} or {@code INTERFACE_SPECIAL}
129          * </UL>
130          * @param refKind refKind of desired member
131          * @param isInterface whether desired member is for interface methods
132          * @return the matching enumeration member
133          * @throws IllegalArgumentException if there is no such member
134          */
135         public static Kind valueOf(int refKind, boolean isInterface) {
136             int i = tableIndex(refKind, isInterface);
137             if (i >= 2 && i < TABLE.length) {
138                 return TABLE[i];
139             }
140             throw new IllegalArgumentException(String.format("refKind=%d isInterface=%s", refKind, isInterface));
141         }
142 
143         private static int tableIndex(int refKind, boolean isInterface) {
144             if (refKind < 0)  return refKind;
145             return (refKind * 2) + (isInterface ? 1 : 0);
146         }
147 
148         private static final @Stable Kind[] TABLE;
149 
150         static {
151             // Pack the static table.
152             int max = 0;
153             for (Kind k : values())
154                 max = Math.max(max, tableIndex(k.refKind, true));
155 
156             TABLE = new Kind[max+1];
157             for (Kind kind : values()) {
158                 int i = tableIndex(kind.refKind, kind.isInterface);
159                 if (i >= TABLE.length || TABLE[i] != null)
160                     throw new AssertionError("TABLE entry for " + kind);
161                 TABLE[i] = kind;
162             }
163 
164             // Pack in some aliases also.
165             int ii = tableIndex(REF_invokeInterface, false);
166             if (TABLE[ii] != null)
167                 throw new AssertionError("TABLE entry for (invokeInterface, false) used by " + TABLE[ii]);
168             TABLE[ii] = INTERFACE_VIRTUAL;
169 
170             for (Kind kind : values()) {
171                 if (!kind.isInterface) {
172                     // Add extra cache entry to alias the isInterface case.
173                     // For example, (REF_getStatic, X) will produce STATIC_GETTER
174                     // for either truth value of X.
175                     int i = tableIndex(kind.refKind, true);
176                     if (TABLE[i] == null) {
177                         TABLE[i] = kind;
178                     }
179                 }
180             }
181         }
182 
183         /**
184          * Does this {@code Kind} correspond to a virtual method invocation?
185          *
186          * @return if this {@code Kind} corresponds to a virtual method invocation
187          */
188         boolean isVirtualMethod() {
189             switch (this) {
190                 case VIRTUAL:
191                 case SPECIAL:
192                 case INTERFACE_VIRTUAL:
193                 case INTERFACE_SPECIAL:
194                     return true;
195                 default:
196                     return false;
197             }
198         }
199     }
200 
201     /**
202      * Returns the {@code kind} of the method handle described by this nominal
203      * descriptor.
204      *
205      * @return the {@link Kind}
206      */
207     Kind kind();
208 
209     /**
210      * Returns the {@code refKind} of the method handle described by this nominal
211      * reference, as defined by {@link MethodHandleInfo}.
212      *
213      * @return the reference kind
214      */
215     int refKind();
216 
217     /**
218      * Indicates if the method is declared by an interface
219      *
220      * @return true if the method is declared by an interface
221      */
222     boolean isOwnerInterface();
223 
224     /**
225      * Returns a {@link ClassDesc} describing the class declaring the
226      * method or field described by this nominal descriptor.
227      *
228      * @return the class declaring the method or field
229      */
230     ClassDesc owner();
231 
232     /**
233      * Returns the name of the method or field described by this nominal descriptor.
234      * For constructors, returns the reserved name {@code "<init>"}.
235      * For static value class instance factory methods, return {@code "<vnew>"}.
236      *
237      * @return the name of the method or field
238      */
239     String methodName();
240 
241     /**
242      * Returns the lookup descriptor of the method handle described by this descriptor,
243      * after adjusting for the invocation mode.  This will correspond to either
244      * a method type descriptor string (for methods and constructors), or a field
245      * descriptor string (for field access method handles).  The lookup descriptor
246      * string is in the same format as accepted by {@link MethodHandleDesc#of(Kind, ClassDesc, String, String)}.
247      *
248      * @return the lookup descriptor string
249      */
250     String lookupDescriptor();
251 }