Looks like we need the java.lang.invoke classes for lambdas to work jdk8
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Sat, 09 Aug 2014 11:12:05 +0200
branchjdk8
changeset 16475fb6acaa51b8
parent 1645 0101d10bd2e0
parent 1646 c880a8a8803b
child 1648 905b2a470def
Looks like we need the java.lang.invoke classes for lambdas to work
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/AbstractValidatingLambdaMetafactory.java	Sat Aug 09 11:12:05 2014 +0200
     1.3 @@ -0,0 +1,375 @@
     1.4 +/*
     1.5 + * Copyright (c) 2012, 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 +package java.lang.invoke;
    1.29 +
    1.30 +import sun.invoke.util.Wrapper;
    1.31 +
    1.32 +import static sun.invoke.util.Wrapper.forPrimitiveType;
    1.33 +import static sun.invoke.util.Wrapper.forWrapperType;
    1.34 +import static sun.invoke.util.Wrapper.isWrapperType;
    1.35 +
    1.36 +/**
    1.37 + * Abstract implementation of a lambda metafactory which provides parameter
    1.38 + * unrolling and input validation.
    1.39 + *
    1.40 + * @see LambdaMetafactory
    1.41 + */
    1.42 +/* package */ abstract class AbstractValidatingLambdaMetafactory {
    1.43 +
    1.44 +    /*
    1.45 +     * For context, the comments for the following fields are marked in quotes
    1.46 +     * with their values, given this program:
    1.47 +     * interface II<T> {  Object foo(T x); }
    1.48 +     * interface JJ<R extends Number> extends II<R> { }
    1.49 +     * class CC {  String impl(int i) { return "impl:"+i; }}
    1.50 +     * class X {
    1.51 +     *     public static void main(String[] args) {
    1.52 +     *         JJ<Integer> iii = (new CC())::impl;
    1.53 +     *         System.out.printf(">>> %s\n", iii.foo(44));
    1.54 +     * }}
    1.55 +     */
    1.56 +    final Class<?> targetClass;               // The class calling the meta-factory via invokedynamic "class X"
    1.57 +    final MethodType invokedType;             // The type of the invoked method "(CC)II"
    1.58 +    final Class<?> samBase;                   // The type of the returned instance "interface JJ"
    1.59 +    final String samMethodName;               // Name of the SAM method "foo"
    1.60 +    final MethodType samMethodType;           // Type of the SAM method "(Object)Object"
    1.61 +    final MethodHandle implMethod;            // Raw method handle for the implementation method
    1.62 +    final MethodHandleInfo implInfo;          // Info about the implementation method handle "MethodHandleInfo[5 CC.impl(int)String]"
    1.63 +    final int implKind;                       // Invocation kind for implementation "5"=invokevirtual
    1.64 +    final boolean implIsInstanceMethod;       // Is the implementation an instance method "true"
    1.65 +    final Class<?> implDefiningClass;         // Type defining the implementation "class CC"
    1.66 +    final MethodType implMethodType;          // Type of the implementation method "(int)String"
    1.67 +    final MethodType instantiatedMethodType;  // Instantiated erased functional interface method type "(Integer)Object"
    1.68 +    final boolean isSerializable;             // Should the returned instance be serializable
    1.69 +    final Class<?>[] markerInterfaces;        // Additional marker interfaces to be implemented
    1.70 +    final MethodType[] additionalBridges;     // Signatures of additional methods to bridge
    1.71 +
    1.72 +
    1.73 +    /**
    1.74 +     * Meta-factory constructor.
    1.75 +     *
    1.76 +     * @param caller Stacked automatically by VM; represents a lookup context
    1.77 +     *               with the accessibility privileges of the caller.
    1.78 +     * @param invokedType Stacked automatically by VM; the signature of the
    1.79 +     *                    invoked method, which includes the expected static
    1.80 +     *                    type of the returned lambda object, and the static
    1.81 +     *                    types of the captured arguments for the lambda.  In
    1.82 +     *                    the event that the implementation method is an
    1.83 +     *                    instance method, the first argument in the invocation
    1.84 +     *                    signature will correspond to the receiver.
    1.85 +     * @param samMethodName Name of the method in the functional interface to
    1.86 +     *                      which the lambda or method reference is being
    1.87 +     *                      converted, represented as a String.
    1.88 +     * @param samMethodType Type of the method in the functional interface to
    1.89 +     *                      which the lambda or method reference is being
    1.90 +     *                      converted, represented as a MethodType.
    1.91 +     * @param implMethod The implementation method which should be called
    1.92 +     *                   (with suitable adaptation of argument types, return
    1.93 +     *                   types, and adjustment for captured arguments) when
    1.94 +     *                   methods of the resulting functional interface instance
    1.95 +     *                   are invoked.
    1.96 +     * @param instantiatedMethodType The signature of the primary functional
    1.97 +     *                               interface method after type variables are
    1.98 +     *                               substituted with their instantiation from
    1.99 +     *                               the capture site
   1.100 +     * @param isSerializable Should the lambda be made serializable?  If set,
   1.101 +     *                       either the target type or one of the additional SAM
   1.102 +     *                       types must extend {@code Serializable}.
   1.103 +     * @param markerInterfaces Additional interfaces which the lambda object
   1.104 +     *                       should implement.
   1.105 +     * @param additionalBridges Method types for additional signatures to be
   1.106 +     *                          bridged to the implementation method
   1.107 +     * @throws LambdaConversionException If any of the meta-factory protocol
   1.108 +     * invariants are violated
   1.109 +     */
   1.110 +    AbstractValidatingLambdaMetafactory(MethodHandles.Lookup caller,
   1.111 +                                       MethodType invokedType,
   1.112 +                                       String samMethodName,
   1.113 +                                       MethodType samMethodType,
   1.114 +                                       MethodHandle implMethod,
   1.115 +                                       MethodType instantiatedMethodType,
   1.116 +                                       boolean isSerializable,
   1.117 +                                       Class<?>[] markerInterfaces,
   1.118 +                                       MethodType[] additionalBridges)
   1.119 +            throws LambdaConversionException {
   1.120 +        if ((caller.lookupModes() & MethodHandles.Lookup.PRIVATE) == 0) {
   1.121 +            throw new LambdaConversionException(String.format(
   1.122 +                    "Invalid caller: %s",
   1.123 +                    caller.lookupClass().getName()));
   1.124 +        }
   1.125 +        this.targetClass = caller.lookupClass();
   1.126 +        this.invokedType = invokedType;
   1.127 +
   1.128 +        this.samBase = invokedType.returnType();
   1.129 +
   1.130 +        this.samMethodName = samMethodName;
   1.131 +        this.samMethodType  = samMethodType;
   1.132 +
   1.133 +        this.implMethod = implMethod;
   1.134 +        this.implInfo = caller.revealDirect(implMethod);
   1.135 +        this.implKind = implInfo.getReferenceKind();
   1.136 +        this.implIsInstanceMethod =
   1.137 +                implKind == MethodHandleInfo.REF_invokeVirtual ||
   1.138 +                implKind == MethodHandleInfo.REF_invokeSpecial ||
   1.139 +                implKind == MethodHandleInfo.REF_invokeInterface;
   1.140 +        this.implDefiningClass = implInfo.getDeclaringClass();
   1.141 +        this.implMethodType = implInfo.getMethodType();
   1.142 +        this.instantiatedMethodType = instantiatedMethodType;
   1.143 +        this.isSerializable = isSerializable;
   1.144 +        this.markerInterfaces = markerInterfaces;
   1.145 +        this.additionalBridges = additionalBridges;
   1.146 +
   1.147 +        if (!samBase.isInterface()) {
   1.148 +            throw new LambdaConversionException(String.format(
   1.149 +                    "Functional interface %s is not an interface",
   1.150 +                    samBase.getName()));
   1.151 +        }
   1.152 +
   1.153 +        for (Class<?> c : markerInterfaces) {
   1.154 +            if (!c.isInterface()) {
   1.155 +                throw new LambdaConversionException(String.format(
   1.156 +                        "Marker interface %s is not an interface",
   1.157 +                        c.getName()));
   1.158 +            }
   1.159 +        }
   1.160 +    }
   1.161 +
   1.162 +    /**
   1.163 +     * Build the CallSite.
   1.164 +     *
   1.165 +     * @return a CallSite, which, when invoked, will return an instance of the
   1.166 +     * functional interface
   1.167 +     * @throws ReflectiveOperationException
   1.168 +     */
   1.169 +    abstract CallSite buildCallSite()
   1.170 +            throws LambdaConversionException;
   1.171 +
   1.172 +    /**
   1.173 +     * Check the meta-factory arguments for errors
   1.174 +     * @throws LambdaConversionException if there are improper conversions
   1.175 +     */
   1.176 +    void validateMetafactoryArgs() throws LambdaConversionException {
   1.177 +        switch (implKind) {
   1.178 +            case MethodHandleInfo.REF_invokeInterface:
   1.179 +            case MethodHandleInfo.REF_invokeVirtual:
   1.180 +            case MethodHandleInfo.REF_invokeStatic:
   1.181 +            case MethodHandleInfo.REF_newInvokeSpecial:
   1.182 +            case MethodHandleInfo.REF_invokeSpecial:
   1.183 +                break;
   1.184 +            default:
   1.185 +                throw new LambdaConversionException(String.format("Unsupported MethodHandle kind: %s", implInfo));
   1.186 +        }
   1.187 +
   1.188 +        // Check arity: optional-receiver + captured + SAM == impl
   1.189 +        final int implArity = implMethodType.parameterCount();
   1.190 +        final int receiverArity = implIsInstanceMethod ? 1 : 0;
   1.191 +        final int capturedArity = invokedType.parameterCount();
   1.192 +        final int samArity = samMethodType.parameterCount();
   1.193 +        final int instantiatedArity = instantiatedMethodType.parameterCount();
   1.194 +        if (implArity + receiverArity != capturedArity + samArity) {
   1.195 +            throw new LambdaConversionException(
   1.196 +                    String.format("Incorrect number of parameters for %s method %s; %d captured parameters, %d functional interface method parameters, %d implementation parameters",
   1.197 +                                  implIsInstanceMethod ? "instance" : "static", implInfo,
   1.198 +                                  capturedArity, samArity, implArity));
   1.199 +        }
   1.200 +        if (instantiatedArity != samArity) {
   1.201 +            throw new LambdaConversionException(
   1.202 +                    String.format("Incorrect number of parameters for %s method %s; %d instantiated parameters, %d functional interface method parameters",
   1.203 +                                  implIsInstanceMethod ? "instance" : "static", implInfo,
   1.204 +                                  instantiatedArity, samArity));
   1.205 +        }
   1.206 +        for (MethodType bridgeMT : additionalBridges) {
   1.207 +            if (bridgeMT.parameterCount() != samArity) {
   1.208 +                throw new LambdaConversionException(
   1.209 +                        String.format("Incorrect number of parameters for bridge signature %s; incompatible with %s",
   1.210 +                                      bridgeMT, samMethodType));
   1.211 +            }
   1.212 +        }
   1.213 +
   1.214 +        // If instance: first captured arg (receiver) must be subtype of class where impl method is defined
   1.215 +        final int capturedStart;
   1.216 +        final int samStart;
   1.217 +        if (implIsInstanceMethod) {
   1.218 +            final Class<?> receiverClass;
   1.219 +
   1.220 +            // implementation is an instance method, adjust for receiver in captured variables / SAM arguments
   1.221 +            if (capturedArity == 0) {
   1.222 +                // receiver is function parameter
   1.223 +                capturedStart = 0;
   1.224 +                samStart = 1;
   1.225 +                receiverClass = instantiatedMethodType.parameterType(0);
   1.226 +            } else {
   1.227 +                // receiver is a captured variable
   1.228 +                capturedStart = 1;
   1.229 +                samStart = 0;
   1.230 +                receiverClass = invokedType.parameterType(0);
   1.231 +            }
   1.232 +
   1.233 +            // check receiver type
   1.234 +            if (!implDefiningClass.isAssignableFrom(receiverClass)) {
   1.235 +                throw new LambdaConversionException(
   1.236 +                        String.format("Invalid receiver type %s; not a subtype of implementation type %s",
   1.237 +                                      receiverClass, implDefiningClass));
   1.238 +            }
   1.239 +
   1.240 +           Class<?> implReceiverClass = implMethod.type().parameterType(0);
   1.241 +           if (implReceiverClass != implDefiningClass && !implReceiverClass.isAssignableFrom(receiverClass)) {
   1.242 +               throw new LambdaConversionException(
   1.243 +                       String.format("Invalid receiver type %s; not a subtype of implementation receiver type %s",
   1.244 +                                     receiverClass, implReceiverClass));
   1.245 +            }
   1.246 +        } else {
   1.247 +            // no receiver
   1.248 +            capturedStart = 0;
   1.249 +            samStart = 0;
   1.250 +        }
   1.251 +
   1.252 +        // Check for exact match on non-receiver captured arguments
   1.253 +        final int implFromCaptured = capturedArity - capturedStart;
   1.254 +        for (int i=0; i<implFromCaptured; i++) {
   1.255 +            Class<?> implParamType = implMethodType.parameterType(i);
   1.256 +            Class<?> capturedParamType = invokedType.parameterType(i + capturedStart);
   1.257 +            if (!capturedParamType.equals(implParamType)) {
   1.258 +                throw new LambdaConversionException(
   1.259 +                        String.format("Type mismatch in captured lambda parameter %d: expecting %s, found %s",
   1.260 +                                      i, capturedParamType, implParamType));
   1.261 +            }
   1.262 +        }
   1.263 +        // Check for adaptation match on SAM arguments
   1.264 +        final int samOffset = samStart - implFromCaptured;
   1.265 +        for (int i=implFromCaptured; i<implArity; i++) {
   1.266 +            Class<?> implParamType = implMethodType.parameterType(i);
   1.267 +            Class<?> instantiatedParamType = instantiatedMethodType.parameterType(i + samOffset);
   1.268 +            if (!isAdaptableTo(instantiatedParamType, implParamType, true)) {
   1.269 +                throw new LambdaConversionException(
   1.270 +                        String.format("Type mismatch for lambda argument %d: %s is not convertible to %s",
   1.271 +                                      i, instantiatedParamType, implParamType));
   1.272 +            }
   1.273 +        }
   1.274 +
   1.275 +        // Adaptation match: return type
   1.276 +        Class<?> expectedType = instantiatedMethodType.returnType();
   1.277 +        Class<?> actualReturnType =
   1.278 +                (implKind == MethodHandleInfo.REF_newInvokeSpecial)
   1.279 +                  ? implDefiningClass
   1.280 +                  : implMethodType.returnType();
   1.281 +        Class<?> samReturnType = samMethodType.returnType();
   1.282 +        if (!isAdaptableToAsReturn(actualReturnType, expectedType)) {
   1.283 +            throw new LambdaConversionException(
   1.284 +                    String.format("Type mismatch for lambda return: %s is not convertible to %s",
   1.285 +                                  actualReturnType, expectedType));
   1.286 +        }
   1.287 +        if (!isAdaptableToAsReturnStrict(expectedType, samReturnType)) {
   1.288 +            throw new LambdaConversionException(
   1.289 +                    String.format("Type mismatch for lambda expected return: %s is not convertible to %s",
   1.290 +                                  expectedType, samReturnType));
   1.291 +        }
   1.292 +        for (MethodType bridgeMT : additionalBridges) {
   1.293 +            if (!isAdaptableToAsReturnStrict(expectedType, bridgeMT.returnType())) {
   1.294 +                throw new LambdaConversionException(
   1.295 +                        String.format("Type mismatch for lambda expected return: %s is not convertible to %s",
   1.296 +                                      expectedType, bridgeMT.returnType()));
   1.297 +            }
   1.298 +        }
   1.299 +     }
   1.300 +
   1.301 +    /**
   1.302 +     * Check type adaptability for parameter types.
   1.303 +     * @param fromType Type to convert from
   1.304 +     * @param toType Type to convert to
   1.305 +     * @param strict If true, do strict checks, else allow that fromType may be parameterized
   1.306 +     * @return True if 'fromType' can be passed to an argument of 'toType'
   1.307 +     */
   1.308 +    private boolean isAdaptableTo(Class<?> fromType, Class<?> toType, boolean strict) {
   1.309 +        if (fromType.equals(toType)) {
   1.310 +            return true;
   1.311 +        }
   1.312 +        if (fromType.isPrimitive()) {
   1.313 +            Wrapper wfrom = forPrimitiveType(fromType);
   1.314 +            if (toType.isPrimitive()) {
   1.315 +                // both are primitive: widening
   1.316 +                Wrapper wto = forPrimitiveType(toType);
   1.317 +                return wto.isConvertibleFrom(wfrom);
   1.318 +            } else {
   1.319 +                // from primitive to reference: boxing
   1.320 +                return toType.isAssignableFrom(wfrom.wrapperType());
   1.321 +            }
   1.322 +        } else {
   1.323 +            if (toType.isPrimitive()) {
   1.324 +                // from reference to primitive: unboxing
   1.325 +                Wrapper wfrom;
   1.326 +                if (isWrapperType(fromType) && (wfrom = forWrapperType(fromType)).primitiveType().isPrimitive()) {
   1.327 +                    // fromType is a primitive wrapper; unbox+widen
   1.328 +                    Wrapper wto = forPrimitiveType(toType);
   1.329 +                    return wto.isConvertibleFrom(wfrom);
   1.330 +                } else {
   1.331 +                    // must be convertible to primitive
   1.332 +                    return !strict;
   1.333 +                }
   1.334 +            } else {
   1.335 +                // both are reference types: fromType should be a superclass of toType.
   1.336 +                return !strict || toType.isAssignableFrom(fromType);
   1.337 +            }
   1.338 +        }
   1.339 +    }
   1.340 +
   1.341 +    /**
   1.342 +     * Check type adaptability for return types --
   1.343 +     * special handling of void type) and parameterized fromType
   1.344 +     * @return True if 'fromType' can be converted to 'toType'
   1.345 +     */
   1.346 +    private boolean isAdaptableToAsReturn(Class<?> fromType, Class<?> toType) {
   1.347 +        return toType.equals(void.class)
   1.348 +               || !fromType.equals(void.class) && isAdaptableTo(fromType, toType, false);
   1.349 +    }
   1.350 +    private boolean isAdaptableToAsReturnStrict(Class<?> fromType, Class<?> toType) {
   1.351 +        if (fromType.equals(void.class)) return toType.equals(void.class);
   1.352 +        return isAdaptableTo(fromType, toType, true);
   1.353 +    }
   1.354 +
   1.355 +
   1.356 +    /*********** Logging support -- for debugging only, uncomment as needed
   1.357 +    static final Executor logPool = Executors.newSingleThreadExecutor();
   1.358 +    protected static void log(final String s) {
   1.359 +        MethodHandleProxyLambdaMetafactory.logPool.execute(new Runnable() {
   1.360 +            @Override
   1.361 +            public void run() {
   1.362 +                System.out.println(s);
   1.363 +            }
   1.364 +        });
   1.365 +    }
   1.366 +
   1.367 +    protected static void log(final String s, final Throwable e) {
   1.368 +        MethodHandleProxyLambdaMetafactory.logPool.execute(new Runnable() {
   1.369 +            @Override
   1.370 +            public void run() {
   1.371 +                System.out.println(s);
   1.372 +                e.printStackTrace(System.out);
   1.373 +            }
   1.374 +        });
   1.375 +    }
   1.376 +    ***********************/
   1.377 +
   1.378 +}
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/BoundMethodHandle.java	Sat Aug 09 11:12:05 2014 +0200
     2.3 @@ -0,0 +1,864 @@
     2.4 +/*
     2.5 + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
     2.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     2.7 + *
     2.8 + * This code is free software; you can redistribute it and/or modify it
     2.9 + * under the terms of the GNU General Public License version 2 only, as
    2.10 + * published by the Free Software Foundation.  Oracle designates this
    2.11 + * particular file as subject to the "Classpath" exception as provided
    2.12 + * by Oracle in the LICENSE file that accompanied this code.
    2.13 + *
    2.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    2.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    2.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    2.17 + * version 2 for more details (a copy is included in the LICENSE file that
    2.18 + * accompanied this code).
    2.19 + *
    2.20 + * You should have received a copy of the GNU General Public License version
    2.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    2.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    2.23 + *
    2.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    2.25 + * or visit www.oracle.com if you need additional information or have any
    2.26 + * questions.
    2.27 + */
    2.28 +
    2.29 +package java.lang.invoke;
    2.30 +
    2.31 +import static jdk.internal.org.objectweb.asm.Opcodes.*;
    2.32 +import static java.lang.invoke.LambdaForm.basicTypes;
    2.33 +import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic;
    2.34 +import static java.lang.invoke.MethodHandleStatics.*;
    2.35 +
    2.36 +import java.lang.invoke.LambdaForm.Name;
    2.37 +import java.lang.invoke.LambdaForm.NamedFunction;
    2.38 +import java.lang.invoke.MethodHandles.Lookup;
    2.39 +import java.lang.reflect.Field;
    2.40 +import java.util.Arrays;
    2.41 +import java.util.HashMap;
    2.42 +
    2.43 +import sun.invoke.util.ValueConversions;
    2.44 +import sun.invoke.util.Wrapper;
    2.45 +
    2.46 +import jdk.internal.org.objectweb.asm.ClassWriter;
    2.47 +import jdk.internal.org.objectweb.asm.MethodVisitor;
    2.48 +import jdk.internal.org.objectweb.asm.Type;
    2.49 +
    2.50 +/**
    2.51 + * The flavor of method handle which emulates an invoke instruction
    2.52 + * on a predetermined argument.  The JVM dispatches to the correct method
    2.53 + * when the handle is created, not when it is invoked.
    2.54 + *
    2.55 + * All bound arguments are encapsulated in dedicated species.
    2.56 + */
    2.57 +/* non-public */ abstract class BoundMethodHandle extends MethodHandle {
    2.58 +
    2.59 +    /* non-public */ BoundMethodHandle(MethodType type, LambdaForm form) {
    2.60 +        super(type, form);
    2.61 +    }
    2.62 +
    2.63 +    //
    2.64 +    // BMH API and internals
    2.65 +    //
    2.66 +
    2.67 +    static MethodHandle bindSingle(MethodType type, LambdaForm form, char xtype, Object x) {
    2.68 +        // for some type signatures, there exist pre-defined concrete BMH classes
    2.69 +        try {
    2.70 +            switch (xtype) {
    2.71 +            case 'L':
    2.72 +                if (true)  return bindSingle(type, form, x);  // Use known fast path.
    2.73 +                return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('L').constructor[0].invokeBasic(type, form, x);
    2.74 +            case 'I':
    2.75 +                return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('I').constructor[0].invokeBasic(type, form, ValueConversions.widenSubword(x));
    2.76 +            case 'J':
    2.77 +                return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('J').constructor[0].invokeBasic(type, form, (long) x);
    2.78 +            case 'F':
    2.79 +                return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('F').constructor[0].invokeBasic(type, form, (float) x);
    2.80 +            case 'D':
    2.81 +                return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('D').constructor[0].invokeBasic(type, form, (double) x);
    2.82 +            default : throw new InternalError("unexpected xtype: " + xtype);
    2.83 +            }
    2.84 +        } catch (Throwable t) {
    2.85 +            throw newInternalError(t);
    2.86 +        }
    2.87 +    }
    2.88 +
    2.89 +    static MethodHandle bindSingle(MethodType type, LambdaForm form, Object x) {
    2.90 +            return new Species_L(type, form, x);
    2.91 +    }
    2.92 +
    2.93 +    MethodHandle cloneExtend(MethodType type, LambdaForm form, char xtype, Object x) {
    2.94 +        try {
    2.95 +            switch (xtype) {
    2.96 +            case 'L': return cloneExtendL(type, form, x);
    2.97 +            case 'I': return cloneExtendI(type, form, ValueConversions.widenSubword(x));
    2.98 +            case 'J': return cloneExtendJ(type, form, (long) x);
    2.99 +            case 'F': return cloneExtendF(type, form, (float) x);
   2.100 +            case 'D': return cloneExtendD(type, form, (double) x);
   2.101 +            }
   2.102 +        } catch (Throwable t) {
   2.103 +            throw newInternalError(t);
   2.104 +        }
   2.105 +        throw new InternalError("unexpected type: " + xtype);
   2.106 +    }
   2.107 +
   2.108 +    @Override
   2.109 +    MethodHandle bindArgument(int pos, char basicType, Object value) {
   2.110 +        MethodType type = type().dropParameterTypes(pos, pos+1);
   2.111 +        LambdaForm form = internalForm().bind(1+pos, speciesData());
   2.112 +        return cloneExtend(type, form, basicType, value);
   2.113 +    }
   2.114 +
   2.115 +    @Override
   2.116 +    MethodHandle dropArguments(MethodType srcType, int pos, int drops) {
   2.117 +        LambdaForm form = internalForm().addArguments(pos, srcType.parameterList().subList(pos, pos+drops));
   2.118 +        try {
   2.119 +             return clone(srcType, form);
   2.120 +         } catch (Throwable t) {
   2.121 +             throw newInternalError(t);
   2.122 +         }
   2.123 +    }
   2.124 +
   2.125 +    @Override
   2.126 +    MethodHandle permuteArguments(MethodType newType, int[] reorder) {
   2.127 +        try {
   2.128 +             return clone(newType, form.permuteArguments(1, reorder, basicTypes(newType.parameterList())));
   2.129 +         } catch (Throwable t) {
   2.130 +             throw newInternalError(t);
   2.131 +         }
   2.132 +    }
   2.133 +
   2.134 +    static final String EXTENSION_TYPES = "LIJFD";
   2.135 +    static final byte INDEX_L = 0, INDEX_I = 1, INDEX_J = 2, INDEX_F = 3, INDEX_D = 4;
   2.136 +    static byte extensionIndex(char type) {
   2.137 +        int i = EXTENSION_TYPES.indexOf(type);
   2.138 +        if (i < 0)  throw new InternalError();
   2.139 +        return (byte) i;
   2.140 +    }
   2.141 +
   2.142 +    /**
   2.143 +     * Return the {@link SpeciesData} instance representing this BMH species. All subclasses must provide a
   2.144 +     * static field containing this value, and they must accordingly implement this method.
   2.145 +     */
   2.146 +    protected abstract SpeciesData speciesData();
   2.147 +
   2.148 +    @Override
   2.149 +    final Object internalProperties() {
   2.150 +        return "/BMH="+internalValues();
   2.151 +    }
   2.152 +
   2.153 +    @Override
   2.154 +    final Object internalValues() {
   2.155 +        Object[] boundValues = new Object[speciesData().fieldCount()];
   2.156 +        for (int i = 0; i < boundValues.length; ++i) {
   2.157 +            boundValues[i] = arg(i);
   2.158 +        }
   2.159 +        return Arrays.asList(boundValues);
   2.160 +    }
   2.161 +
   2.162 +    public final Object arg(int i) {
   2.163 +        try {
   2.164 +            switch (speciesData().fieldType(i)) {
   2.165 +            case 'L': return argL(i);
   2.166 +            case 'I': return argI(i);
   2.167 +            case 'F': return argF(i);
   2.168 +            case 'D': return argD(i);
   2.169 +            case 'J': return argJ(i);
   2.170 +            }
   2.171 +        } catch (Throwable ex) {
   2.172 +            throw newInternalError(ex);
   2.173 +        }
   2.174 +        throw new InternalError("unexpected type: " + speciesData().types+"."+i);
   2.175 +    }
   2.176 +    public final Object argL(int i) throws Throwable { return          speciesData().getters[i].invokeBasic(this); }
   2.177 +    public final int    argI(int i) throws Throwable { return (int)    speciesData().getters[i].invokeBasic(this); }
   2.178 +    public final float  argF(int i) throws Throwable { return (float)  speciesData().getters[i].invokeBasic(this); }
   2.179 +    public final double argD(int i) throws Throwable { return (double) speciesData().getters[i].invokeBasic(this); }
   2.180 +    public final long   argJ(int i) throws Throwable { return (long)   speciesData().getters[i].invokeBasic(this); }
   2.181 +
   2.182 +    //
   2.183 +    // cloning API
   2.184 +    //
   2.185 +
   2.186 +    public abstract BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable;
   2.187 +    public abstract BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable;
   2.188 +    public abstract BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int    narg) throws Throwable;
   2.189 +    public abstract BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long   narg) throws Throwable;
   2.190 +    public abstract BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float  narg) throws Throwable;
   2.191 +    public abstract BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable;
   2.192 +
   2.193 +    // The following is a grossly irregular hack:
   2.194 +    @Override MethodHandle reinvokerTarget() {
   2.195 +        try {
   2.196 +            return (MethodHandle) argL(0);
   2.197 +        } catch (Throwable ex) {
   2.198 +            throw newInternalError(ex);
   2.199 +        }
   2.200 +    }
   2.201 +
   2.202 +    //
   2.203 +    // concrete BMH classes required to close bootstrap loops
   2.204 +    //
   2.205 +
   2.206 +    private  // make it private to force users to access the enclosing class first
   2.207 +    static final class Species_L extends BoundMethodHandle {
   2.208 +        final Object argL0;
   2.209 +        public Species_L(MethodType mt, LambdaForm lf, Object argL0) {
   2.210 +            super(mt, lf);
   2.211 +            this.argL0 = argL0;
   2.212 +        }
   2.213 +        // The following is a grossly irregular hack:
   2.214 +        @Override MethodHandle reinvokerTarget() { return (MethodHandle) argL0; }
   2.215 +        @Override
   2.216 +        public SpeciesData speciesData() {
   2.217 +            return SPECIES_DATA;
   2.218 +        }
   2.219 +        public static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("L", Species_L.class);
   2.220 +        @Override
   2.221 +        public final BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable {
   2.222 +            return new Species_L(mt, lf, argL0);
   2.223 +        }
   2.224 +        @Override
   2.225 +        public final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable {
   2.226 +            return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argL0, narg);
   2.227 +        }
   2.228 +        @Override
   2.229 +        public final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable {
   2.230 +            return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argL0, narg);
   2.231 +        }
   2.232 +        @Override
   2.233 +        public final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable {
   2.234 +            return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argL0, narg);
   2.235 +        }
   2.236 +        @Override
   2.237 +        public final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable {
   2.238 +            return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argL0, narg);
   2.239 +        }
   2.240 +        @Override
   2.241 +        public final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable {
   2.242 +            return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argL0, narg);
   2.243 +        }
   2.244 +    }
   2.245 +
   2.246 +/*
   2.247 +    static final class Species_LL extends BoundMethodHandle {
   2.248 +        final Object argL0;
   2.249 +        final Object argL1;
   2.250 +        public Species_LL(MethodType mt, LambdaForm lf, Object argL0, Object argL1) {
   2.251 +            super(mt, lf);
   2.252 +            this.argL0 = argL0;
   2.253 +            this.argL1 = argL1;
   2.254 +        }
   2.255 +        @Override
   2.256 +        public SpeciesData speciesData() {
   2.257 +            return SPECIES_DATA;
   2.258 +        }
   2.259 +        public static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("LL", Species_LL.class);
   2.260 +        @Override
   2.261 +        public final BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable {
   2.262 +            return new Species_LL(mt, lf, argL0, argL1);
   2.263 +        }
   2.264 +        @Override
   2.265 +        public final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable {
   2.266 +            return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
   2.267 +        }
   2.268 +        @Override
   2.269 +        public final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable {
   2.270 +            return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
   2.271 +        }
   2.272 +        @Override
   2.273 +        public final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable {
   2.274 +            return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
   2.275 +        }
   2.276 +        @Override
   2.277 +        public final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable {
   2.278 +            return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
   2.279 +        }
   2.280 +        @Override
   2.281 +        public final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable {
   2.282 +            return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
   2.283 +        }
   2.284 +    }
   2.285 +
   2.286 +    static final class Species_JL extends BoundMethodHandle {
   2.287 +        final long argJ0;
   2.288 +        final Object argL1;
   2.289 +        public Species_JL(MethodType mt, LambdaForm lf, long argJ0, Object argL1) {
   2.290 +            super(mt, lf);
   2.291 +            this.argJ0 = argJ0;
   2.292 +            this.argL1 = argL1;
   2.293 +        }
   2.294 +        @Override
   2.295 +        public SpeciesData speciesData() {
   2.296 +            return SPECIES_DATA;
   2.297 +        }
   2.298 +        public static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("JL", Species_JL.class);
   2.299 +        @Override public final long   argJ0() { return argJ0; }
   2.300 +        @Override public final Object argL1() { return argL1; }
   2.301 +        @Override
   2.302 +        public final BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable {
   2.303 +            return new Species_JL(mt, lf, argJ0, argL1);
   2.304 +        }
   2.305 +        @Override
   2.306 +        public final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable {
   2.307 +            return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
   2.308 +        }
   2.309 +        @Override
   2.310 +        public final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable {
   2.311 +            return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
   2.312 +        }
   2.313 +        @Override
   2.314 +        public final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable {
   2.315 +            return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
   2.316 +        }
   2.317 +        @Override
   2.318 +        public final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable {
   2.319 +            return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
   2.320 +        }
   2.321 +        @Override
   2.322 +        public final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable {
   2.323 +            return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
   2.324 +        }
   2.325 +    }
   2.326 +*/
   2.327 +
   2.328 +    //
   2.329 +    // BMH species meta-data
   2.330 +    //
   2.331 +
   2.332 +    /**
   2.333 +     * Meta-data wrapper for concrete BMH classes.
   2.334 +     */
   2.335 +    static class SpeciesData {
   2.336 +        final String                             types;
   2.337 +        final Class<? extends BoundMethodHandle> clazz;
   2.338 +        // Bootstrapping requires circular relations MH -> BMH -> SpeciesData -> MH
   2.339 +        // Therefore, we need a non-final link in the chain.  Use array elements.
   2.340 +        final MethodHandle[]                     constructor;
   2.341 +        final MethodHandle[]                     getters;
   2.342 +        final SpeciesData[]                      extensions;
   2.343 +
   2.344 +        public int fieldCount() {
   2.345 +            return types.length();
   2.346 +        }
   2.347 +        public char fieldType(int i) {
   2.348 +            return types.charAt(i);
   2.349 +        }
   2.350 +
   2.351 +        public String toString() {
   2.352 +            return "SpeciesData["+(isPlaceholder() ? "<placeholder>" : clazz.getSimpleName())+":"+types+"]";
   2.353 +        }
   2.354 +
   2.355 +        /**
   2.356 +         * Return a {@link LambdaForm.Name} containing a {@link LambdaForm.NamedFunction} that
   2.357 +         * represents a MH bound to a generic invoker, which in turn forwards to the corresponding
   2.358 +         * getter.
   2.359 +         */
   2.360 +        Name getterName(Name mhName, int i) {
   2.361 +            MethodHandle mh = getters[i];
   2.362 +            assert(mh != null) : this+"."+i;
   2.363 +            return new Name(mh, mhName);
   2.364 +        }
   2.365 +
   2.366 +        NamedFunction getterFunction(int i) {
   2.367 +            return new NamedFunction(getters[i]);
   2.368 +        }
   2.369 +
   2.370 +        static final SpeciesData EMPTY = new SpeciesData("", BoundMethodHandle.class);
   2.371 +
   2.372 +        private SpeciesData(String types, Class<? extends BoundMethodHandle> clazz) {
   2.373 +            this.types = types;
   2.374 +            this.clazz = clazz;
   2.375 +            if (!INIT_DONE) {
   2.376 +                this.constructor = new MethodHandle[1];
   2.377 +                this.getters = new MethodHandle[types.length()];
   2.378 +            } else {
   2.379 +                this.constructor = Factory.makeCtors(clazz, types, null);
   2.380 +                this.getters = Factory.makeGetters(clazz, types, null);
   2.381 +            }
   2.382 +            this.extensions = new SpeciesData[EXTENSION_TYPES.length()];
   2.383 +        }
   2.384 +
   2.385 +        private void initForBootstrap() {
   2.386 +            assert(!INIT_DONE);
   2.387 +            if (constructor[0] == null) {
   2.388 +                Factory.makeCtors(clazz, types, this.constructor);
   2.389 +                Factory.makeGetters(clazz, types, this.getters);
   2.390 +            }
   2.391 +        }
   2.392 +
   2.393 +        private SpeciesData(String types) {
   2.394 +            // Placeholder only.
   2.395 +            this.types = types;
   2.396 +            this.clazz = null;
   2.397 +            this.constructor = null;
   2.398 +            this.getters = null;
   2.399 +            this.extensions = null;
   2.400 +        }
   2.401 +        private boolean isPlaceholder() { return clazz == null; }
   2.402 +
   2.403 +        private static final HashMap<String, SpeciesData> CACHE = new HashMap<>();
   2.404 +        static { CACHE.put("", EMPTY); }  // make bootstrap predictable
   2.405 +        private static final boolean INIT_DONE;  // set after <clinit> finishes...
   2.406 +
   2.407 +        SpeciesData extendWithType(char type) {
   2.408 +            int i = extensionIndex(type);
   2.409 +            SpeciesData d = extensions[i];
   2.410 +            if (d != null)  return d;
   2.411 +            extensions[i] = d = get(types+type);
   2.412 +            return d;
   2.413 +        }
   2.414 +
   2.415 +        SpeciesData extendWithIndex(byte index) {
   2.416 +            SpeciesData d = extensions[index];
   2.417 +            if (d != null)  return d;
   2.418 +            extensions[index] = d = get(types+EXTENSION_TYPES.charAt(index));
   2.419 +            return d;
   2.420 +        }
   2.421 +
   2.422 +        private static SpeciesData get(String types) {
   2.423 +            // Acquire cache lock for query.
   2.424 +            SpeciesData d = lookupCache(types);
   2.425 +            if (!d.isPlaceholder())
   2.426 +                return d;
   2.427 +            synchronized (d) {
   2.428 +                // Use synch. on the placeholder to prevent multiple instantiation of one species.
   2.429 +                // Creating this class forces a recursive call to getForClass.
   2.430 +                if (lookupCache(types).isPlaceholder())
   2.431 +                    Factory.generateConcreteBMHClass(types);
   2.432 +            }
   2.433 +            // Reacquire cache lock.
   2.434 +            d = lookupCache(types);
   2.435 +            // Class loading must have upgraded the cache.
   2.436 +            assert(d != null && !d.isPlaceholder());
   2.437 +            return d;
   2.438 +        }
   2.439 +        static SpeciesData getForClass(String types, Class<? extends BoundMethodHandle> clazz) {
   2.440 +            // clazz is a new class which is initializing its SPECIES_DATA field
   2.441 +            return updateCache(types, new SpeciesData(types, clazz));
   2.442 +        }
   2.443 +        private static synchronized SpeciesData lookupCache(String types) {
   2.444 +            SpeciesData d = CACHE.get(types);
   2.445 +            if (d != null)  return d;
   2.446 +            d = new SpeciesData(types);
   2.447 +            assert(d.isPlaceholder());
   2.448 +            CACHE.put(types, d);
   2.449 +            return d;
   2.450 +        }
   2.451 +        private static synchronized SpeciesData updateCache(String types, SpeciesData d) {
   2.452 +            SpeciesData d2;
   2.453 +            assert((d2 = CACHE.get(types)) == null || d2.isPlaceholder());
   2.454 +            assert(!d.isPlaceholder());
   2.455 +            CACHE.put(types, d);
   2.456 +            return d;
   2.457 +        }
   2.458 +
   2.459 +        static {
   2.460 +            // pre-fill the BMH speciesdata cache with BMH's inner classes
   2.461 +            final Class<BoundMethodHandle> rootCls = BoundMethodHandle.class;
   2.462 +            SpeciesData d0 = BoundMethodHandle.SPECIES_DATA;  // trigger class init
   2.463 +            assert(d0 == null || d0 == lookupCache("")) : d0;
   2.464 +            try {
   2.465 +                for (Class<?> c : rootCls.getDeclaredClasses()) {
   2.466 +                    if (rootCls.isAssignableFrom(c)) {
   2.467 +                        final Class<? extends BoundMethodHandle> cbmh = c.asSubclass(BoundMethodHandle.class);
   2.468 +                        SpeciesData d = Factory.speciesDataFromConcreteBMHClass(cbmh);
   2.469 +                        assert(d != null) : cbmh.getName();
   2.470 +                        assert(d.clazz == cbmh);
   2.471 +                        assert(d == lookupCache(d.types));
   2.472 +                    }
   2.473 +                }
   2.474 +            } catch (Throwable e) {
   2.475 +                throw newInternalError(e);
   2.476 +            }
   2.477 +
   2.478 +            for (SpeciesData d : CACHE.values()) {
   2.479 +                d.initForBootstrap();
   2.480 +            }
   2.481 +            // Note:  Do not simplify this, because INIT_DONE must not be
   2.482 +            // a compile-time constant during bootstrapping.
   2.483 +            INIT_DONE = Boolean.TRUE;
   2.484 +        }
   2.485 +    }
   2.486 +
   2.487 +    static SpeciesData getSpeciesData(String types) {
   2.488 +        return SpeciesData.get(types);
   2.489 +    }
   2.490 +
   2.491 +    /**
   2.492 +     * Generation of concrete BMH classes.
   2.493 +     *
   2.494 +     * A concrete BMH species is fit for binding a number of values adhering to a
   2.495 +     * given type pattern. Reference types are erased.
   2.496 +     *
   2.497 +     * BMH species are cached by type pattern.
   2.498 +     *
   2.499 +     * A BMH species has a number of fields with the concrete (possibly erased) types of
   2.500 +     * bound values. Setters are provided as an API in BMH. Getters are exposed as MHs,
   2.501 +     * which can be included as names in lambda forms.
   2.502 +     */
   2.503 +    static class Factory {
   2.504 +
   2.505 +        static final String JLO_SIG  = "Ljava/lang/Object;";
   2.506 +        static final String JLS_SIG  = "Ljava/lang/String;";
   2.507 +        static final String JLC_SIG  = "Ljava/lang/Class;";
   2.508 +        static final String MH       = "java/lang/invoke/MethodHandle";
   2.509 +        static final String MH_SIG   = "L"+MH+";";
   2.510 +        static final String BMH      = "java/lang/invoke/BoundMethodHandle";
   2.511 +        static final String BMH_SIG  = "L"+BMH+";";
   2.512 +        static final String SPECIES_DATA     = "java/lang/invoke/BoundMethodHandle$SpeciesData";
   2.513 +        static final String SPECIES_DATA_SIG = "L"+SPECIES_DATA+";";
   2.514 +
   2.515 +        static final String SPECIES_PREFIX_NAME = "Species_";
   2.516 +        static final String SPECIES_PREFIX_PATH = BMH + "$" + SPECIES_PREFIX_NAME;
   2.517 +
   2.518 +        static final String BMHSPECIES_DATA_EWI_SIG = "(B)" + SPECIES_DATA_SIG;
   2.519 +        static final String BMHSPECIES_DATA_GFC_SIG = "(" + JLS_SIG + JLC_SIG + ")" + SPECIES_DATA_SIG;
   2.520 +        static final String MYSPECIES_DATA_SIG = "()" + SPECIES_DATA_SIG;
   2.521 +        static final String VOID_SIG   = "()V";
   2.522 +
   2.523 +        static final String SIG_INCIPIT = "(Ljava/lang/invoke/MethodType;Ljava/lang/invoke/LambdaForm;";
   2.524 +
   2.525 +        static final Class<?>[] TYPES = new Class<?>[] { Object.class, int.class, long.class, float.class, double.class };
   2.526 +
   2.527 +        static final String[] E_THROWABLE = new String[] { "java/lang/Throwable" };
   2.528 +
   2.529 +        /**
   2.530 +         * Generate a concrete subclass of BMH for a given combination of bound types.
   2.531 +         *
   2.532 +         * A concrete BMH species adheres to the following schema:
   2.533 +         *
   2.534 +         * <pre>
   2.535 +         * class Species_[[types]] extends BoundMethodHandle {
   2.536 +         *     [[fields]]
   2.537 +         *     final SpeciesData speciesData() { return SpeciesData.get("[[types]]"); }
   2.538 +         * }
   2.539 +         * </pre>
   2.540 +         *
   2.541 +         * The {@code [[types]]} signature is precisely the string that is passed to this
   2.542 +         * method.
   2.543 +         *
   2.544 +         * The {@code [[fields]]} section consists of one field definition per character in
   2.545 +         * the type signature, adhering to the naming schema described in the definition of
   2.546 +         * {@link #makeFieldName}.
   2.547 +         *
   2.548 +         * For example, a concrete BMH species for two reference and one integral bound values
   2.549 +         * would have the following shape:
   2.550 +         *
   2.551 +         * <pre>
   2.552 +         * class BoundMethodHandle { ... private static
   2.553 +         * final class Species_LLI extends BoundMethodHandle {
   2.554 +         *     final Object argL0;
   2.555 +         *     final Object argL1;
   2.556 +         *     final int argI2;
   2.557 +         *     public Species_LLI(MethodType mt, LambdaForm lf, Object argL0, Object argL1, int argI2) {
   2.558 +         *         super(mt, lf);
   2.559 +         *         this.argL0 = argL0;
   2.560 +         *         this.argL1 = argL1;
   2.561 +         *         this.argI2 = argI2;
   2.562 +         *     }
   2.563 +         *     public final SpeciesData speciesData() { return SPECIES_DATA; }
   2.564 +         *     public static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("LLI", Species_LLI.class);
   2.565 +         *     public final BoundMethodHandle clone(MethodType mt, LambdaForm lf) {
   2.566 +         *         return SPECIES_DATA.constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2);
   2.567 +         *     }
   2.568 +         *     public final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) {
   2.569 +         *         return SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
   2.570 +         *     }
   2.571 +         *     public final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) {
   2.572 +         *         return SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
   2.573 +         *     }
   2.574 +         *     public final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) {
   2.575 +         *         return SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
   2.576 +         *     }
   2.577 +         *     public final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) {
   2.578 +         *         return SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
   2.579 +         *     }
   2.580 +         *     public final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) {
   2.581 +         *         return SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
   2.582 +         *     }
   2.583 +         * }
   2.584 +         * </pre>
   2.585 +         *
   2.586 +         * @param types the type signature, wherein reference types are erased to 'L'
   2.587 +         * @return the generated concrete BMH class
   2.588 +         */
   2.589 +        static Class<? extends BoundMethodHandle> generateConcreteBMHClass(String types) {
   2.590 +            final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
   2.591 +
   2.592 +            final String className  = SPECIES_PREFIX_PATH + types;
   2.593 +            final String sourceFile = SPECIES_PREFIX_NAME + types;
   2.594 +            cw.visit(V1_6, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, className, null, BMH, null);
   2.595 +            cw.visitSource(sourceFile, null);
   2.596 +
   2.597 +            // emit static types and SPECIES_DATA fields
   2.598 +            cw.visitField(ACC_PUBLIC + ACC_STATIC, "SPECIES_DATA", SPECIES_DATA_SIG, null, null).visitEnd();
   2.599 +
   2.600 +            // emit bound argument fields
   2.601 +            for (int i = 0; i < types.length(); ++i) {
   2.602 +                final char t = types.charAt(i);
   2.603 +                final String fieldName = makeFieldName(types, i);
   2.604 +                final String fieldDesc = t == 'L' ? JLO_SIG : String.valueOf(t);
   2.605 +                cw.visitField(ACC_FINAL, fieldName, fieldDesc, null, null).visitEnd();
   2.606 +            }
   2.607 +
   2.608 +            MethodVisitor mv;
   2.609 +
   2.610 +            // emit constructor
   2.611 +            mv = cw.visitMethod(ACC_PUBLIC, "<init>", makeSignature(types, true), null, null);
   2.612 +            mv.visitCode();
   2.613 +            mv.visitVarInsn(ALOAD, 0);
   2.614 +            mv.visitVarInsn(ALOAD, 1);
   2.615 +            mv.visitVarInsn(ALOAD, 2);
   2.616 +
   2.617 +            mv.visitMethodInsn(INVOKESPECIAL, BMH, "<init>", makeSignature("", true));
   2.618 +
   2.619 +            for (int i = 0, j = 0; i < types.length(); ++i, ++j) {
   2.620 +                // i counts the arguments, j counts corresponding argument slots
   2.621 +                char t = types.charAt(i);
   2.622 +                mv.visitVarInsn(ALOAD, 0);
   2.623 +                mv.visitVarInsn(typeLoadOp(t), j + 3); // parameters start at 3
   2.624 +                mv.visitFieldInsn(PUTFIELD, className, makeFieldName(types, i), typeSig(t));
   2.625 +                if (t == 'J' || t == 'D') {
   2.626 +                    ++j; // adjust argument register access
   2.627 +                }
   2.628 +            }
   2.629 +
   2.630 +            mv.visitInsn(RETURN);
   2.631 +            mv.visitMaxs(0, 0);
   2.632 +            mv.visitEnd();
   2.633 +
   2.634 +            // emit implementation of reinvokerTarget()
   2.635 +            mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "reinvokerTarget", "()" + MH_SIG, null, null);
   2.636 +            mv.visitCode();
   2.637 +            mv.visitVarInsn(ALOAD, 0);
   2.638 +            mv.visitFieldInsn(GETFIELD, className, "argL0", JLO_SIG);
   2.639 +            mv.visitTypeInsn(CHECKCAST, MH);
   2.640 +            mv.visitInsn(ARETURN);
   2.641 +            mv.visitMaxs(0, 0);
   2.642 +            mv.visitEnd();
   2.643 +
   2.644 +            // emit implementation of speciesData()
   2.645 +            mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "speciesData", MYSPECIES_DATA_SIG, null, null);
   2.646 +            mv.visitCode();
   2.647 +            mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG);
   2.648 +            mv.visitInsn(ARETURN);
   2.649 +            mv.visitMaxs(0, 0);
   2.650 +            mv.visitEnd();
   2.651 +
   2.652 +            // emit clone()
   2.653 +            mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "clone", makeSignature("", false), null, E_THROWABLE);
   2.654 +            mv.visitCode();
   2.655 +            // return speciesData().constructor[0].invokeBasic(mt, lf, argL0, ...)
   2.656 +            // obtain constructor
   2.657 +            mv.visitVarInsn(ALOAD, 0);
   2.658 +            mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG);
   2.659 +            mv.visitFieldInsn(GETFIELD, SPECIES_DATA, "constructor", "[" + MH_SIG);
   2.660 +            mv.visitInsn(ICONST_0);
   2.661 +            mv.visitInsn(AALOAD);
   2.662 +            // load mt, lf
   2.663 +            mv.visitVarInsn(ALOAD, 1);
   2.664 +            mv.visitVarInsn(ALOAD, 2);
   2.665 +            // put fields on the stack
   2.666 +            emitPushFields(types, className, mv);
   2.667 +            // finally, invoke the constructor and return
   2.668 +            mv.visitMethodInsn(INVOKEVIRTUAL, MH, "invokeBasic", makeSignature(types, false));
   2.669 +            mv.visitInsn(ARETURN);
   2.670 +            mv.visitMaxs(0, 0);
   2.671 +            mv.visitEnd();
   2.672 +
   2.673 +            // for each type, emit cloneExtendT()
   2.674 +            for (Class<?> c : TYPES) {
   2.675 +                char t = Wrapper.basicTypeChar(c);
   2.676 +                mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "cloneExtend" + t, makeSignature(String.valueOf(t), false), null, E_THROWABLE);
   2.677 +                mv.visitCode();
   2.678 +                // return SPECIES_DATA.extendWithIndex(extensionIndex(t)).constructor[0].invokeBasic(mt, lf, argL0, ..., narg)
   2.679 +                // obtain constructor
   2.680 +                mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG);
   2.681 +                int iconstInsn = ICONST_0 + extensionIndex(t);
   2.682 +                assert(iconstInsn <= ICONST_5);
   2.683 +                mv.visitInsn(iconstInsn);
   2.684 +                mv.visitMethodInsn(INVOKEVIRTUAL, SPECIES_DATA, "extendWithIndex", BMHSPECIES_DATA_EWI_SIG);
   2.685 +                mv.visitFieldInsn(GETFIELD, SPECIES_DATA, "constructor", "[" + MH_SIG);
   2.686 +                mv.visitInsn(ICONST_0);
   2.687 +                mv.visitInsn(AALOAD);
   2.688 +                // load mt, lf
   2.689 +                mv.visitVarInsn(ALOAD, 1);
   2.690 +                mv.visitVarInsn(ALOAD, 2);
   2.691 +                // put fields on the stack
   2.692 +                emitPushFields(types, className, mv);
   2.693 +                // put narg on stack
   2.694 +                mv.visitVarInsn(typeLoadOp(t), 3);
   2.695 +                // finally, invoke the constructor and return
   2.696 +                mv.visitMethodInsn(INVOKEVIRTUAL, MH, "invokeBasic", makeSignature(types + t, false));
   2.697 +                mv.visitInsn(ARETURN);
   2.698 +                mv.visitMaxs(0, 0);
   2.699 +                mv.visitEnd();
   2.700 +            }
   2.701 +
   2.702 +            // emit class initializer
   2.703 +            mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "<clinit>", VOID_SIG, null, null);
   2.704 +            mv.visitCode();
   2.705 +            mv.visitLdcInsn(types);
   2.706 +            mv.visitLdcInsn(Type.getObjectType(className));
   2.707 +            mv.visitMethodInsn(INVOKESTATIC, SPECIES_DATA, "getForClass", BMHSPECIES_DATA_GFC_SIG);
   2.708 +            mv.visitFieldInsn(PUTSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG);
   2.709 +            mv.visitInsn(RETURN);
   2.710 +            mv.visitMaxs(0, 0);
   2.711 +            mv.visitEnd();
   2.712 +
   2.713 +            cw.visitEnd();
   2.714 +
   2.715 +            // load class
   2.716 +            final byte[] classFile = cw.toByteArray();
   2.717 +            InvokerBytecodeGenerator.maybeDump(className, classFile);
   2.718 +            Class<? extends BoundMethodHandle> bmhClass =
   2.719 +                //UNSAFE.defineAnonymousClass(BoundMethodHandle.class, classFile, null).asSubclass(BoundMethodHandle.class);
   2.720 +                UNSAFE.defineClass(className, classFile, 0, classFile.length,
   2.721 +                                   BoundMethodHandle.class.getClassLoader(), null)
   2.722 +                    .asSubclass(BoundMethodHandle.class);
   2.723 +            UNSAFE.ensureClassInitialized(bmhClass);
   2.724 +
   2.725 +            return bmhClass;
   2.726 +        }
   2.727 +
   2.728 +        private static int typeLoadOp(char t) {
   2.729 +            switch (t) {
   2.730 +            case 'L': return ALOAD;
   2.731 +            case 'I': return ILOAD;
   2.732 +            case 'J': return LLOAD;
   2.733 +            case 'F': return FLOAD;
   2.734 +            case 'D': return DLOAD;
   2.735 +            default : throw new InternalError("unrecognized type " + t);
   2.736 +            }
   2.737 +        }
   2.738 +
   2.739 +        private static void emitPushFields(String types, String className, MethodVisitor mv) {
   2.740 +            for (int i = 0; i < types.length(); ++i) {
   2.741 +                char tc = types.charAt(i);
   2.742 +                mv.visitVarInsn(ALOAD, 0);
   2.743 +                mv.visitFieldInsn(GETFIELD, className, makeFieldName(types, i), typeSig(tc));
   2.744 +            }
   2.745 +        }
   2.746 +
   2.747 +        static String typeSig(char t) {
   2.748 +            return t == 'L' ? JLO_SIG : String.valueOf(t);
   2.749 +        }
   2.750 +
   2.751 +        //
   2.752 +        // Getter MH generation.
   2.753 +        //
   2.754 +
   2.755 +        private static MethodHandle makeGetter(Class<?> cbmhClass, String types, int index) {
   2.756 +            String fieldName = makeFieldName(types, index);
   2.757 +            Class<?> fieldType = Wrapper.forBasicType(types.charAt(index)).primitiveType();
   2.758 +            try {
   2.759 +                return LOOKUP.findGetter(cbmhClass, fieldName, fieldType);
   2.760 +            } catch (NoSuchFieldException | IllegalAccessException e) {
   2.761 +                throw newInternalError(e);
   2.762 +            }
   2.763 +        }
   2.764 +
   2.765 +        static MethodHandle[] makeGetters(Class<?> cbmhClass, String types, MethodHandle[] mhs) {
   2.766 +            if (mhs == null)  mhs = new MethodHandle[types.length()];
   2.767 +            for (int i = 0; i < mhs.length; ++i) {
   2.768 +                mhs[i] = makeGetter(cbmhClass, types, i);
   2.769 +                assert(mhs[i].internalMemberName().getDeclaringClass() == cbmhClass);
   2.770 +            }
   2.771 +            return mhs;
   2.772 +        }
   2.773 +
   2.774 +        static MethodHandle[] makeCtors(Class<? extends BoundMethodHandle> cbmh, String types, MethodHandle mhs[]) {
   2.775 +            if (mhs == null)  mhs = new MethodHandle[1];
   2.776 +            mhs[0] = makeCbmhCtor(cbmh, types);
   2.777 +            return mhs;
   2.778 +        }
   2.779 +
   2.780 +        //
   2.781 +        // Auxiliary methods.
   2.782 +        //
   2.783 +
   2.784 +        static SpeciesData speciesDataFromConcreteBMHClass(Class<? extends BoundMethodHandle> cbmh) {
   2.785 +            try {
   2.786 +                Field F_SPECIES_DATA = cbmh.getDeclaredField("SPECIES_DATA");
   2.787 +                return (SpeciesData) F_SPECIES_DATA.get(null);
   2.788 +            } catch (ReflectiveOperationException ex) {
   2.789 +                throw newInternalError(ex);
   2.790 +            }
   2.791 +        }
   2.792 +
   2.793 +        /**
   2.794 +         * Field names in concrete BMHs adhere to this pattern:
   2.795 +         * arg + type + index
   2.796 +         * where type is a single character (L, I, J, F, D).
   2.797 +         */
   2.798 +        private static String makeFieldName(String types, int index) {
   2.799 +            assert index >= 0 && index < types.length();
   2.800 +            return "arg" + types.charAt(index) + index;
   2.801 +        }
   2.802 +
   2.803 +        private static String makeSignature(String types, boolean ctor) {
   2.804 +            StringBuilder buf = new StringBuilder(SIG_INCIPIT);
   2.805 +            for (char c : types.toCharArray()) {
   2.806 +                buf.append(typeSig(c));
   2.807 +            }
   2.808 +            return buf.append(')').append(ctor ? "V" : BMH_SIG).toString();
   2.809 +        }
   2.810 +
   2.811 +        static MethodHandle makeCbmhCtor(Class<? extends BoundMethodHandle> cbmh, String types) {
   2.812 +            try {
   2.813 +                return linkConstructor(LOOKUP.findConstructor(cbmh, MethodType.fromMethodDescriptorString(makeSignature(types, true), null)));
   2.814 +            } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | TypeNotPresentException e) {
   2.815 +                throw newInternalError(e);
   2.816 +            }
   2.817 +        }
   2.818 +
   2.819 +        /**
   2.820 +         * Wrap a constructor call in a {@link LambdaForm}.
   2.821 +         *
   2.822 +         * If constructors ({@code <init>} methods) are called in LFs, problems might arise if the LFs
   2.823 +         * are turned into bytecode, because the call to the allocator is routed through an MH, and the
   2.824 +         * verifier cannot find a {@code NEW} instruction preceding the {@code INVOKESPECIAL} to
   2.825 +         * {@code <init>}. To avoid this, we add an indirection by invoking {@code <init>} through
   2.826 +         * {@link MethodHandle#linkToSpecial}.
   2.827 +         *
   2.828 +         * The last {@link LambdaForm.Name Name} in the argument's form is expected to be the {@code void}
   2.829 +         * result of the {@code <init>} invocation. This entry is replaced.
   2.830 +         */
   2.831 +        private static MethodHandle linkConstructor(MethodHandle cmh) {
   2.832 +            final LambdaForm lf = cmh.form;
   2.833 +            final int initNameIndex = lf.names.length - 1;
   2.834 +            final Name initName = lf.names[initNameIndex];
   2.835 +            final MemberName ctorMN = initName.function.member;
   2.836 +            final MethodType ctorMT = ctorMN.getInvocationType();
   2.837 +
   2.838 +            // obtain function member (call target)
   2.839 +            // linker method type replaces initial parameter (BMH species) with BMH to avoid naming a species (anonymous class!)
   2.840 +            final MethodType linkerMT = ctorMT.changeParameterType(0, BoundMethodHandle.class).appendParameterTypes(MemberName.class);
   2.841 +            MemberName linkerMN = new MemberName(MethodHandle.class, "linkToSpecial", linkerMT, REF_invokeStatic);
   2.842 +            try {
   2.843 +                linkerMN = MemberName.getFactory().resolveOrFail(REF_invokeStatic, linkerMN, null, NoSuchMethodException.class);
   2.844 +                assert(linkerMN.isStatic());
   2.845 +            } catch (ReflectiveOperationException ex) {
   2.846 +                throw newInternalError(ex);
   2.847 +            }
   2.848 +            // extend arguments array
   2.849 +            Object[] newArgs = Arrays.copyOf(initName.arguments, initName.arguments.length + 1);
   2.850 +            newArgs[newArgs.length - 1] = ctorMN;
   2.851 +            // replace function
   2.852 +            final NamedFunction nf = new NamedFunction(linkerMN);
   2.853 +            final Name linkedCtor = new Name(nf, newArgs);
   2.854 +            linkedCtor.initIndex(initNameIndex);
   2.855 +            lf.names[initNameIndex] = linkedCtor;
   2.856 +            return cmh;
   2.857 +        }
   2.858 +
   2.859 +    }
   2.860 +
   2.861 +    private static final Lookup LOOKUP = Lookup.IMPL_LOOKUP;
   2.862 +
   2.863 +    /**
   2.864 +     * All subclasses must provide such a value describing their type signature.
   2.865 +     */
   2.866 +    static final SpeciesData SPECIES_DATA = SpeciesData.EMPTY;
   2.867 +}
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/CallSite.java	Sat Aug 09 11:12:05 2014 +0200
     3.3 @@ -0,0 +1,347 @@
     3.4 +/*
     3.5 + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
     3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3.7 + *
     3.8 + * This code is free software; you can redistribute it and/or modify it
     3.9 + * under the terms of the GNU General Public License version 2 only, as
    3.10 + * published by the Free Software Foundation.  Oracle designates this
    3.11 + * particular file as subject to the "Classpath" exception as provided
    3.12 + * by Oracle in the LICENSE file that accompanied this code.
    3.13 + *
    3.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    3.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    3.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    3.17 + * version 2 for more details (a copy is included in the LICENSE file that
    3.18 + * accompanied this code).
    3.19 + *
    3.20 + * You should have received a copy of the GNU General Public License version
    3.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    3.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    3.23 + *
    3.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    3.25 + * or visit www.oracle.com if you need additional information or have any
    3.26 + * questions.
    3.27 + */
    3.28 +
    3.29 +package java.lang.invoke;
    3.30 +
    3.31 +import sun.invoke.empty.Empty;
    3.32 +import static java.lang.invoke.MethodHandleStatics.*;
    3.33 +import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
    3.34 +
    3.35 +/**
    3.36 + * A {@code CallSite} is a holder for a variable {@link MethodHandle},
    3.37 + * which is called its {@code target}.
    3.38 + * An {@code invokedynamic} instruction linked to a {@code CallSite} delegates
    3.39 + * all calls to the site's current target.
    3.40 + * A {@code CallSite} may be associated with several {@code invokedynamic}
    3.41 + * instructions, or it may be "free floating", associated with none.
    3.42 + * In any case, it may be invoked through an associated method handle
    3.43 + * called its {@linkplain #dynamicInvoker dynamic invoker}.
    3.44 + * <p>
    3.45 + * {@code CallSite} is an abstract class which does not allow
    3.46 + * direct subclassing by users.  It has three immediate,
    3.47 + * concrete subclasses that may be either instantiated or subclassed.
    3.48 + * <ul>
    3.49 + * <li>If a mutable target is not required, an {@code invokedynamic} instruction
    3.50 + * may be permanently bound by means of a {@linkplain ConstantCallSite constant call site}.
    3.51 + * <li>If a mutable target is required which has volatile variable semantics,
    3.52 + * because updates to the target must be immediately and reliably witnessed by other threads,
    3.53 + * a {@linkplain VolatileCallSite volatile call site} may be used.
    3.54 + * <li>Otherwise, if a mutable target is required,
    3.55 + * a {@linkplain MutableCallSite mutable call site} may be used.
    3.56 + * </ul>
    3.57 + * <p>
    3.58 + * A non-constant call site may be <em>relinked</em> by changing its target.
    3.59 + * The new target must have the same {@linkplain MethodHandle#type() type}
    3.60 + * as the previous target.
    3.61 + * Thus, though a call site can be relinked to a series of
    3.62 + * successive targets, it cannot change its type.
    3.63 + * <p>
    3.64 + * Here is a sample use of call sites and bootstrap methods which links every
    3.65 + * dynamic call site to print its arguments:
    3.66 +<blockquote><pre>{@code
    3.67 +static void test() throws Throwable {
    3.68 +    // THE FOLLOWING LINE IS PSEUDOCODE FOR A JVM INSTRUCTION
    3.69 +    InvokeDynamic[#bootstrapDynamic].baz("baz arg", 2, 3.14);
    3.70 +}
    3.71 +private static void printArgs(Object... args) {
    3.72 +  System.out.println(java.util.Arrays.deepToString(args));
    3.73 +}
    3.74 +private static final MethodHandle printArgs;
    3.75 +static {
    3.76 +  MethodHandles.Lookup lookup = MethodHandles.lookup();
    3.77 +  Class thisClass = lookup.lookupClass();  // (who am I?)
    3.78 +  printArgs = lookup.findStatic(thisClass,
    3.79 +      "printArgs", MethodType.methodType(void.class, Object[].class));
    3.80 +}
    3.81 +private static CallSite bootstrapDynamic(MethodHandles.Lookup caller, String name, MethodType type) {
    3.82 +  // ignore caller and name, but match the type:
    3.83 +  return new ConstantCallSite(printArgs.asType(type));
    3.84 +}
    3.85 +}</pre></blockquote>
    3.86 + * @author John Rose, JSR 292 EG
    3.87 + */
    3.88 +abstract
    3.89 +public class CallSite {
    3.90 +    static { MethodHandleImpl.initStatics(); }
    3.91 +
    3.92 +    // The actual payload of this call site:
    3.93 +    /*package-private*/
    3.94 +    MethodHandle target;    // Note: This field is known to the JVM.  Do not change.
    3.95 +
    3.96 +    /**
    3.97 +     * Make a blank call site object with the given method type.
    3.98 +     * An initial target method is supplied which will throw
    3.99 +     * an {@link IllegalStateException} if called.
   3.100 +     * <p>
   3.101 +     * Before this {@code CallSite} object is returned from a bootstrap method,
   3.102 +     * it is usually provided with a more useful target method,
   3.103 +     * via a call to {@link CallSite#setTarget(MethodHandle) setTarget}.
   3.104 +     * @throws NullPointerException if the proposed type is null
   3.105 +     */
   3.106 +    /*package-private*/
   3.107 +    CallSite(MethodType type) {
   3.108 +        target = type.invokers().uninitializedCallSite();
   3.109 +    }
   3.110 +
   3.111 +    /**
   3.112 +     * Make a call site object equipped with an initial target method handle.
   3.113 +     * @param target the method handle which will be the initial target of the call site
   3.114 +     * @throws NullPointerException if the proposed target is null
   3.115 +     */
   3.116 +    /*package-private*/
   3.117 +    CallSite(MethodHandle target) {
   3.118 +        target.type();  // null check
   3.119 +        this.target = target;
   3.120 +    }
   3.121 +
   3.122 +    /**
   3.123 +     * Make a call site object equipped with an initial target method handle.
   3.124 +     * @param targetType the desired type of the call site
   3.125 +     * @param createTargetHook a hook which will bind the call site to the target method handle
   3.126 +     * @throws WrongMethodTypeException if the hook cannot be invoked on the required arguments,
   3.127 +     *         or if the target returned by the hook is not of the given {@code targetType}
   3.128 +     * @throws NullPointerException if the hook returns a null value
   3.129 +     * @throws ClassCastException if the hook returns something other than a {@code MethodHandle}
   3.130 +     * @throws Throwable anything else thrown by the hook function
   3.131 +     */
   3.132 +    /*package-private*/
   3.133 +    CallSite(MethodType targetType, MethodHandle createTargetHook) throws Throwable {
   3.134 +        this(targetType);
   3.135 +        ConstantCallSite selfCCS = (ConstantCallSite) this;
   3.136 +        MethodHandle boundTarget = (MethodHandle) createTargetHook.invokeWithArguments(selfCCS);
   3.137 +        checkTargetChange(this.target, boundTarget);
   3.138 +        this.target = boundTarget;
   3.139 +    }
   3.140 +
   3.141 +    /**
   3.142 +     * Returns the type of this call site's target.
   3.143 +     * Although targets may change, any call site's type is permanent, and can never change to an unequal type.
   3.144 +     * The {@code setTarget} method enforces this invariant by refusing any new target that does
   3.145 +     * not have the previous target's type.
   3.146 +     * @return the type of the current target, which is also the type of any future target
   3.147 +     */
   3.148 +    public MethodType type() {
   3.149 +        // warning:  do not call getTarget here, because CCS.getTarget can throw IllegalStateException
   3.150 +        return target.type();
   3.151 +    }
   3.152 +
   3.153 +    /**
   3.154 +     * Returns the target method of the call site, according to the
   3.155 +     * behavior defined by this call site's specific class.
   3.156 +     * The immediate subclasses of {@code CallSite} document the
   3.157 +     * class-specific behaviors of this method.
   3.158 +     *
   3.159 +     * @return the current linkage state of the call site, its target method handle
   3.160 +     * @see ConstantCallSite
   3.161 +     * @see VolatileCallSite
   3.162 +     * @see #setTarget
   3.163 +     * @see ConstantCallSite#getTarget
   3.164 +     * @see MutableCallSite#getTarget
   3.165 +     * @see VolatileCallSite#getTarget
   3.166 +     */
   3.167 +    public abstract MethodHandle getTarget();
   3.168 +
   3.169 +    /**
   3.170 +     * Updates the target method of this call site, according to the
   3.171 +     * behavior defined by this call site's specific class.
   3.172 +     * The immediate subclasses of {@code CallSite} document the
   3.173 +     * class-specific behaviors of this method.
   3.174 +     * <p>
   3.175 +     * The type of the new target must be {@linkplain MethodType#equals equal to}
   3.176 +     * the type of the old target.
   3.177 +     *
   3.178 +     * @param newTarget the new target
   3.179 +     * @throws NullPointerException if the proposed new target is null
   3.180 +     * @throws WrongMethodTypeException if the proposed new target
   3.181 +     *         has a method type that differs from the previous target
   3.182 +     * @see CallSite#getTarget
   3.183 +     * @see ConstantCallSite#setTarget
   3.184 +     * @see MutableCallSite#setTarget
   3.185 +     * @see VolatileCallSite#setTarget
   3.186 +     */
   3.187 +    public abstract void setTarget(MethodHandle newTarget);
   3.188 +
   3.189 +    void checkTargetChange(MethodHandle oldTarget, MethodHandle newTarget) {
   3.190 +        MethodType oldType = oldTarget.type();
   3.191 +        MethodType newType = newTarget.type();  // null check!
   3.192 +        if (!newType.equals(oldType))
   3.193 +            throw wrongTargetType(newTarget, oldType);
   3.194 +    }
   3.195 +
   3.196 +    private static WrongMethodTypeException wrongTargetType(MethodHandle target, MethodType type) {
   3.197 +        return new WrongMethodTypeException(String.valueOf(target)+" should be of type "+type);
   3.198 +    }
   3.199 +
   3.200 +    /**
   3.201 +     * Produces a method handle equivalent to an invokedynamic instruction
   3.202 +     * which has been linked to this call site.
   3.203 +     * <p>
   3.204 +     * This method is equivalent to the following code:
   3.205 +     * <blockquote><pre>{@code
   3.206 +     * MethodHandle getTarget, invoker, result;
   3.207 +     * getTarget = MethodHandles.publicLookup().bind(this, "getTarget", MethodType.methodType(MethodHandle.class));
   3.208 +     * invoker = MethodHandles.exactInvoker(this.type());
   3.209 +     * result = MethodHandles.foldArguments(invoker, getTarget)
   3.210 +     * }</pre></blockquote>
   3.211 +     *
   3.212 +     * @return a method handle which always invokes this call site's current target
   3.213 +     */
   3.214 +    public abstract MethodHandle dynamicInvoker();
   3.215 +
   3.216 +    /*non-public*/ MethodHandle makeDynamicInvoker() {
   3.217 +        MethodHandle getTarget = GET_TARGET.bindReceiver(this);
   3.218 +        MethodHandle invoker = MethodHandles.exactInvoker(this.type());
   3.219 +        return MethodHandles.foldArguments(invoker, getTarget);
   3.220 +    }
   3.221 +
   3.222 +    private static final MethodHandle GET_TARGET;
   3.223 +    static {
   3.224 +        try {
   3.225 +            GET_TARGET = IMPL_LOOKUP.
   3.226 +                findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
   3.227 +        } catch (ReflectiveOperationException e) {
   3.228 +            throw newInternalError(e);
   3.229 +        }
   3.230 +    }
   3.231 +
   3.232 +    /** This guy is rolled into the default target if a MethodType is supplied to the constructor. */
   3.233 +    /*package-private*/
   3.234 +    static Empty uninitializedCallSite() {
   3.235 +        throw new IllegalStateException("uninitialized call site");
   3.236 +    }
   3.237 +
   3.238 +    // unsafe stuff:
   3.239 +    private static final long TARGET_OFFSET;
   3.240 +    static {
   3.241 +        try {
   3.242 +            TARGET_OFFSET = UNSAFE.objectFieldOffset(CallSite.class.getDeclaredField("target"));
   3.243 +        } catch (Exception ex) { throw new Error(ex); }
   3.244 +    }
   3.245 +
   3.246 +    /*package-private*/
   3.247 +    void setTargetNormal(MethodHandle newTarget) {
   3.248 +        MethodHandleNatives.setCallSiteTargetNormal(this, newTarget);
   3.249 +    }
   3.250 +    /*package-private*/
   3.251 +    MethodHandle getTargetVolatile() {
   3.252 +        return (MethodHandle) UNSAFE.getObjectVolatile(this, TARGET_OFFSET);
   3.253 +    }
   3.254 +    /*package-private*/
   3.255 +    void setTargetVolatile(MethodHandle newTarget) {
   3.256 +        MethodHandleNatives.setCallSiteTargetVolatile(this, newTarget);
   3.257 +    }
   3.258 +
   3.259 +    // this implements the upcall from the JVM, MethodHandleNatives.makeDynamicCallSite:
   3.260 +    static CallSite makeSite(MethodHandle bootstrapMethod,
   3.261 +                             // Callee information:
   3.262 +                             String name, MethodType type,
   3.263 +                             // Extra arguments for BSM, if any:
   3.264 +                             Object info,
   3.265 +                             // Caller information:
   3.266 +                             Class<?> callerClass) {
   3.267 +        MethodHandles.Lookup caller = IMPL_LOOKUP.in(callerClass);
   3.268 +        CallSite site;
   3.269 +        try {
   3.270 +            Object binding;
   3.271 +            info = maybeReBox(info);
   3.272 +            if (info == null) {
   3.273 +                binding = bootstrapMethod.invoke(caller, name, type);
   3.274 +            } else if (!info.getClass().isArray()) {
   3.275 +                binding = bootstrapMethod.invoke(caller, name, type, info);
   3.276 +            } else {
   3.277 +                Object[] argv = (Object[]) info;
   3.278 +                maybeReBoxElements(argv);
   3.279 +                switch (argv.length) {
   3.280 +                case 0:
   3.281 +                    binding = bootstrapMethod.invoke(caller, name, type);
   3.282 +                    break;
   3.283 +                case 1:
   3.284 +                    binding = bootstrapMethod.invoke(caller, name, type,
   3.285 +                                                     argv[0]);
   3.286 +                    break;
   3.287 +                case 2:
   3.288 +                    binding = bootstrapMethod.invoke(caller, name, type,
   3.289 +                                                     argv[0], argv[1]);
   3.290 +                    break;
   3.291 +                case 3:
   3.292 +                    binding = bootstrapMethod.invoke(caller, name, type,
   3.293 +                                                     argv[0], argv[1], argv[2]);
   3.294 +                    break;
   3.295 +                case 4:
   3.296 +                    binding = bootstrapMethod.invoke(caller, name, type,
   3.297 +                                                     argv[0], argv[1], argv[2], argv[3]);
   3.298 +                    break;
   3.299 +                case 5:
   3.300 +                    binding = bootstrapMethod.invoke(caller, name, type,
   3.301 +                                                     argv[0], argv[1], argv[2], argv[3], argv[4]);
   3.302 +                    break;
   3.303 +                case 6:
   3.304 +                    binding = bootstrapMethod.invoke(caller, name, type,
   3.305 +                                                     argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
   3.306 +                    break;
   3.307 +                default:
   3.308 +                    final int NON_SPREAD_ARG_COUNT = 3;  // (caller, name, type)
   3.309 +                    if (NON_SPREAD_ARG_COUNT + argv.length > MethodType.MAX_MH_ARITY)
   3.310 +                        throw new BootstrapMethodError("too many bootstrap method arguments");
   3.311 +                    MethodType bsmType = bootstrapMethod.type();
   3.312 +                    MethodType invocationType = MethodType.genericMethodType(NON_SPREAD_ARG_COUNT + argv.length);
   3.313 +                    MethodHandle typedBSM = bootstrapMethod.asType(invocationType);
   3.314 +                    MethodHandle spreader = invocationType.invokers().spreadInvoker(NON_SPREAD_ARG_COUNT);
   3.315 +                    binding = spreader.invokeExact(typedBSM, (Object)caller, (Object)name, (Object)type, argv);
   3.316 +                }
   3.317 +            }
   3.318 +            //System.out.println("BSM for "+name+type+" => "+binding);
   3.319 +            if (binding instanceof CallSite) {
   3.320 +                site = (CallSite) binding;
   3.321 +            }  else {
   3.322 +                throw new ClassCastException("bootstrap method failed to produce a CallSite");
   3.323 +            }
   3.324 +            if (!site.getTarget().type().equals(type))
   3.325 +                throw new WrongMethodTypeException("wrong type: "+site.getTarget());
   3.326 +        } catch (Throwable ex) {
   3.327 +            BootstrapMethodError bex;
   3.328 +            if (ex instanceof BootstrapMethodError)
   3.329 +                bex = (BootstrapMethodError) ex;
   3.330 +            else
   3.331 +                bex = new BootstrapMethodError("call site initialization exception", ex);
   3.332 +            throw bex;
   3.333 +        }
   3.334 +        return site;
   3.335 +    }
   3.336 +
   3.337 +    private static Object maybeReBox(Object x) {
   3.338 +        if (x instanceof Integer) {
   3.339 +            int xi = (int) x;
   3.340 +            if (xi == (byte) xi)
   3.341 +                x = xi;  // must rebox; see JLS 5.1.7
   3.342 +        }
   3.343 +        return x;
   3.344 +    }
   3.345 +    private static void maybeReBoxElements(Object[] xa) {
   3.346 +        for (int i = 0; i < xa.length; i++) {
   3.347 +            xa[i] = maybeReBox(xa[i]);
   3.348 +        }
   3.349 +    }
   3.350 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/ConstantCallSite.java	Sat Aug 09 11:12:05 2014 +0200
     4.3 @@ -0,0 +1,120 @@
     4.4 +/*
     4.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
     4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4.7 + *
     4.8 + * This code is free software; you can redistribute it and/or modify it
     4.9 + * under the terms of the GNU General Public License version 2 only, as
    4.10 + * published by the Free Software Foundation.  Oracle designates this
    4.11 + * particular file as subject to the "Classpath" exception as provided
    4.12 + * by Oracle in the LICENSE file that accompanied this code.
    4.13 + *
    4.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    4.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    4.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    4.17 + * version 2 for more details (a copy is included in the LICENSE file that
    4.18 + * accompanied this code).
    4.19 + *
    4.20 + * You should have received a copy of the GNU General Public License version
    4.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    4.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    4.23 + *
    4.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    4.25 + * or visit www.oracle.com if you need additional information or have any
    4.26 + * questions.
    4.27 + */
    4.28 +
    4.29 +package java.lang.invoke;
    4.30 +
    4.31 +/**
    4.32 + * A {@code ConstantCallSite} is a {@link CallSite} whose target is permanent, and can never be changed.
    4.33 + * An {@code invokedynamic} instruction linked to a {@code ConstantCallSite} is permanently
    4.34 + * bound to the call site's target.
    4.35 + * @author John Rose, JSR 292 EG
    4.36 + */
    4.37 +public class ConstantCallSite extends CallSite {
    4.38 +    private final boolean isFrozen;
    4.39 +
    4.40 +    /**
    4.41 +     * Creates a call site with a permanent target.
    4.42 +     * @param target the target to be permanently associated with this call site
    4.43 +     * @throws NullPointerException if the proposed target is null
    4.44 +     */
    4.45 +    public ConstantCallSite(MethodHandle target) {
    4.46 +        super(target);
    4.47 +        isFrozen = true;
    4.48 +    }
    4.49 +
    4.50 +    /**
    4.51 +     * Creates a call site with a permanent target, possibly bound to the call site itself.
    4.52 +     * <p>
    4.53 +     * During construction of the call site, the {@code createTargetHook} is invoked to
    4.54 +     * produce the actual target, as if by a call of the form
    4.55 +     * {@code (MethodHandle) createTargetHook.invoke(this)}.
    4.56 +     * <p>
    4.57 +     * Note that user code cannot perform such an action directly in a subclass constructor,
    4.58 +     * since the target must be fixed before the {@code ConstantCallSite} constructor returns.
    4.59 +     * <p>
    4.60 +     * The hook is said to bind the call site to a target method handle,
    4.61 +     * and a typical action would be {@code someTarget.bindTo(this)}.
    4.62 +     * However, the hook is free to take any action whatever,
    4.63 +     * including ignoring the call site and returning a constant target.
    4.64 +     * <p>
    4.65 +     * The result returned by the hook must be a method handle of exactly
    4.66 +     * the same type as the call site.
    4.67 +     * <p>
    4.68 +     * While the hook is being called, the new {@code ConstantCallSite}
    4.69 +     * object is in a partially constructed state.
    4.70 +     * In this state,
    4.71 +     * a call to {@code getTarget}, or any other attempt to use the target,
    4.72 +     * will result in an {@code IllegalStateException}.
    4.73 +     * It is legal at all times to obtain the call site's type using the {@code type} method.
    4.74 +     *
    4.75 +     * @param targetType the type of the method handle to be permanently associated with this call site
    4.76 +     * @param createTargetHook a method handle to invoke (on the call site) to produce the call site's target
    4.77 +     * @throws WrongMethodTypeException if the hook cannot be invoked on the required arguments,
    4.78 +     *         or if the target returned by the hook is not of the given {@code targetType}
    4.79 +     * @throws NullPointerException if the hook returns a null value
    4.80 +     * @throws ClassCastException if the hook returns something other than a {@code MethodHandle}
    4.81 +     * @throws Throwable anything else thrown by the hook function
    4.82 +     */
    4.83 +    protected ConstantCallSite(MethodType targetType, MethodHandle createTargetHook) throws Throwable {
    4.84 +        super(targetType, createTargetHook);
    4.85 +        isFrozen = true;
    4.86 +    }
    4.87 +
    4.88 +    /**
    4.89 +     * Returns the target method of the call site, which behaves
    4.90 +     * like a {@code final} field of the {@code ConstantCallSite}.
    4.91 +     * That is, the target is always the original value passed
    4.92 +     * to the constructor call which created this instance.
    4.93 +     *
    4.94 +     * @return the immutable linkage state of this call site, a constant method handle
    4.95 +     * @throws IllegalStateException if the {@code ConstantCallSite} constructor has not completed
    4.96 +     */
    4.97 +    @Override public final MethodHandle getTarget() {
    4.98 +        if (!isFrozen)  throw new IllegalStateException();
    4.99 +        return target;
   4.100 +    }
   4.101 +
   4.102 +    /**
   4.103 +     * Always throws an {@link UnsupportedOperationException}.
   4.104 +     * This kind of call site cannot change its target.
   4.105 +     * @param ignore a new target proposed for the call site, which is ignored
   4.106 +     * @throws UnsupportedOperationException because this kind of call site cannot change its target
   4.107 +     */
   4.108 +    @Override public final void setTarget(MethodHandle ignore) {
   4.109 +        throw new UnsupportedOperationException();
   4.110 +    }
   4.111 +
   4.112 +    /**
   4.113 +     * Returns this call site's permanent target.
   4.114 +     * Since that target will never change, this is a correct implementation
   4.115 +     * of {@link CallSite#dynamicInvoker CallSite.dynamicInvoker}.
   4.116 +     * @return the immutable linkage state of this call site, a constant method handle
   4.117 +     * @throws IllegalStateException if the {@code ConstantCallSite} constructor has not completed
   4.118 +     */
   4.119 +    @Override
   4.120 +    public final MethodHandle dynamicInvoker() {
   4.121 +        return getTarget();
   4.122 +    }
   4.123 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/DirectMethodHandle.java	Sat Aug 09 11:12:05 2014 +0200
     5.3 @@ -0,0 +1,718 @@
     5.4 +/*
     5.5 + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
     5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     5.7 + *
     5.8 + * This code is free software; you can redistribute it and/or modify it
     5.9 + * under the terms of the GNU General Public License version 2 only, as
    5.10 + * published by the Free Software Foundation.  Oracle designates this
    5.11 + * particular file as subject to the "Classpath" exception as provided
    5.12 + * by Oracle in the LICENSE file that accompanied this code.
    5.13 + *
    5.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    5.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    5.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    5.17 + * version 2 for more details (a copy is included in the LICENSE file that
    5.18 + * accompanied this code).
    5.19 + *
    5.20 + * You should have received a copy of the GNU General Public License version
    5.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    5.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    5.23 + *
    5.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    5.25 + * or visit www.oracle.com if you need additional information or have any
    5.26 + * questions.
    5.27 + */
    5.28 +
    5.29 +package java.lang.invoke;
    5.30 +
    5.31 +import sun.misc.Unsafe;
    5.32 +import java.lang.reflect.Method;
    5.33 +import java.util.Arrays;
    5.34 +import sun.invoke.util.VerifyAccess;
    5.35 +import static java.lang.invoke.MethodHandleNatives.Constants.*;
    5.36 +import static java.lang.invoke.LambdaForm.*;
    5.37 +import static java.lang.invoke.MethodTypeForm.*;
    5.38 +import static java.lang.invoke.MethodHandleStatics.*;
    5.39 +import java.lang.ref.WeakReference;
    5.40 +import java.lang.reflect.Field;
    5.41 +import sun.invoke.util.ValueConversions;
    5.42 +import sun.invoke.util.VerifyType;
    5.43 +import sun.invoke.util.Wrapper;
    5.44 +
    5.45 +/**
    5.46 + * The flavor of method handle which implements a constant reference
    5.47 + * to a class member.
    5.48 + * @author jrose
    5.49 + */
    5.50 +class DirectMethodHandle extends MethodHandle {
    5.51 +    final MemberName member;
    5.52 +
    5.53 +    // Constructors and factory methods in this class *must* be package scoped or private.
    5.54 +    private DirectMethodHandle(MethodType mtype, LambdaForm form, MemberName member) {
    5.55 +        super(mtype, form);
    5.56 +        if (!member.isResolved())  throw new InternalError();
    5.57 +
    5.58 +        if (member.getDeclaringClass().isInterface() &&
    5.59 +                member.isMethod() && !member.isAbstract()) {
    5.60 +            // Check for corner case: invokeinterface of Object method
    5.61 +            MemberName m = new MemberName(Object.class, member.getName(), member.getMethodType(), member.getReferenceKind());
    5.62 +            m = MemberName.getFactory().resolveOrNull(m.getReferenceKind(), m, null);
    5.63 +            if (m != null && m.isPublic()) {
    5.64 +                member = m;
    5.65 +            }
    5.66 +        }
    5.67 +
    5.68 +        this.member = member;
    5.69 +    }
    5.70 +
    5.71 +    // Factory methods:
    5.72 +    static DirectMethodHandle make(byte refKind, Class<?> receiver, MemberName member) {
    5.73 +        MethodType mtype = member.getMethodOrFieldType();
    5.74 +        if (!member.isStatic()) {
    5.75 +            if (!member.getDeclaringClass().isAssignableFrom(receiver) || member.isConstructor())
    5.76 +                throw new InternalError(member.toString());
    5.77 +            mtype = mtype.insertParameterTypes(0, receiver);
    5.78 +        }
    5.79 +        if (!member.isField()) {
    5.80 +            if (refKind == REF_invokeSpecial) {
    5.81 +                member = member.asSpecial();
    5.82 +                LambdaForm lform = preparedLambdaForm(member);
    5.83 +                return new Special(mtype, lform, member);
    5.84 +            } else {
    5.85 +                LambdaForm lform = preparedLambdaForm(member);
    5.86 +                return new DirectMethodHandle(mtype, lform, member);
    5.87 +            }
    5.88 +        } else {
    5.89 +            LambdaForm lform = preparedFieldLambdaForm(member);
    5.90 +            if (member.isStatic()) {
    5.91 +                long offset = MethodHandleNatives.staticFieldOffset(member);
    5.92 +                Object base = MethodHandleNatives.staticFieldBase(member);
    5.93 +                return new StaticAccessor(mtype, lform, member, base, offset);
    5.94 +            } else {
    5.95 +                long offset = MethodHandleNatives.objectFieldOffset(member);
    5.96 +                assert(offset == (int)offset);
    5.97 +                return new Accessor(mtype, lform, member, (int)offset);
    5.98 +            }
    5.99 +        }
   5.100 +    }
   5.101 +    static DirectMethodHandle make(Class<?> receiver, MemberName member) {
   5.102 +        byte refKind = member.getReferenceKind();
   5.103 +        if (refKind == REF_invokeSpecial)
   5.104 +            refKind =  REF_invokeVirtual;
   5.105 +        return make(refKind, receiver, member);
   5.106 +    }
   5.107 +    static DirectMethodHandle make(MemberName member) {
   5.108 +        if (member.isConstructor())
   5.109 +            return makeAllocator(member);
   5.110 +        return make(member.getDeclaringClass(), member);
   5.111 +    }
   5.112 +    static DirectMethodHandle make(Method method) {
   5.113 +        return make(method.getDeclaringClass(), new MemberName(method));
   5.114 +    }
   5.115 +    static DirectMethodHandle make(Field field) {
   5.116 +        return make(field.getDeclaringClass(), new MemberName(field));
   5.117 +    }
   5.118 +    private static DirectMethodHandle makeAllocator(MemberName ctor) {
   5.119 +        assert(ctor.isConstructor() && ctor.getName().equals("<init>"));
   5.120 +        Class<?> instanceClass = ctor.getDeclaringClass();
   5.121 +        ctor = ctor.asConstructor();
   5.122 +        assert(ctor.isConstructor() && ctor.getReferenceKind() == REF_newInvokeSpecial) : ctor;
   5.123 +        MethodType mtype = ctor.getMethodType().changeReturnType(instanceClass);
   5.124 +        LambdaForm lform = preparedLambdaForm(ctor);
   5.125 +        MemberName init = ctor.asSpecial();
   5.126 +        assert(init.getMethodType().returnType() == void.class);
   5.127 +        return new Constructor(mtype, lform, ctor, init, instanceClass);
   5.128 +    }
   5.129 +
   5.130 +    @Override
   5.131 +    MethodHandle copyWith(MethodType mt, LambdaForm lf) {
   5.132 +        return new DirectMethodHandle(mt, lf, member);
   5.133 +    }
   5.134 +
   5.135 +    @Override
   5.136 +    String internalProperties() {
   5.137 +        return "/DMH="+member.toString();
   5.138 +    }
   5.139 +
   5.140 +    //// Implementation methods.
   5.141 +    @Override
   5.142 +    MethodHandle viewAsType(MethodType newType) {
   5.143 +        return new DirectMethodHandle(newType, form, member);
   5.144 +    }
   5.145 +    @Override
   5.146 +    @ForceInline
   5.147 +    MemberName internalMemberName() {
   5.148 +        return member;
   5.149 +    }
   5.150 +
   5.151 +    @Override
   5.152 +    MethodHandle bindArgument(int pos, char basicType, Object value) {
   5.153 +        // If the member needs dispatching, do so.
   5.154 +        if (pos == 0 && basicType == 'L') {
   5.155 +            DirectMethodHandle concrete = maybeRebind(value);
   5.156 +            if (concrete != null)
   5.157 +                return concrete.bindReceiver(value);
   5.158 +        }
   5.159 +        return super.bindArgument(pos, basicType, value);
   5.160 +    }
   5.161 +
   5.162 +    @Override
   5.163 +    MethodHandle bindReceiver(Object receiver) {
   5.164 +        // If the member needs dispatching, do so.
   5.165 +        DirectMethodHandle concrete = maybeRebind(receiver);
   5.166 +        if (concrete != null)
   5.167 +            return concrete.bindReceiver(receiver);
   5.168 +        return super.bindReceiver(receiver);
   5.169 +    }
   5.170 +
   5.171 +    private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
   5.172 +
   5.173 +    private DirectMethodHandle maybeRebind(Object receiver) {
   5.174 +        if (receiver != null) {
   5.175 +            switch (member.getReferenceKind()) {
   5.176 +            case REF_invokeInterface:
   5.177 +            case REF_invokeVirtual:
   5.178 +                // Pre-dispatch the member.
   5.179 +                Class<?> concreteClass = receiver.getClass();
   5.180 +                MemberName concrete = new MemberName(concreteClass, member.getName(), member.getMethodType(), REF_invokeSpecial);
   5.181 +                concrete = IMPL_NAMES.resolveOrNull(REF_invokeSpecial, concrete, concreteClass);
   5.182 +                if (concrete != null)
   5.183 +                    return new DirectMethodHandle(type(), preparedLambdaForm(concrete), concrete);
   5.184 +                break;
   5.185 +            }
   5.186 +        }
   5.187 +        return null;
   5.188 +    }
   5.189 +
   5.190 +    /**
   5.191 +     * Create a LF which can invoke the given method.
   5.192 +     * Cache and share this structure among all methods with
   5.193 +     * the same basicType and refKind.
   5.194 +     */
   5.195 +    private static LambdaForm preparedLambdaForm(MemberName m) {
   5.196 +        assert(m.isInvocable()) : m;  // call preparedFieldLambdaForm instead
   5.197 +        MethodType mtype = m.getInvocationType().basicType();
   5.198 +        assert(!m.isMethodHandleInvoke() || "invokeBasic".equals(m.getName())) : m;
   5.199 +        int which;
   5.200 +        switch (m.getReferenceKind()) {
   5.201 +        case REF_invokeVirtual:    which = LF_INVVIRTUAL;    break;
   5.202 +        case REF_invokeStatic:     which = LF_INVSTATIC;     break;
   5.203 +        case REF_invokeSpecial:    which = LF_INVSPECIAL;    break;
   5.204 +        case REF_invokeInterface:  which = LF_INVINTERFACE;  break;
   5.205 +        case REF_newInvokeSpecial: which = LF_NEWINVSPECIAL; break;
   5.206 +        default:  throw new InternalError(m.toString());
   5.207 +        }
   5.208 +        if (which == LF_INVSTATIC && shouldBeInitialized(m)) {
   5.209 +            // precompute the barrier-free version:
   5.210 +            preparedLambdaForm(mtype, which);
   5.211 +            which = LF_INVSTATIC_INIT;
   5.212 +        }
   5.213 +        LambdaForm lform = preparedLambdaForm(mtype, which);
   5.214 +        maybeCompile(lform, m);
   5.215 +        assert(lform.methodType().dropParameterTypes(0, 1)
   5.216 +                .equals(m.getInvocationType().basicType()))
   5.217 +                : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType());
   5.218 +        return lform;
   5.219 +    }
   5.220 +
   5.221 +    private static LambdaForm preparedLambdaForm(MethodType mtype, int which) {
   5.222 +        LambdaForm lform = mtype.form().cachedLambdaForm(which);
   5.223 +        if (lform != null)  return lform;
   5.224 +        lform = makePreparedLambdaForm(mtype, which);
   5.225 +        return mtype.form().setCachedLambdaForm(which, lform);
   5.226 +    }
   5.227 +
   5.228 +    private static LambdaForm makePreparedLambdaForm(MethodType mtype, int which) {
   5.229 +        boolean needsInit = (which == LF_INVSTATIC_INIT);
   5.230 +        boolean doesAlloc = (which == LF_NEWINVSPECIAL);
   5.231 +        String linkerName, lambdaName;
   5.232 +        switch (which) {
   5.233 +        case LF_INVVIRTUAL:    linkerName = "linkToVirtual";    lambdaName = "DMH.invokeVirtual";    break;
   5.234 +        case LF_INVSTATIC:     linkerName = "linkToStatic";     lambdaName = "DMH.invokeStatic";     break;
   5.235 +        case LF_INVSTATIC_INIT:linkerName = "linkToStatic";     lambdaName = "DMH.invokeStaticInit"; break;
   5.236 +        case LF_INVSPECIAL:    linkerName = "linkToSpecial";    lambdaName = "DMH.invokeSpecial";    break;
   5.237 +        case LF_INVINTERFACE:  linkerName = "linkToInterface";  lambdaName = "DMH.invokeInterface";  break;
   5.238 +        case LF_NEWINVSPECIAL: linkerName = "linkToSpecial";    lambdaName = "DMH.newInvokeSpecial"; break;
   5.239 +        default:  throw new InternalError("which="+which);
   5.240 +        }
   5.241 +        MethodType mtypeWithArg = mtype.appendParameterTypes(MemberName.class);
   5.242 +        if (doesAlloc)
   5.243 +            mtypeWithArg = mtypeWithArg
   5.244 +                    .insertParameterTypes(0, Object.class)  // insert newly allocated obj
   5.245 +                    .changeReturnType(void.class);          // <init> returns void
   5.246 +        MemberName linker = new MemberName(MethodHandle.class, linkerName, mtypeWithArg, REF_invokeStatic);
   5.247 +        try {
   5.248 +            linker = IMPL_NAMES.resolveOrFail(REF_invokeStatic, linker, null, NoSuchMethodException.class);
   5.249 +        } catch (ReflectiveOperationException ex) {
   5.250 +            throw newInternalError(ex);
   5.251 +        }
   5.252 +        final int DMH_THIS    = 0;
   5.253 +        final int ARG_BASE    = 1;
   5.254 +        final int ARG_LIMIT   = ARG_BASE + mtype.parameterCount();
   5.255 +        int nameCursor = ARG_LIMIT;
   5.256 +        final int NEW_OBJ     = (doesAlloc ? nameCursor++ : -1);
   5.257 +        final int GET_MEMBER  = nameCursor++;
   5.258 +        final int LINKER_CALL = nameCursor++;
   5.259 +        Name[] names = arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
   5.260 +        assert(names.length == nameCursor);
   5.261 +        if (doesAlloc) {
   5.262 +            // names = { argx,y,z,... new C, init method }
   5.263 +            names[NEW_OBJ] = new Name(Lazy.NF_allocateInstance, names[DMH_THIS]);
   5.264 +            names[GET_MEMBER] = new Name(Lazy.NF_constructorMethod, names[DMH_THIS]);
   5.265 +        } else if (needsInit) {
   5.266 +            names[GET_MEMBER] = new Name(Lazy.NF_internalMemberNameEnsureInit, names[DMH_THIS]);
   5.267 +        } else {
   5.268 +            names[GET_MEMBER] = new Name(Lazy.NF_internalMemberName, names[DMH_THIS]);
   5.269 +        }
   5.270 +        Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, GET_MEMBER+1, Object[].class);
   5.271 +        assert(outArgs[outArgs.length-1] == names[GET_MEMBER]);  // look, shifted args!
   5.272 +        int result = LambdaForm.LAST_RESULT;
   5.273 +        if (doesAlloc) {
   5.274 +            assert(outArgs[outArgs.length-2] == names[NEW_OBJ]);  // got to move this one
   5.275 +            System.arraycopy(outArgs, 0, outArgs, 1, outArgs.length-2);
   5.276 +            outArgs[0] = names[NEW_OBJ];
   5.277 +            result = NEW_OBJ;
   5.278 +        }
   5.279 +        names[LINKER_CALL] = new Name(linker, outArgs);
   5.280 +        lambdaName += "_" + LambdaForm.basicTypeSignature(mtype);
   5.281 +        LambdaForm lform = new LambdaForm(lambdaName, ARG_LIMIT, names, result);
   5.282 +        // This is a tricky bit of code.  Don't send it through the LF interpreter.
   5.283 +        lform.compileToBytecode();
   5.284 +        return lform;
   5.285 +    }
   5.286 +
   5.287 +    private static void maybeCompile(LambdaForm lform, MemberName m) {
   5.288 +        if (VerifyAccess.isSamePackage(m.getDeclaringClass(), MethodHandle.class))
   5.289 +            // Help along bootstrapping...
   5.290 +            lform.compileToBytecode();
   5.291 +    }
   5.292 +
   5.293 +    /** Static wrapper for DirectMethodHandle.internalMemberName. */
   5.294 +    @ForceInline
   5.295 +    /*non-public*/ static Object internalMemberName(Object mh) {
   5.296 +        return ((DirectMethodHandle)mh).member;
   5.297 +    }
   5.298 +
   5.299 +    /** Static wrapper for DirectMethodHandle.internalMemberName.
   5.300 +     * This one also forces initialization.
   5.301 +     */
   5.302 +    /*non-public*/ static Object internalMemberNameEnsureInit(Object mh) {
   5.303 +        DirectMethodHandle dmh = (DirectMethodHandle)mh;
   5.304 +        dmh.ensureInitialized();
   5.305 +        return dmh.member;
   5.306 +    }
   5.307 +
   5.308 +    /*non-public*/ static
   5.309 +    boolean shouldBeInitialized(MemberName member) {
   5.310 +        switch (member.getReferenceKind()) {
   5.311 +        case REF_invokeStatic:
   5.312 +        case REF_getStatic:
   5.313 +        case REF_putStatic:
   5.314 +        case REF_newInvokeSpecial:
   5.315 +            break;
   5.316 +        default:
   5.317 +            // No need to initialize the class on this kind of member.
   5.318 +            return false;
   5.319 +        }
   5.320 +        Class<?> cls = member.getDeclaringClass();
   5.321 +        if (cls == ValueConversions.class ||
   5.322 +            cls == MethodHandleImpl.class ||
   5.323 +            cls == Invokers.class) {
   5.324 +            // These guys have lots of <clinit> DMH creation but we know
   5.325 +            // the MHs will not be used until the system is booted.
   5.326 +            return false;
   5.327 +        }
   5.328 +        if (VerifyAccess.isSamePackage(MethodHandle.class, cls) ||
   5.329 +            VerifyAccess.isSamePackage(ValueConversions.class, cls)) {
   5.330 +            // It is a system class.  It is probably in the process of
   5.331 +            // being initialized, but we will help it along just to be safe.
   5.332 +            if (UNSAFE.shouldBeInitialized(cls)) {
   5.333 +                UNSAFE.ensureClassInitialized(cls);
   5.334 +            }
   5.335 +            return false;
   5.336 +        }
   5.337 +        return UNSAFE.shouldBeInitialized(cls);
   5.338 +    }
   5.339 +
   5.340 +    private static class EnsureInitialized extends ClassValue<WeakReference<Thread>> {
   5.341 +        @Override
   5.342 +        protected WeakReference<Thread> computeValue(Class<?> type) {
   5.343 +            UNSAFE.ensureClassInitialized(type);
   5.344 +            if (UNSAFE.shouldBeInitialized(type))
   5.345 +                // If the previous call didn't block, this can happen.
   5.346 +                // We are executing inside <clinit>.
   5.347 +                return new WeakReference<>(Thread.currentThread());
   5.348 +            return null;
   5.349 +        }
   5.350 +        static final EnsureInitialized INSTANCE = new EnsureInitialized();
   5.351 +    }
   5.352 +
   5.353 +    private void ensureInitialized() {
   5.354 +        if (checkInitialized(member)) {
   5.355 +            // The coast is clear.  Delete the <clinit> barrier.
   5.356 +            if (member.isField())
   5.357 +                updateForm(preparedFieldLambdaForm(member));
   5.358 +            else
   5.359 +                updateForm(preparedLambdaForm(member));
   5.360 +        }
   5.361 +    }
   5.362 +    private static boolean checkInitialized(MemberName member) {
   5.363 +        Class<?> defc = member.getDeclaringClass();
   5.364 +        WeakReference<Thread> ref = EnsureInitialized.INSTANCE.get(defc);
   5.365 +        if (ref == null) {
   5.366 +            return true;  // the final state
   5.367 +        }
   5.368 +        Thread clinitThread = ref.get();
   5.369 +        // Somebody may still be running defc.<clinit>.
   5.370 +        if (clinitThread == Thread.currentThread()) {
   5.371 +            // If anybody is running defc.<clinit>, it is this thread.
   5.372 +            if (UNSAFE.shouldBeInitialized(defc))
   5.373 +                // Yes, we are running it; keep the barrier for now.
   5.374 +                return false;
   5.375 +        } else {
   5.376 +            // We are in a random thread.  Block.
   5.377 +            UNSAFE.ensureClassInitialized(defc);
   5.378 +        }
   5.379 +        assert(!UNSAFE.shouldBeInitialized(defc));
   5.380 +        // put it into the final state
   5.381 +        EnsureInitialized.INSTANCE.remove(defc);
   5.382 +        return true;
   5.383 +    }
   5.384 +
   5.385 +    /*non-public*/ static void ensureInitialized(Object mh) {
   5.386 +        ((DirectMethodHandle)mh).ensureInitialized();
   5.387 +    }
   5.388 +
   5.389 +    /** This subclass represents invokespecial instructions. */
   5.390 +    static class Special extends DirectMethodHandle {
   5.391 +        private Special(MethodType mtype, LambdaForm form, MemberName member) {
   5.392 +            super(mtype, form, member);
   5.393 +        }
   5.394 +        @Override
   5.395 +        boolean isInvokeSpecial() {
   5.396 +            return true;
   5.397 +        }
   5.398 +        @Override
   5.399 +        MethodHandle viewAsType(MethodType newType) {
   5.400 +            return new Special(newType, form, member);
   5.401 +        }
   5.402 +    }
   5.403 +
   5.404 +    /** This subclass handles constructor references. */
   5.405 +    static class Constructor extends DirectMethodHandle {
   5.406 +        final MemberName initMethod;
   5.407 +        final Class<?>   instanceClass;
   5.408 +
   5.409 +        private Constructor(MethodType mtype, LambdaForm form, MemberName constructor,
   5.410 +                            MemberName initMethod, Class<?> instanceClass) {
   5.411 +            super(mtype, form, constructor);
   5.412 +            this.initMethod = initMethod;
   5.413 +            this.instanceClass = instanceClass;
   5.414 +            assert(initMethod.isResolved());
   5.415 +        }
   5.416 +        @Override
   5.417 +        MethodHandle viewAsType(MethodType newType) {
   5.418 +            return new Constructor(newType, form, member, initMethod, instanceClass);
   5.419 +        }
   5.420 +    }
   5.421 +
   5.422 +    /*non-public*/ static Object constructorMethod(Object mh) {
   5.423 +        Constructor dmh = (Constructor)mh;
   5.424 +        return dmh.initMethod;
   5.425 +    }
   5.426 +
   5.427 +    /*non-public*/ static Object allocateInstance(Object mh) throws InstantiationException {
   5.428 +        Constructor dmh = (Constructor)mh;
   5.429 +        return UNSAFE.allocateInstance(dmh.instanceClass);
   5.430 +    }
   5.431 +
   5.432 +    /** This subclass handles non-static field references. */
   5.433 +    static class Accessor extends DirectMethodHandle {
   5.434 +        final Class<?> fieldType;
   5.435 +        final int      fieldOffset;
   5.436 +        private Accessor(MethodType mtype, LambdaForm form, MemberName member,
   5.437 +                         int fieldOffset) {
   5.438 +            super(mtype, form, member);
   5.439 +            this.fieldType   = member.getFieldType();
   5.440 +            this.fieldOffset = fieldOffset;
   5.441 +        }
   5.442 +
   5.443 +        @Override Object checkCast(Object obj) {
   5.444 +            return fieldType.cast(obj);
   5.445 +        }
   5.446 +        @Override
   5.447 +        MethodHandle viewAsType(MethodType newType) {
   5.448 +            return new Accessor(newType, form, member, fieldOffset);
   5.449 +        }
   5.450 +    }
   5.451 +
   5.452 +    @ForceInline
   5.453 +    /*non-public*/ static long fieldOffset(Object accessorObj) {
   5.454 +        // Note: We return a long because that is what Unsafe.getObject likes.
   5.455 +        // We store a plain int because it is more compact.
   5.456 +        return ((Accessor)accessorObj).fieldOffset;
   5.457 +    }
   5.458 +
   5.459 +    @ForceInline
   5.460 +    /*non-public*/ static Object checkBase(Object obj) {
   5.461 +        // Note that the object's class has already been verified,
   5.462 +        // since the parameter type of the Accessor method handle
   5.463 +        // is either member.getDeclaringClass or a subclass.
   5.464 +        // This was verified in DirectMethodHandle.make.
   5.465 +        // Therefore, the only remaining check is for null.
   5.466 +        // Since this check is *not* guaranteed by Unsafe.getInt
   5.467 +        // and its siblings, we need to make an explicit one here.
   5.468 +        obj.getClass();  // maybe throw NPE
   5.469 +        return obj;
   5.470 +    }
   5.471 +
   5.472 +    /** This subclass handles static field references. */
   5.473 +    static class StaticAccessor extends DirectMethodHandle {
   5.474 +        final private Class<?> fieldType;
   5.475 +        final private Object   staticBase;
   5.476 +        final private long     staticOffset;
   5.477 +
   5.478 +        private StaticAccessor(MethodType mtype, LambdaForm form, MemberName member,
   5.479 +                               Object staticBase, long staticOffset) {
   5.480 +            super(mtype, form, member);
   5.481 +            this.fieldType    = member.getFieldType();
   5.482 +            this.staticBase   = staticBase;
   5.483 +            this.staticOffset = staticOffset;
   5.484 +        }
   5.485 +
   5.486 +        @Override Object checkCast(Object obj) {
   5.487 +            return fieldType.cast(obj);
   5.488 +        }
   5.489 +        @Override
   5.490 +        MethodHandle viewAsType(MethodType newType) {
   5.491 +            return new StaticAccessor(newType, form, member, staticBase, staticOffset);
   5.492 +        }
   5.493 +    }
   5.494 +
   5.495 +    @ForceInline
   5.496 +    /*non-public*/ static Object nullCheck(Object obj) {
   5.497 +        obj.getClass();
   5.498 +        return obj;
   5.499 +    }
   5.500 +
   5.501 +    @ForceInline
   5.502 +    /*non-public*/ static Object staticBase(Object accessorObj) {
   5.503 +        return ((StaticAccessor)accessorObj).staticBase;
   5.504 +    }
   5.505 +
   5.506 +    @ForceInline
   5.507 +    /*non-public*/ static long staticOffset(Object accessorObj) {
   5.508 +        return ((StaticAccessor)accessorObj).staticOffset;
   5.509 +    }
   5.510 +
   5.511 +    @ForceInline
   5.512 +    /*non-public*/ static Object checkCast(Object mh, Object obj) {
   5.513 +        return ((DirectMethodHandle) mh).checkCast(obj);
   5.514 +    }
   5.515 +
   5.516 +    Object checkCast(Object obj) {
   5.517 +        return member.getReturnType().cast(obj);
   5.518 +    }
   5.519 +
   5.520 +    // Caching machinery for field accessors:
   5.521 +    private static byte
   5.522 +            AF_GETFIELD        = 0,
   5.523 +            AF_PUTFIELD        = 1,
   5.524 +            AF_GETSTATIC       = 2,
   5.525 +            AF_PUTSTATIC       = 3,
   5.526 +            AF_GETSTATIC_INIT  = 4,
   5.527 +            AF_PUTSTATIC_INIT  = 5,
   5.528 +            AF_LIMIT           = 6;
   5.529 +    // Enumerate the different field kinds using Wrapper,
   5.530 +    // with an extra case added for checked references.
   5.531 +    private static int
   5.532 +            FT_LAST_WRAPPER    = Wrapper.values().length-1,
   5.533 +            FT_UNCHECKED_REF   = Wrapper.OBJECT.ordinal(),
   5.534 +            FT_CHECKED_REF     = FT_LAST_WRAPPER+1,
   5.535 +            FT_LIMIT           = FT_LAST_WRAPPER+2;
   5.536 +    private static int afIndex(byte formOp, boolean isVolatile, int ftypeKind) {
   5.537 +        return ((formOp * FT_LIMIT * 2)
   5.538 +                + (isVolatile ? FT_LIMIT : 0)
   5.539 +                + ftypeKind);
   5.540 +    }
   5.541 +    private static final LambdaForm[] ACCESSOR_FORMS
   5.542 +            = new LambdaForm[afIndex(AF_LIMIT, false, 0)];
   5.543 +    private static int ftypeKind(Class<?> ftype) {
   5.544 +        if (ftype.isPrimitive())
   5.545 +            return Wrapper.forPrimitiveType(ftype).ordinal();
   5.546 +        else if (VerifyType.isNullReferenceConversion(Object.class, ftype))
   5.547 +            return FT_UNCHECKED_REF;
   5.548 +        else
   5.549 +            return FT_CHECKED_REF;
   5.550 +    }
   5.551 +
   5.552 +    /**
   5.553 +     * Create a LF which can access the given field.
   5.554 +     * Cache and share this structure among all fields with
   5.555 +     * the same basicType and refKind.
   5.556 +     */
   5.557 +    private static LambdaForm preparedFieldLambdaForm(MemberName m) {
   5.558 +        Class<?> ftype = m.getFieldType();
   5.559 +        boolean isVolatile = m.isVolatile();
   5.560 +        byte formOp;
   5.561 +        switch (m.getReferenceKind()) {
   5.562 +        case REF_getField:      formOp = AF_GETFIELD;    break;
   5.563 +        case REF_putField:      formOp = AF_PUTFIELD;    break;
   5.564 +        case REF_getStatic:     formOp = AF_GETSTATIC;   break;
   5.565 +        case REF_putStatic:     formOp = AF_PUTSTATIC;   break;
   5.566 +        default:  throw new InternalError(m.toString());
   5.567 +        }
   5.568 +        if (shouldBeInitialized(m)) {
   5.569 +            // precompute the barrier-free version:
   5.570 +            preparedFieldLambdaForm(formOp, isVolatile, ftype);
   5.571 +            assert((AF_GETSTATIC_INIT - AF_GETSTATIC) ==
   5.572 +                   (AF_PUTSTATIC_INIT - AF_PUTSTATIC));
   5.573 +            formOp += (AF_GETSTATIC_INIT - AF_GETSTATIC);
   5.574 +        }
   5.575 +        LambdaForm lform = preparedFieldLambdaForm(formOp, isVolatile, ftype);
   5.576 +        maybeCompile(lform, m);
   5.577 +        assert(lform.methodType().dropParameterTypes(0, 1)
   5.578 +                .equals(m.getInvocationType().basicType()))
   5.579 +                : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType());
   5.580 +        return lform;
   5.581 +    }
   5.582 +    private static LambdaForm preparedFieldLambdaForm(byte formOp, boolean isVolatile, Class<?> ftype) {
   5.583 +        int afIndex = afIndex(formOp, isVolatile, ftypeKind(ftype));
   5.584 +        LambdaForm lform = ACCESSOR_FORMS[afIndex];
   5.585 +        if (lform != null)  return lform;
   5.586 +        lform = makePreparedFieldLambdaForm(formOp, isVolatile, ftypeKind(ftype));
   5.587 +        ACCESSOR_FORMS[afIndex] = lform;  // don't bother with a CAS
   5.588 +        return lform;
   5.589 +    }
   5.590 +
   5.591 +    private static LambdaForm makePreparedFieldLambdaForm(byte formOp, boolean isVolatile, int ftypeKind) {
   5.592 +        boolean isGetter  = (formOp & 1) == (AF_GETFIELD & 1);
   5.593 +        boolean isStatic  = (formOp >= AF_GETSTATIC);
   5.594 +        boolean needsInit = (formOp >= AF_GETSTATIC_INIT);
   5.595 +        boolean needsCast = (ftypeKind == FT_CHECKED_REF);
   5.596 +        Wrapper fw = (needsCast ? Wrapper.OBJECT : Wrapper.values()[ftypeKind]);
   5.597 +        Class<?> ft = fw.primitiveType();
   5.598 +        assert(ftypeKind(needsCast ? String.class : ft) == ftypeKind);
   5.599 +        String tname  = fw.primitiveSimpleName();
   5.600 +        String ctname = Character.toUpperCase(tname.charAt(0)) + tname.substring(1);
   5.601 +        if (isVolatile)  ctname += "Volatile";
   5.602 +        String getOrPut = (isGetter ? "get" : "put");
   5.603 +        String linkerName = (getOrPut + ctname);  // getObject, putIntVolatile, etc.
   5.604 +        MethodType linkerType;
   5.605 +        if (isGetter)
   5.606 +            linkerType = MethodType.methodType(ft, Object.class, long.class);
   5.607 +        else
   5.608 +            linkerType = MethodType.methodType(void.class, Object.class, long.class, ft);
   5.609 +        MemberName linker = new MemberName(Unsafe.class, linkerName, linkerType, REF_invokeVirtual);
   5.610 +        try {
   5.611 +            linker = IMPL_NAMES.resolveOrFail(REF_invokeVirtual, linker, null, NoSuchMethodException.class);
   5.612 +        } catch (ReflectiveOperationException ex) {
   5.613 +            throw newInternalError(ex);
   5.614 +        }
   5.615 +
   5.616 +        // What is the external type of the lambda form?
   5.617 +        MethodType mtype;
   5.618 +        if (isGetter)
   5.619 +            mtype = MethodType.methodType(ft);
   5.620 +        else
   5.621 +            mtype = MethodType.methodType(void.class, ft);
   5.622 +        mtype = mtype.basicType();  // erase short to int, etc.
   5.623 +        if (!isStatic)
   5.624 +            mtype = mtype.insertParameterTypes(0, Object.class);
   5.625 +        final int DMH_THIS  = 0;
   5.626 +        final int ARG_BASE  = 1;
   5.627 +        final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
   5.628 +        // if this is for non-static access, the base pointer is stored at this index:
   5.629 +        final int OBJ_BASE  = isStatic ? -1 : ARG_BASE;
   5.630 +        // if this is for write access, the value to be written is stored at this index:
   5.631 +        final int SET_VALUE  = isGetter ? -1 : ARG_LIMIT - 1;
   5.632 +        int nameCursor = ARG_LIMIT;
   5.633 +        final int F_HOLDER  = (isStatic ? nameCursor++ : -1);  // static base if any
   5.634 +        final int F_OFFSET  = nameCursor++;  // Either static offset or field offset.
   5.635 +        final int OBJ_CHECK = (OBJ_BASE >= 0 ? nameCursor++ : -1);
   5.636 +        final int INIT_BAR  = (needsInit ? nameCursor++ : -1);
   5.637 +        final int PRE_CAST  = (needsCast && !isGetter ? nameCursor++ : -1);
   5.638 +        final int LINKER_CALL = nameCursor++;
   5.639 +        final int POST_CAST = (needsCast && isGetter ? nameCursor++ : -1);
   5.640 +        final int RESULT    = nameCursor-1;  // either the call or the cast
   5.641 +        Name[] names = arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
   5.642 +        if (needsInit)
   5.643 +            names[INIT_BAR] = new Name(Lazy.NF_ensureInitialized, names[DMH_THIS]);
   5.644 +        if (needsCast && !isGetter)
   5.645 +            names[PRE_CAST] = new Name(Lazy.NF_checkCast, names[DMH_THIS], names[SET_VALUE]);
   5.646 +        Object[] outArgs = new Object[1 + linkerType.parameterCount()];
   5.647 +        assert(outArgs.length == (isGetter ? 3 : 4));
   5.648 +        outArgs[0] = UNSAFE;
   5.649 +        if (isStatic) {
   5.650 +            outArgs[1] = names[F_HOLDER]  = new Name(Lazy.NF_staticBase, names[DMH_THIS]);
   5.651 +            outArgs[2] = names[F_OFFSET]  = new Name(Lazy.NF_staticOffset, names[DMH_THIS]);
   5.652 +        } else {
   5.653 +            outArgs[1] = names[OBJ_CHECK] = new Name(Lazy.NF_checkBase, names[OBJ_BASE]);
   5.654 +            outArgs[2] = names[F_OFFSET]  = new Name(Lazy.NF_fieldOffset, names[DMH_THIS]);
   5.655 +        }
   5.656 +        if (!isGetter) {
   5.657 +            outArgs[3] = (needsCast ? names[PRE_CAST] : names[SET_VALUE]);
   5.658 +        }
   5.659 +        for (Object a : outArgs)  assert(a != null);
   5.660 +        names[LINKER_CALL] = new Name(linker, outArgs);
   5.661 +        if (needsCast && isGetter)
   5.662 +            names[POST_CAST] = new Name(Lazy.NF_checkCast, names[DMH_THIS], names[LINKER_CALL]);
   5.663 +        for (Name n : names)  assert(n != null);
   5.664 +        String fieldOrStatic = (isStatic ? "Static" : "Field");
   5.665 +        String lambdaName = (linkerName + fieldOrStatic);  // significant only for debugging
   5.666 +        if (needsCast)  lambdaName += "Cast";
   5.667 +        if (needsInit)  lambdaName += "Init";
   5.668 +        return new LambdaForm(lambdaName, ARG_LIMIT, names, RESULT);
   5.669 +    }
   5.670 +
   5.671 +    /**
   5.672 +     * Pre-initialized NamedFunctions for bootstrapping purposes.
   5.673 +     * Factored in an inner class to delay initialization until first usage.
   5.674 +     */
   5.675 +    private static class Lazy {
   5.676 +        static final NamedFunction
   5.677 +                NF_internalMemberName,
   5.678 +                NF_internalMemberNameEnsureInit,
   5.679 +                NF_ensureInitialized,
   5.680 +                NF_fieldOffset,
   5.681 +                NF_checkBase,
   5.682 +                NF_staticBase,
   5.683 +                NF_staticOffset,
   5.684 +                NF_checkCast,
   5.685 +                NF_allocateInstance,
   5.686 +                NF_constructorMethod;
   5.687 +        static {
   5.688 +            try {
   5.689 +                NamedFunction nfs[] = {
   5.690 +                        NF_internalMemberName = new NamedFunction(DirectMethodHandle.class
   5.691 +                                .getDeclaredMethod("internalMemberName", Object.class)),
   5.692 +                        NF_internalMemberNameEnsureInit = new NamedFunction(DirectMethodHandle.class
   5.693 +                                .getDeclaredMethod("internalMemberNameEnsureInit", Object.class)),
   5.694 +                        NF_ensureInitialized = new NamedFunction(DirectMethodHandle.class
   5.695 +                                .getDeclaredMethod("ensureInitialized", Object.class)),
   5.696 +                        NF_fieldOffset = new NamedFunction(DirectMethodHandle.class
   5.697 +                                .getDeclaredMethod("fieldOffset", Object.class)),
   5.698 +                        NF_checkBase = new NamedFunction(DirectMethodHandle.class
   5.699 +                                .getDeclaredMethod("checkBase", Object.class)),
   5.700 +                        NF_staticBase = new NamedFunction(DirectMethodHandle.class
   5.701 +                                .getDeclaredMethod("staticBase", Object.class)),
   5.702 +                        NF_staticOffset = new NamedFunction(DirectMethodHandle.class
   5.703 +                                .getDeclaredMethod("staticOffset", Object.class)),
   5.704 +                        NF_checkCast = new NamedFunction(DirectMethodHandle.class
   5.705 +                                .getDeclaredMethod("checkCast", Object.class, Object.class)),
   5.706 +                        NF_allocateInstance = new NamedFunction(DirectMethodHandle.class
   5.707 +                                .getDeclaredMethod("allocateInstance", Object.class)),
   5.708 +                        NF_constructorMethod = new NamedFunction(DirectMethodHandle.class
   5.709 +                                .getDeclaredMethod("constructorMethod", Object.class))
   5.710 +                };
   5.711 +                for (NamedFunction nf : nfs) {
   5.712 +                    // Each nf must be statically invocable or we get tied up in our bootstraps.
   5.713 +                    assert(InvokerBytecodeGenerator.isStaticallyInvocable(nf.member)) : nf;
   5.714 +                    nf.resolve();
   5.715 +                }
   5.716 +            } catch (ReflectiveOperationException ex) {
   5.717 +                throw newInternalError(ex);
   5.718 +            }
   5.719 +        }
   5.720 +    }
   5.721 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/DontInline.java	Sat Aug 09 11:12:05 2014 +0200
     6.3 @@ -0,0 +1,37 @@
     6.4 +/*
     6.5 + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
     6.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     6.7 + *
     6.8 + * This code is free software; you can redistribute it and/or modify it
     6.9 + * under the terms of the GNU General Public License version 2 only, as
    6.10 + * published by the Free Software Foundation.  Oracle designates this
    6.11 + * particular file as subject to the "Classpath" exception as provided
    6.12 + * by Oracle in the LICENSE file that accompanied this code.
    6.13 + *
    6.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    6.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    6.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    6.17 + * version 2 for more details (a copy is included in the LICENSE file that
    6.18 + * accompanied this code).
    6.19 + *
    6.20 + * You should have received a copy of the GNU General Public License version
    6.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    6.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    6.23 + *
    6.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    6.25 + * or visit www.oracle.com if you need additional information or have any
    6.26 + * questions.
    6.27 + */
    6.28 +
    6.29 +package java.lang.invoke;
    6.30 +
    6.31 +import java.lang.annotation.*;
    6.32 +
    6.33 +/**
    6.34 + * Internal marker for some methods in the JSR 292 implementation.
    6.35 + */
    6.36 +/*non-public*/
    6.37 +@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
    6.38 +@Retention(RetentionPolicy.RUNTIME)
    6.39 +@interface DontInline {
    6.40 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/ForceInline.java	Sat Aug 09 11:12:05 2014 +0200
     7.3 @@ -0,0 +1,37 @@
     7.4 +/*
     7.5 + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
     7.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     7.7 + *
     7.8 + * This code is free software; you can redistribute it and/or modify it
     7.9 + * under the terms of the GNU General Public License version 2 only, as
    7.10 + * published by the Free Software Foundation.  Oracle designates this
    7.11 + * particular file as subject to the "Classpath" exception as provided
    7.12 + * by Oracle in the LICENSE file that accompanied this code.
    7.13 + *
    7.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    7.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    7.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    7.17 + * version 2 for more details (a copy is included in the LICENSE file that
    7.18 + * accompanied this code).
    7.19 + *
    7.20 + * You should have received a copy of the GNU General Public License version
    7.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    7.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    7.23 + *
    7.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    7.25 + * or visit www.oracle.com if you need additional information or have any
    7.26 + * questions.
    7.27 + */
    7.28 +
    7.29 +package java.lang.invoke;
    7.30 +
    7.31 +import java.lang.annotation.*;
    7.32 +
    7.33 +/**
    7.34 + * Internal marker for some methods in the JSR 292 implementation.
    7.35 + */
    7.36 +/*non-public*/
    7.37 +@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
    7.38 +@Retention(RetentionPolicy.RUNTIME)
    7.39 +@interface ForceInline {
    7.40 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/InfoFromMemberName.java	Sat Aug 09 11:12:05 2014 +0200
     8.3 @@ -0,0 +1,145 @@
     8.4 +/*
     8.5 + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
     8.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     8.7 + *
     8.8 + * This code is free software; you can redistribute it and/or modify it
     8.9 + * under the terms of the GNU General Public License version 2 only, as
    8.10 + * published by the Free Software Foundation.  Oracle designates this
    8.11 + * particular file as subject to the "Classpath" exception as provided
    8.12 + * by Oracle in the LICENSE file that accompanied this code.
    8.13 + *
    8.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    8.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    8.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    8.17 + * version 2 for more details (a copy is included in the LICENSE file that
    8.18 + * accompanied this code).
    8.19 + *
    8.20 + * You should have received a copy of the GNU General Public License version
    8.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    8.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    8.23 + *
    8.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    8.25 + * or visit www.oracle.com if you need additional information or have any
    8.26 + * questions.
    8.27 + */
    8.28 +
    8.29 +package java.lang.invoke;
    8.30 +
    8.31 +import java.security.*;
    8.32 +import java.lang.reflect.*;
    8.33 +import java.lang.invoke.MethodHandleNatives.Constants;
    8.34 +import java.lang.invoke.MethodHandles.Lookup;
    8.35 +import static java.lang.invoke.MethodHandleStatics.*;
    8.36 +
    8.37 +/*
    8.38 + * Auxiliary to MethodHandleInfo, wants to nest in MethodHandleInfo but must be non-public.
    8.39 + */
    8.40 +/*non-public*/
    8.41 +final
    8.42 +class InfoFromMemberName implements MethodHandleInfo {
    8.43 +    private final MemberName member;
    8.44 +    private final int referenceKind;
    8.45 +
    8.46 +    InfoFromMemberName(Lookup lookup, MemberName member, byte referenceKind) {
    8.47 +        assert(member.isResolved() || member.isMethodHandleInvoke());
    8.48 +        assert(member.referenceKindIsConsistentWith(referenceKind));
    8.49 +        this.member = member;
    8.50 +        this.referenceKind = referenceKind;
    8.51 +    }
    8.52 +
    8.53 +    @Override
    8.54 +    public Class<?> getDeclaringClass() {
    8.55 +        return member.getDeclaringClass();
    8.56 +    }
    8.57 +
    8.58 +    @Override
    8.59 +    public String getName() {
    8.60 +        return member.getName();
    8.61 +    }
    8.62 +
    8.63 +    @Override
    8.64 +    public MethodType getMethodType() {
    8.65 +        return member.getMethodOrFieldType();
    8.66 +    }
    8.67 +
    8.68 +    @Override
    8.69 +    public int getModifiers() {
    8.70 +        return member.getModifiers();
    8.71 +    }
    8.72 +
    8.73 +    @Override
    8.74 +    public int getReferenceKind() {
    8.75 +        return referenceKind;
    8.76 +    }
    8.77 +
    8.78 +    @Override
    8.79 +    public String toString() {
    8.80 +        return MethodHandleInfo.toString(getReferenceKind(), getDeclaringClass(), getName(), getMethodType());
    8.81 +    }
    8.82 +
    8.83 +    @Override
    8.84 +    public <T extends Member> T reflectAs(Class<T> expected, Lookup lookup) {
    8.85 +        if (member.isMethodHandleInvoke() && !member.isVarargs()) {
    8.86 +            // This member is an instance of a signature-polymorphic method, which cannot be reflected
    8.87 +            // A method handle invoker can come in either of two forms:
    8.88 +            // A generic placeholder (present in the source code, and varargs)
    8.89 +            // and a signature-polymorphic instance (synthetic and not varargs).
    8.90 +            // For more information see comments on {@link MethodHandleNatives#linkMethod}.
    8.91 +            throw new IllegalArgumentException("cannot reflect signature polymorphic method");
    8.92 +        }
    8.93 +        Member mem = AccessController.doPrivileged(new PrivilegedAction<Member>() {
    8.94 +                public Member run() {
    8.95 +                    try {
    8.96 +                        return reflectUnchecked();
    8.97 +                    } catch (ReflectiveOperationException ex) {
    8.98 +                        throw new IllegalArgumentException(ex);
    8.99 +                    }
   8.100 +                }
   8.101 +            });
   8.102 +        try {
   8.103 +            Class<?> defc = getDeclaringClass();
   8.104 +            byte refKind = (byte) getReferenceKind();
   8.105 +            lookup.checkAccess(refKind, defc, convertToMemberName(refKind, mem));
   8.106 +        } catch (IllegalAccessException ex) {
   8.107 +            throw new IllegalArgumentException(ex);
   8.108 +        }
   8.109 +        return expected.cast(mem);
   8.110 +    }
   8.111 +
   8.112 +    private Member reflectUnchecked() throws ReflectiveOperationException {
   8.113 +        byte refKind = (byte) getReferenceKind();
   8.114 +        Class<?> defc = getDeclaringClass();
   8.115 +        boolean isPublic = Modifier.isPublic(getModifiers());
   8.116 +        if (MethodHandleNatives.refKindIsMethod(refKind)) {
   8.117 +            if (isPublic)
   8.118 +                return defc.getMethod(getName(), getMethodType().parameterArray());
   8.119 +            else
   8.120 +                return defc.getDeclaredMethod(getName(), getMethodType().parameterArray());
   8.121 +        } else if (MethodHandleNatives.refKindIsConstructor(refKind)) {
   8.122 +            if (isPublic)
   8.123 +                return defc.getConstructor(getMethodType().parameterArray());
   8.124 +            else
   8.125 +                return defc.getDeclaredConstructor(getMethodType().parameterArray());
   8.126 +        } else if (MethodHandleNatives.refKindIsField(refKind)) {
   8.127 +            if (isPublic)
   8.128 +                return defc.getField(getName());
   8.129 +            else
   8.130 +                return defc.getDeclaredField(getName());
   8.131 +        } else {
   8.132 +            throw new IllegalArgumentException("referenceKind="+refKind);
   8.133 +        }
   8.134 +    }
   8.135 +
   8.136 +    private static MemberName convertToMemberName(byte refKind, Member mem) throws IllegalAccessException {
   8.137 +        if (mem instanceof Method) {
   8.138 +            boolean wantSpecial = (refKind == REF_invokeSpecial);
   8.139 +            return new MemberName((Method) mem, wantSpecial);
   8.140 +        } else if (mem instanceof Constructor) {
   8.141 +            return new MemberName((Constructor) mem);
   8.142 +        } else if (mem instanceof Field) {
   8.143 +            boolean isSetter = (refKind == REF_putField || refKind == REF_putStatic);
   8.144 +            return new MemberName((Field) mem, isSetter);
   8.145 +        }
   8.146 +        throw new InternalError(mem.getClass().getName());
   8.147 +    }
   8.148 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/InnerClassLambdaMetafactory.java	Sat Aug 09 11:12:05 2014 +0200
     9.3 @@ -0,0 +1,561 @@
     9.4 +/*
     9.5 + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
     9.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     9.7 + *
     9.8 + * This code is free software; you can redistribute it and/or modify it
     9.9 + * under the terms of the GNU General Public License version 2 only, as
    9.10 + * published by the Free Software Foundation.  Oracle designates this
    9.11 + * particular file as subject to the "Classpath" exception as provided
    9.12 + * by Oracle in the LICENSE file that accompanied this code.
    9.13 + *
    9.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    9.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    9.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    9.17 + * version 2 for more details (a copy is included in the LICENSE file that
    9.18 + * accompanied this code).
    9.19 + *
    9.20 + * You should have received a copy of the GNU General Public License version
    9.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    9.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    9.23 + *
    9.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    9.25 + * or visit www.oracle.com if you need additional information or have any
    9.26 + * questions.
    9.27 + */
    9.28 +
    9.29 +package java.lang.invoke;
    9.30 +
    9.31 +import jdk.internal.org.objectweb.asm.*;
    9.32 +import sun.invoke.util.BytecodeDescriptor;
    9.33 +import sun.misc.Unsafe;
    9.34 +import sun.security.action.GetPropertyAction;
    9.35 +
    9.36 +import java.io.FilePermission;
    9.37 +import java.io.Serializable;
    9.38 +import java.lang.reflect.Constructor;
    9.39 +import java.security.AccessController;
    9.40 +import java.security.PrivilegedAction;
    9.41 +import java.util.LinkedHashSet;
    9.42 +import java.util.concurrent.atomic.AtomicInteger;
    9.43 +import java.util.PropertyPermission;
    9.44 +import java.util.Set;
    9.45 +
    9.46 +import static jdk.internal.org.objectweb.asm.Opcodes.*;
    9.47 +
    9.48 +/**
    9.49 + * Lambda metafactory implementation which dynamically creates an
    9.50 + * inner-class-like class per lambda callsite.
    9.51 + *
    9.52 + * @see LambdaMetafactory
    9.53 + */
    9.54 +/* package */ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory {
    9.55 +    private static final Unsafe UNSAFE = Unsafe.getUnsafe();
    9.56 +
    9.57 +    private static final int CLASSFILE_VERSION = 52;
    9.58 +    private static final String METHOD_DESCRIPTOR_VOID = Type.getMethodDescriptor(Type.VOID_TYPE);
    9.59 +    private static final String JAVA_LANG_OBJECT = "java/lang/Object";
    9.60 +    private static final String NAME_CTOR = "<init>";
    9.61 +    private static final String NAME_FACTORY = "get$Lambda";
    9.62 +
    9.63 +    //Serialization support
    9.64 +    private static final String NAME_SERIALIZED_LAMBDA = "java/lang/invoke/SerializedLambda";
    9.65 +    private static final String NAME_NOT_SERIALIZABLE_EXCEPTION = "java/io/NotSerializableException";
    9.66 +    private static final String DESCR_METHOD_WRITE_REPLACE = "()Ljava/lang/Object;";
    9.67 +    private static final String DESCR_METHOD_WRITE_OBJECT = "(Ljava/io/ObjectOutputStream;)V";
    9.68 +    private static final String DESCR_METHOD_READ_OBJECT = "(Ljava/io/ObjectInputStream;)V";
    9.69 +    private static final String NAME_METHOD_WRITE_REPLACE = "writeReplace";
    9.70 +    private static final String NAME_METHOD_READ_OBJECT = "readObject";
    9.71 +    private static final String NAME_METHOD_WRITE_OBJECT = "writeObject";
    9.72 +    private static final String DESCR_CTOR_SERIALIZED_LAMBDA
    9.73 +            = MethodType.methodType(void.class,
    9.74 +                                    Class.class,
    9.75 +                                    String.class, String.class, String.class,
    9.76 +                                    int.class, String.class, String.class, String.class,
    9.77 +                                    String.class,
    9.78 +                                    Object[].class).toMethodDescriptorString();
    9.79 +    private static final String DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION
    9.80 +            = MethodType.methodType(void.class, String.class).toMethodDescriptorString();
    9.81 +    private static final String[] SER_HOSTILE_EXCEPTIONS = new String[] {NAME_NOT_SERIALIZABLE_EXCEPTION};
    9.82 +
    9.83 +
    9.84 +    private static final String[] EMPTY_STRING_ARRAY = new String[0];
    9.85 +
    9.86 +    // Used to ensure that each spun class name is unique
    9.87 +    private static final AtomicInteger counter = new AtomicInteger(0);
    9.88 +
    9.89 +    // For dumping generated classes to disk, for debugging purposes
    9.90 +    private static final ProxyClassesDumper dumper;
    9.91 +
    9.92 +    static {
    9.93 +        final String key = "jdk.internal.lambda.dumpProxyClasses";
    9.94 +        String path = AccessController.doPrivileged(
    9.95 +                new GetPropertyAction(key), null,
    9.96 +                new PropertyPermission(key , "read"));
    9.97 +        dumper = (null == path) ? null : ProxyClassesDumper.getInstance(path);
    9.98 +    }
    9.99 +
   9.100 +    // See context values in AbstractValidatingLambdaMetafactory
   9.101 +    private final String implMethodClassName;        // Name of type containing implementation "CC"
   9.102 +    private final String implMethodName;             // Name of implementation method "impl"
   9.103 +    private final String implMethodDesc;             // Type descriptor for implementation methods "(I)Ljava/lang/String;"
   9.104 +    private final Class<?> implMethodReturnClass;    // class for implementaion method return type "Ljava/lang/String;"
   9.105 +    private final MethodType constructorType;        // Generated class constructor type "(CC)void"
   9.106 +    private final ClassWriter cw;                    // ASM class writer
   9.107 +    private final String[] argNames;                 // Generated names for the constructor arguments
   9.108 +    private final String[] argDescs;                 // Type descriptors for the constructor arguments
   9.109 +    private final String lambdaClassName;            // Generated name for the generated class "X$$Lambda$1"
   9.110 +
   9.111 +    /**
   9.112 +     * General meta-factory constructor, supporting both standard cases and
   9.113 +     * allowing for uncommon options such as serialization or bridging.
   9.114 +     *
   9.115 +     * @param caller Stacked automatically by VM; represents a lookup context
   9.116 +     *               with the accessibility privileges of the caller.
   9.117 +     * @param invokedType Stacked automatically by VM; the signature of the
   9.118 +     *                    invoked method, which includes the expected static
   9.119 +     *                    type of the returned lambda object, and the static
   9.120 +     *                    types of the captured arguments for the lambda.  In
   9.121 +     *                    the event that the implementation method is an
   9.122 +     *                    instance method, the first argument in the invocation
   9.123 +     *                    signature will correspond to the receiver.
   9.124 +     * @param samMethodName Name of the method in the functional interface to
   9.125 +     *                      which the lambda or method reference is being
   9.126 +     *                      converted, represented as a String.
   9.127 +     * @param samMethodType Type of the method in the functional interface to
   9.128 +     *                      which the lambda or method reference is being
   9.129 +     *                      converted, represented as a MethodType.
   9.130 +     * @param implMethod The implementation method which should be called (with
   9.131 +     *                   suitable adaptation of argument types, return types,
   9.132 +     *                   and adjustment for captured arguments) when methods of
   9.133 +     *                   the resulting functional interface instance are invoked.
   9.134 +     * @param instantiatedMethodType The signature of the primary functional
   9.135 +     *                               interface method after type variables are
   9.136 +     *                               substituted with their instantiation from
   9.137 +     *                               the capture site
   9.138 +     * @param isSerializable Should the lambda be made serializable?  If set,
   9.139 +     *                       either the target type or one of the additional SAM
   9.140 +     *                       types must extend {@code Serializable}.
   9.141 +     * @param markerInterfaces Additional interfaces which the lambda object
   9.142 +     *                       should implement.
   9.143 +     * @param additionalBridges Method types for additional signatures to be
   9.144 +     *                          bridged to the implementation method
   9.145 +     * @throws LambdaConversionException If any of the meta-factory protocol
   9.146 +     * invariants are violated
   9.147 +     */
   9.148 +    public InnerClassLambdaMetafactory(MethodHandles.Lookup caller,
   9.149 +                                       MethodType invokedType,
   9.150 +                                       String samMethodName,
   9.151 +                                       MethodType samMethodType,
   9.152 +                                       MethodHandle implMethod,
   9.153 +                                       MethodType instantiatedMethodType,
   9.154 +                                       boolean isSerializable,
   9.155 +                                       Class<?>[] markerInterfaces,
   9.156 +                                       MethodType[] additionalBridges)
   9.157 +            throws LambdaConversionException {
   9.158 +        super(caller, invokedType, samMethodName, samMethodType,
   9.159 +              implMethod, instantiatedMethodType,
   9.160 +              isSerializable, markerInterfaces, additionalBridges);
   9.161 +        implMethodClassName = implDefiningClass.getName().replace('.', '/');
   9.162 +        implMethodName = implInfo.getName();
   9.163 +        implMethodDesc = implMethodType.toMethodDescriptorString();
   9.164 +        implMethodReturnClass = (implKind == MethodHandleInfo.REF_newInvokeSpecial)
   9.165 +                ? implDefiningClass
   9.166 +                : implMethodType.returnType();
   9.167 +        constructorType = invokedType.changeReturnType(Void.TYPE);
   9.168 +        lambdaClassName = targetClass.getName().replace('.', '/') + "$$Lambda$" + counter.incrementAndGet();
   9.169 +        cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
   9.170 +        int parameterCount = invokedType.parameterCount();
   9.171 +        if (parameterCount > 0) {
   9.172 +            argNames = new String[parameterCount];
   9.173 +            argDescs = new String[parameterCount];
   9.174 +            for (int i = 0; i < parameterCount; i++) {
   9.175 +                argNames[i] = "arg$" + (i + 1);
   9.176 +                argDescs[i] = BytecodeDescriptor.unparse(invokedType.parameterType(i));
   9.177 +            }
   9.178 +        } else {
   9.179 +            argNames = argDescs = EMPTY_STRING_ARRAY;
   9.180 +        }
   9.181 +    }
   9.182 +
   9.183 +    /**
   9.184 +     * Build the CallSite. Generate a class file which implements the functional
   9.185 +     * interface, define the class, if there are no parameters create an instance
   9.186 +     * of the class which the CallSite will return, otherwise, generate handles
   9.187 +     * which will call the class' constructor.
   9.188 +     *
   9.189 +     * @return a CallSite, which, when invoked, will return an instance of the
   9.190 +     * functional interface
   9.191 +     * @throws ReflectiveOperationException
   9.192 +     * @throws LambdaConversionException If properly formed functional interface
   9.193 +     * is not found
   9.194 +     */
   9.195 +    @Override
   9.196 +    CallSite buildCallSite() throws LambdaConversionException {
   9.197 +        final Class<?> innerClass = spinInnerClass();
   9.198 +        if (invokedType.parameterCount() == 0) {
   9.199 +            final Constructor[] ctrs = AccessController.doPrivileged(
   9.200 +                    new PrivilegedAction<Constructor[]>() {
   9.201 +                @Override
   9.202 +                public Constructor[] run() {
   9.203 +                    Constructor<?>[] ctrs = innerClass.getDeclaredConstructors();
   9.204 +                    if (ctrs.length == 1) {
   9.205 +                        // The lambda implementing inner class constructor is private, set
   9.206 +                        // it accessible (by us) before creating the constant sole instance
   9.207 +                        ctrs[0].setAccessible(true);
   9.208 +                    }
   9.209 +                    return ctrs;
   9.210 +                }
   9.211 +                    });
   9.212 +            if (ctrs.length != 1) {
   9.213 +                throw new LambdaConversionException("Expected one lambda constructor for "
   9.214 +                        + innerClass.getCanonicalName() + ", got " + ctrs.length);
   9.215 +            }
   9.216 +
   9.217 +            try {
   9.218 +                Object inst = ctrs[0].newInstance();
   9.219 +                return new ConstantCallSite(MethodHandles.constant(samBase, inst));
   9.220 +            }
   9.221 +            catch (ReflectiveOperationException e) {
   9.222 +                throw new LambdaConversionException("Exception instantiating lambda object", e);
   9.223 +            }
   9.224 +        } else {
   9.225 +            try {
   9.226 +                UNSAFE.ensureClassInitialized(innerClass);
   9.227 +                return new ConstantCallSite(
   9.228 +                        MethodHandles.Lookup.IMPL_LOOKUP
   9.229 +                             .findStatic(innerClass, NAME_FACTORY, invokedType));
   9.230 +            }
   9.231 +            catch (ReflectiveOperationException e) {
   9.232 +                throw new LambdaConversionException("Exception finding constructor", e);
   9.233 +            }
   9.234 +        }
   9.235 +    }
   9.236 +
   9.237 +    /**
   9.238 +     * Generate a class file which implements the functional
   9.239 +     * interface, define and return the class.
   9.240 +     *
   9.241 +     * @implNote The class that is generated does not include signature
   9.242 +     * information for exceptions that may be present on the SAM method.
   9.243 +     * This is to reduce classfile size, and is harmless as checked exceptions
   9.244 +     * are erased anyway, no one will ever compile against this classfile,
   9.245 +     * and we make no guarantees about the reflective properties of lambda
   9.246 +     * objects.
   9.247 +     *
   9.248 +     * @return a Class which implements the functional interface
   9.249 +     * @throws LambdaConversionException If properly formed functional interface
   9.250 +     * is not found
   9.251 +     */
   9.252 +    private Class<?> spinInnerClass() throws LambdaConversionException {
   9.253 +        String[] interfaces;
   9.254 +        String samIntf = samBase.getName().replace('.', '/');
   9.255 +        boolean accidentallySerializable = !isSerializable && Serializable.class.isAssignableFrom(samBase);
   9.256 +        if (markerInterfaces.length == 0) {
   9.257 +            interfaces = new String[]{samIntf};
   9.258 +        } else {
   9.259 +            // Assure no duplicate interfaces (ClassFormatError)
   9.260 +            Set<String> itfs = new LinkedHashSet<>(markerInterfaces.length + 1);
   9.261 +            itfs.add(samIntf);
   9.262 +            for (Class<?> markerInterface : markerInterfaces) {
   9.263 +                itfs.add(markerInterface.getName().replace('.', '/'));
   9.264 +                accidentallySerializable |= !isSerializable && Serializable.class.isAssignableFrom(markerInterface);
   9.265 +            }
   9.266 +            interfaces = itfs.toArray(new String[itfs.size()]);
   9.267 +        }
   9.268 +
   9.269 +        cw.visit(CLASSFILE_VERSION, ACC_SUPER + ACC_FINAL + ACC_SYNTHETIC,
   9.270 +                 lambdaClassName, null,
   9.271 +                 JAVA_LANG_OBJECT, interfaces);
   9.272 +
   9.273 +        // Generate final fields to be filled in by constructor
   9.274 +        for (int i = 0; i < argDescs.length; i++) {
   9.275 +            FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_FINAL,
   9.276 +                                            argNames[i],
   9.277 +                                            argDescs[i],
   9.278 +                                            null, null);
   9.279 +            fv.visitEnd();
   9.280 +        }
   9.281 +
   9.282 +        generateConstructor();
   9.283 +
   9.284 +        if (invokedType.parameterCount() != 0) {
   9.285 +            generateFactory();
   9.286 +        }
   9.287 +
   9.288 +        // Forward the SAM method
   9.289 +        MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, samMethodName,
   9.290 +                                          samMethodType.toMethodDescriptorString(), null, null);
   9.291 +        new ForwardingMethodGenerator(mv).generate(samMethodType);
   9.292 +
   9.293 +        // Forward the bridges
   9.294 +        if (additionalBridges != null) {
   9.295 +            for (MethodType mt : additionalBridges) {
   9.296 +                mv = cw.visitMethod(ACC_PUBLIC|ACC_BRIDGE, samMethodName,
   9.297 +                                    mt.toMethodDescriptorString(), null, null);
   9.298 +                new ForwardingMethodGenerator(mv).generate(mt);
   9.299 +            }
   9.300 +        }
   9.301 +
   9.302 +        if (isSerializable)
   9.303 +            generateSerializationFriendlyMethods();
   9.304 +        else if (accidentallySerializable)
   9.305 +            generateSerializationHostileMethods();
   9.306 +
   9.307 +        cw.visitEnd();
   9.308 +
   9.309 +        // Define the generated class in this VM.
   9.310 +
   9.311 +        final byte[] classBytes = cw.toByteArray();
   9.312 +
   9.313 +        // If requested, dump out to a file for debugging purposes
   9.314 +        if (dumper != null) {
   9.315 +            AccessController.doPrivileged(new PrivilegedAction<Void>() {
   9.316 +                @Override
   9.317 +                public Void run() {
   9.318 +                    dumper.dumpClass(lambdaClassName, classBytes);
   9.319 +                    return null;
   9.320 +                }
   9.321 +            }, null,
   9.322 +            new FilePermission("<<ALL FILES>>", "read, write"),
   9.323 +            // createDirectories may need it
   9.324 +            new PropertyPermission("user.dir", "read"));
   9.325 +        }
   9.326 +
   9.327 +        return UNSAFE.defineAnonymousClass(targetClass, classBytes, null);
   9.328 +    }
   9.329 +
   9.330 +    /**
   9.331 +     * Generate the factory method for the class
   9.332 +     */
   9.333 +    private void generateFactory() {
   9.334 +        MethodVisitor m = cw.visitMethod(ACC_PRIVATE | ACC_STATIC, NAME_FACTORY, invokedType.toMethodDescriptorString(), null, null);
   9.335 +        m.visitCode();
   9.336 +        m.visitTypeInsn(NEW, lambdaClassName);
   9.337 +        m.visitInsn(Opcodes.DUP);
   9.338 +        int parameterCount = invokedType.parameterCount();
   9.339 +        for (int typeIndex = 0, varIndex = 0; typeIndex < parameterCount; typeIndex++) {
   9.340 +            Class<?> argType = invokedType.parameterType(typeIndex);
   9.341 +            m.visitVarInsn(getLoadOpcode(argType), varIndex);
   9.342 +            varIndex += getParameterSize(argType);
   9.343 +        }
   9.344 +        m.visitMethodInsn(INVOKESPECIAL, lambdaClassName, NAME_CTOR, constructorType.toMethodDescriptorString());
   9.345 +        m.visitInsn(ARETURN);
   9.346 +        m.visitMaxs(-1, -1);
   9.347 +        m.visitEnd();
   9.348 +    }
   9.349 +
   9.350 +    /**
   9.351 +     * Generate the constructor for the class
   9.352 +     */
   9.353 +    private void generateConstructor() {
   9.354 +        // Generate constructor
   9.355 +        MethodVisitor ctor = cw.visitMethod(ACC_PRIVATE, NAME_CTOR,
   9.356 +                                            constructorType.toMethodDescriptorString(), null, null);
   9.357 +        ctor.visitCode();
   9.358 +        ctor.visitVarInsn(ALOAD, 0);
   9.359 +        ctor.visitMethodInsn(INVOKESPECIAL, JAVA_LANG_OBJECT, NAME_CTOR,
   9.360 +                             METHOD_DESCRIPTOR_VOID);
   9.361 +        int parameterCount = invokedType.parameterCount();
   9.362 +        for (int i = 0, lvIndex = 0; i < parameterCount; i++) {
   9.363 +            ctor.visitVarInsn(ALOAD, 0);
   9.364 +            Class<?> argType = invokedType.parameterType(i);
   9.365 +            ctor.visitVarInsn(getLoadOpcode(argType), lvIndex + 1);
   9.366 +            lvIndex += getParameterSize(argType);
   9.367 +            ctor.visitFieldInsn(PUTFIELD, lambdaClassName, argNames[i], argDescs[i]);
   9.368 +        }
   9.369 +        ctor.visitInsn(RETURN);
   9.370 +        // Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored
   9.371 +        ctor.visitMaxs(-1, -1);
   9.372 +        ctor.visitEnd();
   9.373 +    }
   9.374 +
   9.375 +    /**
   9.376 +     * Generate a writeReplace method that supports serialization
   9.377 +     */
   9.378 +    private void generateSerializationFriendlyMethods() {
   9.379 +        TypeConvertingMethodAdapter mv
   9.380 +                = new TypeConvertingMethodAdapter(
   9.381 +                    cw.visitMethod(ACC_PRIVATE + ACC_FINAL,
   9.382 +                    NAME_METHOD_WRITE_REPLACE, DESCR_METHOD_WRITE_REPLACE,
   9.383 +                    null, null));
   9.384 +
   9.385 +        mv.visitCode();
   9.386 +        mv.visitTypeInsn(NEW, NAME_SERIALIZED_LAMBDA);
   9.387 +        mv.visitInsn(DUP);
   9.388 +        mv.visitLdcInsn(Type.getType(targetClass));
   9.389 +        mv.visitLdcInsn(invokedType.returnType().getName().replace('.', '/'));
   9.390 +        mv.visitLdcInsn(samMethodName);
   9.391 +        mv.visitLdcInsn(samMethodType.toMethodDescriptorString());
   9.392 +        mv.visitLdcInsn(implInfo.getReferenceKind());
   9.393 +        mv.visitLdcInsn(implInfo.getDeclaringClass().getName().replace('.', '/'));
   9.394 +        mv.visitLdcInsn(implInfo.getName());
   9.395 +        mv.visitLdcInsn(implInfo.getMethodType().toMethodDescriptorString());
   9.396 +        mv.visitLdcInsn(instantiatedMethodType.toMethodDescriptorString());
   9.397 +        mv.iconst(argDescs.length);
   9.398 +        mv.visitTypeInsn(ANEWARRAY, JAVA_LANG_OBJECT);
   9.399 +        for (int i = 0; i < argDescs.length; i++) {
   9.400 +            mv.visitInsn(DUP);
   9.401 +            mv.iconst(i);
   9.402 +            mv.visitVarInsn(ALOAD, 0);
   9.403 +            mv.visitFieldInsn(GETFIELD, lambdaClassName, argNames[i], argDescs[i]);
   9.404 +            mv.boxIfTypePrimitive(Type.getType(argDescs[i]));
   9.405 +            mv.visitInsn(AASTORE);
   9.406 +        }
   9.407 +        mv.visitMethodInsn(INVOKESPECIAL, NAME_SERIALIZED_LAMBDA, NAME_CTOR,
   9.408 +                DESCR_CTOR_SERIALIZED_LAMBDA);
   9.409 +        mv.visitInsn(ARETURN);
   9.410 +        // Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored
   9.411 +        mv.visitMaxs(-1, -1);
   9.412 +        mv.visitEnd();
   9.413 +    }
   9.414 +
   9.415 +    /**
   9.416 +     * Generate a readObject/writeObject method that is hostile to serialization
   9.417 +     */
   9.418 +    private void generateSerializationHostileMethods() {
   9.419 +        MethodVisitor mv = cw.visitMethod(ACC_PRIVATE + ACC_FINAL,
   9.420 +                                          NAME_METHOD_WRITE_OBJECT, DESCR_METHOD_WRITE_OBJECT,
   9.421 +                                          null, SER_HOSTILE_EXCEPTIONS);
   9.422 +        mv.visitCode();
   9.423 +        mv.visitTypeInsn(NEW, NAME_NOT_SERIALIZABLE_EXCEPTION);
   9.424 +        mv.visitInsn(DUP);
   9.425 +        mv.visitLdcInsn("Non-serializable lambda");
   9.426 +        mv.visitMethodInsn(INVOKESPECIAL, NAME_NOT_SERIALIZABLE_EXCEPTION, NAME_CTOR,
   9.427 +                           DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION);
   9.428 +        mv.visitInsn(ATHROW);
   9.429 +        mv.visitMaxs(-1, -1);
   9.430 +        mv.visitEnd();
   9.431 +
   9.432 +        mv = cw.visitMethod(ACC_PRIVATE + ACC_FINAL,
   9.433 +                            NAME_METHOD_READ_OBJECT, DESCR_METHOD_READ_OBJECT,
   9.434 +                            null, SER_HOSTILE_EXCEPTIONS);
   9.435 +        mv.visitCode();
   9.436 +        mv.visitTypeInsn(NEW, NAME_NOT_SERIALIZABLE_EXCEPTION);
   9.437 +        mv.visitInsn(DUP);
   9.438 +        mv.visitLdcInsn("Non-serializable lambda");
   9.439 +        mv.visitMethodInsn(INVOKESPECIAL, NAME_NOT_SERIALIZABLE_EXCEPTION, NAME_CTOR,
   9.440 +                           DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION);
   9.441 +        mv.visitInsn(ATHROW);
   9.442 +        mv.visitMaxs(-1, -1);
   9.443 +        mv.visitEnd();
   9.444 +    }
   9.445 +
   9.446 +    /**
   9.447 +     * This class generates a method body which calls the lambda implementation
   9.448 +     * method, converting arguments, as needed.
   9.449 +     */
   9.450 +    private class ForwardingMethodGenerator extends TypeConvertingMethodAdapter {
   9.451 +
   9.452 +        ForwardingMethodGenerator(MethodVisitor mv) {
   9.453 +            super(mv);
   9.454 +        }
   9.455 +
   9.456 +        void generate(MethodType methodType) {
   9.457 +            visitCode();
   9.458 +
   9.459 +            if (implKind == MethodHandleInfo.REF_newInvokeSpecial) {
   9.460 +                visitTypeInsn(NEW, implMethodClassName);
   9.461 +                visitInsn(DUP);
   9.462 +            }
   9.463 +            for (int i = 0; i < argNames.length; i++) {
   9.464 +                visitVarInsn(ALOAD, 0);
   9.465 +                visitFieldInsn(GETFIELD, lambdaClassName, argNames[i], argDescs[i]);
   9.466 +            }
   9.467 +
   9.468 +            convertArgumentTypes(methodType);
   9.469 +
   9.470 +            // Invoke the method we want to forward to
   9.471 +            visitMethodInsn(invocationOpcode(), implMethodClassName,
   9.472 +                            implMethodName, implMethodDesc,
   9.473 +                            implDefiningClass.isInterface());
   9.474 +
   9.475 +            // Convert the return value (if any) and return it
   9.476 +            // Note: if adapting from non-void to void, the 'return'
   9.477 +            // instruction will pop the unneeded result
   9.478 +            Class<?> samReturnClass = methodType.returnType();
   9.479 +            convertType(implMethodReturnClass, samReturnClass, samReturnClass);
   9.480 +            visitInsn(getReturnOpcode(samReturnClass));
   9.481 +            // Maxs computed by ClassWriter.COMPUTE_MAXS,these arguments ignored
   9.482 +            visitMaxs(-1, -1);
   9.483 +            visitEnd();
   9.484 +        }
   9.485 +
   9.486 +        private void convertArgumentTypes(MethodType samType) {
   9.487 +            int lvIndex = 0;
   9.488 +            boolean samIncludesReceiver = implIsInstanceMethod &&
   9.489 +                                                   invokedType.parameterCount() == 0;
   9.490 +            int samReceiverLength = samIncludesReceiver ? 1 : 0;
   9.491 +            if (samIncludesReceiver) {
   9.492 +                // push receiver
   9.493 +                Class<?> rcvrType = samType.parameterType(0);
   9.494 +                visitVarInsn(getLoadOpcode(rcvrType), lvIndex + 1);
   9.495 +                lvIndex += getParameterSize(rcvrType);
   9.496 +                convertType(rcvrType, implDefiningClass, instantiatedMethodType.parameterType(0));
   9.497 +            }
   9.498 +            int samParametersLength = samType.parameterCount();
   9.499 +            int argOffset = implMethodType.parameterCount() - samParametersLength;
   9.500 +            for (int i = samReceiverLength; i < samParametersLength; i++) {
   9.501 +                Class<?> argType = samType.parameterType(i);
   9.502 +                visitVarInsn(getLoadOpcode(argType), lvIndex + 1);
   9.503 +                lvIndex += getParameterSize(argType);
   9.504 +                convertType(argType, implMethodType.parameterType(argOffset + i), instantiatedMethodType.parameterType(i));
   9.505 +            }
   9.506 +        }
   9.507 +
   9.508 +        private int invocationOpcode() throws InternalError {
   9.509 +            switch (implKind) {
   9.510 +                case MethodHandleInfo.REF_invokeStatic:
   9.511 +                    return INVOKESTATIC;
   9.512 +                case MethodHandleInfo.REF_newInvokeSpecial:
   9.513 +                    return INVOKESPECIAL;
   9.514 +                 case MethodHandleInfo.REF_invokeVirtual:
   9.515 +                    return INVOKEVIRTUAL;
   9.516 +                case MethodHandleInfo.REF_invokeInterface:
   9.517 +                    return INVOKEINTERFACE;
   9.518 +                case MethodHandleInfo.REF_invokeSpecial:
   9.519 +                    return INVOKESPECIAL;
   9.520 +                default:
   9.521 +                    throw new InternalError("Unexpected invocation kind: " + implKind);
   9.522 +            }
   9.523 +        }
   9.524 +    }
   9.525 +
   9.526 +    static int getParameterSize(Class<?> c) {
   9.527 +        if (c == Void.TYPE) {
   9.528 +            return 0;
   9.529 +        } else if (c == Long.TYPE || c == Double.TYPE) {
   9.530 +            return 2;
   9.531 +        }
   9.532 +        return 1;
   9.533 +    }
   9.534 +
   9.535 +    static int getLoadOpcode(Class<?> c) {
   9.536 +        if(c == Void.TYPE) {
   9.537 +            throw new InternalError("Unexpected void type of load opcode");
   9.538 +        }
   9.539 +        return ILOAD + getOpcodeOffset(c);
   9.540 +    }
   9.541 +
   9.542 +    static int getReturnOpcode(Class<?> c) {
   9.543 +        if(c == Void.TYPE) {
   9.544 +            return RETURN;
   9.545 +        }
   9.546 +        return IRETURN + getOpcodeOffset(c);
   9.547 +    }
   9.548 +
   9.549 +    private static int getOpcodeOffset(Class<?> c) {
   9.550 +        if (c.isPrimitive()) {
   9.551 +            if (c == Long.TYPE) {
   9.552 +                return 1;
   9.553 +            } else if (c == Float.TYPE) {
   9.554 +                return 2;
   9.555 +            } else if (c == Double.TYPE) {
   9.556 +                return 3;
   9.557 +            }
   9.558 +            return 0;
   9.559 +        } else {
   9.560 +            return 4;
   9.561 +        }
   9.562 +    }
   9.563 +
   9.564 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/InvokeDynamic.java	Sat Aug 09 11:12:05 2014 +0200
    10.3 @@ -0,0 +1,33 @@
    10.4 +/*
    10.5 + * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
    10.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    10.7 + *
    10.8 + * This code is free software; you can redistribute it and/or modify it
    10.9 + * under the terms of the GNU General Public License version 2 only, as
   10.10 + * published by the Free Software Foundation.  Oracle designates this
   10.11 + * particular file as subject to the "Classpath" exception as provided
   10.12 + * by Oracle in the LICENSE file that accompanied this code.
   10.13 + *
   10.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   10.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   10.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   10.17 + * version 2 for more details (a copy is included in the LICENSE file that
   10.18 + * accompanied this code).
   10.19 + *
   10.20 + * You should have received a copy of the GNU General Public License version
   10.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   10.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   10.23 + *
   10.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   10.25 + * or visit www.oracle.com if you need additional information or have any
   10.26 + * questions.
   10.27 + */
   10.28 +
   10.29 +package java.lang.invoke;
   10.30 +
   10.31 +/**
   10.32 + * This is a place-holder class.  Some HotSpot implementations need to see it.
   10.33 + */
   10.34 +final class InvokeDynamic {
   10.35 +    private InvokeDynamic() { throw new InternalError(); }  // do not instantiate
   10.36 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/InvokerBytecodeGenerator.java	Sat Aug 09 11:12:05 2014 +0200
    11.3 @@ -0,0 +1,1052 @@
    11.4 +/*
    11.5 + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
    11.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    11.7 + *
    11.8 + * This code is free software; you can redistribute it and/or modify it
    11.9 + * under the terms of the GNU General Public License version 2 only, as
   11.10 + * published by the Free Software Foundation.  Oracle designates this
   11.11 + * particular file as subject to the "Classpath" exception as provided
   11.12 + * by Oracle in the LICENSE file that accompanied this code.
   11.13 + *
   11.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   11.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   11.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   11.17 + * version 2 for more details (a copy is included in the LICENSE file that
   11.18 + * accompanied this code).
   11.19 + *
   11.20 + * You should have received a copy of the GNU General Public License version
   11.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   11.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   11.23 + *
   11.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   11.25 + * or visit www.oracle.com if you need additional information or have any
   11.26 + * questions.
   11.27 + */
   11.28 +
   11.29 +package java.lang.invoke;
   11.30 +
   11.31 +import sun.invoke.util.VerifyAccess;
   11.32 +import java.lang.invoke.LambdaForm.Name;
   11.33 +import java.lang.invoke.MethodHandles.Lookup;
   11.34 +
   11.35 +import sun.invoke.util.Wrapper;
   11.36 +
   11.37 +import java.io.*;
   11.38 +import java.util.*;
   11.39 +
   11.40 +import jdk.internal.org.objectweb.asm.*;
   11.41 +
   11.42 +import java.lang.reflect.*;
   11.43 +import static java.lang.invoke.MethodHandleStatics.*;
   11.44 +import static java.lang.invoke.MethodHandleNatives.Constants.*;
   11.45 +import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
   11.46 +import sun.invoke.util.ValueConversions;
   11.47 +import sun.invoke.util.VerifyType;
   11.48 +
   11.49 +/**
   11.50 + * Code generation backend for LambdaForm.
   11.51 + * <p>
   11.52 + * @author John Rose, JSR 292 EG
   11.53 + */
   11.54 +class InvokerBytecodeGenerator {
   11.55 +    /** Define class names for convenience. */
   11.56 +    private static final String MH      = "java/lang/invoke/MethodHandle";
   11.57 +    private static final String BMH     = "java/lang/invoke/BoundMethodHandle";
   11.58 +    private static final String LF      = "java/lang/invoke/LambdaForm";
   11.59 +    private static final String LFN     = "java/lang/invoke/LambdaForm$Name";
   11.60 +    private static final String CLS     = "java/lang/Class";
   11.61 +    private static final String OBJ     = "java/lang/Object";
   11.62 +    private static final String OBJARY  = "[Ljava/lang/Object;";
   11.63 +
   11.64 +    private static final String LF_SIG  = "L" + LF + ";";
   11.65 +    private static final String LFN_SIG = "L" + LFN + ";";
   11.66 +    private static final String LL_SIG  = "(L" + OBJ + ";)L" + OBJ + ";";
   11.67 +
   11.68 +    /** Name of its super class*/
   11.69 +    private static final String superName = LF;
   11.70 +
   11.71 +    /** Name of new class */
   11.72 +    private final String className;
   11.73 +
   11.74 +    /** Name of the source file (for stack trace printing). */
   11.75 +    private final String sourceFile;
   11.76 +
   11.77 +    private final LambdaForm lambdaForm;
   11.78 +    private final String     invokerName;
   11.79 +    private final MethodType invokerType;
   11.80 +    private final int[] localsMap;
   11.81 +
   11.82 +    /** ASM bytecode generation. */
   11.83 +    private ClassWriter cw;
   11.84 +    private MethodVisitor mv;
   11.85 +
   11.86 +    private static final MemberName.Factory MEMBERNAME_FACTORY = MemberName.getFactory();
   11.87 +    private static final Class<?> HOST_CLASS = LambdaForm.class;
   11.88 +
   11.89 +    private InvokerBytecodeGenerator(LambdaForm lambdaForm, int localsMapSize,
   11.90 +                                     String className, String invokerName, MethodType invokerType) {
   11.91 +        if (invokerName.contains(".")) {
   11.92 +            int p = invokerName.indexOf(".");
   11.93 +            className = invokerName.substring(0, p);
   11.94 +            invokerName = invokerName.substring(p+1);
   11.95 +        }
   11.96 +        if (DUMP_CLASS_FILES) {
   11.97 +            className = makeDumpableClassName(className);
   11.98 +        }
   11.99 +        this.className  = superName + "$" + className;
  11.100 +        this.sourceFile = "LambdaForm$" + className;
  11.101 +        this.lambdaForm = lambdaForm;
  11.102 +        this.invokerName = invokerName;
  11.103 +        this.invokerType = invokerType;
  11.104 +        this.localsMap = new int[localsMapSize];
  11.105 +    }
  11.106 +
  11.107 +    private InvokerBytecodeGenerator(String className, String invokerName, MethodType invokerType) {
  11.108 +        this(null, invokerType.parameterCount(),
  11.109 +             className, invokerName, invokerType);
  11.110 +        // Create an array to map name indexes to locals indexes.
  11.111 +        for (int i = 0; i < localsMap.length; i++) {
  11.112 +            localsMap[i] = invokerType.parameterSlotCount() - invokerType.parameterSlotDepth(i);
  11.113 +        }
  11.114 +    }
  11.115 +
  11.116 +    private InvokerBytecodeGenerator(String className, LambdaForm form, MethodType invokerType) {
  11.117 +        this(form, form.names.length,
  11.118 +             className, form.debugName, invokerType);
  11.119 +        // Create an array to map name indexes to locals indexes.
  11.120 +        Name[] names = form.names;
  11.121 +        for (int i = 0, index = 0; i < localsMap.length; i++) {
  11.122 +            localsMap[i] = index;
  11.123 +            index += Wrapper.forBasicType(names[i].type).stackSlots();
  11.124 +        }
  11.125 +    }
  11.126 +
  11.127 +
  11.128 +    /** instance counters for dumped classes */
  11.129 +    private final static HashMap<String,Integer> DUMP_CLASS_FILES_COUNTERS;
  11.130 +    /** debugging flag for saving generated class files */
  11.131 +    private final static File DUMP_CLASS_FILES_DIR;
  11.132 +
  11.133 +    static {
  11.134 +        if (DUMP_CLASS_FILES) {
  11.135 +            DUMP_CLASS_FILES_COUNTERS = new HashMap<>();
  11.136 +            try {
  11.137 +                File dumpDir = new File("DUMP_CLASS_FILES");
  11.138 +                if (!dumpDir.exists()) {
  11.139 +                    dumpDir.mkdirs();
  11.140 +                }
  11.141 +                DUMP_CLASS_FILES_DIR = dumpDir;
  11.142 +                System.out.println("Dumping class files to "+DUMP_CLASS_FILES_DIR+"/...");
  11.143 +            } catch (Exception e) {
  11.144 +                throw newInternalError(e);
  11.145 +            }
  11.146 +        } else {
  11.147 +            DUMP_CLASS_FILES_COUNTERS = null;
  11.148 +            DUMP_CLASS_FILES_DIR = null;
  11.149 +        }
  11.150 +    }
  11.151 +
  11.152 +    static void maybeDump(final String className, final byte[] classFile) {
  11.153 +        if (DUMP_CLASS_FILES) {
  11.154 +            System.out.println("dump: " + className);
  11.155 +            java.security.AccessController.doPrivileged(
  11.156 +            new java.security.PrivilegedAction<Void>() {
  11.157 +                public Void run() {
  11.158 +                    try {
  11.159 +                        String dumpName = className;
  11.160 +                        //dumpName = dumpName.replace('/', '-');
  11.161 +                        File dumpFile = new File(DUMP_CLASS_FILES_DIR, dumpName+".class");
  11.162 +                        dumpFile.getParentFile().mkdirs();
  11.163 +                        FileOutputStream file = new FileOutputStream(dumpFile);
  11.164 +                        file.write(classFile);
  11.165 +                        file.close();
  11.166 +                        return null;
  11.167 +                    } catch (IOException ex) {
  11.168 +                        throw newInternalError(ex);
  11.169 +                    }
  11.170 +                }
  11.171 +            });
  11.172 +        }
  11.173 +
  11.174 +    }
  11.175 +
  11.176 +    private static String makeDumpableClassName(String className) {
  11.177 +        Integer ctr;
  11.178 +        synchronized (DUMP_CLASS_FILES_COUNTERS) {
  11.179 +            ctr = DUMP_CLASS_FILES_COUNTERS.get(className);
  11.180 +            if (ctr == null)  ctr = 0;
  11.181 +            DUMP_CLASS_FILES_COUNTERS.put(className, ctr+1);
  11.182 +        }
  11.183 +        String sfx = ctr.toString();
  11.184 +        while (sfx.length() < 3)
  11.185 +            sfx = "0"+sfx;
  11.186 +        className += sfx;
  11.187 +        return className;
  11.188 +    }
  11.189 +
  11.190 +    class CpPatch {
  11.191 +        final int index;
  11.192 +        final String placeholder;
  11.193 +        final Object value;
  11.194 +        CpPatch(int index, String placeholder, Object value) {
  11.195 +            this.index = index;
  11.196 +            this.placeholder = placeholder;
  11.197 +            this.value = value;
  11.198 +        }
  11.199 +        public String toString() {
  11.200 +            return "CpPatch/index="+index+",placeholder="+placeholder+",value="+value;
  11.201 +        }
  11.202 +    }
  11.203 +
  11.204 +    Map<Object, CpPatch> cpPatches = new HashMap<>();
  11.205 +
  11.206 +    int cph = 0;  // for counting constant placeholders
  11.207 +
  11.208 +    String constantPlaceholder(Object arg) {
  11.209 +        String cpPlaceholder = "CONSTANT_PLACEHOLDER_" + cph++;
  11.210 +        if (DUMP_CLASS_FILES) cpPlaceholder += " <<" + arg.toString() + ">>";  // debugging aid
  11.211 +        if (cpPatches.containsKey(cpPlaceholder)) {
  11.212 +            throw new InternalError("observed CP placeholder twice: " + cpPlaceholder);
  11.213 +        }
  11.214 +        // insert placeholder in CP and remember the patch
  11.215 +        int index = cw.newConst((Object) cpPlaceholder);  // TODO check if aready in the constant pool
  11.216 +        cpPatches.put(cpPlaceholder, new CpPatch(index, cpPlaceholder, arg));
  11.217 +        return cpPlaceholder;
  11.218 +    }
  11.219 +
  11.220 +    Object[] cpPatches(byte[] classFile) {
  11.221 +        int size = getConstantPoolSize(classFile);
  11.222 +        Object[] res = new Object[size];
  11.223 +        for (CpPatch p : cpPatches.values()) {
  11.224 +            if (p.index >= size)
  11.225 +                throw new InternalError("in cpool["+size+"]: "+p+"\n"+Arrays.toString(Arrays.copyOf(classFile, 20)));
  11.226 +            res[p.index] = p.value;
  11.227 +        }
  11.228 +        return res;
  11.229 +    }
  11.230 +
  11.231 +    /**
  11.232 +     * Extract the number of constant pool entries from a given class file.
  11.233 +     *
  11.234 +     * @param classFile the bytes of the class file in question.
  11.235 +     * @return the number of entries in the constant pool.
  11.236 +     */
  11.237 +    private static int getConstantPoolSize(byte[] classFile) {
  11.238 +        // The first few bytes:
  11.239 +        // u4 magic;
  11.240 +        // u2 minor_version;
  11.241 +        // u2 major_version;
  11.242 +        // u2 constant_pool_count;
  11.243 +        return ((classFile[8] & 0xFF) << 8) | (classFile[9] & 0xFF);
  11.244 +    }
  11.245 +
  11.246 +    /**
  11.247 +     * Extract the MemberName of a newly-defined method.
  11.248 +     */
  11.249 +    private MemberName loadMethod(byte[] classFile) {
  11.250 +        Class<?> invokerClass = loadAndInitializeInvokerClass(classFile, cpPatches(classFile));
  11.251 +        return resolveInvokerMember(invokerClass, invokerName, invokerType);
  11.252 +    }
  11.253 +
  11.254 +    /**
  11.255 +     * Define a given class as anonymous class in the runtime system.
  11.256 +     */
  11.257 +    private static Class<?> loadAndInitializeInvokerClass(byte[] classBytes, Object[] patches) {
  11.258 +        Class<?> invokerClass = UNSAFE.defineAnonymousClass(HOST_CLASS, classBytes, patches);
  11.259 +        UNSAFE.ensureClassInitialized(invokerClass);  // Make sure the class is initialized; VM might complain.
  11.260 +        return invokerClass;
  11.261 +    }
  11.262 +
  11.263 +    private static MemberName resolveInvokerMember(Class<?> invokerClass, String name, MethodType type) {
  11.264 +        MemberName member = new MemberName(invokerClass, name, type, REF_invokeStatic);
  11.265 +        //System.out.println("resolveInvokerMember => "+member);
  11.266 +        //for (Method m : invokerClass.getDeclaredMethods())  System.out.println("  "+m);
  11.267 +        try {
  11.268 +            member = MEMBERNAME_FACTORY.resolveOrFail(REF_invokeStatic, member, HOST_CLASS, ReflectiveOperationException.class);
  11.269 +        } catch (ReflectiveOperationException e) {
  11.270 +            throw newInternalError(e);
  11.271 +        }
  11.272 +        //System.out.println("resolveInvokerMember => "+member);
  11.273 +        return member;
  11.274 +    }
  11.275 +
  11.276 +    /**
  11.277 +     * Set up class file generation.
  11.278 +     */
  11.279 +    private void classFilePrologue() {
  11.280 +        cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
  11.281 +        cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_SUPER, className, null, superName, null);
  11.282 +        cw.visitSource(sourceFile, null);
  11.283 +
  11.284 +        String invokerDesc = invokerType.toMethodDescriptorString();
  11.285 +        mv = cw.visitMethod(Opcodes.ACC_STATIC, invokerName, invokerDesc, null, null);
  11.286 +    }
  11.287 +
  11.288 +    /**
  11.289 +     * Tear down class file generation.
  11.290 +     */
  11.291 +    private void classFileEpilogue() {
  11.292 +        mv.visitMaxs(0, 0);
  11.293 +        mv.visitEnd();
  11.294 +    }
  11.295 +
  11.296 +    /*
  11.297 +     * Low-level emit helpers.
  11.298 +     */
  11.299 +    private void emitConst(Object con) {
  11.300 +        if (con == null) {
  11.301 +            mv.visitInsn(Opcodes.ACONST_NULL);
  11.302 +            return;
  11.303 +        }
  11.304 +        if (con instanceof Integer) {
  11.305 +            emitIconstInsn((int) con);
  11.306 +            return;
  11.307 +        }
  11.308 +        if (con instanceof Long) {
  11.309 +            long x = (long) con;
  11.310 +            if (x == (short) x) {
  11.311 +                emitIconstInsn((int) x);
  11.312 +                mv.visitInsn(Opcodes.I2L);
  11.313 +                return;
  11.314 +            }
  11.315 +        }
  11.316 +        if (con instanceof Float) {
  11.317 +            float x = (float) con;
  11.318 +            if (x == (short) x) {
  11.319 +                emitIconstInsn((int) x);
  11.320 +                mv.visitInsn(Opcodes.I2F);
  11.321 +                return;
  11.322 +            }
  11.323 +        }
  11.324 +        if (con instanceof Double) {
  11.325 +            double x = (double) con;
  11.326 +            if (x == (short) x) {
  11.327 +                emitIconstInsn((int) x);
  11.328 +                mv.visitInsn(Opcodes.I2D);
  11.329 +                return;
  11.330 +            }
  11.331 +        }
  11.332 +        if (con instanceof Boolean) {
  11.333 +            emitIconstInsn((boolean) con ? 1 : 0);
  11.334 +            return;
  11.335 +        }
  11.336 +        // fall through:
  11.337 +        mv.visitLdcInsn(con);
  11.338 +    }
  11.339 +
  11.340 +    private void emitIconstInsn(int i) {
  11.341 +        int opcode;
  11.342 +        switch (i) {
  11.343 +        case 0:  opcode = Opcodes.ICONST_0;  break;
  11.344 +        case 1:  opcode = Opcodes.ICONST_1;  break;
  11.345 +        case 2:  opcode = Opcodes.ICONST_2;  break;
  11.346 +        case 3:  opcode = Opcodes.ICONST_3;  break;
  11.347 +        case 4:  opcode = Opcodes.ICONST_4;  break;
  11.348 +        case 5:  opcode = Opcodes.ICONST_5;  break;
  11.349 +        default:
  11.350 +            if (i == (byte) i) {
  11.351 +                mv.visitIntInsn(Opcodes.BIPUSH, i & 0xFF);
  11.352 +            } else if (i == (short) i) {
  11.353 +                mv.visitIntInsn(Opcodes.SIPUSH, (char) i);
  11.354 +            } else {
  11.355 +                mv.visitLdcInsn(i);
  11.356 +            }
  11.357 +            return;
  11.358 +        }
  11.359 +        mv.visitInsn(opcode);
  11.360 +    }
  11.361 +
  11.362 +    /*
  11.363 +     * NOTE: These load/store methods use the localsMap to find the correct index!
  11.364 +     */
  11.365 +    private void emitLoadInsn(char type, int index) {
  11.366 +        int opcode;
  11.367 +        switch (type) {
  11.368 +        case 'I':  opcode = Opcodes.ILOAD;  break;
  11.369 +        case 'J':  opcode = Opcodes.LLOAD;  break;
  11.370 +        case 'F':  opcode = Opcodes.FLOAD;  break;
  11.371 +        case 'D':  opcode = Opcodes.DLOAD;  break;
  11.372 +        case 'L':  opcode = Opcodes.ALOAD;  break;
  11.373 +        default:
  11.374 +            throw new InternalError("unknown type: " + type);
  11.375 +        }
  11.376 +        mv.visitVarInsn(opcode, localsMap[index]);
  11.377 +    }
  11.378 +    private void emitAloadInsn(int index) {
  11.379 +        emitLoadInsn('L', index);
  11.380 +    }
  11.381 +
  11.382 +    private void emitStoreInsn(char type, int index) {
  11.383 +        int opcode;
  11.384 +        switch (type) {
  11.385 +        case 'I':  opcode = Opcodes.ISTORE;  break;
  11.386 +        case 'J':  opcode = Opcodes.LSTORE;  break;
  11.387 +        case 'F':  opcode = Opcodes.FSTORE;  break;
  11.388 +        case 'D':  opcode = Opcodes.DSTORE;  break;
  11.389 +        case 'L':  opcode = Opcodes.ASTORE;  break;
  11.390 +        default:
  11.391 +            throw new InternalError("unknown type: " + type);
  11.392 +        }
  11.393 +        mv.visitVarInsn(opcode, localsMap[index]);
  11.394 +    }
  11.395 +    private void emitAstoreInsn(int index) {
  11.396 +        emitStoreInsn('L', index);
  11.397 +    }
  11.398 +
  11.399 +    /**
  11.400 +     * Emit a boxing call.
  11.401 +     *
  11.402 +     * @param type primitive type class to box.
  11.403 +     */
  11.404 +    private void emitBoxing(Class<?> type) {
  11.405 +        Wrapper wrapper = Wrapper.forPrimitiveType(type);
  11.406 +        String owner = "java/lang/" + wrapper.wrapperType().getSimpleName();
  11.407 +        String name  = "valueOf";
  11.408 +        String desc  = "(" + wrapper.basicTypeChar() + ")L" + owner + ";";
  11.409 +        mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc);
  11.410 +    }
  11.411 +
  11.412 +    /**
  11.413 +     * Emit an unboxing call (plus preceding checkcast).
  11.414 +     *
  11.415 +     * @param type wrapper type class to unbox.
  11.416 +     */
  11.417 +    private void emitUnboxing(Class<?> type) {
  11.418 +        Wrapper wrapper = Wrapper.forWrapperType(type);
  11.419 +        String owner = "java/lang/" + wrapper.wrapperType().getSimpleName();
  11.420 +        String name  = wrapper.primitiveSimpleName() + "Value";
  11.421 +        String desc  = "()" + wrapper.basicTypeChar();
  11.422 +        mv.visitTypeInsn(Opcodes.CHECKCAST, owner);
  11.423 +        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc);
  11.424 +    }
  11.425 +
  11.426 +    /**
  11.427 +     * Emit an implicit conversion.
  11.428 +     *
  11.429 +     * @param ptype type of value present on stack
  11.430 +     * @param pclass type of value required on stack
  11.431 +     */
  11.432 +    private void emitImplicitConversion(char ptype, Class<?> pclass) {
  11.433 +        switch (ptype) {
  11.434 +        case 'L':
  11.435 +            if (VerifyType.isNullConversion(Object.class, pclass))
  11.436 +                return;
  11.437 +            if (isStaticallyNameable(pclass)) {
  11.438 +                mv.visitTypeInsn(Opcodes.CHECKCAST, getInternalName(pclass));
  11.439 +            } else {
  11.440 +                mv.visitLdcInsn(constantPlaceholder(pclass));
  11.441 +                mv.visitTypeInsn(Opcodes.CHECKCAST, CLS);
  11.442 +                mv.visitInsn(Opcodes.SWAP);
  11.443 +                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, CLS, "cast", LL_SIG);
  11.444 +                if (pclass.isArray())
  11.445 +                    mv.visitTypeInsn(Opcodes.CHECKCAST, OBJARY);
  11.446 +            }
  11.447 +            return;
  11.448 +        case 'I':
  11.449 +            if (!VerifyType.isNullConversion(int.class, pclass))
  11.450 +                emitPrimCast(ptype, Wrapper.basicTypeChar(pclass));
  11.451 +            return;
  11.452 +        case 'J':
  11.453 +            assert(pclass == long.class);
  11.454 +            return;
  11.455 +        case 'F':
  11.456 +            assert(pclass == float.class);
  11.457 +            return;
  11.458 +        case 'D':
  11.459 +            assert(pclass == double.class);
  11.460 +            return;
  11.461 +        }
  11.462 +        throw new InternalError("bad implicit conversion: tc="+ptype+": "+pclass);
  11.463 +    }
  11.464 +
  11.465 +    /**
  11.466 +     * Emits an actual return instruction conforming to the given return type.
  11.467 +     */
  11.468 +    private void emitReturnInsn(Class<?> type) {
  11.469 +        int opcode;
  11.470 +        switch (Wrapper.basicTypeChar(type)) {
  11.471 +        case 'I':  opcode = Opcodes.IRETURN;  break;
  11.472 +        case 'J':  opcode = Opcodes.LRETURN;  break;
  11.473 +        case 'F':  opcode = Opcodes.FRETURN;  break;
  11.474 +        case 'D':  opcode = Opcodes.DRETURN;  break;
  11.475 +        case 'L':  opcode = Opcodes.ARETURN;  break;
  11.476 +        case 'V':  opcode = Opcodes.RETURN;   break;
  11.477 +        default:
  11.478 +            throw new InternalError("unknown return type: " + type);
  11.479 +        }
  11.480 +        mv.visitInsn(opcode);
  11.481 +    }
  11.482 +
  11.483 +    private static String getInternalName(Class<?> c) {
  11.484 +        assert(VerifyAccess.isTypeVisible(c, Object.class));
  11.485 +        return c.getName().replace('.', '/');
  11.486 +    }
  11.487 +
  11.488 +    /**
  11.489 +     * Generate customized bytecode for a given LambdaForm.
  11.490 +     */
  11.491 +    static MemberName generateCustomizedCode(LambdaForm form, MethodType invokerType) {
  11.492 +        InvokerBytecodeGenerator g = new InvokerBytecodeGenerator("MH", form, invokerType);
  11.493 +        return g.loadMethod(g.generateCustomizedCodeBytes());
  11.494 +    }
  11.495 +
  11.496 +    /**
  11.497 +     * Generate an invoker method for the passed {@link LambdaForm}.
  11.498 +     */
  11.499 +    private byte[] generateCustomizedCodeBytes() {
  11.500 +        classFilePrologue();
  11.501 +
  11.502 +        // Suppress this method in backtraces displayed to the user.
  11.503 +        mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true);
  11.504 +
  11.505 +        // Mark this method as a compiled LambdaForm
  11.506 +        mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Compiled;", true);
  11.507 +
  11.508 +        // Force inlining of this invoker method.
  11.509 +        mv.visitAnnotation("Ljava/lang/invoke/ForceInline;", true);
  11.510 +
  11.511 +        // iterate over the form's names, generating bytecode instructions for each
  11.512 +        // start iterating at the first name following the arguments
  11.513 +        for (int i = lambdaForm.arity; i < lambdaForm.names.length; i++) {
  11.514 +            Name name = lambdaForm.names[i];
  11.515 +            MemberName member = name.function.member();
  11.516 +
  11.517 +            if (isSelectAlternative(member)) {
  11.518 +                // selectAlternative idiom
  11.519 +                // FIXME: make sure this idiom is really present!
  11.520 +                emitSelectAlternative(name, lambdaForm.names[i + 1]);
  11.521 +                i++;  // skip MH.invokeBasic of the selectAlternative result
  11.522 +            } else if (isStaticallyInvocable(member)) {
  11.523 +                emitStaticInvoke(member, name);
  11.524 +            } else {
  11.525 +                emitInvoke(name);
  11.526 +            }
  11.527 +
  11.528 +            // store the result from evaluating to the target name in a local if required
  11.529 +            // (if this is the last value, i.e., the one that is going to be returned,
  11.530 +            // avoid store/load/return and just return)
  11.531 +            if (i == lambdaForm.names.length - 1 && i == lambdaForm.result) {
  11.532 +                // return value - do nothing
  11.533 +            } else if (name.type != 'V') {
  11.534 +                // non-void: actually assign
  11.535 +                emitStoreInsn(name.type, name.index());
  11.536 +            }
  11.537 +        }
  11.538 +
  11.539 +        // return statement
  11.540 +        emitReturn();
  11.541 +
  11.542 +        classFileEpilogue();
  11.543 +        bogusMethod(lambdaForm);
  11.544 +
  11.545 +        final byte[] classFile = cw.toByteArray();
  11.546 +        maybeDump(className, classFile);
  11.547 +        return classFile;
  11.548 +    }
  11.549 +
  11.550 +    /**
  11.551 +     * Emit an invoke for the given name.
  11.552 +     */
  11.553 +    void emitInvoke(Name name) {
  11.554 +        if (true) {
  11.555 +            // push receiver
  11.556 +            MethodHandle target = name.function.resolvedHandle;
  11.557 +            assert(target != null) : name.exprString();
  11.558 +            mv.visitLdcInsn(constantPlaceholder(target));
  11.559 +            mv.visitTypeInsn(Opcodes.CHECKCAST, MH);
  11.560 +        } else {
  11.561 +            // load receiver
  11.562 +            emitAloadInsn(0);
  11.563 +            mv.visitTypeInsn(Opcodes.CHECKCAST, MH);
  11.564 +            mv.visitFieldInsn(Opcodes.GETFIELD, MH, "form", LF_SIG);
  11.565 +            mv.visitFieldInsn(Opcodes.GETFIELD, LF, "names", LFN_SIG);
  11.566 +            // TODO more to come
  11.567 +        }
  11.568 +
  11.569 +        // push arguments
  11.570 +        for (int i = 0; i < name.arguments.length; i++) {
  11.571 +            emitPushArgument(name, i);
  11.572 +        }
  11.573 +
  11.574 +        // invocation
  11.575 +        MethodType type = name.function.methodType();
  11.576 +        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, MH, "invokeBasic", type.basicType().toMethodDescriptorString());
  11.577 +    }
  11.578 +
  11.579 +    static private Class<?>[] STATICALLY_INVOCABLE_PACKAGES = {
  11.580 +        // Sample classes from each package we are willing to bind to statically:
  11.581 +        java.lang.Object.class,
  11.582 +        java.util.Arrays.class,
  11.583 +        sun.misc.Unsafe.class
  11.584 +        //MethodHandle.class already covered
  11.585 +    };
  11.586 +
  11.587 +    static boolean isStaticallyInvocable(MemberName member) {
  11.588 +        if (member == null)  return false;
  11.589 +        if (member.isConstructor())  return false;
  11.590 +        Class<?> cls = member.getDeclaringClass();
  11.591 +        if (cls.isArray() || cls.isPrimitive())
  11.592 +            return false;  // FIXME
  11.593 +        if (cls.isAnonymousClass() || cls.isLocalClass())
  11.594 +            return false;  // inner class of some sort
  11.595 +        if (cls.getClassLoader() != MethodHandle.class.getClassLoader())
  11.596 +            return false;  // not on BCP
  11.597 +        MethodType mtype = member.getMethodOrFieldType();
  11.598 +        if (!isStaticallyNameable(mtype.returnType()))
  11.599 +            return false;
  11.600 +        for (Class<?> ptype : mtype.parameterArray())
  11.601 +            if (!isStaticallyNameable(ptype))
  11.602 +                return false;
  11.603 +        if (!member.isPrivate() && VerifyAccess.isSamePackage(MethodHandle.class, cls))
  11.604 +            return true;   // in java.lang.invoke package
  11.605 +        if (member.isPublic() && isStaticallyNameable(cls))
  11.606 +            return true;
  11.607 +        return false;
  11.608 +    }
  11.609 +
  11.610 +    static boolean isStaticallyNameable(Class<?> cls) {
  11.611 +        while (cls.isArray())
  11.612 +            cls = cls.getComponentType();
  11.613 +        if (cls.isPrimitive())
  11.614 +            return true;  // int[].class, for example
  11.615 +        // could use VerifyAccess.isClassAccessible but the following is a safe approximation
  11.616 +        if (cls.getClassLoader() != Object.class.getClassLoader())
  11.617 +            return false;
  11.618 +        if (VerifyAccess.isSamePackage(MethodHandle.class, cls))
  11.619 +            return true;
  11.620 +        if (!Modifier.isPublic(cls.getModifiers()))
  11.621 +            return false;
  11.622 +        for (Class<?> pkgcls : STATICALLY_INVOCABLE_PACKAGES) {
  11.623 +            if (VerifyAccess.isSamePackage(pkgcls, cls))
  11.624 +                return true;
  11.625 +        }
  11.626 +        return false;
  11.627 +    }
  11.628 +
  11.629 +    /**
  11.630 +     * Emit an invoke for the given name, using the MemberName directly.
  11.631 +     */
  11.632 +    void emitStaticInvoke(MemberName member, Name name) {
  11.633 +        assert(member.equals(name.function.member()));
  11.634 +        String cname = getInternalName(member.getDeclaringClass());
  11.635 +        String mname = member.getName();
  11.636 +        String mtype;
  11.637 +        byte refKind = member.getReferenceKind();
  11.638 +        if (refKind == REF_invokeSpecial) {
  11.639 +            // in order to pass the verifier, we need to convert this to invokevirtual in all cases
  11.640 +            assert(member.canBeStaticallyBound()) : member;
  11.641 +            refKind = REF_invokeVirtual;
  11.642 +        }
  11.643 +
  11.644 +        if (member.getDeclaringClass().isInterface() && refKind == REF_invokeVirtual) {
  11.645 +            // Methods from Object declared in an interface can be resolved by JVM to invokevirtual kind.
  11.646 +            // Need to convert it back to invokeinterface to pass verification and make the invocation works as expected.
  11.647 +            refKind = REF_invokeInterface;
  11.648 +        }
  11.649 +
  11.650 +        // push arguments
  11.651 +        for (int i = 0; i < name.arguments.length; i++) {
  11.652 +            emitPushArgument(name, i);
  11.653 +        }
  11.654 +
  11.655 +        // invocation
  11.656 +        if (member.isMethod()) {
  11.657 +            mtype = member.getMethodType().toMethodDescriptorString();
  11.658 +            mv.visitMethodInsn(refKindOpcode(refKind), cname, mname, mtype,
  11.659 +                               member.getDeclaringClass().isInterface());
  11.660 +        } else {
  11.661 +            mtype = MethodType.toFieldDescriptorString(member.getFieldType());
  11.662 +            mv.visitFieldInsn(refKindOpcode(refKind), cname, mname, mtype);
  11.663 +        }
  11.664 +    }
  11.665 +    int refKindOpcode(byte refKind) {
  11.666 +        switch (refKind) {
  11.667 +        case REF_invokeVirtual:      return Opcodes.INVOKEVIRTUAL;
  11.668 +        case REF_invokeStatic:       return Opcodes.INVOKESTATIC;
  11.669 +        case REF_invokeSpecial:      return Opcodes.INVOKESPECIAL;
  11.670 +        case REF_invokeInterface:    return Opcodes.INVOKEINTERFACE;
  11.671 +        case REF_getField:           return Opcodes.GETFIELD;
  11.672 +        case REF_putField:           return Opcodes.PUTFIELD;
  11.673 +        case REF_getStatic:          return Opcodes.GETSTATIC;
  11.674 +        case REF_putStatic:          return Opcodes.PUTSTATIC;
  11.675 +        }
  11.676 +        throw new InternalError("refKind="+refKind);
  11.677 +    }
  11.678 +
  11.679 +    /**
  11.680 +     * Check if MemberName is a call to MethodHandleImpl.selectAlternative.
  11.681 +     */
  11.682 +    private boolean isSelectAlternative(MemberName member) {
  11.683 +        return member != null &&
  11.684 +               member.getDeclaringClass() == MethodHandleImpl.class &&
  11.685 +               member.getName().equals("selectAlternative");
  11.686 +    }
  11.687 +
  11.688 +    /**
  11.689 +     * Emit bytecode for the selectAlternative idiom.
  11.690 +     *
  11.691 +     * The pattern looks like (Cf. MethodHandleImpl.makeGuardWithTest):
  11.692 +     * <blockquote><pre>{@code
  11.693 +     *   Lambda(a0:L,a1:I)=>{
  11.694 +     *     t2:I=foo.test(a1:I);
  11.695 +     *     t3:L=MethodHandleImpl.selectAlternative(t2:I,(MethodHandle(int)int),(MethodHandle(int)int));
  11.696 +     *     t4:I=MethodHandle.invokeBasic(t3:L,a1:I);t4:I}
  11.697 +     * }</pre></blockquote>
  11.698 +     */
  11.699 +    private void emitSelectAlternative(Name selectAlternativeName, Name invokeBasicName) {
  11.700 +        MethodType type = selectAlternativeName.function.methodType();
  11.701 +
  11.702 +        Name receiver = (Name) invokeBasicName.arguments[0];
  11.703 +
  11.704 +        Label L_fallback = new Label();
  11.705 +        Label L_done     = new Label();
  11.706 +
  11.707 +        // load test result
  11.708 +        emitPushArgument(selectAlternativeName, 0);
  11.709 +        mv.visitInsn(Opcodes.ICONST_1);
  11.710 +
  11.711 +        // if_icmpne L_fallback
  11.712 +        mv.visitJumpInsn(Opcodes.IF_ICMPNE, L_fallback);
  11.713 +
  11.714 +        // invoke selectAlternativeName.arguments[1]
  11.715 +        MethodHandle target = (MethodHandle) selectAlternativeName.arguments[1];
  11.716 +        emitPushArgument(selectAlternativeName, 1);  // get 2nd argument of selectAlternative
  11.717 +        emitAstoreInsn(receiver.index());  // store the MH in the receiver slot
  11.718 +        emitInvoke(invokeBasicName);
  11.719 +
  11.720 +        // goto L_done
  11.721 +        mv.visitJumpInsn(Opcodes.GOTO, L_done);
  11.722 +
  11.723 +        // L_fallback:
  11.724 +        mv.visitLabel(L_fallback);
  11.725 +
  11.726 +        // invoke selectAlternativeName.arguments[2]
  11.727 +        MethodHandle fallback = (MethodHandle) selectAlternativeName.arguments[2];
  11.728 +        emitPushArgument(selectAlternativeName, 2);  // get 3rd argument of selectAlternative
  11.729 +        emitAstoreInsn(receiver.index());  // store the MH in the receiver slot
  11.730 +        emitInvoke(invokeBasicName);
  11.731 +
  11.732 +        // L_done:
  11.733 +        mv.visitLabel(L_done);
  11.734 +    }
  11.735 +
  11.736 +    private void emitPushArgument(Name name, int paramIndex) {
  11.737 +        Object arg = name.arguments[paramIndex];
  11.738 +        char ptype = name.function.parameterType(paramIndex);
  11.739 +        MethodType mtype = name.function.methodType();
  11.740 +        if (arg instanceof Name) {
  11.741 +            Name n = (Name) arg;
  11.742 +            emitLoadInsn(n.type, n.index());
  11.743 +            emitImplicitConversion(n.type, mtype.parameterType(paramIndex));
  11.744 +        } else if ((arg == null || arg instanceof String) && ptype == 'L') {
  11.745 +            emitConst(arg);
  11.746 +        } else {
  11.747 +            if (Wrapper.isWrapperType(arg.getClass()) && ptype != 'L') {
  11.748 +                emitConst(arg);
  11.749 +            } else {
  11.750 +                mv.visitLdcInsn(constantPlaceholder(arg));
  11.751 +                emitImplicitConversion('L', mtype.parameterType(paramIndex));
  11.752 +            }
  11.753 +        }
  11.754 +    }
  11.755 +
  11.756 +    /**
  11.757 +     * Emits a return statement from a LF invoker. If required, the result type is cast to the correct return type.
  11.758 +     */
  11.759 +    private void emitReturn() {
  11.760 +        // return statement
  11.761 +        if (lambdaForm.result == -1) {
  11.762 +            // void
  11.763 +            mv.visitInsn(Opcodes.RETURN);
  11.764 +        } else {
  11.765 +            LambdaForm.Name rn = lambdaForm.names[lambdaForm.result];
  11.766 +            char rtype = Wrapper.basicTypeChar(invokerType.returnType());
  11.767 +
  11.768 +            // put return value on the stack if it is not already there
  11.769 +            if (lambdaForm.result != lambdaForm.names.length - 1) {
  11.770 +                emitLoadInsn(rn.type, lambdaForm.result);
  11.771 +            }
  11.772 +
  11.773 +            // potentially generate cast
  11.774 +            // rtype is the return type of the invoker - generated code must conform to this
  11.775 +            // rn.type is the type of the result Name in the LF
  11.776 +            if (rtype != rn.type) {
  11.777 +                // need cast
  11.778 +                if (rtype == 'L') {
  11.779 +                    // possibly cast the primitive to the correct type for boxing
  11.780 +                    char boxedType = Wrapper.forWrapperType(invokerType.returnType()).basicTypeChar();
  11.781 +                    if (boxedType != rn.type) {
  11.782 +                        emitPrimCast(rn.type, boxedType);
  11.783 +                    }
  11.784 +                    // cast primitive to reference ("boxing")
  11.785 +                    emitBoxing(invokerType.returnType());
  11.786 +                } else {
  11.787 +                    // to-primitive cast
  11.788 +                    if (rn.type != 'L') {
  11.789 +                        // prim-to-prim cast
  11.790 +                        emitPrimCast(rn.type, rtype);
  11.791 +                    } else {
  11.792 +                        // ref-to-prim cast ("unboxing")
  11.793 +                        throw new InternalError("no ref-to-prim (unboxing) casts supported right now");
  11.794 +                    }
  11.795 +                }
  11.796 +            }
  11.797 +
  11.798 +            // generate actual return statement
  11.799 +            emitReturnInsn(invokerType.returnType());
  11.800 +        }
  11.801 +    }
  11.802 +
  11.803 +    /**
  11.804 +     * Emit a type conversion bytecode casting from "from" to "to".
  11.805 +     */
  11.806 +    private void emitPrimCast(char from, char to) {
  11.807 +        // Here's how.
  11.808 +        // -   indicates forbidden
  11.809 +        // <-> indicates implicit
  11.810 +        //      to ----> boolean  byte     short    char     int      long     float    double
  11.811 +        // from boolean    <->        -        -        -        -        -        -        -
  11.812 +        //      byte        -       <->       i2s      i2c      <->      i2l      i2f      i2d
  11.813 +        //      short       -       i2b       <->      i2c      <->      i2l      i2f      i2d
  11.814 +        //      char        -       i2b       i2s      <->      <->      i2l      i2f      i2d
  11.815 +        //      int         -       i2b       i2s      i2c      <->      i2l      i2f      i2d
  11.816 +        //      long        -     l2i,i2b   l2i,i2s  l2i,i2c    l2i      <->      l2f      l2d
  11.817 +        //      float       -     f2i,i2b   f2i,i2s  f2i,i2c    f2i      f2l      <->      f2d
  11.818 +        //      double      -     d2i,i2b   d2i,i2s  d2i,i2c    d2i      d2l      d2f      <->
  11.819 +        if (from == to) {
  11.820 +            // no cast required, should be dead code anyway
  11.821 +            return;
  11.822 +        }
  11.823 +        Wrapper wfrom = Wrapper.forBasicType(from);
  11.824 +        Wrapper wto   = Wrapper.forBasicType(to);
  11.825 +        if (wfrom.isSubwordOrInt()) {
  11.826 +            // cast from {byte,short,char,int} to anything
  11.827 +            emitI2X(to);
  11.828 +        } else {
  11.829 +            // cast from {long,float,double} to anything
  11.830 +            if (wto.isSubwordOrInt()) {
  11.831 +                // cast to {byte,short,char,int}
  11.832 +                emitX2I(from);
  11.833 +                if (wto.bitWidth() < 32) {
  11.834 +                    // targets other than int require another conversion
  11.835 +                    emitI2X(to);
  11.836 +                }
  11.837 +            } else {
  11.838 +                // cast to {long,float,double} - this is verbose
  11.839 +                boolean error = false;
  11.840 +                switch (from) {
  11.841 +                case 'J':
  11.842 +                         if (to == 'F') { mv.visitInsn(Opcodes.L2F); }
  11.843 +                    else if (to == 'D') { mv.visitInsn(Opcodes.L2D); }
  11.844 +                    else error = true;
  11.845 +                    break;
  11.846 +                case 'F':
  11.847 +                         if (to == 'J') { mv.visitInsn(Opcodes.F2L); }
  11.848 +                    else if (to == 'D') { mv.visitInsn(Opcodes.F2D); }
  11.849 +                    else error = true;
  11.850 +                    break;
  11.851 +                case 'D':
  11.852 +                         if (to == 'J') { mv.visitInsn(Opcodes.D2L); }
  11.853 +                    else if (to == 'F') { mv.visitInsn(Opcodes.D2F); }
  11.854 +                    else error = true;
  11.855 +                    break;
  11.856 +                default:
  11.857 +                    error = true;
  11.858 +                    break;
  11.859 +                }
  11.860 +                if (error) {
  11.861 +                    throw new IllegalStateException("unhandled prim cast: " + from + "2" + to);
  11.862 +                }
  11.863 +            }
  11.864 +        }
  11.865 +    }
  11.866 +
  11.867 +    private void emitI2X(char type) {
  11.868 +        switch (type) {
  11.869 +        case 'B':  mv.visitInsn(Opcodes.I2B);  break;
  11.870 +        case 'S':  mv.visitInsn(Opcodes.I2S);  break;
  11.871 +        case 'C':  mv.visitInsn(Opcodes.I2C);  break;
  11.872 +        case 'I':  /* naught */                break;
  11.873 +        case 'J':  mv.visitInsn(Opcodes.I2L);  break;
  11.874 +        case 'F':  mv.visitInsn(Opcodes.I2F);  break;
  11.875 +        case 'D':  mv.visitInsn(Opcodes.I2D);  break;
  11.876 +        case 'Z':
  11.877 +            // For compatibility with ValueConversions and explicitCastArguments:
  11.878 +            mv.visitInsn(Opcodes.ICONST_1);
  11.879 +            mv.visitInsn(Opcodes.IAND);
  11.880 +            break;
  11.881 +        default:   throw new InternalError("unknown type: " + type);
  11.882 +        }
  11.883 +    }
  11.884 +
  11.885 +    private void emitX2I(char type) {
  11.886 +        switch (type) {
  11.887 +        case 'J':  mv.visitInsn(Opcodes.L2I);  break;
  11.888 +        case 'F':  mv.visitInsn(Opcodes.F2I);  break;
  11.889 +        case 'D':  mv.visitInsn(Opcodes.D2I);  break;
  11.890 +        default:   throw new InternalError("unknown type: " + type);
  11.891 +        }
  11.892 +    }
  11.893 +
  11.894 +    private static String basicTypeCharSignature(String prefix, MethodType type) {
  11.895 +        StringBuilder buf = new StringBuilder(prefix);
  11.896 +        for (Class<?> ptype : type.parameterList())
  11.897 +            buf.append(Wrapper.forBasicType(ptype).basicTypeChar());
  11.898 +        buf.append('_').append(Wrapper.forBasicType(type.returnType()).basicTypeChar());
  11.899 +        return buf.toString();
  11.900 +    }
  11.901 +
  11.902 +    /**
  11.903 +     * Generate bytecode for a LambdaForm.vmentry which calls interpretWithArguments.
  11.904 +     */
  11.905 +    static MemberName generateLambdaFormInterpreterEntryPoint(String sig) {
  11.906 +        assert(LambdaForm.isValidSignature(sig));
  11.907 +        //System.out.println("generateExactInvoker "+sig);
  11.908 +        // compute method type
  11.909 +        // first parameter and return type
  11.910 +        char tret = LambdaForm.signatureReturn(sig);
  11.911 +        MethodType type = MethodType.methodType(LambdaForm.typeClass(tret), MethodHandle.class);
  11.912 +        // other parameter types
  11.913 +        int arity = LambdaForm.signatureArity(sig);
  11.914 +        for (int i = 1; i < arity; i++) {
  11.915 +            type = type.appendParameterTypes(LambdaForm.typeClass(sig.charAt(i)));
  11.916 +        }
  11.917 +        InvokerBytecodeGenerator g = new InvokerBytecodeGenerator("LFI", "interpret_"+tret, type);
  11.918 +        return g.loadMethod(g.generateLambdaFormInterpreterEntryPointBytes());
  11.919 +    }
  11.920 +
  11.921 +    private byte[] generateLambdaFormInterpreterEntryPointBytes() {
  11.922 +        classFilePrologue();
  11.923 +
  11.924 +        // Suppress this method in backtraces displayed to the user.
  11.925 +        mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true);
  11.926 +
  11.927 +        // Don't inline the interpreter entry.
  11.928 +        mv.visitAnnotation("Ljava/lang/invoke/DontInline;", true);
  11.929 +
  11.930 +        // create parameter array
  11.931 +        emitIconstInsn(invokerType.parameterCount());
  11.932 +        mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
  11.933 +
  11.934 +        // fill parameter array
  11.935 +        for (int i = 0; i < invokerType.parameterCount(); i++) {
  11.936 +            Class<?> ptype = invokerType.parameterType(i);
  11.937 +            mv.visitInsn(Opcodes.DUP);
  11.938 +            emitIconstInsn(i);
  11.939 +            emitLoadInsn(Wrapper.basicTypeChar(ptype), i);
  11.940 +            // box if primitive type
  11.941 +            if (ptype.isPrimitive()) {
  11.942 +                emitBoxing(ptype);
  11.943 +            }
  11.944 +            mv.visitInsn(Opcodes.AASTORE);
  11.945 +        }
  11.946 +        // invoke
  11.947 +        emitAloadInsn(0);
  11.948 +        mv.visitFieldInsn(Opcodes.GETFIELD, MH, "form", "Ljava/lang/invoke/LambdaForm;");
  11.949 +        mv.visitInsn(Opcodes.SWAP);  // swap form and array; avoid local variable
  11.950 +        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, LF, "interpretWithArguments", "([Ljava/lang/Object;)Ljava/lang/Object;");
  11.951 +
  11.952 +        // maybe unbox
  11.953 +        Class<?> rtype = invokerType.returnType();
  11.954 +        if (rtype.isPrimitive() && rtype != void.class) {
  11.955 +            emitUnboxing(Wrapper.asWrapperType(rtype));
  11.956 +        }
  11.957 +
  11.958 +        // return statement
  11.959 +        emitReturnInsn(rtype);
  11.960 +
  11.961 +        classFileEpilogue();
  11.962 +        bogusMethod(invokerType);
  11.963 +
  11.964 +        final byte[] classFile = cw.toByteArray();
  11.965 +        maybeDump(className, classFile);
  11.966 +        return classFile;
  11.967 +    }
  11.968 +
  11.969 +    /**
  11.970 +     * Generate bytecode for a NamedFunction invoker.
  11.971 +     */
  11.972 +    static MemberName generateNamedFunctionInvoker(MethodTypeForm typeForm) {
  11.973 +        MethodType invokerType = LambdaForm.NamedFunction.INVOKER_METHOD_TYPE;
  11.974 +        String invokerName = basicTypeCharSignature("invoke_", typeForm.erasedType());
  11.975 +        InvokerBytecodeGenerator g = new InvokerBytecodeGenerator("NFI", invokerName, invokerType);
  11.976 +        return g.loadMethod(g.generateNamedFunctionInvokerImpl(typeForm));
  11.977 +    }
  11.978 +
  11.979 +    static int nfi = 0;
  11.980 +
  11.981 +    private byte[] generateNamedFunctionInvokerImpl(MethodTypeForm typeForm) {
  11.982 +        MethodType dstType = typeForm.erasedType();
  11.983 +        classFilePrologue();
  11.984 +
  11.985 +        // Suppress this method in backtraces displayed to the user.
  11.986 +        mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true);
  11.987 +
  11.988 +        // Force inlining of this invoker method.
  11.989 +        mv.visitAnnotation("Ljava/lang/invoke/ForceInline;", true);
  11.990 +
  11.991 +        // Load receiver
  11.992 +        emitAloadInsn(0);
  11.993 +
  11.994 +        // Load arguments from array
  11.995 +        for (int i = 0; i < dstType.parameterCount(); i++) {
  11.996 +            emitAloadInsn(1);
  11.997 +            emitIconstInsn(i);
  11.998 +            mv.visitInsn(Opcodes.AALOAD);
  11.999 +
 11.1000 +            // Maybe unbox
 11.1001 +            Class<?> dptype = dstType.parameterType(i);
 11.1002 +            if (dptype.isPrimitive()) {
 11.1003 +                Class<?> sptype = dstType.basicType().wrap().parameterType(i);
 11.1004 +                Wrapper dstWrapper = Wrapper.forBasicType(dptype);
 11.1005 +                Wrapper srcWrapper = dstWrapper.isSubwordOrInt() ? Wrapper.INT : dstWrapper;  // narrow subword from int
 11.1006 +                emitUnboxing(srcWrapper.wrapperType());
 11.1007 +                emitPrimCast(srcWrapper.basicTypeChar(), dstWrapper.basicTypeChar());
 11.1008 +            }
 11.1009 +        }
 11.1010 +
 11.1011 +        // Invoke
 11.1012 +        String targetDesc = dstType.basicType().toMethodDescriptorString();
 11.1013 +        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, MH, "invokeBasic", targetDesc);
 11.1014 +
 11.1015 +        // Box primitive types
 11.1016 +        Class<?> rtype = dstType.returnType();
 11.1017 +        if (rtype != void.class && rtype.isPrimitive()) {
 11.1018 +            Wrapper srcWrapper = Wrapper.forBasicType(rtype);
 11.1019 +            Wrapper dstWrapper = srcWrapper.isSubwordOrInt() ? Wrapper.INT : srcWrapper;  // widen subword to int
 11.1020 +            // boolean casts not allowed
 11.1021 +            emitPrimCast(srcWrapper.basicTypeChar(), dstWrapper.basicTypeChar());
 11.1022 +            emitBoxing(dstWrapper.primitiveType());
 11.1023 +        }
 11.1024 +
 11.1025 +        // If the return type is void we return a null reference.
 11.1026 +        if (rtype == void.class) {
 11.1027 +            mv.visitInsn(Opcodes.ACONST_NULL);
 11.1028 +        }
 11.1029 +        emitReturnInsn(Object.class);  // NOTE: NamedFunction invokers always return a reference value.
 11.1030 +
 11.1031 +        classFileEpilogue();
 11.1032 +        bogusMethod(dstType);
 11.1033 +
 11.1034 +        final byte[] classFile = cw.toByteArray();
 11.1035 +        maybeDump(className, classFile);
 11.1036 +        return classFile;
 11.1037 +    }
 11.1038 +
 11.1039 +    /**
 11.1040 +     * Emit a bogus method that just loads some string constants. This is to get the constants into the constant pool
 11.1041 +     * for debugging purposes.
 11.1042 +     */
 11.1043 +    private void bogusMethod(Object... os) {
 11.1044 +        if (DUMP_CLASS_FILES) {
 11.1045 +            mv = cw.visitMethod(Opcodes.ACC_STATIC, "dummy", "()V", null, null);
 11.1046 +            for (Object o : os) {
 11.1047 +                mv.visitLdcInsn(o.toString());
 11.1048 +                mv.visitInsn(Opcodes.POP);
 11.1049 +            }
 11.1050 +            mv.visitInsn(Opcodes.RETURN);
 11.1051 +            mv.visitMaxs(0, 0);
 11.1052 +            mv.visitEnd();
 11.1053 +        }
 11.1054 +    }
 11.1055 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/Invokers.java	Sat Aug 09 11:12:05 2014 +0200
    12.3 @@ -0,0 +1,462 @@
    12.4 +/*
    12.5 + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
    12.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    12.7 + *
    12.8 + * This code is free software; you can redistribute it and/or modify it
    12.9 + * under the terms of the GNU General Public License version 2 only, as
   12.10 + * published by the Free Software Foundation.  Oracle designates this
   12.11 + * particular file as subject to the "Classpath" exception as provided
   12.12 + * by Oracle in the LICENSE file that accompanied this code.
   12.13 + *
   12.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   12.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   12.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   12.17 + * version 2 for more details (a copy is included in the LICENSE file that
   12.18 + * accompanied this code).
   12.19 + *
   12.20 + * You should have received a copy of the GNU General Public License version
   12.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   12.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   12.23 + *
   12.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   12.25 + * or visit www.oracle.com if you need additional information or have any
   12.26 + * questions.
   12.27 + */
   12.28 +
   12.29 +package java.lang.invoke;
   12.30 +
   12.31 +import java.util.Arrays;
   12.32 +import sun.invoke.empty.Empty;
   12.33 +import static java.lang.invoke.MethodHandleStatics.*;
   12.34 +import static java.lang.invoke.MethodHandleNatives.Constants.*;
   12.35 +import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
   12.36 +import static java.lang.invoke.LambdaForm.*;
   12.37 +
   12.38 +/**
   12.39 + * Construction and caching of often-used invokers.
   12.40 + * @author jrose
   12.41 + */
   12.42 +class Invokers {
   12.43 +    // exact type (sans leading taget MH) for the outgoing call
   12.44 +    private final MethodType targetType;
   12.45 +
   12.46 +    // FIXME: Get rid of the invokers that are not useful.
   12.47 +
   12.48 +    // exact invoker for the outgoing call
   12.49 +    private /*lazy*/ MethodHandle exactInvoker;
   12.50 +    private /*lazy*/ MethodHandle basicInvoker;  // invokeBasic (unchecked exact)
   12.51 +
   12.52 +    // erased (partially untyped but with primitives) invoker for the outgoing call
   12.53 +    // FIXME: get rid of
   12.54 +    private /*lazy*/ MethodHandle erasedInvoker;
   12.55 +    // FIXME: get rid of
   12.56 +    /*lazy*/ MethodHandle erasedInvokerWithDrops;  // for InvokeGeneric
   12.57 +
   12.58 +    // general invoker for the outgoing call
   12.59 +    private /*lazy*/ MethodHandle generalInvoker;
   12.60 +
   12.61 +    // general invoker for the outgoing call, uses varargs
   12.62 +    private /*lazy*/ MethodHandle varargsInvoker;
   12.63 +
   12.64 +    // general invoker for the outgoing call; accepts a trailing Object[]
   12.65 +    private final /*lazy*/ MethodHandle[] spreadInvokers;
   12.66 +
   12.67 +    // invoker for an unbound callsite
   12.68 +    private /*lazy*/ MethodHandle uninitializedCallSite;
   12.69 +
   12.70 +    /** Compute and cache information common to all collecting adapters
   12.71 +     *  that implement members of the erasure-family of the given erased type.
   12.72 +     */
   12.73 +    /*non-public*/ Invokers(MethodType targetType) {
   12.74 +        this.targetType = targetType;
   12.75 +        this.spreadInvokers = new MethodHandle[targetType.parameterCount()+1];
   12.76 +    }
   12.77 +
   12.78 +    /*non-public*/ MethodHandle exactInvoker() {
   12.79 +        MethodHandle invoker = exactInvoker;
   12.80 +        if (invoker != null)  return invoker;
   12.81 +        invoker = makeExactOrGeneralInvoker(true);
   12.82 +        exactInvoker = invoker;
   12.83 +        return invoker;
   12.84 +    }
   12.85 +
   12.86 +    /*non-public*/ MethodHandle generalInvoker() {
   12.87 +        MethodHandle invoker = generalInvoker;
   12.88 +        if (invoker != null)  return invoker;
   12.89 +        invoker = makeExactOrGeneralInvoker(false);
   12.90 +        generalInvoker = invoker;
   12.91 +        return invoker;
   12.92 +    }
   12.93 +
   12.94 +    private MethodHandle makeExactOrGeneralInvoker(boolean isExact) {
   12.95 +        MethodType mtype = targetType;
   12.96 +        MethodType invokerType = mtype.invokerType();
   12.97 +        int which = (isExact ? MethodTypeForm.LF_EX_INVOKER : MethodTypeForm.LF_GEN_INVOKER);
   12.98 +        LambdaForm lform = invokeHandleForm(mtype, false, which);
   12.99 +        MethodHandle invoker = BoundMethodHandle.bindSingle(invokerType, lform, mtype);
  12.100 +        String whichName = (isExact ? "invokeExact" : "invoke");
  12.101 +        invoker = invoker.withInternalMemberName(MemberName.makeMethodHandleInvoke(whichName, mtype));
  12.102 +        assert(checkInvoker(invoker));
  12.103 +        maybeCompileToBytecode(invoker);
  12.104 +        return invoker;
  12.105 +    }
  12.106 +
  12.107 +    /** If the target type seems to be common enough, eagerly compile the invoker to bytecodes. */
  12.108 +    private void maybeCompileToBytecode(MethodHandle invoker) {
  12.109 +        final int EAGER_COMPILE_ARITY_LIMIT = 10;
  12.110 +        if (targetType == targetType.erase() &&
  12.111 +            targetType.parameterCount() < EAGER_COMPILE_ARITY_LIMIT) {
  12.112 +            invoker.form.compileToBytecode();
  12.113 +        }
  12.114 +    }
  12.115 +
  12.116 +    /*non-public*/ MethodHandle basicInvoker() {
  12.117 +        MethodHandle invoker = basicInvoker;
  12.118 +        if (invoker != null)  return invoker;
  12.119 +        MethodType basicType = targetType.basicType();
  12.120 +        if (basicType != targetType) {
  12.121 +            // double cache; not used significantly
  12.122 +            return basicInvoker = basicType.invokers().basicInvoker();
  12.123 +        }
  12.124 +        MemberName method = invokeBasicMethod(basicType);
  12.125 +        invoker = DirectMethodHandle.make(method);
  12.126 +        assert(checkInvoker(invoker));
  12.127 +        basicInvoker = invoker;
  12.128 +        return invoker;
  12.129 +    }
  12.130 +
  12.131 +    // This next one is called from LambdaForm.NamedFunction.<init>.
  12.132 +    /*non-public*/ static MemberName invokeBasicMethod(MethodType basicType) {
  12.133 +        assert(basicType == basicType.basicType());
  12.134 +        try {
  12.135 +            //Lookup.findVirtual(MethodHandle.class, name, type);
  12.136 +            return IMPL_LOOKUP.resolveOrFail(REF_invokeVirtual, MethodHandle.class, "invokeBasic", basicType);
  12.137 +        } catch (ReflectiveOperationException ex) {
  12.138 +            throw newInternalError("JVM cannot find invoker for "+basicType, ex);
  12.139 +        }
  12.140 +    }
  12.141 +
  12.142 +    private boolean checkInvoker(MethodHandle invoker) {
  12.143 +        assert(targetType.invokerType().equals(invoker.type()))
  12.144 +                : java.util.Arrays.asList(targetType, targetType.invokerType(), invoker);
  12.145 +        assert(invoker.internalMemberName() == null ||
  12.146 +               invoker.internalMemberName().getMethodType().equals(targetType));
  12.147 +        assert(!invoker.isVarargsCollector());
  12.148 +        return true;
  12.149 +    }
  12.150 +
  12.151 +    // FIXME: get rid of
  12.152 +    /*non-public*/ MethodHandle erasedInvoker() {
  12.153 +        MethodHandle xinvoker = exactInvoker();
  12.154 +        MethodHandle invoker = erasedInvoker;
  12.155 +        if (invoker != null)  return invoker;
  12.156 +        MethodType erasedType = targetType.erase();
  12.157 +        invoker = xinvoker.asType(erasedType.invokerType());
  12.158 +        erasedInvoker = invoker;
  12.159 +        return invoker;
  12.160 +    }
  12.161 +
  12.162 +    /*non-public*/ MethodHandle spreadInvoker(int leadingArgCount) {
  12.163 +        MethodHandle vaInvoker = spreadInvokers[leadingArgCount];
  12.164 +        if (vaInvoker != null)  return vaInvoker;
  12.165 +        int spreadArgCount = targetType.parameterCount() - leadingArgCount;
  12.166 +        MethodType spreadInvokerType = targetType
  12.167 +            .replaceParameterTypes(leadingArgCount, targetType.parameterCount(), Object[].class);
  12.168 +        if (targetType.parameterSlotCount() <= MethodType.MAX_MH_INVOKER_ARITY) {
  12.169 +            // Factor sinvoker.invoke(mh, a) into ginvoker.asSpreader().invoke(mh, a)
  12.170 +            // where ginvoker.invoke(mh, a*) => mh.invoke(a*).
  12.171 +            MethodHandle genInvoker = generalInvoker();
  12.172 +            vaInvoker = genInvoker.asSpreader(Object[].class, spreadArgCount);
  12.173 +        } else {
  12.174 +            // Cannot build a general invoker here of type ginvoker.invoke(mh, a*[254]).
  12.175 +            // Instead, factor sinvoker.invoke(mh, a) into ainvoker.invoke(filter(mh), a)
  12.176 +            // where filter(mh) == mh.asSpreader(Object[], spreadArgCount)
  12.177 +            MethodHandle arrayInvoker = MethodHandles.exactInvoker(spreadInvokerType);
  12.178 +            MethodHandle makeSpreader;
  12.179 +            try {
  12.180 +                makeSpreader = IMPL_LOOKUP
  12.181 +                    .findVirtual(MethodHandle.class, "asSpreader",
  12.182 +                        MethodType.methodType(MethodHandle.class, Class.class, int.class));
  12.183 +            } catch (ReflectiveOperationException ex) {
  12.184 +                throw newInternalError(ex);
  12.185 +            }
  12.186 +            makeSpreader = MethodHandles.insertArguments(makeSpreader, 1, Object[].class, spreadArgCount);
  12.187 +            vaInvoker = MethodHandles.filterArgument(arrayInvoker, 0, makeSpreader);
  12.188 +        }
  12.189 +        assert(vaInvoker.type().equals(spreadInvokerType.invokerType()));
  12.190 +        maybeCompileToBytecode(vaInvoker);
  12.191 +        spreadInvokers[leadingArgCount] = vaInvoker;
  12.192 +        return vaInvoker;
  12.193 +    }
  12.194 +
  12.195 +    /*non-public*/ MethodHandle varargsInvoker() {
  12.196 +        MethodHandle vaInvoker = varargsInvoker;
  12.197 +        if (vaInvoker != null)  return vaInvoker;
  12.198 +        vaInvoker = spreadInvoker(0).asType(MethodType.genericMethodType(0, true).invokerType());
  12.199 +        varargsInvoker = vaInvoker;
  12.200 +        return vaInvoker;
  12.201 +    }
  12.202 +
  12.203 +    private static MethodHandle THROW_UCS = null;
  12.204 +
  12.205 +    /*non-public*/ MethodHandle uninitializedCallSite() {
  12.206 +        MethodHandle invoker = uninitializedCallSite;
  12.207 +        if (invoker != null)  return invoker;
  12.208 +        if (targetType.parameterCount() > 0) {
  12.209 +            MethodType type0 = targetType.dropParameterTypes(0, targetType.parameterCount());
  12.210 +            Invokers invokers0 = type0.invokers();
  12.211 +            invoker = MethodHandles.dropArguments(invokers0.uninitializedCallSite(),
  12.212 +                                                  0, targetType.parameterList());
  12.213 +            assert(invoker.type().equals(targetType));
  12.214 +            uninitializedCallSite = invoker;
  12.215 +            return invoker;
  12.216 +        }
  12.217 +        invoker = THROW_UCS;
  12.218 +        if (invoker == null) {
  12.219 +            try {
  12.220 +                THROW_UCS = invoker = IMPL_LOOKUP
  12.221 +                    .findStatic(CallSite.class, "uninitializedCallSite",
  12.222 +                                MethodType.methodType(Empty.class));
  12.223 +            } catch (ReflectiveOperationException ex) {
  12.224 +                throw newInternalError(ex);
  12.225 +            }
  12.226 +        }
  12.227 +        invoker = MethodHandles.explicitCastArguments(invoker, MethodType.methodType(targetType.returnType()));
  12.228 +        invoker = invoker.dropArguments(targetType, 0, targetType.parameterCount());
  12.229 +        assert(invoker.type().equals(targetType));
  12.230 +        uninitializedCallSite = invoker;
  12.231 +        return invoker;
  12.232 +    }
  12.233 +
  12.234 +    public String toString() {
  12.235 +        return "Invokers"+targetType;
  12.236 +    }
  12.237 +
  12.238 +    static MemberName methodHandleInvokeLinkerMethod(String name,
  12.239 +                                                     MethodType mtype,
  12.240 +                                                     Object[] appendixResult) {
  12.241 +        int which;
  12.242 +        switch (name) {
  12.243 +        case "invokeExact":  which = MethodTypeForm.LF_EX_LINKER; break;
  12.244 +        case "invoke":       which = MethodTypeForm.LF_GEN_LINKER; break;
  12.245 +        default:             throw new InternalError("not invoker: "+name);
  12.246 +        }
  12.247 +        LambdaForm lform;
  12.248 +        if (mtype.parameterSlotCount() <= MethodType.MAX_MH_ARITY - MH_LINKER_ARG_APPENDED) {
  12.249 +            lform = invokeHandleForm(mtype, false, which);
  12.250 +            appendixResult[0] = mtype;
  12.251 +        } else {
  12.252 +            lform = invokeHandleForm(mtype, true, which);
  12.253 +        }
  12.254 +        return lform.vmentry;
  12.255 +    }
  12.256 +
  12.257 +    // argument count to account for trailing "appendix value" (typically the mtype)
  12.258 +    private static final int MH_LINKER_ARG_APPENDED = 1;
  12.259 +
  12.260 +    /** Returns an adapter for invokeExact or generic invoke, as a MH or constant pool linker.
  12.261 +     * If !customized, caller is responsible for supplying, during adapter execution,
  12.262 +     * a copy of the exact mtype.  This is because the adapter might be generalized to
  12.263 +     * a basic type.
  12.264 +     * @param mtype the caller's method type (either basic or full-custom)
  12.265 +     * @param customized whether to use a trailing appendix argument (to carry the mtype)
  12.266 +     * @param which bit-encoded 0x01 whether it is a CP adapter ("linker") or MHs.invoker value ("invoker");
  12.267 +     *                          0x02 whether it is for invokeExact or generic invoke
  12.268 +     */
  12.269 +    private static LambdaForm invokeHandleForm(MethodType mtype, boolean customized, int which) {
  12.270 +        boolean isCached;
  12.271 +        if (!customized) {
  12.272 +            mtype = mtype.basicType();  // normalize Z to I, String to Object, etc.
  12.273 +            isCached = true;
  12.274 +        } else {
  12.275 +            isCached = false;  // maybe cache if mtype == mtype.basicType()
  12.276 +        }
  12.277 +        boolean isLinker, isGeneric;
  12.278 +        String debugName;
  12.279 +        switch (which) {
  12.280 +        case MethodTypeForm.LF_EX_LINKER:   isLinker = true;  isGeneric = false; debugName = "invokeExact_MT"; break;
  12.281 +        case MethodTypeForm.LF_EX_INVOKER:  isLinker = false; isGeneric = false; debugName = "exactInvoker"; break;
  12.282 +        case MethodTypeForm.LF_GEN_LINKER:  isLinker = true;  isGeneric = true;  debugName = "invoke_MT"; break;
  12.283 +        case MethodTypeForm.LF_GEN_INVOKER: isLinker = false; isGeneric = true;  debugName = "invoker"; break;
  12.284 +        default: throw new InternalError();
  12.285 +        }
  12.286 +        LambdaForm lform;
  12.287 +        if (isCached) {
  12.288 +            lform = mtype.form().cachedLambdaForm(which);
  12.289 +            if (lform != null)  return lform;
  12.290 +        }
  12.291 +        // exactInvokerForm (Object,Object)Object
  12.292 +        //   link with java.lang.invoke.MethodHandle.invokeBasic(MethodHandle,Object,Object)Object/invokeSpecial
  12.293 +        final int THIS_MH      = 0;
  12.294 +        final int CALL_MH      = THIS_MH + (isLinker ? 0 : 1);
  12.295 +        final int ARG_BASE     = CALL_MH + 1;
  12.296 +        final int OUTARG_LIMIT = ARG_BASE + mtype.parameterCount();
  12.297 +        final int INARG_LIMIT  = OUTARG_LIMIT + (isLinker && !customized ? 1 : 0);
  12.298 +        int nameCursor = OUTARG_LIMIT;
  12.299 +        final int MTYPE_ARG    = customized ? -1 : nameCursor++;  // might be last in-argument
  12.300 +        final int CHECK_TYPE   = nameCursor++;
  12.301 +        final int LINKER_CALL  = nameCursor++;
  12.302 +        MethodType invokerFormType = mtype.invokerType();
  12.303 +        if (isLinker) {
  12.304 +            if (!customized)
  12.305 +                invokerFormType = invokerFormType.appendParameterTypes(MemberName.class);
  12.306 +        } else {
  12.307 +            invokerFormType = invokerFormType.invokerType();
  12.308 +        }
  12.309 +        Name[] names = arguments(nameCursor - INARG_LIMIT, invokerFormType);
  12.310 +        assert(names.length == nameCursor)
  12.311 +                : Arrays.asList(mtype, customized, which, nameCursor, names.length);
  12.312 +        if (MTYPE_ARG >= INARG_LIMIT) {
  12.313 +            assert(names[MTYPE_ARG] == null);
  12.314 +            NamedFunction getter = BoundMethodHandle.getSpeciesData("L").getterFunction(0);
  12.315 +            names[MTYPE_ARG] = new Name(getter, names[THIS_MH]);
  12.316 +            // else if isLinker, then MTYPE is passed in from the caller (e.g., the JVM)
  12.317 +        }
  12.318 +
  12.319 +        // Make the final call.  If isGeneric, then prepend the result of type checking.
  12.320 +        MethodType outCallType = mtype.basicType();
  12.321 +        Object[] outArgs = Arrays.copyOfRange(names, CALL_MH, OUTARG_LIMIT, Object[].class);
  12.322 +        Object mtypeArg = (customized ? mtype : names[MTYPE_ARG]);
  12.323 +        if (!isGeneric) {
  12.324 +            names[CHECK_TYPE] = new Name(NF_checkExactType, names[CALL_MH], mtypeArg);
  12.325 +            // mh.invokeExact(a*):R => checkExactType(mh, TYPEOF(a*:R)); mh.invokeBasic(a*)
  12.326 +        } else {
  12.327 +            names[CHECK_TYPE] = new Name(NF_checkGenericType, names[CALL_MH], mtypeArg);
  12.328 +            // mh.invokeGeneric(a*):R => checkGenericType(mh, TYPEOF(a*:R)).invokeBasic(a*)
  12.329 +            outArgs[0] = names[CHECK_TYPE];
  12.330 +        }
  12.331 +        names[LINKER_CALL] = new Name(outCallType, outArgs);
  12.332 +        lform = new LambdaForm(debugName, INARG_LIMIT, names);
  12.333 +        if (isLinker)
  12.334 +            lform.compileToBytecode();  // JVM needs a real methodOop
  12.335 +        if (isCached)
  12.336 +            lform = mtype.form().setCachedLambdaForm(which, lform);
  12.337 +        return lform;
  12.338 +    }
  12.339 +
  12.340 +    /*non-public*/ static
  12.341 +    WrongMethodTypeException newWrongMethodTypeException(MethodType actual, MethodType expected) {
  12.342 +        // FIXME: merge with JVM logic for throwing WMTE
  12.343 +        return new WrongMethodTypeException("expected "+expected+" but found "+actual);
  12.344 +    }
  12.345 +
  12.346 +    /** Static definition of MethodHandle.invokeExact checking code. */
  12.347 +    /*non-public*/ static
  12.348 +    @ForceInline
  12.349 +    void checkExactType(Object mhObj, Object expectedObj) {
  12.350 +        MethodHandle mh = (MethodHandle) mhObj;
  12.351 +        MethodType expected = (MethodType) expectedObj;
  12.352 +        MethodType actual = mh.type();
  12.353 +        if (actual != expected)
  12.354 +            throw newWrongMethodTypeException(expected, actual);
  12.355 +    }
  12.356 +
  12.357 +    /** Static definition of MethodHandle.invokeGeneric checking code.
  12.358 +     * Directly returns the type-adjusted MH to invoke, as follows:
  12.359 +     * {@code (R)MH.invoke(a*) => MH.asType(TYPEOF(a*:R)).invokeBasic(a*)}
  12.360 +     */
  12.361 +    /*non-public*/ static
  12.362 +    @ForceInline
  12.363 +    Object checkGenericType(Object mhObj, Object expectedObj) {
  12.364 +        MethodHandle mh = (MethodHandle) mhObj;
  12.365 +        MethodType expected = (MethodType) expectedObj;
  12.366 +        if (mh.type() == expected)  return mh;
  12.367 +        MethodHandle atc = mh.asTypeCache;
  12.368 +        if (atc != null && atc.type() == expected)  return atc;
  12.369 +        return mh.asType(expected);
  12.370 +        /* Maybe add more paths here.  Possible optimizations:
  12.371 +         * for (R)MH.invoke(a*),
  12.372 +         * let MT0 = TYPEOF(a*:R), MT1 = MH.type
  12.373 +         *
  12.374 +         * if MT0==MT1 or MT1 can be safely called by MT0
  12.375 +         *  => MH.invokeBasic(a*)
  12.376 +         * if MT1 can be safely called by MT0[R := Object]
  12.377 +         *  => MH.invokeBasic(a*) & checkcast(R)
  12.378 +         * if MT1 can be safely called by MT0[* := Object]
  12.379 +         *  => checkcast(A)* & MH.invokeBasic(a*) & checkcast(R)
  12.380 +         * if a big adapter BA can be pulled out of (MT0,MT1)
  12.381 +         *  => BA.invokeBasic(MT0,MH,a*)
  12.382 +         * if a local adapter LA can cached on static CS0 = new GICS(MT0)
  12.383 +         *  => CS0.LA.invokeBasic(MH,a*)
  12.384 +         * else
  12.385 +         *  => MH.asType(MT0).invokeBasic(A*)
  12.386 +         */
  12.387 +    }
  12.388 +
  12.389 +    static MemberName linkToCallSiteMethod(MethodType mtype) {
  12.390 +        LambdaForm lform = callSiteForm(mtype, false);
  12.391 +        return lform.vmentry;
  12.392 +    }
  12.393 +
  12.394 +    static MemberName linkToTargetMethod(MethodType mtype) {
  12.395 +        LambdaForm lform = callSiteForm(mtype, true);
  12.396 +        return lform.vmentry;
  12.397 +    }
  12.398 +
  12.399 +    // skipCallSite is true if we are optimizing a ConstantCallSite
  12.400 +    private static LambdaForm callSiteForm(MethodType mtype, boolean skipCallSite) {
  12.401 +        mtype = mtype.basicType();  // normalize Z to I, String to Object, etc.
  12.402 +        final int which = (skipCallSite ? MethodTypeForm.LF_MH_LINKER : MethodTypeForm.LF_CS_LINKER);
  12.403 +        LambdaForm lform = mtype.form().cachedLambdaForm(which);
  12.404 +        if (lform != null)  return lform;
  12.405 +        // exactInvokerForm (Object,Object)Object
  12.406 +        //   link with java.lang.invoke.MethodHandle.invokeBasic(MethodHandle,Object,Object)Object/invokeSpecial
  12.407 +        final int ARG_BASE     = 0;
  12.408 +        final int OUTARG_LIMIT = ARG_BASE + mtype.parameterCount();
  12.409 +        final int INARG_LIMIT  = OUTARG_LIMIT + 1;
  12.410 +        int nameCursor = OUTARG_LIMIT;
  12.411 +        final int APPENDIX_ARG = nameCursor++;  // the last in-argument
  12.412 +        final int CSITE_ARG    = skipCallSite ? -1 : APPENDIX_ARG;
  12.413 +        final int CALL_MH      = skipCallSite ? APPENDIX_ARG : nameCursor++;  // result of getTarget
  12.414 +        final int LINKER_CALL  = nameCursor++;
  12.415 +        MethodType invokerFormType = mtype.appendParameterTypes(skipCallSite ? MethodHandle.class : CallSite.class);
  12.416 +        Name[] names = arguments(nameCursor - INARG_LIMIT, invokerFormType);
  12.417 +        assert(names.length == nameCursor);
  12.418 +        assert(names[APPENDIX_ARG] != null);
  12.419 +        if (!skipCallSite)
  12.420 +            names[CALL_MH] = new Name(NF_getCallSiteTarget, names[CSITE_ARG]);
  12.421 +        // (site.)invokedynamic(a*):R => mh = site.getTarget(); mh.invokeBasic(a*)
  12.422 +        final int PREPEND_MH = 0, PREPEND_COUNT = 1;
  12.423 +        Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, OUTARG_LIMIT + PREPEND_COUNT, Object[].class);
  12.424 +        // prepend MH argument:
  12.425 +        System.arraycopy(outArgs, 0, outArgs, PREPEND_COUNT, outArgs.length - PREPEND_COUNT);
  12.426 +        outArgs[PREPEND_MH] = names[CALL_MH];
  12.427 +        names[LINKER_CALL] = new Name(mtype, outArgs);
  12.428 +        lform = new LambdaForm((skipCallSite ? "linkToTargetMethod" : "linkToCallSite"), INARG_LIMIT, names);
  12.429 +        lform.compileToBytecode();  // JVM needs a real methodOop
  12.430 +        lform = mtype.form().setCachedLambdaForm(which, lform);
  12.431 +        return lform;
  12.432 +    }
  12.433 +
  12.434 +    /** Static definition of MethodHandle.invokeGeneric checking code. */
  12.435 +    /*non-public*/ static
  12.436 +    @ForceInline
  12.437 +    Object getCallSiteTarget(Object site) {
  12.438 +        return ((CallSite)site).getTarget();
  12.439 +    }
  12.440 +
  12.441 +    // Local constant functions:
  12.442 +    private static final NamedFunction NF_checkExactType;
  12.443 +    private static final NamedFunction NF_checkGenericType;
  12.444 +    private static final NamedFunction NF_asType;
  12.445 +    private static final NamedFunction NF_getCallSiteTarget;
  12.446 +    static {
  12.447 +        try {
  12.448 +            NF_checkExactType = new NamedFunction(Invokers.class
  12.449 +                    .getDeclaredMethod("checkExactType", Object.class, Object.class));
  12.450 +            NF_checkGenericType = new NamedFunction(Invokers.class
  12.451 +                    .getDeclaredMethod("checkGenericType", Object.class, Object.class));
  12.452 +            NF_asType = new NamedFunction(MethodHandle.class
  12.453 +                    .getDeclaredMethod("asType", MethodType.class));
  12.454 +            NF_getCallSiteTarget = new NamedFunction(Invokers.class
  12.455 +                    .getDeclaredMethod("getCallSiteTarget", Object.class));
  12.456 +            NF_checkExactType.resolve();
  12.457 +            NF_checkGenericType.resolve();
  12.458 +            NF_getCallSiteTarget.resolve();
  12.459 +            // bound
  12.460 +        } catch (ReflectiveOperationException ex) {
  12.461 +            throw newInternalError(ex);
  12.462 +        }
  12.463 +    }
  12.464 +
  12.465 +}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/LambdaConversionException.java	Sat Aug 09 11:12:05 2014 +0200
    13.3 @@ -0,0 +1,76 @@
    13.4 +/*
    13.5 + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
    13.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    13.7 + *
    13.8 + * This code is free software; you can redistribute it and/or modify it
    13.9 + * under the terms of the GNU General Public License version 2 only, as
   13.10 + * published by the Free Software Foundation.  Oracle designates this
   13.11 + * particular file as subject to the "Classpath" exception as provided
   13.12 + * by Oracle in the LICENSE file that accompanied this code.
   13.13 + *
   13.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   13.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   13.17 + * version 2 for more details (a copy is included in the LICENSE file that
   13.18 + * accompanied this code).
   13.19 + *
   13.20 + * You should have received a copy of the GNU General Public License version
   13.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   13.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   13.23 + *
   13.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   13.25 + * or visit www.oracle.com if you need additional information or have any
   13.26 + * questions.
   13.27 + */
   13.28 +
   13.29 +package java.lang.invoke;
   13.30 +
   13.31 +/**
   13.32 + * LambdaConversionException
   13.33 + */
   13.34 +public class LambdaConversionException extends Exception {
   13.35 +    private static final long serialVersionUID = 292L + 8L;
   13.36 +
   13.37 +    /**
   13.38 +     * Constructs a {@code LambdaConversionException}.
   13.39 +     */
   13.40 +    public LambdaConversionException() {
   13.41 +    }
   13.42 +
   13.43 +    /**
   13.44 +     * Constructs a {@code LambdaConversionException} with a message.
   13.45 +     * @param message the detail message
   13.46 +     */
   13.47 +    public LambdaConversionException(String message) {
   13.48 +        super(message);
   13.49 +    }
   13.50 +
   13.51 +    /**
   13.52 +     * Constructs a {@code LambdaConversionException} with a message and cause.
   13.53 +     * @param message the detail message
   13.54 +     * @param cause the cause
   13.55 +     */
   13.56 +    public LambdaConversionException(String message, Throwable cause) {
   13.57 +        super(message, cause);
   13.58 +    }
   13.59 +
   13.60 +    /**
   13.61 +     * Constructs a {@code LambdaConversionException} with a cause.
   13.62 +     * @param cause the cause
   13.63 +     */
   13.64 +    public LambdaConversionException(Throwable cause) {
   13.65 +        super(cause);
   13.66 +    }
   13.67 +
   13.68 +    /**
   13.69 +     * Constructs a {@code LambdaConversionException} with a message,
   13.70 +     * cause, and other settings.
   13.71 +     * @param message the detail message
   13.72 +     * @param cause the cause
   13.73 +     * @param enableSuppression whether or not suppressed exceptions are enabled
   13.74 +     * @param writableStackTrace whether or not the stack trace is writable
   13.75 +     */
   13.76 +    public LambdaConversionException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
   13.77 +        super(message, cause, enableSuppression, writableStackTrace);
   13.78 +    }
   13.79 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/LambdaForm.java	Sat Aug 09 11:12:05 2014 +0200
    14.3 @@ -0,0 +1,1646 @@
    14.4 +/*
    14.5 + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
    14.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    14.7 + *
    14.8 + * This code is free software; you can redistribute it and/or modify it
    14.9 + * under the terms of the GNU General Public License version 2 only, as
   14.10 + * published by the Free Software Foundation.  Oracle designates this
   14.11 + * particular file as subject to the "Classpath" exception as provided
   14.12 + * by Oracle in the LICENSE file that accompanied this code.
   14.13 + *
   14.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   14.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   14.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14.17 + * version 2 for more details (a copy is included in the LICENSE file that
   14.18 + * accompanied this code).
   14.19 + *
   14.20 + * You should have received a copy of the GNU General Public License version
   14.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   14.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   14.23 + *
   14.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   14.25 + * or visit www.oracle.com if you need additional information or have any
   14.26 + * questions.
   14.27 + */
   14.28 +
   14.29 +package java.lang.invoke;
   14.30 +
   14.31 +import java.lang.annotation.*;
   14.32 +import java.lang.reflect.Method;
   14.33 +import java.util.Map;
   14.34 +import java.util.List;
   14.35 +import java.util.Arrays;
   14.36 +import java.util.ArrayList;
   14.37 +import java.util.HashMap;
   14.38 +import java.util.concurrent.ConcurrentHashMap;
   14.39 +import sun.invoke.util.Wrapper;
   14.40 +import static java.lang.invoke.MethodHandleStatics.*;
   14.41 +import static java.lang.invoke.MethodHandleNatives.Constants.*;
   14.42 +import java.lang.reflect.Field;
   14.43 +import java.util.Objects;
   14.44 +
   14.45 +/**
   14.46 + * The symbolic, non-executable form of a method handle's invocation semantics.
   14.47 + * It consists of a series of names.
   14.48 + * The first N (N=arity) names are parameters,
   14.49 + * while any remaining names are temporary values.
   14.50 + * Each temporary specifies the application of a function to some arguments.
   14.51 + * The functions are method handles, while the arguments are mixes of
   14.52 + * constant values and local names.
   14.53 + * The result of the lambda is defined as one of the names, often the last one.
   14.54 + * <p>
   14.55 + * Here is an approximate grammar:
   14.56 + * <blockquote><pre>{@code
   14.57 + * LambdaForm = "(" ArgName* ")=>{" TempName* Result "}"
   14.58 + * ArgName = "a" N ":" T
   14.59 + * TempName = "t" N ":" T "=" Function "(" Argument* ");"
   14.60 + * Function = ConstantValue
   14.61 + * Argument = NameRef | ConstantValue
   14.62 + * Result = NameRef | "void"
   14.63 + * NameRef = "a" N | "t" N
   14.64 + * N = (any whole number)
   14.65 + * T = "L" | "I" | "J" | "F" | "D" | "V"
   14.66 + * }</pre></blockquote>
   14.67 + * Names are numbered consecutively from left to right starting at zero.
   14.68 + * (The letters are merely a taste of syntax sugar.)
   14.69 + * Thus, the first temporary (if any) is always numbered N (where N=arity).
   14.70 + * Every occurrence of a name reference in an argument list must refer to
   14.71 + * a name previously defined within the same lambda.
   14.72 + * A lambda has a void result if and only if its result index is -1.
   14.73 + * If a temporary has the type "V", it cannot be the subject of a NameRef,
   14.74 + * even though possesses a number.
   14.75 + * Note that all reference types are erased to "L", which stands for {@code Object}.
   14.76 + * All subword types (boolean, byte, short, char) are erased to "I" which is {@code int}.
   14.77 + * The other types stand for the usual primitive types.
   14.78 + * <p>
   14.79 + * Function invocation closely follows the static rules of the Java verifier.
   14.80 + * Arguments and return values must exactly match when their "Name" types are
   14.81 + * considered.
   14.82 + * Conversions are allowed only if they do not change the erased type.
   14.83 + * <ul>
   14.84 + * <li>L = Object: casts are used freely to convert into and out of reference types
   14.85 + * <li>I = int: subword types are forcibly narrowed when passed as arguments (see {@code explicitCastArguments})
   14.86 + * <li>J = long: no implicit conversions
   14.87 + * <li>F = float: no implicit conversions
   14.88 + * <li>D = double: no implicit conversions
   14.89 + * <li>V = void: a function result may be void if and only if its Name is of type "V"
   14.90 + * </ul>
   14.91 + * Although implicit conversions are not allowed, explicit ones can easily be
   14.92 + * encoded by using temporary expressions which call type-transformed identity functions.
   14.93 + * <p>
   14.94 + * Examples:
   14.95 + * <blockquote><pre>{@code
   14.96 + * (a0:J)=>{ a0 }
   14.97 + *     == identity(long)
   14.98 + * (a0:I)=>{ t1:V = System.out#println(a0); void }
   14.99 + *     == System.out#println(int)
  14.100 + * (a0:L)=>{ t1:V = System.out#println(a0); a0 }
  14.101 + *     == identity, with printing side-effect
  14.102 + * (a0:L, a1:L)=>{ t2:L = BoundMethodHandle#argument(a0);
  14.103 + *                 t3:L = BoundMethodHandle#target(a0);
  14.104 + *                 t4:L = MethodHandle#invoke(t3, t2, a1); t4 }
  14.105 + *     == general invoker for unary insertArgument combination
  14.106 + * (a0:L, a1:L)=>{ t2:L = FilterMethodHandle#filter(a0);
  14.107 + *                 t3:L = MethodHandle#invoke(t2, a1);
  14.108 + *                 t4:L = FilterMethodHandle#target(a0);
  14.109 + *                 t5:L = MethodHandle#invoke(t4, t3); t5 }
  14.110 + *     == general invoker for unary filterArgument combination
  14.111 + * (a0:L, a1:L)=>{ ...(same as previous example)...
  14.112 + *                 t5:L = MethodHandle#invoke(t4, t3, a1); t5 }
  14.113 + *     == general invoker for unary/unary foldArgument combination
  14.114 + * (a0:L, a1:I)=>{ t2:I = identity(long).asType((int)->long)(a1); t2 }
  14.115 + *     == invoker for identity method handle which performs i2l
  14.116 + * (a0:L, a1:L)=>{ t2:L = BoundMethodHandle#argument(a0);
  14.117 + *                 t3:L = Class#cast(t2,a1); t3 }
  14.118 + *     == invoker for identity method handle which performs cast
  14.119 + * }</pre></blockquote>
  14.120 + * <p>
  14.121 + * @author John Rose, JSR 292 EG
  14.122 + */
  14.123 +class LambdaForm {
  14.124 +    final int arity;
  14.125 +    final int result;
  14.126 +    @Stable final Name[] names;
  14.127 +    final String debugName;
  14.128 +    MemberName vmentry;   // low-level behavior, or null if not yet prepared
  14.129 +    private boolean isCompiled;
  14.130 +
  14.131 +    // Caches for common structural transforms:
  14.132 +    LambdaForm[] bindCache;
  14.133 +
  14.134 +    public static final int VOID_RESULT = -1, LAST_RESULT = -2;
  14.135 +
  14.136 +    LambdaForm(String debugName,
  14.137 +               int arity, Name[] names, int result) {
  14.138 +        assert(namesOK(arity, names));
  14.139 +        this.arity = arity;
  14.140 +        this.result = fixResult(result, names);
  14.141 +        this.names = names.clone();
  14.142 +        this.debugName = debugName;
  14.143 +        normalize();
  14.144 +    }
  14.145 +
  14.146 +    LambdaForm(String debugName,
  14.147 +               int arity, Name[] names) {
  14.148 +        this(debugName,
  14.149 +             arity, names, LAST_RESULT);
  14.150 +    }
  14.151 +
  14.152 +    LambdaForm(String debugName,
  14.153 +               Name[] formals, Name[] temps, Name result) {
  14.154 +        this(debugName,
  14.155 +             formals.length, buildNames(formals, temps, result), LAST_RESULT);
  14.156 +    }
  14.157 +
  14.158 +    private static Name[] buildNames(Name[] formals, Name[] temps, Name result) {
  14.159 +        int arity = formals.length;
  14.160 +        int length = arity + temps.length + (result == null ? 0 : 1);
  14.161 +        Name[] names = Arrays.copyOf(formals, length);
  14.162 +        System.arraycopy(temps, 0, names, arity, temps.length);
  14.163 +        if (result != null)
  14.164 +            names[length - 1] = result;
  14.165 +        return names;
  14.166 +    }
  14.167 +
  14.168 +    private LambdaForm(String sig) {
  14.169 +        // Make a blank lambda form, which returns a constant zero or null.
  14.170 +        // It is used as a template for managing the invocation of similar forms that are non-empty.
  14.171 +        // Called only from getPreparedForm.
  14.172 +        assert(isValidSignature(sig));
  14.173 +        this.arity = signatureArity(sig);
  14.174 +        this.result = (signatureReturn(sig) == 'V' ? -1 : arity);
  14.175 +        this.names = buildEmptyNames(arity, sig);
  14.176 +        this.debugName = "LF.zero";
  14.177 +        assert(nameRefsAreLegal());
  14.178 +        assert(isEmpty());
  14.179 +        assert(sig.equals(basicTypeSignature()));
  14.180 +    }
  14.181 +
  14.182 +    private static Name[] buildEmptyNames(int arity, String basicTypeSignature) {
  14.183 +        assert(isValidSignature(basicTypeSignature));
  14.184 +        int resultPos = arity + 1;  // skip '_'
  14.185 +        if (arity < 0 || basicTypeSignature.length() != resultPos+1)
  14.186 +            throw new IllegalArgumentException("bad arity for "+basicTypeSignature);
  14.187 +        int numRes = (basicTypeSignature.charAt(resultPos) == 'V' ? 0 : 1);
  14.188 +        Name[] names = arguments(numRes, basicTypeSignature.substring(0, arity));
  14.189 +        for (int i = 0; i < numRes; i++) {
  14.190 +            names[arity + i] = constantZero(arity + i, basicTypeSignature.charAt(resultPos + i));
  14.191 +        }
  14.192 +        return names;
  14.193 +    }
  14.194 +
  14.195 +    private static int fixResult(int result, Name[] names) {
  14.196 +        if (result >= 0) {
  14.197 +            if (names[result].type == 'V')
  14.198 +                return -1;
  14.199 +        } else if (result == LAST_RESULT) {
  14.200 +            return names.length - 1;
  14.201 +        }
  14.202 +        return result;
  14.203 +    }
  14.204 +
  14.205 +    private static boolean namesOK(int arity, Name[] names) {
  14.206 +        for (int i = 0; i < names.length; i++) {
  14.207 +            Name n = names[i];
  14.208 +            assert(n != null) : "n is null";
  14.209 +            if (i < arity)
  14.210 +                assert( n.isParam()) : n + " is not param at " + i;
  14.211 +            else
  14.212 +                assert(!n.isParam()) : n + " is param at " + i;
  14.213 +        }
  14.214 +        return true;
  14.215 +    }
  14.216 +
  14.217 +    /** Renumber and/or replace params so that they are interned and canonically numbered. */
  14.218 +    private void normalize() {
  14.219 +        Name[] oldNames = null;
  14.220 +        int changesStart = 0;
  14.221 +        for (int i = 0; i < names.length; i++) {
  14.222 +            Name n = names[i];
  14.223 +            if (!n.initIndex(i)) {
  14.224 +                if (oldNames == null) {
  14.225 +                    oldNames = names.clone();
  14.226 +                    changesStart = i;
  14.227 +                }
  14.228 +                names[i] = n.cloneWithIndex(i);
  14.229 +            }
  14.230 +        }
  14.231 +        if (oldNames != null) {
  14.232 +            int startFixing = arity;
  14.233 +            if (startFixing <= changesStart)
  14.234 +                startFixing = changesStart+1;
  14.235 +            for (int i = startFixing; i < names.length; i++) {
  14.236 +                Name fixed = names[i].replaceNames(oldNames, names, changesStart, i);
  14.237 +                names[i] = fixed.newIndex(i);
  14.238 +            }
  14.239 +        }
  14.240 +        assert(nameRefsAreLegal());
  14.241 +        int maxInterned = Math.min(arity, INTERNED_ARGUMENT_LIMIT);
  14.242 +        boolean needIntern = false;
  14.243 +        for (int i = 0; i < maxInterned; i++) {
  14.244 +            Name n = names[i], n2 = internArgument(n);
  14.245 +            if (n != n2) {
  14.246 +                names[i] = n2;
  14.247 +                needIntern = true;
  14.248 +            }
  14.249 +        }
  14.250 +        if (needIntern) {
  14.251 +            for (int i = arity; i < names.length; i++) {
  14.252 +                names[i].internArguments();
  14.253 +            }
  14.254 +            assert(nameRefsAreLegal());
  14.255 +        }
  14.256 +    }
  14.257 +
  14.258 +    /**
  14.259 +     * Check that all embedded Name references are localizable to this lambda,
  14.260 +     * and are properly ordered after their corresponding definitions.
  14.261 +     * <p>
  14.262 +     * Note that a Name can be local to multiple lambdas, as long as
  14.263 +     * it possesses the same index in each use site.
  14.264 +     * This allows Name references to be freely reused to construct
  14.265 +     * fresh lambdas, without confusion.
  14.266 +     */
  14.267 +    private boolean nameRefsAreLegal() {
  14.268 +        assert(arity >= 0 && arity <= names.length);
  14.269 +        assert(result >= -1 && result < names.length);
  14.270 +        // Do all names possess an index consistent with their local definition order?
  14.271 +        for (int i = 0; i < arity; i++) {
  14.272 +            Name n = names[i];
  14.273 +            assert(n.index() == i) : Arrays.asList(n.index(), i);
  14.274 +            assert(n.isParam());
  14.275 +        }
  14.276 +        // Also, do all local name references
  14.277 +        for (int i = arity; i < names.length; i++) {
  14.278 +            Name n = names[i];
  14.279 +            assert(n.index() == i);
  14.280 +            for (Object arg : n.arguments) {
  14.281 +                if (arg instanceof Name) {
  14.282 +                    Name n2 = (Name) arg;
  14.283 +                    int i2 = n2.index;
  14.284 +                    assert(0 <= i2 && i2 < names.length) : n.debugString() + ": 0 <= i2 && i2 < names.length: 0 <= " + i2 + " < " + names.length;
  14.285 +                    assert(names[i2] == n2) : Arrays.asList("-1-", i, "-2-", n.debugString(), "-3-", i2, "-4-", n2.debugString(), "-5-", names[i2].debugString(), "-6-", this);
  14.286 +                    assert(i2 < i);  // ref must come after def!
  14.287 +                }
  14.288 +            }
  14.289 +        }
  14.290 +        return true;
  14.291 +    }
  14.292 +
  14.293 +    /** Invoke this form on the given arguments. */
  14.294 +    // final Object invoke(Object... args) throws Throwable {
  14.295 +    //     // NYI: fit this into the fast path?
  14.296 +    //     return interpretWithArguments(args);
  14.297 +    // }
  14.298 +
  14.299 +    /** Report the return type. */
  14.300 +    char returnType() {
  14.301 +        if (result < 0)  return 'V';
  14.302 +        Name n = names[result];
  14.303 +        return n.type;
  14.304 +    }
  14.305 +
  14.306 +    /** Report the N-th argument type. */
  14.307 +    char parameterType(int n) {
  14.308 +        assert(n < arity);
  14.309 +        return names[n].type;
  14.310 +    }
  14.311 +
  14.312 +    /** Report the arity. */
  14.313 +    int arity() {
  14.314 +        return arity;
  14.315 +    }
  14.316 +
  14.317 +    /** Return the method type corresponding to my basic type signature. */
  14.318 +    MethodType methodType() {
  14.319 +        return signatureType(basicTypeSignature());
  14.320 +    }
  14.321 +    /** Return ABC_Z, where the ABC are parameter type characters, and Z is the return type character. */
  14.322 +    final String basicTypeSignature() {
  14.323 +        StringBuilder buf = new StringBuilder(arity() + 3);
  14.324 +        for (int i = 0, a = arity(); i < a; i++)
  14.325 +            buf.append(parameterType(i));
  14.326 +        return buf.append('_').append(returnType()).toString();
  14.327 +    }
  14.328 +    static int signatureArity(String sig) {
  14.329 +        assert(isValidSignature(sig));
  14.330 +        return sig.indexOf('_');
  14.331 +    }
  14.332 +    static char signatureReturn(String sig) {
  14.333 +        return sig.charAt(signatureArity(sig)+1);
  14.334 +    }
  14.335 +    static boolean isValidSignature(String sig) {
  14.336 +        int arity = sig.indexOf('_');
  14.337 +        if (arity < 0)  return false;  // must be of the form *_*
  14.338 +        int siglen = sig.length();
  14.339 +        if (siglen != arity + 2)  return false;  // *_X
  14.340 +        for (int i = 0; i < siglen; i++) {
  14.341 +            if (i == arity)  continue;  // skip '_'
  14.342 +            char c = sig.charAt(i);
  14.343 +            if (c == 'V')
  14.344 +                return (i == siglen - 1 && arity == siglen - 2);
  14.345 +            if (ALL_TYPES.indexOf(c) < 0)  return false; // must be [LIJFD]
  14.346 +        }
  14.347 +        return true;  // [LIJFD]*_[LIJFDV]
  14.348 +    }
  14.349 +    static Class<?> typeClass(char t) {
  14.350 +        switch (t) {
  14.351 +        case 'I': return int.class;
  14.352 +        case 'J': return long.class;
  14.353 +        case 'F': return float.class;
  14.354 +        case 'D': return double.class;
  14.355 +        case 'L': return Object.class;
  14.356 +        case 'V': return void.class;
  14.357 +        default: assert false;
  14.358 +        }
  14.359 +        return null;
  14.360 +    }
  14.361 +    static MethodType signatureType(String sig) {
  14.362 +        Class<?>[] ptypes = new Class<?>[signatureArity(sig)];
  14.363 +        for (int i = 0; i < ptypes.length; i++)
  14.364 +            ptypes[i] = typeClass(sig.charAt(i));
  14.365 +        Class<?> rtype = typeClass(signatureReturn(sig));
  14.366 +        return MethodType.methodType(rtype, ptypes);
  14.367 +    }
  14.368 +
  14.369 +    /*
  14.370 +     * Code generation issues:
  14.371 +     *
  14.372 +     * Compiled LFs should be reusable in general.
  14.373 +     * The biggest issue is how to decide when to pull a name into
  14.374 +     * the bytecode, versus loading a reified form from the MH data.
  14.375 +     *
  14.376 +     * For example, an asType wrapper may require execution of a cast
  14.377 +     * after a call to a MH.  The target type of the cast can be placed
  14.378 +     * as a constant in the LF itself.  This will force the cast type
  14.379 +     * to be compiled into the bytecodes and native code for the MH.
  14.380 +     * Or, the target type of the cast can be erased in the LF, and
  14.381 +     * loaded from the MH data.  (Later on, if the MH as a whole is
  14.382 +     * inlined, the data will flow into the inlined instance of the LF,
  14.383 +     * as a constant, and the end result will be an optimal cast.)
  14.384 +     *
  14.385 +     * This erasure of cast types can be done with any use of
  14.386 +     * reference types.  It can also be done with whole method
  14.387 +     * handles.  Erasing a method handle might leave behind
  14.388 +     * LF code that executes correctly for any MH of a given
  14.389 +     * type, and load the required MH from the enclosing MH's data.
  14.390 +     * Or, the erasure might even erase the expected MT.
  14.391 +     *
  14.392 +     * Also, for direct MHs, the MemberName of the target
  14.393 +     * could be erased, and loaded from the containing direct MH.
  14.394 +     * As a simple case, a LF for all int-valued non-static
  14.395 +     * field getters would perform a cast on its input argument
  14.396 +     * (to non-constant base type derived from the MemberName)
  14.397 +     * and load an integer value from the input object
  14.398 +     * (at a non-constant offset also derived from the MemberName).
  14.399 +     * Such MN-erased LFs would be inlinable back to optimized
  14.400 +     * code, whenever a constant enclosing DMH is available
  14.401 +     * to supply a constant MN from its data.
  14.402 +     *
  14.403 +     * The main problem here is to keep LFs reasonably generic,
  14.404 +     * while ensuring that hot spots will inline good instances.
  14.405 +     * "Reasonably generic" means that we don't end up with
  14.406 +     * repeated versions of bytecode or machine code that do
  14.407 +     * not differ in their optimized form.  Repeated versions
  14.408 +     * of machine would have the undesirable overheads of
  14.409 +     * (a) redundant compilation work and (b) extra I$ pressure.
  14.410 +     * To control repeated versions, we need to be ready to
  14.411 +     * erase details from LFs and move them into MH data,
  14.412 +     * whevener those details are not relevant to significant
  14.413 +     * optimization.  "Significant" means optimization of
  14.414 +     * code that is actually hot.
  14.415 +     *
  14.416 +     * Achieving this may require dynamic splitting of MHs, by replacing
  14.417 +     * a generic LF with a more specialized one, on the same MH,
  14.418 +     * if (a) the MH is frequently executed and (b) the MH cannot
  14.419 +     * be inlined into a containing caller, such as an invokedynamic.
  14.420 +     *
  14.421 +     * Compiled LFs that are no longer used should be GC-able.
  14.422 +     * If they contain non-BCP references, they should be properly
  14.423 +     * interlinked with the class loader(s) that their embedded types
  14.424 +     * depend on.  This probably means that reusable compiled LFs
  14.425 +     * will be tabulated (indexed) on relevant class loaders,
  14.426 +     * or else that the tables that cache them will have weak links.
  14.427 +     */
  14.428 +
  14.429 +    /**
  14.430 +     * Make this LF directly executable, as part of a MethodHandle.
  14.431 +     * Invariant:  Every MH which is invoked must prepare its LF
  14.432 +     * before invocation.
  14.433 +     * (In principle, the JVM could do this very lazily,
  14.434 +     * as a sort of pre-invocation linkage step.)
  14.435 +     */
  14.436 +    public void prepare() {
  14.437 +        if (COMPILE_THRESHOLD == 0) {
  14.438 +            compileToBytecode();
  14.439 +        }
  14.440 +        if (this.vmentry != null) {
  14.441 +            // already prepared (e.g., a primitive DMH invoker form)
  14.442 +            return;
  14.443 +        }
  14.444 +        LambdaForm prep = getPreparedForm(basicTypeSignature());
  14.445 +        this.vmentry = prep.vmentry;
  14.446 +        // TO DO: Maybe add invokeGeneric, invokeWithArguments
  14.447 +    }
  14.448 +
  14.449 +    /** Generate optimizable bytecode for this form. */
  14.450 +    MemberName compileToBytecode() {
  14.451 +        MethodType invokerType = methodType();
  14.452 +        assert(vmentry == null || vmentry.getMethodType().basicType().equals(invokerType));
  14.453 +        if (vmentry != null && isCompiled) {
  14.454 +            return vmentry;  // already compiled somehow
  14.455 +        }
  14.456 +        try {
  14.457 +            vmentry = InvokerBytecodeGenerator.generateCustomizedCode(this, invokerType);
  14.458 +            if (TRACE_INTERPRETER)
  14.459 +                traceInterpreter("compileToBytecode", this);
  14.460 +            isCompiled = true;
  14.461 +            return vmentry;
  14.462 +        } catch (Error | Exception ex) {
  14.463 +            throw newInternalError("compileToBytecode", ex);
  14.464 +        }
  14.465 +    }
  14.466 +
  14.467 +    private static final ConcurrentHashMap<String,LambdaForm> PREPARED_FORMS;
  14.468 +    static {
  14.469 +        int   capacity   = 512;    // expect many distinct signatures over time
  14.470 +        float loadFactor = 0.75f;  // normal default
  14.471 +        int   writers    = 1;
  14.472 +        PREPARED_FORMS = new ConcurrentHashMap<>(capacity, loadFactor, writers);
  14.473 +    }
  14.474 +
  14.475 +    private static Map<String,LambdaForm> computeInitialPreparedForms() {
  14.476 +        // Find all predefined invokers and associate them with canonical empty lambda forms.
  14.477 +        HashMap<String,LambdaForm> forms = new HashMap<>();
  14.478 +        for (MemberName m : MemberName.getFactory().getMethods(LambdaForm.class, false, null, null, null)) {
  14.479 +            if (!m.isStatic() || !m.isPackage())  continue;
  14.480 +            MethodType mt = m.getMethodType();
  14.481 +            if (mt.parameterCount() > 0 &&
  14.482 +                mt.parameterType(0) == MethodHandle.class &&
  14.483 +                m.getName().startsWith("interpret_")) {
  14.484 +                String sig = basicTypeSignature(mt);
  14.485 +                assert(m.getName().equals("interpret" + sig.substring(sig.indexOf('_'))));
  14.486 +                LambdaForm form = new LambdaForm(sig);
  14.487 +                form.vmentry = m;
  14.488 +                mt.form().setCachedLambdaForm(MethodTypeForm.LF_COUNTER, form);
  14.489 +                // FIXME: get rid of PREPARED_FORMS; use MethodTypeForm cache only
  14.490 +                forms.put(sig, form);
  14.491 +            }
  14.492 +        }
  14.493 +        //System.out.println("computeInitialPreparedForms => "+forms);
  14.494 +        return forms;
  14.495 +    }
  14.496 +
  14.497 +    // Set this false to disable use of the interpret_L methods defined in this file.
  14.498 +    private static final boolean USE_PREDEFINED_INTERPRET_METHODS = true;
  14.499 +
  14.500 +    // The following are predefined exact invokers.  The system must build
  14.501 +    // a separate invoker for each distinct signature.
  14.502 +    static Object interpret_L(MethodHandle mh) throws Throwable {
  14.503 +        Object[] av = {mh};
  14.504 +        String sig = null;
  14.505 +        assert(argumentTypesMatch(sig = "L_L", av));
  14.506 +        Object res = mh.form.interpretWithArguments(av);
  14.507 +        assert(returnTypesMatch(sig, av, res));
  14.508 +        return res;
  14.509 +    }
  14.510 +    static Object interpret_L(MethodHandle mh, Object x1) throws Throwable {
  14.511 +        Object[] av = {mh, x1};
  14.512 +        String sig = null;
  14.513 +        assert(argumentTypesMatch(sig = "LL_L", av));
  14.514 +        Object res = mh.form.interpretWithArguments(av);
  14.515 +        assert(returnTypesMatch(sig, av, res));
  14.516 +        return res;
  14.517 +    }
  14.518 +    static Object interpret_L(MethodHandle mh, Object x1, Object x2) throws Throwable {
  14.519 +        Object[] av = {mh, x1, x2};
  14.520 +        String sig = null;
  14.521 +        assert(argumentTypesMatch(sig = "LLL_L", av));
  14.522 +        Object res = mh.form.interpretWithArguments(av);
  14.523 +        assert(returnTypesMatch(sig, av, res));
  14.524 +        return res;
  14.525 +    }
  14.526 +    private static LambdaForm getPreparedForm(String sig) {
  14.527 +        MethodType mtype = signatureType(sig);
  14.528 +        //LambdaForm prep = PREPARED_FORMS.get(sig);
  14.529 +        LambdaForm prep =  mtype.form().cachedLambdaForm(MethodTypeForm.LF_INTERPRET);
  14.530 +        if (prep != null)  return prep;
  14.531 +        assert(isValidSignature(sig));
  14.532 +        prep = new LambdaForm(sig);
  14.533 +        prep.vmentry = InvokerBytecodeGenerator.generateLambdaFormInterpreterEntryPoint(sig);
  14.534 +        //LambdaForm prep2 = PREPARED_FORMS.putIfAbsent(sig.intern(), prep);
  14.535 +        return mtype.form().setCachedLambdaForm(MethodTypeForm.LF_INTERPRET, prep);
  14.536 +    }
  14.537 +
  14.538 +    // The next few routines are called only from assert expressions
  14.539 +    // They verify that the built-in invokers process the correct raw data types.
  14.540 +    private static boolean argumentTypesMatch(String sig, Object[] av) {
  14.541 +        int arity = signatureArity(sig);
  14.542 +        assert(av.length == arity) : "av.length == arity: av.length=" + av.length + ", arity=" + arity;
  14.543 +        assert(av[0] instanceof MethodHandle) : "av[0] not instace of MethodHandle: " + av[0];
  14.544 +        MethodHandle mh = (MethodHandle) av[0];
  14.545 +        MethodType mt = mh.type();
  14.546 +        assert(mt.parameterCount() == arity-1);
  14.547 +        for (int i = 0; i < av.length; i++) {
  14.548 +            Class<?> pt = (i == 0 ? MethodHandle.class : mt.parameterType(i-1));
  14.549 +            assert(valueMatches(sig.charAt(i), pt, av[i]));
  14.550 +        }
  14.551 +        return true;
  14.552 +    }
  14.553 +    private static boolean valueMatches(char tc, Class<?> type, Object x) {
  14.554 +        // The following line is needed because (...)void method handles can use non-void invokers
  14.555 +        if (type == void.class)  tc = 'V';   // can drop any kind of value
  14.556 +        assert tc == basicType(type) : tc + " == basicType(" + type + ")=" + basicType(type);
  14.557 +        switch (tc) {
  14.558 +        case 'I': assert checkInt(type, x)   : "checkInt(" + type + "," + x +")";   break;
  14.559 +        case 'J': assert x instanceof Long   : "instanceof Long: " + x;             break;
  14.560 +        case 'F': assert x instanceof Float  : "instanceof Float: " + x;            break;
  14.561 +        case 'D': assert x instanceof Double : "instanceof Double: " + x;           break;
  14.562 +        case 'L': assert checkRef(type, x)   : "checkRef(" + type + "," + x + ")";  break;
  14.563 +        case 'V': break;  // allow anything here; will be dropped
  14.564 +        default:  assert(false);
  14.565 +        }
  14.566 +        return true;
  14.567 +    }
  14.568 +    private static boolean returnTypesMatch(String sig, Object[] av, Object res) {
  14.569 +        MethodHandle mh = (MethodHandle) av[0];
  14.570 +        return valueMatches(signatureReturn(sig), mh.type().returnType(), res);
  14.571 +    }
  14.572 +    private static boolean checkInt(Class<?> type, Object x) {
  14.573 +        assert(x instanceof Integer);
  14.574 +        if (type == int.class)  return true;
  14.575 +        Wrapper w = Wrapper.forBasicType(type);
  14.576 +        assert(w.isSubwordOrInt());
  14.577 +        Object x1 = Wrapper.INT.wrap(w.wrap(x));
  14.578 +        return x.equals(x1);
  14.579 +    }
  14.580 +    private static boolean checkRef(Class<?> type, Object x) {
  14.581 +        assert(!type.isPrimitive());
  14.582 +        if (x == null)  return true;
  14.583 +        if (type.isInterface())  return true;
  14.584 +        return type.isInstance(x);
  14.585 +    }
  14.586 +
  14.587 +    /** If the invocation count hits the threshold we spin bytecodes and call that subsequently. */
  14.588 +    private static final int COMPILE_THRESHOLD;
  14.589 +    static {
  14.590 +        if (MethodHandleStatics.COMPILE_THRESHOLD != null)
  14.591 +            COMPILE_THRESHOLD = MethodHandleStatics.COMPILE_THRESHOLD;
  14.592 +        else
  14.593 +            COMPILE_THRESHOLD = 30;  // default value
  14.594 +    }
  14.595 +    private int invocationCounter = 0;
  14.596 +
  14.597 +    @Hidden
  14.598 +    @DontInline
  14.599 +    /** Interpretively invoke this form on the given arguments. */
  14.600 +    Object interpretWithArguments(Object... argumentValues) throws Throwable {
  14.601 +        if (TRACE_INTERPRETER)
  14.602 +            return interpretWithArgumentsTracing(argumentValues);
  14.603 +        checkInvocationCounter();
  14.604 +        assert(arityCheck(argumentValues));
  14.605 +        Object[] values = Arrays.copyOf(argumentValues, names.length);
  14.606 +        for (int i = argumentValues.length; i < values.length; i++) {
  14.607 +            values[i] = interpretName(names[i], values);
  14.608 +        }
  14.609 +        return (result < 0) ? null : values[result];
  14.610 +    }
  14.611 +
  14.612 +    @Hidden
  14.613 +    @DontInline
  14.614 +    /** Evaluate a single Name within this form, applying its function to its arguments. */
  14.615 +    Object interpretName(Name name, Object[] values) throws Throwable {
  14.616 +        if (TRACE_INTERPRETER)
  14.617 +            traceInterpreter("| interpretName", name.debugString(), (Object[]) null);
  14.618 +        Object[] arguments = Arrays.copyOf(name.arguments, name.arguments.length, Object[].class);
  14.619 +        for (int i = 0; i < arguments.length; i++) {
  14.620 +            Object a = arguments[i];
  14.621 +            if (a instanceof Name) {
  14.622 +                int i2 = ((Name)a).index();
  14.623 +                assert(names[i2] == a);
  14.624 +                a = values[i2];
  14.625 +                arguments[i] = a;
  14.626 +            }
  14.627 +        }
  14.628 +        return name.function.invokeWithArguments(arguments);
  14.629 +    }
  14.630 +
  14.631 +    private void checkInvocationCounter() {
  14.632 +        if (COMPILE_THRESHOLD != 0 &&
  14.633 +            invocationCounter < COMPILE_THRESHOLD) {
  14.634 +            invocationCounter++;  // benign race
  14.635 +            if (invocationCounter >= COMPILE_THRESHOLD) {
  14.636 +                // Replace vmentry with a bytecode version of this LF.
  14.637 +                compileToBytecode();
  14.638 +            }
  14.639 +        }
  14.640 +    }
  14.641 +    Object interpretWithArgumentsTracing(Object... argumentValues) throws Throwable {
  14.642 +        traceInterpreter("[ interpretWithArguments", this, argumentValues);
  14.643 +        if (invocationCounter < COMPILE_THRESHOLD) {
  14.644 +            int ctr = invocationCounter++;  // benign race
  14.645 +            traceInterpreter("| invocationCounter", ctr);
  14.646 +            if (invocationCounter >= COMPILE_THRESHOLD) {
  14.647 +                compileToBytecode();
  14.648 +            }
  14.649 +        }
  14.650 +        Object rval;
  14.651 +        try {
  14.652 +            assert(arityCheck(argumentValues));
  14.653 +            Object[] values = Arrays.copyOf(argumentValues, names.length);
  14.654 +            for (int i = argumentValues.length; i < values.length; i++) {
  14.655 +                values[i] = interpretName(names[i], values);
  14.656 +            }
  14.657 +            rval = (result < 0) ? null : values[result];
  14.658 +        } catch (Throwable ex) {
  14.659 +            traceInterpreter("] throw =>", ex);
  14.660 +            throw ex;
  14.661 +        }
  14.662 +        traceInterpreter("] return =>", rval);
  14.663 +        return rval;
  14.664 +    }
  14.665 +
  14.666 +    //** This transform is applied (statically) to every name.function. */
  14.667 +    /*
  14.668 +    private static MethodHandle eraseSubwordTypes(MethodHandle mh) {
  14.669 +        MethodType mt = mh.type();
  14.670 +        if (mt.hasPrimitives()) {
  14.671 +            mt = mt.changeReturnType(eraseSubwordType(mt.returnType()));
  14.672 +            for (int i = 0; i < mt.parameterCount(); i++) {
  14.673 +                mt = mt.changeParameterType(i, eraseSubwordType(mt.parameterType(i)));
  14.674 +            }
  14.675 +            mh = MethodHandles.explicitCastArguments(mh, mt);
  14.676 +        }
  14.677 +        return mh;
  14.678 +    }
  14.679 +    private static Class<?> eraseSubwordType(Class<?> type) {
  14.680 +        if (!type.isPrimitive())  return type;
  14.681 +        if (type == int.class)  return type;
  14.682 +        Wrapper w = Wrapper.forPrimitiveType(type);
  14.683 +        if (w.isSubwordOrInt())  return int.class;
  14.684 +        return type;
  14.685 +    }
  14.686 +    */
  14.687 +
  14.688 +    static void traceInterpreter(String event, Object obj, Object... args) {
  14.689 +        if (TRACE_INTERPRETER) {
  14.690 +            System.out.println("LFI: "+event+" "+(obj != null ? obj : "")+(args != null && args.length != 0 ? Arrays.asList(args) : ""));
  14.691 +        }
  14.692 +    }
  14.693 +    static void traceInterpreter(String event, Object obj) {
  14.694 +        traceInterpreter(event, obj, (Object[])null);
  14.695 +    }
  14.696 +    private boolean arityCheck(Object[] argumentValues) {
  14.697 +        assert(argumentValues.length == arity) : arity+"!="+Arrays.asList(argumentValues)+".length";
  14.698 +        // also check that the leading (receiver) argument is somehow bound to this LF:
  14.699 +        assert(argumentValues[0] instanceof MethodHandle) : "not MH: " + argumentValues[0];
  14.700 +        assert(((MethodHandle)argumentValues[0]).internalForm() == this);
  14.701 +        // note:  argument #0 could also be an interface wrapper, in the future
  14.702 +        return true;
  14.703 +    }
  14.704 +
  14.705 +    private boolean isEmpty() {
  14.706 +        if (result < 0)
  14.707 +            return (names.length == arity);
  14.708 +        else if (result == arity && names.length == arity + 1)
  14.709 +            return names[arity].isConstantZero();
  14.710 +        else
  14.711 +            return false;
  14.712 +    }
  14.713 +
  14.714 +    public String toString() {
  14.715 +        StringBuilder buf = new StringBuilder(debugName+"=Lambda(");
  14.716 +        for (int i = 0; i < names.length; i++) {
  14.717 +            if (i == arity)  buf.append(")=>{");
  14.718 +            Name n = names[i];
  14.719 +            if (i >= arity)  buf.append("\n    ");
  14.720 +            buf.append(n);
  14.721 +            if (i < arity) {
  14.722 +                if (i+1 < arity)  buf.append(",");
  14.723 +                continue;
  14.724 +            }
  14.725 +            buf.append("=").append(n.exprString());
  14.726 +            buf.append(";");
  14.727 +        }
  14.728 +        buf.append(result < 0 ? "void" : names[result]).append("}");
  14.729 +        if (TRACE_INTERPRETER) {
  14.730 +            // Extra verbosity:
  14.731 +            buf.append(":").append(basicTypeSignature());
  14.732 +            buf.append("/").append(vmentry);
  14.733 +        }
  14.734 +        return buf.toString();
  14.735 +    }
  14.736 +
  14.737 +    /**
  14.738 +     * Apply immediate binding for a Name in this form indicated by its position relative to the form.
  14.739 +     * The first parameter to a LambdaForm, a0:L, always represents the form's method handle, so 0 is not
  14.740 +     * accepted as valid.
  14.741 +     */
  14.742 +    LambdaForm bindImmediate(int pos, char basicType, Object value) {
  14.743 +        // must be an argument, and the types must match
  14.744 +        assert pos > 0 && pos < arity && names[pos].type == basicType && Name.typesMatch(basicType, value);
  14.745 +
  14.746 +        int arity2 = arity - 1;
  14.747 +        Name[] names2 = new Name[names.length - 1];
  14.748 +        for (int r = 0, w = 0; r < names.length; ++r, ++w) { // (r)ead from names, (w)rite to names2
  14.749 +            Name n = names[r];
  14.750 +            if (n.isParam()) {
  14.751 +                if (n.index == pos) {
  14.752 +                    // do not copy over the argument that is to be replaced with a literal,
  14.753 +                    // but adjust the write index
  14.754 +                    --w;
  14.755 +                } else {
  14.756 +                    names2[w] = new Name(w, n.type);
  14.757 +                }
  14.758 +            } else {
  14.759 +                Object[] arguments2 = new Object[n.arguments.length];
  14.760 +                for (int i = 0; i < n.arguments.length; ++i) {
  14.761 +                    Object arg = n.arguments[i];
  14.762 +                    if (arg instanceof Name) {
  14.763 +                        int ni = ((Name) arg).index;
  14.764 +                        if (ni == pos) {
  14.765 +                            arguments2[i] = value;
  14.766 +                        } else if (ni < pos) {
  14.767 +                            // replacement position not yet passed
  14.768 +                            arguments2[i] = names2[ni];
  14.769 +                        } else {
  14.770 +                            // replacement position passed
  14.771 +                            arguments2[i] = names2[ni - 1];
  14.772 +                        }
  14.773 +                    } else {
  14.774 +                        arguments2[i] = arg;
  14.775 +                    }
  14.776 +                }
  14.777 +                names2[w] = new Name(n.function, arguments2);
  14.778 +                names2[w].initIndex(w);
  14.779 +            }
  14.780 +        }
  14.781 +
  14.782 +        int result2 = result == -1 ? -1 : result - 1;
  14.783 +        return new LambdaForm(debugName, arity2, names2, result2);
  14.784 +    }
  14.785 +
  14.786 +    LambdaForm bind(int namePos, BoundMethodHandle.SpeciesData oldData) {
  14.787 +        Name name = names[namePos];
  14.788 +        BoundMethodHandle.SpeciesData newData = oldData.extendWithType(name.type);
  14.789 +        return bind(name, newData.getterName(names[0], oldData.fieldCount()), oldData, newData);
  14.790 +    }
  14.791 +    LambdaForm bind(Name name, Name binding,
  14.792 +                    BoundMethodHandle.SpeciesData oldData,
  14.793 +                    BoundMethodHandle.SpeciesData newData) {
  14.794 +        int pos = name.index;
  14.795 +        assert(name.isParam());
  14.796 +        assert(!binding.isParam());
  14.797 +        assert(name.type == binding.type);
  14.798 +        assert(0 <= pos && pos < arity && names[pos] == name);
  14.799 +        assert(binding.function.memberDeclaringClassOrNull() == newData.clazz);
  14.800 +        assert(oldData.getters.length == newData.getters.length-1);
  14.801 +        if (bindCache != null) {
  14.802 +            LambdaForm form = bindCache[pos];
  14.803 +            if (form != null) {
  14.804 +                assert(form.contains(binding)) : "form << " + form + " >> does not contain binding << " + binding + " >>";
  14.805 +                return form;
  14.806 +            }
  14.807 +        } else {
  14.808 +            bindCache = new LambdaForm[arity];
  14.809 +        }
  14.810 +        assert(nameRefsAreLegal());
  14.811 +        int arity2 = arity-1;
  14.812 +        Name[] names2 = names.clone();
  14.813 +        names2[pos] = binding;  // we might move this in a moment
  14.814 +
  14.815 +        // The newly created LF will run with a different BMH.
  14.816 +        // Switch over any pre-existing BMH field references to the new BMH class.
  14.817 +        int firstOldRef = -1;
  14.818 +        for (int i = 0; i < names2.length; i++) {
  14.819 +            Name n = names[i];
  14.820 +            if (n.function != null &&
  14.821 +                n.function.memberDeclaringClassOrNull() == oldData.clazz) {
  14.822 +                MethodHandle oldGetter = n.function.resolvedHandle;
  14.823 +                MethodHandle newGetter = null;
  14.824 +                for (int j = 0; j < oldData.getters.length; j++) {
  14.825 +                    if (oldGetter == oldData.getters[j])
  14.826 +                        newGetter =  newData.getters[j];
  14.827 +                }
  14.828 +                if (newGetter != null) {
  14.829 +                    if (firstOldRef < 0)  firstOldRef = i;
  14.830 +                    Name n2 = new Name(newGetter, n.arguments);
  14.831 +                    names2[i] = n2;
  14.832 +                }
  14.833 +            }
  14.834 +        }
  14.835 +
  14.836 +        // Walk over the new list of names once, in forward order.
  14.837 +        // Replace references to 'name' with 'binding'.
  14.838 +        // Replace data structure references to the old BMH species with the new.
  14.839 +        // This might cause a ripple effect, but it will settle in one pass.
  14.840 +        assert(firstOldRef < 0 || firstOldRef > pos);
  14.841 +        for (int i = pos+1; i < names2.length; i++) {
  14.842 +            if (i <= arity2)  continue;
  14.843 +            names2[i] = names2[i].replaceNames(names, names2, pos, i);
  14.844 +        }
  14.845 +
  14.846 +        //  (a0, a1, name=a2, a3, a4)  =>  (a0, a1, a3, a4, binding)
  14.847 +        int insPos = pos;
  14.848 +        for (; insPos+1 < names2.length; insPos++) {
  14.849 +            Name n = names2[insPos+1];
  14.850 +            if (n.isSiblingBindingBefore(binding)) {
  14.851 +                names2[insPos] = n;
  14.852 +            } else {
  14.853 +                break;
  14.854 +            }
  14.855 +        }
  14.856 +        names2[insPos] = binding;
  14.857 +
  14.858 +        // Since we moved some stuff, maybe update the result reference:
  14.859 +        int result2 = result;
  14.860 +        if (result2 == pos)
  14.861 +            result2 = insPos;
  14.862 +        else if (result2 > pos && result2 <= insPos)
  14.863 +            result2 -= 1;
  14.864 +
  14.865 +        return bindCache[pos] = new LambdaForm(debugName, arity2, names2, result2);
  14.866 +    }
  14.867 +
  14.868 +    boolean contains(Name name) {
  14.869 +        int pos = name.index();
  14.870 +        if (pos >= 0) {
  14.871 +            return pos < names.length && name.equals(names[pos]);
  14.872 +        }
  14.873 +        for (int i = arity; i < names.length; i++) {
  14.874 +            if (name.equals(names[i]))
  14.875 +                return true;
  14.876 +        }
  14.877 +        return false;
  14.878 +    }
  14.879 +
  14.880 +    LambdaForm addArguments(int pos, char... types) {
  14.881 +        assert(pos <= arity);
  14.882 +        int length = names.length;
  14.883 +        int inTypes = types.length;
  14.884 +        Name[] names2 = Arrays.copyOf(names, length + inTypes);
  14.885 +        int arity2 = arity + inTypes;
  14.886 +        int result2 = result;
  14.887 +        if (result2 >= arity)
  14.888 +            result2 += inTypes;
  14.889 +        // names array has MH in slot 0; skip it.
  14.890 +        int argpos = pos + 1;
  14.891 +        // Note:  The LF constructor will rename names2[argpos...].
  14.892 +        // Make space for new arguments (shift temporaries).
  14.893 +        System.arraycopy(names, argpos, names2, argpos + inTypes, length - argpos);
  14.894 +        for (int i = 0; i < inTypes; i++) {
  14.895 +            names2[argpos + i] = new Name(types[i]);
  14.896 +        }
  14.897 +        return new LambdaForm(debugName, arity2, names2, result2);
  14.898 +    }
  14.899 +
  14.900 +    LambdaForm addArguments(int pos, List<Class<?>> types) {
  14.901 +        char[] basicTypes = new char[types.size()];
  14.902 +        for (int i = 0; i < basicTypes.length; i++)
  14.903 +            basicTypes[i] = basicType(types.get(i));
  14.904 +        return addArguments(pos, basicTypes);
  14.905 +    }
  14.906 +
  14.907 +    LambdaForm permuteArguments(int skip, int[] reorder, char[] types) {
  14.908 +        // Note:  When inArg = reorder[outArg], outArg is fed by a copy of inArg.
  14.909 +        // The types are the types of the new (incoming) arguments.
  14.910 +        int length = names.length;
  14.911 +        int inTypes = types.length;
  14.912 +        int outArgs = reorder.length;
  14.913 +        assert(skip+outArgs == arity);
  14.914 +        assert(permutedTypesMatch(reorder, types, names, skip));
  14.915 +        int pos = 0;
  14.916 +        // skip trivial first part of reordering:
  14.917 +        while (pos < outArgs && reorder[pos] == pos)  pos += 1;
  14.918 +        Name[] names2 = new Name[length - outArgs + inTypes];
  14.919 +        System.arraycopy(names, 0, names2, 0, skip+pos);
  14.920 +        // copy the body:
  14.921 +        int bodyLength = length - arity;
  14.922 +        System.arraycopy(names, skip+outArgs, names2, skip+inTypes, bodyLength);
  14.923 +        int arity2 = names2.length - bodyLength;
  14.924 +        int result2 = result;
  14.925 +        if (result2 >= 0) {
  14.926 +            if (result2 < skip+outArgs) {
  14.927 +                // return the corresponding inArg
  14.928 +                result2 = reorder[result2-skip];
  14.929 +            } else {
  14.930 +                result2 = result2 - outArgs + inTypes;
  14.931 +            }
  14.932 +        }
  14.933 +        // rework names in the body:
  14.934 +        for (int j = pos; j < outArgs; j++) {
  14.935 +            Name n = names[skip+j];
  14.936 +            int i = reorder[j];
  14.937 +            // replace names[skip+j] by names2[skip+i]
  14.938 +            Name n2 = names2[skip+i];
  14.939 +            if (n2 == null)
  14.940 +                names2[skip+i] = n2 = new Name(types[i]);
  14.941 +            else
  14.942 +                assert(n2.type == types[i]);
  14.943 +            for (int k = arity2; k < names2.length; k++) {
  14.944 +                names2[k] = names2[k].replaceName(n, n2);
  14.945 +            }
  14.946 +        }
  14.947 +        // some names are unused, but must be filled in
  14.948 +        for (int i = skip+pos; i < arity2; i++) {
  14.949 +            if (names2[i] == null)
  14.950 +                names2[i] = argument(i, types[i - skip]);
  14.951 +        }
  14.952 +        for (int j = arity; j < names.length; j++) {
  14.953 +            int i = j - arity + arity2;
  14.954 +            // replace names2[i] by names[j]
  14.955 +            Name n = names[j];
  14.956 +            Name n2 = names2[i];
  14.957 +            if (n != n2) {
  14.958 +                for (int k = i+1; k < names2.length; k++) {
  14.959 +                    names2[k] = names2[k].replaceName(n, n2);
  14.960 +                }
  14.961 +            }
  14.962 +        }
  14.963 +        return new LambdaForm(debugName, arity2, names2, result2);
  14.964 +    }
  14.965 +
  14.966 +    static boolean permutedTypesMatch(int[] reorder, char[] types, Name[] names, int skip) {
  14.967 +        int inTypes = types.length;
  14.968 +        int outArgs = reorder.length;
  14.969 +        for (int i = 0; i < outArgs; i++) {
  14.970 +            assert(names[skip+i].isParam());
  14.971 +            assert(names[skip+i].type == types[reorder[i]]);
  14.972 +        }
  14.973 +        return true;
  14.974 +    }
  14.975 +
  14.976 +    static class NamedFunction {
  14.977 +        final MemberName member;
  14.978 +        @Stable MethodHandle resolvedHandle;
  14.979 +        @Stable MethodHandle invoker;
  14.980 +
  14.981 +        NamedFunction(MethodHandle resolvedHandle) {
  14.982 +            this(resolvedHandle.internalMemberName(), resolvedHandle);
  14.983 +        }
  14.984 +        NamedFunction(MemberName member, MethodHandle resolvedHandle) {
  14.985 +            this.member = member;
  14.986 +            //resolvedHandle = eraseSubwordTypes(resolvedHandle);
  14.987 +            this.resolvedHandle = resolvedHandle;
  14.988 +        }
  14.989 +        NamedFunction(MethodType basicInvokerType) {
  14.990 +            assert(basicInvokerType == basicInvokerType.basicType()) : basicInvokerType;
  14.991 +            if (basicInvokerType.parameterSlotCount() < MethodType.MAX_MH_INVOKER_ARITY) {
  14.992 +                this.resolvedHandle = basicInvokerType.invokers().basicInvoker();
  14.993 +                this.member = resolvedHandle.internalMemberName();
  14.994 +            } else {
  14.995 +                // necessary to pass BigArityTest
  14.996 +                this.member = Invokers.invokeBasicMethod(basicInvokerType);
  14.997 +            }
  14.998 +        }
  14.999 +
 14.1000 +        // The next 3 constructors are used to break circular dependencies on MH.invokeStatic, etc.
 14.1001 +        // Any LambdaForm containing such a member is not interpretable.
 14.1002 +        // This is OK, since all such LFs are prepared with special primitive vmentry points.
 14.1003 +        // And even without the resolvedHandle, the name can still be compiled and optimized.
 14.1004 +        NamedFunction(Method method) {
 14.1005 +            this(new MemberName(method));
 14.1006 +        }
 14.1007 +        NamedFunction(Field field) {
 14.1008 +            this(new MemberName(field));
 14.1009 +        }
 14.1010 +        NamedFunction(MemberName member) {
 14.1011 +            this.member = member;
 14.1012 +            this.resolvedHandle = null;
 14.1013 +        }
 14.1014 +
 14.1015 +        MethodHandle resolvedHandle() {
 14.1016 +            if (resolvedHandle == null)  resolve();
 14.1017 +            return resolvedHandle;
 14.1018 +        }
 14.1019 +
 14.1020 +        void resolve() {
 14.1021 +            resolvedHandle = DirectMethodHandle.make(member);
 14.1022 +        }
 14.1023 +
 14.1024 +        @Override
 14.1025 +        public boolean equals(Object other) {
 14.1026 +            if (this == other) return true;
 14.1027 +            if (other == null) return false;
 14.1028 +            if (!(other instanceof NamedFunction)) return false;
 14.1029 +            NamedFunction that = (NamedFunction) other;
 14.1030 +            return this.member != null && this.member.equals(that.member);
 14.1031 +        }
 14.1032 +
 14.1033 +        @Override
 14.1034 +        public int hashCode() {
 14.1035 +            if (member != null)
 14.1036 +                return member.hashCode();
 14.1037 +            return super.hashCode();
 14.1038 +        }
 14.1039 +
 14.1040 +        // Put the predefined NamedFunction invokers into the table.
 14.1041 +        static void initializeInvokers() {
 14.1042 +            for (MemberName m : MemberName.getFactory().getMethods(NamedFunction.class, false, null, null, null)) {
 14.1043 +                if (!m.isStatic() || !m.isPackage())  continue;
 14.1044 +                MethodType type = m.getMethodType();
 14.1045 +                if (type.equals(INVOKER_METHOD_TYPE) &&
 14.1046 +                    m.getName().startsWith("invoke_")) {
 14.1047 +                    String sig = m.getName().substring("invoke_".length());
 14.1048 +                    int arity = LambdaForm.signatureArity(sig);
 14.1049 +                    MethodType srcType = MethodType.genericMethodType(arity);
 14.1050 +                    if (LambdaForm.signatureReturn(sig) == 'V')
 14.1051 +                        srcType = srcType.changeReturnType(void.class);
 14.1052 +                    MethodTypeForm typeForm = srcType.form();
 14.1053 +                    typeForm.namedFunctionInvoker = DirectMethodHandle.make(m);
 14.1054 +                }
 14.1055 +            }
 14.1056 +        }
 14.1057 +
 14.1058 +        // The following are predefined NamedFunction invokers.  The system must build
 14.1059 +        // a separate invoker for each distinct signature.
 14.1060 +        /** void return type invokers. */
 14.1061 +        @Hidden
 14.1062 +        static Object invoke__V(MethodHandle mh, Object[] a) throws Throwable {
 14.1063 +            assert(a.length == 0);
 14.1064 +            mh.invokeBasic();
 14.1065 +            return null;
 14.1066 +        }
 14.1067 +        @Hidden
 14.1068 +        static Object invoke_L_V(MethodHandle mh, Object[] a) throws Throwable {
 14.1069 +            assert(a.length == 1);
 14.1070 +            mh.invokeBasic(a[0]);
 14.1071 +            return null;
 14.1072 +        }
 14.1073 +        @Hidden
 14.1074 +        static Object invoke_LL_V(MethodHandle mh, Object[] a) throws Throwable {
 14.1075 +            assert(a.length == 2);
 14.1076 +            mh.invokeBasic(a[0], a[1]);
 14.1077 +            return null;
 14.1078 +        }
 14.1079 +        @Hidden
 14.1080 +        static Object invoke_LLL_V(MethodHandle mh, Object[] a) throws Throwable {
 14.1081 +            assert(a.length == 3);
 14.1082 +            mh.invokeBasic(a[0], a[1], a[2]);
 14.1083 +            return null;
 14.1084 +        }
 14.1085 +        @Hidden
 14.1086 +        static Object invoke_LLLL_V(MethodHandle mh, Object[] a) throws Throwable {
 14.1087 +            assert(a.length == 4);
 14.1088 +            mh.invokeBasic(a[0], a[1], a[2], a[3]);
 14.1089 +            return null;
 14.1090 +        }
 14.1091 +        @Hidden
 14.1092 +        static Object invoke_LLLLL_V(MethodHandle mh, Object[] a) throws Throwable {
 14.1093 +            assert(a.length == 5);
 14.1094 +            mh.invokeBasic(a[0], a[1], a[2], a[3], a[4]);
 14.1095 +            return null;
 14.1096 +        }
 14.1097 +        /** Object return type invokers. */
 14.1098 +        @Hidden
 14.1099 +        static Object invoke__L(MethodHandle mh, Object[] a) throws Throwable {
 14.1100 +            assert(a.length == 0);
 14.1101 +            return mh.invokeBasic();
 14.1102 +        }
 14.1103 +        @Hidden
 14.1104 +        static Object invoke_L_L(MethodHandle mh, Object[] a) throws Throwable {
 14.1105 +            assert(a.length == 1);
 14.1106 +            return mh.invokeBasic(a[0]);
 14.1107 +        }
 14.1108 +        @Hidden
 14.1109 +        static Object invoke_LL_L(MethodHandle mh, Object[] a) throws Throwable {
 14.1110 +            assert(a.length == 2);
 14.1111 +            return mh.invokeBasic(a[0], a[1]);
 14.1112 +        }
 14.1113 +        @Hidden
 14.1114 +        static Object invoke_LLL_L(MethodHandle mh, Object[] a) throws Throwable {
 14.1115 +            assert(a.length == 3);
 14.1116 +            return mh.invokeBasic(a[0], a[1], a[2]);
 14.1117 +        }
 14.1118 +        @Hidden
 14.1119 +        static Object invoke_LLLL_L(MethodHandle mh, Object[] a) throws Throwable {
 14.1120 +            assert(a.length == 4);
 14.1121 +            return mh.invokeBasic(a[0], a[1], a[2], a[3]);
 14.1122 +        }
 14.1123 +        @Hidden
 14.1124 +        static Object invoke_LLLLL_L(MethodHandle mh, Object[] a) throws Throwable {
 14.1125 +            assert(a.length == 5);
 14.1126 +            return mh.invokeBasic(a[0], a[1], a[2], a[3], a[4]);
 14.1127 +        }
 14.1128 +
 14.1129 +        static final MethodType INVOKER_METHOD_TYPE =
 14.1130 +            MethodType.methodType(Object.class, MethodHandle.class, Object[].class);
 14.1131 +
 14.1132 +        private static MethodHandle computeInvoker(MethodTypeForm typeForm) {
 14.1133 +            MethodHandle mh = typeForm.namedFunctionInvoker;
 14.1134 +            if (mh != null)  return mh;
 14.1135 +            MemberName invoker = InvokerBytecodeGenerator.generateNamedFunctionInvoker(typeForm);  // this could take a while
 14.1136 +            mh = DirectMethodHandle.make(invoker);
 14.1137 +            MethodHandle mh2 = typeForm.namedFunctionInvoker;
 14.1138 +            if (mh2 != null)  return mh2;  // benign race
 14.1139 +            if (!mh.type().equals(INVOKER_METHOD_TYPE))
 14.1140 +                throw new InternalError(mh.debugString());
 14.1141 +            return typeForm.namedFunctionInvoker = mh;
 14.1142 +        }
 14.1143 +
 14.1144 +        @Hidden
 14.1145 +        Object invokeWithArguments(Object... arguments) throws Throwable {
 14.1146 +            // If we have a cached invoker, call it right away.
 14.1147 +            // NOTE: The invoker always returns a reference value.
 14.1148 +            if (TRACE_INTERPRETER)  return invokeWithArgumentsTracing(arguments);
 14.1149 +            assert(checkArgumentTypes(arguments, methodType()));
 14.1150 +            return invoker().invokeBasic(resolvedHandle(), arguments);
 14.1151 +        }
 14.1152 +
 14.1153 +        @Hidden
 14.1154 +        Object invokeWithArgumentsTracing(Object[] arguments) throws Throwable {
 14.1155 +            Object rval;
 14.1156 +            try {
 14.1157 +                traceInterpreter("[ call", this, arguments);
 14.1158 +                if (invoker == null) {
 14.1159 +                    traceInterpreter("| getInvoker", this);
 14.1160 +                    invoker();
 14.1161 +                }
 14.1162 +                if (resolvedHandle == null) {
 14.1163 +                    traceInterpreter("| resolve", this);
 14.1164 +                    resolvedHandle();
 14.1165 +                }
 14.1166 +                assert(checkArgumentTypes(arguments, methodType()));
 14.1167 +                rval = invoker().invokeBasic(resolvedHandle(), arguments);
 14.1168 +            } catch (Throwable ex) {
 14.1169 +                traceInterpreter("] throw =>", ex);
 14.1170 +                throw ex;
 14.1171 +            }
 14.1172 +            traceInterpreter("] return =>", rval);
 14.1173 +            return rval;
 14.1174 +        }
 14.1175 +
 14.1176 +        private MethodHandle invoker() {
 14.1177 +            if (invoker != null)  return invoker;
 14.1178 +            // Get an invoker and cache it.
 14.1179 +            return invoker = computeInvoker(methodType().form());
 14.1180 +        }
 14.1181 +
 14.1182 +        private static boolean checkArgumentTypes(Object[] arguments, MethodType methodType) {
 14.1183 +            if (true)  return true;  // FIXME
 14.1184 +            MethodType dstType = methodType.form().erasedType();
 14.1185 +            MethodType srcType = dstType.basicType().wrap();
 14.1186 +            Class<?>[] ptypes = new Class<?>[arguments.length];
 14.1187 +            for (int i = 0; i < arguments.length; i++) {
 14.1188 +                Object arg = arguments[i];
 14.1189 +                Class<?> ptype = arg == null ? Object.class : arg.getClass();
 14.1190 +                // If the dest. type is a primitive we keep the
 14.1191 +                // argument type.
 14.1192 +                ptypes[i] = dstType.parameterType(i).isPrimitive() ? ptype : Object.class;
 14.1193 +            }
 14.1194 +            MethodType argType = MethodType.methodType(srcType.returnType(), ptypes).wrap();
 14.1195 +            assert(argType.isConvertibleTo(srcType)) : "wrong argument types: cannot convert " + argType + " to " + srcType;
 14.1196 +            return true;
 14.1197 +        }
 14.1198 +
 14.1199 +        String basicTypeSignature() {
 14.1200 +            //return LambdaForm.basicTypeSignature(resolvedHandle.type());
 14.1201 +            return LambdaForm.basicTypeSignature(methodType());
 14.1202 +        }
 14.1203 +
 14.1204 +        MethodType methodType() {
 14.1205 +            if (resolvedHandle != null)
 14.1206 +                return resolvedHandle.type();
 14.1207 +            else
 14.1208 +                // only for certain internal LFs during bootstrapping
 14.1209 +                return member.getInvocationType();
 14.1210 +        }
 14.1211 +
 14.1212 +        MemberName member() {
 14.1213 +            assert(assertMemberIsConsistent());
 14.1214 +            return member;
 14.1215 +        }
 14.1216 +
 14.1217 +        // Called only from assert.
 14.1218 +        private boolean assertMemberIsConsistent() {
 14.1219 +            if (resolvedHandle instanceof DirectMethodHandle) {
 14.1220 +                MemberName m = resolvedHandle.internalMemberName();
 14.1221 +                assert(m.equals(member));
 14.1222 +            }
 14.1223 +            return true;
 14.1224 +        }
 14.1225 +
 14.1226 +        Class<?> memberDeclaringClassOrNull() {
 14.1227 +            return (member == null) ? null : member.getDeclaringClass();
 14.1228 +        }
 14.1229 +
 14.1230 +        char returnType() {
 14.1231 +            return basicType(methodType().returnType());
 14.1232 +        }
 14.1233 +
 14.1234 +        char parameterType(int n) {
 14.1235 +            return basicType(methodType().parameterType(n));
 14.1236 +        }
 14.1237 +
 14.1238 +        int arity() {
 14.1239 +            //int siglen = member.getMethodType().parameterCount();
 14.1240 +            //if (!member.isStatic())  siglen += 1;
 14.1241 +            //return siglen;
 14.1242 +            return methodType().parameterCount();
 14.1243 +        }
 14.1244 +
 14.1245 +        public String toString() {
 14.1246 +            if (member == null)  return String.valueOf(resolvedHandle);
 14.1247 +            return member.getDeclaringClass().getSimpleName()+"."+member.getName();
 14.1248 +        }
 14.1249 +    }
 14.1250 +
 14.1251 +    void resolve() {
 14.1252 +        for (Name n : names) n.resolve();
 14.1253 +    }
 14.1254 +
 14.1255 +    public static char basicType(Class<?> type) {
 14.1256 +        char c = Wrapper.basicTypeChar(type);
 14.1257 +        if ("ZBSC".indexOf(c) >= 0)  c = 'I';
 14.1258 +        assert("LIJFDV".indexOf(c) >= 0);
 14.1259 +        return c;
 14.1260 +    }
 14.1261 +    public static char[] basicTypes(List<Class<?>> types) {
 14.1262 +        char[] btypes = new char[types.size()];
 14.1263 +        for (int i = 0; i < btypes.length; i++) {
 14.1264 +            btypes[i] = basicType(types.get(i));
 14.1265 +        }
 14.1266 +        return btypes;
 14.1267 +    }
 14.1268 +    public static String basicTypeSignature(MethodType type) {
 14.1269 +        char[] sig = new char[type.parameterCount() + 2];
 14.1270 +        int sigp = 0;
 14.1271 +        for (Class<?> pt : type.parameterList()) {
 14.1272 +            sig[sigp++] = basicType(pt);
 14.1273 +        }
 14.1274 +        sig[sigp++] = '_';
 14.1275 +        sig[sigp++] = basicType(type.returnType());
 14.1276 +        assert(sigp == sig.length);
 14.1277 +        return String.valueOf(sig);
 14.1278 +    }
 14.1279 +
 14.1280 +    static final class Name {
 14.1281 +        final char type;
 14.1282 +        private short index;
 14.1283 +        final NamedFunction function;
 14.1284 +        @Stable final Object[] arguments;
 14.1285 +
 14.1286 +        private Name(int index, char type, NamedFunction function, Object[] arguments) {
 14.1287 +            this.index = (short)index;
 14.1288 +            this.type = type;
 14.1289 +            this.function = function;
 14.1290 +            this.arguments = arguments;
 14.1291 +            assert(this.index == index);
 14.1292 +        }
 14.1293 +        Name(MethodHandle function, Object... arguments) {
 14.1294 +            this(new NamedFunction(function), arguments);
 14.1295 +        }
 14.1296 +        Name(MethodType functionType, Object... arguments) {
 14.1297 +            this(new NamedFunction(functionType), arguments);
 14.1298 +            assert(arguments[0] instanceof Name && ((Name)arguments[0]).type == 'L');
 14.1299 +        }
 14.1300 +        Name(MemberName function, Object... arguments) {
 14.1301 +            this(new NamedFunction(function), arguments);
 14.1302 +        }
 14.1303 +        Name(NamedFunction function, Object... arguments) {
 14.1304 +            this(-1, function.returnType(), function, arguments = arguments.clone());
 14.1305 +            assert(arguments.length == function.arity()) : "arity mismatch: arguments.length=" + arguments.length + " == function.arity()=" + function.arity() + " in " + debugString();
 14.1306 +            for (int i = 0; i < arguments.length; i++)
 14.1307 +                assert(typesMatch(function.parameterType(i), arguments[i])) : "types don't match: function.parameterType(" + i + ")=" + function.parameterType(i) + ", arguments[" + i + "]=" + arguments[i] + " in " + debugString();
 14.1308 +        }
 14.1309 +        Name(int index, char type) {
 14.1310 +            this(index, type, null, null);
 14.1311 +        }
 14.1312 +        Name(char type) {
 14.1313 +            this(-1, type);
 14.1314 +        }
 14.1315 +
 14.1316 +        char type() { return type; }
 14.1317 +        int index() { return index; }
 14.1318 +        boolean initIndex(int i) {
 14.1319 +            if (index != i) {
 14.1320 +                if (index != -1)  return false;
 14.1321 +                index = (short)i;
 14.1322 +            }
 14.1323 +            return true;
 14.1324 +        }
 14.1325 +
 14.1326 +
 14.1327 +        void resolve() {
 14.1328 +            if (function != null)
 14.1329 +                function.resolve();
 14.1330 +        }
 14.1331 +
 14.1332 +        Name newIndex(int i) {
 14.1333 +            if (initIndex(i))  return this;
 14.1334 +            return cloneWithIndex(i);
 14.1335 +        }
 14.1336 +        Name cloneWithIndex(int i) {
 14.1337 +            Object[] newArguments = (arguments == null) ? null : arguments.clone();
 14.1338 +            return new Name(i, type, function, newArguments);
 14.1339 +        }
 14.1340 +        Name replaceName(Name oldName, Name newName) {  // FIXME: use replaceNames uniformly
 14.1341 +            if (oldName == newName)  return this;
 14.1342 +            @SuppressWarnings("LocalVariableHidesMemberVariable")
 14.1343 +            Object[] arguments = this.arguments;
 14.1344 +            if (arguments == null)  return this;
 14.1345 +            boolean replaced = false;
 14.1346 +            for (int j = 0; j < arguments.length; j++) {
 14.1347 +                if (arguments[j] == oldName) {
 14.1348 +                    if (!replaced) {
 14.1349 +                        replaced = true;
 14.1350 +                        arguments = arguments.clone();
 14.1351 +                    }
 14.1352 +                    arguments[j] = newName;
 14.1353 +                }
 14.1354 +            }
 14.1355 +            if (!replaced)  return this;
 14.1356 +            return new Name(function, arguments);
 14.1357 +        }
 14.1358 +        Name replaceNames(Name[] oldNames, Name[] newNames, int start, int end) {
 14.1359 +            @SuppressWarnings("LocalVariableHidesMemberVariable")
 14.1360 +            Object[] arguments = this.arguments;
 14.1361 +            boolean replaced = false;
 14.1362 +        eachArg:
 14.1363 +            for (int j = 0; j < arguments.length; j++) {
 14.1364 +                if (arguments[j] instanceof Name) {
 14.1365 +                    Name n = (Name) arguments[j];
 14.1366 +                    int check = n.index;
 14.1367 +                    // harmless check to see if the thing is already in newNames:
 14.1368 +                    if (check >= 0 && check < newNames.length && n == newNames[check])
 14.1369 +                        continue eachArg;
 14.1370 +                    // n might not have the correct index: n != oldNames[n.index].
 14.1371 +                    for (int i = start; i < end; i++) {
 14.1372 +                        if (n == oldNames[i]) {
 14.1373 +                            if (n == newNames[i])
 14.1374 +                                continue eachArg;
 14.1375 +                            if (!replaced) {
 14.1376 +                                replaced = true;
 14.1377 +                                arguments = arguments.clone();
 14.1378 +                            }
 14.1379 +                            arguments[j] = newNames[i];
 14.1380 +                            continue eachArg;
 14.1381 +                        }
 14.1382 +                    }
 14.1383 +                }
 14.1384 +            }
 14.1385 +            if (!replaced)  return this;
 14.1386 +            return new Name(function, arguments);
 14.1387 +        }
 14.1388 +        void internArguments() {
 14.1389 +            @SuppressWarnings("LocalVariableHidesMemberVariable")
 14.1390 +            Object[] arguments = this.arguments;
 14.1391 +            for (int j = 0; j < arguments.length; j++) {
 14.1392 +                if (arguments[j] instanceof Name) {
 14.1393 +                    Name n = (Name) arguments[j];
 14.1394 +                    if (n.isParam() && n.index < INTERNED_ARGUMENT_LIMIT)
 14.1395 +                        arguments[j] = internArgument(n);
 14.1396 +                }
 14.1397 +            }
 14.1398 +        }
 14.1399 +        boolean isParam() {
 14.1400 +            return function == null;
 14.1401 +        }
 14.1402 +        boolean isConstantZero() {
 14.1403 +            return !isParam() && arguments.length == 0 && function.equals(constantZero(0, type).function);
 14.1404 +        }
 14.1405 +
 14.1406 +        public String toString() {
 14.1407 +            return (isParam()?"a":"t")+(index >= 0 ? index : System.identityHashCode(this))+":"+type;
 14.1408 +        }
 14.1409 +        public String debugString() {
 14.1410 +            String s = toString();
 14.1411 +            return (function == null) ? s : s + "=" + exprString();
 14.1412 +        }
 14.1413 +        public String exprString() {
 14.1414 +            if (function == null)  return "null";
 14.1415 +            StringBuilder buf = new StringBuilder(function.toString());
 14.1416 +            buf.append("(");
 14.1417 +            String cma = "";
 14.1418 +            for (Object a : arguments) {
 14.1419 +                buf.append(cma); cma = ",";
 14.1420 +                if (a instanceof Name || a instanceof Integer)
 14.1421 +                    buf.append(a);
 14.1422 +                else
 14.1423 +                    buf.append("(").append(a).append(")");
 14.1424 +            }
 14.1425 +            buf.append(")");
 14.1426 +            return buf.toString();
 14.1427 +        }
 14.1428 +
 14.1429 +        private static boolean typesMatch(char parameterType, Object object) {
 14.1430 +            if (object instanceof Name) {
 14.1431 +                return ((Name)object).type == parameterType;
 14.1432 +            }
 14.1433 +            switch (parameterType) {
 14.1434 +                case 'I':  return object instanceof Integer;
 14.1435 +                case 'J':  return object instanceof Long;
 14.1436 +                case 'F':  return object instanceof Float;
 14.1437 +                case 'D':  return object instanceof Double;
 14.1438 +            }
 14.1439 +            assert(parameterType == 'L');
 14.1440 +            return true;
 14.1441 +        }
 14.1442 +
 14.1443 +        /**
 14.1444 +         * Does this Name precede the given binding node in some canonical order?
 14.1445 +         * This predicate is used to order data bindings (via insertion sort)
 14.1446 +         * with some stability.
 14.1447 +         */
 14.1448 +        boolean isSiblingBindingBefore(Name binding) {
 14.1449 +            assert(!binding.isParam());
 14.1450 +            if (isParam())  return true;
 14.1451 +            if (function.equals(binding.function) &&
 14.1452 +                arguments.length == binding.arguments.length) {
 14.1453 +                boolean sawInt = false;
 14.1454 +                for (int i = 0; i < arguments.length; i++) {
 14.1455 +                    Object a1 = arguments[i];
 14.1456 +                    Object a2 = binding.arguments[i];
 14.1457 +                    if (!a1.equals(a2)) {
 14.1458 +                        if (a1 instanceof Integer && a2 instanceof Integer) {
 14.1459 +                            if (sawInt)  continue;
 14.1460 +                            sawInt = true;
 14.1461 +                            if ((int)a1 < (int)a2)  continue;  // still might be true
 14.1462 +                        }
 14.1463 +                        return false;
 14.1464 +                    }
 14.1465 +                }
 14.1466 +                return sawInt;
 14.1467 +            }
 14.1468 +            return false;
 14.1469 +        }
 14.1470 +
 14.1471 +        public boolean equals(Name that) {
 14.1472 +            if (this == that)  return true;
 14.1473 +            if (isParam())
 14.1474 +                // each parameter is a unique atom
 14.1475 +                return false;  // this != that
 14.1476 +            return
 14.1477 +                //this.index == that.index &&
 14.1478 +                this.type == that.type &&
 14.1479 +                this.function.equals(that.function) &&
 14.1480 +                Arrays.equals(this.arguments, that.arguments);
 14.1481 +        }
 14.1482 +        @Override
 14.1483 +        public boolean equals(Object x) {
 14.1484 +            return x instanceof Name && equals((Name)x);
 14.1485 +        }
 14.1486 +        @Override
 14.1487 +        public int hashCode() {
 14.1488 +            if (isParam())
 14.1489 +                return index | (type << 8);
 14.1490 +            return function.hashCode() ^ Arrays.hashCode(arguments);
 14.1491 +        }
 14.1492 +    }
 14.1493 +
 14.1494 +    static Name argument(int which, char type) {
 14.1495 +        int tn = ALL_TYPES.indexOf(type);
 14.1496 +        if (tn < 0 || which >= INTERNED_ARGUMENT_LIMIT)
 14.1497 +            return new Name(which, type);
 14.1498 +        return INTERNED_ARGUMENTS[tn][which];
 14.1499 +    }
 14.1500 +    static Name internArgument(Name n) {
 14.1501 +        assert(n.isParam()) : "not param: " + n;
 14.1502 +        assert(n.index < INTERNED_ARGUMENT_LIMIT);
 14.1503 +        return argument(n.index, n.type);
 14.1504 +    }
 14.1505 +    static Name[] arguments(int extra, String types) {
 14.1506 +        int length = types.length();
 14.1507 +        Name[] names = new Name[length + extra];
 14.1508 +        for (int i = 0; i < length; i++)
 14.1509 +            names[i] = argument(i, types.charAt(i));
 14.1510 +        return names;
 14.1511 +    }
 14.1512 +    static Name[] arguments(int extra, char... types) {
 14.1513 +        int length = types.length;
 14.1514 +        Name[] names = new Name[length + extra];
 14.1515 +        for (int i = 0; i < length; i++)
 14.1516 +            names[i] = argument(i, types[i]);
 14.1517 +        return names;
 14.1518 +    }
 14.1519 +    static Name[] arguments(int extra, List<Class<?>> types) {
 14.1520 +        int length = types.size();
 14.1521 +        Name[] names = new Name[length + extra];
 14.1522 +        for (int i = 0; i < length; i++)
 14.1523 +            names[i] = argument(i, basicType(types.get(i)));
 14.1524 +        return names;
 14.1525 +    }
 14.1526 +    static Name[] arguments(int extra, Class<?>... types) {
 14.1527 +        int length = types.length;
 14.1528 +        Name[] names = new Name[length + extra];
 14.1529 +        for (int i = 0; i < length; i++)
 14.1530 +            names[i] = argument(i, basicType(types[i]));
 14.1531 +        return names;
 14.1532 +    }
 14.1533 +    static Name[] arguments(int extra, MethodType types) {
 14.1534 +        int length = types.parameterCount();
 14.1535 +        Name[] names = new Name[length + extra];
 14.1536 +        for (int i = 0; i < length; i++)
 14.1537 +            names[i] = argument(i, basicType(types.parameterType(i)));
 14.1538 +        return names;
 14.1539 +    }
 14.1540 +    static final String ALL_TYPES = "LIJFD";  // omit V, not an argument type
 14.1541 +    static final int INTERNED_ARGUMENT_LIMIT = 10;
 14.1542 +    private static final Name[][] INTERNED_ARGUMENTS
 14.1543 +            = new Name[ALL_TYPES.length()][INTERNED_ARGUMENT_LIMIT];
 14.1544 +    static {
 14.1545 +        for (int tn = 0; tn < ALL_TYPES.length(); tn++) {
 14.1546 +            for (int i = 0; i < INTERNED_ARGUMENTS[tn].length; i++) {
 14.1547 +                char type = ALL_TYPES.charAt(tn);
 14.1548 +                INTERNED_ARGUMENTS[tn][i] = new Name(i, type);
 14.1549 +            }
 14.1550 +        }
 14.1551 +    }
 14.1552 +
 14.1553 +    private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
 14.1554 +
 14.1555 +    static Name constantZero(int which, char type) {
 14.1556 +        return CONSTANT_ZERO[ALL_TYPES.indexOf(type)].newIndex(which);
 14.1557 +    }
 14.1558 +    private static final Name[] CONSTANT_ZERO
 14.1559 +            = new Name[ALL_TYPES.length()];
 14.1560 +    static {
 14.1561 +        for (int tn = 0; tn < ALL_TYPES.length(); tn++) {
 14.1562 +            char bt = ALL_TYPES.charAt(tn);
 14.1563 +            Wrapper wrap = Wrapper.forBasicType(bt);
 14.1564 +            MemberName zmem = new MemberName(LambdaForm.class, "zero"+bt, MethodType.methodType(wrap.primitiveType()), REF_invokeStatic);
 14.1565 +            try {
 14.1566 +                zmem = IMPL_NAMES.resolveOrFail(REF_invokeStatic, zmem, null, NoSuchMethodException.class);
 14.1567 +            } catch (IllegalAccessException|NoSuchMethodException ex) {
 14.1568 +                throw newInternalError(ex);
 14.1569 +            }
 14.1570 +            NamedFunction zcon = new NamedFunction(zmem);
 14.1571 +            Name n = new Name(zcon).newIndex(0);
 14.1572 +            assert(n.type == ALL_TYPES.charAt(tn));
 14.1573 +            CONSTANT_ZERO[tn] = n;
 14.1574 +            assert(n.isConstantZero());
 14.1575 +        }
 14.1576 +    }
 14.1577 +
 14.1578 +    // Avoid appealing to ValueConversions at bootstrap time:
 14.1579 +    private static int zeroI() { return 0; }
 14.1580 +    private static long zeroJ() { return 0; }
 14.1581 +    private static float zeroF() { return 0; }
 14.1582 +    private static double zeroD() { return 0; }
 14.1583 +    private static Object zeroL() { return null; }
 14.1584 +
 14.1585 +    // Put this last, so that previous static inits can run before.
 14.1586 +    static {
 14.1587 +        if (USE_PREDEFINED_INTERPRET_METHODS)
 14.1588 +            PREPARED_FORMS.putAll(computeInitialPreparedForms());
 14.1589 +    }
 14.1590 +
 14.1591 +    /**
 14.1592 +     * Internal marker for byte-compiled LambdaForms.
 14.1593 +     */
 14.1594 +    /*non-public*/
 14.1595 +    @Target(ElementType.METHOD)
 14.1596 +    @Retention(RetentionPolicy.RUNTIME)
 14.1597 +    @interface Compiled {
 14.1598 +    }
 14.1599 +
 14.1600 +    /**
 14.1601 +     * Internal marker for LambdaForm interpreter frames.
 14.1602 +     */
 14.1603 +    /*non-public*/
 14.1604 +    @Target(ElementType.METHOD)
 14.1605 +    @Retention(RetentionPolicy.RUNTIME)
 14.1606 +    @interface Hidden {
 14.1607 +    }
 14.1608 +
 14.1609 +
 14.1610 +/*
 14.1611 +    // Smoke-test for the invokers used in this file.
 14.1612 +    static void testMethodHandleLinkers() throws Throwable {
 14.1613 +        MemberName.Factory lookup = MemberName.getFactory();
 14.1614 +        MemberName asList_MN = new MemberName(Arrays.class, "asList",
 14.1615 +                                              MethodType.methodType(List.class, Object[].class),
 14.1616 +                                              REF_invokeStatic);
 14.1617 +        //MethodHandleNatives.resolve(asList_MN, null);
 14.1618 +        asList_MN = lookup.resolveOrFail(asList_MN, REF_invokeStatic, null, NoSuchMethodException.class);
 14.1619 +        System.out.println("about to call "+asList_MN);
 14.1620 +        Object[] abc = { "a", "bc" };
 14.1621 +        List<?> lst = (List<?>) MethodHandle.linkToStatic(abc, asList_MN);
 14.1622 +        System.out.println("lst="+lst);
 14.1623 +        MemberName toString_MN = new MemberName(Object.class.getMethod("toString"));
 14.1624 +        String s1 = (String) MethodHandle.linkToVirtual(lst, toString_MN);
 14.1625 +        toString_MN = new MemberName(Object.class.getMethod("toString"), true);
 14.1626 +        String s2 = (String) MethodHandle.linkToSpecial(lst, toString_MN);
 14.1627 +        System.out.println("[s1,s2,lst]="+Arrays.asList(s1, s2, lst.toString()));
 14.1628 +        MemberName toArray_MN = new MemberName(List.class.getMethod("toArray"));
 14.1629 +        Object[] arr = (Object[]) MethodHandle.linkToInterface(lst, toArray_MN);
 14.1630 +        System.out.println("toArray="+Arrays.toString(arr));
 14.1631 +    }
 14.1632 +    static { try { testMethodHandleLinkers(); } catch (Throwable ex) { throw new RuntimeException(ex); } }
 14.1633 +    // Requires these definitions in MethodHandle:
 14.1634 +    static final native Object linkToStatic(Object x1, MemberName mn) throws Throwable;
 14.1635 +    static final native Object linkToVirtual(Object x1, MemberName mn) throws Throwable;
 14.1636 +    static final native Object linkToSpecial(Object x1, MemberName mn) throws Throwable;
 14.1637 +    static final native Object linkToInterface(Object x1, MemberName mn) throws Throwable;
 14.1638 + */
 14.1639 +
 14.1640 +    static { NamedFunction.initializeInvokers(); }
 14.1641 +
 14.1642 +    // The following hack is necessary in order to suppress TRACE_INTERPRETER
 14.1643 +    // during execution of the static initializes of this class.
 14.1644 +    // Turning on TRACE_INTERPRETER too early will cause
 14.1645 +    // stack overflows and other misbehavior during attempts to trace events
 14.1646 +    // that occur during LambdaForm.<clinit>.
 14.1647 +    // Therefore, do not move this line higher in this file, and do not remove.
 14.1648 +    private static final boolean TRACE_INTERPRETER = MethodHandleStatics.TRACE_INTERPRETER;
 14.1649 +}
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/LambdaMetafactory.java	Sat Aug 09 11:12:05 2014 +0200
    15.3 @@ -0,0 +1,475 @@
    15.4 +/*
    15.5 + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
    15.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    15.7 + *
    15.8 + * This code is free software; you can redistribute it and/or modify it
    15.9 + * under the terms of the GNU General Public License version 2 only, as
   15.10 + * published by the Free Software Foundation.  Oracle designates this
   15.11 + * particular file as subject to the "Classpath" exception as provided
   15.12 + * by Oracle in the LICENSE file that accompanied this code.
   15.13 + *
   15.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   15.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   15.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   15.17 + * version 2 for more details (a copy is included in the LICENSE file that
   15.18 + * accompanied this code).
   15.19 + *
   15.20 + * You should have received a copy of the GNU General Public License version
   15.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   15.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   15.23 + *
   15.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   15.25 + * or visit www.oracle.com if you need additional information or have any
   15.26 + * questions.
   15.27 + */
   15.28 +
   15.29 +package java.lang.invoke;
   15.30 +
   15.31 +import java.io.Serializable;
   15.32 +import java.util.Arrays;
   15.33 +
   15.34 +/**
   15.35 + * <p>Methods to facilitate the creation of simple "function objects" that
   15.36 + * implement one or more interfaces by delegation to a provided {@link MethodHandle},
   15.37 + * possibly after type adaptation and partial evaluation of arguments.  These
   15.38 + * methods are typically used as <em>bootstrap methods</em> for {@code invokedynamic}
   15.39 + * call sites, to support the <em>lambda expression</em> and <em>method
   15.40 + * reference expression</em> features of the Java Programming Language.
   15.41 + *
   15.42 + * <p>Indirect access to the behavior specified by the provided {@code MethodHandle}
   15.43 + * proceeds in order through three phases:
   15.44 + * <ul>
   15.45 + *     <li><em>Linkage</em> occurs when the methods in this class are invoked.
   15.46 + *     They take as arguments an interface to be implemented (typically a
   15.47 + *     <em>functional interface</em>, one with a single abstract method), a
   15.48 + *     name and signature of a method from that interface to be implemented, a
   15.49 + *     method handle describing the desired implementation behavior
   15.50 + *     for that method, and possibly other additional metadata, and produce a
   15.51 + *     {@link CallSite} whose target can be used to create suitable function
   15.52 + *     objects.  Linkage may involve dynamically loading a new class that
   15.53 + *     implements the target interface. The {@code CallSite} can be considered a
   15.54 + *     "factory" for function objects and so these linkage methods are referred
   15.55 + *     to as "metafactories".</li>
   15.56 + *
   15.57 + *     <li><em>Capture</em> occurs when the {@code CallSite}'s target is
   15.58 + *     invoked, typically through an {@code invokedynamic} call site,
   15.59 + *     producing a function object.  This may occur many times for
   15.60 + *     a single factory {@code CallSite}.  Capture may involve allocation of a
   15.61 + *     new function object, or may return an existing function object.  The
   15.62 + *     behavior {@code MethodHandle} may have additional parameters beyond those
   15.63 + *     of the specified interface method; these are referred to as <em>captured
   15.64 + *     parameters</em>, which must be provided as arguments to the
   15.65 + *     {@code CallSite} target, and which may be early-bound to the behavior
   15.66 + *     {@code MethodHandle}.  The number of captured parameters and their types
   15.67 + *     are determined during linkage.</li>
   15.68 + *
   15.69 + *     <li><em>Invocation</em> occurs when an implemented interface method
   15.70 + *     is invoked on a function object.  This may occur many times for a single
   15.71 + *     function object.  The method referenced by the behavior {@code MethodHandle}
   15.72 + *     is invoked with the captured arguments and any additional arguments
   15.73 + *     provided on invocation, as if by {@link MethodHandle#invoke(Object...)}.</li>
   15.74 + * </ul>
   15.75 + *
   15.76 + * <p>It is sometimes useful to restrict the set of inputs or results permitted
   15.77 + * at invocation.  For example, when the generic interface {@code Predicate<T>}
   15.78 + * is parameterized as {@code Predicate<String>}, the input must be a
   15.79 + * {@code String}, even though the method to implement allows any {@code Object}.
   15.80 + * At linkage time, an additional {@link MethodType} parameter describes the
   15.81 + * "instantiated" method type; on invocation, the arguments and eventual result
   15.82 + * are checked against this {@code MethodType}.
   15.83 + *
   15.84 + * <p>This class provides two forms of linkage methods: a standard version
   15.85 + * ({@link #metafactory(MethodHandles.Lookup, String, MethodType, MethodType, MethodHandle, MethodType)})
   15.86 + * using an optimized protocol, and an alternate version
   15.87 + * {@link #altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)}).
   15.88 + * The alternate version is a generalization of the standard version, providing
   15.89 + * additional control over the behavior of the generated function objects via
   15.90 + * flags and additional arguments.  The alternate version adds the ability to
   15.91 + * manage the following attributes of function objects:
   15.92 + *
   15.93 + * <ul>
   15.94 + *     <li><em>Bridging.</em>  It is sometimes useful to implement multiple
   15.95 + *     variations of the method signature, involving argument or return type
   15.96 + *     adaptation.  This occurs when multiple distinct VM signatures for a method
   15.97 + *     are logically considered to be the same method by the language.  The
   15.98 + *     flag {@code FLAG_BRIDGES} indicates that a list of additional
   15.99 + *     {@code MethodType}s will be provided, each of which will be implemented
  15.100 + *     by the resulting function object.  These methods will share the same
  15.101 + *     name and instantiated type.</li>
  15.102 + *
  15.103 + *     <li><em>Multiple interfaces.</em>  If needed, more than one interface
  15.104 + *     can be implemented by the function object.  (These additional interfaces
  15.105 + *     are typically marker interfaces with no methods.)  The flag {@code FLAG_MARKERS}
  15.106 + *     indicates that a list of additional interfaces will be provided, each of
  15.107 + *     which should be implemented by the resulting function object.</li>
  15.108 + *
  15.109 + *     <li><em>Serializability.</em>  The generated function objects do not
  15.110 + *     generally support serialization.  If desired, {@code FLAG_SERIALIZABLE}
  15.111 + *     can be used to indicate that the function objects should be serializable.
  15.112 + *     Serializable function objects will use, as their serialized form,
  15.113 + *     instances of the class {@code SerializedLambda}, which requires additional
  15.114 + *     assistance from the capturing class (the class described by the
  15.115 + *     {@link MethodHandles.Lookup} parameter {@code caller}); see
  15.116 + *     {@link SerializedLambda} for details.</li>
  15.117 + * </ul>
  15.118 + *
  15.119 + * <p>Assume the linkage arguments are as follows:
  15.120 + * <ul>
  15.121 + *      <li>{@code invokedType} (describing the {@code CallSite} signature) has
  15.122 + *      K parameters of types (D1..Dk) and return type Rd;</li>
  15.123 + *      <li>{@code samMethodType} (describing the implemented method type) has N
  15.124 + *      parameters, of types (U1..Un) and return type Ru;</li>
  15.125 + *      <li>{@code implMethod} (the {@code MethodHandle} providing the
  15.126 + *      implementation has M parameters, of types (A1..Am) and return type Ra
  15.127 + *      (if the method describes an instance method, the method type of this
  15.128 + *      method handle already includes an extra first argument corresponding to
  15.129 + *      the receiver);</li>
  15.130 + *      <li>{@code instantiatedMethodType} (allowing restrictions on invocation)
  15.131 + *      has N parameters, of types (T1..Tn) and return type Rt.</li>
  15.132 + * </ul>
  15.133 + *
  15.134 + * <p>Then the following linkage invariants must hold:
  15.135 + * <ul>
  15.136 + *     <li>Rd is an interface</li>
  15.137 + *     <li>{@code implMethod} is a <em>direct method handle</em></li>
  15.138 + *     <li>{@code samMethodType} and {@code instantiatedMethodType} have the same
  15.139 + *     arity N, and for i=1..N, Ti and Ui are the same type, or Ti and Ui are
  15.140 + *     both reference types and Ti is a subtype of Ui</li>
  15.141 + *     <li>Either Rt and Ru are the same type, or both are reference types and
  15.142 + *     Rt is a subtype of Ru</li>
  15.143 + *     <li>K + N = M</li>
  15.144 + *     <li>For i=1..K, Di = Ai</li>
  15.145 + *     <li>For i=1..N, Ti is adaptable to Aj, where j=i+k</li>
  15.146 + *     <li>The return type Rt is void, or the return type Ra is not void and is
  15.147 + *     adaptable to Rt</li>
  15.148 + * </ul>
  15.149 + *
  15.150 + * <p>Further, at capture time, if {@code implMethod} corresponds to an instance
  15.151 + * method, and there are any capture arguments ({@code K > 0}), then the first
  15.152 + * capture argument (corresponding to the receiver) must be non-null.
  15.153 + *
  15.154 + * <p>A type Q is considered adaptable to S as follows:
  15.155 + * <table summary="adaptable types">
  15.156 + *     <tr><th>Q</th><th>S</th><th>Link-time checks</th><th>Invocation-time checks</th></tr>
  15.157 + *     <tr>
  15.158 + *         <td>Primitive</td><td>Primitive</td>
  15.159 + *         <td>Q can be converted to S via a primitive widening conversion</td>
  15.160 + *         <td>None</td>
  15.161 + *     </tr>
  15.162 + *     <tr>
  15.163 + *         <td>Primitive</td><td>Reference</td>
  15.164 + *         <td>S is a supertype of the Wrapper(Q)</td>
  15.165 + *         <td>Cast from Wrapper(Q) to S</td>
  15.166 + *     </tr>
  15.167 + *     <tr>
  15.168 + *         <td>Reference</td><td>Primitive</td>
  15.169 + *         <td>for parameter types: Q is a primitive wrapper and Primitive(Q)
  15.170 + *         can be widened to S
  15.171 + *         <br>for return types: If Q is a primitive wrapper, check that
  15.172 + *         Primitive(Q) can be widened to S</td>
  15.173 + *         <td>If Q is not a primitive wrapper, cast Q to the base Wrapper(S);
  15.174 + *         for example Number for numeric types</td>
  15.175 + *     </tr>
  15.176 + *     <tr>
  15.177 + *         <td>Reference</td><td>Reference</td>
  15.178 + *         <td>for parameter types: S is a supertype of Q
  15.179 + *         <br>for return types: none</td>
  15.180 + *         <td>Cast from Q to S</td>
  15.181 + *     </tr>
  15.182 + * </table>
  15.183 + *
  15.184 + * @apiNote These linkage methods are designed to support the evaluation
  15.185 + * of <em>lambda expressions</em> and <em>method references</em> in the Java
  15.186 + * Language.  For every lambda expressions or method reference in the source code,
  15.187 + * there is a target type which is a functional interface.  Evaluating a lambda
  15.188 + * expression produces an object of its target type. The recommended mechanism
  15.189 + * for evaluating lambda expressions is to desugar the lambda body to a method,
  15.190 + * invoke an invokedynamic call site whose static argument list describes the
  15.191 + * sole method of the functional interface and the desugared implementation
  15.192 + * method, and returns an object (the lambda object) that implements the target
  15.193 + * type. (For method references, the implementation method is simply the
  15.194 + * referenced method; no desugaring is needed.)
  15.195 + *
  15.196 + * <p>The argument list of the implementation method and the argument list of
  15.197 + * the interface method(s) may differ in several ways.  The implementation
  15.198 + * methods may have additional arguments to accommodate arguments captured by
  15.199 + * the lambda expression; there may also be differences resulting from permitted
  15.200 + * adaptations of arguments, such as casting, boxing, unboxing, and primitive
  15.201 + * widening. (Varargs adaptations are not handled by the metafactories; these are
  15.202 + * expected to be handled by the caller.)
  15.203 + *
  15.204 + * <p>Invokedynamic call sites have two argument lists: a static argument list
  15.205 + * and a dynamic argument list.  The static argument list is stored in the
  15.206 + * constant pool; the dynamic argument is pushed on the operand stack at capture
  15.207 + * time.  The bootstrap method has access to the entire static argument list
  15.208 + * (which in this case, includes information describing the implementation method,
  15.209 + * the target interface, and the target interface method(s)), as well as a
  15.210 + * method signature describing the number and static types (but not the values)
  15.211 + * of the dynamic arguments and the static return type of the invokedynamic site.
  15.212 + *
  15.213 + * @implNote The implementation method is described with a method handle. In
  15.214 + * theory, any method handle could be used. Currently supported are direct method
  15.215 + * handles representing invocation of virtual, interface, constructor and static
  15.216 + * methods.
  15.217 + */
  15.218 +public class LambdaMetafactory {
  15.219 +
  15.220 +    /** Flag for alternate metafactories indicating the lambda object
  15.221 +     * must be serializable */
  15.222 +    public static final int FLAG_SERIALIZABLE = 1 << 0;
  15.223 +
  15.224 +    /**
  15.225 +     * Flag for alternate metafactories indicating the lambda object implements
  15.226 +     * other marker interfaces
  15.227 +     * besides Serializable
  15.228 +     */
  15.229 +    public static final int FLAG_MARKERS = 1 << 1;
  15.230 +
  15.231 +    /**
  15.232 +     * Flag for alternate metafactories indicating the lambda object requires
  15.233 +     * additional bridge methods
  15.234 +     */
  15.235 +    public static final int FLAG_BRIDGES = 1 << 2;
  15.236 +
  15.237 +    private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
  15.238 +    private static final MethodType[] EMPTY_MT_ARRAY = new MethodType[0];
  15.239 +
  15.240 +    /**
  15.241 +     * Facilitates the creation of simple "function objects" that implement one
  15.242 +     * or more interfaces by delegation to a provided {@link MethodHandle},
  15.243 +     * after appropriate type adaptation and partial evaluation of arguments.
  15.244 +     * Typically used as a <em>bootstrap method</em> for {@code invokedynamic}
  15.245 +     * call sites, to support the <em>lambda expression</em> and <em>method
  15.246 +     * reference expression</em> features of the Java Programming Language.
  15.247 +     *
  15.248 +     * <p>This is the standard, streamlined metafactory; additional flexibility
  15.249 +     * is provided by {@link #altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)}.
  15.250 +     * A general description of the behavior of this method is provided
  15.251 +     * {@link LambdaMetafactory above}.
  15.252 +     *
  15.253 +     * <p>When the target of the {@code CallSite} returned from this method is
  15.254 +     * invoked, the resulting function objects are instances of a class which
  15.255 +     * implements the interface named by the return type of {@code invokedType},
  15.256 +     * declares a method with the name given by {@code invokedName} and the
  15.257 +     * signature given by {@code samMethodType}.  It may also override additional
  15.258 +     * methods from {@code Object}.
  15.259 +     *
  15.260 +     * @param caller Represents a lookup context with the accessibility
  15.261 +     *               privileges of the caller.  When used with {@code invokedynamic},
  15.262 +     *               this is stacked automatically by the VM.
  15.263 +     * @param invokedName The name of the method to implement.  When used with
  15.264 +     *                    {@code invokedynamic}, this is provided by the
  15.265 +     *                    {@code NameAndType} of the {@code InvokeDynamic}
  15.266 +     *                    structure and is stacked automatically by the VM.
  15.267 +     * @param invokedType The expected signature of the {@code CallSite}.  The
  15.268 +     *                    parameter types represent the types of capture variables;
  15.269 +     *                    the return type is the interface to implement.   When
  15.270 +     *                    used with {@code invokedynamic}, this is provided by
  15.271 +     *                    the {@code NameAndType} of the {@code InvokeDynamic}
  15.272 +     *                    structure and is stacked automatically by the VM.
  15.273 +     *                    In the event that the implementation method is an
  15.274 +     *                    instance method and this signature has any parameters,
  15.275 +     *                    the first parameter in the invocation signature must
  15.276 +     *                    correspond to the receiver.
  15.277 +     * @param samMethodType Signature and return type of method to be implemented
  15.278 +     *                      by the function object.
  15.279 +     * @param implMethod A direct method handle describing the implementation
  15.280 +     *                   method which should be called (with suitable adaptation
  15.281 +     *                   of argument types, return types, and with captured
  15.282 +     *                   arguments prepended to the invocation arguments) at
  15.283 +     *                   invocation time.
  15.284 +     * @param instantiatedMethodType The signature and return type that should
  15.285 +     *                               be enforced dynamically at invocation time.
  15.286 +     *                               This may be the same as {@code samMethodType},
  15.287 +     *                               or may be a specialization of it.
  15.288 +     * @return a CallSite whose target can be used to perform capture, generating
  15.289 +     *         instances of the interface named by {@code invokedType}
  15.290 +     * @throws LambdaConversionException If any of the linkage invariants
  15.291 +     *                                   described {@link LambdaMetafactory above}
  15.292 +     *                                   are violated
  15.293 +     */
  15.294 +    public static CallSite metafactory(MethodHandles.Lookup caller,
  15.295 +                                       String invokedName,
  15.296 +                                       MethodType invokedType,
  15.297 +                                       MethodType samMethodType,
  15.298 +                                       MethodHandle implMethod,
  15.299 +                                       MethodType instantiatedMethodType)
  15.300 +            throws LambdaConversionException {
  15.301 +        AbstractValidatingLambdaMetafactory mf;
  15.302 +        mf = new InnerClassLambdaMetafactory(caller, invokedType,
  15.303 +                                             invokedName, samMethodType,
  15.304 +                                             implMethod, instantiatedMethodType,
  15.305 +                                             false, EMPTY_CLASS_ARRAY, EMPTY_MT_ARRAY);
  15.306 +        mf.validateMetafactoryArgs();
  15.307 +        return mf.buildCallSite();
  15.308 +    }
  15.309 +
  15.310 +    /**
  15.311 +     * Facilitates the creation of simple "function objects" that implement one
  15.312 +     * or more interfaces by delegation to a provided {@link MethodHandle},
  15.313 +     * after appropriate type adaptation and partial evaluation of arguments.
  15.314 +     * Typically used as a <em>bootstrap method</em> for {@code invokedynamic}
  15.315 +     * call sites, to support the <em>lambda expression</em> and <em>method
  15.316 +     * reference expression</em> features of the Java Programming Language.
  15.317 +     *
  15.318 +     * <p>This is the general, more flexible metafactory; a streamlined version
  15.319 +     * is provided by {@link #altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)}.
  15.320 +     * A general description of the behavior of this method is provided
  15.321 +     * {@link LambdaMetafactory above}.
  15.322 +     *
  15.323 +     * <p>The argument list for this method includes three fixed parameters,
  15.324 +     * corresponding to the parameters automatically stacked by the VM for the
  15.325 +     * bootstrap method in an {@code invokedynamic} invocation, and an {@code Object[]}
  15.326 +     * parameter that contains additional parameters.  The declared argument
  15.327 +     * list for this method is:
  15.328 +     *
  15.329 +     * <pre>{@code
  15.330 +     *  CallSite altMetafactory(MethodHandles.Lookup caller,
  15.331 +     *                          String invokedName,
  15.332 +     *                          MethodType invokedType,
  15.333 +     *                          Object... args)
  15.334 +     * }</pre>
  15.335 +     *
  15.336 +     * <p>but it behaves as if the argument list is as follows:
  15.337 +     *
  15.338 +     * <pre>{@code
  15.339 +     *  CallSite altMetafactory(MethodHandles.Lookup caller,
  15.340 +     *                          String invokedName,
  15.341 +     *                          MethodType invokedType,
  15.342 +     *                          MethodType samMethodType,
  15.343 +     *                          MethodHandle implMethod,
  15.344 +     *                          MethodType instantiatedMethodType,
  15.345 +     *                          int flags,
  15.346 +     *                          int markerInterfaceCount,  // IF flags has MARKERS set
  15.347 +     *                          Class... markerInterfaces, // IF flags has MARKERS set
  15.348 +     *                          int bridgeCount,           // IF flags has BRIDGES set
  15.349 +     *                          MethodType... bridges      // IF flags has BRIDGES set
  15.350 +     *                          )
  15.351 +     * }</pre>
  15.352 +     *
  15.353 +     * <p>Arguments that appear in the argument list for
  15.354 +     * {@link #metafactory(MethodHandles.Lookup, String, MethodType, MethodType, MethodHandle, MethodType)}
  15.355 +     * have the same specification as in that method.  The additional arguments
  15.356 +     * are interpreted as follows:
  15.357 +     * <ul>
  15.358 +     *     <li>{@code flags} indicates additional options; this is a bitwise
  15.359 +     *     OR of desired flags.  Defined flags are {@link #FLAG_BRIDGES},
  15.360 +     *     {@link #FLAG_MARKERS}, and {@link #FLAG_SERIALIZABLE}.</li>
  15.361 +     *     <li>{@code markerInterfaceCount} is the number of additional interfaces
  15.362 +     *     the function object should implement, and is present if and only if the
  15.363 +     *     {@code FLAG_MARKERS} flag is set.</li>
  15.364 +     *     <li>{@code markerInterfaces} is a variable-length list of additional
  15.365 +     *     interfaces to implement, whose length equals {@code markerInterfaceCount},
  15.366 +     *     and is present if and only if the {@code FLAG_MARKERS} flag is set.</li>
  15.367 +     *     <li>{@code bridgeCount} is the number of additional method signatures
  15.368 +     *     the function object should implement, and is present if and only if
  15.369 +     *     the {@code FLAG_BRIDGES} flag is set.</li>
  15.370 +     *     <li>{@code bridges} is a variable-length list of additional
  15.371 +     *     methods signatures to implement, whose length equals {@code bridgeCount},
  15.372 +     *     and is present if and only if the {@code FLAG_BRIDGES} flag is set.</li>
  15.373 +     * </ul>
  15.374 +     *
  15.375 +     * <p>Each class named by {@code markerInterfaces} is subject to the same
  15.376 +     * restrictions as {@code Rd}, the return type of {@code invokedType},
  15.377 +     * as described {@link LambdaMetafactory above}.  Each {@code MethodType}
  15.378 +     * named by {@code bridges} is subject to the same restrictions as
  15.379 +     * {@code samMethodType}, as described {@link LambdaMetafactory above}.
  15.380 +     *
  15.381 +     * <p>When FLAG_SERIALIZABLE is set in {@code flags}, the function objects
  15.382 +     * will implement {@code Serializable}, and will have a {@code writeReplace}
  15.383 +     * method that returns an appropriate {@link SerializedLambda}.  The
  15.384 +     * {@code caller} class must have an appropriate {@code $deserializeLambda$}
  15.385 +     * method, as described in {@link SerializedLambda}.
  15.386 +     *
  15.387 +     * <p>When the target of the {@code CallSite} returned from this method is
  15.388 +     * invoked, the resulting function objects are instances of a class with
  15.389 +     * the following properties:
  15.390 +     * <ul>
  15.391 +     *     <li>The class implements the interface named by the return type
  15.392 +     *     of {@code invokedType} and any interfaces named by {@code markerInterfaces}</li>
  15.393 +     *     <li>The class declares methods with the name given by {@code invokedName},
  15.394 +     *     and the signature given by {@code samMethodType} and additional signatures
  15.395 +     *     given by {@code bridges}</li>
  15.396 +     *     <li>The class may override methods from {@code Object}, and may
  15.397 +     *     implement methods related to serialization.</li>
  15.398 +     * </ul>
  15.399 +     *
  15.400 +     * @param caller Represents a lookup context with the accessibility
  15.401 +     *               privileges of the caller.  When used with {@code invokedynamic},
  15.402 +     *               this is stacked automatically by the VM.
  15.403 +     * @param invokedName The name of the method to implement.  When used with
  15.404 +     *                    {@code invokedynamic}, this is provided by the
  15.405 +     *                    {@code NameAndType} of the {@code InvokeDynamic}
  15.406 +     *                    structure and is stacked automatically by the VM.
  15.407 +     * @param invokedType The expected signature of the {@code CallSite}.  The
  15.408 +     *                    parameter types represent the types of capture variables;
  15.409 +     *                    the return type is the interface to implement.   When
  15.410 +     *                    used with {@code invokedynamic}, this is provided by
  15.411 +     *                    the {@code NameAndType} of the {@code InvokeDynamic}
  15.412 +     *                    structure and is stacked automatically by the VM.
  15.413 +     *                    In the event that the implementation method is an
  15.414 +     *                    instance method and this signature has any parameters,
  15.415 +     *                    the first parameter in the invocation signature must
  15.416 +     *                    correspond to the receiver.
  15.417 +     * @param  args       An {@code Object[]} array containing the required
  15.418 +     *                    arguments {@code samMethodType}, {@code implMethod},
  15.419 +     *                    {@code instantiatedMethodType}, {@code flags}, and any
  15.420 +     *                    optional arguments, as described
  15.421 +     *                    {@link #altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)} above}
  15.422 +     * @return a CallSite whose target can be used to perform capture, generating
  15.423 +     *         instances of the interface named by {@code invokedType}
  15.424 +     * @throws LambdaConversionException If any of the linkage invariants
  15.425 +     *                                   described {@link LambdaMetafactory above}
  15.426 +     *                                   are violated
  15.427 +     */
  15.428 +    public static CallSite altMetafactory(MethodHandles.Lookup caller,
  15.429 +                                          String invokedName,
  15.430 +                                          MethodType invokedType,
  15.431 +                                          Object... args)
  15.432 +            throws LambdaConversionException {
  15.433 +        MethodType samMethodType = (MethodType)args[0];
  15.434 +        MethodHandle implMethod = (MethodHandle)args[1];
  15.435 +        MethodType instantiatedMethodType = (MethodType)args[2];
  15.436 +        int flags = (Integer) args[3];
  15.437 +        Class<?>[] markerInterfaces;
  15.438 +        MethodType[] bridges;
  15.439 +        int argIndex = 4;
  15.440 +        if ((flags & FLAG_MARKERS) != 0) {
  15.441 +            int markerCount = (Integer) args[argIndex++];
  15.442 +            markerInterfaces = new Class<?>[markerCount];
  15.443 +            System.arraycopy(args, argIndex, markerInterfaces, 0, markerCount);
  15.444 +            argIndex += markerCount;
  15.445 +        }
  15.446 +        else
  15.447 +            markerInterfaces = EMPTY_CLASS_ARRAY;
  15.448 +        if ((flags & FLAG_BRIDGES) != 0) {
  15.449 +            int bridgeCount = (Integer) args[argIndex++];
  15.450 +            bridges = new MethodType[bridgeCount];
  15.451 +            System.arraycopy(args, argIndex, bridges, 0, bridgeCount);
  15.452 +            argIndex += bridgeCount;
  15.453 +        }
  15.454 +        else
  15.455 +            bridges = EMPTY_MT_ARRAY;
  15.456 +
  15.457 +        boolean isSerializable = ((flags & FLAG_SERIALIZABLE) != 0);
  15.458 +        if (isSerializable) {
  15.459 +            boolean foundSerializableSupertype = Serializable.class.isAssignableFrom(invokedType.returnType());
  15.460 +            for (Class<?> c : markerInterfaces)
  15.461 +                foundSerializableSupertype |= Serializable.class.isAssignableFrom(c);
  15.462 +            if (!foundSerializableSupertype) {
  15.463 +                markerInterfaces = Arrays.copyOf(markerInterfaces, markerInterfaces.length + 1);
  15.464 +                markerInterfaces[markerInterfaces.length-1] = Serializable.class;
  15.465 +            }
  15.466 +        }
  15.467 +
  15.468 +        AbstractValidatingLambdaMetafactory mf
  15.469 +                = new InnerClassLambdaMetafactory(caller, invokedType,
  15.470 +                                                  invokedName, samMethodType,
  15.471 +                                                  implMethod,
  15.472 +                                                  instantiatedMethodType,
  15.473 +                                                  isSerializable,
  15.474 +                                                  markerInterfaces, bridges);
  15.475 +        mf.validateMetafactoryArgs();
  15.476 +        return mf.buildCallSite();
  15.477 +    }
  15.478 +}
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/MemberName.java	Sat Aug 09 11:12:05 2014 +0200
    16.3 @@ -0,0 +1,1080 @@
    16.4 +/*
    16.5 + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
    16.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    16.7 + *
    16.8 + * This code is free software; you can redistribute it and/or modify it
    16.9 + * under the terms of the GNU General Public License version 2 only, as
   16.10 + * published by the Free Software Foundation.  Oracle designates this
   16.11 + * particular file as subject to the "Classpath" exception as provided
   16.12 + * by Oracle in the LICENSE file that accompanied this code.
   16.13 + *
   16.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   16.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   16.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   16.17 + * version 2 for more details (a copy is included in the LICENSE file that
   16.18 + * accompanied this code).
   16.19 + *
   16.20 + * You should have received a copy of the GNU General Public License version
   16.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   16.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   16.23 + *
   16.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   16.25 + * or visit www.oracle.com if you need additional information or have any
   16.26 + * questions.
   16.27 + */
   16.28 +
   16.29 +package java.lang.invoke;
   16.30 +
   16.31 +import sun.invoke.util.BytecodeDescriptor;
   16.32 +import sun.invoke.util.VerifyAccess;
   16.33 +
   16.34 +import java.lang.reflect.Constructor;
   16.35 +import java.lang.reflect.Field;
   16.36 +import java.lang.reflect.Method;
   16.37 +import java.lang.reflect.Member;
   16.38 +import java.lang.reflect.Modifier;
   16.39 +import java.util.ArrayList;
   16.40 +import java.util.Arrays;
   16.41 +import java.util.Collections;
   16.42 +import java.util.Iterator;
   16.43 +import java.util.List;
   16.44 +import static java.lang.invoke.MethodHandleNatives.Constants.*;
   16.45 +import static java.lang.invoke.MethodHandleStatics.*;
   16.46 +import java.util.Objects;
   16.47 +
   16.48 +/**
   16.49 + * A {@code MemberName} is a compact symbolic datum which fully characterizes
   16.50 + * a method or field reference.
   16.51 + * A member name refers to a field, method, constructor, or member type.
   16.52 + * Every member name has a simple name (a string) and a type (either a Class or MethodType).
   16.53 + * A member name may also have a non-null declaring class, or it may be simply
   16.54 + * a naked name/type pair.
   16.55 + * A member name may also have non-zero modifier flags.
   16.56 + * Finally, a member name may be either resolved or unresolved.
   16.57 + * If it is resolved, the existence of the named
   16.58 + * <p>
   16.59 + * Whether resolved or not, a member name provides no access rights or
   16.60 + * invocation capability to its possessor.  It is merely a compact
   16.61 + * representation of all symbolic information necessary to link to
   16.62 + * and properly use the named member.
   16.63 + * <p>
   16.64 + * When resolved, a member name's internal implementation may include references to JVM metadata.
   16.65 + * This representation is stateless and only decriptive.
   16.66 + * It provides no private information and no capability to use the member.
   16.67 + * <p>
   16.68 + * By contrast, a {@linkplain java.lang.reflect.Method} contains fuller information
   16.69 + * about the internals of a method (except its bytecodes) and also
   16.70 + * allows invocation.  A MemberName is much lighter than a Method,
   16.71 + * since it contains about 7 fields to the 16 of Method (plus its sub-arrays),
   16.72 + * and those seven fields omit much of the information in Method.
   16.73 + * @author jrose
   16.74 + */
   16.75 +/*non-public*/ final class MemberName implements Member, Cloneable {
   16.76 +    private Class<?> clazz;       // class in which the method is defined
   16.77 +    private String   name;        // may be null if not yet materialized
   16.78 +    private Object   type;        // may be null if not yet materialized
   16.79 +    private int      flags;       // modifier bits; see reflect.Modifier
   16.80 +    //@Injected JVM_Method* vmtarget;
   16.81 +    //@Injected int         vmindex;
   16.82 +    private Object   resolution;  // if null, this guy is resolved
   16.83 +
   16.84 +    /** Return the declaring class of this member.
   16.85 +     *  In the case of a bare name and type, the declaring class will be null.
   16.86 +     */
   16.87 +    public Class<?> getDeclaringClass() {
   16.88 +        return clazz;
   16.89 +    }
   16.90 +
   16.91 +    /** Utility method producing the class loader of the declaring class. */
   16.92 +    public ClassLoader getClassLoader() {
   16.93 +        return clazz.getClassLoader();
   16.94 +    }
   16.95 +
   16.96 +    /** Return the simple name of this member.
   16.97 +     *  For a type, it is the same as {@link Class#getSimpleName}.
   16.98 +     *  For a method or field, it is the simple name of the member.
   16.99 +     *  For a constructor, it is always {@code "&lt;init&gt;"}.
  16.100 +     */
  16.101 +    public String getName() {
  16.102 +        if (name == null) {
  16.103 +            expandFromVM();
  16.104 +            if (name == null) {
  16.105 +                return null;
  16.106 +            }
  16.107 +        }
  16.108 +        return name;
  16.109 +    }
  16.110 +
  16.111 +    public MethodType getMethodOrFieldType() {
  16.112 +        if (isInvocable())
  16.113 +            return getMethodType();
  16.114 +        if (isGetter())
  16.115 +            return MethodType.methodType(getFieldType());
  16.116 +        if (isSetter())
  16.117 +            return MethodType.methodType(void.class, getFieldType());
  16.118 +        throw new InternalError("not a method or field: "+this);
  16.119 +    }
  16.120 +
  16.121 +    /** Return the declared type of this member, which
  16.122 +     *  must be a method or constructor.
  16.123 +     */
  16.124 +    public MethodType getMethodType() {
  16.125 +        if (type == null) {
  16.126 +            expandFromVM();
  16.127 +            if (type == null) {
  16.128 +                return null;
  16.129 +            }
  16.130 +        }
  16.131 +        if (!isInvocable()) {
  16.132 +            throw newIllegalArgumentException("not invocable, no method type");
  16.133 +        }
  16.134 +
  16.135 +        {
  16.136 +            // Get a snapshot of type which doesn't get changed by racing threads.
  16.137 +            final Object type = this.type;
  16.138 +            if (type instanceof MethodType) {
  16.139 +                return (MethodType) type;
  16.140 +            }
  16.141 +        }
  16.142 +
  16.143 +        // type is not a MethodType yet.  Convert it thread-safely.
  16.144 +        synchronized (this) {
  16.145 +            if (type instanceof String) {
  16.146 +                String sig = (String) type;
  16.147 +                MethodType res = MethodType.fromMethodDescriptorString(sig, getClassLoader());
  16.148 +                type = res;
  16.149 +            } else if (type instanceof Object[]) {
  16.150 +                Object[] typeInfo = (Object[]) type;
  16.151 +                Class<?>[] ptypes = (Class<?>[]) typeInfo[1];
  16.152 +                Class<?> rtype = (Class<?>) typeInfo[0];
  16.153 +                MethodType res = MethodType.methodType(rtype, ptypes);
  16.154 +                type = res;
  16.155 +            }
  16.156 +            // Make sure type is a MethodType for racing threads.
  16.157 +            assert type instanceof MethodType : "bad method type " + type;
  16.158 +        }
  16.159 +        return (MethodType) type;
  16.160 +    }
  16.161 +
  16.162 +    /** Return the actual type under which this method or constructor must be invoked.
  16.163 +     *  For non-static methods or constructors, this is the type with a leading parameter,
  16.164 +     *  a reference to declaring class.  For static methods, it is the same as the declared type.
  16.165 +     */
  16.166 +    public MethodType getInvocationType() {
  16.167 +        MethodType itype = getMethodOrFieldType();
  16.168 +        if (isConstructor() && getReferenceKind() == REF_newInvokeSpecial)
  16.169 +            return itype.changeReturnType(clazz);
  16.170 +        if (!isStatic())
  16.171 +            return itype.insertParameterTypes(0, clazz);
  16.172 +        return itype;
  16.173 +    }
  16.174 +
  16.175 +    /** Utility method producing the parameter types of the method type. */
  16.176 +    public Class<?>[] getParameterTypes() {
  16.177 +        return getMethodType().parameterArray();
  16.178 +    }
  16.179 +
  16.180 +    /** Utility method producing the return type of the method type. */
  16.181 +    public Class<?> getReturnType() {
  16.182 +        return getMethodType().returnType();
  16.183 +    }
  16.184 +
  16.185 +    /** Return the declared type of this member, which
  16.186 +     *  must be a field or type.
  16.187 +     *  If it is a type member, that type itself is returned.
  16.188 +     */
  16.189 +    public Class<?> getFieldType() {
  16.190 +        if (type == null) {
  16.191 +            expandFromVM();
  16.192 +            if (type == null) {
  16.193 +                return null;
  16.194 +            }
  16.195 +        }
  16.196 +        if (isInvocable()) {
  16.197 +            throw newIllegalArgumentException("not a field or nested class, no simple type");
  16.198 +        }
  16.199 +
  16.200 +        {
  16.201 +            // Get a snapshot of type which doesn't get changed by racing threads.
  16.202 +            final Object type = this.type;
  16.203 +            if (type instanceof Class<?>) {
  16.204 +                return (Class<?>) type;
  16.205 +            }
  16.206 +        }
  16.207 +
  16.208 +        // type is not a Class yet.  Convert it thread-safely.
  16.209 +        synchronized (this) {
  16.210 +            if (type instanceof String) {
  16.211 +                String sig = (String) type;
  16.212 +                MethodType mtype = MethodType.fromMethodDescriptorString("()"+sig, getClassLoader());
  16.213 +                Class<?> res = mtype.returnType();
  16.214 +                type = res;
  16.215 +            }
  16.216 +            // Make sure type is a Class for racing threads.
  16.217 +            assert type instanceof Class<?> : "bad field type " + type;
  16.218 +        }
  16.219 +        return (Class<?>) type;
  16.220 +    }
  16.221 +
  16.222 +    /** Utility method to produce either the method type or field type of this member. */
  16.223 +    public Object getType() {
  16.224 +        return (isInvocable() ? getMethodType() : getFieldType());
  16.225 +    }
  16.226 +
  16.227 +    /** Utility method to produce the signature of this member,
  16.228 +     *  used within the class file format to describe its type.
  16.229 +     */
  16.230 +    public String getSignature() {
  16.231 +        if (type == null) {
  16.232 +            expandFromVM();
  16.233 +            if (type == null) {
  16.234 +                return null;
  16.235 +            }
  16.236 +        }
  16.237 +        if (isInvocable())
  16.238 +            return BytecodeDescriptor.unparse(getMethodType());
  16.239 +        else
  16.240 +            return BytecodeDescriptor.unparse(getFieldType());
  16.241 +    }
  16.242 +
  16.243 +    /** Return the modifier flags of this member.
  16.244 +     *  @see java.lang.reflect.Modifier
  16.245 +     */
  16.246 +    public int getModifiers() {
  16.247 +        return (flags & RECOGNIZED_MODIFIERS);
  16.248 +    }
  16.249 +
  16.250 +    /** Return the reference kind of this member, or zero if none.
  16.251 +     */
  16.252 +    public byte getReferenceKind() {
  16.253 +        return (byte) ((flags >>> MN_REFERENCE_KIND_SHIFT) & MN_REFERENCE_KIND_MASK);
  16.254 +    }
  16.255 +    private boolean referenceKindIsConsistent() {
  16.256 +        byte refKind = getReferenceKind();
  16.257 +        if (refKind == REF_NONE)  return isType();
  16.258 +        if (isField()) {
  16.259 +            assert(staticIsConsistent());
  16.260 +            assert(MethodHandleNatives.refKindIsField(refKind));
  16.261 +        } else if (isConstructor()) {
  16.262 +            assert(refKind == REF_newInvokeSpecial || refKind == REF_invokeSpecial);
  16.263 +        } else if (isMethod()) {
  16.264 +            assert(staticIsConsistent());
  16.265 +            assert(MethodHandleNatives.refKindIsMethod(refKind));
  16.266 +            if (clazz.isInterface())
  16.267 +                assert(refKind == REF_invokeInterface ||
  16.268 +                       refKind == REF_invokeStatic    ||
  16.269 +                       refKind == REF_invokeSpecial   ||
  16.270 +                       refKind == REF_invokeVirtual && isObjectPublicMethod());
  16.271 +        } else {
  16.272 +            assert(false);
  16.273 +        }
  16.274 +        return true;
  16.275 +    }
  16.276 +    private boolean isObjectPublicMethod() {
  16.277 +        if (clazz == Object.class)  return true;
  16.278 +        MethodType mtype = getMethodType();
  16.279 +        if (name.equals("toString") && mtype.returnType() == String.class && mtype.parameterCount() == 0)
  16.280 +            return true;
  16.281 +        if (name.equals("hashCode") && mtype.returnType() == int.class && mtype.parameterCount() == 0)
  16.282 +            return true;
  16.283 +        if (name.equals("equals") && mtype.returnType() == boolean.class && mtype.parameterCount() == 1 && mtype.parameterType(0) == Object.class)
  16.284 +            return true;
  16.285 +        return false;
  16.286 +    }
  16.287 +    /*non-public*/ boolean referenceKindIsConsistentWith(int originalRefKind) {
  16.288 +        int refKind = getReferenceKind();
  16.289 +        if (refKind == originalRefKind)  return true;
  16.290 +        switch (originalRefKind) {
  16.291 +        case REF_invokeInterface:
  16.292 +            // Looking up an interface method, can get (e.g.) Object.hashCode
  16.293 +            assert(refKind == REF_invokeVirtual ||
  16.294 +                   refKind == REF_invokeSpecial) : this;
  16.295 +            return true;
  16.296 +        case REF_invokeVirtual:
  16.297 +        case REF_newInvokeSpecial:
  16.298 +            // Looked up a virtual, can get (e.g.) final String.hashCode.
  16.299 +            assert(refKind == REF_invokeSpecial) : this;
  16.300 +            return true;
  16.301 +        }
  16.302 +        assert(false) : this+" != "+MethodHandleNatives.refKindName((byte)originalRefKind);
  16.303 +        return true;
  16.304 +    }
  16.305 +    private boolean staticIsConsistent() {
  16.306 +        byte refKind = getReferenceKind();
  16.307 +        return MethodHandleNatives.refKindIsStatic(refKind) == isStatic() || getModifiers() == 0;
  16.308 +    }
  16.309 +    private boolean vminfoIsConsistent() {
  16.310 +        byte refKind = getReferenceKind();
  16.311 +        assert(isResolved());  // else don't call
  16.312 +        Object vminfo = MethodHandleNatives.getMemberVMInfo(this);
  16.313 +        assert(vminfo instanceof Object[]);
  16.314 +        long vmindex = (Long) ((Object[])vminfo)[0];
  16.315 +        Object vmtarget = ((Object[])vminfo)[1];
  16.316 +        if (MethodHandleNatives.refKindIsField(refKind)) {
  16.317 +            assert(vmindex >= 0) : vmindex + ":" + this;
  16.318 +            assert(vmtarget instanceof Class);
  16.319 +        } else {
  16.320 +            if (MethodHandleNatives.refKindDoesDispatch(refKind))
  16.321 +                assert(vmindex >= 0) : vmindex + ":" + this;
  16.322 +            else
  16.323 +                assert(vmindex < 0) : vmindex;
  16.324 +            assert(vmtarget instanceof MemberName) : vmtarget + " in " + this;
  16.325 +        }
  16.326 +        return true;
  16.327 +    }
  16.328 +
  16.329 +    private MemberName changeReferenceKind(byte refKind, byte oldKind) {
  16.330 +        assert(getReferenceKind() == oldKind);
  16.331 +        assert(MethodHandleNatives.refKindIsValid(refKind));
  16.332 +        flags += (((int)refKind - oldKind) << MN_REFERENCE_KIND_SHIFT);
  16.333 +//        if (isConstructor() && refKind != REF_newInvokeSpecial)
  16.334 +//            flags += (IS_METHOD - IS_CONSTRUCTOR);
  16.335 +//        else if (refKind == REF_newInvokeSpecial && isMethod())
  16.336 +//            flags += (IS_CONSTRUCTOR - IS_METHOD);
  16.337 +        return this;
  16.338 +    }
  16.339 +
  16.340 +    private boolean testFlags(int mask, int value) {
  16.341 +        return (flags & mask) == value;
  16.342 +    }
  16.343 +    private boolean testAllFlags(int mask) {
  16.344 +        return testFlags(mask, mask);
  16.345 +    }
  16.346 +    private boolean testAnyFlags(int mask) {
  16.347 +        return !testFlags(mask, 0);
  16.348 +    }
  16.349 +
  16.350 +    /** Utility method to query if this member is a method handle invocation (invoke or invokeExact). */
  16.351 +    public boolean isMethodHandleInvoke() {
  16.352 +        final int bits = MH_INVOKE_MODS;
  16.353 +        final int negs = Modifier.STATIC;
  16.354 +        if (testFlags(bits | negs, bits) &&
  16.355 +            clazz == MethodHandle.class) {
  16.356 +            return isMethodHandleInvokeName(name);
  16.357 +        }
  16.358 +        return false;
  16.359 +    }
  16.360 +    public static boolean isMethodHandleInvokeName(String name) {
  16.361 +        return name.equals("invoke") || name.equals("invokeExact");
  16.362 +    }
  16.363 +    private static final int MH_INVOKE_MODS = Modifier.NATIVE | Modifier.FINAL | Modifier.PUBLIC;
  16.364 +
  16.365 +    /** Utility method to query the modifier flags of this member. */
  16.366 +    public boolean isStatic() {
  16.367 +        return Modifier.isStatic(flags);
  16.368 +    }
  16.369 +    /** Utility method to query the modifier flags of this member. */
  16.370 +    public boolean isPublic() {
  16.371 +        return Modifier.isPublic(flags);
  16.372 +    }
  16.373 +    /** Utility method to query the modifier flags of this member. */
  16.374 +    public boolean isPrivate() {
  16.375 +        return Modifier.isPrivate(flags);
  16.376 +    }
  16.377 +    /** Utility method to query the modifier flags of this member. */
  16.378 +    public boolean isProtected() {
  16.379 +        return Modifier.isProtected(flags);
  16.380 +    }
  16.381 +    /** Utility method to query the modifier flags of this member. */
  16.382 +    public boolean isFinal() {
  16.383 +        return Modifier.isFinal(flags);
  16.384 +    }
  16.385 +    /** Utility method to query whether this member or its defining class is final. */
  16.386 +    public boolean canBeStaticallyBound() {
  16.387 +        return Modifier.isFinal(flags | clazz.getModifiers());
  16.388 +    }
  16.389 +    /** Utility method to query the modifier flags of this member. */
  16.390 +    public boolean isVolatile() {
  16.391 +        return Modifier.isVolatile(flags);
  16.392 +    }
  16.393 +    /** Utility method to query the modifier flags of this member. */
  16.394 +    public boolean isAbstract() {
  16.395 +        return Modifier.isAbstract(flags);
  16.396 +    }
  16.397 +    /** Utility method to query the modifier flags of this member. */
  16.398 +    public boolean isNative() {
  16.399 +        return Modifier.isNative(flags);
  16.400 +    }
  16.401 +    // let the rest (native, volatile, transient, etc.) be tested via Modifier.isFoo
  16.402 +
  16.403 +    // unofficial modifier flags, used by HotSpot:
  16.404 +    static final int BRIDGE    = 0x00000040;
  16.405 +    static final int VARARGS   = 0x00000080;
  16.406 +    static final int SYNTHETIC = 0x00001000;
  16.407 +    static final int ANNOTATION= 0x00002000;
  16.408 +    static final int ENUM      = 0x00004000;
  16.409 +    /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
  16.410 +    public boolean isBridge() {