rt/emul/compact/src/main/java/java/lang/invoke/LambdaForm.java
branchjdk8
changeset 1675 cd50c1894ce5
parent 1674 eca8e9c3ec3e
child 1678 35daab73e225
     1.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/LambdaForm.java	Sun Aug 17 20:09:05 2014 +0200
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,1650 +0,0 @@
     1.4 -/*
     1.5 - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
     1.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 - *
     1.8 - * This code is free software; you can redistribute it and/or modify it
     1.9 - * under the terms of the GNU General Public License version 2 only, as
    1.10 - * published by the Free Software Foundation.  Oracle designates this
    1.11 - * particular file as subject to the "Classpath" exception as provided
    1.12 - * by Oracle in the LICENSE file that accompanied this code.
    1.13 - *
    1.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
    1.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.17 - * version 2 for more details (a copy is included in the LICENSE file that
    1.18 - * accompanied this code).
    1.19 - *
    1.20 - * You should have received a copy of the GNU General Public License version
    1.21 - * 2 along with this work; if not, write to the Free Software Foundation,
    1.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.23 - *
    1.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.25 - * or visit www.oracle.com if you need additional information or have any
    1.26 - * questions.
    1.27 - */
    1.28 -
    1.29 -package java.lang.invoke;
    1.30 -
    1.31 -import java.lang.annotation.*;
    1.32 -import java.lang.reflect.Method;
    1.33 -import java.util.Map;
    1.34 -import java.util.List;
    1.35 -import java.util.Arrays;
    1.36 -import java.util.ArrayList;
    1.37 -import java.util.HashMap;
    1.38 -import java.util.concurrent.ConcurrentHashMap;
    1.39 -import sun.invoke.util.Wrapper;
    1.40 -import static java.lang.invoke.MethodHandleStatics.*;
    1.41 -import static java.lang.invoke.MethodHandleNatives.Constants.*;
    1.42 -import java.lang.reflect.Field;
    1.43 -import java.util.Objects;
    1.44 -
    1.45 -/**
    1.46 - * The symbolic, non-executable form of a method handle's invocation semantics.
    1.47 - * It consists of a series of names.
    1.48 - * The first N (N=arity) names are parameters,
    1.49 - * while any remaining names are temporary values.
    1.50 - * Each temporary specifies the application of a function to some arguments.
    1.51 - * The functions are method handles, while the arguments are mixes of
    1.52 - * constant values and local names.
    1.53 - * The result of the lambda is defined as one of the names, often the last one.
    1.54 - * <p>
    1.55 - * Here is an approximate grammar:
    1.56 - * <blockquote><pre>{@code
    1.57 - * LambdaForm = "(" ArgName* ")=>{" TempName* Result "}"
    1.58 - * ArgName = "a" N ":" T
    1.59 - * TempName = "t" N ":" T "=" Function "(" Argument* ");"
    1.60 - * Function = ConstantValue
    1.61 - * Argument = NameRef | ConstantValue
    1.62 - * Result = NameRef | "void"
    1.63 - * NameRef = "a" N | "t" N
    1.64 - * N = (any whole number)
    1.65 - * T = "L" | "I" | "J" | "F" | "D" | "V"
    1.66 - * }</pre></blockquote>
    1.67 - * Names are numbered consecutively from left to right starting at zero.
    1.68 - * (The letters are merely a taste of syntax sugar.)
    1.69 - * Thus, the first temporary (if any) is always numbered N (where N=arity).
    1.70 - * Every occurrence of a name reference in an argument list must refer to
    1.71 - * a name previously defined within the same lambda.
    1.72 - * A lambda has a void result if and only if its result index is -1.
    1.73 - * If a temporary has the type "V", it cannot be the subject of a NameRef,
    1.74 - * even though possesses a number.
    1.75 - * Note that all reference types are erased to "L", which stands for {@code Object}.
    1.76 - * All subword types (boolean, byte, short, char) are erased to "I" which is {@code int}.
    1.77 - * The other types stand for the usual primitive types.
    1.78 - * <p>
    1.79 - * Function invocation closely follows the static rules of the Java verifier.
    1.80 - * Arguments and return values must exactly match when their "Name" types are
    1.81 - * considered.
    1.82 - * Conversions are allowed only if they do not change the erased type.
    1.83 - * <ul>
    1.84 - * <li>L = Object: casts are used freely to convert into and out of reference types
    1.85 - * <li>I = int: subword types are forcibly narrowed when passed as arguments (see {@code explicitCastArguments})
    1.86 - * <li>J = long: no implicit conversions
    1.87 - * <li>F = float: no implicit conversions
    1.88 - * <li>D = double: no implicit conversions
    1.89 - * <li>V = void: a function result may be void if and only if its Name is of type "V"
    1.90 - * </ul>
    1.91 - * Although implicit conversions are not allowed, explicit ones can easily be
    1.92 - * encoded by using temporary expressions which call type-transformed identity functions.
    1.93 - * <p>
    1.94 - * Examples:
    1.95 - * <blockquote><pre>{@code
    1.96 - * (a0:J)=>{ a0 }
    1.97 - *     == identity(long)
    1.98 - * (a0:I)=>{ t1:V = System.out#println(a0); void }
    1.99 - *     == System.out#println(int)
   1.100 - * (a0:L)=>{ t1:V = System.out#println(a0); a0 }
   1.101 - *     == identity, with printing side-effect
   1.102 - * (a0:L, a1:L)=>{ t2:L = BoundMethodHandle#argument(a0);
   1.103 - *                 t3:L = BoundMethodHandle#target(a0);
   1.104 - *                 t4:L = MethodHandle#invoke(t3, t2, a1); t4 }
   1.105 - *     == general invoker for unary insertArgument combination
   1.106 - * (a0:L, a1:L)=>{ t2:L = FilterMethodHandle#filter(a0);
   1.107 - *                 t3:L = MethodHandle#invoke(t2, a1);
   1.108 - *                 t4:L = FilterMethodHandle#target(a0);
   1.109 - *                 t5:L = MethodHandle#invoke(t4, t3); t5 }
   1.110 - *     == general invoker for unary filterArgument combination
   1.111 - * (a0:L, a1:L)=>{ ...(same as previous example)...
   1.112 - *                 t5:L = MethodHandle#invoke(t4, t3, a1); t5 }
   1.113 - *     == general invoker for unary/unary foldArgument combination
   1.114 - * (a0:L, a1:I)=>{ t2:I = identity(long).asType((int)->long)(a1); t2 }
   1.115 - *     == invoker for identity method handle which performs i2l
   1.116 - * (a0:L, a1:L)=>{ t2:L = BoundMethodHandle#argument(a0);
   1.117 - *                 t3:L = Class#cast(t2,a1); t3 }
   1.118 - *     == invoker for identity method handle which performs cast
   1.119 - * }</pre></blockquote>
   1.120 - * <p>
   1.121 - * @author John Rose, JSR 292 EG
   1.122 - */
   1.123 -class LambdaForm {
   1.124 -    final int arity;
   1.125 -    final int result;
   1.126 -    @Stable final Name[] names;
   1.127 -    final String debugName;
   1.128 -    MemberName vmentry;   // low-level behavior, or null if not yet prepared
   1.129 -    private boolean isCompiled;
   1.130 -
   1.131 -    // Caches for common structural transforms:
   1.132 -    LambdaForm[] bindCache;
   1.133 -
   1.134 -    public static final int VOID_RESULT = -1, LAST_RESULT = -2;
   1.135 -
   1.136 -    LambdaForm(String debugName,
   1.137 -               int arity, Name[] names, int result) {
   1.138 -        assert(namesOK(arity, names));
   1.139 -        this.arity = arity;
   1.140 -        this.result = fixResult(result, names);
   1.141 -        this.names = names.clone();
   1.142 -        this.debugName = debugName;
   1.143 -        normalize();
   1.144 -    }
   1.145 -
   1.146 -    LambdaForm(String debugName,
   1.147 -               int arity, Name[] names) {
   1.148 -        this(debugName,
   1.149 -             arity, names, LAST_RESULT);
   1.150 -    }
   1.151 -
   1.152 -    LambdaForm(String debugName,
   1.153 -               Name[] formals, Name[] temps, Name result) {
   1.154 -        this(debugName,
   1.155 -             formals.length, buildNames(formals, temps, result), LAST_RESULT);
   1.156 -    }
   1.157 -
   1.158 -    private static Name[] buildNames(Name[] formals, Name[] temps, Name result) {
   1.159 -        int arity = formals.length;
   1.160 -        int length = arity + temps.length + (result == null ? 0 : 1);
   1.161 -        Name[] names = Arrays.copyOf(formals, length);
   1.162 -        System.arraycopy(temps, 0, names, arity, temps.length);
   1.163 -        if (result != null)
   1.164 -            names[length - 1] = result;
   1.165 -        return names;
   1.166 -    }
   1.167 -
   1.168 -    private LambdaForm(String sig) {
   1.169 -        // Make a blank lambda form, which returns a constant zero or null.
   1.170 -        // It is used as a template for managing the invocation of similar forms that are non-empty.
   1.171 -        // Called only from getPreparedForm.
   1.172 -        assert(isValidSignature(sig));
   1.173 -        this.arity = signatureArity(sig);
   1.174 -        this.result = (signatureReturn(sig) == 'V' ? -1 : arity);
   1.175 -        this.names = buildEmptyNames(arity, sig);
   1.176 -        this.debugName = "LF.zero";
   1.177 -        assert(nameRefsAreLegal());
   1.178 -        assert(isEmpty());
   1.179 -        assert(sig.equals(basicTypeSignature()));
   1.180 -    }
   1.181 -
   1.182 -    private static Name[] buildEmptyNames(int arity, String basicTypeSignature) {
   1.183 -        assert(isValidSignature(basicTypeSignature));
   1.184 -        int resultPos = arity + 1;  // skip '_'
   1.185 -        if (arity < 0 || basicTypeSignature.length() != resultPos+1)
   1.186 -            throw new IllegalArgumentException("bad arity for "+basicTypeSignature);
   1.187 -        int numRes = (basicTypeSignature.charAt(resultPos) == 'V' ? 0 : 1);
   1.188 -        Name[] names = arguments(numRes, basicTypeSignature.substring(0, arity));
   1.189 -        for (int i = 0; i < numRes; i++) {
   1.190 -            names[arity + i] = constantZero(arity + i, basicTypeSignature.charAt(resultPos + i));
   1.191 -        }
   1.192 -        return names;
   1.193 -    }
   1.194 -
   1.195 -    private static int fixResult(int result, Name[] names) {
   1.196 -        if (result >= 0) {
   1.197 -            if (names[result].type == 'V')
   1.198 -                return -1;
   1.199 -        } else if (result == LAST_RESULT) {
   1.200 -            return names.length - 1;
   1.201 -        }
   1.202 -        return result;
   1.203 -    }
   1.204 -
   1.205 -    private static boolean namesOK(int arity, Name[] names) {
   1.206 -        for (int i = 0; i < names.length; i++) {
   1.207 -            Name n = names[i];
   1.208 -            assert(n != null) : "n is null";
   1.209 -            if (i < arity)
   1.210 -                assert( n.isParam()) : n + " is not param at " + i;
   1.211 -            else
   1.212 -                assert(!n.isParam()) : n + " is param at " + i;
   1.213 -        }
   1.214 -        return true;
   1.215 -    }
   1.216 -
   1.217 -    /** Renumber and/or replace params so that they are interned and canonically numbered. */
   1.218 -    private void normalize() {
   1.219 -        Name[] oldNames = null;
   1.220 -        int changesStart = 0;
   1.221 -        for (int i = 0; i < names.length; i++) {
   1.222 -            Name n = names[i];
   1.223 -            if (!n.initIndex(i)) {
   1.224 -                if (oldNames == null) {
   1.225 -                    oldNames = names.clone();
   1.226 -                    changesStart = i;
   1.227 -                }
   1.228 -                names[i] = n.cloneWithIndex(i);
   1.229 -            }
   1.230 -        }
   1.231 -        if (oldNames != null) {
   1.232 -            int startFixing = arity;
   1.233 -            if (startFixing <= changesStart)
   1.234 -                startFixing = changesStart+1;
   1.235 -            for (int i = startFixing; i < names.length; i++) {
   1.236 -                Name fixed = names[i].replaceNames(oldNames, names, changesStart, i);
   1.237 -                names[i] = fixed.newIndex(i);
   1.238 -            }
   1.239 -        }
   1.240 -        assert(nameRefsAreLegal());
   1.241 -        int maxInterned = Math.min(arity, INTERNED_ARGUMENT_LIMIT);
   1.242 -        boolean needIntern = false;
   1.243 -        for (int i = 0; i < maxInterned; i++) {
   1.244 -            Name n = names[i], n2 = internArgument(n);
   1.245 -            if (n != n2) {
   1.246 -                names[i] = n2;
   1.247 -                needIntern = true;
   1.248 -            }
   1.249 -        }
   1.250 -        if (needIntern) {
   1.251 -            for (int i = arity; i < names.length; i++) {
   1.252 -                names[i].internArguments();
   1.253 -            }
   1.254 -            assert(nameRefsAreLegal());
   1.255 -        }
   1.256 -    }
   1.257 -
   1.258 -    /**
   1.259 -     * Check that all embedded Name references are localizable to this lambda,
   1.260 -     * and are properly ordered after their corresponding definitions.
   1.261 -     * <p>
   1.262 -     * Note that a Name can be local to multiple lambdas, as long as
   1.263 -     * it possesses the same index in each use site.
   1.264 -     * This allows Name references to be freely reused to construct
   1.265 -     * fresh lambdas, without confusion.
   1.266 -     */
   1.267 -    private boolean nameRefsAreLegal() {
   1.268 -        assert(arity >= 0 && arity <= names.length);
   1.269 -        assert(result >= -1 && result < names.length);
   1.270 -        // Do all names possess an index consistent with their local definition order?
   1.271 -        for (int i = 0; i < arity; i++) {
   1.272 -            Name n = names[i];
   1.273 -            assert(n.index() == i) : Arrays.asList(n.index(), i);
   1.274 -            assert(n.isParam());
   1.275 -        }
   1.276 -        // Also, do all local name references
   1.277 -        for (int i = arity; i < names.length; i++) {
   1.278 -            Name n = names[i];
   1.279 -            assert(n.index() == i);
   1.280 -            for (Object arg : n.arguments) {
   1.281 -                if (arg instanceof Name) {
   1.282 -                    Name n2 = (Name) arg;
   1.283 -                    int i2 = n2.index;
   1.284 -                    assert(0 <= i2 && i2 < names.length) : n.debugString() + ": 0 <= i2 && i2 < names.length: 0 <= " + i2 + " < " + names.length;
   1.285 -                    assert(names[i2] == n2) : Arrays.asList("-1-", i, "-2-", n.debugString(), "-3-", i2, "-4-", n2.debugString(), "-5-", names[i2].debugString(), "-6-", this);
   1.286 -                    assert(i2 < i);  // ref must come after def!
   1.287 -                }
   1.288 -            }
   1.289 -        }
   1.290 -        return true;
   1.291 -    }
   1.292 -
   1.293 -    /** Invoke this form on the given arguments. */
   1.294 -    // final Object invoke(Object... args) throws Throwable {
   1.295 -    //     // NYI: fit this into the fast path?
   1.296 -    //     return interpretWithArguments(args);
   1.297 -    // }
   1.298 -
   1.299 -    /** Report the return type. */
   1.300 -    char returnType() {
   1.301 -        if (result < 0)  return 'V';
   1.302 -        Name n = names[result];
   1.303 -        return n.type;
   1.304 -    }
   1.305 -
   1.306 -    /** Report the N-th argument type. */
   1.307 -    char parameterType(int n) {
   1.308 -        assert(n < arity);
   1.309 -        return names[n].type;
   1.310 -    }
   1.311 -
   1.312 -    /** Report the arity. */
   1.313 -    int arity() {
   1.314 -        return arity;
   1.315 -    }
   1.316 -
   1.317 -    /** Return the method type corresponding to my basic type signature. */
   1.318 -    MethodType methodType() {
   1.319 -        return signatureType(basicTypeSignature());
   1.320 -    }
   1.321 -    /** Return ABC_Z, where the ABC are parameter type characters, and Z is the return type character. */
   1.322 -    final String basicTypeSignature() {
   1.323 -        StringBuilder buf = new StringBuilder(arity() + 3);
   1.324 -        for (int i = 0, a = arity(); i < a; i++)
   1.325 -            buf.append(parameterType(i));
   1.326 -        return buf.append('_').append(returnType()).toString();
   1.327 -    }
   1.328 -    static int signatureArity(String sig) {
   1.329 -        assert(isValidSignature(sig));
   1.330 -        return sig.indexOf('_');
   1.331 -    }
   1.332 -    static char signatureReturn(String sig) {
   1.333 -        return sig.charAt(signatureArity(sig)+1);
   1.334 -    }
   1.335 -    static boolean isValidSignature(String sig) {
   1.336 -        int arity = sig.indexOf('_');
   1.337 -        if (arity < 0)  return false;  // must be of the form *_*
   1.338 -        int siglen = sig.length();
   1.339 -        if (siglen != arity + 2)  return false;  // *_X
   1.340 -        for (int i = 0; i < siglen; i++) {
   1.341 -            if (i == arity)  continue;  // skip '_'
   1.342 -            char c = sig.charAt(i);
   1.343 -            if (c == 'V')
   1.344 -                return (i == siglen - 1 && arity == siglen - 2);
   1.345 -            if (ALL_TYPES.indexOf(c) < 0)  return false; // must be [LIJFD]
   1.346 -        }
   1.347 -        return true;  // [LIJFD]*_[LIJFDV]
   1.348 -    }
   1.349 -    static Class<?> typeClass(char t) {
   1.350 -        switch (t) {
   1.351 -        case 'I': return int.class;
   1.352 -        case 'J': return long.class;
   1.353 -        case 'F': return float.class;
   1.354 -        case 'D': return double.class;
   1.355 -        case 'L': return Object.class;
   1.356 -        case 'V': return void.class;
   1.357 -        default: assert false;
   1.358 -        }
   1.359 -        return null;
   1.360 -    }
   1.361 -    static MethodType signatureType(String sig) {
   1.362 -        Class<?>[] ptypes = new Class<?>[signatureArity(sig)];
   1.363 -        for (int i = 0; i < ptypes.length; i++)
   1.364 -            ptypes[i] = typeClass(sig.charAt(i));
   1.365 -        Class<?> rtype = typeClass(signatureReturn(sig));
   1.366 -        return MethodType.methodType(rtype, ptypes);
   1.367 -    }
   1.368 -
   1.369 -    /*
   1.370 -     * Code generation issues:
   1.371 -     *
   1.372 -     * Compiled LFs should be reusable in general.
   1.373 -     * The biggest issue is how to decide when to pull a name into
   1.374 -     * the bytecode, versus loading a reified form from the MH data.
   1.375 -     *
   1.376 -     * For example, an asType wrapper may require execution of a cast
   1.377 -     * after a call to a MH.  The target type of the cast can be placed
   1.378 -     * as a constant in the LF itself.  This will force the cast type
   1.379 -     * to be compiled into the bytecodes and native code for the MH.
   1.380 -     * Or, the target type of the cast can be erased in the LF, and
   1.381 -     * loaded from the MH data.  (Later on, if the MH as a whole is
   1.382 -     * inlined, the data will flow into the inlined instance of the LF,
   1.383 -     * as a constant, and the end result will be an optimal cast.)
   1.384 -     *
   1.385 -     * This erasure of cast types can be done with any use of
   1.386 -     * reference types.  It can also be done with whole method
   1.387 -     * handles.  Erasing a method handle might leave behind
   1.388 -     * LF code that executes correctly for any MH of a given
   1.389 -     * type, and load the required MH from the enclosing MH's data.
   1.390 -     * Or, the erasure might even erase the expected MT.
   1.391 -     *
   1.392 -     * Also, for direct MHs, the MemberName of the target
   1.393 -     * could be erased, and loaded from the containing direct MH.
   1.394 -     * As a simple case, a LF for all int-valued non-static
   1.395 -     * field getters would perform a cast on its input argument
   1.396 -     * (to non-constant base type derived from the MemberName)
   1.397 -     * and load an integer value from the input object
   1.398 -     * (at a non-constant offset also derived from the MemberName).
   1.399 -     * Such MN-erased LFs would be inlinable back to optimized
   1.400 -     * code, whenever a constant enclosing DMH is available
   1.401 -     * to supply a constant MN from its data.
   1.402 -     *
   1.403 -     * The main problem here is to keep LFs reasonably generic,
   1.404 -     * while ensuring that hot spots will inline good instances.
   1.405 -     * "Reasonably generic" means that we don't end up with
   1.406 -     * repeated versions of bytecode or machine code that do
   1.407 -     * not differ in their optimized form.  Repeated versions
   1.408 -     * of machine would have the undesirable overheads of
   1.409 -     * (a) redundant compilation work and (b) extra I$ pressure.
   1.410 -     * To control repeated versions, we need to be ready to
   1.411 -     * erase details from LFs and move them into MH data,
   1.412 -     * whevener those details are not relevant to significant
   1.413 -     * optimization.  "Significant" means optimization of
   1.414 -     * code that is actually hot.
   1.415 -     *
   1.416 -     * Achieving this may require dynamic splitting of MHs, by replacing
   1.417 -     * a generic LF with a more specialized one, on the same MH,
   1.418 -     * if (a) the MH is frequently executed and (b) the MH cannot
   1.419 -     * be inlined into a containing caller, such as an invokedynamic.
   1.420 -     *
   1.421 -     * Compiled LFs that are no longer used should be GC-able.
   1.422 -     * If they contain non-BCP references, they should be properly
   1.423 -     * interlinked with the class loader(s) that their embedded types
   1.424 -     * depend on.  This probably means that reusable compiled LFs
   1.425 -     * will be tabulated (indexed) on relevant class loaders,
   1.426 -     * or else that the tables that cache them will have weak links.
   1.427 -     */
   1.428 -
   1.429 -    /**
   1.430 -     * Make this LF directly executable, as part of a MethodHandle.
   1.431 -     * Invariant:  Every MH which is invoked must prepare its LF
   1.432 -     * before invocation.
   1.433 -     * (In principle, the JVM could do this very lazily,
   1.434 -     * as a sort of pre-invocation linkage step.)
   1.435 -     */
   1.436 -    public void prepare() {
   1.437 -        if (COMPILE_THRESHOLD == 0) {
   1.438 -            compileToBytecode();
   1.439 -        }
   1.440 -        if (this.vmentry != null) {
   1.441 -            // already prepared (e.g., a primitive DMH invoker form)
   1.442 -            return;
   1.443 -        }
   1.444 -        LambdaForm prep = getPreparedForm(basicTypeSignature());
   1.445 -        this.vmentry = prep.vmentry;
   1.446 -        // TO DO: Maybe add invokeGeneric, invokeWithArguments
   1.447 -    }
   1.448 -
   1.449 -    /** Generate optimizable bytecode for this form. */
   1.450 -    MemberName compileToBytecode() {
   1.451 -        MethodType invokerType = methodType();
   1.452 -        assert(vmentry == null || vmentry.getMethodType().basicType().equals(invokerType));
   1.453 -        if (vmentry != null && isCompiled) {
   1.454 -            return vmentry;  // already compiled somehow
   1.455 -        }
   1.456 -        throw newInternalError("compileToBytecode", new Exception());
   1.457 -//        try {
   1.458 -//            vmentry = InvokerBytecodeGenerator.generateCustomizedCode(this, invokerType);
   1.459 -//            if (TRACE_INTERPRETER)
   1.460 -//                traceInterpreter("compileToBytecode", this);
   1.461 -//            isCompiled = true;
   1.462 -//            return vmentry;
   1.463 -//        } catch (Error | Exception ex) {
   1.464 -//            throw newInternalError("compileToBytecode", ex);
   1.465 -//        }
   1.466 -    }
   1.467 -
   1.468 -    private static final ConcurrentHashMap<String,LambdaForm> PREPARED_FORMS;
   1.469 -    static {
   1.470 -        int   capacity   = 512;    // expect many distinct signatures over time
   1.471 -        float loadFactor = 0.75f;  // normal default
   1.472 -        int   writers    = 1;
   1.473 -        PREPARED_FORMS = new ConcurrentHashMap<>(capacity, loadFactor, writers);
   1.474 -    }
   1.475 -
   1.476 -    private static Map<String,LambdaForm> computeInitialPreparedForms() {
   1.477 -        // Find all predefined invokers and associate them with canonical empty lambda forms.
   1.478 -        HashMap<String,LambdaForm> forms = new HashMap<>();
   1.479 -        for (MemberName m : MemberName.getFactory().getMethods(LambdaForm.class, false, null, null, null)) {
   1.480 -            if (!m.isStatic() || !m.isPackage())  continue;
   1.481 -            MethodType mt = m.getMethodType();
   1.482 -            if (mt.parameterCount() > 0 &&
   1.483 -                mt.parameterType(0) == MethodHandle.class &&
   1.484 -                m.getName().startsWith("interpret_")) {
   1.485 -                String sig = basicTypeSignature(mt);
   1.486 -                assert(m.getName().equals("interpret" + sig.substring(sig.indexOf('_'))));
   1.487 -                LambdaForm form = new LambdaForm(sig);
   1.488 -                form.vmentry = m;
   1.489 -                mt.form().setCachedLambdaForm(MethodTypeForm.LF_COUNTER, form);
   1.490 -                // FIXME: get rid of PREPARED_FORMS; use MethodTypeForm cache only
   1.491 -                forms.put(sig, form);
   1.492 -            }
   1.493 -        }
   1.494 -        //System.out.println("computeInitialPreparedForms => "+forms);
   1.495 -        return forms;
   1.496 -    }
   1.497 -
   1.498 -    // Set this false to disable use of the interpret_L methods defined in this file.
   1.499 -    private static final boolean USE_PREDEFINED_INTERPRET_METHODS = true;
   1.500 -
   1.501 -    // The following are predefined exact invokers.  The system must build
   1.502 -    // a separate invoker for each distinct signature.
   1.503 -    static Object interpret_L(MethodHandle mh) throws Throwable {
   1.504 -        Object[] av = {mh};
   1.505 -        String sig = null;
   1.506 -        assert(argumentTypesMatch(sig = "L_L", av));
   1.507 -        Object res = mh.form.interpretWithArguments(av);
   1.508 -        assert(returnTypesMatch(sig, av, res));
   1.509 -        return res;
   1.510 -    }
   1.511 -    static Object interpret_L(MethodHandle mh, Object x1) throws Throwable {
   1.512 -        Object[] av = {mh, x1};
   1.513 -        String sig = null;
   1.514 -        assert(argumentTypesMatch(sig = "LL_L", av));
   1.515 -        Object res = mh.form.interpretWithArguments(av);
   1.516 -        assert(returnTypesMatch(sig, av, res));
   1.517 -        return res;
   1.518 -    }
   1.519 -    static Object interpret_L(MethodHandle mh, Object x1, Object x2) throws Throwable {
   1.520 -        Object[] av = {mh, x1, x2};
   1.521 -        String sig = null;
   1.522 -        assert(argumentTypesMatch(sig = "LLL_L", av));
   1.523 -        Object res = mh.form.interpretWithArguments(av);
   1.524 -        assert(returnTypesMatch(sig, av, res));
   1.525 -        return res;
   1.526 -    }
   1.527 -    private static LambdaForm getPreparedForm(String sig) {
   1.528 -        MethodType mtype = signatureType(sig);
   1.529 -        //LambdaForm prep = PREPARED_FORMS.get(sig);
   1.530 -        LambdaForm prep =  mtype.form().cachedLambdaForm(MethodTypeForm.LF_INTERPRET);
   1.531 -        if (prep != null)  return prep;
   1.532 -        assert(isValidSignature(sig));
   1.533 -        prep = new LambdaForm(sig);
   1.534 -//        prep.vmentry = InvokerBytecodeGenerator.generateLambdaFormInterpreterEntryPoint(sig);
   1.535 -        if (true) throw new IllegalStateException();
   1.536 -
   1.537 -        //LambdaForm prep2 = PREPARED_FORMS.putIfAbsent(sig.intern(), prep);
   1.538 -        return mtype.form().setCachedLambdaForm(MethodTypeForm.LF_INTERPRET, prep);
   1.539 -    }
   1.540 -
   1.541 -    // The next few routines are called only from assert expressions
   1.542 -    // They verify that the built-in invokers process the correct raw data types.
   1.543 -    private static boolean argumentTypesMatch(String sig, Object[] av) {
   1.544 -        int arity = signatureArity(sig);
   1.545 -        assert(av.length == arity) : "av.length == arity: av.length=" + av.length + ", arity=" + arity;
   1.546 -        assert(av[0] instanceof MethodHandle) : "av[0] not instace of MethodHandle: " + av[0];
   1.547 -        MethodHandle mh = (MethodHandle) av[0];
   1.548 -        MethodType mt = mh.type();
   1.549 -        assert(mt.parameterCount() == arity-1);
   1.550 -        for (int i = 0; i < av.length; i++) {
   1.551 -            Class<?> pt = (i == 0 ? MethodHandle.class : mt.parameterType(i-1));
   1.552 -            assert(valueMatches(sig.charAt(i), pt, av[i]));
   1.553 -        }
   1.554 -        return true;
   1.555 -    }
   1.556 -    private static boolean valueMatches(char tc, Class<?> type, Object x) {
   1.557 -        // The following line is needed because (...)void method handles can use non-void invokers
   1.558 -        if (type == void.class)  tc = 'V';   // can drop any kind of value
   1.559 -        assert tc == basicType(type) : tc + " == basicType(" + type + ")=" + basicType(type);
   1.560 -        switch (tc) {
   1.561 -        case 'I': assert checkInt(type, x)   : "checkInt(" + type + "," + x +")";   break;
   1.562 -        case 'J': assert x instanceof Long   : "instanceof Long: " + x;             break;
   1.563 -        case 'F': assert x instanceof Float  : "instanceof Float: " + x;            break;
   1.564 -        case 'D': assert x instanceof Double : "instanceof Double: " + x;           break;
   1.565 -        case 'L': assert checkRef(type, x)   : "checkRef(" + type + "," + x + ")";  break;
   1.566 -        case 'V': break;  // allow anything here; will be dropped
   1.567 -        default:  assert(false);
   1.568 -        }
   1.569 -        return true;
   1.570 -    }
   1.571 -    private static boolean returnTypesMatch(String sig, Object[] av, Object res) {
   1.572 -        MethodHandle mh = (MethodHandle) av[0];
   1.573 -        return valueMatches(signatureReturn(sig), mh.type().returnType(), res);
   1.574 -    }
   1.575 -    private static boolean checkInt(Class<?> type, Object x) {
   1.576 -        assert(x instanceof Integer);
   1.577 -        if (type == int.class)  return true;
   1.578 -        Wrapper w = Wrapper.forBasicType(type);
   1.579 -        assert(w.isSubwordOrInt());
   1.580 -        Object x1 = Wrapper.INT.wrap(w.wrap(x));
   1.581 -        return x.equals(x1);
   1.582 -    }
   1.583 -    private static boolean checkRef(Class<?> type, Object x) {
   1.584 -        assert(!type.isPrimitive());
   1.585 -        if (x == null)  return true;
   1.586 -        if (type.isInterface())  return true;
   1.587 -        return type.isInstance(x);
   1.588 -    }
   1.589 -
   1.590 -    /** If the invocation count hits the threshold we spin bytecodes and call that subsequently. */
   1.591 -    private static final int COMPILE_THRESHOLD;
   1.592 -    static {
   1.593 -        if (MethodHandleStatics.COMPILE_THRESHOLD != null)
   1.594 -            COMPILE_THRESHOLD = MethodHandleStatics.COMPILE_THRESHOLD;
   1.595 -        else
   1.596 -            COMPILE_THRESHOLD = 30;  // default value
   1.597 -    }
   1.598 -    private int invocationCounter = 0;
   1.599 -
   1.600 -    @Hidden
   1.601 -    @DontInline
   1.602 -    /** Interpretively invoke this form on the given arguments. */
   1.603 -    Object interpretWithArguments(Object... argumentValues) throws Throwable {
   1.604 -        if (TRACE_INTERPRETER)
   1.605 -            return interpretWithArgumentsTracing(argumentValues);
   1.606 -        checkInvocationCounter();
   1.607 -        assert(arityCheck(argumentValues));
   1.608 -        Object[] values = Arrays.copyOf(argumentValues, names.length);
   1.609 -        for (int i = argumentValues.length; i < values.length; i++) {
   1.610 -            values[i] = interpretName(names[i], values);
   1.611 -        }
   1.612 -        return (result < 0) ? null : values[result];
   1.613 -    }
   1.614 -
   1.615 -    @Hidden
   1.616 -    @DontInline
   1.617 -    /** Evaluate a single Name within this form, applying its function to its arguments. */
   1.618 -    Object interpretName(Name name, Object[] values) throws Throwable {
   1.619 -        if (TRACE_INTERPRETER)
   1.620 -            traceInterpreter("| interpretName", name.debugString(), (Object[]) null);
   1.621 -        Object[] arguments = Arrays.copyOf(name.arguments, name.arguments.length, Object[].class);
   1.622 -        for (int i = 0; i < arguments.length; i++) {
   1.623 -            Object a = arguments[i];
   1.624 -            if (a instanceof Name) {
   1.625 -                int i2 = ((Name)a).index();
   1.626 -                assert(names[i2] == a);
   1.627 -                a = values[i2];
   1.628 -                arguments[i] = a;
   1.629 -            }
   1.630 -        }
   1.631 -        return name.function.invokeWithArguments(arguments);
   1.632 -    }
   1.633 -
   1.634 -    private void checkInvocationCounter() {
   1.635 -        if (COMPILE_THRESHOLD != 0 &&
   1.636 -            invocationCounter < COMPILE_THRESHOLD) {
   1.637 -            invocationCounter++;  // benign race
   1.638 -            if (invocationCounter >= COMPILE_THRESHOLD) {
   1.639 -                // Replace vmentry with a bytecode version of this LF.
   1.640 -                compileToBytecode();
   1.641 -            }
   1.642 -        }
   1.643 -    }
   1.644 -    Object interpretWithArgumentsTracing(Object... argumentValues) throws Throwable {
   1.645 -        traceInterpreter("[ interpretWithArguments", this, argumentValues);
   1.646 -        if (invocationCounter < COMPILE_THRESHOLD) {
   1.647 -            int ctr = invocationCounter++;  // benign race
   1.648 -            traceInterpreter("| invocationCounter", ctr);
   1.649 -            if (invocationCounter >= COMPILE_THRESHOLD) {
   1.650 -                compileToBytecode();
   1.651 -            }
   1.652 -        }
   1.653 -        Object rval;
   1.654 -        try {
   1.655 -            assert(arityCheck(argumentValues));
   1.656 -            Object[] values = Arrays.copyOf(argumentValues, names.length);
   1.657 -            for (int i = argumentValues.length; i < values.length; i++) {
   1.658 -                values[i] = interpretName(names[i], values);
   1.659 -            }
   1.660 -            rval = (result < 0) ? null : values[result];
   1.661 -        } catch (Throwable ex) {
   1.662 -            traceInterpreter("] throw =>", ex);
   1.663 -            throw ex;
   1.664 -        }
   1.665 -        traceInterpreter("] return =>", rval);
   1.666 -        return rval;
   1.667 -    }
   1.668 -
   1.669 -    //** This transform is applied (statically) to every name.function. */
   1.670 -    /*
   1.671 -    private static MethodHandle eraseSubwordTypes(MethodHandle mh) {
   1.672 -        MethodType mt = mh.type();
   1.673 -        if (mt.hasPrimitives()) {
   1.674 -            mt = mt.changeReturnType(eraseSubwordType(mt.returnType()));
   1.675 -            for (int i = 0; i < mt.parameterCount(); i++) {
   1.676 -                mt = mt.changeParameterType(i, eraseSubwordType(mt.parameterType(i)));
   1.677 -            }
   1.678 -            mh = MethodHandles.explicitCastArguments(mh, mt);
   1.679 -        }
   1.680 -        return mh;
   1.681 -    }
   1.682 -    private static Class<?> eraseSubwordType(Class<?> type) {
   1.683 -        if (!type.isPrimitive())  return type;
   1.684 -        if (type == int.class)  return type;
   1.685 -        Wrapper w = Wrapper.forPrimitiveType(type);
   1.686 -        if (w.isSubwordOrInt())  return int.class;
   1.687 -        return type;
   1.688 -    }
   1.689 -    */
   1.690 -
   1.691 -    static void traceInterpreter(String event, Object obj, Object... args) {
   1.692 -        if (TRACE_INTERPRETER) {
   1.693 -            System.out.println("LFI: "+event+" "+(obj != null ? obj : "")+(args != null && args.length != 0 ? Arrays.asList(args) : ""));
   1.694 -        }
   1.695 -    }
   1.696 -    static void traceInterpreter(String event, Object obj) {
   1.697 -        traceInterpreter(event, obj, (Object[])null);
   1.698 -    }
   1.699 -    private boolean arityCheck(Object[] argumentValues) {
   1.700 -        assert(argumentValues.length == arity) : arity+"!="+Arrays.asList(argumentValues)+".length";
   1.701 -        // also check that the leading (receiver) argument is somehow bound to this LF:
   1.702 -        assert(argumentValues[0] instanceof MethodHandle) : "not MH: " + argumentValues[0];
   1.703 -        assert(((MethodHandle)argumentValues[0]).internalForm() == this);
   1.704 -        // note:  argument #0 could also be an interface wrapper, in the future
   1.705 -        return true;
   1.706 -    }
   1.707 -
   1.708 -    private boolean isEmpty() {
   1.709 -        if (result < 0)
   1.710 -            return (names.length == arity);
   1.711 -        else if (result == arity && names.length == arity + 1)
   1.712 -            return names[arity].isConstantZero();
   1.713 -        else
   1.714 -            return false;
   1.715 -    }
   1.716 -
   1.717 -    public String toString() {
   1.718 -        StringBuilder buf = new StringBuilder(debugName+"=Lambda(");
   1.719 -        for (int i = 0; i < names.length; i++) {
   1.720 -            if (i == arity)  buf.append(")=>{");
   1.721 -            Name n = names[i];
   1.722 -            if (i >= arity)  buf.append("\n    ");
   1.723 -            buf.append(n);
   1.724 -            if (i < arity) {
   1.725 -                if (i+1 < arity)  buf.append(",");
   1.726 -                continue;
   1.727 -            }
   1.728 -            buf.append("=").append(n.exprString());
   1.729 -            buf.append(";");
   1.730 -        }
   1.731 -        buf.append(result < 0 ? "void" : names[result]).append("}");
   1.732 -        if (TRACE_INTERPRETER) {
   1.733 -            // Extra verbosity:
   1.734 -            buf.append(":").append(basicTypeSignature());
   1.735 -            buf.append("/").append(vmentry);
   1.736 -        }
   1.737 -        return buf.toString();
   1.738 -    }
   1.739 -
   1.740 -    /**
   1.741 -     * Apply immediate binding for a Name in this form indicated by its position relative to the form.
   1.742 -     * The first parameter to a LambdaForm, a0:L, always represents the form's method handle, so 0 is not
   1.743 -     * accepted as valid.
   1.744 -     */
   1.745 -    LambdaForm bindImmediate(int pos, char basicType, Object value) {
   1.746 -        // must be an argument, and the types must match
   1.747 -        assert pos > 0 && pos < arity && names[pos].type == basicType && Name.typesMatch(basicType, value);
   1.748 -
   1.749 -        int arity2 = arity - 1;
   1.750 -        Name[] names2 = new Name[names.length - 1];
   1.751 -        for (int r = 0, w = 0; r < names.length; ++r, ++w) { // (r)ead from names, (w)rite to names2
   1.752 -            Name n = names[r];
   1.753 -            if (n.isParam()) {
   1.754 -                if (n.index == pos) {
   1.755 -                    // do not copy over the argument that is to be replaced with a literal,
   1.756 -                    // but adjust the write index
   1.757 -                    --w;
   1.758 -                } else {
   1.759 -                    names2[w] = new Name(w, n.type);
   1.760 -                }
   1.761 -            } else {
   1.762 -                Object[] arguments2 = new Object[n.arguments.length];
   1.763 -                for (int i = 0; i < n.arguments.length; ++i) {
   1.764 -                    Object arg = n.arguments[i];
   1.765 -                    if (arg instanceof Name) {
   1.766 -                        int ni = ((Name) arg).index;
   1.767 -                        if (ni == pos) {
   1.768 -                            arguments2[i] = value;
   1.769 -                        } else if (ni < pos) {
   1.770 -                            // replacement position not yet passed
   1.771 -                            arguments2[i] = names2[ni];
   1.772 -                        } else {
   1.773 -                            // replacement position passed
   1.774 -                            arguments2[i] = names2[ni - 1];
   1.775 -                        }
   1.776 -                    } else {
   1.777 -                        arguments2[i] = arg;
   1.778 -                    }
   1.779 -                }
   1.780 -                names2[w] = new Name(n.function, arguments2);
   1.781 -                names2[w].initIndex(w);
   1.782 -            }
   1.783 -        }
   1.784 -
   1.785 -        int result2 = result == -1 ? -1 : result - 1;
   1.786 -        return new LambdaForm(debugName, arity2, names2, result2);
   1.787 -    }
   1.788 -
   1.789 -    LambdaForm bind(int namePos, BoundMethodHandle.SpeciesData oldData) {
   1.790 -        Name name = names[namePos];
   1.791 -        BoundMethodHandle.SpeciesData newData = oldData.extendWithType(name.type);
   1.792 -        return bind(name, newData.getterName(names[0], oldData.fieldCount()), oldData, newData);
   1.793 -    }
   1.794 -    LambdaForm bind(Name name, Name binding,
   1.795 -                    BoundMethodHandle.SpeciesData oldData,
   1.796 -                    BoundMethodHandle.SpeciesData newData) {
   1.797 -        int pos = name.index;
   1.798 -        assert(name.isParam());
   1.799 -        assert(!binding.isParam());
   1.800 -        assert(name.type == binding.type);
   1.801 -        assert(0 <= pos && pos < arity && names[pos] == name);
   1.802 -        assert(binding.function.memberDeclaringClassOrNull() == newData.clazz);
   1.803 -        assert(oldData.getters.length == newData.getters.length-1);
   1.804 -        if (bindCache != null) {
   1.805 -            LambdaForm form = bindCache[pos];
   1.806 -            if (form != null) {
   1.807 -                assert(form.contains(binding)) : "form << " + form + " >> does not contain binding << " + binding + " >>";
   1.808 -                return form;
   1.809 -            }
   1.810 -        } else {
   1.811 -            bindCache = new LambdaForm[arity];
   1.812 -        }
   1.813 -        assert(nameRefsAreLegal());
   1.814 -        int arity2 = arity-1;
   1.815 -        Name[] names2 = names.clone();
   1.816 -        names2[pos] = binding;  // we might move this in a moment
   1.817 -
   1.818 -        // The newly created LF will run with a different BMH.
   1.819 -        // Switch over any pre-existing BMH field references to the new BMH class.
   1.820 -        int firstOldRef = -1;
   1.821 -        for (int i = 0; i < names2.length; i++) {
   1.822 -            Name n = names[i];
   1.823 -            if (n.function != null &&
   1.824 -                n.function.memberDeclaringClassOrNull() == oldData.clazz) {
   1.825 -                MethodHandle oldGetter = n.function.resolvedHandle;
   1.826 -                MethodHandle newGetter = null;
   1.827 -                for (int j = 0; j < oldData.getters.length; j++) {
   1.828 -                    if (oldGetter == oldData.getters[j])
   1.829 -                        newGetter =  newData.getters[j];
   1.830 -                }
   1.831 -                if (newGetter != null) {
   1.832 -                    if (firstOldRef < 0)  firstOldRef = i;
   1.833 -                    Name n2 = new Name(newGetter, n.arguments);
   1.834 -                    names2[i] = n2;
   1.835 -                }
   1.836 -            }
   1.837 -        }
   1.838 -
   1.839 -        // Walk over the new list of names once, in forward order.
   1.840 -        // Replace references to 'name' with 'binding'.
   1.841 -        // Replace data structure references to the old BMH species with the new.
   1.842 -        // This might cause a ripple effect, but it will settle in one pass.
   1.843 -        assert(firstOldRef < 0 || firstOldRef > pos);
   1.844 -        for (int i = pos+1; i < names2.length; i++) {
   1.845 -            if (i <= arity2)  continue;
   1.846 -            names2[i] = names2[i].replaceNames(names, names2, pos, i);
   1.847 -        }
   1.848 -
   1.849 -        //  (a0, a1, name=a2, a3, a4)  =>  (a0, a1, a3, a4, binding)
   1.850 -        int insPos = pos;
   1.851 -        for (; insPos+1 < names2.length; insPos++) {
   1.852 -            Name n = names2[insPos+1];
   1.853 -            if (n.isSiblingBindingBefore(binding)) {
   1.854 -                names2[insPos] = n;
   1.855 -            } else {
   1.856 -                break;
   1.857 -            }
   1.858 -        }
   1.859 -        names2[insPos] = binding;
   1.860 -
   1.861 -        // Since we moved some stuff, maybe update the result reference:
   1.862 -        int result2 = result;
   1.863 -        if (result2 == pos)
   1.864 -            result2 = insPos;
   1.865 -        else if (result2 > pos && result2 <= insPos)
   1.866 -            result2 -= 1;
   1.867 -
   1.868 -        return bindCache[pos] = new LambdaForm(debugName, arity2, names2, result2);
   1.869 -    }
   1.870 -
   1.871 -    boolean contains(Name name) {
   1.872 -        int pos = name.index();
   1.873 -        if (pos >= 0) {
   1.874 -            return pos < names.length && name.equals(names[pos]);
   1.875 -        }
   1.876 -        for (int i = arity; i < names.length; i++) {
   1.877 -            if (name.equals(names[i]))
   1.878 -                return true;
   1.879 -        }
   1.880 -        return false;
   1.881 -    }
   1.882 -
   1.883 -    LambdaForm addArguments(int pos, char... types) {
   1.884 -        assert(pos <= arity);
   1.885 -        int length = names.length;
   1.886 -        int inTypes = types.length;
   1.887 -        Name[] names2 = Arrays.copyOf(names, length + inTypes);
   1.888 -        int arity2 = arity + inTypes;
   1.889 -        int result2 = result;
   1.890 -        if (result2 >= arity)
   1.891 -            result2 += inTypes;
   1.892 -        // names array has MH in slot 0; skip it.
   1.893 -        int argpos = pos + 1;
   1.894 -        // Note:  The LF constructor will rename names2[argpos...].
   1.895 -        // Make space for new arguments (shift temporaries).
   1.896 -        System.arraycopy(names, argpos, names2, argpos + inTypes, length - argpos);
   1.897 -        for (int i = 0; i < inTypes; i++) {
   1.898 -            names2[argpos + i] = new Name(types[i]);
   1.899 -        }
   1.900 -        return new LambdaForm(debugName, arity2, names2, result2);
   1.901 -    }
   1.902 -
   1.903 -    LambdaForm addArguments(int pos, List<Class<?>> types) {
   1.904 -        char[] basicTypes = new char[types.size()];
   1.905 -        for (int i = 0; i < basicTypes.length; i++)
   1.906 -            basicTypes[i] = basicType(types.get(i));
   1.907 -        return addArguments(pos, basicTypes);
   1.908 -    }
   1.909 -
   1.910 -    LambdaForm permuteArguments(int skip, int[] reorder, char[] types) {
   1.911 -        // Note:  When inArg = reorder[outArg], outArg is fed by a copy of inArg.
   1.912 -        // The types are the types of the new (incoming) arguments.
   1.913 -        int length = names.length;
   1.914 -        int inTypes = types.length;
   1.915 -        int outArgs = reorder.length;
   1.916 -        assert(skip+outArgs == arity);
   1.917 -        assert(permutedTypesMatch(reorder, types, names, skip));
   1.918 -        int pos = 0;
   1.919 -        // skip trivial first part of reordering:
   1.920 -        while (pos < outArgs && reorder[pos] == pos)  pos += 1;
   1.921 -        Name[] names2 = new Name[length - outArgs + inTypes];
   1.922 -        System.arraycopy(names, 0, names2, 0, skip+pos);
   1.923 -        // copy the body:
   1.924 -        int bodyLength = length - arity;
   1.925 -        System.arraycopy(names, skip+outArgs, names2, skip+inTypes, bodyLength);
   1.926 -        int arity2 = names2.length - bodyLength;
   1.927 -        int result2 = result;
   1.928 -        if (result2 >= 0) {
   1.929 -            if (result2 < skip+outArgs) {
   1.930 -                // return the corresponding inArg
   1.931 -                result2 = reorder[result2-skip];
   1.932 -            } else {
   1.933 -                result2 = result2 - outArgs + inTypes;
   1.934 -            }
   1.935 -        }
   1.936 -        // rework names in the body:
   1.937 -        for (int j = pos; j < outArgs; j++) {
   1.938 -            Name n = names[skip+j];
   1.939 -            int i = reorder[j];
   1.940 -            // replace names[skip+j] by names2[skip+i]
   1.941 -            Name n2 = names2[skip+i];
   1.942 -            if (n2 == null)
   1.943 -                names2[skip+i] = n2 = new Name(types[i]);
   1.944 -            else
   1.945 -                assert(n2.type == types[i]);
   1.946 -            for (int k = arity2; k < names2.length; k++) {
   1.947 -                names2[k] = names2[k].replaceName(n, n2);
   1.948 -            }
   1.949 -        }
   1.950 -        // some names are unused, but must be filled in
   1.951 -        for (int i = skip+pos; i < arity2; i++) {
   1.952 -            if (names2[i] == null)
   1.953 -                names2[i] = argument(i, types[i - skip]);
   1.954 -        }
   1.955 -        for (int j = arity; j < names.length; j++) {
   1.956 -            int i = j - arity + arity2;
   1.957 -            // replace names2[i] by names[j]
   1.958 -            Name n = names[j];
   1.959 -            Name n2 = names2[i];
   1.960 -            if (n != n2) {
   1.961 -                for (int k = i+1; k < names2.length; k++) {
   1.962 -                    names2[k] = names2[k].replaceName(n, n2);
   1.963 -                }
   1.964 -            }
   1.965 -        }
   1.966 -        return new LambdaForm(debugName, arity2, names2, result2);
   1.967 -    }
   1.968 -
   1.969 -    static boolean permutedTypesMatch(int[] reorder, char[] types, Name[] names, int skip) {
   1.970 -        int inTypes = types.length;
   1.971 -        int outArgs = reorder.length;
   1.972 -        for (int i = 0; i < outArgs; i++) {
   1.973 -            assert(names[skip+i].isParam());
   1.974 -            assert(names[skip+i].type == types[reorder[i]]);
   1.975 -        }
   1.976 -        return true;
   1.977 -    }
   1.978 -
   1.979 -    static class NamedFunction {
   1.980 -        final MemberName member;
   1.981 -        @Stable MethodHandle resolvedHandle;
   1.982 -        @Stable MethodHandle invoker;
   1.983 -
   1.984 -        NamedFunction(MethodHandle resolvedHandle) {
   1.985 -            this(resolvedHandle.internalMemberName(), resolvedHandle);
   1.986 -        }
   1.987 -        NamedFunction(MemberName member, MethodHandle resolvedHandle) {
   1.988 -            this.member = member;
   1.989 -            //resolvedHandle = eraseSubwordTypes(resolvedHandle);
   1.990 -            this.resolvedHandle = resolvedHandle;
   1.991 -        }
   1.992 -        NamedFunction(MethodType basicInvokerType) {
   1.993 -            assert(basicInvokerType == basicInvokerType.basicType()) : basicInvokerType;
   1.994 -            if (basicInvokerType.parameterSlotCount() < MethodType.MAX_MH_INVOKER_ARITY) {
   1.995 -                this.resolvedHandle = basicInvokerType.invokers().basicInvoker();
   1.996 -                this.member = resolvedHandle.internalMemberName();
   1.997 -            } else {
   1.998 -                // necessary to pass BigArityTest
   1.999 -                this.member = Invokers.invokeBasicMethod(basicInvokerType);
  1.1000 -            }
  1.1001 -        }
  1.1002 -
  1.1003 -        // The next 3 constructors are used to break circular dependencies on MH.invokeStatic, etc.
  1.1004 -        // Any LambdaForm containing such a member is not interpretable.
  1.1005 -        // This is OK, since all such LFs are prepared with special primitive vmentry points.
  1.1006 -        // And even without the resolvedHandle, the name can still be compiled and optimized.
  1.1007 -        NamedFunction(Method method) {
  1.1008 -            this(new MemberName(method));
  1.1009 -        }
  1.1010 -        NamedFunction(Field field) {
  1.1011 -            this(new MemberName(field));
  1.1012 -        }
  1.1013 -        NamedFunction(MemberName member) {
  1.1014 -            this.member = member;
  1.1015 -            this.resolvedHandle = null;
  1.1016 -        }
  1.1017 -
  1.1018 -        MethodHandle resolvedHandle() {
  1.1019 -            if (resolvedHandle == null)  resolve();
  1.1020 -            return resolvedHandle;
  1.1021 -        }
  1.1022 -
  1.1023 -        void resolve() {
  1.1024 -            resolvedHandle = DirectMethodHandle.make(member);
  1.1025 -        }
  1.1026 -
  1.1027 -        @Override
  1.1028 -        public boolean equals(Object other) {
  1.1029 -            if (this == other) return true;
  1.1030 -            if (other == null) return false;
  1.1031 -            if (!(other instanceof NamedFunction)) return false;
  1.1032 -            NamedFunction that = (NamedFunction) other;
  1.1033 -            return this.member != null && this.member.equals(that.member);
  1.1034 -        }
  1.1035 -
  1.1036 -        @Override
  1.1037 -        public int hashCode() {
  1.1038 -            if (member != null)
  1.1039 -                return member.hashCode();
  1.1040 -            return super.hashCode();
  1.1041 -        }
  1.1042 -
  1.1043 -        // Put the predefined NamedFunction invokers into the table.
  1.1044 -        static void initializeInvokers() {
  1.1045 -            for (MemberName m : MemberName.getFactory().getMethods(NamedFunction.class, false, null, null, null)) {
  1.1046 -                if (!m.isStatic() || !m.isPackage())  continue;
  1.1047 -                MethodType type = m.getMethodType();
  1.1048 -                if (type.equals(INVOKER_METHOD_TYPE) &&
  1.1049 -                    m.getName().startsWith("invoke_")) {
  1.1050 -                    String sig = m.getName().substring("invoke_".length());
  1.1051 -                    int arity = LambdaForm.signatureArity(sig);
  1.1052 -                    MethodType srcType = MethodType.genericMethodType(arity);
  1.1053 -                    if (LambdaForm.signatureReturn(sig) == 'V')
  1.1054 -                        srcType = srcType.changeReturnType(void.class);
  1.1055 -                    MethodTypeForm typeForm = srcType.form();
  1.1056 -                    typeForm.namedFunctionInvoker = DirectMethodHandle.make(m);
  1.1057 -                }
  1.1058 -            }
  1.1059 -        }
  1.1060 -
  1.1061 -        // The following are predefined NamedFunction invokers.  The system must build
  1.1062 -        // a separate invoker for each distinct signature.
  1.1063 -        /** void return type invokers. */
  1.1064 -        @Hidden
  1.1065 -        static Object invoke__V(MethodHandle mh, Object[] a) throws Throwable {
  1.1066 -            assert(a.length == 0);
  1.1067 -            mh.invokeBasic();
  1.1068 -            return null;
  1.1069 -        }
  1.1070 -        @Hidden
  1.1071 -        static Object invoke_L_V(MethodHandle mh, Object[] a) throws Throwable {
  1.1072 -            assert(a.length == 1);
  1.1073 -            mh.invokeBasic(a[0]);
  1.1074 -            return null;
  1.1075 -        }
  1.1076 -        @Hidden
  1.1077 -        static Object invoke_LL_V(MethodHandle mh, Object[] a) throws Throwable {
  1.1078 -            assert(a.length == 2);
  1.1079 -            mh.invokeBasic(a[0], a[1]);
  1.1080 -            return null;
  1.1081 -        }
  1.1082 -        @Hidden
  1.1083 -        static Object invoke_LLL_V(MethodHandle mh, Object[] a) throws Throwable {
  1.1084 -            assert(a.length == 3);
  1.1085 -            mh.invokeBasic(a[0], a[1], a[2]);
  1.1086 -            return null;
  1.1087 -        }
  1.1088 -        @Hidden
  1.1089 -        static Object invoke_LLLL_V(MethodHandle mh, Object[] a) throws Throwable {
  1.1090 -            assert(a.length == 4);
  1.1091 -            mh.invokeBasic(a[0], a[1], a[2], a[3]);
  1.1092 -            return null;
  1.1093 -        }
  1.1094 -        @Hidden
  1.1095 -        static Object invoke_LLLLL_V(MethodHandle mh, Object[] a) throws Throwable {
  1.1096 -            assert(a.length == 5);
  1.1097 -            mh.invokeBasic(a[0], a[1], a[2], a[3], a[4]);
  1.1098 -            return null;
  1.1099 -        }
  1.1100 -        /** Object return type invokers. */
  1.1101 -        @Hidden
  1.1102 -        static Object invoke__L(MethodHandle mh, Object[] a) throws Throwable {
  1.1103 -            assert(a.length == 0);
  1.1104 -            return mh.invokeBasic();
  1.1105 -        }
  1.1106 -        @Hidden
  1.1107 -        static Object invoke_L_L(MethodHandle mh, Object[] a) throws Throwable {
  1.1108 -            assert(a.length == 1);
  1.1109 -            return mh.invokeBasic(a[0]);
  1.1110 -        }
  1.1111 -        @Hidden
  1.1112 -        static Object invoke_LL_L(MethodHandle mh, Object[] a) throws Throwable {
  1.1113 -            assert(a.length == 2);
  1.1114 -            return mh.invokeBasic(a[0], a[1]);
  1.1115 -        }
  1.1116 -        @Hidden
  1.1117 -        static Object invoke_LLL_L(MethodHandle mh, Object[] a) throws Throwable {
  1.1118 -            assert(a.length == 3);
  1.1119 -            return mh.invokeBasic(a[0], a[1], a[2]);
  1.1120 -        }
  1.1121 -        @Hidden
  1.1122 -        static Object invoke_LLLL_L(MethodHandle mh, Object[] a) throws Throwable {
  1.1123 -            assert(a.length == 4);
  1.1124 -            return mh.invokeBasic(a[0], a[1], a[2], a[3]);
  1.1125 -        }
  1.1126 -        @Hidden
  1.1127 -        static Object invoke_LLLLL_L(MethodHandle mh, Object[] a) throws Throwable {
  1.1128 -            assert(a.length == 5);
  1.1129 -            return mh.invokeBasic(a[0], a[1], a[2], a[3], a[4]);
  1.1130 -        }
  1.1131 -
  1.1132 -        static final MethodType INVOKER_METHOD_TYPE =
  1.1133 -            MethodType.methodType(Object.class, MethodHandle.class, Object[].class);
  1.1134 -
  1.1135 -        private static MethodHandle computeInvoker(MethodTypeForm typeForm) {
  1.1136 -            MethodHandle mh = typeForm.namedFunctionInvoker;
  1.1137 -            if (mh != null)  return mh;
  1.1138 -//            MemberName invoker = InvokerBytecodeGenerator.generateNamedFunctionInvoker(typeForm);  // this could take a while
  1.1139 -            if (true) throw new IllegalStateException();
  1.1140 -//            mh = DirectMethodHandle.make(invoker);
  1.1141 -            MethodHandle mh2 = typeForm.namedFunctionInvoker;
  1.1142 -            if (mh2 != null)  return mh2;  // benign race
  1.1143 -            if (!mh.type().equals(INVOKER_METHOD_TYPE))
  1.1144 -                throw new InternalError(mh.debugString());
  1.1145 -            return typeForm.namedFunctionInvoker = mh;
  1.1146 -        }
  1.1147 -
  1.1148 -        @Hidden
  1.1149 -        Object invokeWithArguments(Object... arguments) throws Throwable {
  1.1150 -            // If we have a cached invoker, call it right away.
  1.1151 -            // NOTE: The invoker always returns a reference value.
  1.1152 -            if (TRACE_INTERPRETER)  return invokeWithArgumentsTracing(arguments);
  1.1153 -            assert(checkArgumentTypes(arguments, methodType()));
  1.1154 -            return invoker().invokeBasic(resolvedHandle(), arguments);
  1.1155 -        }
  1.1156 -
  1.1157 -        @Hidden
  1.1158 -        Object invokeWithArgumentsTracing(Object[] arguments) throws Throwable {
  1.1159 -            Object rval;
  1.1160 -            try {
  1.1161 -                traceInterpreter("[ call", this, arguments);
  1.1162 -                if (invoker == null) {
  1.1163 -                    traceInterpreter("| getInvoker", this);
  1.1164 -                    invoker();
  1.1165 -                }
  1.1166 -                if (resolvedHandle == null) {
  1.1167 -                    traceInterpreter("| resolve", this);
  1.1168 -                    resolvedHandle();
  1.1169 -                }
  1.1170 -                assert(checkArgumentTypes(arguments, methodType()));
  1.1171 -                rval = invoker().invokeBasic(resolvedHandle(), arguments);
  1.1172 -            } catch (Throwable ex) {
  1.1173 -                traceInterpreter("] throw =>", ex);
  1.1174 -                throw ex;
  1.1175 -            }
  1.1176 -            traceInterpreter("] return =>", rval);
  1.1177 -            return rval;
  1.1178 -        }
  1.1179 -
  1.1180 -        private MethodHandle invoker() {
  1.1181 -            if (invoker != null)  return invoker;
  1.1182 -            // Get an invoker and cache it.
  1.1183 -            return invoker = computeInvoker(methodType().form());
  1.1184 -        }
  1.1185 -
  1.1186 -        private static boolean checkArgumentTypes(Object[] arguments, MethodType methodType) {
  1.1187 -            if (true)  return true;  // FIXME
  1.1188 -            MethodType dstType = methodType.form().erasedType();
  1.1189 -            MethodType srcType = dstType.basicType().wrap();
  1.1190 -            Class<?>[] ptypes = new Class<?>[arguments.length];
  1.1191 -            for (int i = 0; i < arguments.length; i++) {
  1.1192 -                Object arg = arguments[i];
  1.1193 -                Class<?> ptype = arg == null ? Object.class : arg.getClass();
  1.1194 -                // If the dest. type is a primitive we keep the
  1.1195 -                // argument type.
  1.1196 -                ptypes[i] = dstType.parameterType(i).isPrimitive() ? ptype : Object.class;
  1.1197 -            }
  1.1198 -            MethodType argType = MethodType.methodType(srcType.returnType(), ptypes).wrap();
  1.1199 -            assert(argType.isConvertibleTo(srcType)) : "wrong argument types: cannot convert " + argType + " to " + srcType;
  1.1200 -            return true;
  1.1201 -        }
  1.1202 -
  1.1203 -        String basicTypeSignature() {
  1.1204 -            //return LambdaForm.basicTypeSignature(resolvedHandle.type());
  1.1205 -            return LambdaForm.basicTypeSignature(methodType());
  1.1206 -        }
  1.1207 -
  1.1208 -        MethodType methodType() {
  1.1209 -            if (resolvedHandle != null)
  1.1210 -                return resolvedHandle.type();
  1.1211 -            else
  1.1212 -                // only for certain internal LFs during bootstrapping
  1.1213 -                return member.getInvocationType();
  1.1214 -        }
  1.1215 -
  1.1216 -        MemberName member() {
  1.1217 -            assert(assertMemberIsConsistent());
  1.1218 -            return member;
  1.1219 -        }
  1.1220 -
  1.1221 -        // Called only from assert.
  1.1222 -        private boolean assertMemberIsConsistent() {
  1.1223 -            if (resolvedHandle instanceof DirectMethodHandle) {
  1.1224 -                MemberName m = resolvedHandle.internalMemberName();
  1.1225 -                assert(m.equals(member));
  1.1226 -            }
  1.1227 -            return true;
  1.1228 -        }
  1.1229 -
  1.1230 -        Class<?> memberDeclaringClassOrNull() {
  1.1231 -            return (member == null) ? null : member.getDeclaringClass();
  1.1232 -        }
  1.1233 -
  1.1234 -        char returnType() {
  1.1235 -            return basicType(methodType().returnType());
  1.1236 -        }
  1.1237 -
  1.1238 -        char parameterType(int n) {
  1.1239 -            return basicType(methodType().parameterType(n));
  1.1240 -        }
  1.1241 -
  1.1242 -        int arity() {
  1.1243 -            //int siglen = member.getMethodType().parameterCount();
  1.1244 -            //if (!member.isStatic())  siglen += 1;
  1.1245 -            //return siglen;
  1.1246 -            return methodType().parameterCount();
  1.1247 -        }
  1.1248 -
  1.1249 -        public String toString() {
  1.1250 -            if (member == null)  return String.valueOf(resolvedHandle);
  1.1251 -            return member.getDeclaringClass().getSimpleName()+"."+member.getName();
  1.1252 -        }
  1.1253 -    }
  1.1254 -
  1.1255 -    void resolve() {
  1.1256 -        for (Name n : names) n.resolve();
  1.1257 -    }
  1.1258 -
  1.1259 -    public static char basicType(Class<?> type) {
  1.1260 -        char c = Wrapper.basicTypeChar(type);
  1.1261 -        if ("ZBSC".indexOf(c) >= 0)  c = 'I';
  1.1262 -        assert("LIJFDV".indexOf(c) >= 0);
  1.1263 -        return c;
  1.1264 -    }
  1.1265 -    public static char[] basicTypes(List<Class<?>> types) {
  1.1266 -        char[] btypes = new char[types.size()];
  1.1267 -        for (int i = 0; i < btypes.length; i++) {
  1.1268 -            btypes[i] = basicType(types.get(i));
  1.1269 -        }
  1.1270 -        return btypes;
  1.1271 -    }
  1.1272 -    public static String basicTypeSignature(MethodType type) {
  1.1273 -        char[] sig = new char[type.parameterCount() + 2];
  1.1274 -        int sigp = 0;
  1.1275 -        for (Class<?> pt : type.parameterList()) {
  1.1276 -            sig[sigp++] = basicType(pt);
  1.1277 -        }
  1.1278 -        sig[sigp++] = '_';
  1.1279 -        sig[sigp++] = basicType(type.returnType());
  1.1280 -        assert(sigp == sig.length);
  1.1281 -        return String.valueOf(sig);
  1.1282 -    }
  1.1283 -
  1.1284 -    static final class Name {
  1.1285 -        final char type;
  1.1286 -        private short index;
  1.1287 -        final NamedFunction function;
  1.1288 -        @Stable final Object[] arguments;
  1.1289 -
  1.1290 -        private Name(int index, char type, NamedFunction function, Object[] arguments) {
  1.1291 -            this.index = (short)index;
  1.1292 -            this.type = type;
  1.1293 -            this.function = function;
  1.1294 -            this.arguments = arguments;
  1.1295 -            assert(this.index == index);
  1.1296 -        }
  1.1297 -        Name(MethodHandle function, Object... arguments) {
  1.1298 -            this(new NamedFunction(function), arguments);
  1.1299 -        }
  1.1300 -        Name(MethodType functionType, Object... arguments) {
  1.1301 -            this(new NamedFunction(functionType), arguments);
  1.1302 -            assert(arguments[0] instanceof Name && ((Name)arguments[0]).type == 'L');
  1.1303 -        }
  1.1304 -        Name(MemberName function, Object... arguments) {
  1.1305 -            this(new NamedFunction(function), arguments);
  1.1306 -        }
  1.1307 -        Name(NamedFunction function, Object... arguments) {
  1.1308 -            this(-1, function.returnType(), function, arguments = arguments.clone());
  1.1309 -            assert(arguments.length == function.arity()) : "arity mismatch: arguments.length=" + arguments.length + " == function.arity()=" + function.arity() + " in " + debugString();
  1.1310 -            for (int i = 0; i < arguments.length; i++)
  1.1311 -                assert(typesMatch(function.parameterType(i), arguments[i])) : "types don't match: function.parameterType(" + i + ")=" + function.parameterType(i) + ", arguments[" + i + "]=" + arguments[i] + " in " + debugString();
  1.1312 -        }
  1.1313 -        Name(int index, char type) {
  1.1314 -            this(index, type, null, null);
  1.1315 -        }
  1.1316 -        Name(char type) {
  1.1317 -            this(-1, type);
  1.1318 -        }
  1.1319 -
  1.1320 -        char type() { return type; }
  1.1321 -        int index() { return index; }
  1.1322 -        boolean initIndex(int i) {
  1.1323 -            if (index != i) {
  1.1324 -                if (index != -1)  return false;
  1.1325 -                index = (short)i;
  1.1326 -            }
  1.1327 -            return true;
  1.1328 -        }
  1.1329 -
  1.1330 -
  1.1331 -        void resolve() {
  1.1332 -            if (function != null)
  1.1333 -                function.resolve();
  1.1334 -        }
  1.1335 -
  1.1336 -        Name newIndex(int i) {
  1.1337 -            if (initIndex(i))  return this;
  1.1338 -            return cloneWithIndex(i);
  1.1339 -        }
  1.1340 -        Name cloneWithIndex(int i) {
  1.1341 -            Object[] newArguments = (arguments == null) ? null : arguments.clone();
  1.1342 -            return new Name(i, type, function, newArguments);
  1.1343 -        }
  1.1344 -        Name replaceName(Name oldName, Name newName) {  // FIXME: use replaceNames uniformly
  1.1345 -            if (oldName == newName)  return this;
  1.1346 -            @SuppressWarnings("LocalVariableHidesMemberVariable")
  1.1347 -            Object[] arguments = this.arguments;
  1.1348 -            if (arguments == null)  return this;
  1.1349 -            boolean replaced = false;
  1.1350 -            for (int j = 0; j < arguments.length; j++) {
  1.1351 -                if (arguments[j] == oldName) {
  1.1352 -                    if (!replaced) {
  1.1353 -                        replaced = true;
  1.1354 -                        arguments = arguments.clone();
  1.1355 -                    }
  1.1356 -                    arguments[j] = newName;
  1.1357 -                }
  1.1358 -            }
  1.1359 -            if (!replaced)  return this;
  1.1360 -            return new Name(function, arguments);
  1.1361 -        }
  1.1362 -        Name replaceNames(Name[] oldNames, Name[] newNames, int start, int end) {
  1.1363 -            @SuppressWarnings("LocalVariableHidesMemberVariable")
  1.1364 -            Object[] arguments = this.arguments;
  1.1365 -            boolean replaced = false;
  1.1366 -        eachArg:
  1.1367 -            for (int j = 0; j < arguments.length; j++) {
  1.1368 -                if (arguments[j] instanceof Name) {
  1.1369 -                    Name n = (Name) arguments[j];
  1.1370 -                    int check = n.index;
  1.1371 -                    // harmless check to see if the thing is already in newNames:
  1.1372 -                    if (check >= 0 && check < newNames.length && n == newNames[check])
  1.1373 -                        continue eachArg;
  1.1374 -                    // n might not have the correct index: n != oldNames[n.index].
  1.1375 -                    for (int i = start; i < end; i++) {
  1.1376 -                        if (n == oldNames[i]) {
  1.1377 -                            if (n == newNames[i])
  1.1378 -                                continue eachArg;
  1.1379 -                            if (!replaced) {
  1.1380 -                                replaced = true;
  1.1381 -                                arguments = arguments.clone();
  1.1382 -                            }
  1.1383 -                            arguments[j] = newNames[i];
  1.1384 -                            continue eachArg;
  1.1385 -                        }
  1.1386 -                    }
  1.1387 -                }
  1.1388 -            }
  1.1389 -            if (!replaced)  return this;
  1.1390 -            return new Name(function, arguments);
  1.1391 -        }
  1.1392 -        void internArguments() {
  1.1393 -            @SuppressWarnings("LocalVariableHidesMemberVariable")
  1.1394 -            Object[] arguments = this.arguments;
  1.1395 -            for (int j = 0; j < arguments.length; j++) {
  1.1396 -                if (arguments[j] instanceof Name) {
  1.1397 -                    Name n = (Name) arguments[j];
  1.1398 -                    if (n.isParam() && n.index < INTERNED_ARGUMENT_LIMIT)
  1.1399 -                        arguments[j] = internArgument(n);
  1.1400 -                }
  1.1401 -            }
  1.1402 -        }
  1.1403 -        boolean isParam() {
  1.1404 -            return function == null;
  1.1405 -        }
  1.1406 -        boolean isConstantZero() {
  1.1407 -            return !isParam() && arguments.length == 0 && function.equals(constantZero(0, type).function);
  1.1408 -        }
  1.1409 -
  1.1410 -        public String toString() {
  1.1411 -            return (isParam()?"a":"t")+(index >= 0 ? index : System.identityHashCode(this))+":"+type;
  1.1412 -        }
  1.1413 -        public String debugString() {
  1.1414 -            String s = toString();
  1.1415 -            return (function == null) ? s : s + "=" + exprString();
  1.1416 -        }
  1.1417 -        public String exprString() {
  1.1418 -            if (function == null)  return "null";
  1.1419 -            StringBuilder buf = new StringBuilder(function.toString());
  1.1420 -            buf.append("(");
  1.1421 -            String cma = "";
  1.1422 -            for (Object a : arguments) {
  1.1423 -                buf.append(cma); cma = ",";
  1.1424 -                if (a instanceof Name || a instanceof Integer)
  1.1425 -                    buf.append(a);
  1.1426 -                else
  1.1427 -                    buf.append("(").append(a).append(")");
  1.1428 -            }
  1.1429 -            buf.append(")");
  1.1430 -            return buf.toString();
  1.1431 -        }
  1.1432 -
  1.1433 -        private static boolean typesMatch(char parameterType, Object object) {
  1.1434 -            if (object instanceof Name) {
  1.1435 -                return ((Name)object).type == parameterType;
  1.1436 -            }
  1.1437 -            switch (parameterType) {
  1.1438 -                case 'I':  return object instanceof Integer;
  1.1439 -                case 'J':  return object instanceof Long;
  1.1440 -                case 'F':  return object instanceof Float;
  1.1441 -                case 'D':  return object instanceof Double;
  1.1442 -            }
  1.1443 -            assert(parameterType == 'L');
  1.1444 -            return true;
  1.1445 -        }
  1.1446 -
  1.1447 -        /**
  1.1448 -         * Does this Name precede the given binding node in some canonical order?
  1.1449 -         * This predicate is used to order data bindings (via insertion sort)
  1.1450 -         * with some stability.
  1.1451 -         */
  1.1452 -        boolean isSiblingBindingBefore(Name binding) {
  1.1453 -            assert(!binding.isParam());
  1.1454 -            if (isParam())  return true;
  1.1455 -            if (function.equals(binding.function) &&
  1.1456 -                arguments.length == binding.arguments.length) {
  1.1457 -                boolean sawInt = false;
  1.1458 -                for (int i = 0; i < arguments.length; i++) {
  1.1459 -                    Object a1 = arguments[i];
  1.1460 -                    Object a2 = binding.arguments[i];
  1.1461 -                    if (!a1.equals(a2)) {
  1.1462 -                        if (a1 instanceof Integer && a2 instanceof Integer) {
  1.1463 -                            if (sawInt)  continue;
  1.1464 -                            sawInt = true;
  1.1465 -                            if ((int)a1 < (int)a2)  continue;  // still might be true
  1.1466 -                        }
  1.1467 -                        return false;
  1.1468 -                    }
  1.1469 -                }
  1.1470 -                return sawInt;
  1.1471 -            }
  1.1472 -            return false;
  1.1473 -        }
  1.1474 -
  1.1475 -        public boolean equals(Name that) {
  1.1476 -            if (this == that)  return true;
  1.1477 -            if (isParam())
  1.1478 -                // each parameter is a unique atom
  1.1479 -                return false;  // this != that
  1.1480 -            return
  1.1481 -                //this.index == that.index &&
  1.1482 -                this.type == that.type &&
  1.1483 -                this.function.equals(that.function) &&
  1.1484 -                Arrays.equals(this.arguments, that.arguments);
  1.1485 -        }
  1.1486 -        @Override
  1.1487 -        public boolean equals(Object x) {
  1.1488 -            return x instanceof Name && equals((Name)x);
  1.1489 -        }
  1.1490 -        @Override
  1.1491 -        public int hashCode() {
  1.1492 -            if (isParam())
  1.1493 -                return index | (type << 8);
  1.1494 -            return function.hashCode() ^ Arrays.hashCode(arguments);
  1.1495 -        }
  1.1496 -    }
  1.1497 -
  1.1498 -    static Name argument(int which, char type) {
  1.1499 -        int tn = ALL_TYPES.indexOf(type);
  1.1500 -        if (tn < 0 || which >= INTERNED_ARGUMENT_LIMIT)
  1.1501 -            return new Name(which, type);
  1.1502 -        return INTERNED_ARGUMENTS[tn][which];
  1.1503 -    }
  1.1504 -    static Name internArgument(Name n) {
  1.1505 -        assert(n.isParam()) : "not param: " + n;
  1.1506 -        assert(n.index < INTERNED_ARGUMENT_LIMIT);
  1.1507 -        return argument(n.index, n.type);
  1.1508 -    }
  1.1509 -    static Name[] arguments(int extra, String types) {
  1.1510 -        int length = types.length();
  1.1511 -        Name[] names = new Name[length + extra];
  1.1512 -        for (int i = 0; i < length; i++)
  1.1513 -            names[i] = argument(i, types.charAt(i));
  1.1514 -        return names;
  1.1515 -    }
  1.1516 -    static Name[] arguments(int extra, char... types) {
  1.1517 -        int length = types.length;
  1.1518 -        Name[] names = new Name[length + extra];
  1.1519 -        for (int i = 0; i < length; i++)
  1.1520 -            names[i] = argument(i, types[i]);
  1.1521 -        return names;
  1.1522 -    }
  1.1523 -    static Name[] arguments(int extra, List<Class<?>> types) {
  1.1524 -        int length = types.size();
  1.1525 -        Name[] names = new Name[length + extra];
  1.1526 -        for (int i = 0; i < length; i++)
  1.1527 -            names[i] = argument(i, basicType(types.get(i)));
  1.1528 -        return names;
  1.1529 -    }
  1.1530 -    static Name[] arguments(int extra, Class<?>... types) {
  1.1531 -        int length = types.length;
  1.1532 -        Name[] names = new Name[length + extra];
  1.1533 -        for (int i = 0; i < length; i++)
  1.1534 -            names[i] = argument(i, basicType(types[i]));
  1.1535 -        return names;
  1.1536 -    }
  1.1537 -    static Name[] arguments(int extra, MethodType types) {
  1.1538 -        int length = types.parameterCount();
  1.1539 -        Name[] names = new Name[length + extra];
  1.1540 -        for (int i = 0; i < length; i++)
  1.1541 -            names[i] = argument(i, basicType(types.parameterType(i)));
  1.1542 -        return names;
  1.1543 -    }
  1.1544 -    static final String ALL_TYPES = "LIJFD";  // omit V, not an argument type
  1.1545 -    static final int INTERNED_ARGUMENT_LIMIT = 10;
  1.1546 -    private static final Name[][] INTERNED_ARGUMENTS
  1.1547 -            = new Name[ALL_TYPES.length()][INTERNED_ARGUMENT_LIMIT];
  1.1548 -    static {
  1.1549 -        for (int tn = 0; tn < ALL_TYPES.length(); tn++) {
  1.1550 -            for (int i = 0; i < INTERNED_ARGUMENTS[tn].length; i++) {
  1.1551 -                char type = ALL_TYPES.charAt(tn);
  1.1552 -                INTERNED_ARGUMENTS[tn][i] = new Name(i, type);
  1.1553 -            }
  1.1554 -        }
  1.1555 -    }
  1.1556 -
  1.1557 -    private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
  1.1558 -
  1.1559 -    static Name constantZero(int which, char type) {
  1.1560 -        return CONSTANT_ZERO[ALL_TYPES.indexOf(type)].newIndex(which);
  1.1561 -    }
  1.1562 -    private static final Name[] CONSTANT_ZERO
  1.1563 -            = new Name[ALL_TYPES.length()];
  1.1564 -    static {
  1.1565 -        for (int tn = 0; tn < ALL_TYPES.length(); tn++) {
  1.1566 -            char bt = ALL_TYPES.charAt(tn);
  1.1567 -            Wrapper wrap = Wrapper.forBasicType(bt);
  1.1568 -            MemberName zmem = new MemberName(LambdaForm.class, "zero"+bt, MethodType.methodType(wrap.primitiveType()), REF_invokeStatic);
  1.1569 -            try {
  1.1570 -                zmem = IMPL_NAMES.resolveOrFail(REF_invokeStatic, zmem, null, NoSuchMethodException.class);
  1.1571 -            } catch (IllegalAccessException|NoSuchMethodException ex) {
  1.1572 -                throw newInternalError(ex);
  1.1573 -            }
  1.1574 -            NamedFunction zcon = new NamedFunction(zmem);
  1.1575 -            Name n = new Name(zcon).newIndex(0);
  1.1576 -            assert(n.type == ALL_TYPES.charAt(tn));
  1.1577 -            CONSTANT_ZERO[tn] = n;
  1.1578 -            assert(n.isConstantZero());
  1.1579 -        }
  1.1580 -    }
  1.1581 -
  1.1582 -    // Avoid appealing to ValueConversions at bootstrap time:
  1.1583 -    private static int zeroI() { return 0; }
  1.1584 -    private static long zeroJ() { return 0; }
  1.1585 -    private static float zeroF() { return 0; }
  1.1586 -    private static double zeroD() { return 0; }
  1.1587 -    private static Object zeroL() { return null; }
  1.1588 -
  1.1589 -    // Put this last, so that previous static inits can run before.
  1.1590 -    static {
  1.1591 -        if (USE_PREDEFINED_INTERPRET_METHODS)
  1.1592 -            PREPARED_FORMS.putAll(computeInitialPreparedForms());
  1.1593 -    }
  1.1594 -
  1.1595 -    /**
  1.1596 -     * Internal marker for byte-compiled LambdaForms.
  1.1597 -     */
  1.1598 -    /*non-public*/
  1.1599 -    @Target(ElementType.METHOD)
  1.1600 -    @Retention(RetentionPolicy.RUNTIME)
  1.1601 -    @interface Compiled {
  1.1602 -    }
  1.1603 -
  1.1604 -    /**
  1.1605 -     * Internal marker for LambdaForm interpreter frames.
  1.1606 -     */
  1.1607 -    /*non-public*/
  1.1608 -    @Target(ElementType.METHOD)
  1.1609 -    @Retention(RetentionPolicy.RUNTIME)
  1.1610 -    @interface Hidden {
  1.1611 -    }
  1.1612 -
  1.1613 -
  1.1614 -/*
  1.1615 -    // Smoke-test for the invokers used in this file.
  1.1616 -    static void testMethodHandleLinkers() throws Throwable {
  1.1617 -        MemberName.Factory lookup = MemberName.getFactory();
  1.1618 -        MemberName asList_MN = new MemberName(Arrays.class, "asList",
  1.1619 -                                              MethodType.methodType(List.class, Object[].class),
  1.1620 -                                              REF_invokeStatic);
  1.1621 -        //MethodHandleNatives.resolve(asList_MN, null);
  1.1622 -        asList_MN = lookup.resolveOrFail(asList_MN, REF_invokeStatic, null, NoSuchMethodException.class);
  1.1623 -        System.out.println("about to call "+asList_MN);
  1.1624 -        Object[] abc = { "a", "bc" };
  1.1625 -        List<?> lst = (List<?>) MethodHandle.linkToStatic(abc, asList_MN);
  1.1626 -        System.out.println("lst="+lst);
  1.1627 -        MemberName toString_MN = new MemberName(Object.class.getMethod("toString"));
  1.1628 -        String s1 = (String) MethodHandle.linkToVirtual(lst, toString_MN);
  1.1629 -        toString_MN = new MemberName(Object.class.getMethod("toString"), true);
  1.1630 -        String s2 = (String) MethodHandle.linkToSpecial(lst, toString_MN);
  1.1631 -        System.out.println("[s1,s2,lst]="+Arrays.asList(s1, s2, lst.toString()));
  1.1632 -        MemberName toArray_MN = new MemberName(List.class.getMethod("toArray"));
  1.1633 -        Object[] arr = (Object[]) MethodHandle.linkToInterface(lst, toArray_MN);
  1.1634 -        System.out.println("toArray="+Arrays.toString(arr));
  1.1635 -    }
  1.1636 -    static { try { testMethodHandleLinkers(); } catch (Throwable ex) { throw new RuntimeException(ex); } }
  1.1637 -    // Requires these definitions in MethodHandle:
  1.1638 -    static final native Object linkToStatic(Object x1, MemberName mn) throws Throwable;
  1.1639 -    static final native Object linkToVirtual(Object x1, MemberName mn) throws Throwable;
  1.1640 -    static final native Object linkToSpecial(Object x1, MemberName mn) throws Throwable;
  1.1641 -    static final native Object linkToInterface(Object x1, MemberName mn) throws Throwable;
  1.1642 - */
  1.1643 -
  1.1644 -    static { NamedFunction.initializeInvokers(); }
  1.1645 -
  1.1646 -    // The following hack is necessary in order to suppress TRACE_INTERPRETER
  1.1647 -    // during execution of the static initializes of this class.
  1.1648 -    // Turning on TRACE_INTERPRETER too early will cause
  1.1649 -    // stack overflows and other misbehavior during attempts to trace events
  1.1650 -    // that occur during LambdaForm.<clinit>.
  1.1651 -    // Therefore, do not move this line higher in this file, and do not remove.
  1.1652 -    private static final boolean TRACE_INTERPRETER = MethodHandleStatics.TRACE_INTERPRETER;
  1.1653 -}