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.Enum.EnumDesc;
  28 import java.lang.invoke.CallSite;
  29 import java.lang.invoke.ConstantBootstraps;
  30 import java.lang.invoke.MethodHandle;
  31 import java.lang.invoke.MethodHandles;
  32 import java.lang.invoke.MethodHandles.Lookup;
  33 import java.lang.invoke.MethodType;
  34 import java.lang.invoke.VarHandle;
  35 import java.lang.invoke.VarHandle.VarHandleDesc;
  36 import java.util.Collection;
  37 import java.util.List;
  38 import java.util.Map;
  39 import java.util.Set;
  40 
  41 import static java.lang.constant.DirectMethodHandleDesc.Kind.STATIC;
  42 
  43 /**
  44  * Predefined values of <a href="package-summary.html#nominal">nominal descriptor</a>
  45  * for common constants, including descriptors for primitive class types and
  46  * other common platform types, and descriptors for method handles for standard
  47  * bootstrap methods.
  48  *
  49  * @see ConstantDesc
  50  */
  51 public final class ConstantDescs {
  52     // No instances
  53     private ConstantDescs() { }
  54 
  55     /** Invocation name to use when no name is needed, such as the name of a
  56      * constructor, or the invocation name of a dynamic constant or dynamic
  57      * callsite when the bootstrap is known to ignore the invocation name.
  58      */
  59     public static final String DEFAULT_NAME = "_";
  60 
  61     // Don't change the order of these declarations!
  62 
  63     /** {@link ClassDesc} representing {@link Object} */
  64     public static final ClassDesc CR_Object = ClassDesc.of("java.lang.Object");
  65 
  66     /** {@link ClassDesc} representing {@link String} */
  67     public static final ClassDesc CR_String = ClassDesc.of("java.lang.String");
  68 
  69     /** {@link ClassDesc} representing {@link Class} */
  70     public static final ClassDesc CR_Class = ClassDesc.of("java.lang.Class");
  71 
  72     /** {@link ClassDesc} representing {@link Number} */
  73     public static final ClassDesc CR_Number = ClassDesc.of("java.lang.Number");
  74 
  75     /** {@link ClassDesc} representing {@link Integer} */
  76     public static final ClassDesc CR_Integer = ClassDesc.of("java.lang.Integer");
  77 
  78     /** {@link ClassDesc} representing {@link Long} */
  79     public static final ClassDesc CR_Long = ClassDesc.of("java.lang.Long");
  80 
  81     /** {@link ClassDesc} representing {@link Float} */
  82     public static final ClassDesc CR_Float = ClassDesc.of("java.lang.Float");
  83 
  84     /** {@link ClassDesc} representing {@link Double} */
  85     public static final ClassDesc CR_Double = ClassDesc.of("java.lang.Double");
  86 
  87     /** {@link ClassDesc} representing {@link Short} */
  88     public static final ClassDesc CR_Short = ClassDesc.of("java.lang.Short");
  89 
  90     /** {@link ClassDesc} representing {@link Byte} */
  91     public static final ClassDesc CR_Byte = ClassDesc.of("java.lang.Byte");
  92 
  93     /** {@link ClassDesc} representing {@link Character} */
  94     public static final ClassDesc CR_Character = ClassDesc.of("java.lang.Character");
  95 
  96     /** {@link ClassDesc} representing {@link Boolean} */
  97     public static final ClassDesc CR_Boolean = ClassDesc.of("java.lang.Boolean");
  98 
  99     /** {@link ClassDesc} representing {@link Void} */
 100     public static final ClassDesc CR_Void = ClassDesc.of("java.lang.Void");
 101 
 102     /** {@link ClassDesc} representing {@link Throwable} */
 103     public static final ClassDesc CR_Throwable = ClassDesc.of("java.lang.Throwable");
 104 
 105     /** {@link ClassDesc} representing {@link Exception} */
 106     public static final ClassDesc CR_Exception = ClassDesc.of("java.lang.Exception");
 107 
 108     /** {@link ClassDesc} representing {@link Enum} */
 109     public static final ClassDesc CR_Enum = ClassDesc.of("java.lang.Enum");
 110 
 111     /** {@link ClassDesc} representing {@link VarHandle} */
 112     public static final ClassDesc CR_VarHandle = ClassDesc.of("java.lang.invoke.VarHandle");
 113 
 114     /** {@link ClassDesc} representing {@link MethodHandles} */
 115     public static final ClassDesc CR_MethodHandles = ClassDesc.of("java.lang.invoke.MethodHandles");
 116 
 117     /** {@link ClassDesc} representing {@link MethodHandles.Lookup} */
 118     public static final ClassDesc CR_MethodHandles_Lookup = CR_MethodHandles.inner("Lookup");
 119 
 120     /** {@link ClassDesc} representing {@link MethodHandle} */
 121     public static final ClassDesc CR_MethodHandle = ClassDesc.of("java.lang.invoke.MethodHandle");
 122 
 123     /** {@link ClassDesc} representing {@link MethodType} */
 124     public static final ClassDesc CR_MethodType = ClassDesc.of("java.lang.invoke.MethodType");
 125 
 126     /** {@link ClassDesc} representing {@link CallSite} */
 127     public static final ClassDesc CR_CallSite = ClassDesc.of("java.lang.invoke.CallSite");
 128 
 129     /** {@link ClassDesc} representing {@link Collection} */
 130     public static final ClassDesc CR_Collection = ClassDesc.of("java.util.Collection");
 131 
 132     /** {@link ClassDesc} representing {@link List} */
 133     public static final ClassDesc CR_List = ClassDesc.of("java.util.List");
 134 
 135     /** {@link ClassDesc} representing {@link Set} */
 136     public static final ClassDesc CR_Set = ClassDesc.of("java.util.Set");
 137 
 138     /** {@link ClassDesc} representing {@link Map} */
 139     public static final ClassDesc CR_Map = ClassDesc.of("java.util.Map");
 140 
 141     /** {@link ClassDesc} representing {@link ConstantDesc} */
 142     public static final ClassDesc CR_ConstantDesc = ClassDesc.of("java.lang.constant.ConstantDesc");
 143 
 144     /** {@link ClassDesc} representing {@link ClassDesc} */
 145     public static final ClassDesc CR_ClassDesc = ClassDesc.of("java.lang.constant.ClassDesc");
 146 
 147     /** {@link ClassDesc} representing {@link EnumDesc} */
 148     public static final ClassDesc CR_EnumDesc = CR_Enum.inner("EnumDesc");
 149 
 150     /** {@link ClassDesc} representing {@link MethodTypeDesc} */
 151     public static final ClassDesc CR_MethodTypeDesc = ClassDesc.of("java.lang.constant.MethodTypeDesc");
 152 
 153     /** {@link ClassDesc} representing {@link MethodHandleDesc} */
 154     public static final ClassDesc CR_MethodHandleDesc = ClassDesc.of("java.lang.constant.MethodHandleDesc");
 155 
 156     /** {@link ClassDesc} representing {@link DirectMethodHandleDescImpl} */
 157     public static final ClassDesc CR_DirectMethodHandleDesc = ClassDesc.of("java.lang.constant.DirectMethodHandleDesc");
 158 
 159     /** {@link ClassDesc} representing {@link VarHandleDesc} */
 160     public static final ClassDesc CR_VarHandleDesc = CR_VarHandle.inner("VarHandleDesc");
 161 
 162     /** {@link ClassDesc} representing {@link DirectMethodHandleDesc.Kind} */
 163     public static final ClassDesc CR_MethodHandleDesc_Kind = CR_DirectMethodHandleDesc.inner("Kind");
 164 
 165     /** {@link ClassDesc} representing {@link DynamicConstantDesc} */
 166     public static final ClassDesc CR_DynamicConstantDesc = ClassDesc.of("java.lang.constant.DynamicConstantDesc");
 167 
 168     /** {@link ClassDesc} representing {@link DynamicCallSiteDesc} */
 169     public static final ClassDesc CR_DynamicCallSiteDesc = ClassDesc.of("java.lang.constant.DynamicCallSiteDesc");
 170 
 171     /** {@link ClassDesc} representing {@link ConstantBootstraps} */
 172     public static final ClassDesc CR_ConstantBootstraps = ClassDesc.of("java.lang.invoke.ConstantBootstraps");
 173 
 174     private static final ClassDesc[] INDY_BOOTSTRAP_ARGS = {
 175             ConstantDescs.CR_MethodHandles_Lookup,
 176             ConstantDescs.CR_String,
 177             ConstantDescs.CR_MethodType };
 178 
 179     private static final ClassDesc[] CONDY_BOOTSTRAP_ARGS = {
 180             ConstantDescs.CR_MethodHandles_Lookup,
 181             ConstantDescs.CR_String,
 182             ConstantDescs.CR_Class };
 183 
 184     /** {@link MethodHandleDesc} representing {@link ConstantBootstraps#primitiveClass(Lookup, String, Class)} */
 185     public static final DirectMethodHandleDesc BSM_PRIMITIVE_CLASS
 186             = ofConstantBootstrap(CR_ConstantBootstraps, "primitiveClass",
 187                                   CR_Class);
 188 
 189     /** {@link MethodHandleDesc} representing {@link ConstantBootstraps#enumConstant(Lookup, String, Class)} */
 190     public static final DirectMethodHandleDesc BSM_ENUM_CONSTANT
 191             = ofConstantBootstrap(CR_ConstantBootstraps, "enumConstant",
 192                                   CR_Enum);
 193 
 194     /** {@link MethodHandleDesc} representing {@link ConstantBootstraps#nullConstant(Lookup, String, Class)} */
 195     public static final DirectMethodHandleDesc BSM_NULL_CONSTANT
 196             = ofConstantBootstrap(CR_ConstantBootstraps, "nullConstant",
 197                                   ConstantDescs.CR_Object);
 198 
 199     /** {@link MethodHandleDesc} representing {@link ConstantBootstraps#fieldVarHandle(Lookup, String, Class, Class, Class)} */
 200     public static final DirectMethodHandleDesc BSM_VARHANDLE_FIELD
 201             = ofConstantBootstrap(CR_ConstantBootstraps, "fieldVarHandle",
 202                                   CR_VarHandle, CR_Class, CR_Class);
 203 
 204     /** {@link MethodHandleDesc} representing {@link ConstantBootstraps#staticFieldVarHandle(Lookup, String, Class, Class, Class)} */
 205     public static final DirectMethodHandleDesc BSM_VARHANDLE_STATIC_FIELD
 206             = ofConstantBootstrap(CR_ConstantBootstraps, "staticFieldVarHandle",
 207                                   CR_VarHandle, CR_Class, CR_Class);
 208 
 209     /** {@link MethodHandleDesc} representing {@link ConstantBootstraps#arrayVarHandle(Lookup, String, Class, Class)} */
 210     public static final DirectMethodHandleDesc BSM_VARHANDLE_ARRAY
 211             = ofConstantBootstrap(CR_ConstantBootstraps, "arrayVarHandle",
 212                                   CR_VarHandle, CR_Class);
 213 
 214     /** {@link MethodHandleDesc} representing {@link ConstantBootstraps#invoke(Lookup, String, Class, MethodHandle, Object...)} */
 215     public static final DirectMethodHandleDesc BSM_INVOKE
 216             = ofConstantBootstrap(CR_ConstantBootstraps, "invoke",
 217                                   CR_Object, CR_MethodHandle, CR_Object.arrayType());
 218 
 219     /** {@link ClassDesc} representing the primitive type {@code int} */
 220     public static final ClassDesc CR_int = ClassDesc.ofDescriptor("I");
 221 
 222     /** {@link ClassDesc} representing the primitive type {@code long} */
 223     public static final ClassDesc CR_long = ClassDesc.ofDescriptor("J");
 224 
 225     /** {@link ClassDesc} representing the primitive type {@code float} */
 226     public static final ClassDesc CR_float = ClassDesc.ofDescriptor("F");
 227 
 228     /** {@link ClassDesc} representing the primitive type {@code double} */
 229     public static final ClassDesc CR_double = ClassDesc.ofDescriptor("D");
 230 
 231     /** {@link ClassDesc} representing the primitive type {@code short} */
 232     public static final ClassDesc CR_short = ClassDesc.ofDescriptor("S");
 233 
 234     /** {@link ClassDesc} representing the primitive type {@code byte} */
 235     public static final ClassDesc CR_byte = ClassDesc.ofDescriptor("B");
 236 
 237     /** {@link ClassDesc} representing the primitive type {@code char} */
 238     public static final ClassDesc CR_char = ClassDesc.ofDescriptor("C");
 239 
 240     /** {@link ClassDesc} representing the primitive type {@code boolean} */
 241     public static final ClassDesc CR_boolean = ClassDesc.ofDescriptor("Z");
 242 
 243     /** {@link ClassDesc} representing the primitive type {@code void} */
 244     public static final ClassDesc CR_void = ClassDesc.ofDescriptor("V");
 245 
 246     /** Nominal descriptor representing the constant {@code null} */
 247     public static final ConstantDesc<?> NULL
 248             = DynamicConstantDesc.ofNamed(ConstantDescs.BSM_NULL_CONSTANT,
 249                                           DEFAULT_NAME, ConstantDescs.CR_Object);
 250 
 251     // Used by XxxDesc classes, but need to be here to avoid bootstrap cycles
 252     static final DirectMethodHandleDesc MHR_METHODTYPEDESC_FACTORY
 253             = MethodHandleDesc.of(DirectMethodHandleDesc.Kind.STATIC, CR_MethodTypeDesc, "ofDescriptor",
 254                                   CR_MethodTypeDesc, CR_String);
 255 
 256     static final DirectMethodHandleDesc MHR_CLASSDESC_FACTORY
 257             = MethodHandleDesc.of(DirectMethodHandleDesc.Kind.STATIC, CR_ClassDesc, "ofDescriptor",
 258                                   CR_ClassDesc, CR_String);
 259 
 260     static final DirectMethodHandleDesc MHR_METHODHANDLEDESC_FACTORY
 261             = MethodHandleDesc.of(DirectMethodHandleDesc.Kind.STATIC, CR_DirectMethodHandleDesc, "ofDescriptor",
 262                                   CR_DirectMethodHandleDesc, CR_String, CR_String, CR_String, CR_String);
 263 
 264     static final DirectMethodHandleDesc MHR_METHODHANDLE_ASTYPE
 265             = MethodHandleDesc.of(DirectMethodHandleDesc.Kind.VIRTUAL, CR_MethodHandle, "asType",
 266                                   CR_MethodHandle, CR_MethodType);
 267 
 268     static final DirectMethodHandleDesc MHR_METHODHANDLEDESC_ASTYPE
 269             = MethodHandleDesc.of(DirectMethodHandleDesc.Kind.VIRTUAL, CR_MethodHandleDesc, "asType",
 270                                   CR_MethodHandleDesc, CR_MethodTypeDesc);
 271 
 272     static final DirectMethodHandleDesc MHR_DYNAMICCONSTANTDESC_FACTORY
 273             = MethodHandleDesc.of(DirectMethodHandleDesc.Kind.STATIC, CR_DynamicConstantDesc, "of",
 274                                   CR_DynamicConstantDesc, CR_DirectMethodHandleDesc, CR_ConstantDesc.arrayType());
 275 
 276     static final DirectMethodHandleDesc MHR_DYNAMICCONSTANTDESC_NAMED_FACTORY
 277             = MethodHandleDesc.of(DirectMethodHandleDesc.Kind.STATIC, CR_DynamicConstantDesc, "ofNamed",
 278                                   CR_DynamicConstantDesc, CR_DirectMethodHandleDesc, CR_String, CR_String, CR_ConstantDesc.arrayType());
 279 
 280     /** {@link MethodHandleDesc} representing {@link EnumDesc#ofDescriptor(String, String)} */
 281     public static final DirectMethodHandleDesc MHR_ENUMDESC_FACTORY
 282             = MethodHandleDesc.of(DirectMethodHandleDesc.Kind.STATIC, CR_EnumDesc, "ofDescriptor",
 283                                   CR_EnumDesc, CR_String, CR_String);
 284 
 285     /** {@link MethodHandleDesc} representing {@link VarHandleDesc#ofField(ClassDesc, String, ClassDesc)} */
 286     public static final DirectMethodHandleDesc MHR_VARHANDLEDESC_OFFIELD
 287             = MethodHandleDesc.of(DirectMethodHandleDesc.Kind.STATIC, CR_VarHandleDesc, "ofField",
 288                                   CR_VarHandleDesc, CR_ClassDesc, CR_String, CR_ClassDesc);
 289     /** {@link MethodHandleDesc} representing {@link VarHandleDesc#ofStaticField(ClassDesc, String, ClassDesc)} */
 290     public static final DirectMethodHandleDesc MHR_VARHANDLEDESC_OFSTATIC
 291             = MethodHandleDesc.of(DirectMethodHandleDesc.Kind.STATIC, CR_VarHandleDesc, "ofStaticField",
 292                                   CR_VarHandleDesc, CR_ClassDesc, CR_String, CR_ClassDesc);
 293 
 294     /** {@link MethodHandleDesc} representing {@link VarHandleDesc#ofArray(ClassDesc)} */
 295     public static final DirectMethodHandleDesc MHR_VARHANDLEDESC_OFARRAY
 296             = MethodHandleDesc.of(DirectMethodHandleDesc.Kind.STATIC, CR_VarHandleDesc, "ofArray",
 297                                   CR_VarHandleDesc, CR_ClassDesc);
 298 
 299     static final DirectMethodHandleDesc BSM_METHODHANDLEDESC
 300             = ConstantDescs.ofConstantBootstrap(CR_DirectMethodHandleDesc,
 301                                                 "constantBootstrap", CR_DirectMethodHandleDesc,
 302                                                 CR_String, CR_String, CR_String, CR_String);
 303 
 304     static final DirectMethodHandleDesc BSM_DYNAMICCONSTANTDESC
 305             = ConstantDescs.ofConstantBootstrap(CR_DynamicConstantDesc,
 306                                                 "constantBootstrap",
 307                                                 CR_DynamicConstantDesc,
 308                                                 CR_DirectMethodHandleDesc, CR_String, CR_String, CR_ConstantDesc.arrayType());
 309 
 310     /**
 311      * Return a {@link MethodHandleDesc} corresponding to a bootstrap method for
 312      * an {@code invokedynamic} callsite, which is a static method whose leading
 313      * parameter types are {@code Lookup}, {@code String}, and {@code MethodType}.
 314      *
 315      * @param clazz the class declaring the method
 316      * @param name the name of the method, as per JVMS 4.2.2
 317      * @param returnType the return type of the method
 318      * @param paramTypes the types of the static bootstrap arguments, if any
 319      * @return the {@link MethodHandleDesc}
 320      * @throws NullPointerException if any of the arguments are null
 321      * @jvms 4.2.2 Unqualified Names
 322      */
 323     public static DirectMethodHandleDesc ofCallsiteBootstrap(ClassDesc clazz,
 324                                                              String name,
 325                                                              ClassDesc returnType,
 326                                                              ClassDesc... paramTypes) {
 327         return MethodHandleDesc.of(STATIC, clazz, name, MethodTypeDesc.of(returnType, paramTypes)
 328                                                                       .insertParameterTypes(0, INDY_BOOTSTRAP_ARGS));
 329     }
 330 
 331     /**
 332      * Return a {@link MethodHandleDesc} corresponding to a bootstrap method for a
 333      * dynamic constant, which is a static method whose leading arguments are
 334      * {@code Lookup}, {@code String}, and {@code Class}.
 335      *
 336      * @param clazz the class declaring the method
 337      * @param name the name of the method, as per JVMS 4.2.2
 338      * @param returnType the return type of the method
 339      * @param paramTypes the types of the static bootstrap arguments, if any
 340      * @return the {@link MethodHandleDesc}
 341      * @throws NullPointerException if any of the arguments are null
 342      * @jvms 4.2.2 Unqualified Names
 343      */
 344     public static DirectMethodHandleDesc ofConstantBootstrap(ClassDesc clazz,
 345                                                              String name,
 346                                                              ClassDesc returnType,
 347                                                              ClassDesc... paramTypes) {
 348         return MethodHandleDesc.of(STATIC, clazz, name, MethodTypeDesc.of(returnType, paramTypes)
 349                                                                       .insertParameterTypes(0, CONDY_BOOTSTRAP_ARGS));
 350     }
 351 }