• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;
Kind(int refKind)91         Kind(int refKind) {
92             this(refKind, false);
93         }
94 
Kind(int refKind, boolean isInterface)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          */
valueOf(int refKind)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          */
valueOf(int refKind, boolean isInterface)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 
tableIndex(int refKind, boolean isInterface)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          */
isVirtualMethod()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      */
kind()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      */
refKind()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      */
isOwnerInterface()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      */
owner()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      *
236      * @return the name of the method or field
237      */
methodName()238     String methodName();
239 
240     /**
241      * Returns the lookup descriptor of the method handle described by this descriptor,
242      * after adjusting for the invocation mode.  This will correspond to either
243      * a method type descriptor string (for methods and constructors), or a field
244      * descriptor string (for field access method handles).  The lookup descriptor
245      * string is in the same format as accepted by {@link MethodHandleDesc#of(Kind, ClassDesc, String, String)}.
246      *
247      * @return the lookup descriptor string
248      */
lookupDescriptor()249     String lookupDescriptor();
250 }
251