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