jdk/src/share/classes/java/lang/invoke/FromGeneric.java
changeset 10204 bbd2c5e0ce05
parent 10203 cca843a7d258
parent 10174 e63dffa79ddb
child 10205 de9223c94f9c
equal deleted inserted replaced
10203:cca843a7d258 10204:bbd2c5e0ce05
     1 /*
       
     2  * Copyright (c) 2008, 2011, 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.lang.invoke;
       
    27 
       
    28 import sun.invoke.util.ValueConversions;
       
    29 import sun.invoke.util.Wrapper;
       
    30 import java.lang.reflect.*;
       
    31 import static java.lang.invoke.MethodHandleStatics.*;
       
    32 import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
       
    33 
       
    34 /**
       
    35  * Adapters which mediate between incoming calls which are generic
       
    36  * and outgoing calls which are not.  Any call can be represented generically
       
    37  * boxing up its arguments, and (on return) unboxing the return value.
       
    38  * <p>
       
    39  * A call is "generic" (in MethodHandle terms) if its MethodType features
       
    40  * only Object arguments.  A non-generic call therefore features
       
    41  * primitives and/or reference types other than Object.
       
    42  * An adapter has types for its incoming and outgoing calls.
       
    43  * The incoming call type is simply determined by the adapter's type
       
    44  * (the MethodType it presents to callers).  The outgoing call type
       
    45  * is determined by the adapter's target (a MethodHandle that the adapter
       
    46  * either binds internally or else takes as a leading argument).
       
    47  * (To stretch the term, adapter-like method handles may have multiple
       
    48  * targets or be polymorphic across multiple call types.)
       
    49  * @author jrose
       
    50  */
       
    51 class FromGeneric {
       
    52     // type for the outgoing call (may have primitives, etc.)
       
    53     private final MethodType targetType;
       
    54     // type of the outgoing call internal to the adapter
       
    55     private final MethodType internalType;
       
    56     // prototype adapter (clone and customize for each new target!)
       
    57     private final Adapter adapter;
       
    58     // entry point for adapter (Adapter mh, a...) => ...
       
    59     private final MethodHandle entryPoint;
       
    60     // unboxing invoker of type (MH, Object**N) => raw return value
       
    61     // it makes up the difference of internalType => targetType
       
    62     private final MethodHandle unboxingInvoker;
       
    63     // conversion which boxes a the target's raw return value
       
    64     private final MethodHandle returnConversion;
       
    65 
       
    66     /** Compute and cache information common to all unboxing adapters
       
    67      *  that can call out to targets of the erasure-family of the given erased type.
       
    68      */
       
    69     private FromGeneric(MethodType targetType) {
       
    70         this.targetType = targetType;
       
    71         MethodType internalType0;
       
    72         // the target invoker will generally need casts on reference arguments
       
    73         Adapter ad = findAdapter(internalType0 = targetType.erase());
       
    74         if (ad != null) {
       
    75             // Immediate hit to exactly the adapter we want,
       
    76             // with no monkeying around with primitive types.
       
    77             this.internalType = internalType0;
       
    78             this.adapter = ad;
       
    79             this.entryPoint = ad.prototypeEntryPoint();
       
    80             this.returnConversion = computeReturnConversion(targetType, internalType0);
       
    81             this.unboxingInvoker = computeUnboxingInvoker(targetType, internalType0);
       
    82             return;
       
    83         }
       
    84 
       
    85         // outgoing primitive arguments will be wrapped; unwrap them
       
    86         MethodType primsAsObj = targetType.form().primArgsAsBoxes();
       
    87         MethodType objArgsRawRet = primsAsObj.form().primsAsInts();
       
    88         if (objArgsRawRet != targetType)
       
    89             ad = findAdapter(internalType0 = objArgsRawRet);
       
    90         if (ad == null) {
       
    91             ad = buildAdapterFromBytecodes(internalType0 = targetType);
       
    92         }
       
    93         this.internalType = internalType0;
       
    94         this.adapter = ad;
       
    95         MethodType tepType = targetType.insertParameterTypes(0, adapter.getClass());
       
    96         this.entryPoint = ad.prototypeEntryPoint();
       
    97         this.returnConversion = computeReturnConversion(targetType, internalType0);
       
    98         this.unboxingInvoker = computeUnboxingInvoker(targetType, internalType0);
       
    99     }
       
   100 
       
   101     static {
       
   102         assert(MethodHandleNatives.workaroundWithoutRicochetFrames());  // this class is deprecated
       
   103     }
       
   104 
       
   105     /**
       
   106      * The typed target will be called according to targetType.
       
   107      * The adapter code will in fact see the raw result from internalType,
       
   108      * and must box it into an object.  Produce a converter for this.
       
   109      */
       
   110     private static MethodHandle computeReturnConversion(
       
   111             MethodType targetType, MethodType internalType) {
       
   112         Class<?> tret = targetType.returnType();
       
   113         Class<?> iret = internalType.returnType();
       
   114         Wrapper wrap = Wrapper.forBasicType(tret);
       
   115         if (!iret.isPrimitive()) {
       
   116             assert(iret == Object.class);
       
   117             return ValueConversions.identity();
       
   118         } else if (wrap.primitiveType() == iret) {
       
   119             return ValueConversions.box(wrap);
       
   120         } else {
       
   121             assert(tret == double.class ? iret == long.class : iret == int.class);
       
   122             return ValueConversions.boxRaw(wrap);
       
   123         }
       
   124     }
       
   125 
       
   126     /**
       
   127      * The typed target will need an exact invocation point; provide it here.
       
   128      * The adapter will possibly need to make a slightly different call,
       
   129      * so adapt the invoker.  This way, the logic for making up the
       
   130      * difference between what the adapter can call and what the target
       
   131      * needs can be cached once per type.
       
   132      */
       
   133     private static MethodHandle computeUnboxingInvoker(
       
   134             MethodType targetType, MethodType internalType) {
       
   135         // All the adapters we have here have reference-untyped internal calls.
       
   136         assert(internalType == internalType.erase());
       
   137         MethodHandle invoker = targetType.invokers().exactInvoker();
       
   138         // cast all narrow reference types, unbox all primitive arguments:
       
   139         MethodType fixArgsType = internalType.changeReturnType(targetType.returnType());
       
   140         MethodHandle fixArgs = MethodHandleImpl.convertArguments(
       
   141                                  invoker, Invokers.invokerType(fixArgsType),
       
   142                                  invoker.type(), 0);
       
   143         if (fixArgs == null)
       
   144             throw new InternalError("bad fixArgs");
       
   145         // reinterpret the calling sequence as raw:
       
   146         MethodHandle retyper = AdapterMethodHandle.makeRetypeRaw(
       
   147                                         Invokers.invokerType(internalType), fixArgs);
       
   148         if (retyper == null)
       
   149             throw new InternalError("bad retyper");
       
   150         return retyper;
       
   151     }
       
   152 
       
   153     Adapter makeInstance(MethodHandle typedTarget) {
       
   154         MethodType type = typedTarget.type();
       
   155         if (type == targetType) {
       
   156             return adapter.makeInstance(entryPoint, unboxingInvoker, returnConversion, typedTarget);
       
   157         }
       
   158         // my erased-type is not exactly the same as the desired type
       
   159         assert(type.erase() == targetType);  // else we are busted
       
   160         MethodHandle invoker = computeUnboxingInvoker(type, internalType);
       
   161         return adapter.makeInstance(entryPoint, invoker, returnConversion, typedTarget);
       
   162     }
       
   163 
       
   164     /** Build an adapter of the given generic type, which invokes typedTarget
       
   165      *  on the incoming arguments, after unboxing as necessary.
       
   166      *  The return value is boxed if necessary.
       
   167      * @param typedTarget the target
       
   168      * @return an adapter method handle
       
   169      */
       
   170     public static MethodHandle make(MethodHandle typedTarget) {
       
   171         MethodType type = typedTarget.type();
       
   172         if (type == type.generic())  return typedTarget;
       
   173         return FromGeneric.of(type).makeInstance(typedTarget);
       
   174     }
       
   175 
       
   176     /** Return the adapter information for this type's erasure. */
       
   177     static FromGeneric of(MethodType type) {
       
   178         MethodTypeForm form = type.form();
       
   179         FromGeneric fromGen = form.fromGeneric;
       
   180         if (fromGen == null)
       
   181             form.fromGeneric = fromGen = new FromGeneric(form.erasedType());
       
   182         return fromGen;
       
   183     }
       
   184 
       
   185     public String toString() {
       
   186         return "FromGeneric"+targetType;
       
   187     }
       
   188 
       
   189     /* Create an adapter that handles spreading calls for the given type. */
       
   190     static Adapter findAdapter(MethodType internalType) {
       
   191         MethodType entryType = internalType.generic();
       
   192         MethodTypeForm form = internalType.form();
       
   193         Class<?> rtype = internalType.returnType();
       
   194         int argc = form.parameterCount();
       
   195         int lac = form.longPrimitiveParameterCount();
       
   196         int iac = form.primitiveParameterCount() - lac;
       
   197         String intsAndLongs = (iac > 0 ? "I"+iac : "")+(lac > 0 ? "J"+lac : "");
       
   198         String rawReturn = String.valueOf(Wrapper.forPrimitiveType(rtype).basicTypeChar());
       
   199         String cname0 = rawReturn + argc;
       
   200         String cname1 = "A"       + argc;
       
   201         String[] cnames = { cname0+intsAndLongs, cname0, cname1+intsAndLongs, cname1 };
       
   202         String iname = "invoke_"+cname0+intsAndLongs;
       
   203         // e.g., D5I2, D5, L5I2, L5; invoke_D5
       
   204         for (String cname : cnames) {
       
   205             Class<? extends Adapter> acls = Adapter.findSubClass(cname);
       
   206             if (acls == null)  continue;
       
   207             // see if it has the required invoke method
       
   208             MethodHandle entryPoint = null;
       
   209             try {
       
   210                 entryPoint = IMPL_LOOKUP.findSpecial(acls, iname, entryType, acls);
       
   211             } catch (ReflectiveOperationException ex) {
       
   212             }
       
   213             if (entryPoint == null)  continue;
       
   214             Constructor<? extends Adapter> ctor = null;
       
   215             try {
       
   216                 ctor = acls.getDeclaredConstructor(MethodHandle.class);
       
   217             } catch (NoSuchMethodException ex) {
       
   218             } catch (SecurityException ex) {
       
   219             }
       
   220             if (ctor == null)  continue;
       
   221             try {
       
   222                 // Produce an instance configured as a prototype.
       
   223                 return ctor.newInstance(entryPoint);
       
   224             } catch (IllegalArgumentException ex) {
       
   225             } catch (InvocationTargetException wex) {
       
   226                 Throwable ex = wex.getTargetException();
       
   227                 if (ex instanceof Error)  throw (Error)ex;
       
   228                 if (ex instanceof RuntimeException)  throw (RuntimeException)ex;
       
   229             } catch (InstantiationException ex) {
       
   230             } catch (IllegalAccessException ex) {
       
   231             }
       
   232         }
       
   233         return null;
       
   234     }
       
   235 
       
   236     static Adapter buildAdapterFromBytecodes(MethodType internalType) {
       
   237         throw new UnsupportedOperationException("NYI "+internalType);
       
   238     }
       
   239 
       
   240     /**
       
   241      * This adapter takes some untyped arguments, and returns an untyped result.
       
   242      * Internally, it applies the invoker to the target, which causes the
       
   243      * objects to be unboxed; the result is a raw type in L/I/J/F/D.
       
   244      * This result is passed to convert, which is responsible for
       
   245      * converting the raw result into a boxed object.
       
   246      * The invoker is kept separate from the target because it can be
       
   247      * generated once per type erasure family, and reused across adapters.
       
   248      */
       
   249     static abstract class Adapter extends BoundMethodHandle {
       
   250         /*
       
   251          * class X<<R,int N>> extends Adapter {
       
   252          *   (MH, Object**N)=>raw(R) invoker;
       
   253          *   (any**N)=>R target;
       
   254          *   raw(R)=>Object convert;
       
   255          *   Object invoke(Object**N a) = convert(invoker(target, a...))
       
   256          * }
       
   257          */
       
   258         protected final MethodHandle invoker;  // (MH, Object**N) => raw(R)
       
   259         protected final MethodHandle convert;  // raw(R) => Object
       
   260         protected final MethodHandle target;   // (any**N) => R
       
   261 
       
   262         @Override
       
   263         String debugString() {
       
   264             return addTypeString(target, this);
       
   265         }
       
   266 
       
   267         protected boolean isPrototype() { return target == null; }
       
   268         protected Adapter(MethodHandle entryPoint) {
       
   269             this(entryPoint, null, entryPoint, null);
       
   270             assert(isPrototype());
       
   271         }
       
   272         protected MethodHandle prototypeEntryPoint() {
       
   273             if (!isPrototype())  throw new InternalError();
       
   274             return convert;
       
   275         }
       
   276 
       
   277         protected Adapter(MethodHandle entryPoint,
       
   278                           MethodHandle invoker, MethodHandle convert, MethodHandle target) {
       
   279             super(entryPoint);
       
   280             this.invoker = invoker;
       
   281             this.convert = convert;
       
   282             this.target  = target;
       
   283         }
       
   284 
       
   285         /** Make a copy of self, with new fields. */
       
   286         protected abstract Adapter makeInstance(MethodHandle entryPoint,
       
   287                 MethodHandle invoker, MethodHandle convert, MethodHandle target);
       
   288         // { return new ThisType(entryPoint, convert, target); }
       
   289 
       
   290         /// Conversions on the value returned from the target.
       
   291         protected Object convert_L(Object result) throws Throwable { return convert.invokeExact(result); }
       
   292         protected Object convert_I(int    result) throws Throwable { return convert.invokeExact(result); }
       
   293         protected Object convert_J(long   result) throws Throwable { return convert.invokeExact(result); }
       
   294         protected Object convert_F(float  result) throws Throwable { return convert.invokeExact(result); }
       
   295         protected Object convert_D(double result) throws Throwable { return convert.invokeExact(result); }
       
   296 
       
   297         static private final String CLASS_PREFIX; // "java.lang.invoke.FromGeneric$"
       
   298         static {
       
   299             String aname = Adapter.class.getName();
       
   300             String sname = Adapter.class.getSimpleName();
       
   301             if (!aname.endsWith(sname))  throw new InternalError();
       
   302             CLASS_PREFIX = aname.substring(0, aname.length() - sname.length());
       
   303         }
       
   304         /** Find a sibing class of Adapter. */
       
   305         static Class<? extends Adapter> findSubClass(String name) {
       
   306             String cname = Adapter.CLASS_PREFIX + name;
       
   307             try {
       
   308                 return Class.forName(cname).asSubclass(Adapter.class);
       
   309             } catch (ClassNotFoundException ex) {
       
   310                 return null;
       
   311             } catch (ClassCastException ex) {
       
   312                 return null;
       
   313             }
       
   314         }
       
   315     }
       
   316 
       
   317     /* generated classes follow this pattern:
       
   318     static class xA2 extends Adapter {
       
   319         protected xA2(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
       
   320         protected xA2(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
       
   321                         { super(e, i, c, t); }
       
   322         protected xA2 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
       
   323                         { return new xA2(e, i, c, t); }
       
   324         protected Object invoke_L2(Object a0, Object a1) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1)); }
       
   325         protected Object invoke_I2(Object a0, Object a1) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0, a1)); }
       
   326         protected Object invoke_J2(Object a0, Object a1) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0, a1)); }
       
   327         protected Object invoke_F2(Object a0, Object a1) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1)); }
       
   328         protected Object invoke_D2(Object a0, Object a1) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1)); }
       
   329     }
       
   330     // */
       
   331 
       
   332 /*
       
   333 : SHELL; n=FromGeneric; cp -p $n.java $n.java-; sed < $n.java- > $n.java+ -e '/{{*{{/,/}}*}}/w /tmp/genclasses.java' -e '/}}*}}/q'; (cd /tmp; javac -d . genclasses.java; java -cp . genclasses) >> $n.java+; echo '}' >> $n.java+; mv $n.java+ $n.java; mv $n.java- $n.java~
       
   334 //{{{
       
   335 import java.util.*;
       
   336 class genclasses {
       
   337     static String[] TYPES = { "Object",    "int   ",    "long  ",    "float ",    "double" };
       
   338     static String[] WRAPS = { "         ", "(Integer)", "(Long)   ", "(Float)  ", "(Double) " };
       
   339     static String[] TCHARS = { "L",     "I",      "J",      "F",      "D",     "A" };
       
   340     static String[][] TEMPLATES = { {
       
   341         "@for@ arity=0..10  rcat<=4 nrefs<=99 nints=0   nlongs=0",
       
   342         "    //@each-cat@",
       
   343         "    static class @cat@ extends Adapter {",
       
   344         "        protected @cat@(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype",
       
   345         "        protected @cat@(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)",
       
   346         "                        { super(e, i, c, t); }",
       
   347         "        protected @cat@ makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)",
       
   348         "                        { return new @cat@(e, i, c, t); }",
       
   349         "        //@each-R@",
       
   350         "        protected Object invoke_@catN@(@Tvav@) throws Throwable { return convert_@Rc@((@R@)@W@invoker.invokeExact(target@av@)); }",
       
   351         "        //@end-R@",
       
   352         "    }",
       
   353     } };
       
   354     static final String NEWLINE_INDENT = "\n                ";
       
   355     enum VAR {
       
   356         cat, catN, R, Rc, W, av, Tvav, Ovav;
       
   357         public final String pattern = "@"+toString().replace('_','.')+"@";
       
   358         public String binding;
       
   359         static void makeBindings(boolean topLevel, int rcat, int nrefs, int nints, int nlongs) {
       
   360             int nargs = nrefs + nints + nlongs;
       
   361             if (topLevel)
       
   362                 VAR.cat.binding = catstr(ALL_RETURN_TYPES ? TYPES.length : rcat, nrefs, nints, nlongs);
       
   363             VAR.catN.binding = catstr(rcat, nrefs, nints, nlongs);
       
   364             VAR.R.binding = TYPES[rcat];
       
   365             VAR.Rc.binding = TCHARS[rcat];
       
   366             VAR.W.binding = WRAPS[rcat];
       
   367             String[] Tv = new String[nargs];
       
   368             String[] av = new String[nargs];
       
   369             String[] Tvav = new String[nargs];
       
   370             String[] Ovav = new String[nargs];
       
   371             for (int i = 0; i < nargs; i++) {
       
   372                 int tcat = (i < nrefs) ? 0 : (i < nrefs + nints) ? 1 : 2;
       
   373                 Tv[i] = TYPES[tcat];
       
   374                 av[i] = arg(i);
       
   375                 Tvav[i] = param(Tv[i], av[i]);
       
   376                 Ovav[i] = param("Object", av[i]);
       
   377             }
       
   378             VAR.av.binding = comma(", ", av);
       
   379             VAR.Tvav.binding = comma(Tvav);
       
   380             VAR.Ovav.binding = comma(Ovav);
       
   381         }
       
   382         static String arg(int i) { return "a"+i; }
       
   383         static String param(String t, String a) { return t+" "+a; }
       
   384         static String comma(String[] v) { return comma("", v); }
       
   385         static String comma(String sep, String[] v) {
       
   386             if (v.length == 0)  return "";
       
   387             String res = sep+v[0];
       
   388             for (int i = 1; i < v.length; i++)  res += ", "+v[i];
       
   389             return res;
       
   390         }
       
   391         static String transform(String string) {
       
   392             for (VAR var : values())
       
   393                 string = string.replaceAll(var.pattern, var.binding);
       
   394             return string;
       
   395         }
       
   396     }
       
   397     static String[] stringsIn(String[] strings, int beg, int end) {
       
   398         return Arrays.copyOfRange(strings, beg, Math.min(end, strings.length));
       
   399     }
       
   400     static String[] stringsBefore(String[] strings, int pos) {
       
   401         return stringsIn(strings, 0, pos);
       
   402     }
       
   403     static String[] stringsAfter(String[] strings, int pos) {
       
   404         return stringsIn(strings, pos, strings.length);
       
   405     }
       
   406     static int indexAfter(String[] strings, int pos, String tag) {
       
   407         return Math.min(indexBefore(strings, pos, tag) + 1, strings.length);
       
   408     }
       
   409     static int indexBefore(String[] strings, int pos, String tag) {
       
   410         for (int i = pos, end = strings.length; ; i++) {
       
   411             if (i == end || strings[i].endsWith(tag))  return i;
       
   412         }
       
   413     }
       
   414     static int MIN_ARITY, MAX_ARITY, MAX_RCAT, MAX_REFS, MAX_INTS, MAX_LONGS;
       
   415     static boolean ALL_ARG_TYPES, ALL_RETURN_TYPES;
       
   416     static HashSet<String> done = new HashSet<String>();
       
   417     public static void main(String... av) {
       
   418         for (String[] template : TEMPLATES) {
       
   419             int forLinesLimit = indexBefore(template, 0, "@each-cat@");
       
   420             String[] forLines = stringsBefore(template, forLinesLimit);
       
   421             template = stringsAfter(template, forLinesLimit);
       
   422             for (String forLine : forLines)
       
   423                 expandTemplate(forLine, template);
       
   424         }
       
   425     }
       
   426     static void expandTemplate(String forLine, String[] template) {
       
   427         String[] params = forLine.split("[^0-9]+");
       
   428         if (params[0].length() == 0)  params = stringsAfter(params, 1);
       
   429         System.out.println("//params="+Arrays.asList(params));
       
   430         int pcur = 0;
       
   431         MIN_ARITY = Integer.valueOf(params[pcur++]);
       
   432         MAX_ARITY = Integer.valueOf(params[pcur++]);
       
   433         MAX_RCAT  = Integer.valueOf(params[pcur++]);
       
   434         MAX_REFS  = Integer.valueOf(params[pcur++]);
       
   435         MAX_INTS  = Integer.valueOf(params[pcur++]);
       
   436         MAX_LONGS = Integer.valueOf(params[pcur++]);
       
   437         if (pcur != params.length)  throw new RuntimeException("bad extra param: "+forLine);
       
   438         if (MAX_RCAT >= TYPES.length)  MAX_RCAT = TYPES.length - 1;
       
   439         ALL_ARG_TYPES = (indexBefore(template, 0, "@each-Tv@") < template.length);
       
   440         ALL_RETURN_TYPES = (indexBefore(template, 0, "@each-R@") < template.length);
       
   441         for (int nargs = MIN_ARITY; nargs <= MAX_ARITY; nargs++) {
       
   442             for (int rcat = 0; rcat <= MAX_RCAT; rcat++) {
       
   443                 expandTemplate(template, true, rcat, nargs, 0, 0);
       
   444                 if (ALL_ARG_TYPES)  break;
       
   445                 expandTemplateForPrims(template, true, rcat, nargs, 1, 1);
       
   446                 if (ALL_RETURN_TYPES)  break;
       
   447             }
       
   448         }
       
   449     }
       
   450     static String catstr(int rcat, int nrefs, int nints, int nlongs) {
       
   451         int nargs = nrefs + nints + nlongs;
       
   452         String cat = TCHARS[rcat] + nargs;
       
   453         if (!ALL_ARG_TYPES)  cat += (nints==0?"":"I"+nints)+(nlongs==0?"":"J"+nlongs);
       
   454         return cat;
       
   455     }
       
   456     static void expandTemplateForPrims(String[] template, boolean topLevel, int rcat, int nargs, int minints, int minlongs) {
       
   457         for (int isLong = 0; isLong <= 1; isLong++) {
       
   458             for (int nprims = 1; nprims <= nargs; nprims++) {
       
   459                 int nrefs = nargs - nprims;
       
   460                 int nints = ((1-isLong) * nprims);
       
   461                 int nlongs = (isLong * nprims);
       
   462                 expandTemplate(template, topLevel, rcat, nrefs, nints, nlongs);
       
   463             }
       
   464         }
       
   465     }
       
   466     static void expandTemplate(String[] template, boolean topLevel,
       
   467                                int rcat, int nrefs, int nints, int nlongs) {
       
   468         int nargs = nrefs + nints + nlongs;
       
   469         if (nrefs > MAX_REFS || nints > MAX_INTS || nlongs > MAX_LONGS)  return;
       
   470         VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
       
   471         if (topLevel && !done.add(VAR.cat.binding)) {
       
   472             System.out.println("    //repeat "+VAR.cat.binding);
       
   473             return;
       
   474         }
       
   475         for (int i = 0; i < template.length; i++) {
       
   476             String line = template[i];
       
   477             if (line.endsWith("@each-cat@")) {
       
   478                 // ignore
       
   479             } else if (line.endsWith("@each-R@")) {
       
   480                 int blockEnd = indexAfter(template, i, "@end-R@");
       
   481                 String[] block = stringsIn(template, i+1, blockEnd-1);
       
   482                 for (int rcat1 = rcat; rcat1 <= MAX_RCAT; rcat1++)
       
   483                     expandTemplate(block, false, rcat1, nrefs, nints, nlongs);
       
   484                 VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
       
   485                 i = blockEnd-1; continue;
       
   486             } else if (line.endsWith("@each-Tv@")) {
       
   487                 int blockEnd = indexAfter(template, i, "@end-Tv@");
       
   488                 String[] block = stringsIn(template, i+1, blockEnd-1);
       
   489                 expandTemplate(block, false, rcat, nrefs, nints, nlongs);
       
   490                 expandTemplateForPrims(block, false, rcat, nargs, nints+1, nlongs+1);
       
   491                 VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
       
   492                 i = blockEnd-1; continue;
       
   493             } else {
       
   494                 System.out.println(VAR.transform(line));
       
   495             }
       
   496         }
       
   497     }
       
   498 }
       
   499 //}}} */
       
   500 //params=[0, 10, 4, 99, 0, 0]
       
   501     static class A0 extends Adapter {
       
   502         protected A0(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
       
   503         protected A0(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
       
   504                         { super(e, i, c, t); }
       
   505         protected A0 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
       
   506                         { return new A0(e, i, c, t); }
       
   507         protected Object invoke_L0() throws Throwable { return convert_L((Object)invoker.invokeExact(target)); }
       
   508         protected Object invoke_I0() throws Throwable { return convert_I((int)   invoker.invokeExact(target)); }
       
   509         protected Object invoke_J0() throws Throwable { return convert_J((long)  invoker.invokeExact(target)); }
       
   510         protected Object invoke_F0() throws Throwable { return convert_F((float) invoker.invokeExact(target)); }
       
   511         protected Object invoke_D0() throws Throwable { return convert_D((double)invoker.invokeExact(target)); }
       
   512     }
       
   513     static class A1 extends Adapter {
       
   514         protected A1(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
       
   515         protected A1(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
       
   516                         { super(e, i, c, t); }
       
   517         protected A1 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
       
   518                         { return new A1(e, i, c, t); }
       
   519         protected Object invoke_L1(Object a0) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0)); }
       
   520         protected Object invoke_I1(Object a0) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0)); }
       
   521         protected Object invoke_J1(Object a0) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0)); }
       
   522         protected Object invoke_F1(Object a0) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0)); }
       
   523         protected Object invoke_D1(Object a0) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0)); }
       
   524     }
       
   525     static class A2 extends Adapter {
       
   526         protected A2(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
       
   527         protected A2(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
       
   528                         { super(e, i, c, t); }
       
   529         protected A2 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
       
   530                         { return new A2(e, i, c, t); }
       
   531         protected Object invoke_L2(Object a0, Object a1) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1)); }
       
   532         protected Object invoke_I2(Object a0, Object a1) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0, a1)); }
       
   533         protected Object invoke_J2(Object a0, Object a1) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0, a1)); }
       
   534         protected Object invoke_F2(Object a0, Object a1) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1)); }
       
   535         protected Object invoke_D2(Object a0, Object a1) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1)); }
       
   536     }
       
   537     static class A3 extends Adapter {
       
   538         protected A3(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
       
   539         protected A3(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
       
   540                         { super(e, i, c, t); }
       
   541         protected A3 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
       
   542                         { return new A3(e, i, c, t); }
       
   543         protected Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2)); }
       
   544         protected Object invoke_I3(Object a0, Object a1, Object a2) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0, a1, a2)); }
       
   545         protected Object invoke_J3(Object a0, Object a1, Object a2) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0, a1, a2)); }
       
   546         protected Object invoke_F3(Object a0, Object a1, Object a2) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2)); }
       
   547         protected Object invoke_D3(Object a0, Object a1, Object a2) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2)); }
       
   548     }
       
   549     static class A4 extends Adapter {
       
   550         protected A4(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
       
   551         protected A4(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
       
   552                         { super(e, i, c, t); }
       
   553         protected A4 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
       
   554                         { return new A4(e, i, c, t); }
       
   555         protected Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3)); }
       
   556         protected Object invoke_I4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0, a1, a2, a3)); }
       
   557         protected Object invoke_J4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0, a1, a2, a3)); }
       
   558         protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3)); }
       
   559         protected Object invoke_D4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3)); }
       
   560     }
       
   561     static class A5 extends Adapter {
       
   562         protected A5(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
       
   563         protected A5(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
       
   564                         { super(e, i, c, t); }
       
   565         protected A5 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
       
   566                         { return new A5(e, i, c, t); }
       
   567         protected Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4)); }
       
   568         protected Object invoke_I5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0, a1, a2, a3, a4)); }
       
   569         protected Object invoke_J5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0, a1, a2, a3, a4)); }
       
   570         protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4)); }
       
   571         protected Object invoke_D5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4)); }
       
   572     }
       
   573     static class A6 extends Adapter {
       
   574         protected A6(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
       
   575         protected A6(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
       
   576                         { super(e, i, c, t); }
       
   577         protected A6 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
       
   578                         { return new A6(e, i, c, t); }
       
   579         protected Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); }
       
   580         protected Object invoke_I6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); }
       
   581         protected Object invoke_J6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); }
       
   582         protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); }
       
   583         protected Object invoke_D6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); }
       
   584     }
       
   585     static class A7 extends Adapter {
       
   586         protected A7(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
       
   587         protected A7(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
       
   588                         { super(e, i, c, t); }
       
   589         protected A7 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
       
   590                         { return new A7(e, i, c, t); }
       
   591         protected Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); }
       
   592         protected Object invoke_I7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); }
       
   593         protected Object invoke_J7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); }
       
   594         protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); }
       
   595         protected Object invoke_D7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); }
       
   596     }
       
   597     static class A8 extends Adapter {
       
   598         protected A8(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
       
   599         protected A8(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
       
   600                         { super(e, i, c, t); }
       
   601         protected A8 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
       
   602                         { return new A8(e, i, c, t); }
       
   603         protected Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
       
   604         protected Object invoke_I8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
       
   605         protected Object invoke_J8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
       
   606         protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
       
   607         protected Object invoke_D8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
       
   608     }
       
   609     static class A9 extends Adapter {
       
   610         protected A9(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
       
   611         protected A9(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
       
   612                         { super(e, i, c, t); }
       
   613         protected A9 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
       
   614                         { return new A9(e, i, c, t); }
       
   615         protected Object invoke_L9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
       
   616         protected Object invoke_I9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
       
   617         protected Object invoke_J9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
       
   618         protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
       
   619         protected Object invoke_D9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
       
   620     }
       
   621     static class A10 extends Adapter {
       
   622         protected A10(MethodHandle entryPoint) { super(entryPoint); }  // to build prototype
       
   623         protected A10(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
       
   624                         { super(e, i, c, t); }
       
   625         protected A10 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
       
   626                         { return new A10(e, i, c, t); }
       
   627         protected Object invoke_L10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
       
   628         protected Object invoke_I10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_I((int)   invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
       
   629         protected Object invoke_J10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_J((long)  invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
       
   630         protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
       
   631         protected Object invoke_D10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
       
   632     }
       
   633 }