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