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