jdk/src/share/classes/java/dyn/MethodType.java
changeset 8821 2836ee97ee27
parent 8348 3b2ac15dfc16
equal deleted inserted replaced
8693:2173b8120b13 8821:2836ee97ee27
    27 
    27 
    28 import java.util.Arrays;
    28 import java.util.Arrays;
    29 import java.util.Collections;
    29 import java.util.Collections;
    30 import java.util.HashMap;
    30 import java.util.HashMap;
    31 import java.util.List;
    31 import java.util.List;
    32 import sun.dyn.Access;
       
    33 import sun.dyn.Invokers;
       
    34 import sun.dyn.MethodHandleImpl;
       
    35 import sun.dyn.MethodTypeImpl;
       
    36 import sun.dyn.util.BytecodeDescriptor;
    32 import sun.dyn.util.BytecodeDescriptor;
    37 import static sun.dyn.MemberName.newIllegalArgumentException;
    33 import static java.dyn.MethodHandleStatics.*;
    38 
    34 
    39 /**
    35 /**
    40  * A method type represents the arguments and return type accepted and
    36  * A method type represents the arguments and return type accepted and
    41  * returned by a method handle, or the arguments and return type passed
    37  * returned by a method handle, or the arguments and return type passed
    42  * and expected  by a method handle caller.  Method types must be properly
    38  * and expected  by a method handle caller.  Method types must be properly
    94     // The remaining fields are caches of various sorts:
    90     // The remaining fields are caches of various sorts:
    95     private MethodTypeForm form; // erased form, plus cached data about primitives
    91     private MethodTypeForm form; // erased form, plus cached data about primitives
    96     private MethodType wrapAlt;  // alternative wrapped/unwrapped version
    92     private MethodType wrapAlt;  // alternative wrapped/unwrapped version
    97     private Invokers invokers;   // cache of handy higher-order adapters
    93     private Invokers invokers;   // cache of handy higher-order adapters
    98 
    94 
    99     private static final Access IMPL_TOKEN = Access.getToken();
       
   100 
       
   101     // share a cache with a friend in this package
       
   102     Invokers getInvokers() { return invokers; }
       
   103     void setInvokers(Invokers inv) { invokers = inv; }
       
   104 
       
   105     static {
       
   106         // This hack allows the implementation package special access to
       
   107         // the internals of MethodType.  In particular, the MTImpl has all sorts
       
   108         // of cached information useful to the implementation code.
       
   109         MethodTypeImpl.setMethodTypeFriend(IMPL_TOKEN, new MethodTypeImpl.MethodTypeFriend() {
       
   110             public Class<?>[] ptypes(MethodType mt)        { return mt.ptypes; }
       
   111             public MethodTypeImpl form(MethodType mt)      { return mt.form; }
       
   112             public void setForm(MethodType mt, MethodTypeImpl form) {
       
   113                 assert(mt.form == null);
       
   114                 mt.form = (MethodTypeForm) form;
       
   115             }
       
   116             public MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
       
   117                 return MethodType.makeImpl(rtype, ptypes, trusted);
       
   118             }
       
   119             public MethodTypeImpl newMethodTypeForm(MethodType mt) {
       
   120                 return new MethodTypeForm(mt);
       
   121             }
       
   122             public Invokers getInvokers(MethodType mt)    { return mt.invokers; }
       
   123             public void setInvokers(MethodType mt, Invokers inv) { mt.invokers = inv; }
       
   124         });
       
   125     }
       
   126 
       
   127     /**
    95     /**
   128      * Check the given parameters for validity and store them into the final fields.
    96      * Check the given parameters for validity and store them into the final fields.
   129      */
    97      */
   130     private MethodType(Class<?> rtype, Class<?>[] ptypes) {
    98     private MethodType(Class<?> rtype, Class<?>[] ptypes) {
   131         checkRtype(rtype);
    99         checkRtype(rtype);
   132         checkPtypes(ptypes);
   100         checkPtypes(ptypes);
   133         this.rtype = rtype;
   101         this.rtype = rtype;
   134         this.ptypes = ptypes;
   102         this.ptypes = ptypes;
   135     }
   103     }
       
   104 
       
   105     /*trusted*/ MethodTypeForm form() { return form; }
       
   106     /*trusted*/ Class<?> rtype() { return rtype; }
       
   107     /*trusted*/ Class<?>[] ptypes() { return ptypes; }
   136 
   108 
   137     private static void checkRtype(Class<?> rtype) {
   109     private static void checkRtype(Class<?> rtype) {
   138         rtype.equals(rtype);  // null check
   110         rtype.equals(rtype);  // null check
   139     }
   111     }
   140     private static int checkPtype(Class<?> ptype) {
   112     private static int checkPtype(Class<?> ptype) {
   251      * @param rtype desired return type
   223      * @param rtype desired return type
   252      * @param ptypes desired parameter types
   224      * @param ptypes desired parameter types
   253      * @param trusted whether the ptypes can be used without cloning
   225      * @param trusted whether the ptypes can be used without cloning
   254      * @return the unique method type of the desired structure
   226      * @return the unique method type of the desired structure
   255      */
   227      */
   256     private static
   228     /*trusted*/ static
   257     MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
   229     MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
   258         if (ptypes == null || ptypes.length == 0) {
   230         if (ptypes == null || ptypes.length == 0) {
   259             ptypes = NO_PTYPES; trusted = true;
   231             ptypes = NO_PTYPES; trusted = true;
   260         }
   232         }
   261         MethodType mt1 = new MethodType(rtype, ptypes);
   233         MethodType mt1 = new MethodType(rtype, ptypes);
   267         }
   239         }
   268         if (!trusted)
   240         if (!trusted)
   269             // defensively copy the array passed in by the user
   241             // defensively copy the array passed in by the user
   270             mt1 = new MethodType(rtype, ptypes.clone());
   242             mt1 = new MethodType(rtype, ptypes.clone());
   271         // promote the object to the Real Thing, and reprobe
   243         // promote the object to the Real Thing, and reprobe
   272         MethodTypeImpl.initForm(IMPL_TOKEN, mt1);
   244         MethodTypeForm form = MethodTypeForm.findForm(mt1);
       
   245         mt1.form = form;
       
   246         if (form.erasedType == mt1) {
       
   247             // This is a principal (erased) type; show it to the JVM.
       
   248             MethodHandleNatives.init(mt1);
       
   249         }
   273         synchronized (internTable) {
   250         synchronized (internTable) {
   274             mt0 = internTable.get(mt1);
   251             mt0 = internTable.get(mt1);
   275             if (mt0 != null)
   252             if (mt0 != null)
   276                 return mt0;
   253                 return mt0;
   277             internTable.put(mt1, mt1);
   254             internTable.put(mt1, mt1);
   278         }
   255         }
   279         return mt1;
   256         return mt1;
   280     }
       
   281 
       
   282     // Entry point from JVM.  TODO: Change the name & signature.
       
   283     private static MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes,
       
   284             boolean ignore1, boolean ignore2) {
       
   285         return makeImpl(rtype, ptypes, true);
       
   286     }
   257     }
   287 
   258 
   288     private static final MethodType[] objectOnlyTypes = new MethodType[20];
   259     private static final MethodType[] objectOnlyTypes = new MethodType[20];
   289 
   260 
   290     /**
   261     /**
   533     private static MethodType wrapWithPrims(MethodType pt) {
   504     private static MethodType wrapWithPrims(MethodType pt) {
   534         assert(pt.hasPrimitives());
   505         assert(pt.hasPrimitives());
   535         MethodType wt = pt.wrapAlt;
   506         MethodType wt = pt.wrapAlt;
   536         if (wt == null) {
   507         if (wt == null) {
   537             // fill in lazily
   508             // fill in lazily
   538             wt = MethodTypeImpl.canonicalize(pt, MethodTypeImpl.WRAP, MethodTypeImpl.WRAP);
   509             wt = MethodTypeForm.canonicalize(pt, MethodTypeForm.WRAP, MethodTypeForm.WRAP);
   539             assert(wt != null);
   510             assert(wt != null);
   540             pt.wrapAlt = wt;
   511             pt.wrapAlt = wt;
   541         }
   512         }
   542         return wt;
   513         return wt;
   543     }
   514     }
   545     private static MethodType unwrapWithNoPrims(MethodType wt) {
   516     private static MethodType unwrapWithNoPrims(MethodType wt) {
   546         assert(!wt.hasPrimitives());
   517         assert(!wt.hasPrimitives());
   547         MethodType uwt = wt.wrapAlt;
   518         MethodType uwt = wt.wrapAlt;
   548         if (uwt == null) {
   519         if (uwt == null) {
   549             // fill in lazily
   520             // fill in lazily
   550             uwt = MethodTypeImpl.canonicalize(wt, MethodTypeImpl.UNWRAP, MethodTypeImpl.UNWRAP);
   521             uwt = MethodTypeForm.canonicalize(wt, MethodTypeForm.UNWRAP, MethodTypeForm.UNWRAP);
   551             if (uwt == null)
   522             if (uwt == null)
   552                 uwt = wt;    // type has no wrappers or prims at all
   523                 uwt = wt;    // type has no wrappers or prims at all
   553             wt.wrapAlt = uwt;
   524             wt.wrapAlt = uwt;
   554         }
   525         }
   555         return uwt;
   526         return uwt;
   664      * number of long and double parameters (if any).
   635      * number of long and double parameters (if any).
   665      * <p>
   636      * <p>
   666      * This method is included for the benfit of applications that must
   637      * This method is included for the benfit of applications that must
   667      * generate bytecodes that process method handles and invokedynamic.
   638      * generate bytecodes that process method handles and invokedynamic.
   668      * @return the number of JVM stack slots for this type's parameters
   639      * @return the number of JVM stack slots for this type's parameters
   669      * @deprecated Will be removed for PFD.
   640      */
   670      */
   641     /*non-public*/ int parameterSlotCount() {
   671     public int parameterSlotCount() {
       
   672         return form.parameterSlotCount();
   642         return form.parameterSlotCount();
       
   643     }
       
   644 
       
   645     /*non-public*/ Invokers invokers() {
       
   646         Invokers inv = invokers;
       
   647         if (inv != null)  return inv;
       
   648         invokers = inv = new Invokers(this);
       
   649         return inv;
   673     }
   650     }
   674 
   651 
   675     /** Reports the number of JVM stack slots which carry all parameters including and after
   652     /** Reports the number of JVM stack slots which carry all parameters including and after
   676      * the given position, which must be in the range of 0 to
   653      * the given position, which must be in the range of 0 to
   677      * {@code parameterCount} inclusive.  Successive parameters are
   654      * {@code parameterCount} inclusive.  Successive parameters are
   692      * generate bytecodes that process method handles and invokedynamic.
   669      * generate bytecodes that process method handles and invokedynamic.
   693      * @param num an index (zero-based, inclusive) within the parameter types
   670      * @param num an index (zero-based, inclusive) within the parameter types
   694      * @return the index of the (shallowest) JVM stack slot transmitting the
   671      * @return the index of the (shallowest) JVM stack slot transmitting the
   695      *         given parameter
   672      *         given parameter
   696      * @throws IllegalArgumentException if {@code num} is negative or greater than {@code parameterCount()}
   673      * @throws IllegalArgumentException if {@code num} is negative or greater than {@code parameterCount()}
   697      * @deprecated Will be removed for PFD.
   674      */
   698      */
   675     /*non-public*/ int parameterSlotDepth(int num) {
   699     public int parameterSlotDepth(int num) {
       
   700         if (num < 0 || num > ptypes.length)
   676         if (num < 0 || num > ptypes.length)
   701             parameterType(num);  // force a range check
   677             parameterType(num);  // force a range check
   702         return form.parameterToArgSlot(num-1);
   678         return form.parameterToArgSlot(num-1);
   703     }
   679     }
   704 
   680 
   708      * else if the return type is long or double, it will be two, else one.
   684      * else if the return type is long or double, it will be two, else one.
   709      * <p>
   685      * <p>
   710      * This method is included for the benfit of applications that must
   686      * This method is included for the benfit of applications that must
   711      * generate bytecodes that process method handles and invokedynamic.
   687      * generate bytecodes that process method handles and invokedynamic.
   712      * @return the number of JVM stack slots (0, 1, or 2) for this type's return value
   688      * @return the number of JVM stack slots (0, 1, or 2) for this type's return value
   713      * @deprecated Will be removed for PFD.
   689      * Will be removed for PFD.
   714      */
   690      */
   715     public int returnSlotCount() {
   691     /*non-public*/ int returnSlotCount() {
   716         return form.returnSlotCount();
   692         return form.returnSlotCount();
   717     }
   693     }
   718 
   694 
   719     /**
   695     /**
   720      * Find or create an instance of a method type, given the spelling of its bytecode descriptor.
   696      * Find or create an instance of a method type, given the spelling of its bytecode descriptor.