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.lang.invoke.MethodHandles;
  30 
  31 import jdk.internal.vm.annotation.Stable;
  32 
  33 import static java.lang.invoke.MethodHandleInfo.REF_getField;
  34 import static java.lang.invoke.MethodHandleInfo.REF_getStatic;
  35 import static java.lang.invoke.MethodHandleInfo.REF_invokeInterface;
  36 import static java.lang.invoke.MethodHandleInfo.REF_invokeSpecial;
  37 import static java.lang.invoke.MethodHandleInfo.REF_invokeStatic;
  38 import static java.lang.invoke.MethodHandleInfo.REF_invokeVirtual;
  39 import static java.lang.invoke.MethodHandleInfo.REF_newInvokeSpecial;
  40 import static java.lang.invoke.MethodHandleInfo.REF_putField;
  41 import static java.lang.invoke.MethodHandleInfo.REF_putStatic;
  42 
  43 /**
  44  * A <a href="package-summary.html#nominal">nominal descriptor</a> for a direct
  45  * {@link MethodHandle}.  A {@linkplain DirectMethodHandleDescImpl} corresponds to
  46  * a {@code Constant_MethodHandle_info} entry in the constant pool of a classfile.
  47  *
  48  * @apiNote In the future, if the Java language permits, {@linkplain DirectMethodHandleDesc}
  49  * may become a {@code sealed} interface, which would prohibit subclassing except
  50  * by explicitly permitted types.  Non-platform classes should not implement
  51  * {@linkplain DirectMethodHandleDesc} directly.
  52  */
  53 public interface DirectMethodHandleDesc extends MethodHandleDesc {
  54     /**
  55      * Kinds of method handles that can be described with {@linkplain DirectMethodHandleDesc}.
  56      */
  57     enum Kind {
  58         /** A method handle for a method invoked as with {@code invokestatic} */
  59         STATIC(REF_invokeStatic),
  60         /** A method handle for a method invoked as with {@code invokestatic} */
  61         INTERFACE_STATIC(REF_invokeStatic, true),
  62         /** A method handle for a method invoked as with {@code invokevirtual} */
  63         VIRTUAL(REF_invokeVirtual),
  64         /** A method handle for a method invoked as with {@code invokeinterface} */
  65         INTERFACE_VIRTUAL(REF_invokeInterface, true),
  66         /** A method handle for a method invoked as with {@code invokespecial} */
  67         SPECIAL(REF_invokeSpecial),
  68         /** A method handle for an interface method invoked as with {@code invokespecial} */
  69         INTERFACE_SPECIAL(REF_invokeSpecial, true),
  70         /** A method handle for a constructor */
  71         CONSTRUCTOR(REF_newInvokeSpecial),
  72         /** A method handle for a read accessor for an instance field  */
  73         GETTER(REF_getField),
  74         /** A method handle for a write accessor for an instance field  */
  75         SETTER(REF_putField),
  76         /** A method handle for a read accessor for a static field  */
  77         STATIC_GETTER(REF_getStatic),
  78         /** A method handle for a write accessor for a static field  */
  79         STATIC_SETTER(REF_putStatic);
  80 
  81         /** The corresponding {@code refKind} value for this kind of method handle,
  82          * as defined by {@link MethodHandleInfo}
  83          */
  84         public final int refKind;
  85 
  86         /** Is this an interface
  87          */
  88         public final boolean isInterface;
  89         Kind(int refKind) {
  90             this(refKind, false);
  91         }
  92 
  93         Kind(int refKind, boolean isInterface) { this.refKind = refKind; this.isInterface = isInterface; }
  94 
  95         /**
  96          * Find the enumeration member with the given {@code refKind} field.
  97          * More precisely, invoke {@code valueOf(refKind, false)}.
  98          * @param refKind refKind of desired member
  99          * @return the matching enumeration member
 100          * @throws IllegalArgumentException if there is no such member
 101          */
 102         public static Kind valueOf(int refKind) {
 103             return valueOf(refKind, false);
 104         }
 105 
 106         /**
 107          * Find the enumeration member with the given {@code refKind} and
 108          * {@code isInterface} fields.
 109          * If {@code isInterface} is true and there is no such enumeration member,
 110          * return the member, if any, with the same {@code refKind} and a false
 111          * {@code isInterface} field.
 112          * If {@code isInterface} is false and {@code refKind} is {@code REF_invokeInterface}
 113          * return {@code INTERFACE_VIRTUAL}.
 114          * @param refKind refKind of desired member
 115          * @param isInterface whether desired member is for interface methods
 116          * @return the matching enumeration member
 117          * @throws IllegalArgumentException if there is no such member
 118          */
 119         public static Kind valueOf(int refKind, boolean isInterface) {
 120             int i = tableIndex(refKind, isInterface);
 121             if (i >= 0 && i < TABLE.length) {
 122                 Kind kind = TABLE[i];
 123                 if (kind.refKind == refKind && kind.isInterface == isInterface) {
 124                     return kind;
 125                 }
 126             }
 127             if (isInterface)  return valueOf(refKind);
 128             if (refKind == REF_invokeInterface)  return INTERFACE_VIRTUAL;
 129             throw new IllegalArgumentException("refKind="+refKind+(isInterface?"&isInterface":""));
 130         }
 131         private static int tableIndex(int refKind, boolean isInterface) {
 132             if (refKind < 0)  return refKind;
 133             return (refKind * 2) + (isInterface ? 1 : 0);
 134         }
 135         private static final @Stable Kind[] TABLE = new Kind[20];
 136         static {
 137             // Pack the static table.
 138             for (Kind kind : values()) {
 139                 int i = tableIndex(kind.refKind, kind.isInterface);
 140                 if (i >= TABLE.length || TABLE[i] != null)
 141                     throw new AssertionError("TABLE entry for "+kind);
 142                 TABLE[i] = kind;
 143             }
 144         }
 145     }
 146     /**
 147      * Return the {@code kind} of the method handle described by this nominal
 148      * descriptor.
 149      *
 150      * @return the {@link Kind}
 151      */
 152     Kind kind();
 153 
 154     /**
 155      * Return the {@code refKind} of the method handle described by this nominal
 156      * reference, as defined by {@link MethodHandleInfo}.
 157      *
 158      * @return the reference kind
 159      */
 160     int refKind();
 161 
 162     /**
 163      * Indicates if the method is declared by an interface
 164      *
 165      * @return true if the method is declared by an interface
 166      */
 167     boolean isOwnerInterface();
 168 
 169     /**
 170      * Return a {@link ClassDesc} describing the class declaring the
 171      * method or field described by this nominal descriptor.
 172      *
 173      * @return the class declaring the method or field
 174      */
 175     ClassDesc owner();
 176 
 177     /**
 178      * Return the name of the method or field described by this nominal descriptor.
 179      *
 180      * @return the name of the method or field
 181      */
 182     String methodName();
 183 
 184     /**
 185      * Return a {@link MethodTypeDesc} describing the invocation type of the
 186      * method handle described by this nominal descriptor
 187      *
 188      * @return the method type
 189      */
 190     MethodTypeDesc methodType();
 191 }