jdk/src/share/classes/java/lang/invoke/MethodType.java
changeset 21604 2ad6b165b7d8
parent 20877 83ea903d5cf1
child 21637 fcaf599f308f
equal deleted inserted replaced
21603:e88919c55dac 21604:2ad6b165b7d8
    30 import java.lang.ref.Reference;
    30 import java.lang.ref.Reference;
    31 import java.lang.ref.ReferenceQueue;
    31 import java.lang.ref.ReferenceQueue;
    32 import java.util.Arrays;
    32 import java.util.Arrays;
    33 import java.util.Collections;
    33 import java.util.Collections;
    34 import java.util.List;
    34 import java.util.List;
       
    35 import java.util.Objects;
    35 import java.util.concurrent.ConcurrentMap;
    36 import java.util.concurrent.ConcurrentMap;
    36 import java.util.concurrent.ConcurrentHashMap;
    37 import java.util.concurrent.ConcurrentHashMap;
    37 import sun.invoke.util.BytecodeDescriptor;
    38 import sun.invoke.util.BytecodeDescriptor;
    38 import static java.lang.invoke.MethodHandleStatics.*;
    39 import static java.lang.invoke.MethodHandleStatics.*;
    39 import sun.invoke.util.VerifyType;
    40 import sun.invoke.util.VerifyType;
    96 
    97 
    97     // The remaining fields are caches of various sorts:
    98     // The remaining fields are caches of various sorts:
    98     private @Stable MethodTypeForm form; // erased form, plus cached data about primitives
    99     private @Stable MethodTypeForm form; // erased form, plus cached data about primitives
    99     private @Stable MethodType wrapAlt;  // alternative wrapped/unwrapped version
   100     private @Stable MethodType wrapAlt;  // alternative wrapped/unwrapped version
   100     private @Stable Invokers invokers;   // cache of handy higher-order adapters
   101     private @Stable Invokers invokers;   // cache of handy higher-order adapters
       
   102     private @Stable String methodDescriptor;  // cache for toMethodDescriptorString
   101 
   103 
   102     /**
   104     /**
   103      * Check the given parameters for validity and store them into the final fields.
   105      * Check the given parameters for validity and store them into the final fields.
   104      */
   106      */
   105     private MethodType(Class<?> rtype, Class<?>[] ptypes) {
   107     private MethodType(Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
   106         checkRtype(rtype);
   108         checkRtype(rtype);
   107         checkPtypes(ptypes);
   109         checkPtypes(ptypes);
       
   110         this.rtype = rtype;
       
   111         // defensively copy the array passed in by the user
       
   112         this.ptypes = trusted ? ptypes : Arrays.copyOf(ptypes, ptypes.length);
       
   113     }
       
   114 
       
   115     /**
       
   116      * Construct a temporary unchecked instance of MethodType for use only as a key to the intern table.
       
   117      * Does not check the given parameters for validity, and must be discarded after it is used as a searching key.
       
   118      * The parameters are reversed for this constructor, so that is is not accidentally used.
       
   119      */
       
   120     private MethodType(Class<?>[] ptypes, Class<?> rtype) {
   108         this.rtype = rtype;
   121         this.rtype = rtype;
   109         this.ptypes = ptypes;
   122         this.ptypes = ptypes;
   110     }
   123     }
   111 
   124 
   112     /*trusted*/ MethodTypeForm form() { return form; }
   125     /*trusted*/ MethodTypeForm form() { return form; }
   144      *  {@code invokermh.invoke(targetmh, arg1, arg2, ..., arg253)}.
   157      *  {@code invokermh.invoke(targetmh, arg1, arg2, ..., arg253)}.
   145      */
   158      */
   146     /*non-public*/ static final int MAX_MH_INVOKER_ARITY = MAX_MH_ARITY-1;  // deduct one more for invoker
   159     /*non-public*/ static final int MAX_MH_INVOKER_ARITY = MAX_MH_ARITY-1;  // deduct one more for invoker
   147 
   160 
   148     private static void checkRtype(Class<?> rtype) {
   161     private static void checkRtype(Class<?> rtype) {
   149         rtype.equals(rtype);  // null check
   162         Objects.requireNonNull(rtype);
   150     }
   163     }
   151     private static int checkPtype(Class<?> ptype) {
   164     private static void checkPtype(Class<?> ptype) {
   152         ptype.getClass();  //NPE
   165         Objects.requireNonNull(ptype);
   153         if (ptype == void.class)
   166         if (ptype == void.class)
   154             throw newIllegalArgumentException("parameter type cannot be void");
   167             throw newIllegalArgumentException("parameter type cannot be void");
   155         if (ptype == double.class || ptype == long.class)  return 1;
       
   156         return 0;
       
   157     }
   168     }
   158     /** Return number of extra slots (count of long/double args). */
   169     /** Return number of extra slots (count of long/double args). */
   159     private static int checkPtypes(Class<?>[] ptypes) {
   170     private static int checkPtypes(Class<?>[] ptypes) {
   160         int slots = 0;
   171         int slots = 0;
   161         for (Class<?> ptype : ptypes) {
   172         for (Class<?> ptype : ptypes) {
   162             slots += checkPtype(ptype);
   173             checkPtype(ptype);
       
   174             if (ptype == double.class || ptype == long.class) {
       
   175                 slots++;
       
   176             }
   163         }
   177         }
   164         checkSlotCount(ptypes.length + slots);
   178         checkSlotCount(ptypes.length + slots);
   165         return slots;
   179         return slots;
   166     }
   180     }
   167     static void checkSlotCount(int count) {
   181     static void checkSlotCount(int count) {
   282      * @param trusted whether the ptypes can be used without cloning
   296      * @param trusted whether the ptypes can be used without cloning
   283      * @return the unique method type of the desired structure
   297      * @return the unique method type of the desired structure
   284      */
   298      */
   285     /*trusted*/ static
   299     /*trusted*/ static
   286     MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
   300     MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
       
   301         MethodType mt = internTable.get(new MethodType(ptypes, rtype));
       
   302         if (mt != null)
       
   303             return mt;
   287         if (ptypes.length == 0) {
   304         if (ptypes.length == 0) {
   288             ptypes = NO_PTYPES; trusted = true;
   305             ptypes = NO_PTYPES; trusted = true;
   289         }
   306         }
   290         MethodType mt1 = new MethodType(rtype, ptypes);
   307         mt = new MethodType(rtype, ptypes, trusted);
   291         MethodType mt0 = internTable.get(mt1);
       
   292         if (mt0 != null)
       
   293             return mt0;
       
   294         if (!trusted)
       
   295             // defensively copy the array passed in by the user
       
   296             mt1 = new MethodType(rtype, ptypes.clone());
       
   297         // promote the object to the Real Thing, and reprobe
   308         // promote the object to the Real Thing, and reprobe
   298         MethodTypeForm form = MethodTypeForm.findForm(mt1);
   309         mt.form = MethodTypeForm.findForm(mt);
   299         mt1.form = form;
   310         return internTable.add(mt);
   300         return internTable.add(mt1);
       
   301     }
   311     }
   302     private static final MethodType[] objectOnlyTypes = new MethodType[20];
   312     private static final MethodType[] objectOnlyTypes = new MethodType[20];
   303 
   313 
   304     /**
   314     /**
   305      * Finds or creates a method type whose components are {@code Object} with an optional trailing {@code Object[]} array.
   315      * Finds or creates a method type whose components are {@code Object} with an optional trailing {@code Object[]} array.
   917      * {@link #fromMethodDescriptorString(java.lang.String, java.lang.ClassLoader) fromMethodDescriptorString},
   927      * {@link #fromMethodDescriptorString(java.lang.String, java.lang.ClassLoader) fromMethodDescriptorString},
   918      * because the latter requires a suitable class loader argument.
   928      * because the latter requires a suitable class loader argument.
   919      * @return the bytecode type descriptor representation
   929      * @return the bytecode type descriptor representation
   920      */
   930      */
   921     public String toMethodDescriptorString() {
   931     public String toMethodDescriptorString() {
   922         return BytecodeDescriptor.unparse(this);
   932         String desc = methodDescriptor;
       
   933         if (desc == null) {
       
   934             desc = BytecodeDescriptor.unparse(this);
       
   935             methodDescriptor = desc;
       
   936         }
       
   937         return desc;
   923     }
   938     }
   924 
   939 
   925     /*non-public*/ static String toFieldDescriptorString(Class<?> cls) {
   940     /*non-public*/ static String toFieldDescriptorString(Class<?> cls) {
   926         return BytecodeDescriptor.unparse(cls);
   941         return BytecodeDescriptor.unparse(cls);
   927     }
   942     }