1 /*
   2  * Copyright (c) 2008, 2010, 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 
  26 package java.dyn;
  27 
  28 import java.util.Arrays;
  29 import java.util.Collections;
  30 import java.util.HashMap;
  31 import java.util.List;
  32 import sun.dyn.Access;
  33 import sun.dyn.Invokers;
  34 import sun.dyn.MethodTypeImpl;
  35 import sun.dyn.util.BytecodeDescriptor;
  36 import static sun.dyn.MemberName.newIllegalArgumentException;
  37 
  38 /**
  39  * A method type represents the arguments and return type accepted and
  40  * returned by a method handle, or the arguments and return type passed
  41  * and expected  by a method handle caller.  Method types must be properly
  42  * matched between a method handle and all its callers,
  43  * and the JVM's operations enforce this matching at, specifically
  44  * during calls to {@link MethodHandle#invokeExact}
  45  * and {@link MethodHandle#invokeGeneric}, and during execution
  46  * of {@code invokedynamic} instructions.
  47  * <p>
  48  * The structure is a return type accompanied by any number of parameter types.
  49  * The types (primitive, {@code void}, and reference) are represented by {@link Class} objects.
  50  * (For ease of exposition, we treat {@code void} as if it were a type.
  51  * In fact, it denotes the absence of a return type.)
  52  * <p>
  53  * All instances of {@code MethodType} are immutable.
  54  * Two instances are completely interchangeable if they compare equal.
  55  * Equality depends on pairwise correspondence of the return and parameter types and on nothing else.
  56  * <p>
  57  * This type can be created only by factory methods.
  58  * All factory methods may cache values, though caching is not guaranteed.
  59  * Some factory methods are static, while others are virtual methods which
  60  * modify precursor method types, e.g., by changing a selected parameter.
  61  * <p>
  62  * Factory methods which operate on groups of parameter types
  63  * are systematically presented in two versions, so that both Java arrays and
  64  * Java lists can be used to work with groups of parameter types.
  65  * The query methods {@code parameterArray} and {@code parameterList}
  66  * also provide a choice between arrays and lists.
  67  * <p>
  68  * {@code MethodType} objects are sometimes derived from bytecode instructions
  69  * such as {@code invokedynamic}, specifically from the type descriptor strings associated
  70  * with the instructions in a class file's constant pool.
  71  * <p>
  72  * Like classes and strings, method types can also be represented directly
  73  * in a class file's constant pool as constants. The may be loaded by an {@code ldc}
  74  * instruction which refers to a suitable {@code CONSTANT_MethodType} constant pool entry.
  75  * The entry refers to a {@code CONSTANT_Utf8} spelling for the descriptor string.
  76  * For more details, see the <a href="package-summary.html#mtcon">package summary</a>.
  77  * <p>
  78  * When the JVM materializes a {@code MethodType} from a descriptor string,
  79  * all classes named in the descriptor must be accessible, and will be loaded.
  80  * (But the classes need not be initialized, as is the case with a {@code CONSTANT_Class}.)
  81  * This loading may occur at any time before the {@code MethodType} object is first derived.
  82  * @author John Rose, JSR 292 EG
  83  */
  84 public final
  85 class MethodType {
  86     private final Class<?>   rtype;
  87     private final Class<?>[] ptypes;
  88     private MethodTypeForm form; // erased form, plus cached data about primitives
  89     private MethodType wrapAlt;  // alternative wrapped/unwrapped version
  90     private Invokers invokers;   // cache of handy higher-order adapters
  91 
  92     private static final Access IMPL_TOKEN = Access.getToken();
  93 
  94     // share a cache with a friend in this package
  95     Invokers getInvokers() { return invokers; }
  96     void setInvokers(Invokers inv) { invokers = inv; }
  97 
  98     static {
  99         // This hack allows the implementation package special access to
 100         // the internals of MethodType.  In particular, the MTImpl has all sorts
 101         // of cached information useful to the implementation code.
 102         MethodTypeImpl.setMethodTypeFriend(IMPL_TOKEN, new MethodTypeImpl.MethodTypeFriend() {
 103             public Class<?>[] ptypes(MethodType mt)        { return mt.ptypes; }
 104             public MethodTypeImpl form(MethodType mt)      { return mt.form; }
 105             public void setForm(MethodType mt, MethodTypeImpl form) {
 106                 assert(mt.form == null);
 107                 mt.form = (MethodTypeForm) form;
 108             }
 109             public MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
 110                 return MethodType.makeImpl(rtype, ptypes, trusted);
 111             }
 112             public MethodTypeImpl newMethodTypeForm(MethodType mt) {
 113                 return new MethodTypeForm(mt);
 114             }
 115             public Invokers getInvokers(MethodType mt)    { return mt.invokers; }
 116             public void setInvokers(MethodType mt, Invokers inv) { mt.invokers = inv; }
 117         });
 118     }
 119 
 120     private MethodType(Class<?> rtype, Class<?>[] ptypes) {
 121         checkRtype(rtype);
 122         checkPtypes(ptypes);
 123         this.rtype = rtype;
 124         this.ptypes = ptypes;
 125     }
 126 
 127     private void checkRtype(Class<?> rtype) {
 128         rtype.equals(rtype);  // null check
 129     }
 130     private void checkPtypes(Class<?>[] ptypes) {
 131         for (Class<?> ptype : ptypes) {
 132             ptype.equals(ptype);  // null check
 133             if (ptype == void.class)
 134                 throw newIllegalArgumentException("parameter type cannot be void");
 135         }
 136     }
 137 
 138     static final HashMap<MethodType,MethodType> internTable
 139             = new HashMap<MethodType, MethodType>();
 140 
 141     static final Class<?>[] NO_PTYPES = {};
 142 
 143     /** Find or create an instance of the given method type.
 144      * @param rtype  the return type
 145      * @param ptypes the parameter types
 146      * @return a method type with the given parts
 147      * @throws NullPointerException if rtype or any ptype is null
 148      * @throws IllegalArgumentException if any of the ptypes is void
 149      */
 150     public static
 151     MethodType methodType(Class<?> rtype, Class<?>[] ptypes) {
 152         return makeImpl(rtype, ptypes, false);
 153     }
 154 
 155     /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. */
 156     public static
 157     MethodType methodType(Class<?> rtype, List<? extends Class<?>> ptypes) {
 158         boolean notrust = false;  // random List impl. could return evil ptypes array
 159         return makeImpl(rtype, ptypes.toArray(NO_PTYPES), notrust);
 160     }
 161 
 162     /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
 163      *  The leading parameter type is prepended to the remaining array.
 164      */
 165     public static
 166     MethodType methodType(Class<?> rtype, Class<?> ptype0, Class<?>... ptypes) {
 167         Class<?>[] ptypes1 = new Class<?>[1+ptypes.length];
 168         ptypes1[0] = ptype0;
 169         System.arraycopy(ptypes, 0, ptypes1, 1, ptypes.length);
 170         return makeImpl(rtype, ptypes1, true);
 171     }
 172 
 173     /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
 174      *  The resulting method has no parameter types.
 175      */
 176     public static
 177     MethodType methodType(Class<?> rtype) {
 178         return makeImpl(rtype, NO_PTYPES, true);
 179     }
 180 
 181     /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
 182      *  The resulting method has the single given parameter type.
 183      */
 184     public static
 185     MethodType methodType(Class<?> rtype, Class<?> ptype0) {
 186         return makeImpl(rtype, new Class<?>[]{ ptype0 }, true);
 187     }
 188 
 189     /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
 190      *  The resulting method has the same parameter types as {@code ptypes},
 191      *  and the specified return type.
 192      */
 193     public static
 194     MethodType methodType(Class<?> rtype, MethodType ptypes) {
 195         return makeImpl(rtype, ptypes.ptypes, true);
 196     }
 197 
 198     /**
 199      * Sole factory method to find or create an interned method type.
 200      * @param rtype desired return type
 201      * @param ptypes desired parameter types
 202      * @param trusted whether the ptypes can be used without cloning
 203      * @return the unique method type of the desired structure
 204      */
 205     private static
 206     MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
 207         if (ptypes == null || ptypes.length == 0) {
 208             ptypes = NO_PTYPES; trusted = true;
 209         }
 210         MethodType mt1 = new MethodType(rtype, ptypes);
 211         MethodType mt0;
 212         synchronized (internTable) {
 213             mt0 = internTable.get(mt1);
 214             if (mt0 != null)
 215                 return mt0;
 216         }
 217         if (!trusted)
 218             // defensively copy the array passed in by the user
 219             mt1 = new MethodType(rtype, ptypes.clone());
 220         // promote the object to the Real Thing, and reprobe
 221         MethodTypeImpl.initForm(IMPL_TOKEN, mt1);
 222         synchronized (internTable) {
 223             mt0 = internTable.get(mt1);
 224             if (mt0 != null)
 225                 return mt0;
 226             internTable.put(mt1, mt1);
 227         }
 228         return mt1;
 229     }
 230 
 231     // Entry point from JVM.  TODO: Change the name & signature.
 232     private static MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes,
 233             boolean ignore1, boolean ignore2) {
 234         return makeImpl(rtype, ptypes, true);
 235     }
 236 
 237     private static final MethodType[] objectOnlyTypes = new MethodType[20];
 238 
 239     /**
 240      * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
 241      * All parameters and the return type will be {@code Object},
 242      * except the final varargs parameter if any, which will be {@code Object[]}.
 243      * @param objectArgCount number of parameters (excluding the varargs parameter if any)
 244      * @param varargs whether there will be a varargs parameter, of type {@code Object[]}
 245      * @return a totally generic method type, given only its count of parameters and varargs
 246      * @see #genericMethodType(int)
 247      */
 248     public static
 249     MethodType genericMethodType(int objectArgCount, boolean varargs) {
 250         MethodType mt;
 251         int ivarargs = (!varargs ? 0 : 1);
 252         int ootIndex = objectArgCount*2 + ivarargs;
 253         if (ootIndex < objectOnlyTypes.length) {
 254             mt = objectOnlyTypes[ootIndex];
 255             if (mt != null)  return mt;
 256         }
 257         Class<?>[] ptypes = new Class<?>[objectArgCount + ivarargs];
 258         Arrays.fill(ptypes, Object.class);
 259         if (ivarargs != 0)  ptypes[objectArgCount] = Object[].class;
 260         mt = makeImpl(Object.class, ptypes, true);
 261         if (ootIndex < objectOnlyTypes.length) {
 262             objectOnlyTypes[ootIndex] = mt;     // cache it here also!
 263         }
 264         return mt;
 265     }
 266 
 267     /**
 268      * All parameters and the return type will be Object.
 269      * @param objectArgCount number of parameters
 270      * @return a totally generic method type, given only its count of parameters
 271      * @see #genericMethodType(int, boolean)
 272      */
 273     public static
 274     MethodType genericMethodType(int objectArgCount) {
 275         return genericMethodType(objectArgCount, false);
 276     }
 277 
 278     /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
 279      * @param num    the index (zero-based) of the parameter type to change
 280      * @param nptype a new parameter type to replace the old one with
 281      * @return the same type, except with the selected parameter changed
 282      */
 283     public MethodType changeParameterType(int num, Class<?> nptype) {
 284         if (parameterType(num) == nptype)  return this;
 285         Class<?>[] nptypes = ptypes.clone();
 286         nptypes[num] = nptype;
 287         return makeImpl(rtype, nptypes, true);
 288     }
 289 
 290     /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
 291      * @param num    the position (zero-based) of the inserted parameter type(s)
 292      * @param ptypesToInsert zero or more a new parameter types to insert into the parameter list
 293      * @return the same type, except with the selected parameter(s) inserted
 294      */
 295     public MethodType insertParameterTypes(int num, Class<?>... ptypesToInsert) {
 296         int len = ptypes.length;
 297         if (num < 0 || num > len)
 298             throw newIllegalArgumentException("num="+num); //SPECME
 299         int ilen = ptypesToInsert.length;
 300         if (ilen == 0)  return this;
 301         Class<?>[] nptypes = Arrays.copyOfRange(ptypes, 0, len+ilen);
 302         System.arraycopy(nptypes, num, nptypes, num+ilen, len-num);
 303         System.arraycopy(ptypesToInsert, 0, nptypes, num, ilen);
 304         return makeImpl(rtype, nptypes, true);
 305     }
 306 
 307     /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
 308      * @param ptypesToInsert zero or more a new parameter types to insert after the end of the parameter list
 309      * @return the same type, except with the selected parameter(s) appended
 310      */
 311     public MethodType appendParameterTypes(Class<?>... ptypesToInsert) {
 312         return insertParameterTypes(parameterCount(), ptypesToInsert);
 313     }
 314 
 315     /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
 316      * @param ptypesToInsert zero or more a new parameter types to insert after the end of the parameter list
 317      * @return the same type, except with the selected parameter(s) appended
 318      */
 319     public MethodType appendParameterTypes(List<Class<?>> ptypesToInsert) {
 320         return insertParameterTypes(parameterCount(), ptypesToInsert);
 321     }
 322 
 323     /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
 324      * @param num    the position (zero-based) of the inserted parameter type(s)
 325      * @param ptypesToInsert zero or more a new parameter types to insert into the parameter list
 326      * @return the same type, except with the selected parameter(s) inserted
 327      */
 328     public MethodType insertParameterTypes(int num, List<Class<?>> ptypesToInsert) {
 329         return insertParameterTypes(num, ptypesToInsert.toArray(NO_PTYPES));
 330     }
 331 
 332     /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
 333      * @param start  the index (zero-based) of the first parameter type to remove
 334      * @param end    the index (greater than {@code start}) of the first parameter type after not to remove
 335      * @return the same type, except with the selected parameter(s) removed
 336      */
 337     public MethodType dropParameterTypes(int start, int end) {
 338         int len = ptypes.length;
 339         if (!(0 <= start && start <= end && end <= len))
 340             throw newIllegalArgumentException("start="+start+" end="+end); //SPECME
 341         if (start == end)  return this;
 342         Class<?>[] nptypes;
 343         if (start == 0) {
 344             if (end == len) {
 345                 // drop all parameters
 346                 nptypes = NO_PTYPES;
 347             } else {
 348                 // drop initial parameter(s)
 349                 nptypes = Arrays.copyOfRange(ptypes, end, len);
 350             }
 351         } else {
 352             if (end == len) {
 353                 // drop trailing parameter(s)
 354                 nptypes = Arrays.copyOfRange(ptypes, 0, start);
 355             } else {
 356                 int tail = len - end;
 357                 nptypes = Arrays.copyOfRange(ptypes, 0, start + tail);
 358                 System.arraycopy(ptypes, end, nptypes, start, tail);
 359             }
 360         }
 361         return makeImpl(rtype, nptypes, true);
 362     }
 363 
 364     /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
 365      * @param nrtype a return parameter type to replace the old one with
 366      * @return the same type, except with the return type change
 367      */
 368     public MethodType changeReturnType(Class<?> nrtype) {
 369         if (returnType() == nrtype)  return this;
 370         return makeImpl(nrtype, ptypes, true);
 371     }
 372 
 373     /** Convenience method.
 374      * Report if this type contains a primitive argument or return value.
 375      * The return type {@code void} counts as a primitive.
 376      * @return true if any of the types are primitives
 377      */
 378     public boolean hasPrimitives() {
 379         return form.hasPrimitives();
 380     }
 381 
 382     /** Convenience method.
 383      * Report if this type contains a wrapper argument or return value.
 384      * Wrappers are types which box primitive values, such as {@link Integer}.
 385      * The reference type {@code java.lang.Void} counts as a wrapper.
 386      * @return true if any of the types are wrappers
 387      */
 388     public boolean hasWrappers() {
 389         return unwrap() != this;
 390     }
 391 
 392     /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
 393      * Erase all reference types to {@code Object}.
 394      * All primitive types (including {@code void}) will remain unchanged.
 395      * @return a version of the original type with all reference types replaced
 396      */
 397     public MethodType erase() {
 398         return form.erasedType();
 399     }
 400 
 401     /** Convenience method for {@link #genericMethodType(int)}.
 402      * Convert all types, both reference and primitive, to {@code Object}.
 403      * The expression {@code type.wrap().erase()} produces the same value
 404      * as {@code type.generic()}.
 405      * @return a version of the original type with all types replaced
 406      */
 407     public MethodType generic() {
 408         return genericMethodType(parameterCount());
 409     }
 410 
 411     /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
 412      * Convert all primitive types to their corresponding wrapper types.
 413      * All reference types (including wrapper types) will remain unchanged.
 414      * A {@code void} return type is changed to the type {@code java.lang.Void}.
 415      * The expression {@code type.wrap().erase()} produces the same value
 416      * as {@code type.generic()}.
 417      * @return a version of the original type with all primitive types replaced
 418      */
 419     public MethodType wrap() {
 420         return hasPrimitives() ? wrapWithPrims(this) : this;
 421     }
 422 
 423     /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
 424      * Convert all wrapper types to their corresponding primitive types.
 425      * All primitive types (including {@code void}) will remain unchanged.
 426      * A return type of {@code java.lang.Void} is changed to {@code void}.
 427      * @return a version of the original type with all wrapper types replaced
 428      */
 429     public MethodType unwrap() {
 430         MethodType noprims = !hasPrimitives() ? this : wrapWithPrims(this);
 431         return unwrapWithNoPrims(noprims);
 432     }
 433 
 434     private static MethodType wrapWithPrims(MethodType pt) {
 435         assert(pt.hasPrimitives());
 436         MethodType wt = pt.wrapAlt;
 437         if (wt == null) {
 438             // fill in lazily
 439             wt = MethodTypeImpl.canonicalize(pt, MethodTypeImpl.WRAP, MethodTypeImpl.WRAP);
 440             assert(wt != null);
 441             pt.wrapAlt = wt;
 442         }
 443         return wt;
 444     }
 445 
 446     private static MethodType unwrapWithNoPrims(MethodType wt) {
 447         assert(!wt.hasPrimitives());
 448         MethodType uwt = wt.wrapAlt;
 449         if (uwt == null) {
 450             // fill in lazily
 451             uwt = MethodTypeImpl.canonicalize(wt, MethodTypeImpl.UNWRAP, MethodTypeImpl.UNWRAP);
 452             if (uwt == null)
 453                 uwt = wt;    // type has no wrappers or prims at all
 454             wt.wrapAlt = uwt;
 455         }
 456         return uwt;
 457     }
 458 
 459     /** @param num the index (zero-based) of the desired parameter type
 460      *  @return the selected parameter type
 461      */
 462     public Class<?> parameterType(int num) {
 463         return ptypes[num];
 464     }
 465     /** @return the number of parameter types */
 466     public int parameterCount() {
 467         return ptypes.length;
 468     }
 469     /** @return the return type */
 470     public Class<?> returnType() {
 471         return rtype;
 472     }
 473 
 474     /**
 475      * Convenience method to present the arguments as a list.
 476      * @return the parameter types (as an immutable list)
 477      */
 478     public List<Class<?>> parameterList() {
 479         return Collections.unmodifiableList(Arrays.asList(ptypes));
 480     }
 481 
 482     /**
 483      * Convenience method to present the arguments as an array.
 484      * Changes to the array will not result in changes to the type.
 485      * @return the parameter types (as a fresh copy if necessary)
 486      */
 487     public Class<?>[] parameterArray() {
 488         return ptypes.clone();
 489     }
 490 
 491     /**
 492      * Compares the specified object with this type for equality.
 493      * That is, it returns <tt>true</tt> if and only if the specified object
 494      * is also a method type with exactly the same parameters and return type.
 495      * @param x object to compare
 496      * @see Object#equals(Object)
 497      */
 498     @Override
 499     public boolean equals(Object x) {
 500         return this == x || x instanceof MethodType && equals((MethodType)x);
 501     }
 502 
 503     private boolean equals(MethodType that) {
 504         return this.rtype == that.rtype
 505             && Arrays.equals(this.ptypes, that.ptypes);
 506     }
 507 
 508     /**
 509      * Returns the hash code value for this method type.
 510      * It is defined to be the same as the hashcode of a List
 511      * whose elements are the return type followed by the
 512      * parameter types.
 513      * @return the hash code value for this method type
 514      * @see Object#hashCode()
 515      * @see #equals(Object)
 516      * @see List#hashCode()
 517      */
 518     @Override
 519     public int hashCode() {
 520       int hashCode = 31 + rtype.hashCode();
 521       for (Class<?> ptype : ptypes)
 522           hashCode = 31*hashCode + ptype.hashCode();
 523       return hashCode;
 524     }
 525 
 526     /**
 527      * The string representation of a method type is a
 528      * parenthesis enclosed, comma separated list of type names,
 529      * followed immediately by the return type.
 530      * <p>
 531      * Each type is represented by its
 532      * {@link java.lang.Class#getSimpleName simple name}.
 533      * If a type name name is array, it the base type followed
 534      * by [], rather than the Class.getName of the array type.
 535      */
 536     @Override
 537     public String toString() {
 538         StringBuilder sb = new StringBuilder();
 539         sb.append("(");
 540         for (int i = 0; i < ptypes.length; i++) {
 541             if (i > 0)  sb.append(",");
 542             sb.append(ptypes[i].getSimpleName());
 543         }
 544         sb.append(")");
 545         sb.append(rtype.getSimpleName());
 546         return sb.toString();
 547     }
 548 
 549     /// Queries which have to do with the bytecode architecture
 550 
 551     /** The number of JVM stack slots required to invoke a method
 552      * of this type.  Note that (for historic reasons) the JVM requires
 553      * a second stack slot to pass long and double arguments.
 554      * So this method returns {@link #parameterCount()} plus the
 555      * number of long and double parameters (if any).
 556      * <p>
 557      * This method is included for the benfit of applications that must
 558      * generate bytecodes that process method handles and invokedynamic.
 559      * @return the number of JVM stack slots for this type's parameters
 560      */
 561     public int parameterSlotCount() {
 562         return form.parameterSlotCount();
 563     }
 564 
 565     /** Number of JVM stack slots which carry all parameters including and after
 566      * the given position, which must be in the range of 0 to
 567      * {@code parameterCount} inclusive.  Successive parameters are
 568      * more shallowly stacked, and parameters are indexed in the bytecodes
 569      * according to their trailing edge.  Thus, to obtain the depth
 570      * in the outgoing call stack of parameter {@code N}, obtain
 571      * the {@code parameterSlotDepth} of its trailing edge
 572      * at position {@code N+1}.
 573      * <p>
 574      * Parameters of type {@code long} and {@code double} occupy
 575      * two stack slots (for historical reasons) and all others occupy one.
 576      * Therefore, the number returned is the number of arguments
 577      * <em>including</em> and <em>after</em> the given parameter,
 578      * <em>plus</em> the number of long or double arguments
 579      * at or after after the argument for the given parameter.
 580      * <p>
 581      * This method is included for the benfit of applications that must
 582      * generate bytecodes that process method handles and invokedynamic.
 583      * @param num an index (zero-based, inclusive) within the parameter types
 584      * @return the index of the (shallowest) JVM stack slot transmitting the
 585      *         given parameter
 586      */
 587     public int parameterSlotDepth(int num) {
 588         if (num < 0 || num > ptypes.length)
 589             parameterType(num);  // force a range check
 590         return form.parameterToArgSlot(num-1);
 591     }
 592 
 593     /** The number of JVM stack slots required to receive a return value
 594      * from a method of this type.
 595      * If the {@link #returnType() return type} is void, it will be zero,
 596      * else if the return type is long or double, it will be two, else one.
 597      * <p>
 598      * This method is included for the benfit of applications that must
 599      * generate bytecodes that process method handles and invokedynamic.
 600      * @return the number of JVM stack slots (0, 1, or 2) for this type's return value
 601      */
 602     public int returnSlotCount() {
 603         return form.returnSlotCount();
 604     }
 605 
 606     /** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
 607      * Find or create an instance of the given method type.
 608      * Any class or interface name embedded in the descriptor string
 609      * will be resolved by calling {@link ClassLoader#loadClass(java.lang.String)}
 610      * on the given loader (or if it is null, on the system class loader).
 611      * <p>
 612      * Note that it is possible to encounter method types which cannot be
 613      * constructed by this method, because their component types are
 614      * not all reachable from a common class loader.
 615      * <p>
 616      * This method is included for the benfit of applications that must
 617      * generate bytecodes that process method handles and invokedynamic.
 618      * @param descriptor a bytecode-level signature string "(T...)T"
 619      * @param loader the class loader in which to look up the types
 620      * @return a method type matching the bytecode-level signature
 621      * @throws IllegalArgumentException if the string is not well-formed
 622      * @throws TypeNotPresentException if a named type cannot be found
 623      */
 624     public static MethodType fromMethodDescriptorString(String descriptor, ClassLoader loader)
 625         throws IllegalArgumentException, TypeNotPresentException
 626     {
 627         List<Class<?>> types = BytecodeDescriptor.parseMethod(descriptor, loader);
 628         Class<?> rtype = types.remove(types.size() - 1);
 629         Class<?>[] ptypes = types.toArray(NO_PTYPES);
 630         return makeImpl(rtype, ptypes, true);
 631     }
 632 
 633     /**
 634      * Create a bytecode descriptor representation of the method type.
 635      * <p>
 636      * Note that this is not a strict inverse of {@link #fromMethodDescriptorString}.
 637      * Two distinct classes which share a common name but have different class loaders
 638      * will appear identical when viewed within descriptor strings.
 639      * <p>
 640      * This method is included for the benfit of applications that must
 641      * generate bytecodes that process method handles and invokedynamic.
 642      * {@link #fromMethodDescriptorString(java.lang.String, java.lang.ClassLoader)},
 643      * because the latter requires a suitable class loader argument.
 644      * @return the bytecode signature representation
 645      */
 646     public String toMethodDescriptorString() {
 647         return BytecodeDescriptor.unparse(this);
 648     }
 649 }