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() {
  16.411 +        return testAllFlags(IS_METHOD | BRIDGE);
  16.412 +    }
  16.413 +    /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
  16.414 +    public boolean isVarargs() {
  16.415 +        return testAllFlags(VARARGS) && isInvocable();
  16.416 +    }
  16.417 +    /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
  16.418 +    public boolean isSynthetic() {
  16.419 +        return testAllFlags(SYNTHETIC);
  16.420 +    }
  16.421 +
  16.422 +    static final String CONSTRUCTOR_NAME = "<init>";  // the ever-popular
  16.423 +
  16.424 +    // modifiers exported by the JVM:
  16.425 +    static final int RECOGNIZED_MODIFIERS = 0xFFFF;
  16.426 +
  16.427 +    // private flags, not part of RECOGNIZED_MODIFIERS:
  16.428 +    static final int
  16.429 +            IS_METHOD        = MN_IS_METHOD,        // method (not constructor)
  16.430 +            IS_CONSTRUCTOR   = MN_IS_CONSTRUCTOR,   // constructor
  16.431 +            IS_FIELD         = MN_IS_FIELD,         // field
  16.432 +            IS_TYPE          = MN_IS_TYPE,          // nested type
  16.433 +            CALLER_SENSITIVE = MN_CALLER_SENSITIVE; // @CallerSensitive annotation detected
  16.434 +
  16.435 +    static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
  16.436 +    static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE;
  16.437 +    static final int IS_INVOCABLE = IS_METHOD | IS_CONSTRUCTOR;
  16.438 +    static final int IS_FIELD_OR_METHOD = IS_METHOD | IS_FIELD;
  16.439 +    static final int SEARCH_ALL_SUPERS = MN_SEARCH_SUPERCLASSES | MN_SEARCH_INTERFACES;
  16.440 +
  16.441 +    /** Utility method to query whether this member is a method or constructor. */
  16.442 +    public boolean isInvocable() {
  16.443 +        return testAnyFlags(IS_INVOCABLE);
  16.444 +    }
  16.445 +    /** Utility method to query whether this member is a method, constructor, or field. */
  16.446 +    public boolean isFieldOrMethod() {
  16.447 +        return testAnyFlags(IS_FIELD_OR_METHOD);
  16.448 +    }
  16.449 +    /** Query whether this member is a method. */
  16.450 +    public boolean isMethod() {
  16.451 +        return testAllFlags(IS_METHOD);
  16.452 +    }
  16.453 +    /** Query whether this member is a constructor. */
  16.454 +    public boolean isConstructor() {
  16.455 +        return testAllFlags(IS_CONSTRUCTOR);
  16.456 +    }
  16.457 +    /** Query whether this member is a field. */
  16.458 +    public boolean isField() {
  16.459 +        return testAllFlags(IS_FIELD);
  16.460 +    }
  16.461 +    /** Query whether this member is a type. */
  16.462 +    public boolean isType() {
  16.463 +        return testAllFlags(IS_TYPE);
  16.464 +    }
  16.465 +    /** Utility method to query whether this member is neither public, private, nor protected. */
  16.466 +    public boolean isPackage() {
  16.467 +        return !testAnyFlags(ALL_ACCESS);
  16.468 +    }
  16.469 +    /** Query whether this member has a CallerSensitive annotation. */
  16.470 +    public boolean isCallerSensitive() {
  16.471 +        return testAllFlags(CALLER_SENSITIVE);
  16.472 +    }
  16.473 +
  16.474 +    /** Utility method to query whether this member is accessible from a given lookup class. */
  16.475 +    public boolean isAccessibleFrom(Class<?> lookupClass) {
  16.476 +        return VerifyAccess.isMemberAccessible(this.getDeclaringClass(), this.getDeclaringClass(), flags,
  16.477 +                                               lookupClass, ALL_ACCESS|MethodHandles.Lookup.PACKAGE);
  16.478 +    }
  16.479 +
  16.480 +    /** Initialize a query.   It is not resolved. */
  16.481 +    private void init(Class<?> defClass, String name, Object type, int flags) {
  16.482 +        // defining class is allowed to be null (for a naked name/type pair)
  16.483 +        //name.toString();  // null check
  16.484 +        //type.equals(type);  // null check
  16.485 +        // fill in fields:
  16.486 +        this.clazz = defClass;
  16.487 +        this.name = name;
  16.488 +        this.type = type;
  16.489 +        this.flags = flags;
  16.490 +        assert(testAnyFlags(ALL_KINDS));
  16.491 +        assert(this.resolution == null);  // nobody should have touched this yet
  16.492 +        //assert(referenceKindIsConsistent());  // do this after resolution
  16.493 +    }
  16.494 +
  16.495 +    /**
  16.496 +     * Calls down to the VM to fill in the fields.  This method is
  16.497 +     * synchronized to avoid racing calls.
  16.498 +     */
  16.499 +    private void expandFromVM() {
  16.500 +        if (type != null) {
  16.501 +            return;
  16.502 +        }
  16.503 +        if (!isResolved()) {
  16.504 +            return;
  16.505 +        }
  16.506 +        MethodHandleNatives.expand(this);
  16.507 +    }
  16.508 +
  16.509 +    // Capturing information from the Core Reflection API:
  16.510 +    private static int flagsMods(int flags, int mods, byte refKind) {
  16.511 +        assert((flags & RECOGNIZED_MODIFIERS) == 0);
  16.512 +        assert((mods & ~RECOGNIZED_MODIFIERS) == 0);
  16.513 +        assert((refKind & ~MN_REFERENCE_KIND_MASK) == 0);
  16.514 +        return flags | mods | (refKind << MN_REFERENCE_KIND_SHIFT);
  16.515 +    }
  16.516 +    /** Create a name for the given reflected method.  The resulting name will be in a resolved state. */
  16.517 +    public MemberName(Method m) {
  16.518 +        this(m, false);
  16.519 +    }
  16.520 +    @SuppressWarnings("LeakingThisInConstructor")
  16.521 +    public MemberName(Method m, boolean wantSpecial) {
  16.522 +        m.getClass();  // NPE check
  16.523 +        // fill in vmtarget, vmindex while we have m in hand:
  16.524 +        MethodHandleNatives.init(this, m);
  16.525 +        if (clazz == null) {  // MHN.init failed
  16.526 +            if (m.getDeclaringClass() == MethodHandle.class &&
  16.527 +                isMethodHandleInvokeName(m.getName())) {
  16.528 +                // The JVM did not reify this signature-polymorphic instance.
  16.529 +                // Need a special case here.
  16.530 +                // See comments on MethodHandleNatives.linkMethod.
  16.531 +                MethodType type = MethodType.methodType(m.getReturnType(), m.getParameterTypes());
  16.532 +                int flags = flagsMods(IS_METHOD, m.getModifiers(), REF_invokeVirtual);
  16.533 +                init(MethodHandle.class, m.getName(), type, flags);
  16.534 +                if (isMethodHandleInvoke())
  16.535 +                    return;
  16.536 +            }
  16.537 +            throw new LinkageError(m.toString());
  16.538 +        }
  16.539 +        assert(isResolved() && this.clazz != null);
  16.540 +        this.name = m.getName();
  16.541 +        if (this.type == null)
  16.542 +            this.type = new Object[] { m.getReturnType(), m.getParameterTypes() };
  16.543 +        if (wantSpecial) {
  16.544 +            if (isAbstract())
  16.545 +                throw new AbstractMethodError(this.toString());
  16.546 +            if (getReferenceKind() == REF_invokeVirtual)
  16.547 +                changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual);
  16.548 +            else if (getReferenceKind() == REF_invokeInterface)
  16.549 +                // invokeSpecial on a default method
  16.550 +                changeReferenceKind(REF_invokeSpecial, REF_invokeInterface);
  16.551 +        }
  16.552 +    }
  16.553 +    public MemberName asSpecial() {
  16.554 +        switch (getReferenceKind()) {
  16.555 +        case REF_invokeSpecial:     return this;
  16.556 +        case REF_invokeVirtual:     return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual);
  16.557 +        case REF_invokeInterface:   return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeInterface);
  16.558 +        case REF_newInvokeSpecial:  return clone().changeReferenceKind(REF_invokeSpecial, REF_newInvokeSpecial);
  16.559 +        }
  16.560 +        throw new IllegalArgumentException(this.toString());
  16.561 +    }
  16.562 +    /** If this MN is not REF_newInvokeSpecial, return a clone with that ref. kind.
  16.563 +     *  In that case it must already be REF_invokeSpecial.
  16.564 +     */
  16.565 +    public MemberName asConstructor() {
  16.566 +        switch (getReferenceKind()) {
  16.567 +        case REF_invokeSpecial:     return clone().changeReferenceKind(REF_newInvokeSpecial, REF_invokeSpecial);
  16.568 +        case REF_newInvokeSpecial:  return this;
  16.569 +        }
  16.570 +        throw new IllegalArgumentException(this.toString());
  16.571 +    }
  16.572 +    /** If this MN is a REF_invokeSpecial, return a clone with the "normal" kind
  16.573 +     *  REF_invokeVirtual; also switch either to REF_invokeInterface if clazz.isInterface.
  16.574 +     *  The end result is to get a fully virtualized version of the MN.
  16.575 +     *  (Note that resolving in the JVM will sometimes devirtualize, changing
  16.576 +     *  REF_invokeVirtual of a final to REF_invokeSpecial, and REF_invokeInterface
  16.577 +     *  in some corner cases to either of the previous two; this transform
  16.578 +     *  undoes that change under the assumption that it occurred.)
  16.579 +     */
  16.580 +    public MemberName asNormalOriginal() {
  16.581 +        byte normalVirtual = clazz.isInterface() ? REF_invokeInterface : REF_invokeVirtual;
  16.582 +        byte refKind = getReferenceKind();
  16.583 +        byte newRefKind = refKind;
  16.584 +        MemberName result = this;
  16.585 +        switch (refKind) {
  16.586 +        case REF_invokeInterface:
  16.587 +        case REF_invokeVirtual:
  16.588 +        case REF_invokeSpecial:
  16.589 +            newRefKind = normalVirtual;
  16.590 +            break;
  16.591 +        }
  16.592 +        if (newRefKind == refKind)
  16.593 +            return this;
  16.594 +        result = clone().changeReferenceKind(newRefKind, refKind);
  16.595 +        assert(this.referenceKindIsConsistentWith(result.getReferenceKind()));
  16.596 +        return result;
  16.597 +    }
  16.598 +    /** Create a name for the given reflected constructor.  The resulting name will be in a resolved state. */
  16.599 +    @SuppressWarnings("LeakingThisInConstructor")
  16.600 +    public MemberName(Constructor<?> ctor) {
  16.601 +        ctor.getClass();  // NPE check
  16.602 +        // fill in vmtarget, vmindex while we have ctor in hand:
  16.603 +        MethodHandleNatives.init(this, ctor);
  16.604 +        assert(isResolved() && this.clazz != null);
  16.605 +        this.name = CONSTRUCTOR_NAME;
  16.606 +        if (this.type == null)
  16.607 +            this.type = new Object[] { void.class, ctor.getParameterTypes() };
  16.608 +    }
  16.609 +    /** Create a name for the given reflected field.  The resulting name will be in a resolved state.
  16.610 +     */
  16.611 +    public MemberName(Field fld) {
  16.612 +        this(fld, false);
  16.613 +    }
  16.614 +    @SuppressWarnings("LeakingThisInConstructor")
  16.615 +    public MemberName(Field fld, boolean makeSetter) {
  16.616 +        fld.getClass();  // NPE check
  16.617 +        // fill in vmtarget, vmindex while we have fld in hand:
  16.618 +        MethodHandleNatives.init(this, fld);
  16.619 +        assert(isResolved() && this.clazz != null);
  16.620 +        this.name = fld.getName();
  16.621 +        this.type = fld.getType();
  16.622 +        assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField));
  16.623 +        byte refKind = this.getReferenceKind();
  16.624 +        assert(refKind == (isStatic() ? REF_getStatic : REF_getField));
  16.625 +        if (makeSetter) {
  16.626 +            changeReferenceKind((byte)(refKind + (REF_putStatic - REF_getStatic)), refKind);
  16.627 +        }
  16.628 +    }
  16.629 +    public boolean isGetter() {
  16.630 +        return MethodHandleNatives.refKindIsGetter(getReferenceKind());
  16.631 +    }
  16.632 +    public boolean isSetter() {
  16.633 +        return MethodHandleNatives.refKindIsSetter(getReferenceKind());
  16.634 +    }
  16.635 +    public MemberName asSetter() {
  16.636 +        byte refKind = getReferenceKind();
  16.637 +        assert(MethodHandleNatives.refKindIsGetter(refKind));
  16.638 +        assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField));
  16.639 +        byte setterRefKind = (byte)(refKind + (REF_putField - REF_getField));
  16.640 +        return clone().changeReferenceKind(setterRefKind, refKind);
  16.641 +    }
  16.642 +    /** Create a name for the given class.  The resulting name will be in a resolved state. */
  16.643 +    public MemberName(Class<?> type) {
  16.644 +        init(type.getDeclaringClass(), type.getSimpleName(), type,
  16.645 +                flagsMods(IS_TYPE, type.getModifiers(), REF_NONE));
  16.646 +        initResolved(true);
  16.647 +    }
  16.648 +
  16.649 +    /**
  16.650 +     * Create a name for a signature-polymorphic invoker.
  16.651 +     * This is a placeholder for a signature-polymorphic instance
  16.652 +     * (of MH.invokeExact, etc.) that the JVM does not reify.
  16.653 +     * See comments on {@link MethodHandleNatives#linkMethod}.
  16.654 +     */
  16.655 +    static MemberName makeMethodHandleInvoke(String name, MethodType type) {
  16.656 +        return makeMethodHandleInvoke(name, type, MH_INVOKE_MODS | SYNTHETIC);
  16.657 +    }
  16.658 +    static MemberName makeMethodHandleInvoke(String name, MethodType type, int mods) {
  16.659 +        MemberName mem = new MemberName(MethodHandle.class, name, type, REF_invokeVirtual);
  16.660 +        mem.flags |= mods;  // it's not resolved, but add these modifiers anyway
  16.661 +        assert(mem.isMethodHandleInvoke()) : mem;
  16.662 +        return mem;
  16.663 +    }
  16.664 +
  16.665 +    // bare-bones constructor; the JVM will fill it in
  16.666 +    MemberName() { }
  16.667 +
  16.668 +    // locally useful cloner
  16.669 +    @Override protected MemberName clone() {
  16.670 +        try {
  16.671 +            return (MemberName) super.clone();
  16.672 +        } catch (CloneNotSupportedException ex) {
  16.673 +            throw newInternalError(ex);
  16.674 +        }
  16.675 +     }
  16.676 +
  16.677 +    /** Get the definition of this member name.
  16.678 +     *  This may be in a super-class of the declaring class of this member.
  16.679 +     */
  16.680 +    public MemberName getDefinition() {
  16.681 +        if (!isResolved())  throw new IllegalStateException("must be resolved: "+this);
  16.682 +        if (isType())  return this;
  16.683 +        MemberName res = this.clone();
  16.684 +        res.clazz = null;
  16.685 +        res.type = null;
  16.686 +        res.name = null;
  16.687 +        res.resolution = res;
  16.688 +        res.expandFromVM();
  16.689 +        assert(res.getName().equals(this.getName()));
  16.690 +        return res;
  16.691 +    }
  16.692 +
  16.693 +    @Override
  16.694 +    public int hashCode() {
  16.695 +        return Objects.hash(clazz, getReferenceKind(), name, getType());
  16.696 +    }
  16.697 +    @Override
  16.698 +    public boolean equals(Object that) {
  16.699 +        return (that instanceof MemberName && this.equals((MemberName)that));
  16.700 +    }
  16.701 +
  16.702 +    /** Decide if two member names have exactly the same symbolic content.
  16.703 +     *  Does not take into account any actual class members, so even if
  16.704 +     *  two member names resolve to the same actual member, they may
  16.705 +     *  be distinct references.
  16.706 +     */
  16.707 +    public boolean equals(MemberName that) {
  16.708 +        if (this == that)  return true;
  16.709 +        if (that == null)  return false;
  16.710 +        return this.clazz == that.clazz
  16.711 +                && this.getReferenceKind() == that.getReferenceKind()
  16.712 +                && Objects.equals(this.name, that.name)
  16.713 +                && Objects.equals(this.getType(), that.getType());
  16.714 +    }
  16.715 +
  16.716 +    // Construction from symbolic parts, for queries:
  16.717 +    /** Create a field or type name from the given components:
  16.718 +     *  Declaring class, name, type, reference kind.
  16.719 +     *  The declaring class may be supplied as null if this is to be a bare name and type.
  16.720 +     *  The resulting name will in an unresolved state.
  16.721 +     */
  16.722 +    public MemberName(Class<?> defClass, String name, Class<?> type, byte refKind) {
  16.723 +        init(defClass, name, type, flagsMods(IS_FIELD, 0, refKind));
  16.724 +        initResolved(false);
  16.725 +    }
  16.726 +    /** Create a field or type name from the given components:  Declaring class, name, type.
  16.727 +     *  The declaring class may be supplied as null if this is to be a bare name and type.
  16.728 +     *  The modifier flags default to zero.
  16.729 +     *  The resulting name will in an unresolved state.
  16.730 +     */
  16.731 +    public MemberName(Class<?> defClass, String name, Class<?> type, Void unused) {
  16.732 +        this(defClass, name, type, REF_NONE);
  16.733 +        initResolved(false);
  16.734 +    }
  16.735 +    /** Create a method or constructor name from the given components:  Declaring class, name, type, modifiers.
  16.736 +     *  It will be a constructor if and only if the name is {@code "&lt;init&gt;"}.
  16.737 +     *  The declaring class may be supplied as null if this is to be a bare name and type.
  16.738 +     *  The last argument is optional, a boolean which requests REF_invokeSpecial.
  16.739 +     *  The resulting name will in an unresolved state.
  16.740 +     */
  16.741 +    public MemberName(Class<?> defClass, String name, MethodType type, byte refKind) {
  16.742 +        int initFlags = (name != null && name.equals(CONSTRUCTOR_NAME) ? IS_CONSTRUCTOR : IS_METHOD);
  16.743 +        init(defClass, name, type, flagsMods(initFlags, 0, refKind));
  16.744 +        initResolved(false);
  16.745 +    }
  16.746 +    /** Create a method, constructor, or field name from the given components:
  16.747 +     *  Reference kind, declaring class, name, type.
  16.748 +     */
  16.749 +    public MemberName(byte refKind, Class<?> defClass, String name, Object type) {
  16.750 +        int kindFlags;
  16.751 +        if (MethodHandleNatives.refKindIsField(refKind)) {
  16.752 +            kindFlags = IS_FIELD;
  16.753 +            if (!(type instanceof Class))
  16.754 +                throw newIllegalArgumentException("not a field type");
  16.755 +        } else if (MethodHandleNatives.refKindIsMethod(refKind)) {
  16.756 +            kindFlags = IS_METHOD;
  16.757 +            if (!(type instanceof MethodType))
  16.758 +                throw newIllegalArgumentException("not a method type");
  16.759 +        } else if (refKind == REF_newInvokeSpecial) {
  16.760 +            kindFlags = IS_CONSTRUCTOR;
  16.761 +            if (!(type instanceof MethodType) ||
  16.762 +                !CONSTRUCTOR_NAME.equals(name))
  16.763 +                throw newIllegalArgumentException("not a constructor type or name");
  16.764 +        } else {
  16.765 +            throw newIllegalArgumentException("bad reference kind "+refKind);
  16.766 +        }
  16.767 +        init(defClass, name, type, flagsMods(kindFlags, 0, refKind));
  16.768 +        initResolved(false);
  16.769 +    }
  16.770 +    /** Query whether this member name is resolved to a non-static, non-final method.
  16.771 +     */
  16.772 +    public boolean hasReceiverTypeDispatch() {
  16.773 +        return MethodHandleNatives.refKindDoesDispatch(getReferenceKind());
  16.774 +    }
  16.775 +
  16.776 +    /** Query whether this member name is resolved.
  16.777 +     *  A resolved member name is one for which the JVM has found
  16.778 +     *  a method, constructor, field, or type binding corresponding exactly to the name.
  16.779 +     *  (Document?)
  16.780 +     */
  16.781 +    public boolean isResolved() {
  16.782 +        return resolution == null;
  16.783 +    }
  16.784 +
  16.785 +    private void initResolved(boolean isResolved) {
  16.786 +        assert(this.resolution == null);  // not initialized yet!
  16.787 +        if (!isResolved)
  16.788 +            this.resolution = this;
  16.789 +        assert(isResolved() == isResolved);
  16.790 +    }
  16.791 +
  16.792 +    void checkForTypeAlias() {
  16.793 +        if (isInvocable()) {
  16.794 +            MethodType type;
  16.795 +            if (this.type instanceof MethodType)
  16.796 +                type = (MethodType) this.type;
  16.797 +            else
  16.798 +                this.type = type = getMethodType();
  16.799 +            if (type.erase() == type)  return;
  16.800 +            if (VerifyAccess.isTypeVisible(type, clazz))  return;
  16.801 +            throw new LinkageError("bad method type alias: "+type+" not visible from "+clazz);
  16.802 +        } else {
  16.803 +            Class<?> type;
  16.804 +            if (this.type instanceof Class<?>)
  16.805 +                type = (Class<?>) this.type;
  16.806 +            else
  16.807 +                this.type = type = getFieldType();
  16.808 +            if (VerifyAccess.isTypeVisible(type, clazz))  return;
  16.809 +            throw new LinkageError("bad field type alias: "+type+" not visible from "+clazz);
  16.810 +        }
  16.811 +    }
  16.812 +
  16.813 +
  16.814 +    /** Produce a string form of this member name.
  16.815 +     *  For types, it is simply the type's own string (as reported by {@code toString}).
  16.816 +     *  For fields, it is {@code "DeclaringClass.name/type"}.
  16.817 +     *  For methods and constructors, it is {@code "DeclaringClass.name(ptype...)rtype"}.
  16.818 +     *  If the declaring class is null, the prefix {@code "DeclaringClass."} is omitted.
  16.819 +     *  If the member is unresolved, a prefix {@code "*."} is prepended.
  16.820 +     */
  16.821 +    @SuppressWarnings("LocalVariableHidesMemberVariable")
  16.822 +    @Override
  16.823 +    public String toString() {
  16.824 +        if (isType())
  16.825 +            return type.toString();  // class java.lang.String
  16.826 +        // else it is a field, method, or constructor
  16.827 +        StringBuilder buf = new StringBuilder();
  16.828 +        if (getDeclaringClass() != null) {
  16.829 +            buf.append(getName(clazz));
  16.830 +            buf.append('.');
  16.831 +        }
  16.832 +        String name = getName();
  16.833 +        buf.append(name == null ? "*" : name);
  16.834 +        Object type = getType();
  16.835 +        if (!isInvocable()) {
  16.836 +            buf.append('/');
  16.837 +            buf.append(type == null ? "*" : getName(type));
  16.838 +        } else {
  16.839 +            buf.append(type == null ? "(*)*" : getName(type));
  16.840 +        }
  16.841 +        byte refKind = getReferenceKind();
  16.842 +        if (refKind != REF_NONE) {
  16.843 +            buf.append('/');
  16.844 +            buf.append(MethodHandleNatives.refKindName(refKind));
  16.845 +        }
  16.846 +        //buf.append("#").append(System.identityHashCode(this));
  16.847 +        return buf.toString();
  16.848 +    }
  16.849 +    private static String getName(Object obj) {
  16.850 +        if (obj instanceof Class<?>)
  16.851 +            return ((Class<?>)obj).getName();
  16.852 +        return String.valueOf(obj);
  16.853 +    }
  16.854 +
  16.855 +    public IllegalAccessException makeAccessException(String message, Object from) {
  16.856 +        message = message + ": "+ toString();
  16.857 +        if (from != null)  message += ", from " + from;
  16.858 +        return new IllegalAccessException(message);
  16.859 +    }
  16.860 +    private String message() {
  16.861 +        if (isResolved())
  16.862 +            return "no access";
  16.863 +        else if (isConstructor())
  16.864 +            return "no such constructor";
  16.865 +        else if (isMethod())
  16.866 +            return "no such method";
  16.867 +        else
  16.868 +            return "no such field";
  16.869 +    }
  16.870 +    public ReflectiveOperationException makeAccessException() {
  16.871 +        String message = message() + ": "+ toString();
  16.872 +        ReflectiveOperationException ex;
  16.873 +        if (isResolved() || !(resolution instanceof NoSuchMethodError ||
  16.874 +                              resolution instanceof NoSuchFieldError))
  16.875 +            ex = new IllegalAccessException(message);
  16.876 +        else if (isConstructor())
  16.877 +            ex = new NoSuchMethodException(message);
  16.878 +        else if (isMethod())
  16.879 +            ex = new NoSuchMethodException(message);
  16.880 +        else
  16.881 +            ex = new NoSuchFieldException(message);
  16.882 +        if (resolution instanceof Throwable)
  16.883 +            ex.initCause((Throwable) resolution);
  16.884 +        return ex;
  16.885 +    }
  16.886 +
  16.887 +    /** Actually making a query requires an access check. */
  16.888 +    /*non-public*/ static Factory getFactory() {
  16.889 +        return Factory.INSTANCE;
  16.890 +    }
  16.891 +    /** A factory type for resolving member names with the help of the VM.
  16.892 +     *  TBD: Define access-safe public constructors for this factory.
  16.893 +     */
  16.894 +    /*non-public*/ static class Factory {
  16.895 +        private Factory() { } // singleton pattern
  16.896 +        static Factory INSTANCE = new Factory();
  16.897 +
  16.898 +        private static int ALLOWED_FLAGS = ALL_KINDS;
  16.899 +
  16.900 +        /// Queries
  16.901 +        List<MemberName> getMembers(Class<?> defc,
  16.902 +                String matchName, Object matchType,
  16.903 +                int matchFlags, Class<?> lookupClass) {
  16.904 +            matchFlags &= ALLOWED_FLAGS;
  16.905 +            String matchSig = null;
  16.906 +            if (matchType != null) {
  16.907 +                matchSig = BytecodeDescriptor.unparse(matchType);
  16.908 +                if (matchSig.startsWith("("))
  16.909 +                    matchFlags &= ~(ALL_KINDS & ~IS_INVOCABLE);
  16.910 +                else
  16.911 +                    matchFlags &= ~(ALL_KINDS & ~IS_FIELD);
  16.912 +            }
  16.913 +            final int BUF_MAX = 0x2000;
  16.914 +            int len1 = matchName == null ? 10 : matchType == null ? 4 : 1;
  16.915 +            MemberName[] buf = newMemberBuffer(len1);
  16.916 +            int totalCount = 0;
  16.917 +            ArrayList<MemberName[]> bufs = null;
  16.918 +            int bufCount = 0;
  16.919 +            for (;;) {
  16.920 +                bufCount = MethodHandleNatives.getMembers(defc,
  16.921 +                        matchName, matchSig, matchFlags,
  16.922 +                        lookupClass,
  16.923 +                        totalCount, buf);
  16.924 +                if (bufCount <= buf.length) {
  16.925 +                    if (bufCount < 0)  bufCount = 0;
  16.926 +                    totalCount += bufCount;
  16.927 +                    break;
  16.928 +                }
  16.929 +                // JVM returned to us with an intentional overflow!
  16.930 +                totalCount += buf.length;
  16.931 +                int excess = bufCount - buf.length;
  16.932 +                if (bufs == null)  bufs = new ArrayList<>(1);
  16.933 +                bufs.add(buf);
  16.934 +                int len2 = buf.length;
  16.935 +                len2 = Math.max(len2, excess);
  16.936 +                len2 = Math.max(len2, totalCount / 4);
  16.937 +                buf = newMemberBuffer(Math.min(BUF_MAX, len2));
  16.938 +            }
  16.939 +            ArrayList<MemberName> result = new ArrayList<>(totalCount);
  16.940 +            if (bufs != null) {
  16.941 +                for (MemberName[] buf0 : bufs) {
  16.942 +                    Collections.addAll(result, buf0);
  16.943 +                }
  16.944 +            }
  16.945 +            result.addAll(Arrays.asList(buf).subList(0, bufCount));
  16.946 +            // Signature matching is not the same as type matching, since
  16.947 +            // one signature might correspond to several types.
  16.948 +            // So if matchType is a Class or MethodType, refilter the results.
  16.949 +            if (matchType != null && matchType != matchSig) {
  16.950 +                for (Iterator<MemberName> it = result.iterator(); it.hasNext();) {
  16.951 +                    MemberName m = it.next();
  16.952 +                    if (!matchType.equals(m.getType()))
  16.953 +                        it.remove();
  16.954 +                }
  16.955 +            }
  16.956 +            return result;
  16.957 +        }
  16.958 +        /** Produce a resolved version of the given member.
  16.959 +         *  Super types are searched (for inherited members) if {@code searchSupers} is true.
  16.960 +         *  Access checking is performed on behalf of the given {@code lookupClass}.
  16.961 +         *  If lookup fails or access is not permitted, null is returned.
  16.962 +         *  Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
  16.963 +         */
  16.964 +        private MemberName resolve(byte refKind, MemberName ref, Class<?> lookupClass) {
  16.965 +            MemberName m = ref.clone();  // JVM will side-effect the ref
  16.966 +            assert(refKind == m.getReferenceKind());
  16.967 +            try {
  16.968 +                m = MethodHandleNatives.resolve(m, lookupClass);
  16.969 +                m.checkForTypeAlias();
  16.970 +                m.resolution = null;
  16.971 +            } catch (LinkageError ex) {
  16.972 +                // JVM reports that the "bytecode behavior" would get an error
  16.973 +                assert(!m.isResolved());
  16.974 +                m.resolution = ex;
  16.975 +                return m;
  16.976 +            }
  16.977 +            assert(m.referenceKindIsConsistent());
  16.978 +            m.initResolved(true);
  16.979 +            assert(m.vminfoIsConsistent());
  16.980 +            return m;
  16.981 +        }
  16.982 +        /** Produce a resolved version of the given member.
  16.983 +         *  Super types are searched (for inherited members) if {@code searchSupers} is true.
  16.984 +         *  Access checking is performed on behalf of the given {@code lookupClass}.
  16.985 +         *  If lookup fails or access is not permitted, a {@linkplain ReflectiveOperationException} is thrown.
  16.986 +         *  Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
  16.987 +         */
  16.988 +        public
  16.989 +        <NoSuchMemberException extends ReflectiveOperationException>
  16.990 +        MemberName resolveOrFail(byte refKind, MemberName m, Class<?> lookupClass,
  16.991 +                                 Class<NoSuchMemberException> nsmClass)
  16.992 +                throws IllegalAccessException, NoSuchMemberException {
  16.993 +            MemberName result = resolve(refKind, m, lookupClass);
  16.994 +            if (result.isResolved())
  16.995 +                return result;
  16.996 +            ReflectiveOperationException ex = result.makeAccessException();
  16.997 +            if (ex instanceof IllegalAccessException)  throw (IllegalAccessException) ex;
  16.998 +            throw nsmClass.cast(ex);
  16.999 +        }
 16.1000 +        /** Produce a resolved version of the given member.
 16.1001 +         *  Super types are searched (for inherited members) if {@code searchSupers} is true.
 16.1002 +         *  Access checking is performed on behalf of the given {@code lookupClass}.
 16.1003 +         *  If lookup fails or access is not permitted, return null.
 16.1004 +         *  Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
 16.1005 +         */
 16.1006 +        public
 16.1007 +        MemberName resolveOrNull(byte refKind, MemberName m, Class<?> lookupClass) {
 16.1008 +            MemberName result = resolve(refKind, m, lookupClass);
 16.1009 +            if (result.isResolved())
 16.1010 +                return result;
 16.1011 +            return null;
 16.1012 +        }
 16.1013 +        /** Return a list of all methods defined by the given class.
 16.1014 +         *  Super types are searched (for inherited members) if {@code searchSupers} is true.
 16.1015 +         *  Access checking is performed on behalf of the given {@code lookupClass}.
 16.1016 +         *  Inaccessible members are not added to the last.
 16.1017 +         */
 16.1018 +        public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
 16.1019 +                Class<?> lookupClass) {
 16.1020 +            return getMethods(defc, searchSupers, null, null, lookupClass);
 16.1021 +        }
 16.1022 +        /** Return a list of matching methods defined by the given class.
 16.1023 +         *  Super types are searched (for inherited members) if {@code searchSupers} is true.
 16.1024 +         *  Returned methods will match the name (if not null) and the type (if not null).
 16.1025 +         *  Access checking is performed on behalf of the given {@code lookupClass}.
 16.1026 +         *  Inaccessible members are not added to the last.
 16.1027 +         */
 16.1028 +        public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
 16.1029 +                String name, MethodType type, Class<?> lookupClass) {
 16.1030 +            int matchFlags = IS_METHOD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
 16.1031 +            return getMembers(defc, name, type, matchFlags, lookupClass);
 16.1032 +        }
 16.1033 +        /** Return a list of all constructors defined by the given class.
 16.1034 +         *  Access checking is performed on behalf of the given {@code lookupClass}.
 16.1035 +         *  Inaccessible members are not added to the last.
 16.1036 +         */
 16.1037 +        public List<MemberName> getConstructors(Class<?> defc, Class<?> lookupClass) {
 16.1038 +            return getMembers(defc, null, null, IS_CONSTRUCTOR, lookupClass);
 16.1039 +        }
 16.1040 +        /** Return a list of all fields defined by the given class.
 16.1041 +         *  Super types are searched (for inherited members) if {@code searchSupers} is true.
 16.1042 +         *  Access checking is performed on behalf of the given {@code lookupClass}.
 16.1043 +         *  Inaccessible members are not added to the last.
 16.1044 +         */
 16.1045 +        public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
 16.1046 +                Class<?> lookupClass) {
 16.1047 +            return getFields(defc, searchSupers, null, null, lookupClass);
 16.1048 +        }
 16.1049 +        /** Return a list of all fields defined by the given class.
 16.1050 +         *  Super types are searched (for inherited members) if {@code searchSupers} is true.
 16.1051 +         *  Returned fields will match the name (if not null) and the type (if not null).
 16.1052 +         *  Access checking is performed on behalf of the given {@code lookupClass}.
 16.1053 +         *  Inaccessible members are not added to the last.
 16.1054 +         */
 16.1055 +        public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
 16.1056 +                String name, Class<?> type, Class<?> lookupClass) {
 16.1057 +            int matchFlags = IS_FIELD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
 16.1058 +            return getMembers(defc, name, type, matchFlags, lookupClass);
 16.1059 +        }
 16.1060 +        /** Return a list of all nested types defined by the given class.
 16.1061 +         *  Super types are searched (for inherited members) if {@code searchSupers} is true.
 16.1062 +         *  Access checking is performed on behalf of the given {@code lookupClass}.
 16.1063 +         *  Inaccessible members are not added to the last.
 16.1064 +         */
 16.1065 +        public List<MemberName> getNestedTypes(Class<?> defc, boolean searchSupers,
 16.1066 +                Class<?> lookupClass) {
 16.1067 +            int matchFlags = IS_TYPE | (searchSupers ? SEARCH_ALL_SUPERS : 0);
 16.1068 +            return getMembers(defc, null, null, matchFlags, lookupClass);
 16.1069 +        }
 16.1070 +        private static MemberName[] newMemberBuffer(int length) {
 16.1071 +            MemberName[] buf = new MemberName[length];
 16.1072 +            // fill the buffer with dummy structs for the JVM to fill in
 16.1073 +            for (int i = 0; i < length; i++)
 16.1074 +                buf[i] = new MemberName();
 16.1075 +            return buf;
 16.1076 +        }
 16.1077 +    }
 16.1078 +
 16.1079 +//    static {
 16.1080 +//        System.out.println("Hello world!  My methods are:");
 16.1081 +//        System.out.println(Factory.INSTANCE.getMethods(MemberName.class, true, null));
 16.1082 +//    }
 16.1083 +}
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/MethodHandle.java	Sat Aug 09 11:12:05 2014 +0200
    17.3 @@ -0,0 +1,1505 @@
    17.4 +/*
    17.5 + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
    17.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    17.7 + *
    17.8 + * This code is free software; you can redistribute it and/or modify it
    17.9 + * under the terms of the GNU General Public License version 2 only, as
   17.10 + * published by the Free Software Foundation.  Oracle designates this
   17.11 + * particular file as subject to the "Classpath" exception as provided
   17.12 + * by Oracle in the LICENSE file that accompanied this code.
   17.13 + *
   17.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   17.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   17.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   17.17 + * version 2 for more details (a copy is included in the LICENSE file that
   17.18 + * accompanied this code).
   17.19 + *
   17.20 + * You should have received a copy of the GNU General Public License version
   17.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   17.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   17.23 + *
   17.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   17.25 + * or visit www.oracle.com if you need additional information or have any
   17.26 + * questions.
   17.27 + */
   17.28 +
   17.29 +package java.lang.invoke;
   17.30 +
   17.31 +
   17.32 +import java.util.*;
   17.33 +import sun.invoke.util.*;
   17.34 +import sun.misc.Unsafe;
   17.35 +
   17.36 +import static java.lang.invoke.MethodHandleStatics.*;
   17.37 +import java.util.logging.Level;
   17.38 +import java.util.logging.Logger;
   17.39 +
   17.40 +/**
   17.41 + * A method handle is a typed, directly executable reference to an underlying method,
   17.42 + * constructor, field, or similar low-level operation, with optional
   17.43 + * transformations of arguments or return values.
   17.44 + * These transformations are quite general, and include such patterns as
   17.45 + * {@linkplain #asType conversion},
   17.46 + * {@linkplain #bindTo insertion},
   17.47 + * {@linkplain java.lang.invoke.MethodHandles#dropArguments deletion},
   17.48 + * and {@linkplain java.lang.invoke.MethodHandles#filterArguments substitution}.
   17.49 + *
   17.50 + * <h1>Method handle contents</h1>
   17.51 + * Method handles are dynamically and strongly typed according to their parameter and return types.
   17.52 + * They are not distinguished by the name or the defining class of their underlying methods.
   17.53 + * A method handle must be invoked using a symbolic type descriptor which matches
   17.54 + * the method handle's own {@linkplain #type type descriptor}.
   17.55 + * <p>
   17.56 + * Every method handle reports its type descriptor via the {@link #type type} accessor.
   17.57 + * This type descriptor is a {@link java.lang.invoke.MethodType MethodType} object,
   17.58 + * whose structure is a series of classes, one of which is
   17.59 + * the return type of the method (or {@code void.class} if none).
   17.60 + * <p>
   17.61 + * A method handle's type controls the types of invocations it accepts,
   17.62 + * and the kinds of transformations that apply to it.
   17.63 + * <p>
   17.64 + * A method handle contains a pair of special invoker methods
   17.65 + * called {@link #invokeExact invokeExact} and {@link #invoke invoke}.
   17.66 + * Both invoker methods provide direct access to the method handle's
   17.67 + * underlying method, constructor, field, or other operation,
   17.68 + * as modified by transformations of arguments and return values.
   17.69 + * Both invokers accept calls which exactly match the method handle's own type.
   17.70 + * The plain, inexact invoker also accepts a range of other call types.
   17.71 + * <p>
   17.72 + * Method handles are immutable and have no visible state.
   17.73 + * Of course, they can be bound to underlying methods or data which exhibit state.
   17.74 + * With respect to the Java Memory Model, any method handle will behave
   17.75 + * as if all of its (internal) fields are final variables.  This means that any method
   17.76 + * handle made visible to the application will always be fully formed.
   17.77 + * This is true even if the method handle is published through a shared
   17.78 + * variable in a data race.
   17.79 + * <p>
   17.80 + * Method handles cannot be subclassed by the user.
   17.81 + * Implementations may (or may not) create internal subclasses of {@code MethodHandle}
   17.82 + * which may be visible via the {@link java.lang.Object#getClass Object.getClass}
   17.83 + * operation.  The programmer should not draw conclusions about a method handle
   17.84 + * from its specific class, as the method handle class hierarchy (if any)
   17.85 + * may change from time to time or across implementations from different vendors.
   17.86 + *
   17.87 + * <h1>Method handle compilation</h1>
   17.88 + * A Java method call expression naming {@code invokeExact} or {@code invoke}
   17.89 + * can invoke a method handle from Java source code.
   17.90 + * From the viewpoint of source code, these methods can take any arguments
   17.91 + * and their result can be cast to any return type.
   17.92 + * Formally this is accomplished by giving the invoker methods
   17.93 + * {@code Object} return types and variable arity {@code Object} arguments,
   17.94 + * but they have an additional quality called <em>signature polymorphism</em>
   17.95 + * which connects this freedom of invocation directly to the JVM execution stack.
   17.96 + * <p>
   17.97 + * As is usual with virtual methods, source-level calls to {@code invokeExact}
   17.98 + * and {@code invoke} compile to an {@code invokevirtual} instruction.
   17.99 + * More unusually, the compiler must record the actual argument types,
  17.100 + * and may not perform method invocation conversions on the arguments.
  17.101 + * Instead, it must push them on the stack according to their own unconverted types.
  17.102 + * The method handle object itself is pushed on the stack before the arguments.
  17.103 + * The compiler then calls the method handle with a symbolic type descriptor which
  17.104 + * describes the argument and return types.
  17.105 + * <p>
  17.106 + * To issue a complete symbolic type descriptor, the compiler must also determine
  17.107 + * the return type.  This is based on a cast on the method invocation expression,
  17.108 + * if there is one, or else {@code Object} if the invocation is an expression
  17.109 + * or else {@code void} if the invocation is a statement.
  17.110 + * The cast may be to a primitive type (but not {@code void}).
  17.111 + * <p>
  17.112 + * As a corner case, an uncasted {@code null} argument is given
  17.113 + * a symbolic type descriptor of {@code java.lang.Void}.
  17.114 + * The ambiguity with the type {@code Void} is harmless, since there are no references of type
  17.115 + * {@code Void} except the null reference.
  17.116 + *
  17.117 + * <h1>Method handle invocation</h1>
  17.118 + * The first time a {@code invokevirtual} instruction is executed
  17.119 + * it is linked, by symbolically resolving the names in the instruction
  17.120 + * and verifying that the method call is statically legal.
  17.121 + * This is true of calls to {@code invokeExact} and {@code invoke}.
  17.122 + * In this case, the symbolic type descriptor emitted by the compiler is checked for
  17.123 + * correct syntax and names it contains are resolved.
  17.124 + * Thus, an {@code invokevirtual} instruction which invokes
  17.125 + * a method handle will always link, as long
  17.126 + * as the symbolic type descriptor is syntactically well-formed
  17.127 + * and the types exist.
  17.128 + * <p>
  17.129 + * When the {@code invokevirtual} is executed after linking,
  17.130 + * the receiving method handle's type is first checked by the JVM
  17.131 + * to ensure that it matches the symbolic type descriptor.
  17.132 + * If the type match fails, it means that the method which the
  17.133 + * caller is invoking is not present on the individual
  17.134 + * method handle being invoked.
  17.135 + * <p>
  17.136 + * In the case of {@code invokeExact}, the type descriptor of the invocation
  17.137 + * (after resolving symbolic type names) must exactly match the method type
  17.138 + * of the receiving method handle.
  17.139 + * In the case of plain, inexact {@code invoke}, the resolved type descriptor
  17.140 + * must be a valid argument to the receiver's {@link #asType asType} method.
  17.141 + * Thus, plain {@code invoke} is more permissive than {@code invokeExact}.
  17.142 + * <p>
  17.143 + * After type matching, a call to {@code invokeExact} directly
  17.144 + * and immediately invoke the method handle's underlying method
  17.145 + * (or other behavior, as the case may be).
  17.146 + * <p>
  17.147 + * A call to plain {@code invoke} works the same as a call to
  17.148 + * {@code invokeExact}, if the symbolic type descriptor specified by the caller
  17.149 + * exactly matches the method handle's own type.
  17.150 + * If there is a type mismatch, {@code invoke} attempts
  17.151 + * to adjust the type of the receiving method handle,
  17.152 + * as if by a call to {@link #asType asType},
  17.153 + * to obtain an exactly invokable method handle {@code M2}.
  17.154 + * This allows a more powerful negotiation of method type
  17.155 + * between caller and callee.
  17.156 + * <p>
  17.157 + * (<em>Note:</em> The adjusted method handle {@code M2} is not directly observable,
  17.158 + * and implementations are therefore not required to materialize it.)
  17.159 + *
  17.160 + * <h1>Invocation checking</h1>
  17.161 + * In typical programs, method handle type matching will usually succeed.
  17.162 + * But if a match fails, the JVM will throw a {@link WrongMethodTypeException},
  17.163 + * either directly (in the case of {@code invokeExact}) or indirectly as if
  17.164 + * by a failed call to {@code asType} (in the case of {@code invoke}).
  17.165 + * <p>
  17.166 + * Thus, a method type mismatch which might show up as a linkage error
  17.167 + * in a statically typed program can show up as
  17.168 + * a dynamic {@code WrongMethodTypeException}
  17.169 + * in a program which uses method handles.
  17.170 + * <p>
  17.171 + * Because method types contain "live" {@code Class} objects,
  17.172 + * method type matching takes into account both types names and class loaders.
  17.173 + * Thus, even if a method handle {@code M} is created in one
  17.174 + * class loader {@code L1} and used in another {@code L2},
  17.175 + * method handle calls are type-safe, because the caller's symbolic type
  17.176 + * descriptor, as resolved in {@code L2},
  17.177 + * is matched against the original callee method's symbolic type descriptor,
  17.178 + * as resolved in {@code L1}.
  17.179 + * The resolution in {@code L1} happens when {@code M} is created
  17.180 + * and its type is assigned, while the resolution in {@code L2} happens
  17.181 + * when the {@code invokevirtual} instruction is linked.
  17.182 + * <p>
  17.183 + * Apart from the checking of type descriptors,
  17.184 + * a method handle's capability to call its underlying method is unrestricted.
  17.185 + * If a method handle is formed on a non-public method by a class
  17.186 + * that has access to that method, the resulting handle can be used
  17.187 + * in any place by any caller who receives a reference to it.
  17.188 + * <p>
  17.189 + * Unlike with the Core Reflection API, where access is checked every time
  17.190 + * a reflective method is invoked,
  17.191 + * method handle access checking is performed
  17.192 + * <a href="MethodHandles.Lookup.html#access">when the method handle is created</a>.
  17.193 + * In the case of {@code ldc} (see below), access checking is performed as part of linking
  17.194 + * the constant pool entry underlying the constant method handle.
  17.195 + * <p>
  17.196 + * Thus, handles to non-public methods, or to methods in non-public classes,
  17.197 + * should generally be kept secret.
  17.198 + * They should not be passed to untrusted code unless their use from
  17.199 + * the untrusted code would be harmless.
  17.200 + *
  17.201 + * <h1>Method handle creation</h1>
  17.202 + * Java code can create a method handle that directly accesses
  17.203 + * any method, constructor, or field that is accessible to that code.
  17.204 + * This is done via a reflective, capability-based API called
  17.205 + * {@link java.lang.invoke.MethodHandles.Lookup MethodHandles.Lookup}
  17.206 + * For example, a static method handle can be obtained
  17.207 + * from {@link java.lang.invoke.MethodHandles.Lookup#findStatic Lookup.findStatic}.
  17.208 + * There are also conversion methods from Core Reflection API objects,
  17.209 + * such as {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect}.
  17.210 + * <p>
  17.211 + * Like classes and strings, method handles that correspond to accessible
  17.212 + * fields, methods, and constructors can also be represented directly
  17.213 + * in a class file's constant pool as constants to be loaded by {@code ldc} bytecodes.
  17.214 + * A new type of constant pool entry, {@code CONSTANT_MethodHandle},
  17.215 + * refers directly to an associated {@code CONSTANT_Methodref},
  17.216 + * {@code CONSTANT_InterfaceMethodref}, or {@code CONSTANT_Fieldref}
  17.217 + * constant pool entry.
  17.218 + * (For full details on method handle constants,
  17.219 + * see sections 4.4.8 and 5.4.3.5 of the Java Virtual Machine Specification.)
  17.220 + * <p>
  17.221 + * Method handles produced by lookups or constant loads from methods or
  17.222 + * constructors with the variable arity modifier bit ({@code 0x0080})
  17.223 + * have a corresponding variable arity, as if they were defined with
  17.224 + * the help of {@link #asVarargsCollector asVarargsCollector}.
  17.225 + * <p>
  17.226 + * A method reference may refer either to a static or non-static method.
  17.227 + * In the non-static case, the method handle type includes an explicit
  17.228 + * receiver argument, prepended before any other arguments.
  17.229 + * In the method handle's type, the initial receiver argument is typed
  17.230 + * according to the class under which the method was initially requested.
  17.231 + * (E.g., if a non-static method handle is obtained via {@code ldc},
  17.232 + * the type of the receiver is the class named in the constant pool entry.)
  17.233 + * <p>
  17.234 + * Method handle constants are subject to the same link-time access checks
  17.235 + * their corresponding bytecode instructions, and the {@code ldc} instruction
  17.236 + * will throw corresponding linkage errors if the bytecode behaviors would
  17.237 + * throw such errors.
  17.238 + * <p>
  17.239 + * As a corollary of this, access to protected members is restricted
  17.240 + * to receivers only of the accessing class, or one of its subclasses,
  17.241 + * and the accessing class must in turn be a subclass (or package sibling)
  17.242 + * of the protected member's defining class.
  17.243 + * If a method reference refers to a protected non-static method or field
  17.244 + * of a class outside the current package, the receiver argument will
  17.245 + * be narrowed to the type of the accessing class.
  17.246 + * <p>
  17.247 + * When a method handle to a virtual method is invoked, the method is
  17.248 + * always looked up in the receiver (that is, the first argument).
  17.249 + * <p>
  17.250 + * A non-virtual method handle to a specific virtual method implementation
  17.251 + * can also be created.  These do not perform virtual lookup based on
  17.252 + * receiver type.  Such a method handle simulates the effect of
  17.253 + * an {@code invokespecial} instruction to the same method.
  17.254 + *
  17.255 + * <h1>Usage examples</h1>
  17.256 + * Here are some examples of usage:
  17.257 + * <blockquote><pre>{@code
  17.258 +Object x, y; String s; int i;
  17.259 +MethodType mt; MethodHandle mh;
  17.260 +MethodHandles.Lookup lookup = MethodHandles.lookup();
  17.261 +// mt is (char,char)String
  17.262 +mt = MethodType.methodType(String.class, char.class, char.class);
  17.263 +mh = lookup.findVirtual(String.class, "replace", mt);
  17.264 +s = (String) mh.invokeExact("daddy",'d','n');
  17.265 +// invokeExact(Ljava/lang/String;CC)Ljava/lang/String;
  17.266 +assertEquals(s, "nanny");
  17.267 +// weakly typed invocation (using MHs.invoke)
  17.268 +s = (String) mh.invokeWithArguments("sappy", 'p', 'v');
  17.269 +assertEquals(s, "savvy");
  17.270 +// mt is (Object[])List
  17.271 +mt = MethodType.methodType(java.util.List.class, Object[].class);
  17.272 +mh = lookup.findStatic(java.util.Arrays.class, "asList", mt);
  17.273 +assert(mh.isVarargsCollector());
  17.274 +x = mh.invoke("one", "two");
  17.275 +// invoke(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;
  17.276 +assertEquals(x, java.util.Arrays.asList("one","two"));
  17.277 +// mt is (Object,Object,Object)Object
  17.278 +mt = MethodType.genericMethodType(3);
  17.279 +mh = mh.asType(mt);
  17.280 +x = mh.invokeExact((Object)1, (Object)2, (Object)3);
  17.281 +// invokeExact(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
  17.282 +assertEquals(x, java.util.Arrays.asList(1,2,3));
  17.283 +// mt is ()int
  17.284 +mt = MethodType.methodType(int.class);
  17.285 +mh = lookup.findVirtual(java.util.List.class, "size", mt);
  17.286 +i = (int) mh.invokeExact(java.util.Arrays.asList(1,2,3));
  17.287 +// invokeExact(Ljava/util/List;)I
  17.288 +assert(i == 3);
  17.289 +mt = MethodType.methodType(void.class, String.class);
  17.290 +mh = lookup.findVirtual(java.io.PrintStream.class, "println", mt);
  17.291 +mh.invokeExact(System.out, "Hello, world.");
  17.292 +// invokeExact(Ljava/io/PrintStream;Ljava/lang/String;)V
  17.293 + * }</pre></blockquote>
  17.294 + * Each of the above calls to {@code invokeExact} or plain {@code invoke}
  17.295 + * generates a single invokevirtual instruction with
  17.296 + * the symbolic type descriptor indicated in the following comment.
  17.297 + * In these examples, the helper method {@code assertEquals} is assumed to
  17.298 + * be a method which calls {@link java.util.Objects#equals(Object,Object) Objects.equals}
  17.299 + * on its arguments, and asserts that the result is true.
  17.300 + *
  17.301 + * <h1>Exceptions</h1>
  17.302 + * The methods {@code invokeExact} and {@code invoke} are declared
  17.303 + * to throw {@link java.lang.Throwable Throwable},
  17.304 + * which is to say that there is no static restriction on what a method handle
  17.305 + * can throw.  Since the JVM does not distinguish between checked
  17.306 + * and unchecked exceptions (other than by their class, of course),
  17.307 + * there is no particular effect on bytecode shape from ascribing
  17.308 + * checked exceptions to method handle invocations.  But in Java source
  17.309 + * code, methods which perform method handle calls must either explicitly
  17.310 + * throw {@code Throwable}, or else must catch all
  17.311 + * throwables locally, rethrowing only those which are legal in the context,
  17.312 + * and wrapping ones which are illegal.
  17.313 + *
  17.314 + * <h1><a name="sigpoly"></a>Signature polymorphism</h1>
  17.315 + * The unusual compilation and linkage behavior of
  17.316 + * {@code invokeExact} and plain {@code invoke}
  17.317 + * is referenced by the term <em>signature polymorphism</em>.
  17.318 + * As defined in the Java Language Specification,
  17.319 + * a signature polymorphic method is one which can operate with
  17.320 + * any of a wide range of call signatures and return types.
  17.321 + * <p>
  17.322 + * In source code, a call to a signature polymorphic method will
  17.323 + * compile, regardless of the requested symbolic type descriptor.
  17.324 + * As usual, the Java compiler emits an {@code invokevirtual}
  17.325 + * instruction with the given symbolic type descriptor against the named method.
  17.326 + * The unusual part is that the symbolic type descriptor is derived from
  17.327 + * the actual argument and return types, not from the method declaration.
  17.328 + * <p>
  17.329 + * When the JVM processes bytecode containing signature polymorphic calls,
  17.330 + * it will successfully link any such call, regardless of its symbolic type descriptor.
  17.331 + * (In order to retain type safety, the JVM will guard such calls with suitable
  17.332 + * dynamic type checks, as described elsewhere.)
  17.333 + * <p>
  17.334 + * Bytecode generators, including the compiler back end, are required to emit
  17.335 + * untransformed symbolic type descriptors for these methods.
  17.336 + * Tools which determine symbolic linkage are required to accept such
  17.337 + * untransformed descriptors, without reporting linkage errors.
  17.338 + *
  17.339 + * <h1>Interoperation between method handles and the Core Reflection API</h1>
  17.340 + * Using factory methods in the {@link java.lang.invoke.MethodHandles.Lookup Lookup} API,
  17.341 + * any class member represented by a Core Reflection API object
  17.342 + * can be converted to a behaviorally equivalent method handle.
  17.343 + * For example, a reflective {@link java.lang.reflect.Method Method} can
  17.344 + * be converted to a method handle using
  17.345 + * {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect}.
  17.346 + * The resulting method handles generally provide more direct and efficient
  17.347 + * access to the underlying class members.
  17.348 + * <p>
  17.349 + * As a special case,
  17.350 + * when the Core Reflection API is used to view the signature polymorphic
  17.351 + * methods {@code invokeExact} or plain {@code invoke} in this class,
  17.352 + * they appear as ordinary non-polymorphic methods.
  17.353 + * Their reflective appearance, as viewed by
  17.354 + * {@link java.lang.Class#getDeclaredMethod Class.getDeclaredMethod},
  17.355 + * is unaffected by their special status in this API.
  17.356 + * For example, {@link java.lang.reflect.Method#getModifiers Method.getModifiers}
  17.357 + * will report exactly those modifier bits required for any similarly
  17.358 + * declared method, including in this case {@code native} and {@code varargs} bits.
  17.359 + * <p>
  17.360 + * As with any reflected method, these methods (when reflected) may be
  17.361 + * invoked via {@link java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}.
  17.362 + * However, such reflective calls do not result in method handle invocations.
  17.363 + * Such a call, if passed the required argument
  17.364 + * (a single one, of type {@code Object[]}), will ignore the argument and
  17.365 + * will throw an {@code UnsupportedOperationException}.
  17.366 + * <p>
  17.367 + * Since {@code invokevirtual} instructions can natively
  17.368 + * invoke method handles under any symbolic type descriptor, this reflective view conflicts
  17.369 + * with the normal presentation of these methods via bytecodes.
  17.370 + * Thus, these two native methods, when reflectively viewed by
  17.371 + * {@code Class.getDeclaredMethod}, may be regarded as placeholders only.
  17.372 + * <p>
  17.373 + * In order to obtain an invoker method for a particular type descriptor,
  17.374 + * use {@link java.lang.invoke.MethodHandles#exactInvoker MethodHandles.exactInvoker},
  17.375 + * or {@link java.lang.invoke.MethodHandles#invoker MethodHandles.invoker}.
  17.376 + * The {@link java.lang.invoke.MethodHandles.Lookup#findVirtual Lookup.findVirtual}
  17.377 + * API is also able to return a method handle
  17.378 + * to call {@code invokeExact} or plain {@code invoke},
  17.379 + * for any specified type descriptor .
  17.380 + *
  17.381 + * <h1>Interoperation between method handles and Java generics</h1>
  17.382 + * A method handle can be obtained on a method, constructor, or field
  17.383 + * which is declared with Java generic types.
  17.384 + * As with the Core Reflection API, the type of the method handle
  17.385 + * will constructed from the erasure of the source-level type.
  17.386 + * When a method handle is invoked, the types of its arguments
  17.387 + * or the return value cast type may be generic types or type instances.
  17.388 + * If this occurs, the compiler will replace those
  17.389 + * types by their erasures when it constructs the symbolic type descriptor
  17.390 + * for the {@code invokevirtual} instruction.
  17.391 + * <p>
  17.392 + * Method handles do not represent
  17.393 + * their function-like types in terms of Java parameterized (generic) types,
  17.394 + * because there are three mismatches between function-like types and parameterized
  17.395 + * Java types.
  17.396 + * <ul>
  17.397 + * <li>Method types range over all possible arities,
  17.398 + * from no arguments to up to the  <a href="MethodHandle.html#maxarity">maximum number</a> of allowed arguments.
  17.399 + * Generics are not variadic, and so cannot represent this.</li>
  17.400 + * <li>Method types can specify arguments of primitive types,
  17.401 + * which Java generic types cannot range over.</li>
  17.402 + * <li>Higher order functions over method handles (combinators) are
  17.403 + * often generic across a wide range of function types, including
  17.404 + * those of multiple arities.  It is impossible to represent such
  17.405 + * genericity with a Java type parameter.</li>
  17.406 + * </ul>
  17.407 + *
  17.408 + * <h1><a name="maxarity"></a>Arity limits</h1>
  17.409 + * The JVM imposes on all methods and constructors of any kind an absolute
  17.410 + * limit of 255 stacked arguments.  This limit can appear more restrictive
  17.411 + * in certain cases:
  17.412 + * <ul>
  17.413 + * <li>A {@code long} or {@code double} argument counts (for purposes of arity limits) as two argument slots.
  17.414 + * <li>A non-static method consumes an extra argument for the object on which the method is called.
  17.415 + * <li>A constructor consumes an extra argument for the object which is being constructed.
  17.416 + * <li>Since a method handle&rsquo;s {@code invoke} method (or other signature-polymorphic method) is non-virtual,
  17.417 + *     it consumes an extra argument for the method handle itself, in addition to any non-virtual receiver object.
  17.418 + * </ul>
  17.419 + * These limits imply that certain method handles cannot be created, solely because of the JVM limit on stacked arguments.
  17.420 + * For example, if a static JVM method accepts exactly 255 arguments, a method handle cannot be created for it.
  17.421 + * Attempts to create method handles with impossible method types lead to an {@link IllegalArgumentException}.
  17.422 + * In particular, a method handle&rsquo;s type must not have an arity of the exact maximum 255.
  17.423 + *
  17.424 + * @see MethodType
  17.425 + * @see MethodHandles
  17.426 + * @author John Rose, JSR 292 EG
  17.427 + */
  17.428 +public abstract class MethodHandle {
  17.429 +    static { MethodHandleImpl.initStatics(); }
  17.430 +
  17.431 +    /**
  17.432 +     * Internal marker interface which distinguishes (to the Java compiler)
  17.433 +     * those methods which are <a href="MethodHandle.html#sigpoly">signature polymorphic</a>.
  17.434 +     */
  17.435 +    @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD})
  17.436 +    @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
  17.437 +    @interface PolymorphicSignature { }
  17.438 +
  17.439 +    private final MethodType type;
  17.440 +    /*private*/ final LambdaForm form;
  17.441 +    // form is not private so that invokers can easily fetch it
  17.442 +    /*private*/ MethodHandle asTypeCache;
  17.443 +    // asTypeCache is not private so that invokers can easily fetch it
  17.444 +
  17.445 +    /**
  17.446 +     * Reports the type of this method handle.
  17.447 +     * Every invocation of this method handle via {@code invokeExact} must exactly match this type.
  17.448 +     * @return the method handle type
  17.449 +     */
  17.450 +    public MethodType type() {
  17.451 +        return type;
  17.452 +    }
  17.453 +
  17.454 +    /**
  17.455 +     * Package-private constructor for the method handle implementation hierarchy.
  17.456 +     * Method handle inheritance will be contained completely within
  17.457 +     * the {@code java.lang.invoke} package.
  17.458 +     */
  17.459 +    // @param type type (permanently assigned) of the new method handle
  17.460 +    /*non-public*/ MethodHandle(MethodType type, LambdaForm form) {
  17.461 +        type.getClass();  // explicit NPE
  17.462 +        form.getClass();  // explicit NPE
  17.463 +        this.type = type;
  17.464 +        this.form = form;
  17.465 +
  17.466 +        form.prepare();  // TO DO:  Try to delay this step until just before invocation.
  17.467 +    }
  17.468 +
  17.469 +    /**
  17.470 +     * Invokes the method handle, allowing any caller type descriptor, but requiring an exact type match.
  17.471 +     * The symbolic type descriptor at the call site of {@code invokeExact} must
  17.472 +     * exactly match this method handle's {@link #type type}.
  17.473 +     * No conversions are allowed on arguments or return values.
  17.474 +     * <p>
  17.475 +     * When this method is observed via the Core Reflection API,
  17.476 +     * it will appear as a single native method, taking an object array and returning an object.
  17.477 +     * If this native method is invoked directly via
  17.478 +     * {@link java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}, via JNI,
  17.479 +     * or indirectly via {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect},
  17.480 +     * it will throw an {@code UnsupportedOperationException}.
  17.481 +     * @param args the signature-polymorphic parameter list, statically represented using varargs
  17.482 +     * @return the signature-polymorphic result, statically represented using {@code Object}
  17.483 +     * @throws WrongMethodTypeException if the target's type is not identical with the caller's symbolic type descriptor
  17.484 +     * @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call
  17.485 +     */
  17.486 +    public final native @PolymorphicSignature Object invokeExact(Object... args) throws Throwable;
  17.487 +
  17.488 +    /**
  17.489 +     * Invokes the method handle, allowing any caller type descriptor,
  17.490 +     * and optionally performing conversions on arguments and return values.
  17.491 +     * <p>
  17.492 +     * If the call site's symbolic type descriptor exactly matches this method handle's {@link #type type},
  17.493 +     * the call proceeds as if by {@link #invokeExact invokeExact}.
  17.494 +     * <p>
  17.495 +     * Otherwise, the call proceeds as if this method handle were first
  17.496 +     * adjusted by calling {@link #asType asType} to adjust this method handle
  17.497 +     * to the required type, and then the call proceeds as if by
  17.498 +     * {@link #invokeExact invokeExact} on the adjusted method handle.
  17.499 +     * <p>
  17.500 +     * There is no guarantee that the {@code asType} call is actually made.
  17.501 +     * If the JVM can predict the results of making the call, it may perform
  17.502 +     * adaptations directly on the caller's arguments,
  17.503 +     * and call the target method handle according to its own exact type.
  17.504 +     * <p>
  17.505 +     * The resolved type descriptor at the call site of {@code invoke} must
  17.506 +     * be a valid argument to the receivers {@code asType} method.
  17.507 +     * In particular, the caller must specify the same argument arity
  17.508 +     * as the callee's type,
  17.509 +     * if the callee is not a {@linkplain #asVarargsCollector variable arity collector}.
  17.510 +     * <p>
  17.511 +     * When this method is observed via the Core Reflection API,
  17.512 +     * it will appear as a single native method, taking an object array and returning an object.
  17.513 +     * If this native method is invoked directly via
  17.514 +     * {@link java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}, via JNI,
  17.515 +     * or indirectly via {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect},
  17.516 +     * it will throw an {@code UnsupportedOperationException}.
  17.517 +     * @param args the signature-polymorphic parameter list, statically represented using varargs
  17.518 +     * @return the signature-polymorphic result, statically represented using {@code Object}
  17.519 +     * @throws WrongMethodTypeException if the target's type cannot be adjusted to the caller's symbolic type descriptor
  17.520 +     * @throws ClassCastException if the target's type can be adjusted to the caller, but a reference cast fails
  17.521 +     * @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call
  17.522 +     */
  17.523 +    public final native @PolymorphicSignature Object invoke(Object... args) throws Throwable;
  17.524 +
  17.525 +    /**
  17.526 +     * Private method for trusted invocation of a method handle respecting simplified signatures.
  17.527 +     * Type mismatches will not throw {@code WrongMethodTypeException}, but could crash the JVM.
  17.528 +     * <p>
  17.529 +     * The caller signature is restricted to the following basic types:
  17.530 +     * Object, int, long, float, double, and void return.
  17.531 +     * <p>
  17.532 +     * The caller is responsible for maintaining type correctness by ensuring
  17.533 +     * that the each outgoing argument value is a member of the range of the corresponding
  17.534 +     * callee argument type.
  17.535 +     * (The caller should therefore issue appropriate casts and integer narrowing
  17.536 +     * operations on outgoing argument values.)
  17.537 +     * The caller can assume that the incoming result value is part of the range
  17.538 +     * of the callee's return type.
  17.539 +     * @param args the signature-polymorphic parameter list, statically represented using varargs
  17.540 +     * @return the signature-polymorphic result, statically represented using {@code Object}
  17.541 +     */
  17.542 +    /*non-public*/ final native @PolymorphicSignature Object invokeBasic(Object... args) throws Throwable;
  17.543 +
  17.544 +    /**
  17.545 +     * Private method for trusted invocation of a MemberName of kind {@code REF_invokeVirtual}.
  17.546 +     * The caller signature is restricted to basic types as with {@code invokeBasic}.
  17.547 +     * The trailing (not leading) argument must be a MemberName.
  17.548 +     * @param args the signature-polymorphic parameter list, statically represented using varargs
  17.549 +     * @return the signature-polymorphic result, statically represented using {@code Object}
  17.550 +     */
  17.551 +    /*non-public*/ static native @PolymorphicSignature Object linkToVirtual(Object... args) throws Throwable;
  17.552 +
  17.553 +    /**
  17.554 +     * Private method for trusted invocation of a MemberName of kind {@code REF_invokeStatic}.
  17.555 +     * The caller signature is restricted to basic types as with {@code invokeBasic}.
  17.556 +     * The trailing (not leading) argument must be a MemberName.
  17.557 +     * @param args the signature-polymorphic parameter list, statically represented using varargs
  17.558 +     * @return the signature-polymorphic result, statically represented using {@code Object}
  17.559 +     */
  17.560 +    /*non-public*/ static native @PolymorphicSignature Object linkToStatic(Object... args) throws Throwable;
  17.561 +
  17.562 +    /**
  17.563 +     * Private method for trusted invocation of a MemberName of kind {@code REF_invokeSpecial}.
  17.564 +     * The caller signature is restricted to basic types as with {@code invokeBasic}.
  17.565 +     * The trailing (not leading) argument must be a MemberName.
  17.566 +     * @param args the signature-polymorphic parameter list, statically represented using varargs
  17.567 +     * @return the signature-polymorphic result, statically represented using {@code Object}
  17.568 +     */
  17.569 +    /*non-public*/ static native @PolymorphicSignature Object linkToSpecial(Object... args) throws Throwable;
  17.570 +
  17.571 +    /**
  17.572 +     * Private method for trusted invocation of a MemberName of kind {@code REF_invokeInterface}.
  17.573 +     * The caller signature is restricted to basic types as with {@code invokeBasic}.
  17.574 +     * The trailing (not leading) argument must be a MemberName.
  17.575 +     * @param args the signature-polymorphic parameter list, statically represented using varargs
  17.576 +     * @return the signature-polymorphic result, statically represented using {@code Object}
  17.577 +     */
  17.578 +    /*non-public*/ static native @PolymorphicSignature Object linkToInterface(Object... args) throws Throwable;
  17.579 +
  17.580 +    /**
  17.581 +     * Performs a variable arity invocation, passing the arguments in the given list
  17.582 +     * to the method handle, as if via an inexact {@link #invoke invoke} from a call site
  17.583 +     * which mentions only the type {@code Object}, and whose arity is the length
  17.584 +     * of the argument list.
  17.585 +     * <p>
  17.586 +     * Specifically, execution proceeds as if by the following steps,
  17.587 +     * although the methods are not guaranteed to be called if the JVM
  17.588 +     * can predict their effects.
  17.589 +     * <ul>
  17.590 +     * <li>Determine the length of the argument array as {@code N}.
  17.591 +     *     For a null reference, {@code N=0}. </li>
  17.592 +     * <li>Determine the general type {@code TN} of {@code N} arguments as
  17.593 +     *     as {@code TN=MethodType.genericMethodType(N)}.</li>
  17.594 +     * <li>Force the original target method handle {@code MH0} to the
  17.595 +     *     required type, as {@code MH1 = MH0.asType(TN)}. </li>
  17.596 +     * <li>Spread the array into {@code N} separate arguments {@code A0, ...}. </li>
  17.597 +     * <li>Invoke the type-adjusted method handle on the unpacked arguments:
  17.598 +     *     MH1.invokeExact(A0, ...). </li>
  17.599 +     * <li>Take the return value as an {@code Object} reference. </li>
  17.600 +     * </ul>
  17.601 +     * <p>
  17.602 +     * Because of the action of the {@code asType} step, the following argument
  17.603 +     * conversions are applied as necessary:
  17.604 +     * <ul>
  17.605 +     * <li>reference casting
  17.606 +     * <li>unboxing
  17.607 +     * <li>widening primitive conversions
  17.608 +     * </ul>
  17.609 +     * <p>
  17.610 +     * The result returned by the call is boxed if it is a primitive,
  17.611 +     * or forced to null if the return type is void.
  17.612 +     * <p>
  17.613 +     * This call is equivalent to the following code:
  17.614 +     * <blockquote><pre>{@code
  17.615 +     * MethodHandle invoker = MethodHandles.spreadInvoker(this.type(), 0);
  17.616 +     * Object result = invoker.invokeExact(this, arguments);
  17.617 +     * }</pre></blockquote>
  17.618 +     * <p>
  17.619 +     * Unlike the signature polymorphic methods {@code invokeExact} and {@code invoke},
  17.620 +     * {@code invokeWithArguments} can be accessed normally via the Core Reflection API and JNI.
  17.621 +     * It can therefore be used as a bridge between native or reflective code and method handles.
  17.622 +     *
  17.623 +     * @param arguments the arguments to pass to the target
  17.624 +     * @return the result returned by the target
  17.625 +     * @throws ClassCastException if an argument cannot be converted by reference casting
  17.626 +     * @throws WrongMethodTypeException if the target's type cannot be adjusted to take the given number of {@code Object} arguments
  17.627 +     * @throws Throwable anything thrown by the target method invocation
  17.628 +     * @see MethodHandles#spreadInvoker
  17.629 +     */
  17.630 +    public Object invokeWithArguments(Object... arguments) throws Throwable {
  17.631 +        int argc = arguments == null ? 0 : arguments.length;
  17.632 +        @SuppressWarnings("LocalVariableHidesMemberVariable")
  17.633 +        MethodType type = type();
  17.634 +        if (type.parameterCount() != argc || isVarargsCollector()) {
  17.635 +            // simulate invoke
  17.636 +            return asType(MethodType.genericMethodType(argc)).invokeWithArguments(arguments);
  17.637 +        }
  17.638 +        MethodHandle invoker = type.invokers().varargsInvoker();
  17.639 +        return invoker.invokeExact(this, arguments);
  17.640 +    }
  17.641 +
  17.642 +    /**
  17.643 +     * Performs a variable arity invocation, passing the arguments in the given array
  17.644 +     * to the method handle, as if via an inexact {@link #invoke invoke} from a call site
  17.645 +     * which mentions only the type {@code Object}, and whose arity is the length
  17.646 +     * of the argument array.
  17.647 +     * <p>
  17.648 +     * This method is also equivalent to the following code:
  17.649 +     * <blockquote><pre>{@code
  17.650 +     *   invokeWithArguments(arguments.toArray()
  17.651 +     * }</pre></blockquote>
  17.652 +     *
  17.653 +     * @param arguments the arguments to pass to the target
  17.654 +     * @return the result returned by the target
  17.655 +     * @throws NullPointerException if {@code arguments} is a null reference
  17.656 +     * @throws ClassCastException if an argument cannot be converted by reference casting
  17.657 +     * @throws WrongMethodTypeException if the target's type cannot be adjusted to take the given number of {@code Object} arguments
  17.658 +     * @throws Throwable anything thrown by the target method invocation
  17.659 +     */
  17.660 +    public Object invokeWithArguments(java.util.List<?> arguments) throws Throwable {
  17.661 +        return invokeWithArguments(arguments.toArray());
  17.662 +    }
  17.663 +
  17.664 +    /**
  17.665 +     * Produces an adapter method handle which adapts the type of the
  17.666 +     * current method handle to a new type.
  17.667 +     * The resulting method handle is guaranteed to report a type
  17.668 +     * which is equal to the desired new type.
  17.669 +     * <p>
  17.670 +     * If the original type and new type are equal, returns {@code this}.
  17.671 +     * <p>
  17.672 +     * The new method handle, when invoked, will perform the following
  17.673 +     * steps:
  17.674 +     * <ul>
  17.675 +     * <li>Convert the incoming argument list to match the original
  17.676 +     *     method handle's argument list.
  17.677 +     * <li>Invoke the original method handle on the converted argument list.
  17.678 +     * <li>Convert any result returned by the original method handle
  17.679 +     *     to the return type of new method handle.
  17.680 +     * </ul>
  17.681 +     * <p>
  17.682 +     * This method provides the crucial behavioral difference between
  17.683 +     * {@link #invokeExact invokeExact} and plain, inexact {@link #invoke invoke}.
  17.684 +     * The two methods
  17.685 +     * perform the same steps when the caller's type descriptor exactly m atches
  17.686 +     * the callee's, but when the types differ, plain {@link #invoke invoke}
  17.687 +     * also calls {@code asType} (or some internal equivalent) in order
  17.688 +     * to match up the caller's and callee's types.
  17.689 +     * <p>
  17.690 +     * If the current method is a variable arity method handle
  17.691 +     * argument list conversion may involve the conversion and collection
  17.692 +     * of several arguments into an array, as
  17.693 +     * {@linkplain #asVarargsCollector described elsewhere}.
  17.694 +     * In every other case, all conversions are applied <em>pairwise</em>,
  17.695 +     * which means that each argument or return value is converted to
  17.696 +     * exactly one argument or return value (or no return value).
  17.697 +     * The applied conversions are defined by consulting the
  17.698 +     * the corresponding component types of the old and new
  17.699 +     * method handle types.
  17.700 +     * <p>
  17.701 +     * Let <em>T0</em> and <em>T1</em> be corresponding new and old parameter types,
  17.702 +     * or old and new return types.  Specifically, for some valid index {@code i}, let
  17.703 +     * <em>T0</em>{@code =newType.parameterType(i)} and <em>T1</em>{@code =this.type().parameterType(i)}.
  17.704 +     * Or else, going the other way for return values, let
  17.705 +     * <em>T0</em>{@code =this.type().returnType()} and <em>T1</em>{@code =newType.returnType()}.
  17.706 +     * If the types are the same, the new method handle makes no change
  17.707 +     * to the corresponding argument or return value (if any).
  17.708 +     * Otherwise, one of the following conversions is applied
  17.709 +     * if possible:
  17.710 +     * <ul>
  17.711 +     * <li>If <em>T0</em> and <em>T1</em> are references, then a cast to <em>T1</em> is applied.
  17.712 +     *     (The types do not need to be related in any particular way.
  17.713 +     *     This is because a dynamic value of null can convert to any reference type.)
  17.714 +     * <li>If <em>T0</em> and <em>T1</em> are primitives, then a Java method invocation
  17.715 +     *     conversion (JLS 5.3) is applied, if one exists.
  17.716 +     *     (Specifically, <em>T0</em> must convert to <em>T1</em> by a widening primitive conversion.)
  17.717 +     * <li>If <em>T0</em> is a primitive and <em>T1</em> a reference,
  17.718 +     *     a Java casting conversion (JLS 5.5) is applied if one exists.
  17.719 +     *     (Specifically, the value is boxed from <em>T0</em> to its wrapper class,
  17.720 +     *     which is then widened as needed to <em>T1</em>.)
  17.721 +     * <li>If <em>T0</em> is a reference and <em>T1</em> a primitive, an unboxing
  17.722 +     *     conversion will be applied at runtime, possibly followed
  17.723 +     *     by a Java method invocation conversion (JLS 5.3)
  17.724 +     *     on the primitive value.  (These are the primitive widening conversions.)
  17.725 +     *     <em>T0</em> must be a wrapper class or a supertype of one.
  17.726 +     *     (In the case where <em>T0</em> is Object, these are the conversions
  17.727 +     *     allowed by {@link java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}.)
  17.728 +     *     The unboxing conversion must have a possibility of success, which means that
  17.729 +     *     if <em>T0</em> is not itself a wrapper class, there must exist at least one
  17.730 +     *     wrapper class <em>TW</em> which is a subtype of <em>T0</em> and whose unboxed
  17.731 +     *     primitive value can be widened to <em>T1</em>.
  17.732 +     * <li>If the return type <em>T1</em> is marked as void, any returned value is discarded
  17.733 +     * <li>If the return type <em>T0</em> is void and <em>T1</em> a reference, a null value is introduced.
  17.734 +     * <li>If the return type <em>T0</em> is void and <em>T1</em> a primitive,
  17.735 +     *     a zero value is introduced.
  17.736 +     * </ul>
  17.737 +    * (<em>Note:</em> Both <em>T0</em> and <em>T1</em> may be regarded as static types,
  17.738 +     * because neither corresponds specifically to the <em>dynamic type</em> of any
  17.739 +     * actual argument or return value.)
  17.740 +     * <p>
  17.741 +     * The method handle conversion cannot be made if any one of the required
  17.742 +     * pairwise conversions cannot be made.
  17.743 +     * <p>
  17.744 +     * At runtime, the conversions applied to reference arguments
  17.745 +     * or return values may require additional runtime checks which can fail.
  17.746 +     * An unboxing operation may fail because the original reference is null,
  17.747 +     * causing a {@link java.lang.NullPointerException NullPointerException}.
  17.748 +     * An unboxing operation or a reference cast may also fail on a reference
  17.749 +     * to an object of the wrong type,
  17.750 +     * causing a {@link java.lang.ClassCastException ClassCastException}.
  17.751 +     * Although an unboxing operation may accept several kinds of wrappers,
  17.752 +     * if none are available, a {@code ClassCastException} will be thrown.
  17.753 +     *
  17.754 +     * @param newType the expected type of the new method handle
  17.755 +     * @return a method handle which delegates to {@code this} after performing
  17.756 +     *           any necessary argument conversions, and arranges for any
  17.757 +     *           necessary return value conversions
  17.758 +     * @throws NullPointerException if {@code newType} is a null reference
  17.759 +     * @throws WrongMethodTypeException if the conversion cannot be made
  17.760 +     * @see MethodHandles#explicitCastArguments
  17.761 +     */
  17.762 +    public MethodHandle asType(MethodType newType) {
  17.763 +        // Fast path alternative to a heavyweight {@code asType} call.
  17.764 +        // Return 'this' if the conversion will be a no-op.
  17.765 +        if (newType == type) {
  17.766 +            return this;
  17.767 +        }
  17.768 +        // Return 'this.asTypeCache' if the conversion is already memoized.
  17.769 +        MethodHandle atc = asTypeCache;
  17.770 +        if (atc != null && newType == atc.type) {
  17.771 +            return atc;
  17.772 +        }
  17.773 +        return asTypeUncached(newType);
  17.774 +    }
  17.775 +
  17.776 +    /** Override this to change asType behavior. */
  17.777 +    /*non-public*/ MethodHandle asTypeUncached(MethodType newType) {
  17.778 +        if (!type.isConvertibleTo(newType))
  17.779 +            throw new WrongMethodTypeException("cannot convert "+this+" to "+newType);
  17.780 +        return asTypeCache = convertArguments(newType);
  17.781 +    }
  17.782 +
  17.783 +    /**
  17.784 +     * Makes an <em>array-spreading</em> method handle, which accepts a trailing array argument
  17.785 +     * and spreads its elements as positional arguments.
  17.786 +     * The new method handle adapts, as its <i>target</i>,
  17.787 +     * the current method handle.  The type of the adapter will be
  17.788 +     * the same as the type of the target, except that the final
  17.789 +     * {@code arrayLength} parameters of the target's type are replaced
  17.790 +     * by a single array parameter of type {@code arrayType}.
  17.791 +     * <p>
  17.792 +     * If the array element type differs from any of the corresponding
  17.793 +     * argument types on the original target,
  17.794 +     * the original target is adapted to take the array elements directly,
  17.795 +     * as if by a call to {@link #asType asType}.
  17.796 +     * <p>
  17.797 +     * When called, the adapter replaces a trailing array argument
  17.798 +     * by the array's elements, each as its own argument to the target.
  17.799 +     * (The order of the arguments is preserved.)
  17.800 +     * They are converted pairwise by casting and/or unboxing
  17.801 +     * to the types of the trailing parameters of the target.
  17.802 +     * Finally the target is called.
  17.803 +     * What the target eventually returns is returned unchanged by the adapter.
  17.804 +     * <p>
  17.805 +     * Before calling the target, the adapter verifies that the array
  17.806 +     * contains exactly enough elements to provide a correct argument count
  17.807 +     * to the target method handle.
  17.808 +     * (The array may also be null when zero elements are required.)
  17.809 +     * <p>
  17.810 +     * If, when the adapter is called, the supplied array argument does
  17.811 +     * not have the correct number of elements, the adapter will throw
  17.812 +     * an {@link IllegalArgumentException} instead of invoking the target.
  17.813 +     * <p>
  17.814 +     * Here are some simple examples of array-spreading method handles:
  17.815 +     * <blockquote><pre>{@code
  17.816 +MethodHandle equals = publicLookup()
  17.817 +  .findVirtual(String.class, "equals", methodType(boolean.class, Object.class));
  17.818 +assert( (boolean) equals.invokeExact("me", (Object)"me"));
  17.819 +assert(!(boolean) equals.invokeExact("me", (Object)"thee"));
  17.820 +// spread both arguments from a 2-array:
  17.821 +MethodHandle eq2 = equals.asSpreader(Object[].class, 2);
  17.822 +assert( (boolean) eq2.invokeExact(new Object[]{ "me", "me" }));
  17.823 +assert(!(boolean) eq2.invokeExact(new Object[]{ "me", "thee" }));
  17.824 +// try to spread from anything but a 2-array:
  17.825 +for (int n = 0; n <= 10; n++) {
  17.826 +  Object[] badArityArgs = (n == 2 ? null : new Object[n]);
  17.827 +  try { assert((boolean) eq2.invokeExact(badArityArgs) && false); }
  17.828 +  catch (IllegalArgumentException ex) { } // OK
  17.829 +}
  17.830 +// spread both arguments from a String array:
  17.831 +MethodHandle eq2s = equals.asSpreader(String[].class, 2);
  17.832 +assert( (boolean) eq2s.invokeExact(new String[]{ "me", "me" }));
  17.833 +assert(!(boolean) eq2s.invokeExact(new String[]{ "me", "thee" }));
  17.834 +// spread second arguments from a 1-array:
  17.835 +MethodHandle eq1 = equals.asSpreader(Object[].class, 1);
  17.836 +assert( (boolean) eq1.invokeExact("me", new Object[]{ "me" }));
  17.837 +assert(!(boolean) eq1.invokeExact("me", new Object[]{ "thee" }));
  17.838 +// spread no arguments from a 0-array or null:
  17.839 +MethodHandle eq0 = equals.asSpreader(Object[].class, 0);
  17.840 +assert( (boolean) eq0.invokeExact("me", (Object)"me", new Object[0]));
  17.841 +assert(!(boolean) eq0.invokeExact("me", (Object)"thee", (Object[])null));
  17.842 +// asSpreader and asCollector are approximate inverses:
  17.843 +for (int n = 0; n <= 2; n++) {
  17.844 +    for (Class<?> a : new Class<?>[]{Object[].class, String[].class, CharSequence[].class}) {
  17.845 +        MethodHandle equals2 = equals.asSpreader(a, n).asCollector(a, n);
  17.846 +        assert( (boolean) equals2.invokeWithArguments("me", "me"));
  17.847 +        assert(!(boolean) equals2.invokeWithArguments("me", "thee"));
  17.848 +    }
  17.849 +}
  17.850 +MethodHandle caToString = publicLookup()
  17.851 +  .findStatic(Arrays.class, "toString", methodType(String.class, char[].class));
  17.852 +assertEquals("[A, B, C]", (String) caToString.invokeExact("ABC".toCharArray()));
  17.853 +MethodHandle caString3 = caToString.asCollector(char[].class, 3);
  17.854 +assertEquals("[A, B, C]", (String) caString3.invokeExact('A', 'B', 'C'));
  17.855 +MethodHandle caToString2 = caString3.asSpreader(char[].class, 2);
  17.856 +assertEquals("[A, B, C]", (String) caToString2.invokeExact('A', "BC".toCharArray()));
  17.857 +     * }</pre></blockquote>
  17.858 +     * @param arrayType usually {@code Object[]}, the type of the array argument from which to extract the spread arguments
  17.859 +     * @param arrayLength the number of arguments to spread from an incoming array argument
  17.860 +     * @return a new method handle which spreads its final array argument,
  17.861 +     *         before calling the original method handle
  17.862 +     * @throws NullPointerException if {@code arrayType} is a null reference
  17.863 +     * @throws IllegalArgumentException if {@code arrayType} is not an array type,
  17.864 +     *         or if target does not have at least
  17.865 +     *         {@code arrayLength} parameter types,
  17.866 +     *         or if {@code arrayLength} is negative,
  17.867 +     *         or if the resulting method handle's type would have
  17.868 +     *         <a href="MethodHandle.html#maxarity">too many parameters</a>
  17.869 +     * @throws WrongMethodTypeException if the implied {@code asType} call fails
  17.870 +     * @see #asCollector
  17.871 +     */
  17.872 +    public MethodHandle asSpreader(Class<?> arrayType, int arrayLength) {
  17.873 +        asSpreaderChecks(arrayType, arrayLength);
  17.874 +        int spreadArgPos = type.parameterCount() - arrayLength;
  17.875 +        return MethodHandleImpl.makeSpreadArguments(this, arrayType, spreadArgPos, arrayLength);
  17.876 +    }
  17.877 +
  17.878 +    private void asSpreaderChecks(Class<?> arrayType, int arrayLength) {
  17.879 +        spreadArrayChecks(arrayType, arrayLength);
  17.880 +        int nargs = type().parameterCount();
  17.881 +        if (nargs < arrayLength || arrayLength < 0)
  17.882 +            throw newIllegalArgumentException("bad spread array length");
  17.883 +        if (arrayType != Object[].class && arrayLength != 0) {
  17.884 +            boolean sawProblem = false;
  17.885 +            Class<?> arrayElement = arrayType.getComponentType();
  17.886 +            for (int i = nargs - arrayLength; i < nargs; i++) {
  17.887 +                if (!MethodType.canConvert(arrayElement, type().parameterType(i))) {
  17.888 +                    sawProblem = true;
  17.889 +                    break;
  17.890 +                }
  17.891 +            }
  17.892 +            if (sawProblem) {
  17.893 +                ArrayList<Class<?>> ptypes = new ArrayList<>(type().parameterList());
  17.894 +                for (int i = nargs - arrayLength; i < nargs; i++) {
  17.895 +                    ptypes.set(i, arrayElement);
  17.896 +                }
  17.897 +                // elicit an error:
  17.898 +                this.asType(MethodType.methodType(type().returnType(), ptypes));
  17.899 +            }
  17.900 +        }
  17.901 +    }
  17.902 +
  17.903 +    private void spreadArrayChecks(Class<?> arrayType, int arrayLength) {
  17.904 +        Class<?> arrayElement = arrayType.getComponentType();
  17.905 +        if (arrayElement == null)
  17.906 +            throw newIllegalArgumentException("not an array type", arrayType);
  17.907 +        if ((arrayLength & 0x7F) != arrayLength) {
  17.908 +            if ((arrayLength & 0xFF) != arrayLength)
  17.909 +                throw newIllegalArgumentException("array length is not legal", arrayLength);
  17.910 +            assert(arrayLength >= 128);
  17.911 +            if (arrayElement == long.class ||
  17.912 +                arrayElement == double.class)
  17.913 +                throw newIllegalArgumentException("array length is not legal for long[] or double[]", arrayLength);
  17.914 +        }
  17.915 +    }
  17.916 +
  17.917 +    /**
  17.918 +     * Makes an <em>array-collecting</em> method handle, which accepts a given number of trailing
  17.919 +     * positional arguments and collects them into an array argument.
  17.920 +     * The new method handle adapts, as its <i>target</i>,
  17.921 +     * the current method handle.  The type of the adapter will be
  17.922 +     * the same as the type of the target, except that a single trailing
  17.923 +     * parameter (usually of type {@code arrayType}) is replaced by
  17.924 +     * {@code arrayLength} parameters whose type is element type of {@code arrayType}.
  17.925 +     * <p>
  17.926 +     * If the array type differs from the final argument type on the original target,
  17.927 +     * the original target is adapted to take the array type directly,
  17.928 +     * as if by a call to {@link #asType asType}.
  17.929 +     * <p>
  17.930 +     * When called, the adapter replaces its trailing {@code arrayLength}
  17.931 +     * arguments by a single new array of type {@code arrayType}, whose elements
  17.932 +     * comprise (in order) the replaced arguments.
  17.933 +     * Finally the target is called.
  17.934 +     * What the target eventually returns is returned unchanged by the adapter.
  17.935 +     * <p>
  17.936 +     * (The array may also be a shared constant when {@code arrayLength} is zero.)
  17.937 +     * <p>
  17.938 +     * (<em>Note:</em> The {@code arrayType} is often identical to the last
  17.939 +     * parameter type of the original target.
  17.940 +     * It is an explicit argument for symmetry with {@code asSpreader}, and also
  17.941 +     * to allow the target to use a simple {@code Object} as its last parameter type.)
  17.942 +     * <p>
  17.943 +     * In order to create a collecting adapter which is not restricted to a particular
  17.944 +     * number of collected arguments, use {@link #asVarargsCollector asVarargsCollector} instead.
  17.945 +     * <p>
  17.946 +     * Here are some examples of array-collecting method handles:
  17.947 +     * <blockquote><pre>{@code
  17.948 +MethodHandle deepToString = publicLookup()
  17.949 +  .findStatic(Arrays.class, "deepToString", methodType(String.class, Object[].class));
  17.950 +assertEquals("[won]",   (String) deepToString.invokeExact(new Object[]{"won"}));
  17.951 +MethodHandle ts1 = deepToString.asCollector(Object[].class, 1);
  17.952 +assertEquals(methodType(String.class, Object.class), ts1.type());
  17.953 +//assertEquals("[won]", (String) ts1.invokeExact(         new Object[]{"won"})); //FAIL
  17.954 +assertEquals("[[won]]", (String) ts1.invokeExact((Object) new Object[]{"won"}));
  17.955 +// arrayType can be a subtype of Object[]
  17.956 +MethodHandle ts2 = deepToString.asCollector(String[].class, 2);
  17.957 +assertEquals(methodType(String.class, String.class, String.class), ts2.type());
  17.958 +assertEquals("[two, too]", (String) ts2.invokeExact("two", "too"));
  17.959 +MethodHandle ts0 = deepToString.asCollector(Object[].class, 0);
  17.960 +assertEquals("[]", (String) ts0.invokeExact());
  17.961 +// collectors can be nested, Lisp-style
  17.962 +MethodHandle ts22 = deepToString.asCollector(Object[].class, 3).asCollector(String[].class, 2);
  17.963 +assertEquals("[A, B, [C, D]]", ((String) ts22.invokeExact((Object)'A', (Object)"B", "C", "D")));
  17.964 +// arrayType can be any primitive array type
  17.965 +MethodHandle bytesToString = publicLookup()
  17.966 +  .findStatic(Arrays.class, "toString", methodType(String.class, byte[].class))
  17.967 +  .asCollector(byte[].class, 3);
  17.968 +assertEquals("[1, 2, 3]", (String) bytesToString.invokeExact((byte)1, (byte)2, (byte)3));
  17.969 +MethodHandle longsToString = publicLookup()
  17.970 +  .findStatic(Arrays.class, "toString", methodType(String.class, long[].class))
  17.971 +  .asCollector(long[].class, 1);
  17.972 +assertEquals("[123]", (String) longsToString.invokeExact((long)123));
  17.973 +     * }</pre></blockquote>
  17.974 +     * @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments
  17.975 +     * @param arrayLength the number of arguments to collect into a new array argument
  17.976 +     * @return a new method handle which collects some trailing argument
  17.977 +     *         into an array, before calling the original method handle
  17.978 +     * @throws NullPointerException if {@code arrayType} is a null reference
  17.979 +     * @throws IllegalArgumentException if {@code arrayType} is not an array type
  17.980 +     *         or {@code arrayType} is not assignable to this method handle's trailing parameter type,
  17.981 +     *         or {@code arrayLength} is not a legal array size,
  17.982 +     *         or the resulting method handle's type would have
  17.983 +     *         <a href="MethodHandle.html#maxarity">too many parameters</a>
  17.984 +     * @throws WrongMethodTypeException if the implied {@code asType} call fails
  17.985 +     * @see #asSpreader
  17.986 +     * @see #asVarargsCollector
  17.987 +     */
  17.988 +    public MethodHandle asCollector(Class<?> arrayType, int arrayLength) {
  17.989 +        asCollectorChecks(arrayType, arrayLength);
  17.990 +        int collectArgPos = type().parameterCount()-1;
  17.991 +        MethodHandle target = this;
  17.992 +        if (arrayType != type().parameterType(collectArgPos))
  17.993 +            target = convertArguments(type().changeParameterType(collectArgPos, arrayType));
  17.994 +        MethodHandle collector = ValueConversions.varargsArray(arrayType, arrayLength);
  17.995 +        return MethodHandles.collectArguments(target, collectArgPos, collector);
  17.996 +    }
  17.997 +
  17.998 +    // private API: return true if last param exactly matches arrayType
  17.999 +    private boolean asCollectorChecks(Class<?> arrayType, int arrayLength) {
 17.1000 +        spreadArrayChecks(arrayType, arrayLength);
 17.1001 +        int nargs = type().parameterCount();
 17.1002 +        if (nargs != 0) {
 17.1003 +            Class<?> lastParam = type().parameterType(nargs-1);
 17.1004 +            if (lastParam == arrayType)  return true;
 17.1005 +            if (lastParam.isAssignableFrom(arrayType))  return false;
 17.1006 +        }
 17.1007 +        throw newIllegalArgumentException("array type not assignable to trailing argument", this, arrayType);
 17.1008 +    }
 17.1009 +
 17.1010 +    /**
 17.1011 +     * Makes a <em>variable arity</em> adapter which is able to accept
 17.1012 +     * any number of trailing positional arguments and collect them
 17.1013 +     * into an array argument.
 17.1014 +     * <p>
 17.1015 +     * The type and behavior of the adapter will be the same as
 17.1016 +     * the type and behavior of the target, except that certain
 17.1017 +     * {@code invoke} and {@code asType} requests can lead to
 17.1018 +     * trailing positional arguments being collected into target's
 17.1019 +     * trailing parameter.
 17.1020 +     * Also, the last parameter type of the adapter will be
 17.1021 +     * {@code arrayType}, even if the target has a different
 17.1022 +     * last parameter type.
 17.1023 +     * <p>
 17.1024 +     * This transformation may return {@code this} if the method handle is
 17.1025 +     * already of variable arity and its trailing parameter type
 17.1026 +     * is identical to {@code arrayType}.
 17.1027 +     * <p>
 17.1028 +     * When called with {@link #invokeExact invokeExact}, the adapter invokes
 17.1029 +     * the target with no argument changes.
 17.1030 +     * (<em>Note:</em> This behavior is different from a
 17.1031 +     * {@linkplain #asCollector fixed arity collector},
 17.1032 +     * since it accepts a whole array of indeterminate length,
 17.1033 +     * rather than a fixed number of arguments.)
 17.1034 +     * <p>
 17.1035 +     * When called with plain, inexact {@link #invoke invoke}, if the caller
 17.1036 +     * type is the same as the adapter, the adapter invokes the target as with
 17.1037 +     * {@code invokeExact}.
 17.1038 +     * (This is the normal behavior for {@code invoke} when types match.)
 17.1039 +     * <p>
 17.1040 +     * Otherwise, if the caller and adapter arity are the same, and the
 17.1041 +     * trailing parameter type of the caller is a reference type identical to
 17.1042 +     * or assignable to the trailing parameter type of the adapter,
 17.1043 +     * the arguments and return values are converted pairwise,
 17.1044 +     * as if by {@link #asType asType} on a fixed arity
 17.1045 +     * method handle.
 17.1046 +     * <p>
 17.1047 +     * Otherwise, the arities differ, or the adapter's trailing parameter
 17.1048 +     * type is not assignable from the corresponding caller type.
 17.1049 +     * In this case, the adapter replaces all trailing arguments from
 17.1050 +     * the original trailing argument position onward, by
 17.1051 +     * a new array of type {@code arrayType}, whose elements
 17.1052 +     * comprise (in order) the replaced arguments.
 17.1053 +     * <p>
 17.1054 +     * The caller type must provides as least enough arguments,
 17.1055 +     * and of the correct type, to satisfy the target's requirement for
 17.1056 +     * positional arguments before the trailing array argument.
 17.1057 +     * Thus, the caller must supply, at a minimum, {@code N-1} arguments,
 17.1058 +     * where {@code N} is the arity of the target.
 17.1059 +     * Also, there must exist conversions from the incoming arguments
 17.1060 +     * to the target's arguments.
 17.1061 +     * As with other uses of plain {@code invoke}, if these basic
 17.1062 +     * requirements are not fulfilled, a {@code WrongMethodTypeException}
 17.1063 +     * may be thrown.
 17.1064 +     * <p>
 17.1065 +     * In all cases, what the target eventually returns is returned unchanged by the adapter.
 17.1066 +     * <p>
 17.1067 +     * In the final case, it is exactly as if the target method handle were
 17.1068 +     * temporarily adapted with a {@linkplain #asCollector fixed arity collector}
 17.1069 +     * to the arity required by the caller type.
 17.1070 +     * (As with {@code asCollector}, if the array length is zero,
 17.1071 +     * a shared constant may be used instead of a new array.
 17.1072 +     * If the implied call to {@code asCollector} would throw
 17.1073 +     * an {@code IllegalArgumentException} or {@code WrongMethodTypeException},
 17.1074 +     * the call to the variable arity adapter must throw
 17.1075 +     * {@code WrongMethodTypeException}.)
 17.1076 +     * <p>
 17.1077 +     * The behavior of {@link #asType asType} is also specialized for
 17.1078 +     * variable arity adapters, to maintain the invariant that
 17.1079 +     * plain, inexact {@code invoke} is always equivalent to an {@code asType}
 17.1080 +     * call to adjust the target type, followed by {@code invokeExact}.
 17.1081 +     * Therefore, a variable arity adapter responds
 17.1082 +     * to an {@code asType} request by building a fixed arity collector,
 17.1083 +     * if and only if the adapter and requested type differ either
 17.1084 +     * in arity or trailing argument type.
 17.1085 +     * The resulting fixed arity collector has its type further adjusted
 17.1086 +     * (if necessary) to the requested type by pairwise conversion,
 17.1087 +     * as if by another application of {@code asType}.
 17.1088 +     * <p>
 17.1089 +     * When a method handle is obtained by executing an {@code ldc} instruction
 17.1090 +     * of a {@code CONSTANT_MethodHandle} constant, and the target method is marked
 17.1091 +     * as a variable arity method (with the modifier bit {@code 0x0080}),
 17.1092 +     * the method handle will accept multiple arities, as if the method handle
 17.1093 +     * constant were created by means of a call to {@code asVarargsCollector}.
 17.1094 +     * <p>
 17.1095 +     * In order to create a collecting adapter which collects a predetermined
 17.1096 +     * number of arguments, and whose type reflects this predetermined number,
 17.1097 +     * use {@link #asCollector asCollector} instead.
 17.1098 +     * <p>
 17.1099 +     * No method handle transformations produce new method handles with
 17.1100 +     * variable arity, unless they are documented as doing so.
 17.1101 +     * Therefore, besides {@code asVarargsCollector},
 17.1102 +     * all methods in {@code MethodHandle} and {@code MethodHandles}
 17.1103 +     * will return a method handle with fixed arity,
 17.1104 +     * except in the cases where they are specified to return their original
 17.1105 +     * operand (e.g., {@code asType} of the method handle's own type).
 17.1106 +     * <p>
 17.1107 +     * Calling {@code asVarargsCollector} on a method handle which is already
 17.1108 +     * of variable arity will produce a method handle with the same type and behavior.
 17.1109 +     * It may (or may not) return the original variable arity method handle.
 17.1110 +     * <p>
 17.1111 +     * Here is an example, of a list-making variable arity method handle:
 17.1112 +     * <blockquote><pre>{@code
 17.1113 +MethodHandle deepToString = publicLookup()
 17.1114 +  .findStatic(Arrays.class, "deepToString", methodType(String.class, Object[].class));
 17.1115 +MethodHandle ts1 = deepToString.asVarargsCollector(Object[].class);
 17.1116 +assertEquals("[won]",   (String) ts1.invokeExact(    new Object[]{"won"}));
 17.1117 +assertEquals("[won]",   (String) ts1.invoke(         new Object[]{"won"}));
 17.1118 +assertEquals("[won]",   (String) ts1.invoke(                      "won" ));
 17.1119 +assertEquals("[[won]]", (String) ts1.invoke((Object) new Object[]{"won"}));
 17.1120 +// findStatic of Arrays.asList(...) produces a variable arity method handle:
 17.1121 +MethodHandle asList = publicLookup()
 17.1122 +  .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class));
 17.1123 +assertEquals(methodType(List.class, Object[].class), asList.type());
 17.1124 +assert(asList.isVarargsCollector());
 17.1125 +assertEquals("[]", asList.invoke().toString());
 17.1126 +assertEquals("[1]", asList.invoke(1).toString());
 17.1127 +assertEquals("[two, too]", asList.invoke("two", "too").toString());
 17.1128 +String[] argv = { "three", "thee", "tee" };
 17.1129 +assertEquals("[three, thee, tee]", asList.invoke(argv).toString());
 17.1130 +assertEquals("[three, thee, tee]", asList.invoke((Object[])argv).toString());
 17.1131 +List ls = (List) asList.invoke((Object)argv);
 17.1132 +assertEquals(1, ls.size());
 17.1133 +assertEquals("[three, thee, tee]", Arrays.toString((Object[])ls.get(0)));
 17.1134 +     * }</pre></blockquote>
 17.1135 +     * <p style="font-size:smaller;">
 17.1136 +     * <em>Discussion:</em>
 17.1137 +     * These rules are designed as a dynamically-typed variation
 17.1138 +     * of the Java rules for variable arity methods.
 17.1139 +     * In both cases, callers to a variable arity method or method handle
 17.1140 +     * can either pass zero or more positional arguments, or else pass
 17.1141 +     * pre-collected arrays of any length.  Users should be aware of the
 17.1142 +     * special role of the final argument, and of the effect of a
 17.1143 +     * type match on that final argument, which determines whether
 17.1144 +     * or not a single trailing argument is interpreted as a whole
 17.1145 +     * array or a single element of an array to be collected.
 17.1146 +     * Note that the dynamic type of the trailing argument has no
 17.1147 +     * effect on this decision, only a comparison between the symbolic
 17.1148 +     * type descriptor of the call site and the type descriptor of the method handle.)
 17.1149 +     *
 17.1150 +     * @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments
 17.1151 +     * @return a new method handle which can collect any number of trailing arguments
 17.1152 +     *         into an array, before calling the original method handle
 17.1153 +     * @throws NullPointerException if {@code arrayType} is a null reference
 17.1154 +     * @throws IllegalArgumentException if {@code arrayType} is not an array type
 17.1155 +     *         or {@code arrayType} is not assignable to this method handle's trailing parameter type
 17.1156 +     * @see #asCollector
 17.1157 +     * @see #isVarargsCollector
 17.1158 +     * @see #asFixedArity
 17.1159 +     */
 17.1160 +    public MethodHandle asVarargsCollector(Class<?> arrayType) {
 17.1161 +        Class<?> arrayElement = arrayType.getComponentType();
 17.1162 +        boolean lastMatch = asCollectorChecks(arrayType, 0);
 17.1163 +        if (isVarargsCollector() && lastMatch)
 17.1164 +            return this;
 17.1165 +        return MethodHandleImpl.makeVarargsCollector(this, arrayType);
 17.1166 +    }
 17.1167 +
 17.1168 +    /**
 17.1169 +     * Determines if this method handle
 17.1170 +     * supports {@linkplain #asVarargsCollector variable arity} calls.
 17.1171 +     * Such method handles arise from the following sources:
 17.1172 +     * <ul>
 17.1173 +     * <li>a call to {@linkplain #asVarargsCollector asVarargsCollector}
 17.1174 +     * <li>a call to a {@linkplain java.lang.invoke.MethodHandles.Lookup lookup method}
 17.1175 +     *     which resolves to a variable arity Java method or constructor
 17.1176 +     * <li>an {@code ldc} instruction of a {@code CONSTANT_MethodHandle}
 17.1177 +     *     which resolves to a variable arity Java method or constructor
 17.1178 +     * </ul>
 17.1179 +     * @return true if this method handle accepts more than one arity of plain, inexact {@code invoke} calls
 17.1180 +     * @see #asVarargsCollector
 17.1181 +     * @see #asFixedArity
 17.1182 +     */
 17.1183 +    public boolean isVarargsCollector() {
 17.1184 +        return false;
 17.1185 +    }
 17.1186 +
 17.1187 +    /**
 17.1188 +     * Makes a <em>fixed arity</em> method handle which is otherwise
 17.1189 +     * equivalent to the current method handle.
 17.1190 +     * <p>
 17.1191 +     * If the current method handle is not of
 17.1192 +     * {@linkplain #asVarargsCollector variable arity},
 17.1193 +     * the current method handle is returned.
 17.1194 +     * This is true even if the current method handle
 17.1195 +     * could not be a valid input to {@code asVarargsCollector}.
 17.1196 +     * <p>
 17.1197 +     * Otherwise, the resulting fixed-arity method handle has the same
 17.1198 +     * type and behavior of the current method handle,
 17.1199 +     * except that {@link #isVarargsCollector isVarargsCollector}
 17.1200 +     * will be false.
 17.1201 +     * The fixed-arity method handle may (or may not) be the
 17.1202 +     * a previous argument to {@code asVarargsCollector}.
 17.1203 +     * <p>
 17.1204 +     * Here is an example, of a list-making variable arity method handle:
 17.1205 +     * <blockquote><pre>{@code
 17.1206 +MethodHandle asListVar = publicLookup()
 17.1207 +  .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class))
 17.1208 +  .asVarargsCollector(Object[].class);
 17.1209 +MethodHandle asListFix = asListVar.asFixedArity();
 17.1210 +assertEquals("[1]", asListVar.invoke(1).toString());
 17.1211 +Exception caught = null;
 17.1212 +try { asListFix.invoke((Object)1); }
 17.1213 +catch (Exception ex) { caught = ex; }
 17.1214 +assert(caught instanceof ClassCastException);
 17.1215 +assertEquals("[two, too]", asListVar.invoke("two", "too").toString());
 17.1216 +try { asListFix.invoke("two", "too"); }
 17.1217 +catch (Exception ex) { caught = ex; }
 17.1218 +assert(caught instanceof WrongMethodTypeException);
 17.1219 +Object[] argv = { "three", "thee", "tee" };
 17.1220 +assertEquals("[three, thee, tee]", asListVar.invoke(argv).toString());
 17.1221 +assertEquals("[three, thee, tee]", asListFix.invoke(argv).toString());
 17.1222 +assertEquals(1, ((List) asListVar.invoke((Object)argv)).size());
 17.1223 +assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString());
 17.1224 +     * }</pre></blockquote>
 17.1225 +     *
 17.1226 +     * @return a new method handle which accepts only a fixed number of arguments
 17.1227 +     * @see #asVarargsCollector
 17.1228 +     * @see #isVarargsCollector
 17.1229 +     */
 17.1230 +    public MethodHandle asFixedArity() {
 17.1231 +        assert(!isVarargsCollector());
 17.1232 +        return this;
 17.1233 +    }
 17.1234 +
 17.1235 +    /**
 17.1236 +     * Binds a value {@code x} to the first argument of a method handle, without invoking it.
 17.1237 +     * The new method handle adapts, as its <i>target</i>,
 17.1238 +     * the current method handle by binding it to the given argument.
 17.1239 +     * The type of the bound handle will be
 17.1240 +     * the same as the type of the target, except that a single leading
 17.1241 +     * reference parameter will be omitted.
 17.1242 +     * <p>
 17.1243 +     * When called, the bound handle inserts the given value {@code x}
 17.1244 +     * as a new leading argument to the target.  The other arguments are
 17.1245 +     * also passed unchanged.
 17.1246 +     * What the target eventually returns is returned unchanged by the bound handle.
 17.1247 +     * <p>
 17.1248 +     * The reference {@code x} must be convertible to the first parameter
 17.1249 +     * type of the target.
 17.1250 +     * <p>
 17.1251 +     * (<em>Note:</em>  Because method handles are immutable, the target method handle
 17.1252 +     * retains its original type and behavior.)
 17.1253 +     * @param x  the value to bind to the first argument of the target
 17.1254 +     * @return a new method handle which prepends the given value to the incoming
 17.1255 +     *         argument list, before calling the original method handle
 17.1256 +     * @throws IllegalArgumentException if the target does not have a
 17.1257 +     *         leading parameter type that is a reference type
 17.1258 +     * @throws ClassCastException if {@code x} cannot be converted
 17.1259 +     *         to the leading parameter type of the target
 17.1260 +     * @see MethodHandles#insertArguments
 17.1261 +     */
 17.1262 +    public MethodHandle bindTo(Object x) {
 17.1263 +        Class<?> ptype;
 17.1264 +        @SuppressWarnings("LocalVariableHidesMemberVariable")
 17.1265 +        MethodType type = type();
 17.1266 +        if (type.parameterCount() == 0 ||
 17.1267 +            (ptype = type.parameterType(0)).isPrimitive())
 17.1268 +            throw newIllegalArgumentException("no leading reference parameter", x);
 17.1269 +        x = ptype.cast(x);  // throw CCE if needed
 17.1270 +        return bindReceiver(x);
 17.1271 +    }
 17.1272 +
 17.1273 +    /**
 17.1274 +     * Returns a string representation of the method handle,
 17.1275 +     * starting with the string {@code "MethodHandle"} and
 17.1276 +     * ending with the string representation of the method handle's type.
 17.1277 +     * In other words, this method returns a string equal to the value of:
 17.1278 +     * <blockquote><pre>{@code
 17.1279 +     * "MethodHandle" + type().toString()
 17.1280 +     * }</pre></blockquote>
 17.1281 +     * <p>
 17.1282 +     * (<em>Note:</em>  Future releases of this API may add further information
 17.1283 +     * to the string representation.
 17.1284 +     * Therefore, the present syntax should not be parsed by applications.)
 17.1285 +     *
 17.1286 +     * @return a string representation of the method handle
 17.1287 +     */
 17.1288 +    @Override
 17.1289 +    public String toString() {
 17.1290 +        if (DEBUG_METHOD_HANDLE_NAMES)  return debugString();
 17.1291 +        return standardString();
 17.1292 +    }
 17.1293 +    String standardString() {
 17.1294 +        return "MethodHandle"+type;
 17.1295 +    }
 17.1296 +    String debugString() {
 17.1297 +        return standardString()+"/LF="+internalForm()+internalProperties();
 17.1298 +    }
 17.1299 +
 17.1300 +    //// Implementation methods.
 17.1301 +    //// Sub-classes can override these default implementations.
 17.1302 +    //// All these methods assume arguments are already validated.
 17.1303 +
 17.1304 +    // Other transforms to do:  convert, explicitCast, permute, drop, filter, fold, GWT, catch
 17.1305 +
 17.1306 +    /*non-public*/
 17.1307 +    MethodHandle setVarargs(MemberName member) throws IllegalAccessException {
 17.1308 +        if (!member.isVarargs())  return this;
 17.1309 +        int argc = type().parameterCount();
 17.1310 +        if (argc != 0) {
 17.1311 +            Class<?> arrayType = type().parameterType(argc-1);
 17.1312 +            if (arrayType.isArray()) {
 17.1313 +                return MethodHandleImpl.makeVarargsCollector(this, arrayType);
 17.1314 +            }
 17.1315 +        }
 17.1316 +        throw member.makeAccessException("cannot make variable arity", null);
 17.1317 +    }
 17.1318 +    /*non-public*/
 17.1319 +    MethodHandle viewAsType(MethodType newType) {
 17.1320 +        // No actual conversions, just a new view of the same method.
 17.1321 +        return MethodHandleImpl.makePairwiseConvert(this, newType, 0);
 17.1322 +    }
 17.1323 +
 17.1324 +    // Decoding
 17.1325 +
 17.1326 +    /*non-public*/
 17.1327 +    LambdaForm internalForm() {
 17.1328 +        return form;
 17.1329 +    }
 17.1330 +
 17.1331 +    /*non-public*/
 17.1332 +    MemberName internalMemberName() {
 17.1333 +        return null;  // DMH returns DMH.member
 17.1334 +    }
 17.1335 +
 17.1336 +    /*non-public*/
 17.1337 +    Class<?> internalCallerClass() {
 17.1338 +        return null;  // caller-bound MH for @CallerSensitive method returns caller
 17.1339 +    }
 17.1340 +
 17.1341 +    /*non-public*/
 17.1342 +    MethodHandle withInternalMemberName(MemberName member) {
 17.1343 +        if (member != null) {
 17.1344 +            return MethodHandleImpl.makeWrappedMember(this, member);
 17.1345 +        } else if (internalMemberName() == null) {
 17.1346 +            // The required internaMemberName is null, and this MH (like most) doesn't have one.
 17.1347 +            return this;
 17.1348 +        } else {
 17.1349 +            // The following case is rare. Mask the internalMemberName by wrapping the MH in a BMH.
 17.1350 +            MethodHandle result = rebind();
 17.1351 +            assert (result.internalMemberName() == null);
 17.1352 +            return result;
 17.1353 +        }
 17.1354 +    }
 17.1355 +
 17.1356 +    /*non-public*/
 17.1357 +    boolean isInvokeSpecial() {
 17.1358 +        return false;  // DMH.Special returns true
 17.1359 +    }
 17.1360 +
 17.1361 +    /*non-public*/
 17.1362 +    Object internalValues() {
 17.1363 +        return null;
 17.1364 +    }
 17.1365 +
 17.1366 +    /*non-public*/
 17.1367 +    Object internalProperties() {
 17.1368 +        // Override to something like "/FOO=bar"
 17.1369 +        return "";
 17.1370 +    }
 17.1371 +
 17.1372 +    //// Method handle implementation methods.
 17.1373 +    //// Sub-classes can override these default implementations.
 17.1374 +    //// All these methods assume arguments are already validated.
 17.1375 +
 17.1376 +    /*non-public*/ MethodHandle convertArguments(MethodType newType) {
 17.1377 +        // Override this if it can be improved.
 17.1378 +        return MethodHandleImpl.makePairwiseConvert(this, newType, 1);
 17.1379 +    }
 17.1380 +
 17.1381 +    /*non-public*/
 17.1382 +    MethodHandle bindArgument(int pos, char basicType, Object value) {
 17.1383 +        // Override this if it can be improved.
 17.1384 +        return rebind().bindArgument(pos, basicType, value);
 17.1385 +    }
 17.1386 +
 17.1387 +    /*non-public*/
 17.1388 +    MethodHandle bindReceiver(Object receiver) {
 17.1389 +        // Override this if it can be improved.
 17.1390 +        return bindArgument(0, 'L', receiver);
 17.1391 +    }
 17.1392 +
 17.1393 +    /*non-public*/
 17.1394 +    MethodHandle bindImmediate(int pos, char basicType, Object value) {
 17.1395 +        // Bind an immediate value to a position in the arguments.
 17.1396 +        // This means, elide the respective argument,
 17.1397 +        // and replace all references to it in NamedFunction args with the specified value.
 17.1398 +
 17.1399 +        // CURRENT RESTRICTIONS
 17.1400 +        // * only for pos 0 and UNSAFE (position is adjusted in MHImpl to make API usable for others)
 17.1401 +        assert pos == 0 && basicType == 'L' && value instanceof Unsafe;
 17.1402 +        MethodType type2 = type.dropParameterTypes(pos, pos + 1); // adjustment: ignore receiver!
 17.1403 +        LambdaForm form2 = form.bindImmediate(pos + 1, basicType, value); // adjust pos to form-relative pos
 17.1404 +        return copyWith(type2, form2);
 17.1405 +    }
 17.1406 +
 17.1407 +    /*non-public*/
 17.1408 +    MethodHandle copyWith(MethodType mt, LambdaForm lf) {
 17.1409 +        throw new InternalError("copyWith: " + this.getClass());
 17.1410 +    }
 17.1411 +
 17.1412 +    /*non-public*/
 17.1413 +    MethodHandle dropArguments(MethodType srcType, int pos, int drops) {
 17.1414 +        // Override this if it can be improved.
 17.1415 +        return rebind().dropArguments(srcType, pos, drops);
 17.1416 +    }
 17.1417 +
 17.1418 +    /*non-public*/
 17.1419 +    MethodHandle permuteArguments(MethodType newType, int[] reorder) {
 17.1420 +        // Override this if it can be improved.
 17.1421 +        return rebind().permuteArguments(newType, reorder);
 17.1422 +    }
 17.1423 +
 17.1424 +    /*non-public*/
 17.1425 +    MethodHandle rebind() {
 17.1426 +        // Bind 'this' into a new invoker, of the known class BMH.
 17.1427 +        MethodType type2 = type();
 17.1428 +        LambdaForm form2 = reinvokerForm(this);
 17.1429 +        // form2 = lambda (bmh, arg*) { thismh = bmh[0]; invokeBasic(thismh, arg*) }
 17.1430 +        return BoundMethodHandle.bindSingle(type2, form2, this);
 17.1431 +    }
 17.1432 +
 17.1433 +    /*non-public*/
 17.1434 +    MethodHandle reinvokerTarget() {
 17.1435 +        throw new InternalError("not a reinvoker MH: "+this.getClass().getName()+": "+this);
 17.1436 +    }
 17.1437 +
 17.1438 +    /** Create a LF which simply reinvokes a target of the given basic type.
 17.1439 +     *  The target MH must override {@link #reinvokerTarget} to provide the target.
 17.1440 +     */
 17.1441 +    static LambdaForm reinvokerForm(MethodHandle target) {
 17.1442 +        MethodType mtype = target.type().basicType();
 17.1443 +        LambdaForm reinvoker = mtype.form().cachedLambdaForm(MethodTypeForm.LF_REINVOKE);
 17.1444 +        if (reinvoker != null)  return reinvoker;
 17.1445 +        if (mtype.parameterSlotCount() >= MethodType.MAX_MH_ARITY)
 17.1446 +            return makeReinvokerForm(target.type(), target);  // cannot cache this
 17.1447 +        reinvoker = makeReinvokerForm(mtype, null);
 17.1448 +        return mtype.form().setCachedLambdaForm(MethodTypeForm.LF_REINVOKE, reinvoker);
 17.1449 +    }
 17.1450 +    private static LambdaForm makeReinvokerForm(MethodType mtype, MethodHandle customTargetOrNull) {
 17.1451 +        boolean customized = (customTargetOrNull != null);
 17.1452 +        MethodHandle MH_invokeBasic = customized ? null : MethodHandles.basicInvoker(mtype);
 17.1453 +        final int THIS_BMH    = 0;
 17.1454 +        final int ARG_BASE    = 1;
 17.1455 +        final int ARG_LIMIT   = ARG_BASE + mtype.parameterCount();
 17.1456 +        int nameCursor = ARG_LIMIT;
 17.1457 +        final int NEXT_MH     = customized ? -1 : nameCursor++;
 17.1458 +        final int REINVOKE    = nameCursor++;
 17.1459 +        LambdaForm.Name[] names = LambdaForm.arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
 17.1460 +        Object[] targetArgs;
 17.1461 +        MethodHandle targetMH;
 17.1462 +        if (customized) {
 17.1463 +            targetArgs = Arrays.copyOfRange(names, ARG_BASE, ARG_LIMIT, Object[].class);
 17.1464 +            targetMH = customTargetOrNull;
 17.1465 +        } else {
 17.1466 +            names[NEXT_MH] = new LambdaForm.Name(NF_reinvokerTarget, names[THIS_BMH]);
 17.1467 +            targetArgs = Arrays.copyOfRange(names, THIS_BMH, ARG_LIMIT, Object[].class);
 17.1468 +            targetArgs[0] = names[NEXT_MH];  // overwrite this MH with next MH
 17.1469 +            targetMH = MethodHandles.basicInvoker(mtype);
 17.1470 +        }
 17.1471 +        names[REINVOKE] = new LambdaForm.Name(targetMH, targetArgs);
 17.1472 +        return new LambdaForm("BMH.reinvoke", ARG_LIMIT, names);
 17.1473 +    }
 17.1474 +
 17.1475 +    private static final LambdaForm.NamedFunction NF_reinvokerTarget;
 17.1476 +    static {
 17.1477 +        try {
 17.1478 +            NF_reinvokerTarget = new LambdaForm.NamedFunction(MethodHandle.class
 17.1479 +                .getDeclaredMethod("reinvokerTarget"));
 17.1480 +        } catch (ReflectiveOperationException ex) {
 17.1481 +            throw newInternalError(ex);
 17.1482 +        }
 17.1483 +    }
 17.1484 +
 17.1485 +    /**
 17.1486 +     * Replace the old lambda form of this method handle with a new one.
 17.1487 +     * The new one must be functionally equivalent to the old one.
 17.1488 +     * Threads may continue running the old form indefinitely,
 17.1489 +     * but it is likely that the new one will be preferred for new executions.
 17.1490 +     * Use with discretion.
 17.1491 +     */
 17.1492 +    /*non-public*/
 17.1493 +    void updateForm(LambdaForm newForm) {
 17.1494 +        if (form == newForm)  return;
 17.1495 +        // ISSUE: Should we have a memory fence here?
 17.1496 +        UNSAFE.putObject(this, FORM_OFFSET, newForm);
 17.1497 +        this.form.prepare();  // as in MethodHandle.<init>
 17.1498 +    }
 17.1499 +
 17.1500 +    private static final long FORM_OFFSET;
 17.1501 +    static {
 17.1502 +        try {
 17.1503 +            FORM_OFFSET = UNSAFE.objectFieldOffset(MethodHandle.class.getDeclaredField("form"));
 17.1504 +        } catch (ReflectiveOperationException ex) {
 17.1505 +            throw newInternalError(ex);
 17.1506 +        }
 17.1507 +    }
 17.1508 +}
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/MethodHandleImpl.java	Sat Aug 09 11:12:05 2014 +0200
    18.3 @@ -0,0 +1,1013 @@
    18.4 +/*
    18.5 + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
    18.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    18.7 + *
    18.8 + * This code is free software; you can redistribute it and/or modify it
    18.9 + * under the terms of the GNU General Public License version 2 only, as
   18.10 + * published by the Free Software Foundation.  Oracle designates this
   18.11 + * particular file as subject to the "Classpath" exception as provided
   18.12 + * by Oracle in the LICENSE file that accompanied this code.
   18.13 + *
   18.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   18.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   18.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   18.17 + * version 2 for more details (a copy is included in the LICENSE file that
   18.18 + * accompanied this code).
   18.19 + *
   18.20 + * You should have received a copy of the GNU General Public License version
   18.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   18.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   18.23 + *
   18.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   18.25 + * or visit www.oracle.com if you need additional information or have any
   18.26 + * questions.
   18.27 + */
   18.28 +
   18.29 +package java.lang.invoke;
   18.30 +
   18.31 +import java.security.AccessController;
   18.32 +import java.security.PrivilegedAction;
   18.33 +import java.util.ArrayList;
   18.34 +import java.util.Arrays;
   18.35 +import java.util.HashMap;
   18.36 +import sun.invoke.empty.Empty;
   18.37 +import sun.invoke.util.ValueConversions;
   18.38 +import sun.invoke.util.VerifyType;
   18.39 +import sun.invoke.util.Wrapper;
   18.40 +import sun.reflect.CallerSensitive;
   18.41 +import sun.reflect.Reflection;
   18.42 +import static java.lang.invoke.LambdaForm.*;
   18.43 +import static java.lang.invoke.MethodHandleStatics.*;
   18.44 +import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
   18.45 +
   18.46 +/**
   18.47 + * Trusted implementation code for MethodHandle.
   18.48 + * @author jrose
   18.49 + */
   18.50 +/*non-public*/ abstract class MethodHandleImpl {
   18.51 +    /// Factory methods to create method handles:
   18.52 +
   18.53 +    static void initStatics() {
   18.54 +        // Trigger selected static initializations.
   18.55 +        MemberName.Factory.INSTANCE.getClass();
   18.56 +    }
   18.57 +
   18.58 +    static MethodHandle makeArrayElementAccessor(Class<?> arrayClass, boolean isSetter) {
   18.59 +        if (!arrayClass.isArray())
   18.60 +            throw newIllegalArgumentException("not an array: "+arrayClass);
   18.61 +        MethodHandle accessor = ArrayAccessor.getAccessor(arrayClass, isSetter);
   18.62 +        MethodType srcType = accessor.type().erase();
   18.63 +        MethodType lambdaType = srcType.invokerType();
   18.64 +        Name[] names = arguments(1, lambdaType);
   18.65 +        Name[] args  = Arrays.copyOfRange(names, 1, 1 + srcType.parameterCount());
   18.66 +        names[names.length - 1] = new Name(accessor.asType(srcType), (Object[]) args);
   18.67 +        LambdaForm form = new LambdaForm("getElement", lambdaType.parameterCount(), names);
   18.68 +        MethodHandle mh = SimpleMethodHandle.make(srcType, form);
   18.69 +        if (ArrayAccessor.needCast(arrayClass)) {
   18.70 +            mh = mh.bindTo(arrayClass);
   18.71 +        }
   18.72 +        mh = mh.asType(ArrayAccessor.correctType(arrayClass, isSetter));
   18.73 +        return mh;
   18.74 +    }
   18.75 +
   18.76 +    static final class ArrayAccessor {
   18.77 +        /// Support for array element access
   18.78 +        static final HashMap<Class<?>, MethodHandle> GETTER_CACHE = new HashMap<>();  // TODO use it
   18.79 +        static final HashMap<Class<?>, MethodHandle> SETTER_CACHE = new HashMap<>();  // TODO use it
   18.80 +
   18.81 +        static int     getElementI(int[]     a, int i)            { return              a[i]; }
   18.82 +        static long    getElementJ(long[]    a, int i)            { return              a[i]; }
   18.83 +        static float   getElementF(float[]   a, int i)            { return              a[i]; }
   18.84 +        static double  getElementD(double[]  a, int i)            { return              a[i]; }
   18.85 +        static boolean getElementZ(boolean[] a, int i)            { return              a[i]; }
   18.86 +        static byte    getElementB(byte[]    a, int i)            { return              a[i]; }
   18.87 +        static short   getElementS(short[]   a, int i)            { return              a[i]; }
   18.88 +        static char    getElementC(char[]    a, int i)            { return              a[i]; }
   18.89 +        static Object  getElementL(Object[]  a, int i)            { return              a[i]; }
   18.90 +
   18.91 +        static void    setElementI(int[]     a, int i, int     x) {              a[i] = x; }
   18.92 +        static void    setElementJ(long[]    a, int i, long    x) {              a[i] = x; }
   18.93 +        static void    setElementF(float[]   a, int i, float   x) {              a[i] = x; }
   18.94 +        static void    setElementD(double[]  a, int i, double  x) {              a[i] = x; }
   18.95 +        static void    setElementZ(boolean[] a, int i, boolean x) {              a[i] = x; }
   18.96 +        static void    setElementB(byte[]    a, int i, byte    x) {              a[i] = x; }
   18.97 +        static void    setElementS(short[]   a, int i, short   x) {              a[i] = x; }
   18.98 +        static void    setElementC(char[]    a, int i, char    x) {              a[i] = x; }
   18.99 +        static void    setElementL(Object[]  a, int i, Object  x) {              a[i] = x; }
  18.100 +
  18.101 +        static Object  getElementL(Class<?> arrayClass, Object[] a, int i)           { arrayClass.cast(a); return a[i]; }
  18.102 +        static void    setElementL(Class<?> arrayClass, Object[] a, int i, Object x) { arrayClass.cast(a); a[i] = x; }
  18.103 +
  18.104 +        // Weakly typed wrappers of Object[] accessors:
  18.105 +        static Object  getElementL(Object    a, int i)            { return getElementL((Object[])a, i); }
  18.106 +        static void    setElementL(Object    a, int i, Object  x) {        setElementL((Object[]) a, i, x); }
  18.107 +        static Object  getElementL(Object   arrayClass, Object a, int i)             { return getElementL((Class<?>) arrayClass, (Object[])a, i); }
  18.108 +        static void    setElementL(Object   arrayClass, Object a, int i, Object x)   {        setElementL((Class<?>) arrayClass, (Object[])a, i, x); }
  18.109 +
  18.110 +        static boolean needCast(Class<?> arrayClass) {
  18.111 +            Class<?> elemClass = arrayClass.getComponentType();
  18.112 +            return !elemClass.isPrimitive() && elemClass != Object.class;
  18.113 +        }
  18.114 +        static String name(Class<?> arrayClass, boolean isSetter) {
  18.115 +            Class<?> elemClass = arrayClass.getComponentType();
  18.116 +            if (elemClass == null)  throw new IllegalArgumentException();
  18.117 +            return (!isSetter ? "getElement" : "setElement") + Wrapper.basicTypeChar(elemClass);
  18.118 +        }
  18.119 +        static final boolean USE_WEAKLY_TYPED_ARRAY_ACCESSORS = false;  // FIXME: decide
  18.120 +        static MethodType type(Class<?> arrayClass, boolean isSetter) {
  18.121 +            Class<?> elemClass = arrayClass.getComponentType();
  18.122 +            Class<?> arrayArgClass = arrayClass;
  18.123 +            if (!elemClass.isPrimitive()) {
  18.124 +                arrayArgClass = Object[].class;
  18.125 +                if (USE_WEAKLY_TYPED_ARRAY_ACCESSORS)
  18.126 +                    arrayArgClass = Object.class;
  18.127 +            }
  18.128 +            if (!needCast(arrayClass)) {
  18.129 +                return !isSetter ?
  18.130 +                    MethodType.methodType(elemClass,  arrayArgClass, int.class) :
  18.131 +                    MethodType.methodType(void.class, arrayArgClass, int.class, elemClass);
  18.132 +            } else {
  18.133 +                Class<?> classArgClass = Class.class;
  18.134 +                if (USE_WEAKLY_TYPED_ARRAY_ACCESSORS)
  18.135 +                    classArgClass = Object.class;
  18.136 +                return !isSetter ?
  18.137 +                    MethodType.methodType(Object.class, classArgClass, arrayArgClass, int.class) :
  18.138 +                    MethodType.methodType(void.class,   classArgClass, arrayArgClass, int.class, Object.class);
  18.139 +            }
  18.140 +        }
  18.141 +        static MethodType correctType(Class<?> arrayClass, boolean isSetter) {
  18.142 +            Class<?> elemClass = arrayClass.getComponentType();
  18.143 +            return !isSetter ?
  18.144 +                    MethodType.methodType(elemClass,  arrayClass, int.class) :
  18.145 +                    MethodType.methodType(void.class, arrayClass, int.class, elemClass);
  18.146 +        }
  18.147 +        static MethodHandle getAccessor(Class<?> arrayClass, boolean isSetter) {
  18.148 +            String     name = name(arrayClass, isSetter);
  18.149 +            MethodType type = type(arrayClass, isSetter);
  18.150 +            try {
  18.151 +                return IMPL_LOOKUP.findStatic(ArrayAccessor.class, name, type);
  18.152 +            } catch (ReflectiveOperationException ex) {
  18.153 +                throw uncaughtException(ex);
  18.154 +            }
  18.155 +        }
  18.156 +    }
  18.157 +
  18.158 +    /**
  18.159 +     * Create a JVM-level adapter method handle to conform the given method
  18.160 +     * handle to the similar newType, using only pairwise argument conversions.
  18.161 +     * For each argument, convert incoming argument to the exact type needed.
  18.162 +     * The argument conversions allowed are casting, boxing and unboxing,
  18.163 +     * integral widening or narrowing, and floating point widening or narrowing.
  18.164 +     * @param srcType required call type
  18.165 +     * @param target original method handle
  18.166 +     * @param level which strength of conversion is allowed
  18.167 +     * @return an adapter to the original handle with the desired new type,
  18.168 +     *          or the original target if the types are already identical
  18.169 +     *          or null if the adaptation cannot be made
  18.170 +     */
  18.171 +    static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType, int level) {
  18.172 +        assert(level >= 0 && level <= 2);
  18.173 +        MethodType dstType = target.type();
  18.174 +        assert(dstType.parameterCount() == target.type().parameterCount());
  18.175 +        if (srcType == dstType)
  18.176 +            return target;
  18.177 +
  18.178 +        // Calculate extra arguments (temporaries) required in the names array.
  18.179 +        // FIXME: Use an ArrayList<Name>.  Some arguments require more than one conversion step.
  18.180 +        final int INARG_COUNT = srcType.parameterCount();
  18.181 +        int conversions = 0;
  18.182 +        boolean[] needConv = new boolean[1+INARG_COUNT];
  18.183 +        for (int i = 0; i <= INARG_COUNT; i++) {
  18.184 +            Class<?> src = (i == INARG_COUNT) ? dstType.returnType() : srcType.parameterType(i);
  18.185 +            Class<?> dst = (i == INARG_COUNT) ? srcType.returnType() : dstType.parameterType(i);
  18.186 +            if (!VerifyType.isNullConversion(src, dst) ||
  18.187 +                level <= 1 && dst.isInterface() && !dst.isAssignableFrom(src)) {
  18.188 +                needConv[i] = true;
  18.189 +                conversions++;
  18.190 +            }
  18.191 +        }
  18.192 +        boolean retConv = needConv[INARG_COUNT];
  18.193 +
  18.194 +        final int IN_MH         = 0;
  18.195 +        final int INARG_BASE    = 1;
  18.196 +        final int INARG_LIMIT   = INARG_BASE + INARG_COUNT;
  18.197 +        final int NAME_LIMIT    = INARG_LIMIT + conversions + 1;
  18.198 +        final int RETURN_CONV   = (!retConv ? -1         : NAME_LIMIT - 1);
  18.199 +        final int OUT_CALL      = (!retConv ? NAME_LIMIT : RETURN_CONV) - 1;
  18.200 +
  18.201 +        // Now build a LambdaForm.
  18.202 +        MethodType lambdaType = srcType.basicType().invokerType();
  18.203 +        Name[] names = arguments(NAME_LIMIT - INARG_LIMIT, lambdaType);
  18.204 +
  18.205 +        // Collect the arguments to the outgoing call, maybe with conversions:
  18.206 +        final int OUTARG_BASE = 0;  // target MH is Name.function, name Name.arguments[0]
  18.207 +        Object[] outArgs = new Object[OUTARG_BASE + INARG_COUNT];
  18.208 +
  18.209 +        int nameCursor = INARG_LIMIT;
  18.210 +        for (int i = 0; i < INARG_COUNT; i++) {
  18.211 +            Class<?> src = srcType.parameterType(i);
  18.212 +            Class<?> dst = dstType.parameterType(i);
  18.213 +
  18.214 +            if (!needConv[i]) {
  18.215 +                // do nothing: difference is trivial
  18.216 +                outArgs[OUTARG_BASE + i] = names[INARG_BASE + i];
  18.217 +                continue;
  18.218 +            }
  18.219 +
  18.220 +            // Tricky case analysis follows.
  18.221 +            MethodHandle fn = null;
  18.222 +            if (src.isPrimitive()) {
  18.223 +                if (dst.isPrimitive()) {
  18.224 +                    fn = ValueConversions.convertPrimitive(src, dst);
  18.225 +                } else {
  18.226 +                    Wrapper w = Wrapper.forPrimitiveType(src);
  18.227 +                    MethodHandle boxMethod = ValueConversions.box(w);
  18.228 +                    if (dst == w.wrapperType())
  18.229 +                        fn = boxMethod;
  18.230 +                    else
  18.231 +                        fn = boxMethod.asType(MethodType.methodType(dst, src));
  18.232 +                }
  18.233 +            } else {
  18.234 +                if (dst.isPrimitive()) {
  18.235 +                    // Caller has boxed a primitive.  Unbox it for the target.
  18.236 +                    Wrapper w = Wrapper.forPrimitiveType(dst);
  18.237 +                    if (level == 0 || VerifyType.isNullConversion(src, w.wrapperType())) {
  18.238 +                        fn = ValueConversions.unbox(dst);
  18.239 +                    } else if (src == Object.class || !Wrapper.isWrapperType(src)) {
  18.240 +                        // Examples:  Object->int, Number->int, Comparable->int; Byte->int, Character->int
  18.241 +                        // must include additional conversions
  18.242 +                        // src must be examined at runtime, to detect Byte, Character, etc.
  18.243 +                        MethodHandle unboxMethod = (level == 1
  18.244 +                                                    ? ValueConversions.unbox(dst)
  18.245 +                                                    : ValueConversions.unboxCast(dst));
  18.246 +                        fn = unboxMethod;
  18.247 +                    } else {
  18.248 +                        // Example: Byte->int
  18.249 +                        // Do this by reformulating the problem to Byte->byte.
  18.250 +                        Class<?> srcPrim = Wrapper.forWrapperType(src).primitiveType();
  18.251 +                        MethodHandle unbox = ValueConversions.unbox(srcPrim);
  18.252 +                        // Compose the two conversions.  FIXME:  should make two Names for this job
  18.253 +                        fn = unbox.asType(MethodType.methodType(dst, src));
  18.254 +                    }
  18.255 +                } else {
  18.256 +                    // Simple reference conversion.
  18.257 +                    // Note:  Do not check for a class hierarchy relation
  18.258 +                    // between src and dst.  In all cases a 'null' argument
  18.259 +                    // will pass the cast conversion.
  18.260 +                    fn = ValueConversions.cast(dst);
  18.261 +                }
  18.262 +            }
  18.263 +            Name conv = new Name(fn, names[INARG_BASE + i]);
  18.264 +            assert(names[nameCursor] == null);
  18.265 +            names[nameCursor++] = conv;
  18.266 +            assert(outArgs[OUTARG_BASE + i] == null);
  18.267 +            outArgs[OUTARG_BASE + i] = conv;
  18.268 +        }
  18.269 +
  18.270 +        // Build argument array for the call.
  18.271 +        assert(nameCursor == OUT_CALL);
  18.272 +        names[OUT_CALL] = new Name(target, outArgs);
  18.273 +
  18.274 +        if (RETURN_CONV < 0) {
  18.275 +            assert(OUT_CALL == names.length-1);
  18.276 +        } else {
  18.277 +            Class<?> needReturn = srcType.returnType();
  18.278 +            Class<?> haveReturn = dstType.returnType();
  18.279 +            MethodHandle fn;
  18.280 +            Object[] arg = { names[OUT_CALL] };
  18.281 +            if (haveReturn == void.class) {
  18.282 +                // synthesize a zero value for the given void
  18.283 +                Object zero = Wrapper.forBasicType(needReturn).zero();
  18.284 +                fn = MethodHandles.constant(needReturn, zero);
  18.285 +                arg = new Object[0];  // don't pass names[OUT_CALL] to conversion
  18.286 +            } else {
  18.287 +                MethodHandle identity = MethodHandles.identity(needReturn);
  18.288 +                MethodType needConversion = identity.type().changeParameterType(0, haveReturn);
  18.289 +                fn = makePairwiseConvert(identity, needConversion, level);
  18.290 +            }
  18.291 +            assert(names[RETURN_CONV] == null);
  18.292 +            names[RETURN_CONV] = new Name(fn, arg);
  18.293 +            assert(RETURN_CONV == names.length-1);
  18.294 +        }
  18.295 +
  18.296 +        LambdaForm form = new LambdaForm("convert", lambdaType.parameterCount(), names);
  18.297 +        return SimpleMethodHandle.make(srcType, form);
  18.298 +    }
  18.299 +
  18.300 +    static MethodHandle makeReferenceIdentity(Class<?> refType) {
  18.301 +        MethodType lambdaType = MethodType.genericMethodType(1).invokerType();
  18.302 +        Name[] names = arguments(1, lambdaType);
  18.303 +        names[names.length - 1] = new Name(ValueConversions.identity(), names[1]);
  18.304 +        LambdaForm form = new LambdaForm("identity", lambdaType.parameterCount(), names);
  18.305 +        return SimpleMethodHandle.make(MethodType.methodType(refType, refType), form);
  18.306 +    }
  18.307 +
  18.308 +    static MethodHandle makeVarargsCollector(MethodHandle target, Class<?> arrayType) {
  18.309 +        MethodType type = target.type();
  18.310 +        int last = type.parameterCount() - 1;
  18.311 +        if (type.parameterType(last) != arrayType)
  18.312 +            target = target.asType(type.changeParameterType(last, arrayType));
  18.313 +        target = target.asFixedArity();  // make sure this attribute is turned off
  18.314 +        return new AsVarargsCollector(target, target.type(), arrayType);
  18.315 +    }
  18.316 +
  18.317 +    static class AsVarargsCollector extends MethodHandle {
  18.318 +        private final MethodHandle target;
  18.319 +        private final Class<?> arrayType;
  18.320 +        private /*@Stable*/ MethodHandle asCollectorCache;
  18.321 +
  18.322 +        AsVarargsCollector(MethodHandle target, MethodType type, Class<?> arrayType) {
  18.323 +            super(type, reinvokerForm(target));
  18.324 +            this.target = target;
  18.325 +            this.arrayType = arrayType;
  18.326 +            this.asCollectorCache = target.asCollector(arrayType, 0);
  18.327 +        }
  18.328 +
  18.329 +        @Override MethodHandle reinvokerTarget() { return target; }
  18.330 +
  18.331 +        @Override
  18.332 +        public boolean isVarargsCollector() {
  18.333 +            return true;
  18.334 +        }
  18.335 +
  18.336 +        @Override
  18.337 +        public MethodHandle asFixedArity() {
  18.338 +            return target;
  18.339 +        }
  18.340 +
  18.341 +        @Override
  18.342 +        public MethodHandle asTypeUncached(MethodType newType) {
  18.343 +            MethodType type = this.type();
  18.344 +            int collectArg = type.parameterCount() - 1;
  18.345 +            int newArity = newType.parameterCount();
  18.346 +            if (newArity == collectArg+1 &&
  18.347 +                type.parameterType(collectArg).isAssignableFrom(newType.parameterType(collectArg))) {
  18.348 +                // if arity and trailing parameter are compatible, do normal thing
  18.349 +                return asTypeCache = asFixedArity().asType(newType);
  18.350 +            }
  18.351 +            // check cache
  18.352 +            MethodHandle acc = asCollectorCache;
  18.353 +            if (acc != null && acc.type().parameterCount() == newArity)
  18.354 +                return asTypeCache = acc.asType(newType);
  18.355 +            // build and cache a collector
  18.356 +            int arrayLength = newArity - collectArg;
  18.357 +            MethodHandle collector;
  18.358 +            try {
  18.359 +                collector = asFixedArity().asCollector(arrayType, arrayLength);
  18.360 +                assert(collector.type().parameterCount() == newArity) : "newArity="+newArity+" but collector="+collector;
  18.361 +            } catch (IllegalArgumentException ex) {
  18.362 +                throw new WrongMethodTypeException("cannot build collector", ex);
  18.363 +            }
  18.364 +            asCollectorCache = collector;
  18.365 +            return asTypeCache = collector.asType(newType);
  18.366 +        }
  18.367 +
  18.368 +        @Override
  18.369 +        MethodHandle setVarargs(MemberName member) {
  18.370 +            if (member.isVarargs())  return this;
  18.371 +            return asFixedArity();
  18.372 +        }
  18.373 +
  18.374 +        @Override
  18.375 +        MethodHandle viewAsType(MethodType newType) {
  18.376 +            if (newType.lastParameterType() != type().lastParameterType())
  18.377 +                throw new InternalError();
  18.378 +            MethodHandle newTarget = asFixedArity().viewAsType(newType);
  18.379 +            // put back the varargs bit:
  18.380 +            return new AsVarargsCollector(newTarget, newType, arrayType);
  18.381 +        }
  18.382 +
  18.383 +        @Override
  18.384 +        MemberName internalMemberName() {
  18.385 +            return asFixedArity().internalMemberName();
  18.386 +        }
  18.387 +        @Override
  18.388 +        Class<?> internalCallerClass() {
  18.389 +            return asFixedArity().internalCallerClass();
  18.390 +        }
  18.391 +
  18.392 +        /*non-public*/
  18.393 +        @Override
  18.394 +        boolean isInvokeSpecial() {
  18.395 +            return asFixedArity().isInvokeSpecial();
  18.396 +        }
  18.397 +
  18.398 +
  18.399 +        @Override
  18.400 +        MethodHandle bindArgument(int pos, char basicType, Object value) {
  18.401 +            return asFixedArity().bindArgument(pos, basicType, value);
  18.402 +        }
  18.403 +
  18.404 +        @Override
  18.405 +        MethodHandle bindReceiver(Object receiver) {
  18.406 +            return asFixedArity().bindReceiver(receiver);
  18.407 +        }
  18.408 +
  18.409 +        @Override
  18.410 +        MethodHandle dropArguments(MethodType srcType, int pos, int drops) {
  18.411 +            return asFixedArity().dropArguments(srcType, pos, drops);
  18.412 +        }
  18.413 +
  18.414 +        @Override
  18.415 +        MethodHandle permuteArguments(MethodType newType, int[] reorder) {
  18.416 +            return asFixedArity().permuteArguments(newType, reorder);
  18.417 +        }
  18.418 +    }
  18.419 +
  18.420 +    /** Factory method:  Spread selected argument. */
  18.421 +    static MethodHandle makeSpreadArguments(MethodHandle target,
  18.422 +                                            Class<?> spreadArgType, int spreadArgPos, int spreadArgCount) {
  18.423 +        MethodType targetType = target.type();
  18.424 +
  18.425 +        for (int i = 0; i < spreadArgCount; i++) {
  18.426 +            Class<?> arg = VerifyType.spreadArgElementType(spreadArgType, i);
  18.427 +            if (arg == null)  arg = Object.class;
  18.428 +            targetType = targetType.changeParameterType(spreadArgPos + i, arg);
  18.429 +        }
  18.430 +        target = target.asType(targetType);
  18.431 +
  18.432 +        MethodType srcType = targetType
  18.433 +                .replaceParameterTypes(spreadArgPos, spreadArgPos + spreadArgCount, spreadArgType);
  18.434 +        // Now build a LambdaForm.
  18.435 +        MethodType lambdaType = srcType.invokerType();
  18.436 +        Name[] names = arguments(spreadArgCount + 2, lambdaType);
  18.437 +        int nameCursor = lambdaType.parameterCount();
  18.438 +        int[] indexes = new int[targetType.parameterCount()];
  18.439 +
  18.440 +        for (int i = 0, argIndex = 1; i < targetType.parameterCount() + 1; i++, argIndex++) {
  18.441 +            Class<?> src = lambdaType.parameterType(i);
  18.442 +            if (i == spreadArgPos) {
  18.443 +                // Spread the array.
  18.444 +                MethodHandle aload = MethodHandles.arrayElementGetter(spreadArgType);
  18.445 +                Name array = names[argIndex];
  18.446 +                names[nameCursor++] = new Name(Lazy.NF_checkSpreadArgument, array, spreadArgCount);
  18.447 +                for (int j = 0; j < spreadArgCount; i++, j++) {
  18.448 +                    indexes[i] = nameCursor;
  18.449 +                    names[nameCursor++] = new Name(aload, array, j);
  18.450 +                }
  18.451 +            } else if (i < indexes.length) {
  18.452 +                indexes[i] = argIndex;
  18.453 +            }
  18.454 +        }
  18.455 +        assert(nameCursor == names.length-1);  // leave room for the final call
  18.456 +
  18.457 +        // Build argument array for the call.
  18.458 +        Name[] targetArgs = new Name[targetType.parameterCount()];
  18.459 +        for (int i = 0; i < targetType.parameterCount(); i++) {
  18.460 +            int idx = indexes[i];
  18.461 +            targetArgs[i] = names[idx];
  18.462 +        }
  18.463 +        names[names.length - 1] = new Name(target, (Object[]) targetArgs);
  18.464 +
  18.465 +        LambdaForm form = new LambdaForm("spread", lambdaType.parameterCount(), names);
  18.466 +        return SimpleMethodHandle.make(srcType, form);
  18.467 +    }
  18.468 +
  18.469 +    static void checkSpreadArgument(Object av, int n) {
  18.470 +        if (av == null) {
  18.471 +            if (n == 0)  return;
  18.472 +        } else if (av instanceof Object[]) {
  18.473 +            int len = ((Object[])av).length;
  18.474 +            if (len == n)  return;
  18.475 +        } else {
  18.476 +            int len = java.lang.reflect.Array.getLength(av);
  18.477 +            if (len == n)  return;
  18.478 +        }
  18.479 +        // fall through to error:
  18.480 +        throw newIllegalArgumentException("array is not of length "+n);
  18.481 +    }
  18.482 +
  18.483 +    /**
  18.484 +     * Pre-initialized NamedFunctions for bootstrapping purposes.
  18.485 +     * Factored in an inner class to delay initialization until first usage.
  18.486 +     */
  18.487 +    private static class Lazy {
  18.488 +        static final NamedFunction NF_checkSpreadArgument;
  18.489 +        static {
  18.490 +            try {
  18.491 +                NF_checkSpreadArgument = new NamedFunction(MethodHandleImpl.class
  18.492 +                        .getDeclaredMethod("checkSpreadArgument", Object.class, int.class));
  18.493 +                NF_checkSpreadArgument.resolve();
  18.494 +            } catch (ReflectiveOperationException ex) {
  18.495 +                throw newInternalError(ex);
  18.496 +            }
  18.497 +        }
  18.498 +    }
  18.499 +
  18.500 +    /** Factory method:  Collect or filter selected argument(s). */
  18.501 +    static MethodHandle makeCollectArguments(MethodHandle target,
  18.502 +                MethodHandle collector, int collectArgPos, boolean retainOriginalArgs) {
  18.503 +        MethodType targetType = target.type();          // (a..., c, [b...])=>r
  18.504 +        MethodType collectorType = collector.type();    // (b...)=>c
  18.505 +        int collectArgCount = collectorType.parameterCount();
  18.506 +        Class<?> collectValType = collectorType.returnType();
  18.507 +        int collectValCount = (collectValType == void.class ? 0 : 1);
  18.508 +        MethodType srcType = targetType                 // (a..., [b...])=>r
  18.509 +                .dropParameterTypes(collectArgPos, collectArgPos+collectValCount);
  18.510 +        if (!retainOriginalArgs) {                      // (a..., b...)=>r
  18.511 +            srcType = srcType.insertParameterTypes(collectArgPos, collectorType.parameterList());
  18.512 +        }
  18.513 +        // in  arglist: [0: ...keep1 | cpos: collect...  | cpos+cacount: keep2... ]
  18.514 +        // out arglist: [0: ...keep1 | cpos: collectVal? | cpos+cvcount: keep2... ]
  18.515 +        // out(retain): [0: ...keep1 | cpos: cV? coll... | cpos+cvc+cac: keep2... ]
  18.516 +
  18.517 +        // Now build a LambdaForm.
  18.518 +        MethodType lambdaType = srcType.invokerType();
  18.519 +        Name[] names = arguments(2, lambdaType);
  18.520 +        final int collectNamePos = names.length - 2;
  18.521 +        final int targetNamePos  = names.length - 1;
  18.522 +
  18.523 +        Name[] collectorArgs = Arrays.copyOfRange(names, 1 + collectArgPos, 1 + collectArgPos + collectArgCount);
  18.524 +        names[collectNamePos] = new Name(collector, (Object[]) collectorArgs);
  18.525 +
  18.526 +        // Build argument array for the target.
  18.527 +        // Incoming LF args to copy are: [ (mh) headArgs collectArgs tailArgs ].
  18.528 +        // Output argument array is [ headArgs (collectVal)? (collectArgs)? tailArgs ].
  18.529 +        Name[] targetArgs = new Name[targetType.parameterCount()];
  18.530 +        int inputArgPos  = 1;  // incoming LF args to copy to target
  18.531 +        int targetArgPos = 0;  // fill pointer for targetArgs
  18.532 +        int chunk = collectArgPos;  // |headArgs|
  18.533 +        System.arraycopy(names, inputArgPos, targetArgs, targetArgPos, chunk);
  18.534 +        inputArgPos  += chunk;
  18.535 +        targetArgPos += chunk;
  18.536 +        if (collectValType != void.class) {
  18.537 +            targetArgs[targetArgPos++] = names[collectNamePos];
  18.538 +        }
  18.539 +        chunk = collectArgCount;
  18.540 +        if (retainOriginalArgs) {
  18.541 +            System.arraycopy(names, inputArgPos, targetArgs, targetArgPos, chunk);
  18.542 +            targetArgPos += chunk;   // optionally pass on the collected chunk
  18.543 +        }
  18.544 +        inputArgPos += chunk;
  18.545 +        chunk = targetArgs.length - targetArgPos;  // all the rest
  18.546 +        System.arraycopy(names, inputArgPos, targetArgs, targetArgPos, chunk);
  18.547 +        assert(inputArgPos + chunk == collectNamePos);  // use of rest of input args also
  18.548 +        names[targetNamePos] = new Name(target, (Object[]) targetArgs);
  18.549 +
  18.550 +        LambdaForm form = new LambdaForm("collect", lambdaType.parameterCount(), names);
  18.551 +        return SimpleMethodHandle.make(srcType, form);
  18.552 +    }
  18.553 +
  18.554 +    static
  18.555 +    MethodHandle selectAlternative(boolean testResult, MethodHandle target, MethodHandle fallback) {
  18.556 +        return testResult ? target : fallback;
  18.557 +    }
  18.558 +
  18.559 +    static MethodHandle SELECT_ALTERNATIVE;
  18.560 +    static MethodHandle selectAlternative() {
  18.561 +        if (SELECT_ALTERNATIVE != null)  return SELECT_ALTERNATIVE;
  18.562 +        try {
  18.563 +            SELECT_ALTERNATIVE
  18.564 +            = IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "selectAlternative",
  18.565 +                    MethodType.methodType(MethodHandle.class, boolean.class, MethodHandle.class, MethodHandle.class));
  18.566 +        } catch (ReflectiveOperationException ex) {
  18.567 +            throw new RuntimeException(ex);
  18.568 +        }
  18.569 +        return SELECT_ALTERNATIVE;
  18.570 +    }
  18.571 +
  18.572 +    static
  18.573 +    MethodHandle makeGuardWithTest(MethodHandle test,
  18.574 +                                   MethodHandle target,
  18.575 +                                   MethodHandle fallback) {
  18.576 +        MethodType basicType = target.type().basicType();
  18.577 +        MethodHandle invokeBasic = MethodHandles.basicInvoker(basicType);
  18.578 +        int arity = basicType.parameterCount();
  18.579 +        int extraNames = 3;
  18.580 +        MethodType lambdaType = basicType.invokerType();
  18.581 +        Name[] names = arguments(extraNames, lambdaType);
  18.582 +
  18.583 +        Object[] testArgs   = Arrays.copyOfRange(names, 1, 1 + arity, Object[].class);
  18.584 +        Object[] targetArgs = Arrays.copyOfRange(names, 0, 1 + arity, Object[].class);
  18.585 +
  18.586 +        // call test
  18.587 +        names[arity + 1] = new Name(test, testArgs);
  18.588 +
  18.589 +        // call selectAlternative
  18.590 +        Object[] selectArgs = { names[arity + 1], target, fallback };
  18.591 +        names[arity + 2] = new Name(MethodHandleImpl.selectAlternative(), selectArgs);
  18.592 +        targetArgs[0] = names[arity + 2];
  18.593 +
  18.594 +        // call target or fallback
  18.595 +        names[arity + 3] = new Name(new NamedFunction(invokeBasic), targetArgs);
  18.596 +
  18.597 +        LambdaForm form = new LambdaForm("guard", lambdaType.parameterCount(), names);
  18.598 +        return SimpleMethodHandle.make(target.type(), form);
  18.599 +    }
  18.600 +
  18.601 +    private static class GuardWithCatch {
  18.602 +        private final MethodHandle target;
  18.603 +        private final Class<? extends Throwable> exType;
  18.604 +        private final MethodHandle catcher;
  18.605 +        // FIXME: Build the control flow out of foldArguments.
  18.606 +        GuardWithCatch(MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher) {
  18.607 +            this.target = target;
  18.608 +            this.exType = exType;
  18.609 +            this.catcher = catcher;
  18.610 +        }
  18.611 +        @LambdaForm.Hidden
  18.612 +        private Object invoke_V(Object... av) throws Throwable {
  18.613 +            try {
  18.614 +                return target.invokeExact(av);
  18.615 +            } catch (Throwable t) {
  18.616 +                if (!exType.isInstance(t))  throw t;
  18.617 +                return catcher.invokeExact(t, av);
  18.618 +            }
  18.619 +        }
  18.620 +        @LambdaForm.Hidden
  18.621 +        private Object invoke_L0() throws Throwable {
  18.622 +            try {
  18.623 +                return target.invokeExact();
  18.624 +            } catch (Throwable t) {
  18.625 +                if (!exType.isInstance(t))  throw t;
  18.626 +                return catcher.invokeExact(t);
  18.627 +            }
  18.628 +        }
  18.629 +        @LambdaForm.Hidden
  18.630 +        private Object invoke_L1(Object a0) throws Throwable {
  18.631 +            try {
  18.632 +                return target.invokeExact(a0);
  18.633 +            } catch (Throwable t) {
  18.634 +                if (!exType.isInstance(t))  throw t;
  18.635 +                return catcher.invokeExact(t, a0);
  18.636 +            }
  18.637 +        }
  18.638 +        @LambdaForm.Hidden
  18.639 +        private Object invoke_L2(Object a0, Object a1) throws Throwable {
  18.640 +            try {
  18.641 +                return target.invokeExact(a0, a1);
  18.642 +            } catch (Throwable t) {
  18.643 +                if (!exType.isInstance(t))  throw t;
  18.644 +                return catcher.invokeExact(t, a0, a1);
  18.645 +            }
  18.646 +        }
  18.647 +        @LambdaForm.Hidden
  18.648 +        private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
  18.649 +            try {
  18.650 +                return target.invokeExact(a0, a1, a2);
  18.651 +            } catch (Throwable t) {
  18.652 +                if (!exType.isInstance(t))  throw t;
  18.653 +                return catcher.invokeExact(t, a0, a1, a2);
  18.654 +            }
  18.655 +        }
  18.656 +        @LambdaForm.Hidden
  18.657 +        private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
  18.658 +            try {
  18.659 +                return target.invokeExact(a0, a1, a2, a3);
  18.660 +            } catch (Throwable t) {
  18.661 +                if (!exType.isInstance(t))  throw t;
  18.662 +                return catcher.invokeExact(t, a0, a1, a2, a3);
  18.663 +            }
  18.664 +        }
  18.665 +        @LambdaForm.Hidden
  18.666 +        private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
  18.667 +            try {
  18.668 +                return target.invokeExact(a0, a1, a2, a3, a4);
  18.669 +            } catch (Throwable t) {
  18.670 +                if (!exType.isInstance(t))  throw t;
  18.671 +                return catcher.invokeExact(t, a0, a1, a2, a3, a4);
  18.672 +            }
  18.673 +        }
  18.674 +        @LambdaForm.Hidden
  18.675 +        private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
  18.676 +            try {
  18.677 +                return target.invokeExact(a0, a1, a2, a3, a4, a5);
  18.678 +            } catch (Throwable t) {
  18.679 +                if (!exType.isInstance(t))  throw t;
  18.680 +                return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5);
  18.681 +            }
  18.682 +        }
  18.683 +        @LambdaForm.Hidden
  18.684 +        private Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable {
  18.685 +            try {
  18.686 +                return target.invokeExact(a0, a1, a2, a3, a4, a5, a6);
  18.687 +            } catch (Throwable t) {
  18.688 +                if (!exType.isInstance(t))  throw t;
  18.689 +                return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5, a6);
  18.690 +            }
  18.691 +        }
  18.692 +        @LambdaForm.Hidden
  18.693 +        private Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable {
  18.694 +            try {
  18.695 +                return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7);
  18.696 +            } catch (Throwable t) {
  18.697 +                if (!exType.isInstance(t))  throw t;
  18.698 +                return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5, a6, a7);
  18.699 +            }
  18.700 +        }
  18.701 +        static MethodHandle[] makeInvokes() {
  18.702 +            ArrayList<MethodHandle> invokes = new ArrayList<>();
  18.703 +            MethodHandles.Lookup lookup = IMPL_LOOKUP;
  18.704 +            for (;;) {
  18.705 +                int nargs = invokes.size();
  18.706 +                String name = "invoke_L"+nargs;
  18.707 +                MethodHandle invoke = null;
  18.708 +                try {
  18.709 +                    invoke = lookup.findVirtual(GuardWithCatch.class, name, MethodType.genericMethodType(nargs));
  18.710 +                } catch (ReflectiveOperationException ex) {
  18.711 +                }
  18.712 +                if (invoke == null)  break;
  18.713 +                invokes.add(invoke);
  18.714 +            }
  18.715 +            assert(invokes.size() == 9);  // current number of methods
  18.716 +            return invokes.toArray(new MethodHandle[0]);
  18.717 +        };
  18.718 +        static final MethodHandle[] INVOKES = makeInvokes();
  18.719 +        // For testing use this:
  18.720 +        //static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2);
  18.721 +        static final MethodHandle VARARGS_INVOKE;
  18.722 +        static {
  18.723 +            try {
  18.724 +                VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(GuardWithCatch.class, "invoke_V", MethodType.genericMethodType(0, true));
  18.725 +            } catch (ReflectiveOperationException ex) {
  18.726 +                throw uncaughtException(ex);
  18.727 +            }
  18.728 +        }
  18.729 +    }
  18.730 +
  18.731 +
  18.732 +    static
  18.733 +    MethodHandle makeGuardWithCatch(MethodHandle target,
  18.734 +                                    Class<? extends Throwable> exType,
  18.735 +                                    MethodHandle catcher) {
  18.736 +        MethodType type = target.type();
  18.737 +        MethodType ctype = catcher.type();
  18.738 +        int nargs = type.parameterCount();
  18.739 +        if (nargs < GuardWithCatch.INVOKES.length) {
  18.740 +            MethodType gtype = type.generic();
  18.741 +            MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class);
  18.742 +            // Note: convertArguments(...2) avoids interface casts present in convertArguments(...0)
  18.743 +            MethodHandle gtarget = makePairwiseConvert(target, gtype, 2);
  18.744 +            MethodHandle gcatcher = makePairwiseConvert(catcher, gcatchType, 2);
  18.745 +            GuardWithCatch gguard = new GuardWithCatch(gtarget, exType, gcatcher);
  18.746 +            if (gtarget == null || gcatcher == null)  throw new InternalError();
  18.747 +            MethodHandle ginvoker = GuardWithCatch.INVOKES[nargs].bindReceiver(gguard);
  18.748 +            return makePairwiseConvert(ginvoker, type, 2);
  18.749 +        } else {
  18.750 +            target = target.asType(type.changeReturnType(Object.class));
  18.751 +            MethodHandle gtarget = makeSpreadArguments(target, Object[].class, 0, nargs);
  18.752 +            MethodType catcherType = ctype.changeParameterType(0, Throwable.class)
  18.753 +                                          .changeReturnType(Object.class);
  18.754 +            catcher = catcher.asType(catcherType);
  18.755 +            MethodHandle gcatcher = makeSpreadArguments(catcher, Object[].class, 1, nargs);
  18.756 +            GuardWithCatch gguard = new GuardWithCatch(gtarget, exType, gcatcher);
  18.757 +            if (gtarget == null || gcatcher == null)  throw new InternalError();
  18.758 +            MethodHandle ginvoker = GuardWithCatch.VARARGS_INVOKE.bindReceiver(gguard);
  18.759 +            MethodHandle gcollect = makeCollectArguments(ginvoker, ValueConversions.varargsArray(nargs), 0, false);
  18.760 +            return makePairwiseConvert(gcollect, type, 2);
  18.761 +        }
  18.762 +    }
  18.763 +
  18.764 +    static
  18.765 +    MethodHandle throwException(MethodType type) {
  18.766 +        assert(Throwable.class.isAssignableFrom(type.parameterType(0)));
  18.767 +        int arity = type.parameterCount();
  18.768 +        if (arity > 1) {
  18.769 +            return throwException(type.dropParameterTypes(1, arity)).dropArguments(type, 1, arity-1);
  18.770 +        }
  18.771 +        return makePairwiseConvert(throwException(), type, 2);
  18.772 +    }
  18.773 +
  18.774 +    static MethodHandle THROW_EXCEPTION;
  18.775 +    static MethodHandle throwException() {
  18.776 +        MethodHandle mh = THROW_EXCEPTION;
  18.777 +        if (mh != null)  return mh;
  18.778 +        try {
  18.779 +            mh
  18.780 +            = IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "throwException",
  18.781 +                    MethodType.methodType(Empty.class, Throwable.class));
  18.782 +        } catch (ReflectiveOperationException ex) {
  18.783 +            throw new RuntimeException(ex);
  18.784 +        }
  18.785 +        THROW_EXCEPTION = mh;
  18.786 +        return mh;
  18.787 +    }
  18.788 +    static <T extends Throwable> Empty throwException(T t) throws T { throw t; }
  18.789 +
  18.790 +    static MethodHandle[] FAKE_METHOD_HANDLE_INVOKE = new MethodHandle[2];
  18.791 +    static MethodHandle fakeMethodHandleInvoke(MemberName method) {
  18.792 +        int idx;
  18.793 +        assert(method.isMethodHandleInvoke());
  18.794 +        switch (method.getName()) {
  18.795 +        case "invoke":       idx = 0; break;
  18.796 +        case "invokeExact":  idx = 1; break;
  18.797 +        default:             throw new InternalError(method.getName());
  18.798 +        }
  18.799 +        MethodHandle mh = FAKE_METHOD_HANDLE_INVOKE[idx];
  18.800 +        if (mh != null)  return mh;
  18.801 +        MethodType type = MethodType.methodType(Object.class, UnsupportedOperationException.class,
  18.802 +                                                MethodHandle.class, Object[].class);
  18.803 +        mh = throwException(type);
  18.804 +        mh = mh.bindTo(new UnsupportedOperationException("cannot reflectively invoke MethodHandle"));
  18.805 +        if (!method.getInvocationType().equals(mh.type()))
  18.806 +            throw new InternalError(method.toString());
  18.807 +        mh = mh.withInternalMemberName(method);
  18.808 +        mh = mh.asVarargsCollector(Object[].class);
  18.809 +        assert(method.isVarargs());
  18.810 +        FAKE_METHOD_HANDLE_INVOKE[idx] = mh;
  18.811 +        return mh;
  18.812 +    }
  18.813 +
  18.814 +    /**
  18.815 +     * Create an alias for the method handle which, when called,
  18.816 +     * appears to be called from the same class loader and protection domain
  18.817 +     * as hostClass.
  18.818 +     * This is an expensive no-op unless the method which is called
  18.819 +     * is sensitive to its caller.  A small number of system methods
  18.820 +     * are in this category, including Class.forName and Method.invoke.
  18.821 +     */
  18.822 +    static
  18.823 +    MethodHandle bindCaller(MethodHandle mh, Class<?> hostClass) {
  18.824 +        return BindCaller.bindCaller(mh, hostClass);
  18.825 +    }
  18.826 +
  18.827 +    // Put the whole mess into its own nested class.
  18.828 +    // That way we can lazily load the code and set up the constants.
  18.829 +    private static class BindCaller {
  18.830 +        static
  18.831 +        MethodHandle bindCaller(MethodHandle mh, Class<?> hostClass) {
  18.832 +            // Do not use this function to inject calls into system classes.
  18.833 +            if (hostClass == null
  18.834 +                ||    (hostClass.isArray() ||
  18.835 +                       hostClass.isPrimitive() ||
  18.836 +                       hostClass.getName().startsWith("java.") ||
  18.837 +                       hostClass.getName().startsWith("sun."))) {
  18.838 +                throw new InternalError();  // does not happen, and should not anyway
  18.839 +            }
  18.840 +            // For simplicity, convert mh to a varargs-like method.
  18.841 +            MethodHandle vamh = prepareForInvoker(mh);
  18.842 +            // Cache the result of makeInjectedInvoker once per argument class.
  18.843 +            MethodHandle bccInvoker = CV_makeInjectedInvoker.get(hostClass);
  18.844 +            return restoreToType(bccInvoker.bindTo(vamh), mh.type(), mh.internalMemberName(), hostClass);
  18.845 +        }
  18.846 +
  18.847 +        private static MethodHandle makeInjectedInvoker(Class<?> hostClass) {
  18.848 +            Class<?> bcc = UNSAFE.defineAnonymousClass(hostClass, T_BYTES, null);
  18.849 +            if (hostClass.getClassLoader() != bcc.getClassLoader())
  18.850 +                throw new InternalError(hostClass.getName()+" (CL)");
  18.851 +            try {
  18.852 +                if (hostClass.getProtectionDomain() != bcc.getProtectionDomain())
  18.853 +                    throw new InternalError(hostClass.getName()+" (PD)");
  18.854 +            } catch (SecurityException ex) {
  18.855 +                // Self-check was blocked by security manager.  This is OK.
  18.856 +                // In fact the whole try body could be turned into an assertion.
  18.857 +            }
  18.858 +            try {
  18.859 +                MethodHandle init = IMPL_LOOKUP.findStatic(bcc, "init", MethodType.methodType(void.class));
  18.860 +                init.invokeExact();  // force initialization of the class
  18.861 +            } catch (Throwable ex) {
  18.862 +                throw uncaughtException(ex);
  18.863 +            }
  18.864 +            MethodHandle bccInvoker;
  18.865 +            try {
  18.866 +                MethodType invokerMT = MethodType.methodType(Object.class, MethodHandle.class, Object[].class);
  18.867 +                bccInvoker = IMPL_LOOKUP.findStatic(bcc, "invoke_V", invokerMT);
  18.868 +            } catch (ReflectiveOperationException ex) {
  18.869 +                throw uncaughtException(ex);
  18.870 +            }
  18.871 +            // Test the invoker, to ensure that it really injects into the right place.
  18.872 +            try {
  18.873 +                MethodHandle vamh = prepareForInvoker(MH_checkCallerClass);
  18.874 +                Object ok = bccInvoker.invokeExact(vamh, new Object[]{hostClass, bcc});
  18.875 +            } catch (Throwable ex) {
  18.876 +                throw new InternalError(ex);
  18.877 +            }
  18.878 +            return bccInvoker;
  18.879 +        }
  18.880 +        private static ClassValue<MethodHandle> CV_makeInjectedInvoker = new ClassValue<MethodHandle>() {
  18.881 +            @Override protected MethodHandle computeValue(Class<?> hostClass) {
  18.882 +                return makeInjectedInvoker(hostClass);
  18.883 +            }
  18.884 +        };
  18.885 +
  18.886 +        // Adapt mh so that it can be called directly from an injected invoker:
  18.887 +        private static MethodHandle prepareForInvoker(MethodHandle mh) {
  18.888 +            mh = mh.asFixedArity();
  18.889 +            MethodType mt = mh.type();
  18.890 +            int arity = mt.parameterCount();
  18.891 +            MethodHandle vamh = mh.asType(mt.generic());
  18.892 +            vamh.internalForm().compileToBytecode();  // eliminate LFI stack frames
  18.893 +            vamh = vamh.asSpreader(Object[].class, arity);
  18.894 +            vamh.internalForm().compileToBytecode();  // eliminate LFI stack frames
  18.895 +            return vamh;
  18.896 +        }
  18.897 +
  18.898 +        // Undo the adapter effect of prepareForInvoker:
  18.899 +        private static MethodHandle restoreToType(MethodHandle vamh, MethodType type,
  18.900 +                                                  MemberName member,
  18.901 +                                                  Class<?> hostClass) {
  18.902 +            MethodHandle mh = vamh.asCollector(Object[].class, type.parameterCount());
  18.903 +            mh = mh.asType(type);
  18.904 +            mh = new WrappedMember(mh, type, member, hostClass);
  18.905 +            return mh;
  18.906 +        }
  18.907 +
  18.908 +        private static final MethodHandle MH_checkCallerClass;
  18.909 +        static {
  18.910 +            final Class<?> THIS_CLASS = BindCaller.class;
  18.911 +            assert(checkCallerClass(THIS_CLASS, THIS_CLASS));
  18.912 +            try {
  18.913 +                MH_checkCallerClass = IMPL_LOOKUP
  18.914 +                    .findStatic(THIS_CLASS, "checkCallerClass",
  18.915 +                                MethodType.methodType(boolean.class, Class.class, Class.class));
  18.916 +                assert((boolean) MH_checkCallerClass.invokeExact(THIS_CLASS, THIS_CLASS));
  18.917 +            } catch (Throwable ex) {
  18.918 +                throw new InternalError(ex);
  18.919 +            }
  18.920 +        }
  18.921 +
  18.922 +        @CallerSensitive
  18.923 +        private static boolean checkCallerClass(Class<?> expected, Class<?> expected2) {
  18.924 +            // This method is called via MH_checkCallerClass and so it's
  18.925 +            // correct to ask for the immediate caller here.
  18.926 +            Class<?> actual = Reflection.getCallerClass();
  18.927 +            if (actual != expected && actual != expected2)
  18.928 +                throw new InternalError("found "+actual.getName()+", expected "+expected.getName()
  18.929 +                                        +(expected == expected2 ? "" : ", or else "+expected2.getName()));
  18.930 +            return true;
  18.931 +        }
  18.932 +
  18.933 +        private static final byte[] T_BYTES;
  18.934 +        static {
  18.935 +            final Object[] values = {null};
  18.936 +            AccessController.doPrivileged(new PrivilegedAction<Void>() {
  18.937 +                    public Void run() {
  18.938 +                        try {
  18.939 +                            Class<T> tClass = T.class;
  18.940 +                            String tName = tClass.getName();
  18.941 +                            String tResource = tName.substring(tName.lastIndexOf('.')+1)+".class";
  18.942 +                            java.net.URLConnection uconn = tClass.getResource(tResource).openConnection();
  18.943 +                            int len = uconn.getContentLength();
  18.944 +                            byte[] bytes = new byte[len];
  18.945 +                            try (java.io.InputStream str = uconn.getInputStream()) {
  18.946 +                                int nr = str.read(bytes);
  18.947 +                                if (nr != len)  throw new java.io.IOException(tResource);
  18.948 +                            }
  18.949 +                            values[0] = bytes;
  18.950 +                        } catch (java.io.IOException ex) {
  18.951 +                            throw new InternalError(ex);
  18.952 +                        }
  18.953 +                        return null;
  18.954 +                    }
  18.955 +                });
  18.956 +            T_BYTES = (byte[]) values[0];
  18.957 +        }
  18.958 +
  18.959 +        // The following class is used as a template for Unsafe.defineAnonymousClass:
  18.960 +        private static class T {
  18.961 +            static void init() { }  // side effect: initializes this class
  18.962 +            static Object invoke_V(MethodHandle vamh, Object[] args) throws Throwable {
  18.963 +                return vamh.invokeExact(args);
  18.964 +            }
  18.965 +        }
  18.966 +    }
  18.967 +
  18.968 +
  18.969 +    /** This subclass allows a wrapped method handle to be re-associated with an arbitrary member name. */
  18.970 +    static class WrappedMember extends MethodHandle {
  18.971 +        private final MethodHandle target;
  18.972 +        private final MemberName member;
  18.973 +        private final Class<?> callerClass;
  18.974 +
  18.975 +        private WrappedMember(MethodHandle target, MethodType type, MemberName member, Class<?> callerClass) {
  18.976 +            super(type, reinvokerForm(target));
  18.977 +            this.target = target;
  18.978 +            this.member = member;
  18.979 +            this.callerClass = callerClass;
  18.980 +        }
  18.981 +
  18.982 +        @Override
  18.983 +        MethodHandle reinvokerTarget() {
  18.984 +            return target;
  18.985 +        }
  18.986 +        @Override
  18.987 +        public MethodHandle asTypeUncached(MethodType newType) {
  18.988 +            // This MH is an alias for target, except for the MemberName
  18.989 +            // Drop the MemberName if there is any conversion.
  18.990 +            return asTypeCache = target.asType(newType);
  18.991 +        }
  18.992 +        @Override
  18.993 +        MemberName internalMemberName() {
  18.994 +            return member;
  18.995 +        }
  18.996 +        @Override
  18.997 +        Class<?> internalCallerClass() {
  18.998 +            return callerClass;
  18.999 +        }
 18.1000 +        @Override
 18.1001 +        boolean isInvokeSpecial() {
 18.1002 +            return target.isInvokeSpecial();
 18.1003 +        }
 18.1004 +        @Override
 18.1005 +        MethodHandle viewAsType(MethodType newType) {
 18.1006 +            return new WrappedMember(target, newType, member, callerClass);
 18.1007 +        }
 18.1008 +    }
 18.1009 +
 18.1010 +    static MethodHandle makeWrappedMember(MethodHandle target, MemberName member) {
 18.1011 +        if (member.equals(target.internalMemberName()))
 18.1012 +            return target;
 18.1013 +        return new WrappedMember(target, target.type(), member, null);
 18.1014 +    }
 18.1015 +
 18.1016 +}
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/MethodHandleInfo.java	Sat Aug 09 11:12:05 2014 +0200
    19.3 @@ -0,0 +1,284 @@
    19.4 +/*
    19.5 + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
    19.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    19.7 + *
    19.8 + * This code is free software; you can redistribute it and/or modify it
    19.9 + * under the terms of the GNU General Public License version 2 only, as
   19.10 + * published by the Free Software Foundation.  Oracle designates this
   19.11 + * particular file as subject to the "Classpath" exception as provided
   19.12 + * by Oracle in the LICENSE file that accompanied this code.
   19.13 + *
   19.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   19.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   19.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   19.17 + * version 2 for more details (a copy is included in the LICENSE file that
   19.18 + * accompanied this code).
   19.19 + *
   19.20 + * You should have received a copy of the GNU General Public License version
   19.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   19.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   19.23 + *
   19.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   19.25 + * or visit www.oracle.com if you need additional information or have any
   19.26 + * questions.
   19.27 + */
   19.28 +
   19.29 +package java.lang.invoke;
   19.30 +
   19.31 +import java.lang.reflect.*;
   19.32 +import java.util.*;
   19.33 +import java.lang.invoke.MethodHandleNatives.Constants;
   19.34 +import java.lang.invoke.MethodHandles.Lookup;
   19.35 +import static java.lang.invoke.MethodHandleStatics.*;
   19.36 +
   19.37 +/**
   19.38 + * A symbolic reference obtained by cracking a direct method handle
   19.39 + * into its consitutent symbolic parts.
   19.40 + * To crack a direct method handle, call {@link Lookup#revealDirect Lookup.revealDirect}.
   19.41 + * <h1><a name="directmh"></a>Direct Method Handles</h1>
   19.42 + * A <em>direct method handle</em> represents a method, constructor, or field without
   19.43 + * any intervening argument bindings or other transformations.
   19.44 + * The method, constructor, or field referred to by a direct method handle is called
   19.45 + * its <em>underlying member</em>.
   19.46 + * Direct method handles may be obtained in any of these ways:
   19.47 + * <ul>
   19.48 + * <li>By executing an {@code ldc} instruction on a {@code CONSTANT_MethodHandle} constant.
   19.49 + *     (See the Java Virtual Machine Specification, sections 4.4.8 and 5.4.3.)
   19.50 + * <li>By calling one of the <a href="MethodHandles.Lookup.html#lookups">Lookup Factory Methods</a>,
   19.51 + *     such as {@link Lookup#findVirtual Lookup.findVirtual},
   19.52 + *     to resolve a symbolic reference into a method handle.
   19.53 + *     A symbolic reference consists of a class, name string, and type.
   19.54 + * <li>By calling the factory method {@link Lookup#unreflect Lookup.unreflect}
   19.55 + *     or {@link Lookup#unreflectSpecial Lookup.unreflectSpecial}
   19.56 + *     to convert a {@link Method} into a method handle.
   19.57 + * <li>By calling the factory method {@link Lookup#unreflectConstructor Lookup.unreflectConstructor}
   19.58 + *     to convert a {@link Constructor} into a method handle.
   19.59 + * <li>By calling the factory method {@link Lookup#unreflectGetter Lookup.unreflectGetter}
   19.60 + *     or {@link Lookup#unreflectSetter Lookup.unreflectSetter}
   19.61 + *     to convert a {@link Field} into a method handle.
   19.62 + * </ul>
   19.63 + *
   19.64 + * <h1>Restrictions on Cracking</h1>
   19.65 + * Given a suitable {@code Lookup} object, it is possible to crack any direct method handle
   19.66 + * to recover a symbolic reference for the underlying method, constructor, or field.
   19.67 + * Cracking must be done via a {@code Lookup} object equivalent to that which created
   19.68 + * the target method handle, or which has enough access permissions to recreate
   19.69 + * an equivalent method handle.
   19.70 + * <p>
   19.71 + * If the underlying method is <a href="MethodHandles.Lookup.html#callsens">caller sensitive</a>,
   19.72 + * the direct method handle will have been "bound" to a particular caller class, the
   19.73 + * {@linkplain java.lang.invoke.MethodHandles.Lookup#lookupClass() lookup class}
   19.74 + * of the lookup object used to create it.
   19.75 + * Cracking this method handle with a different lookup class will fail
   19.76 + * even if the underlying method is public (like {@code Class.forName}).
   19.77 + * <p>
   19.78 + * The requirement of lookup object matching provides a "fast fail" behavior
   19.79 + * for programs which may otherwise trust erroneous revelation of a method
   19.80 + * handle with symbolic information (or caller binding) from an unexpected scope.
   19.81 + * Use {@link java.lang.invoke.MethodHandles#reflectAs} to override this limitation.
   19.82 + *
   19.83 + * <h1><a name="refkinds"></a>Reference kinds</h1>
   19.84 + * The <a href="MethodHandles.Lookup.html#lookups">Lookup Factory Methods</a>
   19.85 + * correspond to all major use cases for methods, constructors, and fields.
   19.86 + * These use cases may be distinguished using small integers as follows:
   19.87 + * <table border=1 cellpadding=5 summary="reference kinds">
   19.88 + * <tr><th>reference kind</th><th>descriptive name</th><th>scope</th><th>member</th><th>behavior</th></tr>
   19.89 + * <tr>
   19.90 + *     <td>{@code 1}</td><td>{@code REF_getField}</td><td>{@code class}</td>
   19.91 + *     <td>{@code FT f;}</td><td>{@code (T) this.f;}</td>
   19.92 + * </tr>
   19.93 + * <tr>
   19.94 + *     <td>{@code 2}</td><td>{@code REF_getStatic}</td><td>{@code class} or {@code interface}</td>
   19.95 + *     <td>{@code static}<br>{@code FT f;}</td><td>{@code (T) C.f;}</td>
   19.96 + * </tr>
   19.97 + * <tr>
   19.98 + *     <td>{@code 3}</td><td>{@code REF_putField}</td><td>{@code class}</td>
   19.99 + *     <td>{@code FT f;}</td><td>{@code this.f = x;}</td>
  19.100 + * </tr>
  19.101 + * <tr>
  19.102 + *     <td>{@code 4}</td><td>{@code REF_putStatic}</td><td>{@code class}</td>
  19.103 + *     <td>{@code static}<br>{@code FT f;}</td><td>{@code C.f = arg;}</td>
  19.104 + * </tr>
  19.105 + * <tr>
  19.106 + *     <td>{@code 5}</td><td>{@code REF_invokeVirtual}</td><td>{@code class}</td>
  19.107 + *     <td>{@code T m(A*);}</td><td>{@code (T) this.m(arg*);}</td>
  19.108 + * </tr>
  19.109 + * <tr>
  19.110 + *     <td>{@code 6}</td><td>{@code REF_invokeStatic}</td><td>{@code class} or {@code interface}</td>
  19.111 + *     <td>{@code static}<br>{@code T m(A*);}</td><td>{@code (T) C.m(arg*);}</td>
  19.112 + * </tr>
  19.113 + * <tr>
  19.114 + *     <td>{@code 7}</td><td>{@code REF_invokeSpecial}</td><td>{@code class} or {@code interface}</td>
  19.115 + *     <td>{@code T m(A*);}</td><td>{@code (T) super.m(arg*);}</td>
  19.116 + * </tr>
  19.117 + * <tr>
  19.118 + *     <td>{@code 8}</td><td>{@code REF_newInvokeSpecial}</td><td>{@code class}</td>
  19.119 + *     <td>{@code C(A*);}</td><td>{@code new C(arg*);}</td>
  19.120 + * </tr>
  19.121 + * <tr>
  19.122 + *     <td>{@code 9}</td><td>{@code REF_invokeInterface}</td><td>{@code interface}</td>
  19.123 + *     <td>{@code T m(A*);}</td><td>{@code (T) this.m(arg*);}</td>
  19.124 + * </tr>
  19.125 + * </table>
  19.126 + * @since 1.8
  19.127 + */
  19.128 +public
  19.129 +interface MethodHandleInfo {
  19.130 +    /**
  19.131 +     * A direct method handle reference kind,
  19.132 +     * as defined in the <a href="MethodHandleInfo.html#refkinds">table above</a>.
  19.133 +     */
  19.134 +    public static final int
  19.135 +        REF_getField                = Constants.REF_getField,
  19.136 +        REF_getStatic               = Constants.REF_getStatic,
  19.137 +        REF_putField                = Constants.REF_putField,
  19.138 +        REF_putStatic               = Constants.REF_putStatic,
  19.139 +        REF_invokeVirtual           = Constants.REF_invokeVirtual,
  19.140 +        REF_invokeStatic            = Constants.REF_invokeStatic,
  19.141 +        REF_invokeSpecial           = Constants.REF_invokeSpecial,
  19.142 +        REF_newInvokeSpecial        = Constants.REF_newInvokeSpecial,
  19.143 +        REF_invokeInterface         = Constants.REF_invokeInterface;
  19.144 +
  19.145 +    /**
  19.146 +     * Returns the reference kind of the cracked method handle, which in turn
  19.147 +     * determines whether the method handle's underlying member was a constructor, method, or field.
  19.148 +     * See the <a href="MethodHandleInfo.html#refkinds">table above</a> for definitions.
  19.149 +     * @return the integer code for the kind of reference used to access the underlying member
  19.150 +     */
  19.151 +    public int getReferenceKind();
  19.152 +
  19.153 +    /**
  19.154 +     * Returns the class in which the cracked method handle's underlying member was defined.
  19.155 +     * @return the declaring class of the underlying member
  19.156 +     */
  19.157 +    public Class<?> getDeclaringClass();
  19.158 +
  19.159 +    /**
  19.160 +     * Returns the name of the cracked method handle's underlying member.
  19.161 +     * This is {@code "&lt;init&gt;"} if the underlying member was a constructor,
  19.162 +     * else it is a simple method name or field name.
  19.163 +     * @return the simple name of the underlying member
  19.164 +     */
  19.165 +    public String getName();
  19.166 +
  19.167 +    /**
  19.168 +     * Returns the nominal type of the cracked symbolic reference, expressed as a method type.
  19.169 +     * If the reference is to a constructor, the return type will be {@code void}.
  19.170 +     * If it is to a non-static method, the method type will not mention the {@code this} parameter.
  19.171 +     * If it is to a field and the requested access is to read the field,
  19.172 +     * the method type will have no parameters and return the field type.
  19.173 +     * If it is to a field and the requested access is to write the field,
  19.174 +     * the method type will have one parameter of the field type and return {@code void}.
  19.175 +     * <p>
  19.176 +     * Note that original direct method handle may include a leading {@code this} parameter,
  19.177 +     * or (in the case of a constructor) will replace the {@code void} return type
  19.178 +     * with the constructed class.
  19.179 +     * The nominal type does not include any {@code this} parameter,
  19.180 +     * and (in the case of a constructor) will return {@code void}.
  19.181 +     * @return the type of the underlying member, expressed as a method type
  19.182 +     */
  19.183 +    public MethodType getMethodType();
  19.184 +
  19.185 +    // Utility methods.
  19.186 +    // NOTE: class/name/type and reference kind constitute a symbolic reference
  19.187 +    // member and modifiers are an add-on, derived from Core Reflection (or the equivalent)
  19.188 +
  19.189 +    /**
  19.190 +     * Reflects the underlying member as a method, constructor, or field object.
  19.191 +     * If the underlying member is public, it is reflected as if by
  19.192 +     * {@code getMethod}, {@code getConstructor}, or {@code getField}.
  19.193 +     * Otherwise, it is reflected as if by
  19.194 +     * {@code getDeclaredMethod}, {@code getDeclaredConstructor}, or {@code getDeclaredField}.
  19.195 +     * The underlying member must be accessible to the given lookup object.
  19.196 +     * @param <T> the desired type of the result, either {@link Member} or a subtype
  19.197 +     * @param expected a class object representing the desired result type {@code T}
  19.198 +     * @param lookup the lookup object that created this MethodHandleInfo, or one with equivalent access privileges
  19.199 +     * @return a reference to the method, constructor, or field object
  19.200 +     * @exception ClassCastException if the member is not of the expected type
  19.201 +     * @exception NullPointerException if either argument is {@code null}
  19.202 +     * @exception IllegalArgumentException if the underlying member is not accessible to the given lookup object
  19.203 +     */
  19.204 +    public <T extends Member> T reflectAs(Class<T> expected, Lookup lookup);
  19.205 +
  19.206 +    /**
  19.207 +     * Returns the access modifiers of the underlying member.
  19.208 +     * @return the Java language modifiers for underlying member,
  19.209 +     *         or -1 if the member cannot be accessed
  19.210 +     * @see Modifier
  19.211 +     * @see #reflectAs
  19.212 +     */
  19.213 +    public int getModifiers();
  19.214 +
  19.215 +    /**
  19.216 +     * Determines if the underlying member was a variable arity method or constructor.
  19.217 +     * Such members are represented by method handles that are varargs collectors.
  19.218 +     * @implSpec
  19.219 +     * This produces a result equivalent to:
  19.220 +     * <pre>{@code
  19.221 +     *     getReferenceKind() >= REF_invokeVirtual && Modifier.isTransient(getModifiers())
  19.222 +     * }</pre>
  19.223 +     *
  19.224 +     *
  19.225 +     * @return {@code true} if and only if the underlying member was declared with variable arity.
  19.226 +     */
  19.227 +    // spelling derived from java.lang.reflect.Executable, not MethodHandle.isVarargsCollector
  19.228 +    public default boolean isVarArgs()  {
  19.229 +        // fields are never varargs:
  19.230 +        if (MethodHandleNatives.refKindIsField((byte) getReferenceKind()))
  19.231 +            return false;
  19.232 +        // not in the public API: Modifier.VARARGS
  19.233 +        final int ACC_VARARGS = 0x00000080;  // from JVMS 4.6 (Table 4.20)
  19.234 +        assert(ACC_VARARGS == Modifier.TRANSIENT);
  19.235 +        return Modifier.isTransient(getModifiers());
  19.236 +    }
  19.237 +
  19.238 +    /**
  19.239 +     * Returns the descriptive name of the given reference kind,
  19.240 +     * as defined in the <a href="MethodHandleInfo.html#refkinds">table above</a>.
  19.241 +     * The conventional prefix "REF_" is omitted.
  19.242 +     * @param referenceKind an integer code for a kind of reference used to access a class member
  19.243 +     * @return a mixed-case string such as {@code "getField"}
  19.244 +     * @exception IllegalArgumentException if the argument is not a valid
  19.245 +     *            <a href="MethodHandleInfo.html#refkinds">reference kind number</a>
  19.246 +     */
  19.247 +    public static String referenceKindToString(int referenceKind) {
  19.248 +        if (!MethodHandleNatives.refKindIsValid(referenceKind))
  19.249 +            throw newIllegalArgumentException("invalid reference kind", referenceKind);
  19.250 +        return MethodHandleNatives.refKindName((byte)referenceKind);
  19.251 +    }
  19.252 +
  19.253 +    /**
  19.254 +     * Returns a string representation for a {@code MethodHandleInfo},
  19.255 +     * given the four parts of its symbolic reference.
  19.256 +     * This is defined to be of the form {@code "RK C.N:MT"}, where {@code RK} is the
  19.257 +     * {@linkplain #referenceKindToString reference kind string} for {@code kind},
  19.258 +     * {@code C} is the {@linkplain java.lang.Class#getName name} of {@code defc}
  19.259 +     * {@code N} is the {@code name}, and
  19.260 +     * {@code MT} is the {@code type}.
  19.261 +     * These four values may be obtained from the
  19.262 +     * {@linkplain #getReferenceKind reference kind},
  19.263 +     * {@linkplain #getDeclaringClass declaring class},
  19.264 +     * {@linkplain #getName member name},
  19.265 +     * and {@linkplain #getMethodType method type}
  19.266 +     * of a {@code MethodHandleInfo} object.
  19.267 +     *
  19.268 +     * @implSpec
  19.269 +     * This produces a result equivalent to:
  19.270 +     * <pre>{@code
  19.271 +     *     String.format("%s %s.%s:%s", referenceKindToString(kind), defc.getName(), name, type)
  19.272 +     * }</pre>
  19.273 +     *
  19.274 +     * @param kind the {@linkplain #getReferenceKind reference kind} part of the symbolic reference
  19.275 +     * @param defc the {@linkplain #getDeclaringClass declaring class} part of the symbolic reference
  19.276 +     * @param name the {@linkplain #getName member name} part of the symbolic reference
  19.277 +     * @param type the {@linkplain #getMethodType method type} part of the symbolic reference
  19.278 +     * @return a string of the form {@code "RK C.N:MT"}
  19.279 +     * @exception IllegalArgumentException if the first argument is not a valid
  19.280 +     *            <a href="MethodHandleInfo.html#refkinds">reference kind number</a>
  19.281 +     * @exception NullPointerException if any reference argument is {@code null}
  19.282 +     */
  19.283 +    public static String toString(int kind, Class<?> defc, String name, MethodType type) {
  19.284 +        Objects.requireNonNull(name); Objects.requireNonNull(type);
  19.285 +        return String.format("%s %s.%s:%s", referenceKindToString(kind), defc.getName(), name, type);
  19.286 +    }
  19.287 +}
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/MethodHandleNatives.java	Sat Aug 09 11:12:05 2014 +0200
    20.3 @@ -0,0 +1,505 @@
    20.4 +/*
    20.5 + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
    20.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    20.7 + *
    20.8 + * This code is free software; you can redistribute it and/or modify it
    20.9 + * under the terms of the GNU General Public License version 2 only, as
   20.10 + * published by the Free Software Foundation.  Oracle designates this
   20.11 + * particular file as subject to the "Classpath" exception as provided
   20.12 + * by Oracle in the LICENSE file that accompanied this code.
   20.13 + *
   20.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   20.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   20.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   20.17 + * version 2 for more details (a copy is included in the LICENSE file that
   20.18 + * accompanied this code).
   20.19 + *
   20.20 + * You should have received a copy of the GNU General Public License version
   20.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   20.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20.23 + *
   20.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   20.25 + * or visit www.oracle.com if you need additional information or have any
   20.26 + * questions.
   20.27 + */
   20.28 +
   20.29 +package java.lang.invoke;
   20.30 +
   20.31 +import java.lang.invoke.MethodHandles.Lookup;
   20.32 +import java.lang.reflect.Field;
   20.33 +import static java.lang.invoke.MethodHandleNatives.Constants.*;
   20.34 +import static java.lang.invoke.MethodHandleStatics.*;
   20.35 +import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
   20.36 +
   20.37 +/**
   20.38 + * The JVM interface for the method handles package is all here.
   20.39 + * This is an interface internal and private to an implementation of JSR 292.
   20.40 + * <em>This class is not part of the JSR 292 standard.</em>
   20.41 + * @author jrose
   20.42 + */
   20.43 +class MethodHandleNatives {
   20.44 +
   20.45 +    private MethodHandleNatives() { } // static only
   20.46 +
   20.47 +    /// MemberName support
   20.48 +
   20.49 +    static native void init(MemberName self, Object ref);
   20.50 +    static native void expand(MemberName self);
   20.51 +    static native MemberName resolve(MemberName self, Class<?> caller) throws LinkageError;
   20.52 +    static native int getMembers(Class<?> defc, String matchName, String matchSig,
   20.53 +            int matchFlags, Class<?> caller, int skip, MemberName[] results);
   20.54 +
   20.55 +    /// Field layout queries parallel to sun.misc.Unsafe:
   20.56 +    static native long objectFieldOffset(MemberName self);  // e.g., returns vmindex
   20.57 +    static native long staticFieldOffset(MemberName self);  // e.g., returns vmindex
   20.58 +    static native Object staticFieldBase(MemberName self);  // e.g., returns clazz
   20.59 +    static native Object getMemberVMInfo(MemberName self);  // returns {vmindex,vmtarget}
   20.60 +
   20.61 +    /// MethodHandle support
   20.62 +
   20.63 +    /** Fetch MH-related JVM parameter.
   20.64 +     *  which=0 retrieves MethodHandlePushLimit
   20.65 +     *  which=1 retrieves stack slot push size (in address units)
   20.66 +     */
   20.67 +    static native int getConstant(int which);
   20.68 +
   20.69 +    static final boolean COUNT_GWT;
   20.70 +
   20.71 +    /// CallSite support
   20.72 +
   20.73 +    /** Tell the JVM that we need to change the target of a CallSite. */
   20.74 +    static native void setCallSiteTargetNormal(CallSite site, MethodHandle target);
   20.75 +    static native void setCallSiteTargetVolatile(CallSite site, MethodHandle target);
   20.76 +
   20.77 +    private static native void registerNatives();
   20.78 +    static {
   20.79 +        registerNatives();
   20.80 +        COUNT_GWT                   = getConstant(Constants.GC_COUNT_GWT) != 0;
   20.81 +
   20.82 +        // The JVM calls MethodHandleNatives.<clinit>.  Cascade the <clinit> calls as needed:
   20.83 +        MethodHandleImpl.initStatics();
   20.84 +}
   20.85 +
   20.86 +    // All compile-time constants go here.
   20.87 +    // There is an opportunity to check them against the JVM's idea of them.
   20.88 +    static class Constants {
   20.89 +        Constants() { } // static only
   20.90 +        // MethodHandleImpl
   20.91 +        static final int // for getConstant
   20.92 +                GC_COUNT_GWT = 4,
   20.93 +                GC_LAMBDA_SUPPORT = 5;
   20.94 +
   20.95 +        // MemberName
   20.96 +        // The JVM uses values of -2 and above for vtable indexes.
   20.97 +        // Field values are simple positive offsets.
   20.98 +        // Ref: src/share/vm/oops/methodOop.hpp
   20.99 +        // This value is negative enough to avoid such numbers,
  20.100 +        // but not too negative.
  20.101 +        static final int
  20.102 +                MN_IS_METHOD           = 0x00010000, // method (not constructor)
  20.103 +                MN_IS_CONSTRUCTOR      = 0x00020000, // constructor
  20.104 +                MN_IS_FIELD            = 0x00040000, // field
  20.105 +                MN_IS_TYPE             = 0x00080000, // nested type
  20.106 +                MN_CALLER_SENSITIVE    = 0x00100000, // @CallerSensitive annotation detected
  20.107 +                MN_REFERENCE_KIND_SHIFT = 24, // refKind
  20.108 +                MN_REFERENCE_KIND_MASK = 0x0F000000 >> MN_REFERENCE_KIND_SHIFT,
  20.109 +                // The SEARCH_* bits are not for MN.flags but for the matchFlags argument of MHN.getMembers:
  20.110 +                MN_SEARCH_SUPERCLASSES = 0x00100000,
  20.111 +                MN_SEARCH_INTERFACES   = 0x00200000;
  20.112 +
  20.113 +        /**
  20.114 +         * Basic types as encoded in the JVM.  These code values are not
  20.115 +         * intended for use outside this class.  They are used as part of
  20.116 +         * a private interface between the JVM and this class.
  20.117 +         */
  20.118 +        static final int
  20.119 +            T_BOOLEAN  =  4,
  20.120 +            T_CHAR     =  5,
  20.121 +            T_FLOAT    =  6,
  20.122 +            T_DOUBLE   =  7,
  20.123 +            T_BYTE     =  8,
  20.124 +            T_SHORT    =  9,
  20.125 +            T_INT      = 10,
  20.126 +            T_LONG     = 11,
  20.127 +            T_OBJECT   = 12,
  20.128 +            //T_ARRAY    = 13
  20.129 +            T_VOID     = 14,
  20.130 +            //T_ADDRESS  = 15
  20.131 +            T_ILLEGAL  = 99;
  20.132 +
  20.133 +        /**
  20.134 +         * Constant pool entry types.
  20.135 +         */
  20.136 +        static final byte
  20.137 +            CONSTANT_Utf8                = 1,
  20.138 +            CONSTANT_Integer             = 3,
  20.139 +            CONSTANT_Float               = 4,
  20.140 +            CONSTANT_Long                = 5,
  20.141 +            CONSTANT_Double              = 6,
  20.142 +            CONSTANT_Class               = 7,
  20.143 +            CONSTANT_String              = 8,
  20.144 +            CONSTANT_Fieldref            = 9,
  20.145 +            CONSTANT_Methodref           = 10,
  20.146 +            CONSTANT_InterfaceMethodref  = 11,
  20.147 +            CONSTANT_NameAndType         = 12,
  20.148 +            CONSTANT_MethodHandle        = 15,  // JSR 292
  20.149 +            CONSTANT_MethodType          = 16,  // JSR 292
  20.150 +            CONSTANT_InvokeDynamic       = 18,
  20.151 +            CONSTANT_LIMIT               = 19;   // Limit to tags found in classfiles
  20.152 +
  20.153 +        /**
  20.154 +         * Access modifier flags.
  20.155 +         */
  20.156 +        static final char
  20.157 +            ACC_PUBLIC                 = 0x0001,
  20.158 +            ACC_PRIVATE                = 0x0002,
  20.159 +            ACC_PROTECTED              = 0x0004,
  20.160 +            ACC_STATIC                 = 0x0008,
  20.161 +            ACC_FINAL                  = 0x0010,
  20.162 +            ACC_SYNCHRONIZED           = 0x0020,
  20.163 +            ACC_VOLATILE               = 0x0040,
  20.164 +            ACC_TRANSIENT              = 0x0080,
  20.165 +            ACC_NATIVE                 = 0x0100,
  20.166 +            ACC_INTERFACE              = 0x0200,
  20.167 +            ACC_ABSTRACT               = 0x0400,
  20.168 +            ACC_STRICT                 = 0x0800,
  20.169 +            ACC_SYNTHETIC              = 0x1000,
  20.170 +            ACC_ANNOTATION             = 0x2000,
  20.171 +            ACC_ENUM                   = 0x4000,
  20.172 +            // aliases:
  20.173 +            ACC_SUPER                  = ACC_SYNCHRONIZED,
  20.174 +            ACC_BRIDGE                 = ACC_VOLATILE,
  20.175 +            ACC_VARARGS                = ACC_TRANSIENT;
  20.176 +
  20.177 +        /**
  20.178 +         * Constant pool reference-kind codes, as used by CONSTANT_MethodHandle CP entries.
  20.179 +         */
  20.180 +        static final byte
  20.181 +            REF_NONE                    = 0,  // null value
  20.182 +            REF_getField                = 1,
  20.183 +            REF_getStatic               = 2,
  20.184 +            REF_putField                = 3,
  20.185 +            REF_putStatic               = 4,
  20.186 +            REF_invokeVirtual           = 5,
  20.187 +            REF_invokeStatic            = 6,
  20.188 +            REF_invokeSpecial           = 7,
  20.189 +            REF_newInvokeSpecial        = 8,
  20.190 +            REF_invokeInterface         = 9,
  20.191 +            REF_LIMIT                  = 10;
  20.192 +    }
  20.193 +
  20.194 +    static boolean refKindIsValid(int refKind) {
  20.195 +        return (refKind > REF_NONE && refKind < REF_LIMIT);
  20.196 +    }
  20.197 +    static boolean refKindIsField(byte refKind) {
  20.198 +        assert(refKindIsValid(refKind));
  20.199 +        return (refKind <= REF_putStatic);
  20.200 +    }
  20.201 +    static boolean refKindIsGetter(byte refKind) {
  20.202 +        assert(refKindIsValid(refKind));
  20.203 +        return (refKind <= REF_getStatic);
  20.204 +    }
  20.205 +    static boolean refKindIsSetter(byte refKind) {
  20.206 +        return refKindIsField(refKind) && !refKindIsGetter(refKind);
  20.207 +    }
  20.208 +    static boolean refKindIsMethod(byte refKind) {
  20.209 +        return !refKindIsField(refKind) && (refKind != REF_newInvokeSpecial);
  20.210 +    }
  20.211 +    static boolean refKindIsConstructor(byte refKind) {
  20.212 +        return (refKind == REF_newInvokeSpecial);
  20.213 +    }
  20.214 +    static boolean refKindHasReceiver(byte refKind) {
  20.215 +        assert(refKindIsValid(refKind));
  20.216 +        return (refKind & 1) != 0;
  20.217 +    }
  20.218 +    static boolean refKindIsStatic(byte refKind) {
  20.219 +        return !refKindHasReceiver(refKind) && (refKind != REF_newInvokeSpecial);
  20.220 +    }
  20.221 +    static boolean refKindDoesDispatch(byte refKind) {
  20.222 +        assert(refKindIsValid(refKind));
  20.223 +        return (refKind == REF_invokeVirtual ||
  20.224 +                refKind == REF_invokeInterface);
  20.225 +    }
  20.226 +    static {
  20.227 +        final int HR_MASK = ((1 << REF_getField) |
  20.228 +                             (1 << REF_putField) |
  20.229 +                             (1 << REF_invokeVirtual) |
  20.230 +                             (1 << REF_invokeSpecial) |
  20.231 +                             (1 << REF_invokeInterface)
  20.232 +                            );
  20.233 +        for (byte refKind = REF_NONE+1; refKind < REF_LIMIT; refKind++) {
  20.234 +            assert(refKindHasReceiver(refKind) == (((1<<refKind) & HR_MASK) != 0)) : refKind;
  20.235 +        }
  20.236 +    }
  20.237 +    static String refKindName(byte refKind) {
  20.238 +        assert(refKindIsValid(refKind));
  20.239 +        switch (refKind) {
  20.240 +        case REF_getField:          return "getField";
  20.241 +        case REF_getStatic:         return "getStatic";
  20.242 +        case REF_putField:          return "putField";
  20.243 +        case REF_putStatic:         return "putStatic";
  20.244 +        case REF_invokeVirtual:     return "invokeVirtual";
  20.245 +        case REF_invokeStatic:      return "invokeStatic";
  20.246 +        case REF_invokeSpecial:     return "invokeSpecial";
  20.247 +        case REF_newInvokeSpecial:  return "newInvokeSpecial";
  20.248 +        case REF_invokeInterface:   return "invokeInterface";
  20.249 +        default:                    return "REF_???";
  20.250 +        }
  20.251 +    }
  20.252 +
  20.253 +    private static native int getNamedCon(int which, Object[] name);
  20.254 +    static boolean verifyConstants() {
  20.255 +        Object[] box = { null };
  20.256 +        for (int i = 0; ; i++) {
  20.257 +            box[0] = null;
  20.258 +            int vmval = getNamedCon(i, box);
  20.259 +            if (box[0] == null)  break;
  20.260 +            String name = (String) box[0];
  20.261 +            try {
  20.262 +                Field con = Constants.class.getDeclaredField(name);
  20.263 +                int jval = con.getInt(null);
  20.264 +                if (jval == vmval)  continue;
  20.265 +                String err = (name+": JVM has "+vmval+" while Java has "+jval);
  20.266 +                if (name.equals("CONV_OP_LIMIT")) {
  20.267 +                    System.err.println("warning: "+err);
  20.268 +                    continue;
  20.269 +                }
  20.270 +                throw new InternalError(err);
  20.271 +            } catch (NoSuchFieldException | IllegalAccessException ex) {
  20.272 +                String err = (name+": JVM has "+vmval+" which Java does not define");
  20.273 +                // ignore exotic ops the JVM cares about; we just wont issue them
  20.274 +                //System.err.println("warning: "+err);
  20.275 +                continue;
  20.276 +            }
  20.277 +        }
  20.278 +        return true;
  20.279 +    }
  20.280 +    static {
  20.281 +        assert(verifyConstants());
  20.282 +    }
  20.283 +
  20.284 +    // Up-calls from the JVM.
  20.285 +    // These must NOT be public.
  20.286 +
  20.287 +    /**
  20.288 +     * The JVM is linking an invokedynamic instruction.  Create a reified call site for it.
  20.289 +     */
  20.290 +    static MemberName linkCallSite(Object callerObj,
  20.291 +                                   Object bootstrapMethodObj,
  20.292 +                                   Object nameObj, Object typeObj,
  20.293 +                                   Object staticArguments,
  20.294 +                                   Object[] appendixResult) {
  20.295 +        MethodHandle bootstrapMethod = (MethodHandle)bootstrapMethodObj;
  20.296 +        Class<?> caller = (Class<?>)callerObj;
  20.297 +        String name = nameObj.toString().intern();
  20.298 +        MethodType type = (MethodType)typeObj;
  20.299 +        CallSite callSite = CallSite.makeSite(bootstrapMethod,
  20.300 +                                              name,
  20.301 +                                              type,
  20.302 +                                              staticArguments,
  20.303 +                                              caller);
  20.304 +        if (callSite instanceof ConstantCallSite) {
  20.305 +            appendixResult[0] = callSite.dynamicInvoker();
  20.306 +            return Invokers.linkToTargetMethod(type);
  20.307 +        } else {
  20.308 +            appendixResult[0] = callSite;
  20.309 +            return Invokers.linkToCallSiteMethod(type);
  20.310 +        }
  20.311 +    }
  20.312 +
  20.313 +    /**
  20.314 +     * The JVM wants a pointer to a MethodType.  Oblige it by finding or creating one.
  20.315 +     */
  20.316 +    static MethodType findMethodHandleType(Class<?> rtype, Class<?>[] ptypes) {
  20.317 +        return MethodType.makeImpl(rtype, ptypes, true);
  20.318 +    }
  20.319 +
  20.320 +    /**
  20.321 +     * The JVM wants to link a call site that requires a dynamic type check.
  20.322 +     * Name is a type-checking invoker, invokeExact or invoke.
  20.323 +     * Return a JVM method (MemberName) to handle the invoking.
  20.324 +     * The method assumes the following arguments on the stack:
  20.325 +     * 0: the method handle being invoked
  20.326 +     * 1-N: the arguments to the method handle invocation
  20.327 +     * N+1: an optional, implicitly added argument (typically the given MethodType)
  20.328 +     * <p>
  20.329 +     * The nominal method at such a call site is an instance of
  20.330 +     * a signature-polymorphic method (see @PolymorphicSignature).
  20.331 +     * Such method instances are user-visible entities which are
  20.332 +     * "split" from the generic placeholder method in {@code MethodHandle}.
  20.333 +     * (Note that the placeholder method is not identical with any of
  20.334 +     * its instances.  If invoked reflectively, is guaranteed to throw an
  20.335 +     * {@code UnsupportedOperationException}.)
  20.336 +     * If the signature-polymorphic method instance is ever reified,
  20.337 +     * it appears as a "copy" of the original placeholder
  20.338 +     * (a native final member of {@code MethodHandle}) except
  20.339 +     * that its type descriptor has shape required by the instance,
  20.340 +     * and the method instance is <em>not</em> varargs.
  20.341 +     * The method instance is also marked synthetic, since the
  20.342 +     * method (by definition) does not appear in Java source code.
  20.343 +     * <p>
  20.344 +     * The JVM is allowed to reify this method as instance metadata.
  20.345 +     * For example, {@code invokeBasic} is always reified.
  20.346 +     * But the JVM may instead call {@code linkMethod}.
  20.347 +     * If the result is an * ordered pair of a {@code (method, appendix)},
  20.348 +     * the method gets all the arguments (0..N inclusive)
  20.349 +     * plus the appendix (N+1), and uses the appendix to complete the call.
  20.350 +     * In this way, one reusable method (called a "linker method")
  20.351 +     * can perform the function of any number of polymorphic instance
  20.352 +     * methods.
  20.353 +     * <p>
  20.354 +     * Linker methods are allowed to be weakly typed, with any or
  20.355 +     * all references rewritten to {@code Object} and any primitives
  20.356 +     * (except {@code long}/{@code float}/{@code double})
  20.357 +     * rewritten to {@code int}.
  20.358 +     * A linker method is trusted to return a strongly typed result,
  20.359 +     * according to the specific method type descriptor of the
  20.360 +     * signature-polymorphic instance it is emulating.
  20.361 +     * This can involve (as necessary) a dynamic check using
  20.362 +     * data extracted from the appendix argument.
  20.363 +     * <p>
  20.364 +     * The JVM does not inspect the appendix, other than to pass
  20.365 +     * it verbatim to the linker method at every call.
  20.366 +     * This means that the JDK runtime has wide latitude
  20.367 +     * for choosing the shape of each linker method and its
  20.368 +     * corresponding appendix.
  20.369 +     * Linker methods should be generated from {@code LambdaForm}s
  20.370 +     * so that they do not become visible on stack traces.
  20.371 +     * <p>
  20.372 +     * The {@code linkMethod} call is free to omit the appendix
  20.373 +     * (returning null) and instead emulate the required function
  20.374 +     * completely in the linker method.
  20.375 +     * As a corner case, if N==255, no appendix is possible.
  20.376 +     * In this case, the method returned must be custom-generated to
  20.377 +     * to perform any needed type checking.
  20.378 +     * <p>
  20.379 +     * If the JVM does not reify a method at a call site, but instead
  20.380 +     * calls {@code linkMethod}, the corresponding call represented
  20.381 +     * in the bytecodes may mention a valid method which is not
  20.382 +     * representable with a {@code MemberName}.
  20.383 +     * Therefore, use cases for {@code linkMethod} tend to correspond to
  20.384 +     * special cases in reflective code such as {@code findVirtual}
  20.385 +     * or {@code revealDirect}.
  20.386 +     */
  20.387 +    static MemberName linkMethod(Class<?> callerClass, int refKind,
  20.388 +                                 Class<?> defc, String name, Object type,
  20.389 +                                 Object[] appendixResult) {
  20.390 +        if (!TRACE_METHOD_LINKAGE)
  20.391 +            return linkMethodImpl(callerClass, refKind, defc, name, type, appendixResult);
  20.392 +        return linkMethodTracing(callerClass, refKind, defc, name, type, appendixResult);
  20.393 +    }
  20.394 +    static MemberName linkMethodImpl(Class<?> callerClass, int refKind,
  20.395 +                                     Class<?> defc, String name, Object type,
  20.396 +                                     Object[] appendixResult) {
  20.397 +        try {
  20.398 +            if (defc == MethodHandle.class && refKind == REF_invokeVirtual) {
  20.399 +                return Invokers.methodHandleInvokeLinkerMethod(name, fixMethodType(callerClass, type), appendixResult);
  20.400 +            }
  20.401 +        } catch (Throwable ex) {
  20.402 +            if (ex instanceof LinkageError)
  20.403 +                throw (LinkageError) ex;
  20.404 +            else
  20.405 +                throw new LinkageError(ex.getMessage(), ex);
  20.406 +        }
  20.407 +        throw new LinkageError("no such method "+defc.getName()+"."+name+type);
  20.408 +    }
  20.409 +    private static MethodType fixMethodType(Class<?> callerClass, Object type) {
  20.410 +        if (type instanceof MethodType)
  20.411 +            return (MethodType) type;
  20.412 +        else
  20.413 +            return MethodType.fromMethodDescriptorString((String)type, callerClass.getClassLoader());
  20.414 +    }
  20.415 +    // Tracing logic:
  20.416 +    static MemberName linkMethodTracing(Class<?> callerClass, int refKind,
  20.417 +                                        Class<?> defc, String name, Object type,
  20.418 +                                        Object[] appendixResult) {
  20.419 +        System.out.println("linkMethod "+defc.getName()+"."+
  20.420 +                           name+type+"/"+Integer.toHexString(refKind));
  20.421 +        try {
  20.422 +            MemberName res = linkMethodImpl(callerClass, refKind, defc, name, type, appendixResult);
  20.423 +            System.out.println("linkMethod => "+res+" + "+appendixResult[0]);
  20.424 +            return res;
  20.425 +        } catch (Throwable ex) {
  20.426 +            System.out.println("linkMethod => throw "+ex);
  20.427 +            throw ex;
  20.428 +        }
  20.429 +    }
  20.430 +
  20.431 +
  20.432 +    /**
  20.433 +     * The JVM is resolving a CONSTANT_MethodHandle CP entry.  And it wants our help.
  20.434 +     * It will make an up-call to this method.  (Do not change the name or signature.)
  20.435 +     * The type argument is a Class for field requests and a MethodType for non-fields.
  20.436 +     * <p>
  20.437 +     * Recent versions of the JVM may also pass a resolved MemberName for the type.
  20.438 +     * In that case, the name is ignored and may be null.
  20.439 +     */
  20.440 +    static MethodHandle linkMethodHandleConstant(Class<?> callerClass, int refKind,
  20.441 +                                                 Class<?> defc, String name, Object type) {
  20.442 +        try {
  20.443 +            Lookup lookup = IMPL_LOOKUP.in(callerClass);
  20.444 +            assert(refKindIsValid(refKind));
  20.445 +            return lookup.linkMethodHandleConstant((byte) refKind, defc, name, type);
  20.446 +        } catch (IllegalAccessException ex) {
  20.447 +            Throwable cause = ex.getCause();
  20.448 +            if (cause instanceof AbstractMethodError) {
  20.449 +                throw (AbstractMethodError) cause;
  20.450 +            } else {
  20.451 +                Error err = new IllegalAccessError(ex.getMessage());
  20.452 +                throw initCauseFrom(err, ex);
  20.453 +            }
  20.454 +        } catch (NoSuchMethodException ex) {
  20.455 +            Error err = new NoSuchMethodError(ex.getMessage());
  20.456 +            throw initCauseFrom(err, ex);
  20.457 +        } catch (NoSuchFieldException ex) {
  20.458 +            Error err = new NoSuchFieldError(ex.getMessage());
  20.459 +            throw initCauseFrom(err, ex);
  20.460 +        } catch (ReflectiveOperationException ex) {
  20.461 +            Error err = new IncompatibleClassChangeError();
  20.462 +            throw initCauseFrom(err, ex);
  20.463 +        }
  20.464 +    }
  20.465 +
  20.466 +    /**
  20.467 +     * Use best possible cause for err.initCause(), substituting the
  20.468 +     * cause for err itself if the cause has the same (or better) type.
  20.469 +     */
  20.470 +    static private Error initCauseFrom(Error err, Exception ex) {
  20.471 +        Throwable th = ex.getCause();
  20.472 +        if (err.getClass().isInstance(th))
  20.473 +           return (Error) th;
  20.474 +        err.initCause(th == null ? ex : th);
  20.475 +        return err;
  20.476 +    }
  20.477 +
  20.478 +    /**
  20.479 +     * Is this method a caller-sensitive method?
  20.480 +     * I.e., does it call Reflection.getCallerClass or a similer method
  20.481 +     * to ask about the identity of its caller?
  20.482 +     */
  20.483 +    static boolean isCallerSensitive(MemberName mem) {
  20.484 +        if (!mem.isInvocable())  return false;  // fields are not caller sensitive
  20.485 +
  20.486 +        return mem.isCallerSensitive() || canBeCalledVirtual(mem);
  20.487 +    }
  20.488 +
  20.489 +    static boolean canBeCalledVirtual(MemberName mem) {
  20.490 +        assert(mem.isInvocable());
  20.491 +        Class<?> defc = mem.getDeclaringClass();
  20.492 +        switch (mem.getName()) {
  20.493 +        case "checkMemberAccess":
  20.494 +            return canBeCalledVirtual(mem, java.lang.SecurityManager.class);
  20.495 +        case "getContextClassLoader":
  20.496 +            return canBeCalledVirtual(mem, java.lang.Thread.class);
  20.497 +        }
  20.498 +        return false;
  20.499 +    }
  20.500 +
  20.501 +    static boolean canBeCalledVirtual(MemberName symbolicRef, Class<?> definingClass) {
  20.502 +        Class<?> symbolicRefClass = symbolicRef.getDeclaringClass();
  20.503 +        if (symbolicRefClass == definingClass)  return true;
  20.504 +        if (symbolicRef.isStatic() || symbolicRef.isPrivate())  return false;
  20.505 +        return (definingClass.isAssignableFrom(symbolicRefClass) ||  // Msym overrides Mdef
  20.506 +                symbolicRefClass.isInterface());                     // Mdef implements Msym
  20.507 +    }
  20.508 +}
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/MethodHandleProxies.java	Sat Aug 09 11:12:05 2014 +0200
    21.3 @@ -0,0 +1,321 @@
    21.4 +/*
    21.5 + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
    21.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    21.7 + *
    21.8 + * This code is free software; you can redistribute it and/or modify it
    21.9 + * under the terms of the GNU General Public License version 2 only, as
   21.10 + * published by the Free Software Foundation.  Oracle designates this
   21.11 + * particular file as subject to the "Classpath" exception as provided
   21.12 + * by Oracle in the LICENSE file that accompanied this code.
   21.13 + *
   21.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   21.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   21.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   21.17 + * version 2 for more details (a copy is included in the LICENSE file that
   21.18 + * accompanied this code).
   21.19 + *
   21.20 + * You should have received a copy of the GNU General Public License version
   21.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   21.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   21.23 + *
   21.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   21.25 + * or visit www.oracle.com if you need additional information or have any
   21.26 + * questions.
   21.27 + */
   21.28 +
   21.29 +package java.lang.invoke;
   21.30 +
   21.31 +import java.lang.reflect.*;
   21.32 +import java.security.AccessController;
   21.33 +import java.security.PrivilegedAction;
   21.34 +import sun.invoke.WrapperInstance;
   21.35 +import java.util.ArrayList;
   21.36 +import sun.reflect.CallerSensitive;
   21.37 +import sun.reflect.Reflection;
   21.38 +import sun.reflect.misc.ReflectUtil;
   21.39 +
   21.40 +/**
   21.41 + * This class consists exclusively of static methods that help adapt
   21.42 + * method handles to other JVM types, such as interfaces.
   21.43 + */
   21.44 +public class MethodHandleProxies {
   21.45 +
   21.46 +    private MethodHandleProxies() { }  // do not instantiate
   21.47 +
   21.48 +    /**
   21.49 +     * Produces an instance of the given single-method interface which redirects
   21.50 +     * its calls to the given method handle.
   21.51 +     * <p>
   21.52 +     * A single-method interface is an interface which declares a uniquely named method.
   21.53 +     * When determining the uniquely named method of a single-method interface,
   21.54 +     * the public {@code Object} methods ({@code toString}, {@code equals}, {@code hashCode})
   21.55 +     * are disregarded.  For example, {@link java.util.Comparator} is a single-method interface,
   21.56 +     * even though it re-declares the {@code Object.equals} method.
   21.57 +     * <p>
   21.58 +     * The interface must be public.  No additional access checks are performed.
   21.59 +     * <p>
   21.60 +     * The resulting instance of the required type will respond to
   21.61 +     * invocation of the type's uniquely named method by calling
   21.62 +     * the given target on the incoming arguments,
   21.63 +     * and returning or throwing whatever the target
   21.64 +     * returns or throws.  The invocation will be as if by
   21.65 +     * {@code target.invoke}.
   21.66 +     * The target's type will be checked before the
   21.67 +     * instance is created, as if by a call to {@code asType},
   21.68 +     * which may result in a {@code WrongMethodTypeException}.
   21.69 +     * <p>
   21.70 +     * The uniquely named method is allowed to be multiply declared,
   21.71 +     * with distinct type descriptors.  (E.g., it can be overloaded,
   21.72 +     * or can possess bridge methods.)  All such declarations are
   21.73 +     * connected directly to the target method handle.
   21.74 +     * Argument and return types are adjusted by {@code asType}
   21.75 +     * for each individual declaration.
   21.76 +     * <p>
   21.77 +     * The wrapper instance will implement the requested interface
   21.78 +     * and its super-types, but no other single-method interfaces.
   21.79 +     * This means that the instance will not unexpectedly
   21.80 +     * pass an {@code instanceof} test for any unrequested type.
   21.81 +     * <p style="font-size:smaller;">
   21.82 +     * <em>Implementation Note:</em>
   21.83 +     * Therefore, each instance must implement a unique single-method interface.
   21.84 +     * Implementations may not bundle together
   21.85 +     * multiple single-method interfaces onto single implementation classes
   21.86 +     * in the style of {@link java.awt.AWTEventMulticaster}.
   21.87 +     * <p>
   21.88 +     * The method handle may throw an <em>undeclared exception</em>,
   21.89 +     * which means any checked exception (or other checked throwable)
   21.90 +     * not declared by the requested type's single abstract method.
   21.91 +     * If this happens, the throwable will be wrapped in an instance of
   21.92 +     * {@link java.lang.reflect.UndeclaredThrowableException UndeclaredThrowableException}
   21.93 +     * and thrown in that wrapped form.
   21.94 +     * <p>
   21.95 +     * Like {@link java.lang.Integer#valueOf Integer.valueOf},
   21.96 +     * {@code asInterfaceInstance} is a factory method whose results are defined
   21.97 +     * by their behavior.
   21.98 +     * It is not guaranteed to return a new instance for every call.
   21.99 +     * <p>
  21.100 +     * Because of the possibility of {@linkplain java.lang.reflect.Method#isBridge bridge methods}
  21.101 +     * and other corner cases, the interface may also have several abstract methods
  21.102 +     * with the same name but having distinct descriptors (types of returns and parameters).
  21.103 +     * In this case, all the methods are bound in common to the one given target.
  21.104 +     * The type check and effective {@code asType} conversion is applied to each
  21.105 +     * method type descriptor, and all abstract methods are bound to the target in common.
  21.106 +     * Beyond this type check, no further checks are made to determine that the
  21.107 +     * abstract methods are related in any way.
  21.108 +     * <p>
  21.109 +     * Future versions of this API may accept additional types,
  21.110 +     * such as abstract classes with single abstract methods.
  21.111 +     * Future versions of this API may also equip wrapper instances
  21.112 +     * with one or more additional public "marker" interfaces.
  21.113 +     * <p>
  21.114 +     * If a security manager is installed, this method is caller sensitive.
  21.115 +     * During any invocation of the target method handle via the returned wrapper,
  21.116 +     * the original creator of the wrapper (the caller) will be visible
  21.117 +     * to context checks requested by the security manager.
  21.118 +     *
  21.119 +     * @param <T> the desired type of the wrapper, a single-method interface
  21.120 +     * @param intfc a class object representing {@code T}
  21.121 +     * @param target the method handle to invoke from the wrapper
  21.122 +     * @return a correctly-typed wrapper for the given target
  21.123 +     * @throws NullPointerException if either argument is null
  21.124 +     * @throws IllegalArgumentException if the {@code intfc} is not a
  21.125 +     *         valid argument to this method
  21.126 +     * @throws WrongMethodTypeException if the target cannot
  21.127 +     *         be converted to the type required by the requested interface
  21.128 +     */
  21.129 +    // Other notes to implementors:
  21.130 +    // <p>
  21.131 +    // No stable mapping is promised between the single-method interface and
  21.132 +    // the implementation class C.  Over time, several implementation
  21.133 +    // classes might be used for the same type.
  21.134 +    // <p>
  21.135 +    // If the implementation is able
  21.136 +    // to prove that a wrapper of the required type
  21.137 +    // has already been created for a given
  21.138 +    // method handle, or for another method handle with the
  21.139 +    // same behavior, the implementation may return that wrapper in place of
  21.140 +    // a new wrapper.
  21.141 +    // <p>
  21.142 +    // This method is designed to apply to common use cases
  21.143 +    // where a single method handle must interoperate with
  21.144 +    // an interface that implements a function-like
  21.145 +    // API.  Additional variations, such as single-abstract-method classes with
  21.146 +    // private constructors, or interfaces with multiple but related
  21.147 +    // entry points, must be covered by hand-written or automatically
  21.148 +    // generated adapter classes.
  21.149 +    //
  21.150 +    @CallerSensitive
  21.151 +    public static
  21.152 +    <T> T asInterfaceInstance(final Class<T> intfc, final MethodHandle target) {
  21.153 +        if (!intfc.isInterface() || !Modifier.isPublic(intfc.getModifiers()))
  21.154 +            throw new IllegalArgumentException("not a public interface: "+intfc.getName());
  21.155 +        final MethodHandle mh;
  21.156 +        if (System.getSecurityManager() != null) {
  21.157 +            final Class<?> caller = Reflection.getCallerClass();
  21.158 +            final ClassLoader ccl = caller != null ? caller.getClassLoader() : null;
  21.159 +            ReflectUtil.checkProxyPackageAccess(ccl, intfc);
  21.160 +            mh = ccl != null ? bindCaller(target, caller) : target;
  21.161 +        } else {
  21.162 +            mh = target;
  21.163 +        }
  21.164 +        ClassLoader proxyLoader = intfc.getClassLoader();
  21.165 +        if (proxyLoader == null) {
  21.166 +            ClassLoader cl = Thread.currentThread().getContextClassLoader(); // avoid use of BCP
  21.167 +            proxyLoader = cl != null ? cl : ClassLoader.getSystemClassLoader();
  21.168 +        }
  21.169 +        final Method[] methods = getSingleNameMethods(intfc);
  21.170 +        if (methods == null)
  21.171 +            throw new IllegalArgumentException("not a single-method interface: "+intfc.getName());
  21.172 +        final MethodHandle[] vaTargets = new MethodHandle[methods.length];
  21.173 +        for (int i = 0; i < methods.length; i++) {
  21.174 +            Method sm = methods[i];
  21.175 +            MethodType smMT = MethodType.methodType(sm.getReturnType(), sm.getParameterTypes());
  21.176 +            MethodHandle checkTarget = mh.asType(smMT);  // make throw WMT
  21.177 +            checkTarget = checkTarget.asType(checkTarget.type().changeReturnType(Object.class));
  21.178 +            vaTargets[i] = checkTarget.asSpreader(Object[].class, smMT.parameterCount());
  21.179 +        }
  21.180 +        final InvocationHandler ih = new InvocationHandler() {
  21.181 +                private Object getArg(String name) {
  21.182 +                    if ((Object)name == "getWrapperInstanceTarget")  return target;
  21.183 +                    if ((Object)name == "getWrapperInstanceType")    return intfc;
  21.184 +                    throw new AssertionError();
  21.185 +                }
  21.186 +                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  21.187 +                    for (int i = 0; i < methods.length; i++) {
  21.188 +                        if (method.equals(methods[i]))
  21.189 +                            return vaTargets[i].invokeExact(args);
  21.190 +                    }
  21.191 +                    if (method.getDeclaringClass() == WrapperInstance.class)
  21.192 +                        return getArg(method.getName());
  21.193 +                    if (isObjectMethod(method))
  21.194 +                        return callObjectMethod(proxy, method, args);
  21.195 +                    throw new InternalError("bad proxy method: "+method);
  21.196 +                }
  21.197 +            };
  21.198 +
  21.199 +        final Object proxy;
  21.200 +        if (System.getSecurityManager() != null) {
  21.201 +            // sun.invoke.WrapperInstance is a restricted interface not accessible
  21.202 +            // by any non-null class loader.
  21.203 +            final ClassLoader loader = proxyLoader;
  21.204 +            proxy = AccessController.doPrivileged(new PrivilegedAction<Object>() {
  21.205 +                public Object run() {
  21.206 +                    return Proxy.newProxyInstance(
  21.207 +                            loader,
  21.208 +                            new Class<?>[]{ intfc, WrapperInstance.class },
  21.209 +                            ih);
  21.210 +                }
  21.211 +            });
  21.212 +        } else {
  21.213 +            proxy = Proxy.newProxyInstance(proxyLoader,
  21.214 +                                           new Class<?>[]{ intfc, WrapperInstance.class },
  21.215 +                                           ih);
  21.216 +        }
  21.217 +        return intfc.cast(proxy);
  21.218 +    }
  21.219 +
  21.220 +    private static MethodHandle bindCaller(MethodHandle target, Class<?> hostClass) {
  21.221 +        MethodHandle cbmh = MethodHandleImpl.bindCaller(target, hostClass);
  21.222 +        if (target.isVarargsCollector()) {
  21.223 +            MethodType type = cbmh.type();
  21.224 +            int arity = type.parameterCount();
  21.225 +            return cbmh.asVarargsCollector(type.parameterType(arity-1));
  21.226 +        }
  21.227 +        return cbmh;
  21.228 +    }
  21.229 +
  21.230 +    /**
  21.231 +     * Determines if the given object was produced by a call to {@link #asInterfaceInstance asInterfaceInstance}.
  21.232 +     * @param x any reference
  21.233 +     * @return true if the reference is not null and points to an object produced by {@code asInterfaceInstance}
  21.234 +     */
  21.235 +    public static
  21.236 +    boolean isWrapperInstance(Object x) {
  21.237 +        return x instanceof WrapperInstance;
  21.238 +    }
  21.239 +
  21.240 +    private static WrapperInstance asWrapperInstance(Object x) {
  21.241 +        try {
  21.242 +            if (x != null)
  21.243 +                return (WrapperInstance) x;
  21.244 +        } catch (ClassCastException ex) {
  21.245 +        }
  21.246 +        throw new IllegalArgumentException("not a wrapper instance");
  21.247 +    }
  21.248 +
  21.249 +    /**
  21.250 +     * Produces or recovers a target method handle which is behaviorally
  21.251 +     * equivalent to the unique method of this wrapper instance.
  21.252 +     * The object {@code x} must have been produced by a call to {@link #asInterfaceInstance asInterfaceInstance}.
  21.253 +     * This requirement may be tested via {@link #isWrapperInstance isWrapperInstance}.
  21.254 +     * @param x any reference
  21.255 +     * @return a method handle implementing the unique method
  21.256 +     * @throws IllegalArgumentException if the reference x is not to a wrapper instance
  21.257 +     */
  21.258 +    public static
  21.259 +    MethodHandle wrapperInstanceTarget(Object x) {
  21.260 +        return asWrapperInstance(x).getWrapperInstanceTarget();
  21.261 +    }
  21.262 +
  21.263 +    /**
  21.264 +     * Recovers the unique single-method interface type for which this wrapper instance was created.
  21.265 +     * The object {@code x} must have been produced by a call to {@link #asInterfaceInstance asInterfaceInstance}.
  21.266 +     * This requirement may be tested via {@link #isWrapperInstance isWrapperInstance}.
  21.267 +     * @param x any reference
  21.268 +     * @return the single-method interface type for which the wrapper was created
  21.269 +     * @throws IllegalArgumentException if the reference x is not to a wrapper instance
  21.270 +     */
  21.271 +    public static
  21.272 +    Class<?> wrapperInstanceType(Object x) {
  21.273 +        return asWrapperInstance(x).getWrapperInstanceType();
  21.274 +    }
  21.275 +
  21.276 +    private static
  21.277 +    boolean isObjectMethod(Method m) {
  21.278 +        switch (m.getName()) {
  21.279 +        case "toString":
  21.280 +            return (m.getReturnType() == String.class
  21.281 +                    && m.getParameterTypes().length == 0);
  21.282 +        case "hashCode":
  21.283 +            return (m.getReturnType() == int.class
  21.284 +                    && m.getParameterTypes().length == 0);
  21.285 +        case "equals":
  21.286 +            return (m.getReturnType() == boolean.class
  21.287 +                    && m.getParameterTypes().length == 1
  21.288 +                    && m.getParameterTypes()[0] == Object.class);
  21.289 +        }
  21.290 +        return false;
  21.291 +    }
  21.292 +
  21.293 +    private static
  21.294 +    Object callObjectMethod(Object self, Method m, Object[] args) {
  21.295 +        assert(isObjectMethod(m)) : m;
  21.296 +        switch (m.getName()) {
  21.297 +        case "toString":
  21.298 +            return self.getClass().getName() + "@" + Integer.toHexString(self.hashCode());
  21.299 +        case "hashCode":
  21.300 +            return System.identityHashCode(self);
  21.301 +        case "equals":
  21.302 +            return (self == args[0]);
  21.303 +        }
  21.304 +        return null;
  21.305 +    }
  21.306 +
  21.307 +    private static
  21.308 +    Method[] getSingleNameMethods(Class<?> intfc) {
  21.309 +        ArrayList<Method> methods = new ArrayList<Method>();
  21.310 +        String uniqueName = null;
  21.311 +        for (Method m : intfc.getMethods()) {
  21.312 +            if (isObjectMethod(m))  continue;
  21.313 +            if (!Modifier.isAbstract(m.getModifiers()))  continue;
  21.314 +            String mname = m.getName();
  21.315 +            if (uniqueName == null)
  21.316 +                uniqueName = mname;
  21.317 +            else if (!uniqueName.equals(mname))
  21.318 +                return null;  // too many abstract methods
  21.319 +            methods.add(m);
  21.320 +        }
  21.321 +        if (uniqueName == null)  return null;
  21.322 +        return methods.toArray(new Method[methods.size()]);
  21.323 +    }
  21.324 +}
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/MethodHandleStatics.java	Sat Aug 09 11:12:05 2014 +0200
    22.3 @@ -0,0 +1,131 @@
    22.4 +/*
    22.5 + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
    22.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    22.7 + *
    22.8 + * This code is free software; you can redistribute it and/or modify it
    22.9 + * under the terms of the GNU General Public License version 2 only, as
   22.10 + * published by the Free Software Foundation.  Oracle designates this
   22.11 + * particular file as subject to the "Classpath" exception as provided
   22.12 + * by Oracle in the LICENSE file that accompanied this code.
   22.13 + *
   22.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   22.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   22.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   22.17 + * version 2 for more details (a copy is included in the LICENSE file that
   22.18 + * accompanied this code).
   22.19 + *
   22.20 + * You should have received a copy of the GNU General Public License version
   22.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   22.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   22.23 + *
   22.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22.25 + * or visit www.oracle.com if you need additional information or have any
   22.26 + * questions.
   22.27 + */
   22.28 +
   22.29 +package java.lang.invoke;
   22.30 +
   22.31 +import java.security.AccessController;
   22.32 +import java.security.PrivilegedAction;
   22.33 +import sun.misc.Unsafe;
   22.34 +
   22.35 +/**
   22.36 + * This class consists exclusively of static names internal to the
   22.37 + * method handle implementation.
   22.38 + * Usage:  {@code import static java.lang.invoke.MethodHandleStatics.*}
   22.39 + * @author John Rose, JSR 292 EG
   22.40 + */
   22.41 +/*non-public*/ class MethodHandleStatics {
   22.42 +
   22.43 +    private MethodHandleStatics() { }  // do not instantiate
   22.44 +
   22.45 +    static final Unsafe UNSAFE = Unsafe.getUnsafe();
   22.46 +
   22.47 +    static final boolean DEBUG_METHOD_HANDLE_NAMES;
   22.48 +    static final boolean DUMP_CLASS_FILES;
   22.49 +    static final boolean TRACE_INTERPRETER;
   22.50 +    static final boolean TRACE_METHOD_LINKAGE;
   22.51 +    static final Integer COMPILE_THRESHOLD;
   22.52 +    static {
   22.53 +        final Object[] values = { false, false, false, false, null };
   22.54 +        AccessController.doPrivileged(new PrivilegedAction<Void>() {
   22.55 +                public Void run() {
   22.56 +                    values[0] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DEBUG_NAMES");
   22.57 +                    values[1] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DUMP_CLASS_FILES");
   22.58 +                    values[2] = Boolean.getBoolean("java.lang.invoke.MethodHandle.TRACE_INTERPRETER");
   22.59 +                    values[3] = Boolean.getBoolean("java.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE");
   22.60 +                    values[4] = Integer.getInteger("java.lang.invoke.MethodHandle.COMPILE_THRESHOLD");
   22.61 +                    return null;
   22.62 +                }
   22.63 +            });
   22.64 +        DEBUG_METHOD_HANDLE_NAMES = (Boolean) values[0];
   22.65 +        DUMP_CLASS_FILES          = (Boolean) values[1];
   22.66 +        TRACE_INTERPRETER         = (Boolean) values[2];
   22.67 +        TRACE_METHOD_LINKAGE      = (Boolean) values[3];
   22.68 +        COMPILE_THRESHOLD         = (Integer) values[4];
   22.69 +    }
   22.70 +
   22.71 +    /*non-public*/ static String getNameString(MethodHandle target, MethodType type) {
   22.72 +        if (type == null)
   22.73 +            type = target.type();
   22.74 +        MemberName name = null;
   22.75 +        if (target != null)
   22.76 +            name = target.internalMemberName();
   22.77 +        if (name == null)
   22.78 +            return "invoke" + type;
   22.79 +        return name.getName() + type;
   22.80 +    }
   22.81 +
   22.82 +    /*non-public*/ static String getNameString(MethodHandle target, MethodHandle typeHolder) {
   22.83 +        return getNameString(target, typeHolder == null ? (MethodType) null : typeHolder.type());
   22.84 +    }
   22.85 +
   22.86 +    /*non-public*/ static String getNameString(MethodHandle target) {
   22.87 +        return getNameString(target, (MethodType) null);
   22.88 +    }
   22.89 +
   22.90 +    /*non-public*/ static String addTypeString(Object obj, MethodHandle target) {
   22.91 +        String str = String.valueOf(obj);
   22.92 +        if (target == null)  return str;
   22.93 +        int paren = str.indexOf('(');
   22.94 +        if (paren >= 0) str = str.substring(0, paren);
   22.95 +        return str + target.type();
   22.96 +    }
   22.97 +
   22.98 +    // handy shared exception makers (they simplify the common case code)
   22.99 +    /*non-public*/ static InternalError newInternalError(String message, Throwable cause) {
  22.100 +        return new InternalError(message, cause);
  22.101 +    }
  22.102 +    /*non-public*/ static InternalError newInternalError(Throwable cause) {
  22.103 +        return new InternalError(cause);
  22.104 +    }
  22.105 +    /*non-public*/ static RuntimeException newIllegalStateException(String message) {
  22.106 +        return new IllegalStateException(message);
  22.107 +    }
  22.108 +    /*non-public*/ static RuntimeException newIllegalStateException(String message, Object obj) {
  22.109 +        return new IllegalStateException(message(message, obj));
  22.110 +    }
  22.111 +    /*non-public*/ static RuntimeException newIllegalArgumentException(String message) {
  22.112 +        return new IllegalArgumentException(message);
  22.113 +    }
  22.114 +    /*non-public*/ static RuntimeException newIllegalArgumentException(String message, Object obj) {
  22.115 +        return new IllegalArgumentException(message(message, obj));
  22.116 +    }
  22.117 +    /*non-public*/ static RuntimeException newIllegalArgumentException(String message, Object obj, Object obj2) {
  22.118 +        return new IllegalArgumentException(message(message, obj, obj2));
  22.119 +    }
  22.120 +    /*non-public*/ static Error uncaughtException(Throwable ex) {
  22.121 +        throw newInternalError("uncaught exception", ex);
  22.122 +    }
  22.123 +    static Error NYI() {
  22.124 +        throw new AssertionError("NYI");
  22.125 +    }
  22.126 +    private static String message(String message, Object obj) {
  22.127 +        if (obj != null)  message = message + ": " + obj;
  22.128 +        return message;
  22.129 +    }
  22.130 +    private static String message(String message, Object obj, Object obj2) {
  22.131 +        if (obj != null || obj2 != null)  message = message + ": " + obj + ", " + obj2;
  22.132 +        return message;
  22.133 +    }
  22.134 +}
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/MethodHandles.java	Sat Aug 09 11:12:05 2014 +0200
    23.3 @@ -0,0 +1,2848 @@
    23.4 +/*
    23.5 + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
    23.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    23.7 + *
    23.8 + * This code is free software; you can redistribute it and/or modify it
    23.9 + * under the terms of the GNU General Public License version 2 only, as
   23.10 + * published by the Free Software Foundation.  Oracle designates this
   23.11 + * particular file as subject to the "Classpath" exception as provided
   23.12 + * by Oracle in the LICENSE file that accompanied this code.
   23.13 + *
   23.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   23.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   23.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   23.17 + * version 2 for more details (a copy is included in the LICENSE file that
   23.18 + * accompanied this code).
   23.19 + *
   23.20 + * You should have received a copy of the GNU General Public License version
   23.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   23.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   23.23 + *
   23.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   23.25 + * or visit www.oracle.com if you need additional information or have any
   23.26 + * questions.
   23.27 + */
   23.28 +
   23.29 +package java.lang.invoke;
   23.30 +
   23.31 +import java.lang.reflect.*;
   23.32 +import java.util.List;
   23.33 +import java.util.ArrayList;
   23.34 +import java.util.Arrays;
   23.35 +
   23.36 +import sun.invoke.util.ValueConversions;
   23.37 +import sun.invoke.util.VerifyAccess;
   23.38 +import sun.invoke.util.Wrapper;
   23.39 +import sun.reflect.CallerSensitive;
   23.40 +import sun.reflect.Reflection;
   23.41 +import sun.reflect.misc.ReflectUtil;
   23.42 +import sun.security.util.SecurityConstants;
   23.43 +import static java.lang.invoke.MethodHandleStatics.*;
   23.44 +import static java.lang.invoke.MethodHandleNatives.Constants.*;
   23.45 +import java.util.concurrent.ConcurrentHashMap;
   23.46 +import sun.security.util.SecurityConstants;
   23.47 +
   23.48 +/**
   23.49 + * This class consists exclusively of static methods that operate on or return
   23.50 + * method handles. They fall into several categories:
   23.51 + * <ul>
   23.52 + * <li>Lookup methods which help create method handles for methods and fields.
   23.53 + * <li>Combinator methods, which combine or transform pre-existing method handles into new ones.
   23.54 + * <li>Other factory methods to create method handles that emulate other common JVM operations or control flow patterns.
   23.55 + * </ul>
   23.56 + * <p>
   23.57 + * @author John Rose, JSR 292 EG
   23.58 + * @since 1.7
   23.59 + */
   23.60 +public class MethodHandles {
   23.61 +
   23.62 +    private MethodHandles() { }  // do not instantiate
   23.63 +
   23.64 +    private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
   23.65 +    static { MethodHandleImpl.initStatics(); }
   23.66 +    // See IMPL_LOOKUP below.
   23.67 +
   23.68 +    //// Method handle creation from ordinary methods.
   23.69 +
   23.70 +    /**
   23.71 +     * Returns a {@link Lookup lookup object} with
   23.72 +     * full capabilities to emulate all supported bytecode behaviors of the caller.
   23.73 +     * These capabilities include <a href="MethodHandles.Lookup.html#privacc">private access</a> to the caller.
   23.74 +     * Factory methods on the lookup object can create
   23.75 +     * <a href="MethodHandleInfo.html#directmh">direct method handles</a>
   23.76 +     * for any member that the caller has access to via bytecodes,
   23.77 +     * including protected and private fields and methods.
   23.78 +     * This lookup object is a <em>capability</em> which may be delegated to trusted agents.
   23.79 +     * Do not store it in place where untrusted code can access it.
   23.80 +     * <p>
   23.81 +     * This method is caller sensitive, which means that it may return different
   23.82 +     * values to different callers.
   23.83 +     * <p>
   23.84 +     * For any given caller class {@code C}, the lookup object returned by this call
   23.85 +     * has equivalent capabilities to any lookup object
   23.86 +     * supplied by the JVM to the bootstrap method of an
   23.87 +     * <a href="package-summary.html#indyinsn">invokedynamic instruction</a>
   23.88 +     * executing in the same caller class {@code C}.
   23.89 +     * @return a lookup object for the caller of this method, with private access
   23.90 +     */
   23.91 +    @CallerSensitive
   23.92 +    public static Lookup lookup() {
   23.93 +        return new Lookup(Reflection.getCallerClass());
   23.94 +    }
   23.95 +
   23.96 +    /**
   23.97 +     * Returns a {@link Lookup lookup object} which is trusted minimally.
   23.98 +     * It can only be used to create method handles to
   23.99 +     * publicly accessible fields and methods.
  23.100 +     * <p>
  23.101 +     * As a matter of pure convention, the {@linkplain Lookup#lookupClass lookup class}
  23.102 +     * of this lookup object will be {@link java.lang.Object}.
  23.103 +     *
  23.104 +     * <p style="font-size:smaller;">
  23.105 +     * <em>Discussion:</em>
  23.106 +     * The lookup class can be changed to any other class {@code C} using an expression of the form
  23.107 +     * {@link Lookup#in publicLookup().in(C.class)}.
  23.108 +     * Since all classes have equal access to public names,
  23.109 +     * such a change would confer no new access rights.
  23.110 +     * A public lookup object is always subject to
  23.111 +     * <a href="MethodHandles.Lookup.html#secmgr">security manager checks</a>.
  23.112 +     * Also, it cannot access
  23.113 +     * <a href="MethodHandles.Lookup.html#callsens">caller sensitive methods</a>.
  23.114 +     * @return a lookup object which is trusted minimally
  23.115 +     */
  23.116 +    public static Lookup publicLookup() {
  23.117 +        return Lookup.PUBLIC_LOOKUP;
  23.118 +    }
  23.119 +
  23.120 +    /**
  23.121 +     * Performs an unchecked "crack" of a
  23.122 +     * <a href="MethodHandleInfo.html#directmh">direct method handle</a>.
  23.123 +     * The result is as if the user had obtained a lookup object capable enough
  23.124 +     * to crack the target method handle, called
  23.125 +     * {@link java.lang.invoke.MethodHandles.Lookup#revealDirect Lookup.revealDirect}
  23.126 +     * on the target to obtain its symbolic reference, and then called
  23.127 +     * {@link java.lang.invoke.MethodHandleInfo#reflectAs MethodHandleInfo.reflectAs}
  23.128 +     * to resolve the symbolic reference to a member.
  23.129 +     * <p>
  23.130 +     * If there is a security manager, its {@code checkPermission} method
  23.131 +     * is called with a {@code ReflectPermission("suppressAccessChecks")} permission.
  23.132 +     * @param <T> the desired type of the result, either {@link Member} or a subtype
  23.133 +     * @param target a direct method handle to crack into symbolic reference components
  23.134 +     * @param expected a class object representing the desired result type {@code T}
  23.135 +     * @return a reference to the method, constructor, or field object
  23.136 +     * @exception SecurityException if the caller is not privileged to call {@code setAccessible}
  23.137 +     * @exception NullPointerException if either argument is {@code null}
  23.138 +     * @exception IllegalArgumentException if the target is not a direct method handle
  23.139 +     * @exception ClassCastException if the member is not of the expected type
  23.140 +     * @since 1.8
  23.141 +     */
  23.142 +    public static <T extends Member> T
  23.143 +    reflectAs(Class<T> expected, MethodHandle target) {
  23.144 +        SecurityManager smgr = System.getSecurityManager();
  23.145 +        if (smgr != null)  smgr.checkPermission(ACCESS_PERMISSION);
  23.146 +        Lookup lookup = Lookup.IMPL_LOOKUP;  // use maximally privileged lookup
  23.147 +        return lookup.revealDirect(target).reflectAs(expected, lookup);
  23.148 +    }
  23.149 +    // Copied from AccessibleObject, as used by Method.setAccessible, etc.:
  23.150 +    static final private java.security.Permission ACCESS_PERMISSION =
  23.151 +        new ReflectPermission("suppressAccessChecks");
  23.152 +
  23.153 +    /**
  23.154 +     * A <em>lookup object</em> is a factory for creating method handles,
  23.155 +     * when the creation requires access checking.
  23.156 +     * Method handles do not perform
  23.157 +     * access checks when they are called, but rather when they are created.
  23.158 +     * Therefore, method handle access
  23.159 +     * restrictions must be enforced when a method handle is created.
  23.160 +     * The caller class against which those restrictions are enforced
  23.161 +     * is known as the {@linkplain #lookupClass lookup class}.
  23.162 +     * <p>
  23.163 +     * A lookup class which needs to create method handles will call
  23.164 +     * {@link MethodHandles#lookup MethodHandles.lookup} to create a factory for itself.
  23.165 +     * When the {@code Lookup} factory object is created, the identity of the lookup class is
  23.166 +     * determined, and securely stored in the {@code Lookup} object.
  23.167 +     * The lookup class (or its delegates) may then use factory methods
  23.168 +     * on the {@code Lookup} object to create method handles for access-checked members.
  23.169 +     * This includes all methods, constructors, and fields which are allowed to the lookup class,
  23.170 +     * even private ones.
  23.171 +     *
  23.172 +     * <h1><a name="lookups"></a>Lookup Factory Methods</h1>
  23.173 +     * The factory methods on a {@code Lookup} object correspond to all major
  23.174 +     * use cases for methods, constructors, and fields.
  23.175 +     * Each method handle created by a factory method is the functional
  23.176 +     * equivalent of a particular <em>bytecode behavior</em>.
  23.177 +     * (Bytecode behaviors are described in section 5.4.3.5 of the Java Virtual Machine Specification.)
  23.178 +     * Here is a summary of the correspondence between these factory methods and
  23.179 +     * the behavior the resulting method handles:
  23.180 +     * <table border=1 cellpadding=5 summary="lookup method behaviors">
  23.181 +     * <tr>
  23.182 +     *     <th><a name="equiv"></a>lookup expression</th>
  23.183 +     *     <th>member</th>
  23.184 +     *     <th>bytecode behavior</th>
  23.185 +     * </tr>
  23.186 +     * <tr>
  23.187 +     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findGetter lookup.findGetter(C.class,"f",FT.class)}</td>
  23.188 +     *     <td>{@code FT f;}</td><td>{@code (T) this.f;}</td>
  23.189 +     * </tr>
  23.190 +     * <tr>
  23.191 +     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findStaticGetter lookup.findStaticGetter(C.class,"f",FT.class)}</td>
  23.192 +     *     <td>{@code static}<br>{@code FT f;}</td><td>{@code (T) C.f;}</td>
  23.193 +     * </tr>
  23.194 +     * <tr>
  23.195 +     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findSetter lookup.findSetter(C.class,"f",FT.class)}</td>
  23.196 +     *     <td>{@code FT f;}</td><td>{@code this.f = x;}</td>
  23.197 +     * </tr>
  23.198 +     * <tr>
  23.199 +     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findStaticSetter lookup.findStaticSetter(C.class,"f",FT.class)}</td>
  23.200 +     *     <td>{@code static}<br>{@code FT f;}</td><td>{@code C.f = arg;}</td>
  23.201 +     * </tr>
  23.202 +     * <tr>
  23.203 +     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findVirtual lookup.findVirtual(C.class,"m",MT)}</td>
  23.204 +     *     <td>{@code T m(A*);}</td><td>{@code (T) this.m(arg*);}</td>
  23.205 +     * </tr>
  23.206 +     * <tr>
  23.207 +     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findStatic lookup.findStatic(C.class,"m",MT)}</td>
  23.208 +     *     <td>{@code static}<br>{@code T m(A*);}</td><td>{@code (T) C.m(arg*);}</td>
  23.209 +     * </tr>
  23.210 +     * <tr>
  23.211 +     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findSpecial lookup.findSpecial(C.class,"m",MT,this.class)}</td>
  23.212 +     *     <td>{@code T m(A*);}</td><td>{@code (T) super.m(arg*);}</td>
  23.213 +     * </tr>
  23.214 +     * <tr>
  23.215 +     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#findConstructor lookup.findConstructor(C.class,MT)}</td>
  23.216 +     *     <td>{@code C(A*);}</td><td>{@code new C(arg*);}</td>
  23.217 +     * </tr>
  23.218 +     * <tr>
  23.219 +     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflectGetter lookup.unreflectGetter(aField)}</td>
  23.220 +     *     <td>({@code static})?<br>{@code FT f;}</td><td>{@code (FT) aField.get(thisOrNull);}</td>
  23.221 +     * </tr>
  23.222 +     * <tr>
  23.223 +     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflectSetter lookup.unreflectSetter(aField)}</td>
  23.224 +     *     <td>({@code static})?<br>{@code FT f;}</td><td>{@code aField.set(thisOrNull, arg);}</td>
  23.225 +     * </tr>
  23.226 +     * <tr>
  23.227 +     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td>
  23.228 +     *     <td>({@code static})?<br>{@code T m(A*);}</td><td>{@code (T) aMethod.invoke(thisOrNull, arg*);}</td>
  23.229 +     * </tr>
  23.230 +     * <tr>
  23.231 +     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflectConstructor lookup.unreflectConstructor(aConstructor)}</td>
  23.232 +     *     <td>{@code C(A*);}</td><td>{@code (C) aConstructor.newInstance(arg*);}</td>
  23.233 +     * </tr>
  23.234 +     * <tr>
  23.235 +     *     <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td>
  23.236 +     *     <td>({@code static})?<br>{@code T m(A*);}</td><td>{@code (T) aMethod.invoke(thisOrNull, arg*);}</td>
  23.237 +     * </tr>
  23.238 +     * </table>
  23.239 +     *
  23.240 +     * Here, the type {@code C} is the class or interface being searched for a member,
  23.241 +     * documented as a parameter named {@code refc} in the lookup methods.
  23.242 +     * The method type {@code MT} is composed from the return type {@code T}
  23.243 +     * and the sequence of argument types {@code A*}.
  23.244 +     * The constructor also has a sequence of argument types {@code A*} and
  23.245 +     * is deemed to return the newly-created object of type {@code C}.
  23.246 +     * Both {@code MT} and the field type {@code FT} are documented as a parameter named {@code type}.
  23.247 +     * The formal parameter {@code this} stands for the self-reference of type {@code C};
  23.248 +     * if it is present, it is always the leading argument to the method handle invocation.
  23.249 +     * (In the case of some {@code protected} members, {@code this} may be
  23.250 +     * restricted in type to the lookup class; see below.)
  23.251 +     * The name {@code arg} stands for all the other method handle arguments.
  23.252 +     * In the code examples for the Core Reflection API, the name {@code thisOrNull}
  23.253 +     * stands for a null reference if the accessed method or field is static,
  23.254 +     * and {@code this} otherwise.
  23.255 +     * The names {@code aMethod}, {@code aField}, and {@code aConstructor} stand
  23.256 +     * for reflective objects corresponding to the given members.
  23.257 +     * <p>
  23.258 +     * In cases where the given member is of variable arity (i.e., a method or constructor)
  23.259 +     * the returned method handle will also be of {@linkplain MethodHandle#asVarargsCollector variable arity}.
  23.260 +     * In all other cases, the returned method handle will be of fixed arity.
  23.261 +     * <p style="font-size:smaller;">
  23.262 +     * <em>Discussion:</em>
  23.263 +     * The equivalence between looked-up method handles and underlying
  23.264 +     * class members and bytecode behaviors
  23.265 +     * can break down in a few ways:
  23.266 +     * <ul style="font-size:smaller;">
  23.267 +     * <li>If {@code C} is not symbolically accessible from the lookup class's loader,
  23.268 +     * the lookup can still succeed, even when there is no equivalent
  23.269 +     * Java expression or bytecoded constant.
  23.270 +     * <li>Likewise, if {@code T} or {@code MT}
  23.271 +     * is not symbolically accessible from the lookup class's loader,
  23.272 +     * the lookup can still succeed.
  23.273 +     * For example, lookups for {@code MethodHandle.invokeExact} and
  23.274 +     * {@code MethodHandle.invoke} will always succeed, regardless of requested type.
  23.275 +     * <li>If there is a security manager installed, it can forbid the lookup
  23.276 +     * on various grounds (<a href="MethodHandles.Lookup.html#secmgr">see below</a>).
  23.277 +     * By contrast, the {@code ldc} instruction on a {@code CONSTANT_MethodHandle}
  23.278 +     * constant is not subject to security manager checks.
  23.279 +     * <li>If the looked-up method has a
  23.280 +     * <a href="MethodHandle.html#maxarity">very large arity</a>,
  23.281 +     * the method handle creation may fail, due to the method handle
  23.282 +     * type having too many parameters.
  23.283 +     * </ul>
  23.284 +     *
  23.285 +     * <h1><a name="access"></a>Access checking</h1>
  23.286 +     * Access checks are applied in the factory methods of {@code Lookup},
  23.287 +     * when a method handle is created.
  23.288 +     * This is a key difference from the Core Reflection API, since
  23.289 +     * {@link java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}
  23.290 +     * performs access checking against every caller, on every call.
  23.291 +     * <p>
  23.292 +     * All access checks start from a {@code Lookup} object, which
  23.293 +     * compares its recorded lookup class against all requests to
  23.294 +     * create method handles.
  23.295 +     * A single {@code Lookup} object can be used to create any number
  23.296 +     * of access-checked method handles, all checked against a single
  23.297 +     * lookup class.
  23.298 +     * <p>
  23.299 +     * A {@code Lookup} object can be shared with other trusted code,
  23.300 +     * such as a metaobject protocol.
  23.301 +     * A shared {@code Lookup} object delegates the capability
  23.302 +     * to create method handles on private members of the lookup class.
  23.303 +     * Even if privileged code uses the {@code Lookup} object,
  23.304 +     * the access checking is confined to the privileges of the
  23.305 +     * original lookup class.
  23.306 +     * <p>
  23.307 +     * A lookup can fail, because
  23.308 +     * the containing class is not accessible to the lookup class, or
  23.309 +     * because the desired class member is missing, or because the
  23.310 +     * desired class member is not accessible to the lookup class, or
  23.311 +     * because the lookup object is not trusted enough to access the member.
  23.312 +     * In any of these cases, a {@code ReflectiveOperationException} will be
  23.313 +     * thrown from the attempted lookup.  The exact class will be one of
  23.314 +     * the following:
  23.315 +     * <ul>
  23.316 +     * <li>NoSuchMethodException &mdash; if a method is requested but does not exist
  23.317 +     * <li>NoSuchFieldException &mdash; if a field is requested but does not exist
  23.318 +     * <li>IllegalAccessException &mdash; if the member exists but an access check fails
  23.319 +     * </ul>
  23.320 +     * <p>
  23.321 +     * In general, the conditions under which a method handle may be
  23.322 +     * looked up for a method {@code M} are no more restrictive than the conditions
  23.323 +     * under which the lookup class could have compiled, verified, and resolved a call to {@code M}.
  23.324 +     * Where the JVM would raise exceptions like {@code NoSuchMethodError},
  23.325 +     * a method handle lookup will generally raise a corresponding
  23.326 +     * checked exception, such as {@code NoSuchMethodException}.
  23.327 +     * And the effect of invoking the method handle resulting from the lookup
  23.328 +     * is <a href="MethodHandles.Lookup.html#equiv">exactly equivalent</a>
  23.329 +     * to executing the compiled, verified, and resolved call to {@code M}.
  23.330 +     * The same point is true of fields and constructors.
  23.331 +     * <p style="font-size:smaller;">
  23.332 +     * <em>Discussion:</em>
  23.333 +     * Access checks only apply to named and reflected methods,
  23.334 +     * constructors, and fields.
  23.335 +     * Other method handle creation methods, such as
  23.336 +     * {@link MethodHandle#asType MethodHandle.asType},
  23.337 +     * do not require any access checks, and are used
  23.338 +     * independently of any {@code Lookup} object.
  23.339 +     * <p>
  23.340 +     * If the desired member is {@code protected}, the usual JVM rules apply,
  23.341 +     * including the requirement that the lookup class must be either be in the
  23.342 +     * same package as the desired member, or must inherit that member.
  23.343 +     * (See the Java Virtual Machine Specification, sections 4.9.2, 5.4.3.5, and 6.4.)
  23.344 +     * In addition, if the desired member is a non-static field or method
  23.345 +     * in a different package, the resulting method handle may only be applied
  23.346 +     * to objects of the lookup class or one of its subclasses.
  23.347 +     * This requirement is enforced by narrowing the type of the leading
  23.348 +     * {@code this} parameter from {@code C}
  23.349 +     * (which will necessarily be a superclass of the lookup class)
  23.350 +     * to the lookup class itself.
  23.351 +     * <p>
  23.352 +     * The JVM imposes a similar requirement on {@code invokespecial} instruction,
  23.353 +     * that the receiver argument must match both the resolved method <em>and</em>
  23.354 +     * the current class.  Again, this requirement is enforced by narrowing the
  23.355 +     * type of the leading parameter to the resulting method handle.
  23.356 +     * (See the Java Virtual Machine Specification, section 4.10.1.9.)
  23.357 +     * <p>
  23.358 +     * The JVM represents constructors and static initializer blocks as internal methods
  23.359 +     * with special names ({@code "<init>"} and {@code "<clinit>"}).
  23.360 +     * The internal syntax of invocation instructions allows them to refer to such internal
  23.361 +     * methods as if they were normal methods, but the JVM bytecode verifier rejects them.
  23.362 +     * A lookup of such an internal method will produce a {@code NoSuchMethodException}.
  23.363 +     * <p>
  23.364 +     * In some cases, access between nested classes is obtained by the Java compiler by creating
  23.365 +     * an wrapper method to access a private method of another class
  23.366 +     * in the same top-level declaration.
  23.367 +     * For example, a nested class {@code C.D}
  23.368 +     * can access private members within other related classes such as
  23.369 +     * {@code C}, {@code C.D.E}, or {@code C.B},
  23.370 +     * but the Java compiler may need to generate wrapper methods in
  23.371 +     * those related classes.  In such cases, a {@code Lookup} object on
  23.372 +     * {@code C.E} would be unable to those private members.
  23.373 +     * A workaround for this limitation is the {@link Lookup#in Lookup.in} method,
  23.374 +     * which can transform a lookup on {@code C.E} into one on any of those other
  23.375 +     * classes, without special elevation of privilege.
  23.376 +     * <p>
  23.377 +     * The accesses permitted to a given lookup object may be limited,
  23.378 +     * according to its set of {@link #lookupModes lookupModes},
  23.379 +     * to a subset of members normally accessible to the lookup class.
  23.380 +     * For example, the {@link MethodHandles#publicLookup publicLookup}
  23.381 +     * method produces a lookup object which is only allowed to access
  23.382 +     * public members in public classes.
  23.383 +     * The caller sensitive method {@link MethodHandles#lookup lookup}
  23.384 +     * produces a lookup object with full capabilities relative to
  23.385 +     * its caller class, to emulate all supported bytecode behaviors.
  23.386 +     * Also, the {@link Lookup#in Lookup.in} method may produce a lookup object
  23.387 +     * with fewer access modes than the original lookup object.
  23.388 +     *
  23.389 +     * <p style="font-size:smaller;">
  23.390 +     * <a name="privacc"></a>
  23.391 +     * <em>Discussion of private access:</em>
  23.392 +     * We say that a lookup has <em>private access</em>
  23.393 +     * if its {@linkplain #lookupModes lookup modes}
  23.394 +     * include the possibility of accessing {@code private} members.
  23.395 +     * As documented in the relevant methods elsewhere,
  23.396 +     * only lookups with private access possess the following capabilities:
  23.397 +     * <ul style="font-size:smaller;">
  23.398 +     * <li>access private fields, methods, and constructors of the lookup class
  23.399 +     * <li>create method handles which invoke <a href="MethodHandles.Lookup.html#callsens">caller sensitive</a> methods,
  23.400 +     *     such as {@code Class.forName}
  23.401 +     * <li>create method handles which {@link Lookup#findSpecial emulate invokespecial} instructions
  23.402 +     * <li>avoid <a href="MethodHandles.Lookup.html#secmgr">package access checks</a>
  23.403 +     *     for classes accessible to the lookup class
  23.404 +     * <li>create {@link Lookup#in delegated lookup objects} which have private access to other classes
  23.405 +     *     within the same package member
  23.406 +     * </ul>
  23.407 +     * <p style="font-size:smaller;">
  23.408 +     * Each of these permissions is a consequence of the fact that a lookup object
  23.409 +     * with private access can be securely traced back to an originating class,
  23.410 +     * whose <a href="MethodHandles.Lookup.html#equiv">bytecode behaviors</a> and Java language access permissions
  23.411 +     * can be reliably determined and emulated by method handles.
  23.412 +     *
  23.413 +     * <h1><a name="secmgr"></a>Security manager interactions</h1>
  23.414 +     * Although bytecode instructions can only refer to classes in
  23.415 +     * a related class loader, this API can search for methods in any
  23.416 +     * class, as long as a reference to its {@code Class} object is
  23.417 +     * available.  Such cross-loader references are also possible with the
  23.418 +     * Core Reflection API, and are impossible to bytecode instructions
  23.419 +     * such as {@code invokestatic} or {@code getfield}.
  23.420 +     * There is a {@linkplain java.lang.SecurityManager security manager API}
  23.421 +     * to allow applications to check such cross-loader references.
  23.422 +     * These checks apply to both the {@code MethodHandles.Lookup} API
  23.423 +     * and the Core Reflection API
  23.424 +     * (as found on {@link java.lang.Class Class}).
  23.425 +     * <p>
  23.426 +     * If a security manager is present, member lookups are subject to
  23.427 +     * additional checks.
  23.428 +     * From one to three calls are made to the security manager.
  23.429 +     * Any of these calls can refuse access by throwing a
  23.430 +     * {@link java.lang.SecurityException SecurityException}.
  23.431 +     * Define {@code smgr} as the security manager,
  23.432 +     * {@code lookc} as the lookup class of the current lookup object,
  23.433 +     * {@code refc} as the containing class in which the member
  23.434 +     * is being sought, and {@code defc} as the class in which the
  23.435 +     * member is actually defined.
  23.436 +     * The value {@code lookc} is defined as <em>not present</em>
  23.437 +     * if the current lookup object does not have
  23.438 +     * <a href="MethodHandles.Lookup.html#privacc">private access</a>.
  23.439 +     * The calls are made according to the following rules:
  23.440 +     * <ul>
  23.441 +     * <li><b>Step 1:</b>
  23.442 +     *     If {@code lookc} is not present, or if its class loader is not
  23.443 +     *     the same as or an ancestor of the class loader of {@code refc},
  23.444 +     *     then {@link SecurityManager#checkPackageAccess
  23.445 +     *     smgr.checkPackageAccess(refcPkg)} is called,
  23.446 +     *     where {@code refcPkg} is the package of {@code refc}.
  23.447 +     * <li><b>Step 2:</b>
  23.448 +     *     If the retrieved member is not public and
  23.449 +     *     {@code lookc} is not present, then
  23.450 +     *     {@link SecurityManager#checkPermission smgr.checkPermission}
  23.451 +     *     with {@code RuntimePermission("accessDeclaredMembers")} is called.
  23.452 +     * <li><b>Step 3:</b>
  23.453 +     *     If the retrieved member is not public,
  23.454 +     *     and if {@code lookc} is not present,
  23.455 +     *     and if {@code defc} and {@code refc} are different,
  23.456 +     *     then {@link SecurityManager#checkPackageAccess
  23.457 +     *     smgr.checkPackageAccess(defcPkg)} is called,
  23.458 +     *     where {@code defcPkg} is the package of {@code defc}.
  23.459 +     * </ul>
  23.460 +     * Security checks are performed after other access checks have passed.
  23.461 +     * Therefore, the above rules presuppose a member that is public,
  23.462 +     * or else that is being accessed from a lookup class that has
  23.463 +     * rights to access the member.
  23.464 +     *
  23.465 +     * <h1><a name="callsens"></a>Caller sensitive methods</h1>
  23.466 +     * A small number of Java methods have a special property called caller sensitivity.
  23.467 +     * A <em>caller-sensitive</em> method can behave differently depending on the
  23.468 +     * identity of its immediate caller.
  23.469 +     * <p>
  23.470 +     * If a method handle for a caller-sensitive method is requested,
  23.471 +     * the general rules for <a href="MethodHandles.Lookup.html#equiv">bytecode behaviors</a> apply,
  23.472 +     * but they take account of the lookup class in a special way.
  23.473 +     * The resulting method handle behaves as if it were called
  23.474 +     * from an instruction contained in the lookup class,
  23.475 +     * so that the caller-sensitive method detects the lookup class.
  23.476 +     * (By contrast, the invoker of the method handle is disregarded.)
  23.477 +     * Thus, in the case of caller-sensitive methods,
  23.478 +     * different lookup classes may give rise to
  23.479 +     * differently behaving method handles.
  23.480 +     * <p>
  23.481 +     * In cases where the lookup object is
  23.482 +     * {@link MethodHandles#publicLookup() publicLookup()},
  23.483 +     * or some other lookup object without
  23.484 +     * <a href="MethodHandles.Lookup.html#privacc">private access</a>,
  23.485 +     * the lookup class is disregarded.
  23.486 +     * In such cases, no caller-sensitive method handle can be created,
  23.487 +     * access is forbidden, and the lookup fails with an
  23.488 +     * {@code IllegalAccessException}.
  23.489 +     * <p style="font-size:smaller;">
  23.490 +     * <em>Discussion:</em>
  23.491 +     * For example, the caller-sensitive method
  23.492 +     * {@link java.lang.Class#forName(String) Class.forName(x)}
  23.493 +     * can return varying classes or throw varying exceptions,
  23.494 +     * depending on the class loader of the class that calls it.
  23.495 +     * A public lookup of {@code Class.forName} will fail, because
  23.496 +     * there is no reasonable way to determine its bytecode behavior.
  23.497 +     * <p style="font-size:smaller;">
  23.498 +     * If an application caches method handles for broad sharing,
  23.499 +     * it should use {@code publicLookup()} to create them.
  23.500 +     * If there is a lookup of {@code Class.forName}, it will fail,
  23.501 +     * and the application must take appropriate action in that case.
  23.502 +     * It may be that a later lookup, perhaps during the invocation of a
  23.503 +     * bootstrap method, can incorporate the specific identity
  23.504 +     * of the caller, making the method accessible.
  23.505 +     * <p style="font-size:smaller;">
  23.506 +     * The function {@code MethodHandles.lookup} is caller sensitive
  23.507 +     * so that there can be a secure foundation for lookups.
  23.508 +     * Nearly all other methods in the JSR 292 API rely on lookup
  23.509 +     * objects to check access requests.
  23.510 +     */
  23.511 +    public static final
  23.512 +    class Lookup {
  23.513 +        /** The class on behalf of whom the lookup is being performed. */
  23.514 +        private final Class<?> lookupClass;
  23.515 +
  23.516 +        /** The allowed sorts of members which may be looked up (PUBLIC, etc.). */
  23.517 +        private final int allowedModes;
  23.518 +
  23.519 +        /** A single-bit mask representing {@code public} access,
  23.520 +         *  which may contribute to the result of {@link #lookupModes lookupModes}.
  23.521 +         *  The value, {@code 0x01}, happens to be the same as the value of the
  23.522 +         *  {@code public} {@linkplain java.lang.reflect.Modifier#PUBLIC modifier bit}.
  23.523 +         */
  23.524 +        public static final int PUBLIC = Modifier.PUBLIC;
  23.525 +
  23.526 +        /** A single-bit mask representing {@code private} access,
  23.527 +         *  which may contribute to the result of {@link #lookupModes lookupModes}.
  23.528 +         *  The value, {@code 0x02}, happens to be the same as the value of the
  23.529 +         *  {@code private} {@linkplain java.lang.reflect.Modifier#PRIVATE modifier bit}.
  23.530 +         */
  23.531 +        public static final int PRIVATE = Modifier.PRIVATE;
  23.532 +
  23.533 +        /** A single-bit mask representing {@code protected} access,
  23.534 +         *  which may contribute to the result of {@link #lookupModes lookupModes}.
  23.535 +         *  The value, {@code 0x04}, happens to be the same as the value of the
  23.536 +         *  {@code protected} {@linkplain java.lang.reflect.Modifier#PROTECTED modifier bit}.
  23.537 +         */
  23.538 +        public static final int PROTECTED = Modifier.PROTECTED;
  23.539 +
  23.540 +        /** A single-bit mask representing {@code package} access (default access),
  23.541 +         *  which may contribute to the result of {@link #lookupModes lookupModes}.
  23.542 +         *  The value is {@code 0x08}, which does not correspond meaningfully to
  23.543 +         *  any particular {@linkplain java.lang.reflect.Modifier modifier bit}.
  23.544 +         */
  23.545 +        public static final int PACKAGE = Modifier.STATIC;
  23.546 +
  23.547 +        private static final int ALL_MODES = (PUBLIC | PRIVATE | PROTECTED | PACKAGE);
  23.548 +        private static final int TRUSTED   = -1;
  23.549 +
  23.550 +        private static int fixmods(int mods) {
  23.551 +            mods &= (ALL_MODES - PACKAGE);
  23.552 +            return (mods != 0) ? mods : PACKAGE;
  23.553 +        }
  23.554 +
  23.555 +        /** Tells which class is performing the lookup.  It is this class against
  23.556 +         *  which checks are performed for visibility and access permissions.
  23.557 +         *  <p>
  23.558 +         *  The class implies a maximum level of access permission,
  23.559 +         *  but the permissions may be additionally limited by the bitmask
  23.560 +         *  {@link #lookupModes lookupModes}, which controls whether non-public members
  23.561 +         *  can be accessed.
  23.562 +         *  @return the lookup class, on behalf of which this lookup object finds members
  23.563 +         */
  23.564 +        public Class<?> lookupClass() {
  23.565 +            return lookupClass;
  23.566 +        }
  23.567 +
  23.568 +        // This is just for calling out to MethodHandleImpl.
  23.569 +        private Class<?> lookupClassOrNull() {
  23.570 +            return (allowedModes == TRUSTED) ? null : lookupClass;
  23.571 +        }
  23.572 +
  23.573 +        /** Tells which access-protection classes of members this lookup object can produce.
  23.574 +         *  The result is a bit-mask of the bits
  23.575 +         *  {@linkplain #PUBLIC PUBLIC (0x01)},
  23.576 +         *  {@linkplain #PRIVATE PRIVATE (0x02)},
  23.577 +         *  {@linkplain #PROTECTED PROTECTED (0x04)},
  23.578 +         *  and {@linkplain #PACKAGE PACKAGE (0x08)}.
  23.579 +         *  <p>
  23.580 +         *  A freshly-created lookup object
  23.581 +         *  on the {@linkplain java.lang.invoke.MethodHandles#lookup() caller's class}
  23.582 +         *  has all possible bits set, since the caller class can access all its own members.
  23.583 +         *  A lookup object on a new lookup class
  23.584 +         *  {@linkplain java.lang.invoke.MethodHandles.Lookup#in created from a previous lookup object}
  23.585 +         *  may have some mode bits set to zero.
  23.586 +         *  The purpose of this is to restrict access via the new lookup object,
  23.587 +         *  so that it can access only names which can be reached by the original
  23.588 +         *  lookup object, and also by the new lookup class.
  23.589 +         *  @return the lookup modes, which limit the kinds of access performed by this lookup object
  23.590 +         */
  23.591 +        public int lookupModes() {
  23.592 +            return allowedModes & ALL_MODES;
  23.593 +        }
  23.594 +
  23.595 +        /** Embody the current class (the lookupClass) as a lookup class
  23.596 +         * for method handle creation.
  23.597 +         * Must be called by from a method in this package,
  23.598 +         * which in turn is called by a method not in this package.
  23.599 +         */
  23.600 +        Lookup(Class<?> lookupClass) {
  23.601 +            this(lookupClass, ALL_MODES);
  23.602 +            // make sure we haven't accidentally picked up a privileged class:
  23.603 +            checkUnprivilegedlookupClass(lookupClass, ALL_MODES);
  23.604 +        }
  23.605 +
  23.606 +        private Lookup(Class<?> lookupClass, int allowedModes) {
  23.607 +            this.lookupClass = lookupClass;
  23.608 +            this.allowedModes = allowedModes;
  23.609 +        }
  23.610 +
  23.611 +        /**
  23.612 +         * Creates a lookup on the specified new lookup class.
  23.613 +         * The resulting object will report the specified
  23.614 +         * class as its own {@link #lookupClass lookupClass}.
  23.615 +         * <p>
  23.616 +         * However, the resulting {@code Lookup} object is guaranteed
  23.617 +         * to have no more access capabilities than the original.
  23.618 +         * In particular, access capabilities can be lost as follows:<ul>
  23.619 +         * <li>If the new lookup class differs from the old one,
  23.620 +         * protected members will not be accessible by virtue of inheritance.
  23.621 +         * (Protected members may continue to be accessible because of package sharing.)
  23.622 +         * <li>If the new lookup class is in a different package
  23.623 +         * than the old one, protected and default (package) members will not be accessible.
  23.624 +         * <li>If the new lookup class is not within the same package member
  23.625 +         * as the old one, private members will not be accessible.
  23.626 +         * <li>If the new lookup class is not accessible to the old lookup class,
  23.627 +         * then no members, not even public members, will be accessible.
  23.628 +         * (In all other cases, public members will continue to be accessible.)
  23.629 +         * </ul>
  23.630 +         *
  23.631 +         * @param requestedLookupClass the desired lookup class for the new lookup object
  23.632 +         * @return a lookup object which reports the desired lookup class
  23.633 +         * @throws NullPointerException if the argument is null
  23.634 +         */
  23.635 +        public Lookup in(Class<?> requestedLookupClass) {
  23.636 +            requestedLookupClass.getClass();  // null check
  23.637 +            if (allowedModes == TRUSTED)  // IMPL_LOOKUP can make any lookup at all
  23.638 +                return new Lookup(requestedLookupClass, ALL_MODES);
  23.639 +            if (requestedLookupClass == this.lookupClass)
  23.640 +                return this;  // keep same capabilities
  23.641 +            int newModes = (allowedModes & (ALL_MODES & ~PROTECTED));
  23.642 +            if ((newModes & PACKAGE) != 0
  23.643 +                && !VerifyAccess.isSamePackage(this.lookupClass, requestedLookupClass)) {
  23.644 +                newModes &= ~(PACKAGE|PRIVATE);
  23.645 +            }
  23.646 +            // Allow nestmate lookups to be created without special privilege:
  23.647 +            if ((newModes & PRIVATE) != 0
  23.648 +                && !VerifyAccess.isSamePackageMember(this.lookupClass, requestedLookupClass)) {
  23.649 +                newModes &= ~PRIVATE;
  23.650 +            }
  23.651 +            if ((newModes & PUBLIC) != 0
  23.652 +                && !VerifyAccess.isClassAccessible(requestedLookupClass, this.lookupClass, allowedModes)) {
  23.653 +                // The requested class it not accessible from the lookup class.
  23.654 +                // No permissions.
  23.655 +                newModes = 0;
  23.656 +            }
  23.657 +            checkUnprivilegedlookupClass(requestedLookupClass, newModes);
  23.658 +            return new Lookup(requestedLookupClass, newModes);
  23.659 +        }
  23.660 +
  23.661 +        // Make sure outer class is initialized first.
  23.662 +        static { IMPL_NAMES.getClass(); }
  23.663 +
  23.664 +        /** Version of lookup which is trusted minimally.
  23.665 +         *  It can only be used to create method handles to
  23.666 +         *  publicly accessible members.
  23.667 +         */
  23.668 +        static final Lookup PUBLIC_LOOKUP = new Lookup(Object.class, PUBLIC);
  23.669 +
  23.670 +        /** Package-private version of lookup which is trusted. */
  23.671 +        static final Lookup IMPL_LOOKUP = new Lookup(Object.class, TRUSTED);
  23.672 +
  23.673 +        private static void checkUnprivilegedlookupClass(Class<?> lookupClass, int allowedModes) {
  23.674 +            String name = lookupClass.getName();
  23.675 +            if (name.startsWith("java.lang.invoke."))
  23.676 +                throw newIllegalArgumentException("illegal lookupClass: "+lookupClass);
  23.677 +
  23.678 +            // For caller-sensitive MethodHandles.lookup()
  23.679 +            // disallow lookup more restricted packages
  23.680 +            if (allowedModes == ALL_MODES && lookupClass.getClassLoader() == null) {
  23.681 +                if (name.startsWith("java.") ||
  23.682 +                        (name.startsWith("sun.") && !name.startsWith("sun.invoke."))) {
  23.683 +                    throw newIllegalArgumentException("illegal lookupClass: " + lookupClass);
  23.684 +                }
  23.685 +            }
  23.686 +        }
  23.687 +
  23.688 +        /**
  23.689 +         * Displays the name of the class from which lookups are to be made.
  23.690 +         * (The name is the one reported by {@link java.lang.Class#getName() Class.getName}.)
  23.691 +         * If there are restrictions on the access permitted to this lookup,
  23.692 +         * this is indicated by adding a suffix to the class name, consisting
  23.693 +         * of a slash and a keyword.  The keyword represents the strongest
  23.694 +         * allowed access, and is chosen as follows:
  23.695 +         * <ul>
  23.696 +         * <li>If no access is allowed, the suffix is "/noaccess".
  23.697 +         * <li>If only public access is allowed, the suffix is "/public".
  23.698 +         * <li>If only public and package access are allowed, the suffix is "/package".
  23.699 +         * <li>If only public, package, and private access are allowed, the suffix is "/private".
  23.700 +         * </ul>
  23.701 +         * If none of the above cases apply, it is the case that full
  23.702 +         * access (public, package, private, and protected) is allowed.
  23.703 +         * In this case, no suffix is added.
  23.704 +         * This is true only of an object obtained originally from
  23.705 +         * {@link java.lang.invoke.MethodHandles#lookup MethodHandles.lookup}.
  23.706 +         * Objects created by {@link java.lang.invoke.MethodHandles.Lookup#in Lookup.in}
  23.707 +         * always have restricted access, and will display a suffix.
  23.708 +         * <p>
  23.709 +         * (It may seem strange that protected access should be
  23.710 +         * stronger than private access.  Viewed independently from
  23.711 +         * package access, protected access is the first to be lost,
  23.712 +         * because it requires a direct subclass relationship between
  23.713 +         * caller and callee.)
  23.714 +         * @see #in
  23.715 +         */
  23.716 +        @Override
  23.717 +        public String toString() {
  23.718 +            String cname = lookupClass.getName();
  23.719 +            switch (allowedModes) {
  23.720 +            case 0:  // no privileges
  23.721 +                return cname + "/noaccess";
  23.722 +            case PUBLIC:
  23.723 +                return cname + "/public";
  23.724 +            case PUBLIC|PACKAGE:
  23.725 +                return cname + "/package";
  23.726 +            case ALL_MODES & ~PROTECTED:
  23.727 +                return cname + "/private";
  23.728 +            case ALL_MODES:
  23.729 +                return cname;
  23.730 +            case TRUSTED:
  23.731 +                return "/trusted";  // internal only; not exported
  23.732 +            default:  // Should not happen, but it's a bitfield...
  23.733 +                cname = cname + "/" + Integer.toHexString(allowedModes);
  23.734 +                assert(false) : cname;
  23.735 +                return cname;
  23.736 +            }
  23.737 +        }
  23.738 +
  23.739 +        /**
  23.740 +         * Produces a method handle for a static method.
  23.741 +         * The type of the method handle will be that of the method.
  23.742 +         * (Since static methods do not take receivers, there is no
  23.743 +         * additional receiver argument inserted into the method handle type,
  23.744 +         * as there would be with {@link #findVirtual findVirtual} or {@link #findSpecial findSpecial}.)
  23.745 +         * The method and all its argument types must be accessible to the lookup object.
  23.746 +         * <p>
  23.747 +         * The returned method handle will have
  23.748 +         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
  23.749 +         * the method's variable arity modifier bit ({@code 0x0080}) is set.
  23.750 +         * <p>
  23.751 +         * If the returned method handle is invoked, the method's class will
  23.752 +         * be initialized, if it has not already been initialized.
  23.753 +         * <p><b>Example:</b>
  23.754 +         * <blockquote><pre>{@code
  23.755 +import static java.lang.invoke.MethodHandles.*;
  23.756 +import static java.lang.invoke.MethodType.*;
  23.757 +...
  23.758 +MethodHandle MH_asList = publicLookup().findStatic(Arrays.class,
  23.759 +  "asList", methodType(List.class, Object[].class));
  23.760 +assertEquals("[x, y]", MH_asList.invoke("x", "y").toString());
  23.761 +         * }</pre></blockquote>
  23.762 +         * @param refc the class from which the method is accessed
  23.763 +         * @param name the name of the method
  23.764 +         * @param type the type of the method
  23.765 +         * @return the desired method handle
  23.766 +         * @throws NoSuchMethodException if the method does not exist
  23.767 +         * @throws IllegalAccessException if access checking fails,
  23.768 +         *                                or if the method is not {@code static},
  23.769 +         *                                or if the method's variable arity modifier bit
  23.770 +         *                                is set and {@code asVarargsCollector} fails
  23.771 +         * @exception SecurityException if a security manager is present and it
  23.772 +         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
  23.773 +         * @throws NullPointerException if any argument is null
  23.774 +         */
  23.775 +        public
  23.776 +        MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
  23.777 +            MemberName method = resolveOrFail(REF_invokeStatic, refc, name, type);
  23.778 +            return getDirectMethod(REF_invokeStatic, refc, method, findBoundCallerClass(method));
  23.779 +        }
  23.780 +
  23.781 +        /**
  23.782 +         * Produces a method handle for a virtual method.
  23.783 +         * The type of the method handle will be that of the method,
  23.784 +         * with the receiver type (usually {@code refc}) prepended.
  23.785 +         * The method and all its argument types must be accessible to the lookup object.
  23.786 +         * <p>
  23.787 +         * When called, the handle will treat the first argument as a receiver
  23.788 +         * and dispatch on the receiver's type to determine which method
  23.789 +         * implementation to enter.
  23.790 +         * (The dispatching action is identical with that performed by an
  23.791 +         * {@code invokevirtual} or {@code invokeinterface} instruction.)
  23.792 +         * <p>
  23.793 +         * The first argument will be of type {@code refc} if the lookup
  23.794 +         * class has full privileges to access the member.  Otherwise
  23.795 +         * the member must be {@code protected} and the first argument
  23.796 +         * will be restricted in type to the lookup class.
  23.797 +         * <p>
  23.798 +         * The returned method handle will have
  23.799 +         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
  23.800 +         * the method's variable arity modifier bit ({@code 0x0080}) is set.
  23.801 +         * <p>
  23.802 +         * Because of the general <a href="MethodHandles.Lookup.html#equiv">equivalence</a> between {@code invokevirtual}
  23.803 +         * instructions and method handles produced by {@code findVirtual},
  23.804 +         * if the class is {@code MethodHandle} and the name string is
  23.805 +         * {@code invokeExact} or {@code invoke}, the resulting
  23.806 +         * method handle is equivalent to one produced by
  23.807 +         * {@link java.lang.invoke.MethodHandles#exactInvoker MethodHandles.exactInvoker} or
  23.808 +         * {@link java.lang.invoke.MethodHandles#invoker MethodHandles.invoker}
  23.809 +         * with the same {@code type} argument.
  23.810 +         *
  23.811 +         * <b>Example:</b>
  23.812 +         * <blockquote><pre>{@code
  23.813 +import static java.lang.invoke.MethodHandles.*;
  23.814 +import static java.lang.invoke.MethodType.*;
  23.815 +...
  23.816 +MethodHandle MH_concat = publicLookup().findVirtual(String.class,
  23.817 +  "concat", methodType(String.class, String.class));
  23.818 +MethodHandle MH_hashCode = publicLookup().findVirtual(Object.class,
  23.819 +  "hashCode", methodType(int.class));
  23.820 +MethodHandle MH_hashCode_String = publicLookup().findVirtual(String.class,
  23.821 +  "hashCode", methodType(int.class));
  23.822 +assertEquals("xy", (String) MH_concat.invokeExact("x", "y"));
  23.823 +assertEquals("xy".hashCode(), (int) MH_hashCode.invokeExact((Object)"xy"));
  23.824 +assertEquals("xy".hashCode(), (int) MH_hashCode_String.invokeExact("xy"));
  23.825 +// interface method:
  23.826 +MethodHandle MH_subSequence = publicLookup().findVirtual(CharSequence.class,
  23.827 +  "subSequence", methodType(CharSequence.class, int.class, int.class));
  23.828 +assertEquals("def", MH_subSequence.invoke("abcdefghi", 3, 6).toString());
  23.829 +// constructor "internal method" must be accessed differently:
  23.830 +MethodType MT_newString = methodType(void.class); //()V for new String()
  23.831 +try { assertEquals("impossible", lookup()
  23.832 +        .findVirtual(String.class, "<init>", MT_newString));
  23.833 + } catch (NoSuchMethodException ex) { } // OK
  23.834 +MethodHandle MH_newString = publicLookup()
  23.835 +  .findConstructor(String.class, MT_newString);
  23.836 +assertEquals("", (String) MH_newString.invokeExact());
  23.837 +         * }</pre></blockquote>
  23.838 +         *
  23.839 +         * @param refc the class or interface from which the method is accessed
  23.840 +         * @param name the name of the method
  23.841 +         * @param type the type of the method, with the receiver argument omitted
  23.842 +         * @return the desired method handle
  23.843 +         * @throws NoSuchMethodException if the method does not exist
  23.844 +         * @throws IllegalAccessException if access checking fails,
  23.845 +         *                                or if the method is {@code static}
  23.846 +         *                                or if the method's variable arity modifier bit
  23.847 +         *                                is set and {@code asVarargsCollector} fails
  23.848 +         * @exception SecurityException if a security manager is present and it
  23.849 +         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
  23.850 +         * @throws NullPointerException if any argument is null
  23.851 +         */
  23.852 +        public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
  23.853 +            if (refc == MethodHandle.class) {
  23.854 +                MethodHandle mh = findVirtualForMH(name, type);
  23.855 +                if (mh != null)  return mh;
  23.856 +            }
  23.857 +            byte refKind = (refc.isInterface() ? REF_invokeInterface : REF_invokeVirtual);
  23.858 +            MemberName method = resolveOrFail(refKind, refc, name, type);
  23.859 +            return getDirectMethod(refKind, refc, method, findBoundCallerClass(method));
  23.860 +        }
  23.861 +        private MethodHandle findVirtualForMH(String name, MethodType type) {
  23.862 +            // these names require special lookups because of the implicit MethodType argument
  23.863 +            if ("invoke".equals(name))
  23.864 +                return invoker(type);
  23.865 +            if ("invokeExact".equals(name))
  23.866 +                return exactInvoker(type);
  23.867 +            assert(!MemberName.isMethodHandleInvokeName(name));
  23.868 +            return null;
  23.869 +        }
  23.870 +
  23.871 +        /**
  23.872 +         * Produces a method handle which creates an object and initializes it, using
  23.873 +         * the constructor of the specified type.
  23.874 +         * The parameter types of the method handle will be those of the constructor,
  23.875 +         * while the return type will be a reference to the constructor's class.
  23.876 +         * The constructor and all its argument types must be accessible to the lookup object.
  23.877 +         * <p>
  23.878 +         * The requested type must have a return type of {@code void}.
  23.879 +         * (This is consistent with the JVM's treatment of constructor type descriptors.)
  23.880 +         * <p>
  23.881 +         * The returned method handle will have
  23.882 +         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
  23.883 +         * the constructor's variable arity modifier bit ({@code 0x0080}) is set.
  23.884 +         * <p>
  23.885 +         * If the returned method handle is invoked, the constructor's class will
  23.886 +         * be initialized, if it has not already been initialized.
  23.887 +         * <p><b>Example:</b>
  23.888 +         * <blockquote><pre>{@code
  23.889 +import static java.lang.invoke.MethodHandles.*;
  23.890 +import static java.lang.invoke.MethodType.*;
  23.891 +...
  23.892 +MethodHandle MH_newArrayList = publicLookup().findConstructor(
  23.893 +  ArrayList.class, methodType(void.class, Collection.class));
  23.894 +Collection orig = Arrays.asList("x", "y");
  23.895 +Collection copy = (ArrayList) MH_newArrayList.invokeExact(orig);
  23.896 +assert(orig != copy);
  23.897 +assertEquals(orig, copy);
  23.898 +// a variable-arity constructor:
  23.899 +MethodHandle MH_newProcessBuilder = publicLookup().findConstructor(
  23.900 +  ProcessBuilder.class, methodType(void.class, String[].class));
  23.901 +ProcessBuilder pb = (ProcessBuilder)
  23.902 +  MH_newProcessBuilder.invoke("x", "y", "z");
  23.903 +assertEquals("[x, y, z]", pb.command().toString());
  23.904 +         * }</pre></blockquote>
  23.905 +         * @param refc the class or interface from which the method is accessed
  23.906 +         * @param type the type of the method, with the receiver argument omitted, and a void return type
  23.907 +         * @return the desired method handle
  23.908 +         * @throws NoSuchMethodException if the constructor does not exist
  23.909 +         * @throws IllegalAccessException if access checking fails
  23.910 +         *                                or if the method's variable arity modifier bit
  23.911 +         *                                is set and {@code asVarargsCollector} fails
  23.912 +         * @exception SecurityException if a security manager is present and it
  23.913 +         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
  23.914 +         * @throws NullPointerException if any argument is null
  23.915 +         */
  23.916 +        public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException {
  23.917 +            String name = "<init>";
  23.918 +            MemberName ctor = resolveOrFail(REF_newInvokeSpecial, refc, name, type);
  23.919 +            return getDirectConstructor(refc, ctor);
  23.920 +        }
  23.921 +
  23.922 +        /**
  23.923 +         * Produces an early-bound method handle for a virtual method.
  23.924 +         * It will bypass checks for overriding methods on the receiver,
  23.925 +         * <a href="MethodHandles.Lookup.html#equiv">as if called</a> from an {@code invokespecial}
  23.926 +         * instruction from within the explicitly specified {@code specialCaller}.
  23.927 +         * The type of the method handle will be that of the method,
  23.928 +         * with a suitably restricted receiver type prepended.
  23.929 +         * (The receiver type will be {@code specialCaller} or a subtype.)
  23.930 +         * The method and all its argument types must be accessible
  23.931 +         * to the lookup object.
  23.932 +         * <p>
  23.933 +         * Before method resolution,
  23.934 +         * if the explicitly specified caller class is not identical with the
  23.935 +         * lookup class, or if this lookup object does not have
  23.936 +         * <a href="MethodHandles.Lookup.html#privacc">private access</a>
  23.937 +         * privileges, the access fails.
  23.938 +         * <p>
  23.939 +         * The returned method handle will have
  23.940 +         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
  23.941 +         * the method's variable arity modifier bit ({@code 0x0080}) is set.
  23.942 +         * <p style="font-size:smaller;">
  23.943 +         * <em>(Note:  JVM internal methods named {@code "<init>"} are not visible to this API,
  23.944 +         * even though the {@code invokespecial} instruction can refer to them
  23.945 +         * in special circumstances.  Use {@link #findConstructor findConstructor}
  23.946 +         * to access instance initialization methods in a safe manner.)</em>
  23.947 +         * <p><b>Example:</b>
  23.948 +         * <blockquote><pre>{@code
  23.949 +import static java.lang.invoke.MethodHandles.*;
  23.950 +import static java.lang.invoke.MethodType.*;
  23.951 +...
  23.952 +static class Listie extends ArrayList {
  23.953 +  public String toString() { return "[wee Listie]"; }
  23.954 +  static Lookup lookup() { return MethodHandles.lookup(); }
  23.955 +}
  23.956 +...
  23.957 +// no access to constructor via invokeSpecial:
  23.958 +MethodHandle MH_newListie = Listie.lookup()
  23.959 +  .findConstructor(Listie.class, methodType(void.class));
  23.960 +Listie l = (Listie) MH_newListie.invokeExact();
  23.961 +try { assertEquals("impossible", Listie.lookup().findSpecial(
  23.962 +        Listie.class, "<init>", methodType(void.class), Listie.class));
  23.963 + } catch (NoSuchMethodException ex) { } // OK
  23.964 +// access to super and self methods via invokeSpecial:
  23.965 +MethodHandle MH_super = Listie.lookup().findSpecial(
  23.966 +  ArrayList.class, "toString" , methodType(String.class), Listie.class);
  23.967 +MethodHandle MH_this = Listie.lookup().findSpecial(
  23.968 +  Listie.class, "toString" , methodType(String.class), Listie.class);
  23.969 +MethodHandle MH_duper = Listie.lookup().findSpecial(
  23.970 +  Object.class, "toString" , methodType(String.class), Listie.class);
  23.971 +assertEquals("[]", (String) MH_super.invokeExact(l));
  23.972 +assertEquals(""+l, (String) MH_this.invokeExact(l));
  23.973 +assertEquals("[]", (String) MH_duper.invokeExact(l)); // ArrayList method
  23.974 +try { assertEquals("inaccessible", Listie.lookup().findSpecial(
  23.975 +        String.class, "toString", methodType(String.class), Listie.class));
  23.976 + } catch (IllegalAccessException ex) { } // OK
  23.977 +Listie subl = new Listie() { public String toString() { return "[subclass]"; } };
  23.978 +assertEquals(""+l, (String) MH_this.invokeExact(subl)); // Listie method
  23.979 +         * }</pre></blockquote>
  23.980 +         *
  23.981 +         * @param refc the class or interface from which the method is accessed
  23.982 +         * @param name the name of the method (which must not be "&lt;init&gt;")
  23.983 +         * @param type the type of the method, with the receiver argument omitted
  23.984 +         * @param specialCaller the proposed calling class to perform the {@code invokespecial}
  23.985 +         * @return the desired method handle
  23.986 +         * @throws NoSuchMethodException if the method does not exist
  23.987 +         * @throws IllegalAccessException if access checking fails
  23.988 +         *                                or if the method's variable arity modifier bit
  23.989 +         *                                is set and {@code asVarargsCollector} fails
  23.990 +         * @exception SecurityException if a security manager is present and it
  23.991 +         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
  23.992 +         * @throws NullPointerException if any argument is null
  23.993 +         */
  23.994 +        public MethodHandle findSpecial(Class<?> refc, String name, MethodType type,
  23.995 +                                        Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException {
  23.996 +            checkSpecialCaller(specialCaller);
  23.997 +            Lookup specialLookup = this.in(specialCaller);
  23.998 +            MemberName method = specialLookup.resolveOrFail(REF_invokeSpecial, refc, name, type);
  23.999 +            return specialLookup.getDirectMethod(REF_invokeSpecial, refc, method, findBoundCallerClass(method));
 23.1000 +        }
 23.1001 +
 23.1002 +        /**
 23.1003 +         * Produces a method handle giving read access to a non-static field.
 23.1004 +         * The type of the method handle will have a return type of the field's
 23.1005 +         * value type.
 23.1006 +         * The method handle's single argument will be the instance containing
 23.1007 +         * the field.
 23.1008 +         * Access checking is performed immediately on behalf of the lookup class.
 23.1009 +         * @param refc the class or interface from which the method is accessed
 23.1010 +         * @param name the field's name
 23.1011 +         * @param type the field's type
 23.1012 +         * @return a method handle which can load values from the field
 23.1013 +         * @throws NoSuchFieldException if the field does not exist
 23.1014 +         * @throws IllegalAccessException if access checking fails, or if the field is {@code static}
 23.1015 +         * @exception SecurityException if a security manager is present and it
 23.1016 +         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
 23.1017 +         * @throws NullPointerException if any argument is null
 23.1018 +         */
 23.1019 +        public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
 23.1020 +            MemberName field = resolveOrFail(REF_getField, refc, name, type);
 23.1021 +            return getDirectField(REF_getField, refc, field);
 23.1022 +        }
 23.1023 +
 23.1024 +        /**
 23.1025 +         * Produces a method handle giving write access to a non-static field.
 23.1026 +         * The type of the method handle will have a void return type.
 23.1027 +         * The method handle will take two arguments, the instance containing
 23.1028 +         * the field, and the value to be stored.
 23.1029 +         * The second argument will be of the field's value type.
 23.1030 +         * Access checking is performed immediately on behalf of the lookup class.
 23.1031 +         * @param refc the class or interface from which the method is accessed
 23.1032 +         * @param name the field's name
 23.1033 +         * @param type the field's type
 23.1034 +         * @return a method handle which can store values into the field
 23.1035 +         * @throws NoSuchFieldException if the field does not exist
 23.1036 +         * @throws IllegalAccessException if access checking fails, or if the field is {@code static}
 23.1037 +         * @exception SecurityException if a security manager is present and it
 23.1038 +         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
 23.1039 +         * @throws NullPointerException if any argument is null
 23.1040 +         */
 23.1041 +        public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
 23.1042 +            MemberName field = resolveOrFail(REF_putField, refc, name, type);
 23.1043 +            return getDirectField(REF_putField, refc, field);
 23.1044 +        }
 23.1045 +
 23.1046 +        /**
 23.1047 +         * Produces a method handle giving read access to a static field.
 23.1048 +         * The type of the method handle will have a return type of the field's
 23.1049 +         * value type.
 23.1050 +         * The method handle will take no arguments.
 23.1051 +         * Access checking is performed immediately on behalf of the lookup class.
 23.1052 +         * <p>
 23.1053 +         * If the returned method handle is invoked, the field's class will
 23.1054 +         * be initialized, if it has not already been initialized.
 23.1055 +         * @param refc the class or interface from which the method is accessed
 23.1056 +         * @param name the field's name
 23.1057 +         * @param type the field's type
 23.1058 +         * @return a method handle which can load values from the field
 23.1059 +         * @throws NoSuchFieldException if the field does not exist
 23.1060 +         * @throws IllegalAccessException if access checking fails, or if the field is not {@code static}
 23.1061 +         * @exception SecurityException if a security manager is present and it
 23.1062 +         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
 23.1063 +         * @throws NullPointerException if any argument is null
 23.1064 +         */
 23.1065 +        public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
 23.1066 +            MemberName field = resolveOrFail(REF_getStatic, refc, name, type);
 23.1067 +            return getDirectField(REF_getStatic, refc, field);
 23.1068 +        }
 23.1069 +
 23.1070 +        /**
 23.1071 +         * Produces a method handle giving write access to a static field.
 23.1072 +         * The type of the method handle will have a void return type.
 23.1073 +         * The method handle will take a single
 23.1074 +         * argument, of the field's value type, the value to be stored.
 23.1075 +         * Access checking is performed immediately on behalf of the lookup class.
 23.1076 +         * <p>
 23.1077 +         * If the returned method handle is invoked, the field's class will
 23.1078 +         * be initialized, if it has not already been initialized.
 23.1079 +         * @param refc the class or interface from which the method is accessed
 23.1080 +         * @param name the field's name
 23.1081 +         * @param type the field's type
 23.1082 +         * @return a method handle which can store values into the field
 23.1083 +         * @throws NoSuchFieldException if the field does not exist
 23.1084 +         * @throws IllegalAccessException if access checking fails, or if the field is not {@code static}
 23.1085 +         * @exception SecurityException if a security manager is present and it
 23.1086 +         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
 23.1087 +         * @throws NullPointerException if any argument is null
 23.1088 +         */
 23.1089 +        public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
 23.1090 +            MemberName field = resolveOrFail(REF_putStatic, refc, name, type);
 23.1091 +            return getDirectField(REF_putStatic, refc, field);
 23.1092 +        }
 23.1093 +
 23.1094 +        /**
 23.1095 +         * Produces an early-bound method handle for a non-static method.
 23.1096 +         * The receiver must have a supertype {@code defc} in which a method
 23.1097 +         * of the given name and type is accessible to the lookup class.
 23.1098 +         * The method and all its argument types must be accessible to the lookup object.
 23.1099 +         * The type of the method handle will be that of the method,
 23.1100 +         * without any insertion of an additional receiver parameter.
 23.1101 +         * The given receiver will be bound into the method handle,
 23.1102 +         * so that every call to the method handle will invoke the
 23.1103 +         * requested method on the given receiver.
 23.1104 +         * <p>
 23.1105 +         * The returned method handle will have
 23.1106 +         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
 23.1107 +         * the method's variable arity modifier bit ({@code 0x0080}) is set
 23.1108 +         * <em>and</em> the trailing array argument is not the only argument.
 23.1109 +         * (If the trailing array argument is the only argument,
 23.1110 +         * the given receiver value will be bound to it.)
 23.1111 +         * <p>
 23.1112 +         * This is equivalent to the following code:
 23.1113 +         * <blockquote><pre>{@code
 23.1114 +import static java.lang.invoke.MethodHandles.*;
 23.1115 +import static java.lang.invoke.MethodType.*;
 23.1116 +...
 23.1117 +MethodHandle mh0 = lookup().findVirtual(defc, name, type);
 23.1118 +MethodHandle mh1 = mh0.bindTo(receiver);
 23.1119 +MethodType mt1 = mh1.type();
 23.1120 +if (mh0.isVarargsCollector())
 23.1121 +  mh1 = mh1.asVarargsCollector(mt1.parameterType(mt1.parameterCount()-1));
 23.1122 +return mh1;
 23.1123 +         * }</pre></blockquote>
 23.1124 +         * where {@code defc} is either {@code receiver.getClass()} or a super
 23.1125 +         * type of that class, in which the requested method is accessible
 23.1126 +         * to the lookup class.
 23.1127 +         * (Note that {@code bindTo} does not preserve variable arity.)
 23.1128 +         * @param receiver the object from which the method is accessed
 23.1129 +         * @param name the name of the method
 23.1130 +         * @param type the type of the method, with the receiver argument omitted
 23.1131 +         * @return the desired method handle
 23.1132 +         * @throws NoSuchMethodException if the method does not exist
 23.1133 +         * @throws IllegalAccessException if access checking fails
 23.1134 +         *                                or if the method's variable arity modifier bit
 23.1135 +         *                                is set and {@code asVarargsCollector} fails
 23.1136 +         * @exception SecurityException if a security manager is present and it
 23.1137 +         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
 23.1138 +         * @throws NullPointerException if any argument is null
 23.1139 +         * @see MethodHandle#bindTo
 23.1140 +         * @see #findVirtual
 23.1141 +         */
 23.1142 +        public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
 23.1143 +            Class<? extends Object> refc = receiver.getClass(); // may get NPE
 23.1144 +            MemberName method = resolveOrFail(REF_invokeSpecial, refc, name, type);
 23.1145 +            MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method, findBoundCallerClass(method));
 23.1146 +            return mh.bindReceiver(receiver).setVarargs(method);
 23.1147 +        }
 23.1148 +
 23.1149 +        /**
 23.1150 +         * Makes a <a href="MethodHandleInfo.html#directmh">direct method handle</a>
 23.1151 +         * to <i>m</i>, if the lookup class has permission.
 23.1152 +         * If <i>m</i> is non-static, the receiver argument is treated as an initial argument.
 23.1153 +         * If <i>m</i> is virtual, overriding is respected on every call.
 23.1154 +         * Unlike the Core Reflection API, exceptions are <em>not</em> wrapped.
 23.1155 +         * The type of the method handle will be that of the method,
 23.1156 +         * with the receiver type prepended (but only if it is non-static).
 23.1157 +         * If the method's {@code accessible} flag is not set,
 23.1158 +         * access checking is performed immediately on behalf of the lookup class.
 23.1159 +         * If <i>m</i> is not public, do not share the resulting handle with untrusted parties.
 23.1160 +         * <p>
 23.1161 +         * The returned method handle will have
 23.1162 +         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
 23.1163 +         * the method's variable arity modifier bit ({@code 0x0080}) is set.
 23.1164 +         * <p>
 23.1165 +         * If <i>m</i> is static, and
 23.1166 +         * if the returned method handle is invoked, the method's class will
 23.1167 +         * be initialized, if it has not already been initialized.
 23.1168 +         * @param m the reflected method
 23.1169 +         * @return a method handle which can invoke the reflected method
 23.1170 +         * @throws IllegalAccessException if access checking fails
 23.1171 +         *                                or if the method's variable arity modifier bit
 23.1172 +         *                                is set and {@code asVarargsCollector} fails
 23.1173 +         * @throws NullPointerException if the argument is null
 23.1174 +         */
 23.1175 +        public MethodHandle unreflect(Method m) throws IllegalAccessException {
 23.1176 +            if (m.getDeclaringClass() == MethodHandle.class) {
 23.1177 +                MethodHandle mh = unreflectForMH(m);
 23.1178 +                if (mh != null)  return mh;
 23.1179 +            }
 23.1180 +            MemberName method = new MemberName(m);
 23.1181 +            byte refKind = method.getReferenceKind();
 23.1182 +            if (refKind == REF_invokeSpecial)
 23.1183 +                refKind = REF_invokeVirtual;
 23.1184 +            assert(method.isMethod());
 23.1185 +            Lookup lookup = m.isAccessible() ? IMPL_LOOKUP : this;
 23.1186 +            return lookup.getDirectMethodNoSecurityManager(refKind, method.getDeclaringClass(), method, findBoundCallerClass(method));
 23.1187 +        }
 23.1188 +        private MethodHandle unreflectForMH(Method m) {
 23.1189 +            // these names require special lookups because they throw UnsupportedOperationException
 23.1190 +            if (MemberName.isMethodHandleInvokeName(m.getName()))
 23.1191 +                return MethodHandleImpl.fakeMethodHandleInvoke(new MemberName(m));
 23.1192 +            return null;
 23.1193 +        }
 23.1194 +
 23.1195 +        /**
 23.1196 +         * Produces a method handle for a reflected method.
 23.1197 +         * It will bypass checks for overriding methods on the receiver,
 23.1198 +         * <a href="MethodHandles.Lookup.html#equiv">as if called</a> from an {@code invokespecial}
 23.1199 +         * instruction from within the explicitly specified {@code specialCaller}.
 23.1200 +         * The type of the method handle will be that of the method,
 23.1201 +         * with a suitably restricted receiver type prepended.
 23.1202 +         * (The receiver type will be {@code specialCaller} or a subtype.)
 23.1203 +         * If the method's {@code accessible} flag is not set,
 23.1204 +         * access checking is performed immediately on behalf of the lookup class,
 23.1205 +         * as if {@code invokespecial} instruction were being linked.
 23.1206 +         * <p>
 23.1207 +         * Before method resolution,
 23.1208 +         * if the explicitly specified caller class is not identical with the
 23.1209 +         * lookup class, or if this lookup object does not have
 23.1210 +         * <a href="MethodHandles.Lookup.html#privacc">private access</a>
 23.1211 +         * privileges, the access fails.
 23.1212 +         * <p>
 23.1213 +         * The returned method handle will have
 23.1214 +         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
 23.1215 +         * the method's variable arity modifier bit ({@code 0x0080}) is set.
 23.1216 +         * @param m the reflected method
 23.1217 +         * @param specialCaller the class nominally calling the method
 23.1218 +         * @return a method handle which can invoke the reflected method
 23.1219 +         * @throws IllegalAccessException if access checking fails
 23.1220 +         *                                or if the method's variable arity modifier bit
 23.1221 +         *                                is set and {@code asVarargsCollector} fails
 23.1222 +         * @throws NullPointerException if any argument is null
 23.1223 +         */
 23.1224 +        public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws IllegalAccessException {
 23.1225 +            checkSpecialCaller(specialCaller);
 23.1226 +            Lookup specialLookup = this.in(specialCaller);
 23.1227 +            MemberName method = new MemberName(m, true);
 23.1228 +            assert(method.isMethod());
 23.1229 +            // ignore m.isAccessible:  this is a new kind of access
 23.1230 +            return specialLookup.getDirectMethodNoSecurityManager(REF_invokeSpecial, method.getDeclaringClass(), method, findBoundCallerClass(method));
 23.1231 +        }
 23.1232 +
 23.1233 +        /**
 23.1234 +         * Produces a method handle for a reflected constructor.
 23.1235 +         * The type of the method handle will be that of the constructor,
 23.1236 +         * with the return type changed to the declaring class.
 23.1237 +         * The method handle will perform a {@code newInstance} operation,
 23.1238 +         * creating a new instance of the constructor's class on the
 23.1239 +         * arguments passed to the method handle.
 23.1240 +         * <p>
 23.1241 +         * If the constructor's {@code accessible} flag is not set,
 23.1242 +         * access checking is performed immediately on behalf of the lookup class.
 23.1243 +         * <p>
 23.1244 +         * The returned method handle will have
 23.1245 +         * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
 23.1246 +         * the constructor's variable arity modifier bit ({@code 0x0080}) is set.
 23.1247 +         * <p>
 23.1248 +         * If the returned method handle is invoked, the constructor's class will
 23.1249 +         * be initialized, if it has not already been initialized.
 23.1250 +         * @param c the reflected constructor
 23.1251 +         * @return a method handle which can invoke the reflected constructor
 23.1252 +         * @throws IllegalAccessException if access checking fails
 23.1253 +         *                                or if the method's variable arity modifier bit
 23.1254 +         *                                is set and {@code asVarargsCollector} fails
 23.1255 +         * @throws NullPointerException if the argument is null
 23.1256 +         */
 23.1257 +        public MethodHandle unreflectConstructor(Constructor<?> c) throws IllegalAccessException {
 23.1258 +            MemberName ctor = new MemberName(c);
 23.1259 +            assert(ctor.isConstructor());
 23.1260 +            Lookup lookup = c.isAccessible() ? IMPL_LOOKUP : this;
 23.1261 +            return lookup.getDirectConstructorNoSecurityManager(ctor.getDeclaringClass(), ctor);
 23.1262 +        }
 23.1263 +
 23.1264 +        /**
 23.1265 +         * Produces a method handle giving read access to a reflected field.
 23.1266 +         * The type of the method handle will have a return type of the field's
 23.1267 +         * value type.
 23.1268 +         * If the field is static, the method handle will take no arguments.
 23.1269 +         * Otherwise, its single argument will be the instance containing
 23.1270 +         * the field.
 23.1271 +         * If the field's {@code accessible} flag is not set,
 23.1272 +         * access checking is performed immediately on behalf of the lookup class.
 23.1273 +         * <p>
 23.1274 +         * If the field is static, and
 23.1275 +         * if the returned method handle is invoked, the field's class will
 23.1276 +         * be initialized, if it has not already been initialized.
 23.1277 +         * @param f the reflected field
 23.1278 +         * @return a method handle which can load values from the reflected field
 23.1279 +         * @throws IllegalAccessException if access checking fails
 23.1280 +         * @throws NullPointerException if the argument is null
 23.1281 +         */
 23.1282 +        public MethodHandle unreflectGetter(Field f) throws IllegalAccessException {
 23.1283 +            return unreflectField(f, false);
 23.1284 +        }
 23.1285 +        private MethodHandle unreflectField(Field f, boolean isSetter) throws IllegalAccessException {
 23.1286 +            MemberName field = new MemberName(f, isSetter);
 23.1287 +            assert(isSetter
 23.1288 +                    ? MethodHandleNatives.refKindIsSetter(field.getReferenceKind())
 23.1289 +                    : MethodHandleNatives.refKindIsGetter(field.getReferenceKind()));
 23.1290 +            Lookup lookup = f.isAccessible() ? IMPL_LOOKUP : this;
 23.1291 +            return lookup.getDirectFieldNoSecurityManager(field.getReferenceKind(), f.getDeclaringClass(), field);
 23.1292 +        }
 23.1293 +
 23.1294 +        /**
 23.1295 +         * Produces a method handle giving write access to a reflected field.
 23.1296 +         * The type of the method handle will have a void return type.
 23.1297 +         * If the field is static, the method handle will take a single
 23.1298 +         * argument, of the field's value type, the value to be stored.
 23.1299 +         * Otherwise, the two arguments will be the instance containing
 23.1300 +         * the field, and the value to be stored.
 23.1301 +         * If the field's {@code accessible} flag is not set,
 23.1302 +         * access checking is performed immediately on behalf of the lookup class.
 23.1303 +         * <p>
 23.1304 +         * If the field is static, and
 23.1305 +         * if the returned method handle is invoked, the field's class will
 23.1306 +         * be initialized, if it has not already been initialized.
 23.1307 +         * @param f the reflected field
 23.1308 +         * @return a method handle which can store values into the reflected field
 23.1309 +         * @throws IllegalAccessException if access checking fails
 23.1310 +         * @throws NullPointerException if the argument is null
 23.1311 +         */
 23.1312 +        public MethodHandle unreflectSetter(Field f) throws IllegalAccessException {
 23.1313 +            return unreflectField(f, true);
 23.1314 +        }
 23.1315 +
 23.1316 +        /**
 23.1317 +         * Cracks a <a href="MethodHandleInfo.html#directmh">direct method handle</a>
 23.1318 +         * created by this lookup object or a similar one.
 23.1319 +         * Security and access checks are performed to ensure that this lookup object
 23.1320 +         * is capable of reproducing the target method handle.
 23.1321 +         * This means that the cracking may fail if target is a direct method handle
 23.1322 +         * but was created by an unrelated lookup object.
 23.1323 +         * This can happen if the method handle is <a href="MethodHandles.Lookup.html#callsens">caller sensitive</a>
 23.1324 +         * and was created by a lookup object for a different class.
 23.1325 +         * @param target a direct method handle to crack into symbolic reference components
 23.1326 +         * @return a symbolic reference which can be used to reconstruct this method handle from this lookup object
 23.1327 +         * @exception SecurityException if a security manager is present and it
 23.1328 +         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
 23.1329 +         * @throws IllegalArgumentException if the target is not a direct method handle or if access checking fails
 23.1330 +         * @exception NullPointerException if the target is {@code null}
 23.1331 +         * @see MethodHandleInfo
 23.1332 +         * @since 1.8
 23.1333 +         */
 23.1334 +        public MethodHandleInfo revealDirect(MethodHandle target) {
 23.1335 +            MemberName member = target.internalMemberName();
 23.1336 +            if (member == null || (!member.isResolved() && !member.isMethodHandleInvoke()))
 23.1337 +                throw newIllegalArgumentException("not a direct method handle");
 23.1338 +            Class<?> defc = member.getDeclaringClass();
 23.1339 +            byte refKind = member.getReferenceKind();
 23.1340 +            assert(MethodHandleNatives.refKindIsValid(refKind));
 23.1341 +            if (refKind == REF_invokeSpecial && !target.isInvokeSpecial())
 23.1342 +                // Devirtualized method invocation is usually formally virtual.
 23.1343 +                // To avoid creating extra MemberName objects for this common case,
 23.1344 +                // we encode this extra degree of freedom using MH.isInvokeSpecial.
 23.1345 +                refKind = REF_invokeVirtual;
 23.1346 +            if (refKind == REF_invokeVirtual && defc.isInterface())
 23.1347 +                // Symbolic reference is through interface but resolves to Object method (toString, etc.)
 23.1348 +                refKind = REF_invokeInterface;
 23.1349 +            // Check SM permissions and member access before cracking.
 23.1350 +            try {
 23.1351 +                checkAccess(refKind, defc, member);
 23.1352 +                checkSecurityManager(defc, member);
 23.1353 +            } catch (IllegalAccessException ex) {
 23.1354 +                throw new IllegalArgumentException(ex);
 23.1355 +            }
 23.1356 +            if (allowedModes != TRUSTED && member.isCallerSensitive()) {
 23.1357 +                Class<?> callerClass = target.internalCallerClass();
 23.1358 +                if (!hasPrivateAccess() || callerClass != lookupClass())
 23.1359 +                    throw new IllegalArgumentException("method handle is caller sensitive: "+callerClass);
 23.1360 +            }
 23.1361 +            // Produce the handle to the results.
 23.1362 +            return new InfoFromMemberName(this, member, refKind);
 23.1363 +        }
 23.1364 +
 23.1365 +        /// Helper methods, all package-private.
 23.1366 +
 23.1367 +        MemberName resolveOrFail(byte refKind, Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
 23.1368 +            checkSymbolicClass(refc);  // do this before attempting to resolve
 23.1369 +            name.getClass();  // NPE
 23.1370 +            type.getClass();  // NPE
 23.1371 +            return IMPL_NAMES.resolveOrFail(refKind, new MemberName(refc, name, type, refKind), lookupClassOrNull(),
 23.1372 +                                            NoSuchFieldException.class);
 23.1373 +        }
 23.1374 +
 23.1375 +        MemberName resolveOrFail(byte refKind, Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
 23.1376 +            checkSymbolicClass(refc);  // do this before attempting to resolve
 23.1377 +            name.getClass();  // NPE
 23.1378 +            type.getClass();  // NPE
 23.1379 +            checkMethodName(refKind, name);  // NPE check on name
 23.1380 +            return IMPL_NAMES.resolveOrFail(refKind, new MemberName(refc, name, type, refKind), lookupClassOrNull(),
 23.1381 +                                            NoSuchMethodException.class);
 23.1382 +        }
 23.1383 +
 23.1384 +        MemberName resolveOrFail(byte refKind, MemberName member) throws ReflectiveOperationException {
 23.1385 +            checkSymbolicClass(member.getDeclaringClass());  // do this before attempting to resolve
 23.1386 +            member.getName().getClass();  // NPE
 23.1387 +            member.getType().getClass();  // NPE
 23.1388 +            return IMPL_NAMES.resolveOrFail(refKind, member, lookupClassOrNull(),
 23.1389 +                                            ReflectiveOperationException.class);
 23.1390 +        }
 23.1391 +
 23.1392 +        void checkSymbolicClass(Class<?> refc) throws IllegalAccessException {
 23.1393 +            refc.getClass();  // NPE
 23.1394 +            Class<?> caller = lookupClassOrNull();
 23.1395 +            if (caller != null && !VerifyAccess.isClassAccessible(refc, caller, allowedModes))
 23.1396 +                throw new MemberName(refc).makeAccessException("symbolic reference class is not public", this);
 23.1397 +        }
 23.1398 +
 23.1399 +        /** Check name for an illegal leading "&lt;" character. */
 23.1400 +        void checkMethodName(byte refKind, String name) throws NoSuchMethodException {
 23.1401 +            if (name.startsWith("<") && refKind != REF_newInvokeSpecial)
 23.1402 +                throw new NoSuchMethodException("illegal method name: "+name);
 23.1403 +        }
 23.1404 +
 23.1405 +
 23.1406 +        /**
 23.1407 +         * Find my trustable caller class if m is a caller sensitive method.
 23.1408 +         * If this lookup object has private access, then the caller class is the lookupClass.
 23.1409 +         * Otherwise, if m is caller-sensitive, throw IllegalAccessException.
 23.1410 +         */
 23.1411 +        Class<?> findBoundCallerClass(MemberName m) throws IllegalAccessException {
 23.1412 +            Class<?> callerClass = null;
 23.1413 +            if (MethodHandleNatives.isCallerSensitive(m)) {
 23.1414 +                // Only lookups with private access are allowed to resolve caller-sensitive methods
 23.1415 +                if (hasPrivateAccess()) {
 23.1416 +                    callerClass = lookupClass;
 23.1417 +                } else {
 23.1418 +                    throw new IllegalAccessException("Attempt to lookup caller-sensitive method using restricted lookup object");
 23.1419 +                }
 23.1420 +            }
 23.1421 +            return callerClass;
 23.1422 +        }
 23.1423 +
 23.1424 +        private boolean hasPrivateAccess() {
 23.1425 +            return (allowedModes & PRIVATE) != 0;
 23.1426 +        }
 23.1427 +
 23.1428 +        /**
 23.1429 +         * Perform necessary <a href="MethodHandles.Lookup.html#secmgr">access checks</a>.
 23.1430 +         * Determines a trustable caller class to compare with refc, the symbolic reference class.
 23.1431 +         * If this lookup object has private access, then the caller class is the lookupClass.
 23.1432 +         */
 23.1433 +        void checkSecurityManager(Class<?> refc, MemberName m) {
 23.1434 +            SecurityManager smgr = System.getSecurityManager();
 23.1435 +            if (smgr == null)  return;
 23.1436 +            if (allowedModes == TRUSTED)  return;
 23.1437 +
 23.1438 +            // Step 1:
 23.1439 +            boolean fullPowerLookup = hasPrivateAccess();
 23.1440 +            if (!fullPowerLookup ||
 23.1441 +                !VerifyAccess.classLoaderIsAncestor(lookupClass, refc)) {
 23.1442 +                ReflectUtil.checkPackageAccess(refc);
 23.1443 +            }
 23.1444 +
 23.1445 +            // Step 2:
 23.1446 +            if (m.isPublic()) return;
 23.1447 +            if (!fullPowerLookup) {
 23.1448 +                smgr.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION);
 23.1449 +            }
 23.1450 +
 23.1451 +            // Step 3:
 23.1452 +            Class<?> defc = m.getDeclaringClass();
 23.1453 +            if (!fullPowerLookup && defc != refc) {
 23.1454 +                ReflectUtil.checkPackageAccess(defc);
 23.1455 +            }
 23.1456 +        }
 23.1457 +
 23.1458 +        void checkMethod(byte refKind, Class<?> refc, MemberName m) throws IllegalAccessException {
 23.1459 +            boolean wantStatic = (refKind == REF_invokeStatic);
 23.1460 +            String message;
 23.1461 +            if (m.isConstructor())
 23.1462 +                message = "expected a method, not a constructor";
 23.1463 +            else if (!m.isMethod())
 23.1464 +                message = "expected a method";
 23.1465 +            else if (wantStatic != m.isStatic())
 23.1466 +                message = wantStatic ? "expected a static method" : "expected a non-static method";
 23.1467 +            else
 23.1468 +                { checkAccess(refKind, refc, m); return; }
 23.1469 +            throw m.makeAccessException(message, this);
 23.1470 +        }
 23.1471 +
 23.1472 +        void checkField(byte refKind, Class<?> refc, MemberName m) throws IllegalAccessException {
 23.1473 +            boolean wantStatic = !MethodHandleNatives.refKindHasReceiver(refKind);
 23.1474 +            String message;
 23.1475 +            if (wantStatic != m.isStatic())
 23.1476 +                message = wantStatic ? "expected a static field" : "expected a non-static field";
 23.1477 +            else
 23.1478 +                { checkAccess(refKind, refc, m); return; }
 23.1479 +            throw m.makeAccessException(message, this);
 23.1480 +        }
 23.1481 +
 23.1482 +        /** Check public/protected/private bits on the symbolic reference class and its member. */
 23.1483 +        void checkAccess(byte refKind, Class<?> refc, MemberName m) throws IllegalAccessException {
 23.1484 +            assert(m.referenceKindIsConsistentWith(refKind) &&
 23.1485 +                   MethodHandleNatives.refKindIsValid(refKind) &&
 23.1486 +                   (MethodHandleNatives.refKindIsField(refKind) == m.isField()));
 23.1487 +            int allowedModes = this.allowedModes;
 23.1488 +            if (allowedModes == TRUSTED)  return;
 23.1489 +            int mods = m.getModifiers();
 23.1490 +            if (Modifier.isProtected(mods) &&
 23.1491 +                    refKind == REF_invokeVirtual &&
 23.1492 +                    m.getDeclaringClass() == Object.class &&
 23.1493 +                    m.getName().equals("clone") &&
 23.1494 +                    refc.isArray()) {
 23.1495 +                // The JVM does this hack also.
 23.1496 +                // (See ClassVerifier::verify_invoke_instructions
 23.1497 +                // and LinkResolver::check_method_accessability.)
 23.1498 +                // Because the JVM does not allow separate methods on array types,
 23.1499 +                // there is no separate method for int[].clone.
 23.1500 +                // All arrays simply inherit Object.clone.
 23.1501 +                // But for access checking logic, we make Object.clone
 23.1502 +                // (normally protected) appear to be public.
 23.1503 +                // Later on, when the DirectMethodHandle is created,
 23.1504 +                // its leading argument will be restricted to the
 23.1505 +                // requested array type.
 23.1506 +                // N.B. The return type is not adjusted, because
 23.1507 +                // that is *not* the bytecode behavior.
 23.1508 +                mods ^= Modifier.PROTECTED | Modifier.PUBLIC;
 23.1509 +            }
 23.1510 +            if (Modifier.isFinal(mods) &&
 23.1511 +                    MethodHandleNatives.refKindIsSetter(refKind))
 23.1512 +                throw m.makeAccessException("unexpected set of a final field", this);
 23.1513 +            if (Modifier.isPublic(mods) && Modifier.isPublic(refc.getModifiers()) && allowedModes != 0)
 23.1514 +                return;  // common case
 23.1515 +            int requestedModes = fixmods(mods);  // adjust 0 => PACKAGE
 23.1516 +            if ((requestedModes & allowedModes) != 0) {
 23.1517 +                if (VerifyAccess.isMemberAccessible(refc, m.getDeclaringClass(),
 23.1518 +                                                    mods, lookupClass(), allowedModes))
 23.1519 +                    return;
 23.1520 +            } else {
 23.1521 +                // Protected members can also be checked as if they were package-private.
 23.1522 +                if ((requestedModes & PROTECTED) != 0 && (allowedModes & PACKAGE) != 0
 23.1523 +                        && VerifyAccess.isSamePackage(m.getDeclaringClass(), lookupClass()))
 23.1524 +                    return;
 23.1525 +            }
 23.1526 +            throw m.makeAccessException(accessFailedMessage(refc, m), this);
 23.1527 +        }
 23.1528 +
 23.1529 +        String accessFailedMessage(Class<?> refc, MemberName m) {
 23.1530 +            Class<?> defc = m.getDeclaringClass();
 23.1531 +            int mods = m.getModifiers();
 23.1532 +            // check the class first:
 23.1533 +            boolean classOK = (Modifier.isPublic(defc.getModifiers()) &&
 23.1534 +                               (defc == refc ||
 23.1535 +                                Modifier.isPublic(refc.getModifiers())));
 23.1536 +            if (!classOK && (allowedModes & PACKAGE) != 0) {
 23.1537 +                classOK = (VerifyAccess.isClassAccessible(defc, lookupClass(), ALL_MODES) &&
 23.1538 +                           (defc == refc ||
 23.1539 +                            VerifyAccess.isClassAccessible(refc, lookupClass(), ALL_MODES)));
 23.1540 +            }
 23.1541 +            if (!classOK)
 23.1542 +                return "class is not public";
 23.1543 +            if (Modifier.isPublic(mods))
 23.1544 +                return "access to public member failed";  // (how?)
 23.1545 +            if (Modifier.isPrivate(mods))
 23.1546 +                return "member is private";
 23.1547 +            if (Modifier.isProtected(mods))
 23.1548 +                return "member is protected";
 23.1549 +            return "member is private to package";
 23.1550 +        }
 23.1551 +
 23.1552 +        private static final boolean ALLOW_NESTMATE_ACCESS = false;
 23.1553 +
 23.1554 +        private void checkSpecialCaller(Class<?> specialCaller) throws IllegalAccessException {
 23.1555 +            int allowedModes = this.allowedModes;
 23.1556 +            if (allowedModes == TRUSTED)  return;
 23.1557 +            if (!hasPrivateAccess()
 23.1558 +                || (specialCaller != lookupClass()
 23.1559 +                    && !(ALLOW_NESTMATE_ACCESS &&
 23.1560 +                         VerifyAccess.isSamePackageMember(specialCaller, lookupClass()))))
 23.1561 +                throw new MemberName(specialCaller).
 23.1562 +                    makeAccessException("no private access for invokespecial", this);
 23.1563 +        }
 23.1564 +
 23.1565 +        private boolean restrictProtectedReceiver(MemberName method) {
 23.1566 +            // The accessing class only has the right to use a protected member
 23.1567 +            // on itself or a subclass.  Enforce that restriction, from JVMS 5.4.4, etc.
 23.1568 +            if (!method.isProtected() || method.isStatic()
 23.1569 +                || allowedModes == TRUSTED
 23.1570 +                || method.getDeclaringClass() == lookupClass()
 23.1571 +                || VerifyAccess.isSamePackage(method.getDeclaringClass(), lookupClass())
 23.1572 +                || (ALLOW_NESTMATE_ACCESS &&
 23.1573 +                    VerifyAccess.isSamePackageMember(method.getDeclaringClass(), lookupClass())))
 23.1574 +                return false;
 23.1575 +            return true;
 23.1576 +        }
 23.1577 +        private MethodHandle restrictReceiver(MemberName method, MethodHandle mh, Class<?> caller) throws IllegalAccessException {
 23.1578 +            assert(!method.isStatic());
 23.1579 +            // receiver type of mh is too wide; narrow to caller
 23.1580 +            if (!method.getDeclaringClass().isAssignableFrom(caller)) {
 23.1581 +                throw method.makeAccessException("caller class must be a subclass below the method", caller);
 23.1582 +            }
 23.1583 +            MethodType rawType = mh.type();
 23.1584 +            if (rawType.parameterType(0) == caller)  return mh;
 23.1585 +            MethodType narrowType = rawType.changeParameterType(0, caller);
 23.1586 +            return mh.viewAsType(narrowType);
 23.1587 +        }
 23.1588 +
 23.1589 +        /** Check access and get the requested method. */
 23.1590 +        private MethodHandle getDirectMethod(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException {
 23.1591 +            final boolean doRestrict    = true;
 23.1592 +            final boolean checkSecurity = true;
 23.1593 +            return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, callerClass);
 23.1594 +        }
 23.1595 +        /** Check access and get the requested method, eliding receiver narrowing rules. */
 23.1596 +        private MethodHandle getDirectMethodNoRestrict(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException {
 23.1597 +            final boolean doRestrict    = false;
 23.1598 +            final boolean checkSecurity = true;
 23.1599 +            return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, callerClass);
 23.1600 +        }
 23.1601 +        /** Check access and get the requested method, eliding security manager checks. */
 23.1602 +        private MethodHandle getDirectMethodNoSecurityManager(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException {
 23.1603 +            final boolean doRestrict    = true;
 23.1604 +            final boolean checkSecurity = false;  // not needed for reflection or for linking CONSTANT_MH constants
 23.1605 +            return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, callerClass);
 23.1606 +        }
 23.1607 +        /** Common code for all methods; do not call directly except from immediately above. */
 23.1608 +        private MethodHandle getDirectMethodCommon(byte refKind, Class<?> refc, MemberName method,
 23.1609 +                                                   boolean checkSecurity,
 23.1610 +                                                   boolean doRestrict, Class<?> callerClass) throws IllegalAccessException {
 23.1611 +            checkMethod(refKind, refc, method);
 23.1612 +            // Optionally check with the security manager; this isn't needed for unreflect* calls.
 23.1613 +            if (checkSecurity)
 23.1614 +                checkSecurityManager(refc, method);
 23.1615 +            assert(!method.isMethodHandleInvoke());
 23.1616 +
 23.1617 +            Class<?> refcAsSuper;
 23.1618 +            if (refKind == REF_invokeSpecial &&
 23.1619 +                refc != lookupClass() &&
 23.1620 +                !refc.isInterface() &&
 23.1621 +                refc != (refcAsSuper = lookupClass().getSuperclass()) &&
 23.1622 +                refc.isAssignableFrom(lookupClass())) {
 23.1623 +                assert(!method.getName().equals("<init>"));  // not this code path
 23.1624 +                // Per JVMS 6.5, desc. of invokespecial instruction:
 23.1625 +                // If the method is in a superclass of the LC,
 23.1626 +                // and if our original search was above LC.super,
 23.1627 +                // repeat the search (symbolic lookup) from LC.super.
 23.1628 +                // FIXME: MemberName.resolve should handle this instead.
 23.1629 +                MemberName m2 = new MemberName(refcAsSuper,
 23.1630 +                                               method.getName(),
 23.1631 +                                               method.getMethodType(),
 23.1632 +                                               REF_invokeSpecial);
 23.1633 +                m2 = IMPL_NAMES.resolveOrNull(refKind, m2, lookupClassOrNull());
 23.1634 +                if (m2 == null)  throw new InternalError(method.toString());
 23.1635 +                method = m2;
 23.1636 +                refc = refcAsSuper;
 23.1637 +                // redo basic checks
 23.1638 +                checkMethod(refKind, refc, method);
 23.1639 +            }
 23.1640 +
 23.1641 +            MethodHandle mh = DirectMethodHandle.make(refKind, refc, method);
 23.1642 +            mh = maybeBindCaller(method, mh, callerClass);
 23.1643 +            mh = mh.setVarargs(method);
 23.1644 +            // Optionally narrow the receiver argument to refc using restrictReceiver.
 23.1645 +            if (doRestrict &&
 23.1646 +                   (refKind == REF_invokeSpecial ||
 23.1647 +                       (MethodHandleNatives.refKindHasReceiver(refKind) &&
 23.1648 +                           restrictProtectedReceiver(method))))
 23.1649 +                mh = restrictReceiver(method, mh, lookupClass());
 23.1650 +            return mh;
 23.1651 +        }
 23.1652 +        private MethodHandle maybeBindCaller(MemberName method, MethodHandle mh,
 23.1653 +                                             Class<?> callerClass)
 23.1654 +                                             throws IllegalAccessException {
 23.1655 +            if (allowedModes == TRUSTED || !MethodHandleNatives.isCallerSensitive(method))
 23.1656 +                return mh;
 23.1657 +            Class<?> hostClass = lookupClass;
 23.1658 +            if (!hasPrivateAccess())  // caller must have private access
 23.1659 +                hostClass = callerClass;  // callerClass came from a security manager style stack walk
 23.1660 +            MethodHandle cbmh = MethodHandleImpl.bindCaller(mh, hostClass);
 23.1661 +            // Note: caller will apply varargs after this step happens.
 23.1662 +            return cbmh;
 23.1663 +        }
 23.1664 +        /** Check access and get the requested field. */
 23.1665 +        private MethodHandle getDirectField(byte refKind, Class<?> refc, MemberName field) throws IllegalAccessException {
 23.1666 +            final boolean checkSecurity = true;
 23.1667 +            return getDirectFieldCommon(refKind, refc, field, checkSecurity);
 23.1668 +        }
 23.1669 +        /** Check access and get the requested field, eliding security manager checks. */
 23.1670 +        private MethodHandle getDirectFieldNoSecurityManager(byte refKind, Class<?> refc, MemberName field) throws IllegalAccessException {
 23.1671 +            final boolean checkSecurity = false;  // not needed for reflection or for linking CONSTANT_MH constants
 23.1672 +            return getDirectFieldCommon(refKind, refc, field, checkSecurity);
 23.1673 +        }
 23.1674 +        /** Common code for all fields; do not call directly except from immediately above. */
 23.1675 +        private MethodHandle getDirectFieldCommon(byte refKind, Class<?> refc, MemberName field,
 23.1676 +                                                  boolean checkSecurity) throws IllegalAccessException {
 23.1677 +            checkField(refKind, refc, field);
 23.1678 +            // Optionally check with the security manager; this isn't needed for unreflect* calls.
 23.1679 +            if (checkSecurity)
 23.1680 +                checkSecurityManager(refc, field);
 23.1681 +            MethodHandle mh = DirectMethodHandle.make(refc, field);
 23.1682 +            boolean doRestrict = (MethodHandleNatives.refKindHasReceiver(refKind) &&
 23.1683 +                                    restrictProtectedReceiver(field));
 23.1684 +            if (doRestrict)
 23.1685 +                mh = restrictReceiver(field, mh, lookupClass());
 23.1686 +            return mh;
 23.1687 +        }
 23.1688 +        /** Check access and get the requested constructor. */
 23.1689 +        private MethodHandle getDirectConstructor(Class<?> refc, MemberName ctor) throws IllegalAccessException {
 23.1690 +            final boolean checkSecurity = true;
 23.1691 +            return getDirectConstructorCommon(refc, ctor, checkSecurity);
 23.1692 +        }
 23.1693 +        /** Check access and get the requested constructor, eliding security manager checks. */
 23.1694 +        private MethodHandle getDirectConstructorNoSecurityManager(Class<?> refc, MemberName ctor) throws IllegalAccessException {
 23.1695 +            final boolean checkSecurity = false;  // not needed for reflection or for linking CONSTANT_MH constants
 23.1696 +            return getDirectConstructorCommon(refc, ctor, checkSecurity);
 23.1697 +        }
 23.1698 +        /** Common code for all constructors; do not call directly except from immediately above. */
 23.1699 +        private MethodHandle getDirectConstructorCommon(Class<?> refc, MemberName ctor,
 23.1700 +                                                  boolean checkSecurity) throws IllegalAccessException {
 23.1701 +            assert(ctor.isConstructor());
 23.1702 +            checkAccess(REF_newInvokeSpecial, refc, ctor);
 23.1703 +            // Optionally check with the security manager; this isn't needed for unreflect* calls.
 23.1704 +            if (checkSecurity)
 23.1705 +                checkSecurityManager(refc, ctor);
 23.1706 +            assert(!MethodHandleNatives.isCallerSensitive(ctor));  // maybeBindCaller not relevant here
 23.1707 +            return DirectMethodHandle.make(ctor).setVarargs(ctor);
 23.1708 +        }
 23.1709 +
 23.1710 +        /** Hook called from the JVM (via MethodHandleNatives) to link MH constants:
 23.1711 +         */
 23.1712 +        /*non-public*/
 23.1713 +        MethodHandle linkMethodHandleConstant(byte refKind, Class<?> defc, String name, Object type) throws ReflectiveOperationException {
 23.1714 +            if (!(type instanceof Class || type instanceof MethodType))
 23.1715 +                throw new InternalError("unresolved MemberName");
 23.1716 +            MemberName member = new MemberName(refKind, defc, name, type);
 23.1717 +            MethodHandle mh = LOOKASIDE_TABLE.get(member);
 23.1718 +            if (mh != null) {
 23.1719 +                checkSymbolicClass(defc);
 23.1720 +                return mh;
 23.1721 +            }
 23.1722 +            // Treat MethodHandle.invoke and invokeExact specially.
 23.1723 +            if (defc == MethodHandle.class && refKind == REF_invokeVirtual) {
 23.1724 +                mh = findVirtualForMH(member.getName(), member.getMethodType());
 23.1725 +                if (mh != null) {
 23.1726 +                    return mh;
 23.1727 +                }
 23.1728 +            }
 23.1729 +            MemberName resolved = resolveOrFail(refKind, member);
 23.1730 +            mh = getDirectMethodForConstant(refKind, defc, resolved);
 23.1731 +            if (mh instanceof DirectMethodHandle
 23.1732 +                    && canBeCached(refKind, defc, resolved)) {
 23.1733 +                MemberName key = mh.internalMemberName();
 23.1734 +                if (key != null) {
 23.1735 +                    key = key.asNormalOriginal();
 23.1736 +                }
 23.1737 +                if (member.equals(key)) {  // better safe than sorry
 23.1738 +                    LOOKASIDE_TABLE.put(key, (DirectMethodHandle) mh);
 23.1739 +                }
 23.1740 +            }
 23.1741 +            return mh;
 23.1742 +        }
 23.1743 +        private
 23.1744 +        boolean canBeCached(byte refKind, Class<?> defc, MemberName member) {
 23.1745 +            if (refKind == REF_invokeSpecial) {
 23.1746 +                return false;
 23.1747 +            }
 23.1748 +            if (!Modifier.isPublic(defc.getModifiers()) ||
 23.1749 +                    !Modifier.isPublic(member.getDeclaringClass().getModifiers()) ||
 23.1750 +                    !member.isPublic() ||
 23.1751 +                    member.isCallerSensitive()) {
 23.1752 +                return false;
 23.1753 +            }
 23.1754 +            ClassLoader loader = defc.getClassLoader();
 23.1755 +            if (!sun.misc.VM.isSystemDomainLoader(loader)) {
 23.1756 +                ClassLoader sysl = ClassLoader.getSystemClassLoader();
 23.1757 +                boolean found = false;
 23.1758 +                while (sysl != null) {
 23.1759 +                    if (loader == sysl) { found = true; break; }
 23.1760 +                    sysl = sysl.getParent();
 23.1761 +                }
 23.1762 +                if (!found) {
 23.1763 +                    return false;
 23.1764 +                }
 23.1765 +            }
 23.1766 +            try {
 23.1767 +                MemberName resolved2 = publicLookup().resolveOrFail(refKind,
 23.1768 +                    new MemberName(refKind, defc, member.getName(), member.getType()));
 23.1769 +                checkSecurityManager(defc, resolved2);
 23.1770 +            } catch (ReflectiveOperationException | SecurityException ex) {
 23.1771 +                return false;
 23.1772 +            }
 23.1773 +            return true;
 23.1774 +        }
 23.1775 +        private
 23.1776 +        MethodHandle getDirectMethodForConstant(byte refKind, Class<?> defc, MemberName member)
 23.1777 +                throws ReflectiveOperationException {
 23.1778 +            if (MethodHandleNatives.refKindIsField(refKind)) {
 23.1779 +                return getDirectFieldNoSecurityManager(refKind, defc, member);
 23.1780 +            } else if (MethodHandleNatives.refKindIsMethod(refKind)) {
 23.1781 +                return getDirectMethodNoSecurityManager(refKind, defc, member, lookupClass);
 23.1782 +            } else if (refKind == REF_newInvokeSpecial) {
 23.1783 +                return getDirectConstructorNoSecurityManager(defc, member);
 23.1784 +            }
 23.1785 +            // oops
 23.1786 +            throw newIllegalArgumentException("bad MethodHandle constant #"+member);
 23.1787 +        }
 23.1788 +
 23.1789 +        static ConcurrentHashMap<MemberName, DirectMethodHandle> LOOKASIDE_TABLE = new ConcurrentHashMap<>();
 23.1790 +    }
 23.1791 +
 23.1792 +    /**
 23.1793 +     * Produces a method handle giving read access to elements of an array.
 23.1794 +     * The type of the method handle will have a return type of the array's
 23.1795 +     * element type.  Its first argument will be the array type,
 23.1796 +     * and the second will be {@code int}.
 23.1797 +     * @param arrayClass an array type
 23.1798 +     * @return a method handle which can load values from the given array type
 23.1799 +     * @throws NullPointerException if the argument is null
 23.1800 +     * @throws  IllegalArgumentException if arrayClass is not an array type
 23.1801 +     */
 23.1802 +    public static
 23.1803 +    MethodHandle arrayElementGetter(Class<?> arrayClass) throws IllegalArgumentException {
 23.1804 +        return MethodHandleImpl.makeArrayElementAccessor(arrayClass, false);
 23.1805 +    }
 23.1806 +
 23.1807 +    /**
 23.1808 +     * Produces a method handle giving write access to elements of an array.
 23.1809 +     * The type of the method handle will have a void return type.
 23.1810 +     * Its last argument will be the array's element type.
 23.1811 +     * The first and second arguments will be the array type and int.
 23.1812 +     * @param arrayClass the class of an array
 23.1813 +     * @return a method handle which can store values into the array type
 23.1814 +     * @throws NullPointerException if the argument is null
 23.1815 +     * @throws IllegalArgumentException if arrayClass is not an array type
 23.1816 +     */
 23.1817 +    public static
 23.1818 +    MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException {
 23.1819 +        return MethodHandleImpl.makeArrayElementAccessor(arrayClass, true);
 23.1820 +    }
 23.1821 +
 23.1822 +    /// method handle invocation (reflective style)
 23.1823 +
 23.1824 +    /**
 23.1825 +     * Produces a method handle which will invoke any method handle of the
 23.1826 +     * given {@code type}, with a given number of trailing arguments replaced by
 23.1827 +     * a single trailing {@code Object[]} array.
 23.1828 +     * The resulting invoker will be a method handle with the following
 23.1829 +     * arguments:
 23.1830 +     * <ul>
 23.1831 +     * <li>a single {@code MethodHandle} target
 23.1832 +     * <li>zero or more leading values (counted by {@code leadingArgCount})
 23.1833 +     * <li>an {@code Object[]} array containing trailing arguments
 23.1834 +     * </ul>
 23.1835 +     * <p>
 23.1836 +     * The invoker will invoke its target like a call to {@link MethodHandle#invoke invoke} with
 23.1837 +     * the indicated {@code type}.
 23.1838 +     * That is, if the target is exactly of the given {@code type}, it will behave
 23.1839 +     * like {@code invokeExact}; otherwise it behave as if {@link MethodHandle#asType asType}
 23.1840 +     * is used to convert the target to the required {@code type}.
 23.1841 +     * <p>
 23.1842 +     * The type of the returned invoker will not be the given {@code type}, but rather
 23.1843 +     * will have all parameters except the first {@code leadingArgCount}
 23.1844 +     * replaced by a single array of type {@code Object[]}, which will be
 23.1845 +     * the final parameter.
 23.1846 +     * <p>
 23.1847 +     * Before invoking its target, the invoker will spread the final array, apply
 23.1848 +     * reference casts as necessary, and unbox and widen primitive arguments.
 23.1849 +     * If, when the invoker is called, the supplied array argument does
 23.1850 +     * not have the correct number of elements, the invoker will throw
 23.1851 +     * an {@link IllegalArgumentException} instead of invoking the target.
 23.1852 +     * <p>
 23.1853 +     * This method is equivalent to the following code (though it may be more efficient):
 23.1854 +     * <blockquote><pre>{@code
 23.1855 +MethodHandle invoker = MethodHandles.invoker(type);
 23.1856 +int spreadArgCount = type.parameterCount() - leadingArgCount;
 23.1857 +invoker = invoker.asSpreader(Object[].class, spreadArgCount);
 23.1858 +return invoker;
 23.1859 +     * }</pre></blockquote>
 23.1860 +     * This method throws no reflective or security exceptions.
 23.1861 +     * @param type the desired target type
 23.1862 +     * @param leadingArgCount number of fixed arguments, to be passed unchanged to the target
 23.1863 +     * @return a method handle suitable for invoking any method handle of the given type
 23.1864 +     * @throws NullPointerException if {@code type} is null
 23.1865 +     * @throws IllegalArgumentException if {@code leadingArgCount} is not in
 23.1866 +     *                  the range from 0 to {@code type.parameterCount()} inclusive,
 23.1867 +     *                  or if the resulting method handle's type would have
 23.1868 +     *          <a href="MethodHandle.html#maxarity">too many parameters</a>
 23.1869 +     */
 23.1870 +    static public
 23.1871 +    MethodHandle spreadInvoker(MethodType type, int leadingArgCount) {
 23.1872 +        if (leadingArgCount < 0 || leadingArgCount > type.parameterCount())
 23.1873 +            throw new IllegalArgumentException("bad argument count "+leadingArgCount);
 23.1874 +        return type.invokers().spreadInvoker(leadingArgCount);
 23.1875 +    }
 23.1876 +
 23.1877 +    /**
 23.1878 +     * Produces a special <em>invoker method handle</em> which can be used to
 23.1879 +     * invoke any method handle of the given type, as if by {@link MethodHandle#invokeExact invokeExact}.
 23.1880 +     * The resulting invoker will have a type which is
 23.1881 +     * exactly equal to the desired type, except that it will accept
 23.1882 +     * an additional leading argument of type {@code MethodHandle}.
 23.1883 +     * <p>
 23.1884 +     * This method is equivalent to the following code (though it may be more efficient):
 23.1885 +     * {@code publicLookup().findVirtual(MethodHandle.class, "invokeExact", type)}
 23.1886 +     *
 23.1887 +     * <p style="font-size:smaller;">
 23.1888 +     * <em>Discussion:</em>
 23.1889 +     * Invoker method handles can be useful when working with variable method handles
 23.1890 +     * of unknown types.
 23.1891 +     * For example, to emulate an {@code invokeExact} call to a variable method
 23.1892 +     * handle {@code M}, extract its type {@code T},
 23.1893 +     * look up the invoker method {@code X} for {@code T},
 23.1894 +     * and call the invoker method, as {@code X.invoke(T, A...)}.
 23.1895 +     * (It would not work to call {@code X.invokeExact}, since the type {@code T}
 23.1896 +     * is unknown.)
 23.1897 +     * If spreading, collecting, or other argument transformations are required,
 23.1898 +     * they can be applied once to the invoker {@code X} and reused on many {@code M}
 23.1899 +     * method handle values, as long as they are compatible with the type of {@code X}.
 23.1900 +     * <p style="font-size:smaller;">
 23.1901 +     * <em>(Note:  The invoker method is not available via the Core Reflection API.
 23.1902 +     * An attempt to call {@linkplain java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}
 23.1903 +     * on the declared {@code invokeExact} or {@code invoke} method will raise an
 23.1904 +     * {@link java.lang.UnsupportedOperationException UnsupportedOperationException}.)</em>
 23.1905 +     * <p>
 23.1906 +     * This method throws no reflective or security exceptions.
 23.1907 +     * @param type the desired target type
 23.1908 +     * @return a method handle suitable for invoking any method handle of the given type
 23.1909 +     * @throws IllegalArgumentException if the resulting method handle's type would have
 23.1910 +     *          <a href="MethodHandle.html#maxarity">too many parameters</a>
 23.1911 +     */
 23.1912 +    static public
 23.1913 +    MethodHandle exactInvoker(MethodType type) {
 23.1914 +        return type.invokers().exactInvoker();
 23.1915 +    }
 23.1916 +
 23.1917 +    /**
 23.1918 +     * Produces a special <em>invoker method handle</em> which can be used to
 23.1919 +     * invoke any method handle compatible with the given type, as if by {@link MethodHandle#invoke invoke}.
 23.1920 +     * The resulting invoker will have a type which is
 23.1921 +     * exactly equal to the desired type, except that it will accept
 23.1922 +     * an additional leading argument of type {@code MethodHandle}.
 23.1923 +     * <p>
 23.1924 +     * Before invoking its target, if the target differs from the expected type,
 23.1925 +     * the invoker will apply reference casts as
 23.1926 +     * necessary and box, unbox, or widen primitive values, as if by {@link MethodHandle#asType asType}.
 23.1927 +     * Similarly, the return value will be converted as necessary.
 23.1928 +     * If the target is a {@linkplain MethodHandle#asVarargsCollector variable arity method handle},
 23.1929 +     * the required arity conversion will be made, again as if by {@link MethodHandle#asType asType}.
 23.1930 +     * <p>
 23.1931 +     * This method is equivalent to the following code (though it may be more efficient):
 23.1932 +     * {@code publicLookup().findVirtual(MethodHandle.class, "invoke", type)}
 23.1933 +     * <p style="font-size:smaller;">
 23.1934 +     * <em>Discussion:</em>
 23.1935 +     * A {@linkplain MethodType#genericMethodType general method type} is one which
 23.1936 +     * mentions only {@code Object} arguments and return values.
 23.1937 +     * An invoker for such a type is capable of calling any method handle
 23.1938 +     * of the same arity as the general type.
 23.1939 +     * <p style="font-size:smaller;">
 23.1940 +     * <em>(Note:  The invoker method is not available via the Core Reflection API.
 23.1941 +     * An attempt to call {@linkplain java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}
 23.1942 +     * on the declared {@code invokeExact} or {@code invoke} method will raise an
 23.1943 +     * {@link java.lang.UnsupportedOperationException UnsupportedOperationException}.)</em>
 23.1944 +     * <p>
 23.1945 +     * This method throws no reflective or security exceptions.
 23.1946 +     * @param type the desired target type
 23.1947 +     * @return a method handle suitable for invoking any method handle convertible to the given type
 23.1948 +     * @throws IllegalArgumentException if the resulting method handle's type would have
 23.1949 +     *          <a href="MethodHandle.html#maxarity">too many parameters</a>
 23.1950 +     */
 23.1951 +    static public
 23.1952 +    MethodHandle invoker(MethodType type) {
 23.1953 +        return type.invokers().generalInvoker();
 23.1954 +    }
 23.1955 +
 23.1956 +    static /*non-public*/
 23.1957 +    MethodHandle basicInvoker(MethodType type) {
 23.1958 +        return type.form().basicInvoker();
 23.1959 +    }
 23.1960 +
 23.1961 +     /// method handle modification (creation from other method handles)
 23.1962 +
 23.1963 +    /**
 23.1964 +     * Produces a method handle which adapts the type of the
 23.1965 +     * given method handle to a new type by pairwise argument and return type conversion.
 23.1966 +     * The original type and new type must have the same number of arguments.
 23.1967 +     * The resulting method handle is guaranteed to report a type
 23.1968 +     * which is equal to the desired new type.
 23.1969 +     * <p>
 23.1970 +     * If the original type and new type are equal, returns target.
 23.1971 +     * <p>
 23.1972 +     * The same conversions are allowed as for {@link MethodHandle#asType MethodHandle.asType},
 23.1973 +     * and some additional conversions are also applied if those conversions fail.
 23.1974 +     * Given types <em>T0</em>, <em>T1</em>, one of the following conversions is applied
 23.1975 +     * if possible, before or instead of any conversions done by {@code asType}:
 23.1976 +     * <ul>
 23.1977 +     * <li>If <em>T0</em> and <em>T1</em> are references, and <em>T1</em> is an interface type,
 23.1978 +     *     then the value of type <em>T0</em> is passed as a <em>T1</em> without a cast.
 23.1979 +     *     (This treatment of interfaces follows the usage of the bytecode verifier.)
 23.1980 +     * <li>If <em>T0</em> is boolean and <em>T1</em> is another primitive,
 23.1981 +     *     the boolean is converted to a byte value, 1 for true, 0 for false.
 23.1982 +     *     (This treatment follows the usage of the bytecode verifier.)
 23.1983 +     * <li>If <em>T1</em> is boolean and <em>T0</em> is another primitive,
 23.1984 +     *     <em>T0</em> is converted to byte via Java casting conversion (JLS 5.5),
 23.1985 +     *     and the low order bit of the result is tested, as if by {@code (x & 1) != 0}.
 23.1986 +     * <li>If <em>T0</em> and <em>T1</em> are primitives other than boolean,
 23.1987 +     *     then a Java casting conversion (JLS 5.5) is applied.
 23.1988 +     *     (Specifically, <em>T0</em> will convert to <em>T1</em> by
 23.1989 +     *     widening and/or narrowing.)
 23.1990 +     * <li>If <em>T0</em> is a reference and <em>T1</em> a primitive, an unboxing
 23.1991 +     *     conversion will be applied at runtime, possibly followed
 23.1992 +     *     by a Java casting conversion (JLS 5.5) on the primitive value,
 23.1993 +     *     possibly followed by a conversion from byte to boolean by testing
 23.1994 +     *     the low-order bit.
 23.1995 +     * <li>If <em>T0</em> is a reference and <em>T1</em> a primitive,
 23.1996 +     *     and if the reference is null at runtime, a zero value is introduced.
 23.1997 +     * </ul>
 23.1998 +     * @param target the method handle to invoke after arguments are retyped
 23.1999 +     * @param newType the expected type of the new method handle
 23.2000 +     * @return a method handle which delegates to the target after performing
 23.2001 +     *           any necessary argument conversions, and arranges for any
 23.2002 +     *           necessary return value conversions
 23.2003 +     * @throws NullPointerException if either argument is null
 23.2004 +     * @throws WrongMethodTypeException if the conversion cannot be made
 23.2005 +     * @see MethodHandle#asType
 23.2006 +     */
 23.2007 +    public static
 23.2008 +    MethodHandle explicitCastArguments(MethodHandle target, MethodType newType) {
 23.2009 +        if (!target.type().isCastableTo(newType)) {
 23.2010 +            throw new WrongMethodTypeException("cannot explicitly cast "+target+" to "+newType);
 23.2011 +        }
 23.2012 +        return MethodHandleImpl.makePairwiseConvert(target, newType, 2);
 23.2013 +    }
 23.2014 +
 23.2015 +    /**
 23.2016 +     * Produces a method handle which adapts the calling sequence of the
 23.2017 +     * given method handle to a new type, by reordering the arguments.
 23.2018 +     * The resulting method handle is guaranteed to report a type
 23.2019 +     * which is equal to the desired new type.
 23.2020 +     * <p>
 23.2021 +     * The given array controls the reordering.
 23.2022 +     * Call {@code #I} the number of incoming parameters (the value
 23.2023 +     * {@code newType.parameterCount()}, and call {@code #O} the number
 23.2024 +     * of outgoing parameters (the value {@code target.type().parameterCount()}).
 23.2025 +     * Then the length of the reordering array must be {@code #O},
 23.2026 +     * and each element must be a non-negative number less than {@code #I}.
 23.2027 +     * For every {@code N} less than {@code #O}, the {@code N}-th
 23.2028 +     * outgoing argument will be taken from the {@code I}-th incoming
 23.2029 +     * argument, where {@code I} is {@code reorder[N]}.
 23.2030 +     * <p>
 23.2031 +     * No argument or return value conversions are applied.
 23.2032 +     * The type of each incoming argument, as determined by {@code newType},
 23.2033 +     * must be identical to the type of the corresponding outgoing parameter
 23.2034 +     * or parameters in the target method handle.
 23.2035 +     * The return type of {@code newType} must be identical to the return
 23.2036 +     * type of the original target.
 23.2037 +     * <p>
 23.2038 +     * The reordering array need not specify an actual permutation.
 23.2039 +     * An incoming argument will be duplicated if its index appears
 23.2040 +     * more than once in the array, and an incoming argument will be dropped
 23.2041 +     * if its index does not appear in the array.
 23.2042 +     * As in the case of {@link #dropArguments(MethodHandle,int,List) dropArguments},
 23.2043 +     * incoming arguments which are not mentioned in the reordering array
 23.2044 +     * are may be any type, as determined only by {@code newType}.
 23.2045 +     * <blockquote><pre>{@code
 23.2046 +import static java.lang.invoke.MethodHandles.*;
 23.2047 +import static java.lang.invoke.MethodType.*;
 23.2048 +...
 23.2049 +MethodType intfn1 = methodType(int.class, int.class);
 23.2050 +MethodType intfn2 = methodType(int.class, int.class, int.class);
 23.2051 +MethodHandle sub = ... (int x, int y) -> (x-y) ...;
 23.2052 +assert(sub.type().equals(intfn2));
 23.2053 +MethodHandle sub1 = permuteArguments(sub, intfn2, 0, 1);
 23.2054 +MethodHandle rsub = permuteArguments(sub, intfn2, 1, 0);
 23.2055 +assert((int)rsub.invokeExact(1, 100) == 99);
 23.2056 +MethodHandle add = ... (int x, int y) -> (x+y) ...;
 23.2057 +assert(add.type().equals(intfn2));
 23.2058 +MethodHandle twice = permuteArguments(add, intfn1, 0, 0);
 23.2059 +assert(twice.type().equals(intfn1));
 23.2060 +assert((int)twice.invokeExact(21) == 42);
 23.2061 +     * }</pre></blockquote>
 23.2062 +     * @param target the method handle to invoke after arguments are reordered
 23.2063 +     * @param newType the expected type of the new method handle
 23.2064 +     * @param reorder an index array which controls the reordering
 23.2065 +     * @return a method handle which delegates to the target after it
 23.2066 +     *           drops unused arguments and moves and/or duplicates the other arguments
 23.2067 +     * @throws NullPointerException if any argument is null
 23.2068 +     * @throws IllegalArgumentException if the index array length is not equal to
 23.2069 +     *                  the arity of the target, or if any index array element
 23.2070 +     *                  not a valid index for a parameter of {@code newType},
 23.2071 +     *                  or if two corresponding parameter types in
 23.2072 +     *                  {@code target.type()} and {@code newType} are not identical,
 23.2073 +     */
 23.2074 +    public static
 23.2075 +    MethodHandle permuteArguments(MethodHandle target, MethodType newType, int... reorder) {
 23.2076 +        checkReorder(reorder, newType, target.type());
 23.2077 +        return target.permuteArguments(newType, reorder);
 23.2078 +    }
 23.2079 +
 23.2080 +    private static void checkReorder(int[] reorder, MethodType newType, MethodType oldType) {
 23.2081 +        if (newType.returnType() != oldType.returnType())
 23.2082 +            throw newIllegalArgumentException("return types do not match",
 23.2083 +                    oldType, newType);
 23.2084 +        if (reorder.length == oldType.parameterCount()) {
 23.2085 +            int limit = newType.parameterCount();
 23.2086 +            boolean bad = false;
 23.2087 +            for (int j = 0; j < reorder.length; j++) {
 23.2088 +                int i = reorder[j];
 23.2089 +                if (i < 0 || i >= limit) {
 23.2090 +                    bad = true; break;
 23.2091 +                }
 23.2092 +                Class<?> src = newType.parameterType(i);
 23.2093 +                Class<?> dst = oldType.parameterType(j);
 23.2094 +                if (src != dst)
 23.2095 +                    throw newIllegalArgumentException("parameter types do not match after reorder",
 23.2096 +                            oldType, newType);
 23.2097 +            }
 23.2098 +            if (!bad)  return;
 23.2099 +        }
 23.2100 +        throw newIllegalArgumentException("bad reorder array: "+Arrays.toString(reorder));
 23.2101 +    }
 23.2102 +
 23.2103 +    /**
 23.2104 +     * Produces a method handle of the requested return type which returns the given
 23.2105 +     * constant value every time it is invoked.
 23.2106 +     * <p>
 23.2107 +     * Before the method handle is returned, the passed-in value is converted to the requested type.
 23.2108 +     * If the requested type is primitive, widening primitive conversions are attempted,
 23.2109 +     * else reference conversions are attempted.
 23.2110 +     * <p>The returned method handle is equivalent to {@code identity(type).bindTo(value)}.
 23.2111 +     * @param type the return type of the desired method handle
 23.2112 +     * @param value the value to return
 23.2113 +     * @return a method handle of the given return type and no arguments, which always returns the given value
 23.2114 +     * @throws NullPointerException if the {@code type} argument is null
 23.2115 +     * @throws ClassCastException if the value cannot be converted to the required return type
 23.2116 +     * @throws IllegalArgumentException if the given type is {@code void.class}
 23.2117 +     */
 23.2118 +    public static
 23.2119 +    MethodHandle constant(Class<?> type, Object value) {
 23.2120 +        if (type.isPrimitive()) {
 23.2121 +            if (type == void.class)
 23.2122 +                throw newIllegalArgumentException("void type");
 23.2123 +            Wrapper w = Wrapper.forPrimitiveType(type);
 23.2124 +            return insertArguments(identity(type), 0, w.convert(value, type));
 23.2125 +        } else {
 23.2126 +            return identity(type).bindTo(type.cast(value));
 23.2127 +        }
 23.2128 +    }
 23.2129 +
 23.2130 +    /**
 23.2131 +     * Produces a method handle which returns its sole argument when invoked.
 23.2132 +     * @param type the type of the sole parameter and return value of the desired method handle
 23.2133 +     * @return a unary method handle which accepts and returns the given type
 23.2134 +     * @throws NullPointerException if the argument is null
 23.2135 +     * @throws IllegalArgumentException if the given type is {@code void.class}
 23.2136 +     */
 23.2137 +    public static
 23.2138 +    MethodHandle identity(Class<?> type) {
 23.2139 +        if (type == void.class)
 23.2140 +            throw newIllegalArgumentException("void type");
 23.2141 +        else if (type == Object.class)
 23.2142 +            return ValueConversions.identity();
 23.2143 +        else if (type.isPrimitive())
 23.2144 +            return ValueConversions.identity(Wrapper.forPrimitiveType(type));
 23.2145 +        else
 23.2146 +            return MethodHandleImpl.makeReferenceIdentity(type);
 23.2147 +    }
 23.2148 +
 23.2149 +    /**
 23.2150 +     * Provides a target method handle with one or more <em>bound arguments</em>
 23.2151 +     * in advance of the method handle's invocation.
 23.2152 +     * The formal parameters to the target corresponding to the bound
 23.2153 +     * arguments are called <em>bound parameters</em>.
 23.2154 +     * Returns a new method handle which saves away the bound arguments.
 23.2155 +     * When it is invoked, it receives arguments for any non-bound parameters,
 23.2156 +     * binds the saved arguments to their corresponding parameters,
 23.2157 +     * and calls the original target.
 23.2158 +     * <p>
 23.2159 +     * The type of the new method handle will drop the types for the bound
 23.2160 +     * parameters from the original target type, since the new method handle
 23.2161 +     * will no longer require those arguments to be supplied by its callers.
 23.2162 +     * <p>
 23.2163 +     * Each given argument object must match the corresponding bound parameter type.
 23.2164 +     * If a bound parameter type is a primitive, the argument object
 23.2165 +     * must be a wrapper, and will be unboxed to produce the primitive value.
 23.2166 +     * <p>
 23.2167 +     * The {@code pos} argument selects which parameters are to be bound.
 23.2168 +     * It may range between zero and <i>N-L</i> (inclusively),
 23.2169 +     * where <i>N</i> is the arity of the target method handle
 23.2170 +     * and <i>L</i> is the length of the values array.
 23.2171 +     * @param target the method handle to invoke after the argument is inserted
 23.2172 +     * @param pos where to insert the argument (zero for the first)
 23.2173 +     * @param values the series of arguments to insert
 23.2174 +     * @return a method handle which inserts an additional argument,
 23.2175 +     *         before calling the original method handle
 23.2176 +     * @throws NullPointerException if the target or the {@code values} array is null
 23.2177 +     * @see MethodHandle#bindTo
 23.2178 +     */
 23.2179 +    public static
 23.2180 +    MethodHandle insertArguments(MethodHandle target, int pos, Object... values) {
 23.2181 +        int insCount = values.length;
 23.2182 +        MethodType oldType = target.type();
 23.2183 +        int outargs = oldType.parameterCount();
 23.2184 +        int inargs  = outargs - insCount;
 23.2185 +        if (inargs < 0)
 23.2186 +            throw newIllegalArgumentException("too many values to insert");
 23.2187 +        if (pos < 0 || pos > inargs)
 23.2188 +            throw newIllegalArgumentException("no argument type to append");
 23.2189 +        MethodHandle result = target;
 23.2190 +        for (int i = 0; i < insCount; i++) {
 23.2191 +            Object value = values[i];
 23.2192 +            Class<?> ptype = oldType.parameterType(pos+i);
 23.2193 +            if (ptype.isPrimitive()) {
 23.2194 +                char btype = 'I';
 23.2195 +                Wrapper w = Wrapper.forPrimitiveType(ptype);
 23.2196 +                switch (w) {
 23.2197 +                case LONG:    btype = 'J'; break;
 23.2198 +                case FLOAT:   btype = 'F'; break;
 23.2199 +                case DOUBLE:  btype = 'D'; break;
 23.2200 +                }
 23.2201 +                // perform unboxing and/or primitive conversion
 23.2202 +                value = w.convert(value, ptype);
 23.2203 +                result = result.bindArgument(pos, btype, value);
 23.2204 +                continue;
 23.2205 +            }
 23.2206 +            value = ptype.cast(value);  // throw CCE if needed
 23.2207 +            if (pos == 0) {
 23.2208 +                result = result.bindReceiver(value);
 23.2209 +            } else {
 23.2210 +                result = result.bindArgument(pos, 'L', value);
 23.2211 +            }
 23.2212 +        }
 23.2213 +        return result;
 23.2214 +    }
 23.2215 +
 23.2216 +    /**
 23.2217 +     * Produces a method handle which will discard some dummy arguments
 23.2218 +     * before calling some other specified <i>target</i> method handle.
 23.2219 +     * The type of the new method handle will be the same as the target's type,
 23.2220 +     * except it will also include the dummy argument types,
 23.2221 +     * at some given position.
 23.2222 +     * <p>
 23.2223 +     * The {@code pos} argument may range between zero and <i>N</i>,
 23.2224 +     * where <i>N</i> is the arity of the target.
 23.2225 +     * If {@code pos} is zero, the dummy arguments will precede
 23.2226 +     * the target's real arguments; if {@code pos} is <i>N</i>
 23.2227 +     * they will come after.
 23.2228 +     * <p>
 23.2229 +     * <b>Example:</b>
 23.2230 +     * <blockquote><pre>{@code
 23.2231 +import static java.lang.invoke.MethodHandles.*;
 23.2232 +import static java.lang.invoke.MethodType.*;
 23.2233 +...
 23.2234 +MethodHandle cat = lookup().findVirtual(String.class,
 23.2235 +  "concat", methodType(String.class, String.class));
 23.2236 +assertEquals("xy", (String) cat.invokeExact("x", "y"));
 23.2237 +MethodType bigType = cat.type().insertParameterTypes(0, int.class, String.class);
 23.2238 +MethodHandle d0 = dropArguments(cat, 0, bigType.parameterList().subList(0,2));
 23.2239 +assertEquals(bigType, d0.type());
 23.2240 +assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z"));
 23.2241 +     * }</pre></blockquote>
 23.2242 +     * <p>
 23.2243 +     * This method is also equivalent to the following code:
 23.2244 +     * <blockquote><pre>
 23.2245 +     * {@link #dropArguments(MethodHandle,int,Class...) dropArguments}{@code (target, pos, valueTypes.toArray(new Class[0]))}
 23.2246 +     * </pre></blockquote>
 23.2247 +     * @param target the method handle to invoke after the arguments are dropped
 23.2248 +     * @param valueTypes the type(s) of the argument(s) to drop
 23.2249 +     * @param pos position of first argument to drop (zero for the leftmost)
 23.2250 +     * @return a method handle which drops arguments of the given types,
 23.2251 +     *         before calling the original method handle
 23.2252 +     * @throws NullPointerException if the target is null,
 23.2253 +     *                              or if the {@code valueTypes} list or any of its elements is null
 23.2254 +     * @throws IllegalArgumentException if any element of {@code valueTypes} is {@code void.class},
 23.2255 +     *                  or if {@code pos} is negative or greater than the arity of the target,
 23.2256 +     *                  or if the new method handle's type would have too many parameters
 23.2257 +     */
 23.2258 +    public static
 23.2259 +    MethodHandle dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes) {
 23.2260 +        MethodType oldType = target.type();  // get NPE
 23.2261 +        int dropped = valueTypes.size();
 23.2262 +        MethodType.checkSlotCount(dropped);
 23.2263 +        if (dropped == 0)  return target;
 23.2264 +        int outargs = oldType.parameterCount();
 23.2265 +        int inargs  = outargs + dropped;
 23.2266 +        if (pos < 0 || pos >= inargs)
 23.2267 +            throw newIllegalArgumentException("no argument type to remove");
 23.2268 +        ArrayList<Class<?>> ptypes = new ArrayList<>(oldType.parameterList());
 23.2269 +        ptypes.addAll(pos, valueTypes);
 23.2270 +        MethodType newType = MethodType.methodType(oldType.returnType(), ptypes);
 23.2271 +        return target.dropArguments(newType, pos, dropped);
 23.2272 +    }
 23.2273 +
 23.2274 +    /**
 23.2275 +     * Produces a method handle which will discard some dummy arguments
 23.2276 +     * before calling some other specified <i>target</i> method handle.
 23.2277 +     * The type of the new method handle will be the same as the target's type,
 23.2278 +     * except it will also include the dummy argument types,
 23.2279 +     * at some given position.
 23.2280 +     * <p>
 23.2281 +     * The {@code pos} argument may range between zero and <i>N</i>,
 23.2282 +     * where <i>N</i> is the arity of the target.
 23.2283 +     * If {@code pos} is zero, the dummy arguments will precede
 23.2284 +     * the target's real arguments; if {@code pos} is <i>N</i>
 23.2285 +     * they will come after.
 23.2286 +     * <p>
 23.2287 +     * <b>Example:</b>
 23.2288 +     * <blockquote><pre>{@code
 23.2289 +import static java.lang.invoke.MethodHandles.*;
 23.2290 +import static java.lang.invoke.MethodType.*;
 23.2291 +...
 23.2292 +MethodHandle cat = lookup().findVirtual(String.class,
 23.2293 +  "concat", methodType(String.class, String.class));
 23.2294 +assertEquals("xy", (String) cat.invokeExact("x", "y"));
 23.2295 +MethodHandle d0 = dropArguments(cat, 0, String.class);
 23.2296 +assertEquals("yz", (String) d0.invokeExact("x", "y", "z"));
 23.2297 +MethodHandle d1 = dropArguments(cat, 1, String.class);
 23.2298 +assertEquals("xz", (String) d1.invokeExact("x", "y", "z"));
 23.2299 +MethodHandle d2 = dropArguments(cat, 2, String.class);
 23.2300 +assertEquals("xy", (String) d2.invokeExact("x", "y", "z"));
 23.2301 +MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
 23.2302 +assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
 23.2303 +     * }</pre></blockquote>
 23.2304 +     * <p>
 23.2305 +     * This method is also equivalent to the following code:
 23.2306 +     * <blockquote><pre>
 23.2307 +     * {@link #dropArguments(MethodHandle,int,List) dropArguments}{@code (target, pos, Arrays.asList(valueTypes))}
 23.2308 +     * </pre></blockquote>
 23.2309 +     * @param target the method handle to invoke after the arguments are dropped
 23.2310 +     * @param valueTypes the type(s) of the argument(s) to drop
 23.2311 +     * @param pos position of first argument to drop (zero for the leftmost)
 23.2312 +     * @return a method handle which drops arguments of the given types,
 23.2313 +     *         before calling the original method handle
 23.2314 +     * @throws NullPointerException if the target is null,
 23.2315 +     *                              or if the {@code valueTypes} array or any of its elements is null
 23.2316 +     * @throws IllegalArgumentException if any element of {@code valueTypes} is {@code void.class},
 23.2317 +     *                  or if {@code pos} is negative or greater than the arity of the target,
 23.2318 +     *                  or if the new method handle's type would have
 23.2319 +     *                  <a href="MethodHandle.html#maxarity">too many parameters</a>
 23.2320 +     */
 23.2321 +    public static
 23.2322 +    MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) {
 23.2323 +        return dropArguments(target, pos, Arrays.asList(valueTypes));
 23.2324 +    }
 23.2325 +
 23.2326 +    /**
 23.2327 +     * Adapts a target method handle by pre-processing
 23.2328 +     * one or more of its arguments, each with its own unary filter function,
 23.2329 +     * and then calling the target with each pre-processed argument
 23.2330 +     * replaced by the result of its corresponding filter function.
 23.2331 +     * <p>
 23.2332 +     * The pre-processing is performed by one or more method handles,
 23.2333 +     * specified in the elements of the {@code filters} array.
 23.2334 +     * The first element of the filter array corresponds to the {@code pos}
 23.2335 +     * argument of the target, and so on in sequence.
 23.2336 +     * <p>
 23.2337 +     * Null arguments in the array are treated as identity functions,
 23.2338 +     * and the corresponding arguments left unchanged.
 23.2339 +     * (If there are no non-null elements in the array, the original target is returned.)
 23.2340 +     * Each filter is applied to the corresponding argument of the adapter.
 23.2341 +     * <p>
 23.2342 +     * If a filter {@code F} applies to the {@code N}th argument of
 23.2343 +     * the target, then {@code F} must be a method handle which
 23.2344 +     * takes exactly one argument.  The type of {@code F}'s sole argument
 23.2345 +     * replaces the corresponding argument type of the target
 23.2346 +     * in the resulting adapted method handle.
 23.2347 +     * The return type of {@code F} must be identical to the corresponding
 23.2348 +     * parameter type of the target.
 23.2349 +     * <p>
 23.2350 +     * It is an error if there are elements of {@code filters}
 23.2351 +     * (null or not)
 23.2352 +     * which do not correspond to argument positions in the target.
 23.2353 +     * <p><b>Example:</b>
 23.2354 +     * <blockquote><pre>{@code
 23.2355 +import static java.lang.invoke.MethodHandles.*;
 23.2356 +import static java.lang.invoke.MethodType.*;
 23.2357 +...
 23.2358 +MethodHandle cat = lookup().findVirtual(String.class,
 23.2359 +  "concat", methodType(String.class, String.class));
 23.2360 +MethodHandle upcase = lookup().findVirtual(String.class,
 23.2361 +  "toUpperCase", methodType(String.class));
 23.2362 +assertEquals("xy", (String) cat.invokeExact("x", "y"));
 23.2363 +MethodHandle f0 = filterArguments(cat, 0, upcase);
 23.2364 +assertEquals("Xy", (String) f0.invokeExact("x", "y")); // Xy
 23.2365 +MethodHandle f1 = filterArguments(cat, 1, upcase);
 23.2366 +assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY
 23.2367 +MethodHandle f2 = filterArguments(cat, 0, upcase, upcase);
 23.2368 +assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
 23.2369 +     * }</pre></blockquote>
 23.2370 +     * <p> Here is pseudocode for the resulting adapter:
 23.2371 +     * <blockquote><pre>{@code
 23.2372 +     * V target(P... p, A[i]... a[i], B... b);
 23.2373 +     * A[i] filter[i](V[i]);
 23.2374 +     * T adapter(P... p, V[i]... v[i], B... b) {
 23.2375 +     *   return target(p..., f[i](v[i])..., b...);
 23.2376 +     * }
 23.2377 +     * }</pre></blockquote>
 23.2378 +     *
 23.2379 +     * @param target the method handle to invoke after arguments are filtered
 23.2380 +     * @param pos the position of the first argument to filter
 23.2381 +     * @param filters method handles to call initially on filtered arguments
 23.2382 +     * @return method handle which incorporates the specified argument filtering logic
 23.2383 +     * @throws NullPointerException if the target is null
 23.2384 +     *                              or if the {@code filters} array is null
 23.2385 +     * @throws IllegalArgumentException if a non-null element of {@code filters}
 23.2386 +     *          does not match a corresponding argument type of target as described above,
 23.2387 +     *          or if the {@code pos+filters.length} is greater than {@code target.type().parameterCount()},
 23.2388 +     *          or if the resulting method handle's type would have
 23.2389 +     *          <a href="MethodHandle.html#maxarity">too many parameters</a>
 23.2390 +     */
 23.2391 +    public static
 23.2392 +    MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) {
 23.2393 +        MethodType targetType = target.type();
 23.2394 +        MethodHandle adapter = target;
 23.2395 +        MethodType adapterType = null;
 23.2396 +        assert((adapterType = targetType) != null);
 23.2397 +        int maxPos = targetType.parameterCount();
 23.2398 +        if (pos + filters.length > maxPos)
 23.2399 +            throw newIllegalArgumentException("too many filters");
 23.2400 +        int curPos = pos-1;  // pre-incremented
 23.2401 +        for (MethodHandle filter : filters) {
 23.2402 +            curPos += 1;
 23.2403 +            if (filter == null)  continue;  // ignore null elements of filters
 23.2404 +            adapter = filterArgument(adapter, curPos, filter);
 23.2405 +            assert((adapterType = adapterType.changeParameterType(curPos, filter.type().parameterType(0))) != null);
 23.2406 +        }
 23.2407 +        assert(adapterType.equals(adapter.type()));
 23.2408 +        return adapter;
 23.2409 +    }
 23.2410 +
 23.2411 +    /*non-public*/ static
 23.2412 +    MethodHandle filterArgument(MethodHandle target, int pos, MethodHandle filter) {
 23.2413 +        MethodType targetType = target.type();
 23.2414 +        MethodType filterType = filter.type();
 23.2415 +        if (filterType.parameterCount() != 1
 23.2416 +            || filterType.returnType() != targetType.parameterType(pos))
 23.2417 +            throw newIllegalArgumentException("target and filter types do not match", targetType, filterType);
 23.2418 +        return MethodHandleImpl.makeCollectArguments(target, filter, pos, false);
 23.2419 +    }
 23.2420 +
 23.2421 +    /**
 23.2422 +     * Adapts a target method handle by pre-processing
 23.2423 +     * a sub-sequence of its arguments with a filter (another method handle).
 23.2424 +     * The pre-processed arguments are replaced by the result (if any) of the
 23.2425 +     * filter function.
 23.2426 +     * The target is then called on the modified (usually shortened) argument list.
 23.2427 +     * <p>
 23.2428 +     * If the filter returns a value, the target must accept that value as
 23.2429 +     * its argument in position {@code pos}, preceded and/or followed by
 23.2430 +     * any arguments not passed to the filter.
 23.2431 +     * If the filter returns void, the target must accept all arguments
 23.2432 +     * not passed to the filter.
 23.2433 +     * No arguments are reordered, and a result returned from the filter
 23.2434 +     * replaces (in order) the whole subsequence of arguments originally
 23.2435 +     * passed to the adapter.
 23.2436 +     * <p>
 23.2437 +     * The argument types (if any) of the filter
 23.2438 +     * replace zero or one argument types of the target, at position {@code pos},
 23.2439 +     * in the resulting adapted method handle.
 23.2440 +     * The return type of the filter (if any) must be identical to the
 23.2441 +     * argument type of the target at position {@code pos}, and that target argument
 23.2442 +     * is supplied by the return value of the filter.
 23.2443 +     * <p>
 23.2444 +     * In all cases, {@code pos} must be greater than or equal to zero, and
 23.2445 +     * {@code pos} must also be less than or equal to the target's arity.
 23.2446 +     * <p><b>Example:</b>
 23.2447 +     * <blockquote><pre>{@code
 23.2448 +import static java.lang.invoke.MethodHandles.*;
 23.2449 +import static java.lang.invoke.MethodType.*;
 23.2450 +...
 23.2451 +MethodHandle deepToString = publicLookup()
 23.2452 +  .findStatic(Arrays.class, "deepToString", methodType(String.class, Object[].class));
 23.2453 +
 23.2454 +MethodHandle ts1 = deepToString.asCollector(String[].class, 1);
 23.2455 +assertEquals("[strange]", (String) ts1.invokeExact("strange"));
 23.2456 +
 23.2457 +MethodHandle ts2 = deepToString.asCollector(String[].class, 2);
 23.2458 +assertEquals("[up, down]", (String) ts2.invokeExact("up", "down"));
 23.2459 +
 23.2460 +MethodHandle ts3 = deepToString.asCollector(String[].class, 3);
 23.2461 +MethodHandle ts3_ts2 = collectArguments(ts3, 1, ts2);
 23.2462 +assertEquals("[top, [up, down], strange]",
 23.2463 +             (String) ts3_ts2.invokeExact("top", "up", "down", "strange"));
 23.2464 +
 23.2465 +MethodHandle ts3_ts2_ts1 = collectArguments(ts3_ts2, 3, ts1);
 23.2466 +assertEquals("[top, [up, down], [strange]]",
 23.2467 +             (String) ts3_ts2_ts1.invokeExact("top", "up", "down", "strange"));
 23.2468 +
 23.2469 +MethodHandle ts3_ts2_ts3 = collectArguments(ts3_ts2, 1, ts3);
 23.2470 +assertEquals("[top, [[up, down, strange], charm], bottom]",
 23.2471 +             (String) ts3_ts2_ts3.invokeExact("top", "up", "down", "strange", "charm", "bottom"));
 23.2472 +     * }</pre></blockquote>
 23.2473 +     * <p> Here is pseudocode for the resulting adapter:
 23.2474 +     * <blockquote><pre>{@code
 23.2475 +     * T target(A...,V,C...);
 23.2476 +     * V filter(B...);
 23.2477 +     * T adapter(A... a,B... b,C... c) {
 23.2478 +     *   V v = filter(b...);
 23.2479 +     *   return target(a...,v,c...);
 23.2480 +     * }
 23.2481 +     * // and if the filter has no arguments:
 23.2482 +     * T target2(A...,V,C...);
 23.2483 +     * V filter2();
 23.2484 +     * T adapter2(A... a,C... c) {
 23.2485 +     *   V v = filter2();
 23.2486 +     *   return target2(a...,v,c...);
 23.2487 +     * }
 23.2488 +     * // and if the filter has a void return:
 23.2489 +     * T target3(A...,C...);
 23.2490 +     * void filter3(B...);
 23.2491 +     * void adapter3(A... a,B... b,C... c) {
 23.2492 +     *   filter3(b...);
 23.2493 +     *   return target3(a...,c...);
 23.2494 +     * }
 23.2495 +     * }</pre></blockquote>
 23.2496 +     * <p>
 23.2497 +     * A collection adapter {@code collectArguments(mh, 0, coll)} is equivalent to
 23.2498 +     * one which first "folds" the affected arguments, and then drops them, in separate
 23.2499 +     * steps as follows:
 23.2500 +     * <blockquote><pre>{@code
 23.2501 +     * mh = MethodHandles.dropArguments(mh, 1, coll.type().parameterList()); //step 2
 23.2502 +     * mh = MethodHandles.foldArguments(mh, coll); //step 1
 23.2503 +     * }</pre></blockquote>
 23.2504 +     * If the target method handle consumes no arguments besides than the result
 23.2505 +     * (if any) of the filter {@code coll}, then {@code collectArguments(mh, 0, coll)}
 23.2506 +     * is equivalent to {@code filterReturnValue(coll, mh)}.
 23.2507 +     * If the filter method handle {@code coll} consumes one argument and produces
 23.2508 +     * a non-void result, then {@code collectArguments(mh, N, coll)}
 23.2509 +     * is equivalent to {@code filterArguments(mh, N, coll)}.
 23.2510 +     * Other equivalences are possible but would require argument permutation.
 23.2511 +     *
 23.2512 +     * @param target the method handle to invoke after filtering the subsequence of arguments
 23.2513 +     * @param pos the position of the first adapter argument to pass to the filter,
 23.2514 +     *            and/or the target argument which receives the result of the filter
 23.2515 +     * @param filter method handle to call on the subsequence of arguments
 23.2516 +     * @return method handle which incorporates the specified argument subsequence filtering logic
 23.2517 +     * @throws NullPointerException if either argument is null
 23.2518 +     * @throws IllegalArgumentException if the return type of {@code filter}
 23.2519 +     *          is non-void and is not the same as the {@code pos} argument of the target,
 23.2520 +     *          or if {@code pos} is not between 0 and the target's arity, inclusive,
 23.2521 +     *          or if the resulting method handle's type would have
 23.2522 +     *          <a href="MethodHandle.html#maxarity">too many parameters</a>
 23.2523 +     * @see MethodHandles#foldArguments
 23.2524 +     * @see MethodHandles#filterArguments
 23.2525 +     * @see MethodHandles#filterReturnValue
 23.2526 +     */
 23.2527 +    public static
 23.2528 +    MethodHandle collectArguments(MethodHandle target, int pos, MethodHandle filter) {
 23.2529 +        MethodType targetType = target.type();
 23.2530 +        MethodType filterType = filter.type();
 23.2531 +        if (filterType.returnType() != void.class &&
 23.2532 +            filterType.returnType() != targetType.parameterType(pos))
 23.2533 +            throw newIllegalArgumentException("target and filter types do not match", targetType, filterType);
 23.2534 +        return MethodHandleImpl.makeCollectArguments(target, filter, pos, false);
 23.2535 +    }
 23.2536 +
 23.2537 +    /**
 23.2538 +     * Adapts a target method handle by post-processing
 23.2539 +     * its return value (if any) with a filter (another method handle).
 23.2540 +     * The result of the filter is returned from the adapter.
 23.2541 +     * <p>
 23.2542 +     * If the target returns a value, the filter must accept that value as
 23.2543 +     * its only argument.
 23.2544 +     * If the target returns void, the filter must accept no arguments.
 23.2545 +     * <p>
 23.2546 +     * The return type of the filter
 23.2547 +     * replaces the return type of the target
 23.2548 +     * in the resulting adapted method handle.
 23.2549 +     * The argument type of the filter (if any) must be identical to the
 23.2550 +     * return type of the target.
 23.2551 +     * <p><b>Example:</b>
 23.2552 +     * <blockquote><pre>{@code
 23.2553 +import static java.lang.invoke.MethodHandles.*;
 23.2554 +import static java.lang.invoke.MethodType.*;
 23.2555 +...
 23.2556 +MethodHandle cat = lookup().findVirtual(String.class,
 23.2557 +  "concat", methodType(String.class, String.class));
 23.2558 +MethodHandle length = lookup().findVirtual(String.class,
 23.2559 +  "length", methodType(int.class));
 23.2560 +System.out.println((String) cat.invokeExact("x", "y")); // xy
 23.2561 +MethodHandle f0 = filterReturnValue(cat, length);
 23.2562 +System.out.println((int) f0.invokeExact("x", "y")); // 2
 23.2563 +     * }</pre></blockquote>
 23.2564 +     * <p> Here is pseudocode for the resulting adapter:
 23.2565 +     * <blockquote><pre>{@code
 23.2566 +     * V target(A...);
 23.2567 +     * T filter(V);
 23.2568 +     * T adapter(A... a) {
 23.2569 +     *   V v = target(a...);
 23.2570 +     *   return filter(v);
 23.2571 +     * }
 23.2572 +     * // and if the target has a void return:
 23.2573 +     * void target2(A...);
 23.2574 +     * T filter2();
 23.2575 +     * T adapter2(A... a) {
 23.2576 +     *   target2(a...);
 23.2577 +     *   return filter2();
 23.2578 +     * }
 23.2579 +     * // and if the filter has a void return:
 23.2580 +     * V target3(A...);
 23.2581 +     * void filter3(V);
 23.2582 +     * void adapter3(A... a) {
 23.2583 +     *   V v = target3(a...);
 23.2584 +     *   filter3(v);
 23.2585 +     * }
 23.2586 +     * }</pre></blockquote>
 23.2587 +     * @param target the method handle to invoke before filtering the return value
 23.2588 +     * @param filter method handle to call on the return value
 23.2589 +     * @return method handle which incorporates the specified return value filtering logic
 23.2590 +     * @throws NullPointerException if either argument is null
 23.2591 +     * @throws IllegalArgumentException if the argument list of {@code filter}
 23.2592 +     *          does not match the return type of target as described above
 23.2593 +     */
 23.2594 +    public static
 23.2595 +    MethodHandle filterReturnValue(MethodHandle target, MethodHandle filter) {
 23.2596 +        MethodType targetType = target.type();
 23.2597 +        MethodType filterType = filter.type();
 23.2598 +        Class<?> rtype = targetType.returnType();
 23.2599 +        int filterValues = filterType.parameterCount();
 23.2600 +        if (filterValues == 0
 23.2601 +                ? (rtype != void.class)
 23.2602 +                : (rtype != filterType.parameterType(0)))
 23.2603 +            throw newIllegalArgumentException("target and filter types do not match", target, filter);
 23.2604 +        // result = fold( lambda(retval, arg...) { filter(retval) },
 23.2605 +        //                lambda(        arg...) { target(arg...) } )
 23.2606 +        return MethodHandleImpl.makeCollectArguments(filter, target, 0, false);
 23.2607 +    }
 23.2608 +
 23.2609 +    /**
 23.2610 +     * Adapts a target method handle by pre-processing
 23.2611 +     * some of its arguments, and then calling the target with
 23.2612 +     * the result of the pre-processing, inserted into the original
 23.2613 +     * sequence of arguments.
 23.2614 +     * <p>
 23.2615 +     * The pre-processing is performed by {@code combiner}, a second method handle.
 23.2616 +     * Of the arguments passed to the adapter, the first {@code N} arguments
 23.2617 +     * are copied to the combiner, which is then called.
 23.2618 +     * (Here, {@code N} is defined as the parameter count of the combiner.)
 23.2619 +     * After this, control passes to the target, with any result
 23.2620 +     * from the combiner inserted before the original {@code N} incoming
 23.2621 +     * arguments.
 23.2622 +     * <p>
 23.2623 +     * If the combiner returns a value, the first parameter type of the target
 23.2624 +     * must be identical with the return type of the combiner, and the next
 23.2625 +     * {@code N} parameter types of the target must exactly match the parameters
 23.2626 +     * of the combiner.
 23.2627 +     * <p>
 23.2628 +     * If the combiner has a void return, no result will be inserted,
 23.2629 +     * and the first {@code N} parameter types of the target
 23.2630 +     * must exactly match the parameters of the combiner.
 23.2631 +     * <p>
 23.2632 +     * The resulting adapter is the same type as the target, except that the
 23.2633 +     * first parameter type is dropped,
 23.2634 +     * if it corresponds to the result of the combiner.
 23.2635 +     * <p>
 23.2636 +     * (Note that {@link #dropArguments(MethodHandle,int,List) dropArguments} can be used to remove any arguments
 23.2637 +     * that either the combiner or the target does not wish to receive.
 23.2638 +     * If some of the incoming arguments are destined only for the combiner,
 23.2639 +     * consider using {@link MethodHandle#asCollector asCollector} instead, since those
 23.2640 +     * arguments will not need to be live on the stack on entry to the
 23.2641 +     * target.)
 23.2642 +     * <p><b>Example:</b>
 23.2643 +     * <blockquote><pre>{@code
 23.2644 +import static java.lang.invoke.MethodHandles.*;
 23.2645 +import static java.lang.invoke.MethodType.*;
 23.2646 +...
 23.2647 +MethodHandle trace = publicLookup().findVirtual(java.io.PrintStream.class,
 23.2648 +  "println", methodType(void.class, String.class))
 23.2649 +    .bindTo(System.out);
 23.2650 +MethodHandle cat = lookup().findVirtual(String.class,
 23.2651 +  "concat", methodType(String.class, String.class));
 23.2652 +assertEquals("boojum", (String) cat.invokeExact("boo", "jum"));
 23.2653 +MethodHandle catTrace = foldArguments(cat, trace);
 23.2654 +// also prints "boo":
 23.2655 +assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
 23.2656 +     * }</pre></blockquote>
 23.2657 +     * <p> Here is pseudocode for the resulting adapter:
 23.2658 +     * <blockquote><pre>{@code
 23.2659 +     * // there are N arguments in A...
 23.2660 +     * T target(V, A[N]..., B...);
 23.2661 +     * V combiner(A...);
 23.2662 +     * T adapter(A... a, B... b) {
 23.2663 +     *   V v = combiner(a...);
 23.2664 +     *   return target(v, a..., b...);
 23.2665 +     * }
 23.2666 +     * // and if the combiner has a void return:
 23.2667 +     * T target2(A[N]..., B...);
 23.2668 +     * void combiner2(A...);
 23.2669 +     * T adapter2(A... a, B... b) {
 23.2670 +     *   combiner2(a...);
 23.2671 +     *   return target2(a..., b...);
 23.2672 +     * }
 23.2673 +     * }</pre></blockquote>
 23.2674 +     * @param target the method handle to invoke after arguments are combined
 23.2675 +     * @param combiner method handle to call initially on the incoming arguments
 23.2676 +     * @return method handle which incorporates the specified argument folding logic
 23.2677 +     * @throws NullPointerException if either argument is null
 23.2678 +     * @throws IllegalArgumentException if {@code combiner}'s return type
 23.2679 +     *          is non-void and not the same as the first argument type of
 23.2680 +     *          the target, or if the initial {@code N} argument types
 23.2681 +     *          of the target
 23.2682 +     *          (skipping one matching the {@code combiner}'s return type)
 23.2683 +     *          are not identical with the argument types of {@code combiner}
 23.2684 +     */
 23.2685 +    public static
 23.2686 +    MethodHandle foldArguments(MethodHandle target, MethodHandle combiner) {
 23.2687 +        int pos = 0;
 23.2688 +        MethodType targetType = target.type();
 23.2689 +        MethodType combinerType = combiner.type();
 23.2690 +        int foldPos = pos;
 23.2691 +        int foldArgs = combinerType.parameterCount();
 23.2692 +        int foldVals = combinerType.returnType() == void.class ? 0 : 1;
 23.2693 +        int afterInsertPos = foldPos + foldVals;
 23.2694 +        boolean ok = (targetType.parameterCount() >= afterInsertPos + foldArgs);
 23.2695 +        if (ok && !(combinerType.parameterList()
 23.2696 +                    .equals(targetType.parameterList().subList(afterInsertPos,
 23.2697 +                                                               afterInsertPos + foldArgs))))
 23.2698 +            ok = false;
 23.2699 +        if (ok && foldVals != 0 && !combinerType.returnType().equals(targetType.parameterType(0)))
 23.2700 +            ok = false;
 23.2701 +        if (!ok)
 23.2702 +            throw misMatchedTypes("target and combiner types", targetType, combinerType);
 23.2703 +        MethodType newType = targetType.dropParameterTypes(foldPos, afterInsertPos);
 23.2704 +        return MethodHandleImpl.makeCollectArguments(target, combiner, foldPos, true);
 23.2705 +    }
 23.2706 +
 23.2707 +    /**
 23.2708 +     * Makes a method handle which adapts a target method handle,
 23.2709 +     * by guarding it with a test, a boolean-valued method handle.
 23.2710 +     * If the guard fails, a fallback handle is called instead.
 23.2711 +     * All three method handles must have the same corresponding
 23.2712 +     * argument and return types, except that the return type
 23.2713 +     * of the test must be boolean, and the test is allowed
 23.2714 +     * to have fewer arguments than the other two method handles.
 23.2715 +     * <p> Here is pseudocode for the resulting adapter:
 23.2716 +     * <blockquote><pre>{@code
 23.2717 +     * boolean test(A...);
 23.2718 +     * T target(A...,B...);
 23.2719 +     * T fallback(A...,B...);
 23.2720 +     * T adapter(A... a,B... b) {
 23.2721 +     *   if (test(a...))
 23.2722 +     *     return target(a..., b...);
 23.2723 +     *   else
 23.2724 +     *     return fallback(a..., b...);
 23.2725 +     * }
 23.2726 +     * }</pre></blockquote>
 23.2727 +     * Note that the test arguments ({@code a...} in the pseudocode) cannot
 23.2728 +     * be modified by execution of the test, and so are passed unchanged
 23.2729 +     * from the caller to the target or fallback as appropriate.
 23.2730 +     * @param test method handle used for test, must return boolean
 23.2731 +     * @param target method handle to call if test passes
 23.2732 +     * @param fallback method handle to call if test fails
 23.2733 +     * @return method handle which incorporates the specified if/then/else logic
 23.2734 +     * @throws NullPointerException if any argument is null
 23.2735 +     * @throws IllegalArgumentException if {@code test} does not return boolean,
 23.2736 +     *          or if all three method types do not match (with the return
 23.2737 +     *          type of {@code test} changed to match that of the target).
 23.2738 +     */
 23.2739 +    public static
 23.2740 +    MethodHandle guardWithTest(MethodHandle test,
 23.2741 +                               MethodHandle target,
 23.2742 +                               MethodHandle fallback) {
 23.2743 +        MethodType gtype = test.type();
 23.2744 +        MethodType ttype = target.type();
 23.2745 +        MethodType ftype = fallback.type();
 23.2746 +        if (!ttype.equals(ftype))
 23.2747 +            throw misMatchedTypes("target and fallback types", ttype, ftype);
 23.2748 +        if (gtype.returnType() != boolean.class)
 23.2749 +            throw newIllegalArgumentException("guard type is not a predicate "+gtype);
 23.2750 +        List<Class<?>> targs = ttype.parameterList();
 23.2751 +        List<Class<?>> gargs = gtype.parameterList();
 23.2752 +        if (!targs.equals(gargs)) {
 23.2753 +            int gpc = gargs.size(), tpc = targs.size();
 23.2754 +            if (gpc >= tpc || !targs.subList(0, gpc).equals(gargs))
 23.2755 +                throw misMatchedTypes("target and test types", ttype, gtype);
 23.2756 +            test = dropArguments(test, gpc, targs.subList(gpc, tpc));
 23.2757 +            gtype = test.type();
 23.2758 +        }
 23.2759 +        return MethodHandleImpl.makeGuardWithTest(test, target, fallback);
 23.2760 +    }
 23.2761 +
 23.2762 +    static RuntimeException misMatchedTypes(String what, MethodType t1, MethodType t2) {
 23.2763 +        return newIllegalArgumentException(what + " must match: " + t1 + " != " + t2);
 23.2764 +    }
 23.2765 +
 23.2766 +    /**
 23.2767 +     * Makes a method handle which adapts a target method handle,
 23.2768 +     * by running it inside an exception handler.
 23.2769 +     * If the target returns normally, the adapter returns that value.
 23.2770 +     * If an exception matching the specified type is thrown, the fallback
 23.2771 +     * handle is called instead on the exception, plus the original arguments.
 23.2772 +     * <p>
 23.2773 +     * The target and handler must have the same corresponding
 23.2774 +     * argument and return types, except that handler may omit trailing arguments
 23.2775 +     * (similarly to the predicate in {@link #guardWithTest guardWithTest}).
 23.2776 +     * Also, the handler must have an extra leading parameter of {@code exType} or a supertype.
 23.2777 +     * <p> Here is pseudocode for the resulting adapter:
 23.2778 +     * <blockquote><pre>{@code
 23.2779 +     * T target(A..., B...);
 23.2780 +     * T handler(ExType, A...);
 23.2781 +     * T adapter(A... a, B... b) {
 23.2782 +     *   try {
 23.2783 +     *     return target(a..., b...);
 23.2784 +     *   } catch (ExType ex) {
 23.2785 +     *     return handler(ex, a...);
 23.2786 +     *   }
 23.2787 +     * }
 23.2788 +     * }</pre></blockquote>
 23.2789 +     * Note that the saved arguments ({@code a...} in the pseudocode) cannot
 23.2790 +     * be modified by execution of the target, and so are passed unchanged
 23.2791 +     * from the caller to the handler, if the handler is invoked.
 23.2792 +     * <p>
 23.2793 +     * The target and handler must return the same type, even if the handler
 23.2794 +     * always throws.  (This might happen, for instance, because the handler
 23.2795 +     * is simulating a {@code finally} clause).
 23.2796 +     * To create such a throwing handler, compose the handler creation logic
 23.2797 +     * with {@link #throwException throwException},
 23.2798 +     * in order to create a method handle of the correct return type.
 23.2799 +     * @param target method handle to call
 23.2800 +     * @param exType the type of exception which the handler will catch
 23.2801 +     * @param handler method handle to call if a matching exception is thrown
 23.2802 +     * @return method handle which incorporates the specified try/catch logic
 23.2803 +     * @throws NullPointerException if any argument is null
 23.2804 +     * @throws IllegalArgumentException if {@code handler} does not accept
 23.2805 +     *          the given exception type, or if the method handle types do
 23.2806 +     *          not match in their return types and their
 23.2807 +     *          corresponding parameters
 23.2808 +     */
 23.2809 +    public static
 23.2810 +    MethodHandle catchException(MethodHandle target,
 23.2811 +                                Class<? extends Throwable> exType,
 23.2812 +                                MethodHandle handler) {
 23.2813 +        MethodType ttype = target.type();
 23.2814 +        MethodType htype = handler.type();
 23.2815 +        if (htype.parameterCount() < 1 ||
 23.2816 +            !htype.parameterType(0).isAssignableFrom(exType))
 23.2817 +            throw newIllegalArgumentException("handler does not accept exception type "+exType);
 23.2818 +        if (htype.returnType() != ttype.returnType())
 23.2819 +            throw misMatchedTypes("target and handler return types", ttype, htype);
 23.2820 +        List<Class<?>> targs = ttype.parameterList();
 23.2821 +        List<Class<?>> hargs = htype.parameterList();
 23.2822 +        hargs = hargs.subList(1, hargs.size());  // omit leading parameter from handler
 23.2823 +        if (!targs.equals(hargs)) {
 23.2824 +            int hpc = hargs.size(), tpc = targs.size();
 23.2825 +            if (hpc >= tpc || !targs.subList(0, hpc).equals(hargs))
 23.2826 +                throw misMatchedTypes("target and handler types", ttype, htype);
 23.2827 +            handler = dropArguments(handler, 1+hpc, targs.subList(hpc, tpc));
 23.2828 +            htype = handler.type();
 23.2829 +        }
 23.2830 +        return MethodHandleImpl.makeGuardWithCatch(target, exType, handler);
 23.2831 +    }
 23.2832 +
 23.2833 +    /**
 23.2834 +     * Produces a method handle which will throw exceptions of the given {@code exType}.
 23.2835 +     * The method handle will accept a single argument of {@code exType},
 23.2836 +     * and immediately throw it as an exception.
 23.2837 +     * The method type will nominally specify a return of {@code returnType}.
 23.2838 +     * The return type may be anything convenient:  It doesn't matter to the
 23.2839 +     * method handle's behavior, since it will never return normally.
 23.2840 +     * @param returnType the return type of the desired method handle
 23.2841 +     * @param exType the parameter type of the desired method handle
 23.2842 +     * @return method handle which can throw the given exceptions
 23.2843 +     * @throws NullPointerException if either argument is null
 23.2844 +     */
 23.2845 +    public static
 23.2846 +    MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType) {
 23.2847 +        if (!Throwable.class.isAssignableFrom(exType))
 23.2848 +            throw new ClassCastException(exType.getName());
 23.2849 +        return MethodHandleImpl.throwException(MethodType.methodType(returnType, exType));
 23.2850 +    }
 23.2851 +}
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/MethodType.java	Sat Aug 09 11:12:05 2014 +0200
    24.3 @@ -0,0 +1,1149 @@
    24.4 +/*
    24.5 + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
    24.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    24.7 + *
    24.8 + * This code is free software; you can redistribute it and/or modify it
    24.9 + * under the terms of the GNU General Public License version 2 only, as
   24.10 + * published by the Free Software Foundation.  Oracle designates this
   24.11 + * particular file as subject to the "Classpath" exception as provided
   24.12 + * by Oracle in the LICENSE file that accompanied this code.
   24.13 + *
   24.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   24.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   24.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   24.17 + * version 2 for more details (a copy is included in the LICENSE file that
   24.18 + * accompanied this code).
   24.19 + *
   24.20 + * You should have received a copy of the GNU General Public License version
   24.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   24.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   24.23 + *
   24.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   24.25 + * or visit www.oracle.com if you need additional information or have any
   24.26 + * questions.
   24.27 + */
   24.28 +
   24.29 +package java.lang.invoke;
   24.30 +
   24.31 +import sun.invoke.util.Wrapper;
   24.32 +import java.lang.ref.WeakReference;
   24.33 +import java.lang.ref.Reference;
   24.34 +import java.lang.ref.ReferenceQueue;
   24.35 +import java.util.Arrays;
   24.36 +import java.util.Collections;
   24.37 +import java.util.List;
   24.38 +import java.util.Objects;
   24.39 +import java.util.concurrent.ConcurrentMap;
   24.40 +import java.util.concurrent.ConcurrentHashMap;
   24.41 +import sun.invoke.util.BytecodeDescriptor;
   24.42 +import static java.lang.invoke.MethodHandleStatics.*;
   24.43 +import sun.invoke.util.VerifyType;
   24.44 +
   24.45 +/**
   24.46 + * A method type represents the arguments and return type accepted and
   24.47 + * returned by a method handle, or the arguments and return type passed
   24.48 + * and expected  by a method handle caller.  Method types must be properly
   24.49 + * matched between a method handle and all its callers,
   24.50 + * and the JVM's operations enforce this matching at, specifically
   24.51 + * during calls to {@link MethodHandle#invokeExact MethodHandle.invokeExact}
   24.52 + * and {@link MethodHandle#invoke MethodHandle.invoke}, and during execution
   24.53 + * of {@code invokedynamic} instructions.
   24.54 + * <p>
   24.55 + * The structure is a return type accompanied by any number of parameter types.
   24.56 + * The types (primitive, {@code void}, and reference) are represented by {@link Class} objects.
   24.57 + * (For ease of exposition, we treat {@code void} as if it were a type.
   24.58 + * In fact, it denotes the absence of a return type.)
   24.59 + * <p>
   24.60 + * All instances of {@code MethodType} are immutable.
   24.61 + * Two instances are completely interchangeable if they compare equal.
   24.62 + * Equality depends on pairwise correspondence of the return and parameter types and on nothing else.
   24.63 + * <p>
   24.64 + * This type can be created only by factory methods.
   24.65 + * All factory methods may cache values, though caching is not guaranteed.
   24.66 + * Some factory methods are static, while others are virtual methods which
   24.67 + * modify precursor method types, e.g., by changing a selected parameter.
   24.68 + * <p>
   24.69 + * Factory methods which operate on groups of parameter types
   24.70 + * are systematically presented in two versions, so that both Java arrays and
   24.71 + * Java lists can be used to work with groups of parameter types.
   24.72 + * The query methods {@code parameterArray} and {@code parameterList}
   24.73 + * also provide a choice between arrays and lists.
   24.74 + * <p>
   24.75 + * {@code MethodType} objects are sometimes derived from bytecode instructions
   24.76 + * such as {@code invokedynamic}, specifically from the type descriptor strings associated
   24.77 + * with the instructions in a class file's constant pool.
   24.78 + * <p>
   24.79 + * Like classes and strings, method types can also be represented directly
   24.80 + * in a class file's constant pool as constants.
   24.81 + * A method type may be loaded by an {@code ldc} instruction which refers
   24.82 + * to a suitable {@code CONSTANT_MethodType} constant pool entry.
   24.83 + * The entry refers to a {@code CONSTANT_Utf8} spelling for the descriptor string.
   24.84 + * (For full details on method type constants,
   24.85 + * see sections 4.4.8 and 5.4.3.5 of the Java Virtual Machine Specification.)
   24.86 + * <p>
   24.87 + * When the JVM materializes a {@code MethodType} from a descriptor string,
   24.88 + * all classes named in the descriptor must be accessible, and will be loaded.
   24.89 + * (But the classes need not be initialized, as is the case with a {@code CONSTANT_Class}.)
   24.90 + * This loading may occur at any time before the {@code MethodType} object is first derived.
   24.91 + * @author John Rose, JSR 292 EG
   24.92 + */
   24.93 +public final
   24.94 +class MethodType implements java.io.Serializable {
   24.95 +    private static final long serialVersionUID = 292L;  // {rtype, {ptype...}}
   24.96 +
   24.97 +    // The rtype and ptypes fields define the structural identity of the method type:
   24.98 +    private final Class<?>   rtype;
   24.99 +    private final Class<?>[] ptypes;
  24.100 +
  24.101 +    // The remaining fields are caches of various sorts:
  24.102 +    private @Stable MethodTypeForm form; // erased form, plus cached data about primitives
  24.103 +    private @Stable MethodType wrapAlt;  // alternative wrapped/unwrapped version
  24.104 +    private @Stable Invokers invokers;   // cache of handy higher-order adapters
  24.105 +    private @Stable String methodDescriptor;  // cache for toMethodDescriptorString
  24.106 +
  24.107 +    /**
  24.108 +     * Check the given parameters for validity and store them into the final fields.
  24.109 +     */
  24.110 +    private MethodType(Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
  24.111 +        checkRtype(rtype);
  24.112 +        checkPtypes(ptypes);
  24.113 +        this.rtype = rtype;
  24.114 +        // defensively copy the array passed in by the user
  24.115 +        this.ptypes = trusted ? ptypes : Arrays.copyOf(ptypes, ptypes.length);
  24.116 +    }
  24.117 +
  24.118 +    /**
  24.119 +     * Construct a temporary unchecked instance of MethodType for use only as a key to the intern table.
  24.120 +     * Does not check the given parameters for validity, and must be discarded after it is used as a searching key.
  24.121 +     * The parameters are reversed for this constructor, so that is is not accidentally used.
  24.122 +     */
  24.123 +    private MethodType(Class<?>[] ptypes, Class<?> rtype) {
  24.124 +        this.rtype = rtype;
  24.125 +        this.ptypes = ptypes;
  24.126 +    }
  24.127 +
  24.128 +    /*trusted*/ MethodTypeForm form() { return form; }
  24.129 +    /*trusted*/ Class<?> rtype() { return rtype; }
  24.130 +    /*trusted*/ Class<?>[] ptypes() { return ptypes; }
  24.131 +
  24.132 +    void setForm(MethodTypeForm f) { form = f; }
  24.133 +
  24.134 +    /** This number, mandated by the JVM spec as 255,
  24.135 +     *  is the maximum number of <em>slots</em>
  24.136 +     *  that any Java method can receive in its argument list.
  24.137 +     *  It limits both JVM signatures and method type objects.
  24.138 +     *  The longest possible invocation will look like
  24.139 +     *  {@code staticMethod(arg1, arg2, ..., arg255)} or
  24.140 +     *  {@code x.virtualMethod(arg1, arg2, ..., arg254)}.
  24.141 +     */
  24.142 +    /*non-public*/ static final int MAX_JVM_ARITY = 255;  // this is mandated by the JVM spec.
  24.143 +
  24.144 +    /** This number is the maximum arity of a method handle, 254.
  24.145 +     *  It is derived from the absolute JVM-imposed arity by subtracting one,
  24.146 +     *  which is the slot occupied by the method handle itself at the
  24.147 +     *  beginning of the argument list used to invoke the method handle.
  24.148 +     *  The longest possible invocation will look like
  24.149 +     *  {@code mh.invoke(arg1, arg2, ..., arg254)}.
  24.150 +     */
  24.151 +    // Issue:  Should we allow MH.invokeWithArguments to go to the full 255?
  24.152 +    /*non-public*/ static final int MAX_MH_ARITY = MAX_JVM_ARITY-1;  // deduct one for mh receiver
  24.153 +
  24.154 +    /** This number is the maximum arity of a method handle invoker, 253.
  24.155 +     *  It is derived from the absolute JVM-imposed arity by subtracting two,
  24.156 +     *  which are the slots occupied by invoke method handle, and the
  24.157 +     *  target method handle, which are both at the beginning of the argument
  24.158 +     *  list used to invoke the target method handle.
  24.159 +     *  The longest possible invocation will look like
  24.160 +     *  {@code invokermh.invoke(targetmh, arg1, arg2, ..., arg253)}.
  24.161 +     */
  24.162 +    /*non-public*/ static final int MAX_MH_INVOKER_ARITY = MAX_MH_ARITY-1;  // deduct one more for invoker
  24.163 +
  24.164 +    private static void checkRtype(Class<?> rtype) {
  24.165 +        Objects.requireNonNull(rtype);
  24.166 +    }
  24.167 +    private static void checkPtype(Class<?> ptype) {
  24.168 +        Objects.requireNonNull(ptype);
  24.169 +        if (ptype == void.class)
  24.170 +            throw newIllegalArgumentException("parameter type cannot be void");
  24.171 +    }
  24.172 +    /** Return number of extra slots (count of long/double args). */
  24.173 +    private static int checkPtypes(Class<?>[] ptypes) {
  24.174 +        int slots = 0;
  24.175 +        for (Class<?> ptype : ptypes) {
  24.176 +            checkPtype(ptype);
  24.177 +            if (ptype == double.class || ptype == long.class) {
  24.178 +                slots++;
  24.179 +            }
  24.180 +        }
  24.181 +        checkSlotCount(ptypes.length + slots);
  24.182 +        return slots;
  24.183 +    }
  24.184 +    static void checkSlotCount(int count) {
  24.185 +        assert((MAX_JVM_ARITY & (MAX_JVM_ARITY+1)) == 0);
  24.186 +        // MAX_JVM_ARITY must be power of 2 minus 1 for following code trick to work:
  24.187 +        if ((count & MAX_JVM_ARITY) != count)
  24.188 +            throw newIllegalArgumentException("bad parameter count "+count);
  24.189 +    }
  24.190 +    private static IndexOutOfBoundsException newIndexOutOfBoundsException(Object num) {
  24.191 +        if (num instanceof Integer)  num = "bad index: "+num;
  24.192 +        return new IndexOutOfBoundsException(num.toString());
  24.193 +    }
  24.194 +
  24.195 +    static final ConcurrentWeakInternSet<MethodType> internTable = new ConcurrentWeakInternSet<>();
  24.196 +
  24.197 +    static final Class<?>[] NO_PTYPES = {};
  24.198 +
  24.199 +    /**
  24.200 +     * Finds or creates an instance of the given method type.
  24.201 +     * @param rtype  the return type
  24.202 +     * @param ptypes the parameter types
  24.203 +     * @return a method type with the given components
  24.204 +     * @throws NullPointerException if {@code rtype} or {@code ptypes} or any element of {@code ptypes} is null
  24.205 +     * @throws IllegalArgumentException if any element of {@code ptypes} is {@code void.class}
  24.206 +     */
  24.207 +    public static
  24.208 +    MethodType methodType(Class<?> rtype, Class<?>[] ptypes) {
  24.209 +        return makeImpl(rtype, ptypes, false);
  24.210 +    }
  24.211 +
  24.212 +    /**
  24.213 +     * Finds or creates a method type with the given components.
  24.214 +     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
  24.215 +     * @param rtype  the return type
  24.216 +     * @param ptypes the parameter types
  24.217 +     * @return a method type with the given components
  24.218 +     * @throws NullPointerException if {@code rtype} or {@code ptypes} or any element of {@code ptypes} is null
  24.219 +     * @throws IllegalArgumentException if any element of {@code ptypes} is {@code void.class}
  24.220 +     */
  24.221 +    public static
  24.222 +    MethodType methodType(Class<?> rtype, List<Class<?>> ptypes) {
  24.223 +        boolean notrust = false;  // random List impl. could return evil ptypes array
  24.224 +        return makeImpl(rtype, listToArray(ptypes), notrust);
  24.225 +    }
  24.226 +
  24.227 +    private static Class<?>[] listToArray(List<Class<?>> ptypes) {
  24.228 +        // sanity check the size before the toArray call, since size might be huge
  24.229 +        checkSlotCount(ptypes.size());
  24.230 +        return ptypes.toArray(NO_PTYPES);
  24.231 +    }
  24.232 +
  24.233 +    /**
  24.234 +     * Finds or creates a method type with the given components.
  24.235 +     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
  24.236 +     * The leading parameter type is prepended to the remaining array.
  24.237 +     * @param rtype  the return type
  24.238 +     * @param ptype0 the first parameter type
  24.239 +     * @param ptypes the remaining parameter types
  24.240 +     * @return a method type with the given components
  24.241 +     * @throws NullPointerException if {@code rtype} or {@code ptype0} or {@code ptypes} or any element of {@code ptypes} is null
  24.242 +     * @throws IllegalArgumentException if {@code ptype0} or {@code ptypes} or any element of {@code ptypes} is {@code void.class}
  24.243 +     */
  24.244 +    public static
  24.245 +    MethodType methodType(Class<?> rtype, Class<?> ptype0, Class<?>... ptypes) {
  24.246 +        Class<?>[] ptypes1 = new Class<?>[1+ptypes.length];
  24.247 +        ptypes1[0] = ptype0;
  24.248 +        System.arraycopy(ptypes, 0, ptypes1, 1, ptypes.length);
  24.249 +        return makeImpl(rtype, ptypes1, true);
  24.250 +    }
  24.251 +
  24.252 +    /**
  24.253 +     * Finds or creates a method type with the given components.
  24.254 +     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
  24.255 +     * The resulting method has no parameter types.
  24.256 +     * @param rtype  the return type
  24.257 +     * @return a method type with the given return value
  24.258 +     * @throws NullPointerException if {@code rtype} is null
  24.259 +     */
  24.260 +    public static
  24.261 +    MethodType methodType(Class<?> rtype) {
  24.262 +        return makeImpl(rtype, NO_PTYPES, true);
  24.263 +    }
  24.264 +
  24.265 +    /**
  24.266 +     * Finds or creates a method type with the given components.
  24.267 +     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
  24.268 +     * The resulting method has the single given parameter type.
  24.269 +     * @param rtype  the return type
  24.270 +     * @param ptype0 the parameter type
  24.271 +     * @return a method type with the given return value and parameter type
  24.272 +     * @throws NullPointerException if {@code rtype} or {@code ptype0} is null
  24.273 +     * @throws IllegalArgumentException if {@code ptype0} is {@code void.class}
  24.274 +     */
  24.275 +    public static
  24.276 +    MethodType methodType(Class<?> rtype, Class<?> ptype0) {
  24.277 +        return makeImpl(rtype, new Class<?>[]{ ptype0 }, true);
  24.278 +    }
  24.279 +
  24.280 +    /**
  24.281 +     * Finds or creates a method type with the given components.
  24.282 +     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
  24.283 +     * The resulting method has the same parameter types as {@code ptypes},
  24.284 +     * and the specified return type.
  24.285 +     * @param rtype  the return type
  24.286 +     * @param ptypes the method type which supplies the parameter types
  24.287 +     * @return a method type with the given components
  24.288 +     * @throws NullPointerException if {@code rtype} or {@code ptypes} is null
  24.289 +     */
  24.290 +    public static
  24.291 +    MethodType methodType(Class<?> rtype, MethodType ptypes) {
  24.292 +        return makeImpl(rtype, ptypes.ptypes, true);
  24.293 +    }
  24.294 +
  24.295 +    /**
  24.296 +     * Sole factory method to find or create an interned method type.
  24.297 +     * @param rtype desired return type
  24.298 +     * @param ptypes desired parameter types
  24.299 +     * @param trusted whether the ptypes can be used without cloning
  24.300 +     * @return the unique method type of the desired structure
  24.301 +     */
  24.302 +    /*trusted*/ static
  24.303 +    MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
  24.304 +        MethodType mt = internTable.get(new MethodType(ptypes, rtype));
  24.305 +        if (mt != null)
  24.306 +            return mt;
  24.307 +        if (ptypes.length == 0) {
  24.308 +            ptypes = NO_PTYPES; trusted = true;
  24.309 +        }
  24.310 +        mt = new MethodType(rtype, ptypes, trusted);
  24.311 +        // promote the object to the Real Thing, and reprobe
  24.312 +        mt.form = MethodTypeForm.findForm(mt);
  24.313 +        return internTable.add(mt);
  24.314 +    }
  24.315 +    private static final MethodType[] objectOnlyTypes = new MethodType[20];
  24.316 +
  24.317 +    /**
  24.318 +     * Finds or creates a method type whose components are {@code Object} with an optional trailing {@code Object[]} array.
  24.319 +     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
  24.320 +     * All parameters and the return type will be {@code Object},
  24.321 +     * except the final array parameter if any, which will be {@code Object[]}.
  24.322 +     * @param objectArgCount number of parameters (excluding the final array parameter if any)
  24.323 +     * @param finalArray whether there will be a trailing array parameter, of type {@code Object[]}
  24.324 +     * @return a generally applicable method type, for all calls of the given fixed argument count and a collected array of further arguments
  24.325 +     * @throws IllegalArgumentException if {@code objectArgCount} is negative or greater than 255 (or 254, if {@code finalArray} is true)
  24.326 +     * @see #genericMethodType(int)
  24.327 +     */
  24.328 +    public static
  24.329 +    MethodType genericMethodType(int objectArgCount, boolean finalArray) {
  24.330 +        MethodType mt;
  24.331 +        checkSlotCount(objectArgCount);
  24.332 +        int ivarargs = (!finalArray ? 0 : 1);
  24.333 +        int ootIndex = objectArgCount*2 + ivarargs;
  24.334 +        if (ootIndex < objectOnlyTypes.length) {
  24.335 +            mt = objectOnlyTypes[ootIndex];
  24.336 +            if (mt != null)  return mt;
  24.337 +        }
  24.338 +        Class<?>[] ptypes = new Class<?>[objectArgCount + ivarargs];
  24.339 +        Arrays.fill(ptypes, Object.class);
  24.340 +        if (ivarargs != 0)  ptypes[objectArgCount] = Object[].class;
  24.341 +        mt = makeImpl(Object.class, ptypes, true);
  24.342 +        if (ootIndex < objectOnlyTypes.length) {
  24.343 +            objectOnlyTypes[ootIndex] = mt;     // cache it here also!
  24.344 +        }
  24.345 +        return mt;
  24.346 +    }
  24.347 +
  24.348 +    /**
  24.349 +     * Finds or creates a method type whose components are all {@code Object}.
  24.350 +     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
  24.351 +     * All parameters and the return type will be Object.
  24.352 +     * @param objectArgCount number of parameters
  24.353 +     * @return a generally applicable method type, for all calls of the given argument count
  24.354 +     * @throws IllegalArgumentException if {@code objectArgCount} is negative or greater than 255
  24.355 +     * @see #genericMethodType(int, boolean)
  24.356 +     */
  24.357 +    public static
  24.358 +    MethodType genericMethodType(int objectArgCount) {
  24.359 +        return genericMethodType(objectArgCount, false);
  24.360 +    }
  24.361 +
  24.362 +    /**
  24.363 +     * Finds or creates a method type with a single different parameter type.
  24.364 +     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
  24.365 +     * @param num    the index (zero-based) of the parameter type to change
  24.366 +     * @param nptype a new parameter type to replace the old one with
  24.367 +     * @return the same type, except with the selected parameter changed
  24.368 +     * @throws IndexOutOfBoundsException if {@code num} is not a valid index into {@code parameterArray()}
  24.369 +     * @throws IllegalArgumentException if {@code nptype} is {@code void.class}
  24.370 +     * @throws NullPointerException if {@code nptype} is null
  24.371 +     */
  24.372 +    public MethodType changeParameterType(int num, Class<?> nptype) {
  24.373 +        if (parameterType(num) == nptype)  return this;
  24.374 +        checkPtype(nptype);
  24.375 +        Class<?>[] nptypes = ptypes.clone();
  24.376 +        nptypes[num] = nptype;
  24.377 +        return makeImpl(rtype, nptypes, true);
  24.378 +    }
  24.379 +
  24.380 +    /**
  24.381 +     * Finds or creates a method type with additional parameter types.
  24.382 +     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
  24.383 +     * @param num    the position (zero-based) of the inserted parameter type(s)
  24.384 +     * @param ptypesToInsert zero or more new parameter types to insert into the parameter list
  24.385 +     * @return the same type, except with the selected parameter(s) inserted
  24.386 +     * @throws IndexOutOfBoundsException if {@code num} is negative or greater than {@code parameterCount()}
  24.387 +     * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
  24.388 +     *                                  or if the resulting method type would have more than 255 parameter slots
  24.389 +     * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
  24.390 +     */
  24.391 +    public MethodType insertParameterTypes(int num, Class<?>... ptypesToInsert) {
  24.392 +        int len = ptypes.length;
  24.393 +        if (num < 0 || num > len)
  24.394 +            throw newIndexOutOfBoundsException(num);
  24.395 +        int ins = checkPtypes(ptypesToInsert);
  24.396 +        checkSlotCount(parameterSlotCount() + ptypesToInsert.length + ins);
  24.397 +        int ilen = ptypesToInsert.length;
  24.398 +        if (ilen == 0)  return this;
  24.399 +        Class<?>[] nptypes = Arrays.copyOfRange(ptypes, 0, len+ilen);
  24.400 +        System.arraycopy(nptypes, num, nptypes, num+ilen, len-num);
  24.401 +        System.arraycopy(ptypesToInsert, 0, nptypes, num, ilen);
  24.402 +        return makeImpl(rtype, nptypes, true);
  24.403 +    }
  24.404 +
  24.405 +    /**
  24.406 +     * Finds or creates a method type with additional parameter types.
  24.407 +     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
  24.408 +     * @param ptypesToInsert zero or more new parameter types to insert after the end of the parameter list
  24.409 +     * @return the same type, except with the selected parameter(s) appended
  24.410 +     * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
  24.411 +     *                                  or if the resulting method type would have more than 255 parameter slots
  24.412 +     * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
  24.413 +     */
  24.414 +    public MethodType appendParameterTypes(Class<?>... ptypesToInsert) {
  24.415 +        return insertParameterTypes(parameterCount(), ptypesToInsert);
  24.416 +    }
  24.417 +
  24.418 +    /**
  24.419 +     * Finds or creates a method type with additional parameter types.
  24.420 +     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
  24.421 +     * @param num    the position (zero-based) of the inserted parameter type(s)
  24.422 +     * @param ptypesToInsert zero or more new parameter types to insert into the parameter list
  24.423 +     * @return the same type, except with the selected parameter(s) inserted
  24.424 +     * @throws IndexOutOfBoundsException if {@code num} is negative or greater than {@code parameterCount()}
  24.425 +     * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
  24.426 +     *                                  or if the resulting method type would have more than 255 parameter slots
  24.427 +     * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
  24.428 +     */
  24.429 +    public MethodType insertParameterTypes(int num, List<Class<?>> ptypesToInsert) {
  24.430 +        return insertParameterTypes(num, listToArray(ptypesToInsert));
  24.431 +    }
  24.432 +
  24.433 +    /**
  24.434 +     * Finds or creates a method type with additional parameter types.
  24.435 +     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
  24.436 +     * @param ptypesToInsert zero or more new parameter types to insert after the end of the parameter list
  24.437 +     * @return the same type, except with the selected parameter(s) appended
  24.438 +     * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
  24.439 +     *                                  or if the resulting method type would have more than 255 parameter slots
  24.440 +     * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
  24.441 +     */
  24.442 +    public MethodType appendParameterTypes(List<Class<?>> ptypesToInsert) {
  24.443 +        return insertParameterTypes(parameterCount(), ptypesToInsert);
  24.444 +    }
  24.445 +
  24.446 +     /**
  24.447 +     * Finds or creates a method type with modified parameter types.
  24.448 +     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
  24.449 +     * @param start  the position (zero-based) of the first replaced parameter type(s)
  24.450 +     * @param end    the position (zero-based) after the last replaced parameter type(s)
  24.451 +     * @param ptypesToInsert zero or more new parameter types to insert into the parameter list
  24.452 +     * @return the same type, except with the selected parameter(s) replaced
  24.453 +     * @throws IndexOutOfBoundsException if {@code start} is negative or greater than {@code parameterCount()}
  24.454 +     *                                  or if {@code end} is negative or greater than {@code parameterCount()}
  24.455 +     *                                  or if {@code start} is greater than {@code end}
  24.456 +     * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
  24.457 +     *                                  or if the resulting method type would have more than 255 parameter slots
  24.458 +     * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
  24.459 +     */
  24.460 +    /*non-public*/ MethodType replaceParameterTypes(int start, int end, Class<?>... ptypesToInsert) {
  24.461 +        if (start == end)
  24.462 +            return insertParameterTypes(start, ptypesToInsert);
  24.463 +        int len = ptypes.length;
  24.464 +        if (!(0 <= start && start <= end && end <= len))
  24.465 +            throw newIndexOutOfBoundsException("start="+start+" end="+end);
  24.466 +        int ilen = ptypesToInsert.length;
  24.467 +        if (ilen == 0)
  24.468 +            return dropParameterTypes(start, end);
  24.469 +        return dropParameterTypes(start, end).insertParameterTypes(start, ptypesToInsert);
  24.470 +    }
  24.471 +
  24.472 +    /**
  24.473 +     * Finds or creates a method type with some parameter types omitted.
  24.474 +     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
  24.475 +     * @param start  the index (zero-based) of the first parameter type to remove
  24.476 +     * @param end    the index (greater than {@code start}) of the first parameter type after not to remove
  24.477 +     * @return the same type, except with the selected parameter(s) removed
  24.478 +     * @throws IndexOutOfBoundsException if {@code start} is negative or greater than {@code parameterCount()}
  24.479 +     *                                  or if {@code end} is negative or greater than {@code parameterCount()}
  24.480 +     *                                  or if {@code start} is greater than {@code end}
  24.481 +     */
  24.482 +    public MethodType dropParameterTypes(int start, int end) {
  24.483 +        int len = ptypes.length;
  24.484 +        if (!(0 <= start && start <= end && end <= len))
  24.485 +            throw newIndexOutOfBoundsException("start="+start+" end="+end);
  24.486 +        if (start == end)  return this;
  24.487 +        Class<?>[] nptypes;
  24.488 +        if (start == 0) {
  24.489 +            if (end == len) {
  24.490 +                // drop all parameters
  24.491 +                nptypes = NO_PTYPES;
  24.492 +            } else {
  24.493 +                // drop initial parameter(s)
  24.494 +                nptypes = Arrays.copyOfRange(ptypes, end, len);
  24.495 +            }
  24.496 +        } else {
  24.497 +            if (end == len) {
  24.498 +                // drop trailing parameter(s)
  24.499 +                nptypes = Arrays.copyOfRange(ptypes, 0, start);
  24.500 +            } else {
  24.501 +                int tail = len - end;
  24.502 +                nptypes = Arrays.copyOfRange(ptypes, 0, start + tail);
  24.503 +                System.arraycopy(ptypes, end, nptypes, start, tail);
  24.504 +            }
  24.505 +        }
  24.506 +        return makeImpl(rtype, nptypes, true);
  24.507 +    }
  24.508 +
  24.509 +    /**
  24.510 +     * Finds or creates a method type with a different return type.
  24.511 +     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
  24.512 +     * @param nrtype a return parameter type to replace the old one with
  24.513 +     * @return the same type, except with the return type change
  24.514 +     * @throws NullPointerException if {@code nrtype} is null
  24.515 +     */
  24.516 +    public MethodType changeReturnType(Class<?> nrtype) {
  24.517 +        if (returnType() == nrtype)  return this;
  24.518 +        return makeImpl(nrtype, ptypes, true);
  24.519 +    }
  24.520 +
  24.521 +    /**
  24.522 +     * Reports if this type contains a primitive argument or return value.
  24.523 +     * The return type {@code void} counts as a primitive.
  24.524 +     * @return true if any of the types are primitives
  24.525 +     */
  24.526 +    public boolean hasPrimitives() {
  24.527 +        return form.hasPrimitives();
  24.528 +    }
  24.529 +
  24.530 +    /**
  24.531 +     * Reports if this type contains a wrapper argument or return value.
  24.532 +     * Wrappers are types which box primitive values, such as {@link Integer}.
  24.533 +     * The reference type {@code java.lang.Void} counts as a wrapper,
  24.534 +     * if it occurs as a return type.
  24.535 +     * @return true if any of the types are wrappers
  24.536 +     */
  24.537 +    public boolean hasWrappers() {
  24.538 +        return unwrap() != this;
  24.539 +    }
  24.540 +
  24.541 +    /**
  24.542 +     * Erases all reference types to {@code Object}.
  24.543 +     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
  24.544 +     * All primitive types (including {@code void}) will remain unchanged.
  24.545 +     * @return a version of the original type with all reference types replaced
  24.546 +     */
  24.547 +    public MethodType erase() {
  24.548 +        return form.erasedType();
  24.549 +    }
  24.550 +
  24.551 +    /**
  24.552 +     * Erases all reference types to {@code Object}, and all subword types to {@code int}.
  24.553 +     * This is the reduced type polymorphism used by private methods
  24.554 +     * such as {@link MethodHandle#invokeBasic invokeBasic}.
  24.555 +     * @return a version of the original type with all reference and subword types replaced
  24.556 +     */
  24.557 +    /*non-public*/ MethodType basicType() {
  24.558 +        return form.basicType();
  24.559 +    }
  24.560 +
  24.561 +    /**
  24.562 +     * @return a version of the original type with MethodHandle prepended as the first argument
  24.563 +     */
  24.564 +    /*non-public*/ MethodType invokerType() {
  24.565 +        return insertParameterTypes(0, MethodHandle.class);
  24.566 +    }
  24.567 +
  24.568 +    /**
  24.569 +     * Converts all types, both reference and primitive, to {@code Object}.
  24.570 +     * Convenience method for {@link #genericMethodType(int) genericMethodType}.
  24.571 +     * The expression {@code type.wrap().erase()} produces the same value
  24.572 +     * as {@code type.generic()}.
  24.573 +     * @return a version of the original type with all types replaced
  24.574 +     */
  24.575 +    public MethodType generic() {
  24.576 +        return genericMethodType(parameterCount());
  24.577 +    }
  24.578 +
  24.579 +    /**
  24.580 +     * Converts all primitive types to their corresponding wrapper types.
  24.581 +     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
  24.582 +     * All reference types (including wrapper types) will remain unchanged.
  24.583 +     * A {@code void} return type is changed to the type {@code java.lang.Void}.
  24.584 +     * The expression {@code type.wrap().erase()} produces the same value
  24.585 +     * as {@code type.generic()}.
  24.586 +     * @return a version of the original type with all primitive types replaced
  24.587 +     */
  24.588 +    public MethodType wrap() {
  24.589 +        return hasPrimitives() ? wrapWithPrims(this) : this;
  24.590 +    }
  24.591 +
  24.592 +    /**
  24.593 +     * Converts all wrapper types to their corresponding primitive types.
  24.594 +     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
  24.595 +     * All primitive types (including {@code void}) will remain unchanged.
  24.596 +     * A return type of {@code java.lang.Void} is changed to {@code void}.
  24.597 +     * @return a version of the original type with all wrapper types replaced
  24.598 +     */
  24.599 +    public MethodType unwrap() {
  24.600 +        MethodType noprims = !hasPrimitives() ? this : wrapWithPrims(this);
  24.601 +        return unwrapWithNoPrims(noprims);
  24.602 +    }
  24.603 +
  24.604 +    private static MethodType wrapWithPrims(MethodType pt) {
  24.605 +        assert(pt.hasPrimitives());
  24.606 +        MethodType wt = pt.wrapAlt;
  24.607 +        if (wt == null) {
  24.608 +            // fill in lazily
  24.609 +            wt = MethodTypeForm.canonicalize(pt, MethodTypeForm.WRAP, MethodTypeForm.WRAP);
  24.610 +            assert(wt != null);
  24.611 +            pt.wrapAlt = wt;
  24.612 +        }
  24.613 +        return wt;
  24.614 +    }
  24.615 +
  24.616 +    private static MethodType unwrapWithNoPrims(MethodType wt) {
  24.617 +        assert(!wt.hasPrimitives());
  24.618 +        MethodType uwt = wt.wrapAlt;
  24.619 +        if (uwt == null) {
  24.620 +            // fill in lazily
  24.621 +            uwt = MethodTypeForm.canonicalize(wt, MethodTypeForm.UNWRAP, MethodTypeForm.UNWRAP);
  24.622 +            if (uwt == null)
  24.623 +                uwt = wt;    // type has no wrappers or prims at all
  24.624 +            wt.wrapAlt = uwt;
  24.625 +        }
  24.626 +        return uwt;
  24.627 +    }
  24.628 +
  24.629 +    /**
  24.630 +     * Returns the parameter type at the specified index, within this method type.
  24.631 +     * @param num the index (zero-based) of the desired parameter type
  24.632 +     * @return the selected parameter type
  24.633 +     * @throws IndexOutOfBoundsException if {@code num} is not a valid index into {@code parameterArray()}
  24.634 +     */
  24.635 +    public Class<?> parameterType(int num) {
  24.636 +        return ptypes[num];
  24.637 +    }
  24.638 +    /**
  24.639 +     * Returns the number of parameter types in this method type.
  24.640 +     * @return the number of parameter types
  24.641 +     */
  24.642 +    public int parameterCount() {
  24.643 +        return ptypes.length;
  24.644 +    }
  24.645 +    /**
  24.646 +     * Returns the return type of this method type.
  24.647 +     * @return the return type
  24.648 +     */
  24.649 +    public Class<?> returnType() {
  24.650 +        return rtype;
  24.651 +    }
  24.652 +
  24.653 +    /**
  24.654 +     * Presents the parameter types as a list (a convenience method).
  24.655 +     * The list will be immutable.
  24.656 +     * @return the parameter types (as an immutable list)
  24.657 +     */
  24.658 +    public List<Class<?>> parameterList() {
  24.659 +        return Collections.unmodifiableList(Arrays.asList(ptypes));
  24.660 +    }
  24.661 +
  24.662 +    /*non-public*/ Class<?> lastParameterType() {
  24.663 +        int len = ptypes.length;
  24.664 +        return len == 0 ? void.class : ptypes[len-1];
  24.665 +    }
  24.666 +
  24.667 +    /**
  24.668 +     * Presents the parameter types as an array (a convenience method).
  24.669 +     * Changes to the array will not result in changes to the type.
  24.670 +     * @return the parameter types (as a fresh copy if necessary)
  24.671 +     */
  24.672 +    public Class<?>[] parameterArray() {
  24.673 +        return ptypes.clone();
  24.674 +    }
  24.675 +
  24.676 +    /**
  24.677 +     * Compares the specified object with this type for equality.
  24.678 +     * That is, it returns <tt>true</tt> if and only if the specified object
  24.679 +     * is also a method type with exactly the same parameters and return type.
  24.680 +     * @param x object to compare
  24.681 +     * @see Object#equals(Object)
  24.682 +     */
  24.683 +    @Override
  24.684 +    public boolean equals(Object x) {
  24.685 +        return this == x || x instanceof MethodType && equals((MethodType)x);
  24.686 +    }
  24.687 +
  24.688 +    private boolean equals(MethodType that) {
  24.689 +        return this.rtype == that.rtype
  24.690 +            && Arrays.equals(this.ptypes, that.ptypes);
  24.691 +    }
  24.692 +
  24.693 +    /**
  24.694 +     * Returns the hash code value for this method type.
  24.695 +     * It is defined to be the same as the hashcode of a List
  24.696 +     * whose elements are the return type followed by the
  24.697 +     * parameter types.
  24.698 +     * @return the hash code value for this method type
  24.699 +     * @see Object#hashCode()
  24.700 +     * @see #equals(Object)
  24.701 +     * @see List#hashCode()
  24.702 +     */
  24.703 +    @Override
  24.704 +    public int hashCode() {
  24.705 +      int hashCode = 31 + rtype.hashCode();
  24.706 +      for (Class<?> ptype : ptypes)
  24.707 +          hashCode = 31*hashCode + ptype.hashCode();
  24.708 +      return hashCode;
  24.709 +    }
  24.710 +
  24.711 +    /**
  24.712 +     * Returns a string representation of the method type,
  24.713 +     * of the form {@code "(PT0,PT1...)RT"}.
  24.714 +     * The string representation of a method type is a
  24.715 +     * parenthesis enclosed, comma separated list of type names,
  24.716 +     * followed immediately by the return type.
  24.717 +     * <p>
  24.718 +     * Each type is represented by its
  24.719 +     * {@link java.lang.Class#getSimpleName simple name}.
  24.720 +     */
  24.721 +    @Override
  24.722 +    public String toString() {
  24.723 +        StringBuilder sb = new StringBuilder();
  24.724 +        sb.append("(");
  24.725 +        for (int i = 0; i < ptypes.length; i++) {
  24.726 +            if (i > 0)  sb.append(",");
  24.727 +            sb.append(ptypes[i].getSimpleName());
  24.728 +        }
  24.729 +        sb.append(")");
  24.730 +        sb.append(rtype.getSimpleName());
  24.731 +        return sb.toString();
  24.732 +    }
  24.733 +
  24.734 +
  24.735 +    /*non-public*/
  24.736 +    boolean isViewableAs(MethodType newType) {
  24.737 +        if (!VerifyType.isNullConversion(returnType(), newType.returnType()))
  24.738 +            return false;
  24.739 +        int argc = parameterCount();
  24.740 +        if (argc != newType.parameterCount())
  24.741 +            return false;
  24.742 +        for (int i = 0; i < argc; i++) {
  24.743 +            if (!VerifyType.isNullConversion(newType.parameterType(i), parameterType(i)))
  24.744 +                return false;
  24.745 +        }
  24.746 +        return true;
  24.747 +    }
  24.748 +    /*non-public*/
  24.749 +    boolean isCastableTo(MethodType newType) {
  24.750 +        int argc = parameterCount();
  24.751 +        if (argc != newType.parameterCount())
  24.752 +            return false;
  24.753 +        return true;
  24.754 +    }
  24.755 +    /*non-public*/
  24.756 +    boolean isConvertibleTo(MethodType newType) {
  24.757 +        if (!canConvert(returnType(), newType.returnType()))
  24.758 +            return false;
  24.759 +        int argc = parameterCount();
  24.760 +        if (argc != newType.parameterCount())
  24.761 +            return false;
  24.762 +        for (int i = 0; i < argc; i++) {
  24.763 +            if (!canConvert(newType.parameterType(i), parameterType(i)))
  24.764 +                return false;
  24.765 +        }
  24.766 +        return true;
  24.767 +    }
  24.768 +    /*non-public*/
  24.769 +    static boolean canConvert(Class<?> src, Class<?> dst) {
  24.770 +        // short-circuit a few cases:
  24.771 +        if (src == dst || dst == Object.class)  return true;
  24.772 +        // the remainder of this logic is documented in MethodHandle.asType
  24.773 +        if (src.isPrimitive()) {
  24.774 +            // can force void to an explicit null, a la reflect.Method.invoke
  24.775 +            // can also force void to a primitive zero, by analogy
  24.776 +            if (src == void.class)  return true;  //or !dst.isPrimitive()?
  24.777 +            Wrapper sw = Wrapper.forPrimitiveType(src);
  24.778 +            if (dst.isPrimitive()) {
  24.779 +                // P->P must widen
  24.780 +                return Wrapper.forPrimitiveType(dst).isConvertibleFrom(sw);
  24.781 +            } else {
  24.782 +                // P->R must box and widen
  24.783 +                return dst.isAssignableFrom(sw.wrapperType());
  24.784 +            }
  24.785 +        } else if (dst.isPrimitive()) {
  24.786 +            // any value can be dropped
  24.787 +            if (dst == void.class)  return true;
  24.788 +            Wrapper dw = Wrapper.forPrimitiveType(dst);
  24.789 +            // R->P must be able to unbox (from a dynamically chosen type) and widen
  24.790 +            // For example:
  24.791 +            //   Byte/Number/Comparable/Object -> dw:Byte -> byte.
  24.792 +            //   Character/Comparable/Object -> dw:Character -> char
  24.793 +            //   Boolean/Comparable/Object -> dw:Boolean -> boolean
  24.794 +            // This means that dw must be cast-compatible with src.
  24.795 +            if (src.isAssignableFrom(dw.wrapperType())) {
  24.796 +                return true;
  24.797 +            }
  24.798 +            // The above does not work if the source reference is strongly typed
  24.799 +            // to a wrapper whose primitive must be widened.  For example:
  24.800 +            //   Byte -> unbox:byte -> short/int/long/float/double
  24.801 +            //   Character -> unbox:char -> int/long/float/double
  24.802 +            if (Wrapper.isWrapperType(src) &&
  24.803 +                dw.isConvertibleFrom(Wrapper.forWrapperType(src))) {
  24.804 +                // can unbox from src and then widen to dst
  24.805 +                return true;
  24.806 +            }
  24.807 +            // We have already covered cases which arise due to runtime unboxing
  24.808 +            // of a reference type which covers several wrapper types:
  24.809 +            //   Object -> cast:Integer -> unbox:int -> long/float/double
  24.810 +            //   Serializable -> cast:Byte -> unbox:byte -> byte/short/int/long/float/double
  24.811 +            // An marginal case is Number -> dw:Character -> char, which would be OK if there were a
  24.812 +            // subclass of Number which wraps a value that can convert to char.
  24.813 +            // Since there is none, we don't need an extra check here to cover char or boolean.
  24.814 +            return false;
  24.815 +        } else {
  24.816 +            // R->R always works, since null is always valid dynamically
  24.817 +            return true;
  24.818 +        }
  24.819 +    }
  24.820 +
  24.821 +    /// Queries which have to do with the bytecode architecture
  24.822 +
  24.823 +    /** Reports the number of JVM stack slots required to invoke a method
  24.824 +     * of this type.  Note that (for historical reasons) the JVM requires
  24.825 +     * a second stack slot to pass long and double arguments.
  24.826 +     * So this method returns {@link #parameterCount() parameterCount} plus the
  24.827 +     * number of long and double parameters (if any).
  24.828 +     * <p>
  24.829 +     * This method is included for the benefit of applications that must
  24.830 +     * generate bytecodes that process method handles and invokedynamic.
  24.831 +     * @return the number of JVM stack slots for this type's parameters
  24.832 +     */
  24.833 +    /*non-public*/ int parameterSlotCount() {
  24.834 +        return form.parameterSlotCount();
  24.835 +    }
  24.836 +
  24.837 +    /*non-public*/ Invokers invokers() {
  24.838 +        Invokers inv = invokers;
  24.839 +        if (inv != null)  return inv;
  24.840 +        invokers = inv = new Invokers(this);
  24.841 +        return inv;
  24.842 +    }
  24.843 +
  24.844 +    /** Reports the number of JVM stack slots which carry all parameters including and after
  24.845 +     * the given position, which must be in the range of 0 to
  24.846 +     * {@code parameterCount} inclusive.  Successive parameters are
  24.847 +     * more shallowly stacked, and parameters are indexed in the bytecodes
  24.848 +     * according to their trailing edge.  Thus, to obtain the depth
  24.849 +     * in the outgoing call stack of parameter {@code N}, obtain
  24.850 +     * the {@code parameterSlotDepth} of its trailing edge
  24.851 +     * at position {@code N+1}.
  24.852 +     * <p>
  24.853 +     * Parameters of type {@code long} and {@code double} occupy
  24.854 +     * two stack slots (for historical reasons) and all others occupy one.
  24.855 +     * Therefore, the number returned is the number of arguments
  24.856 +     * <em>including</em> and <em>after</em> the given parameter,
  24.857 +     * <em>plus</em> the number of long or double arguments
  24.858 +     * at or after after the argument for the given parameter.
  24.859 +     * <p>
  24.860 +     * This method is included for the benefit of applications that must
  24.861 +     * generate bytecodes that process method handles and invokedynamic.
  24.862 +     * @param num an index (zero-based, inclusive) within the parameter types
  24.863 +     * @return the index of the (shallowest) JVM stack slot transmitting the
  24.864 +     *         given parameter
  24.865 +     * @throws IllegalArgumentException if {@code num} is negative or greater than {@code parameterCount()}
  24.866 +     */
  24.867 +    /*non-public*/ int parameterSlotDepth(int num) {
  24.868 +        if (num < 0 || num > ptypes.length)
  24.869 +            parameterType(num);  // force a range check
  24.870 +        return form.parameterToArgSlot(num-1);
  24.871 +    }
  24.872 +
  24.873 +    /** Reports the number of JVM stack slots required to receive a return value
  24.874 +     * from a method of this type.
  24.875 +     * If the {@link #returnType() return type} is void, it will be zero,
  24.876 +     * else if the return type is long or double, it will be two, else one.
  24.877 +     * <p>
  24.878 +     * This method is included for the benefit of applications that must
  24.879 +     * generate bytecodes that process method handles and invokedynamic.
  24.880 +     * @return the number of JVM stack slots (0, 1, or 2) for this type's return value
  24.881 +     * Will be removed for PFD.
  24.882 +     */
  24.883 +    /*non-public*/ int returnSlotCount() {
  24.884 +        return form.returnSlotCount();
  24.885 +    }
  24.886 +
  24.887 +    /**
  24.888 +     * Finds or creates an instance of a method type, given the spelling of its bytecode descriptor.
  24.889 +     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
  24.890 +     * Any class or interface name embedded in the descriptor string
  24.891 +     * will be resolved by calling {@link ClassLoader#loadClass(java.lang.String)}
  24.892 +     * on the given loader (or if it is null, on the system class loader).
  24.893 +     * <p>
  24.894 +     * Note that it is possible to encounter method types which cannot be
  24.895 +     * constructed by this method, because their component types are
  24.896 +     * not all reachable from a common class loader.
  24.897 +     * <p>
  24.898 +     * This method is included for the benefit of applications that must
  24.899 +     * generate bytecodes that process method handles and {@code invokedynamic}.
  24.900 +     * @param descriptor a bytecode-level type descriptor string "(T...)T"
  24.901 +     * @param loader the class loader in which to look up the types
  24.902 +     * @return a method type matching the bytecode-level type descriptor
  24.903 +     * @throws NullPointerException if the string is null
  24.904 +     * @throws IllegalArgumentException if the string is not well-formed
  24.905 +     * @throws TypeNotPresentException if a named type cannot be found
  24.906 +     */
  24.907 +    public static MethodType fromMethodDescriptorString(String descriptor, ClassLoader loader)
  24.908 +        throws IllegalArgumentException, TypeNotPresentException
  24.909 +    {
  24.910 +        if (!descriptor.startsWith("(") ||  // also generates NPE if needed
  24.911 +            descriptor.indexOf(')') < 0 ||
  24.912 +            descriptor.indexOf('.') >= 0)
  24.913 +            throw new IllegalArgumentException("not a method descriptor: "+descriptor);
  24.914 +        List<Class<?>> types = BytecodeDescriptor.parseMethod(descriptor, loader);
  24.915 +        Class<?> rtype = types.remove(types.size() - 1);
  24.916 +        checkSlotCount(types.size());
  24.917 +        Class<?>[] ptypes = listToArray(types);
  24.918 +        return makeImpl(rtype, ptypes, true);
  24.919 +    }
  24.920 +
  24.921 +    /**
  24.922 +     * Produces a bytecode descriptor representation of the method type.
  24.923 +     * <p>
  24.924 +     * Note that this is not a strict inverse of {@link #fromMethodDescriptorString fromMethodDescriptorString}.
  24.925 +     * Two distinct classes which share a common name but have different class loaders
  24.926 +     * will appear identical when viewed within descriptor strings.
  24.927 +     * <p>
  24.928 +     * This method is included for the benefit of applications that must
  24.929 +     * generate bytecodes that process method handles and {@code invokedynamic}.
  24.930 +     * {@link #fromMethodDescriptorString(java.lang.String, java.lang.ClassLoader) fromMethodDescriptorString},
  24.931 +     * because the latter requires a suitable class loader argument.
  24.932 +     * @return the bytecode type descriptor representation
  24.933 +     */
  24.934 +    public String toMethodDescriptorString() {
  24.935 +        String desc = methodDescriptor;
  24.936 +        if (desc == null) {
  24.937 +            desc = BytecodeDescriptor.unparse(this);
  24.938 +            methodDescriptor = desc;
  24.939 +        }
  24.940 +        return desc;
  24.941 +    }
  24.942 +
  24.943 +    /*non-public*/ static String toFieldDescriptorString(Class<?> cls) {
  24.944 +        return BytecodeDescriptor.unparse(cls);
  24.945 +    }
  24.946 +
  24.947 +    /// Serialization.
  24.948 +
  24.949 +    /**
  24.950 +     * There are no serializable fields for {@code MethodType}.
  24.951 +     */
  24.952 +    private static final java.io.ObjectStreamField[] serialPersistentFields = { };
  24.953 +
  24.954 +    /**
  24.955 +     * Save the {@code MethodType} instance to a stream.
  24.956 +     *
  24.957 +     * @serialData
  24.958 +     * For portability, the serialized format does not refer to named fields.
  24.959 +     * Instead, the return type and parameter type arrays are written directly
  24.960 +     * from the {@code writeObject} method, using two calls to {@code s.writeObject}
  24.961 +     * as follows:
  24.962 +     * <blockquote><pre>{@code
  24.963 +s.writeObject(this.returnType());
  24.964 +s.writeObject(this.parameterArray());
  24.965 +     * }</pre></blockquote>
  24.966 +     * <p>
  24.967 +     * The deserialized field values are checked as if they were
  24.968 +     * provided to the factory method {@link #methodType(Class,Class[]) methodType}.
  24.969 +     * For example, null values, or {@code void} parameter types,
  24.970 +     * will lead to exceptions during deserialization.
  24.971 +     * @param s the stream to write the object to
  24.972 +     * @throws java.io.IOException if there is a problem writing the object
  24.973 +     */
  24.974 +    private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
  24.975 +        s.defaultWriteObject();  // requires serialPersistentFields to be an empty array
  24.976 +        s.writeObject(returnType());
  24.977 +        s.writeObject(parameterArray());
  24.978 +    }
  24.979 +
  24.980 +    /**
  24.981 +     * Reconstitute the {@code MethodType} instance from a stream (that is,
  24.982 +     * deserialize it).
  24.983 +     * This instance is a scratch object with bogus final fields.
  24.984 +     * It provides the parameters to the factory method called by
  24.985 +     * {@link #readResolve readResolve}.
  24.986 +     * After that call it is discarded.
  24.987 +     * @param s the stream to read the object from
  24.988 +     * @throws java.io.IOException if there is a problem reading the object
  24.989 +     * @throws ClassNotFoundException if one of the component classes cannot be resolved
  24.990 +     * @see #MethodType()
  24.991 +     * @see #readResolve
  24.992 +     * @see #writeObject
  24.993 +     */
  24.994 +    private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
  24.995 +        s.defaultReadObject();  // requires serialPersistentFields to be an empty array
  24.996 +
  24.997 +        Class<?>   returnType     = (Class<?>)   s.readObject();
  24.998 +        Class<?>[] parameterArray = (Class<?>[]) s.readObject();
  24.999 +
 24.1000 +        // Probably this object will never escape, but let's check
 24.1001 +        // the field values now, just to be sure.
 24.1002 +        checkRtype(returnType);
 24.1003 +        checkPtypes(parameterArray);
 24.1004 +
 24.1005 +        parameterArray = parameterArray.clone();  // make sure it is unshared
 24.1006 +        MethodType_init(returnType, parameterArray);
 24.1007 +    }
 24.1008 +
 24.1009 +    /**
 24.1010 +     * For serialization only.
 24.1011 +     * Sets the final fields to null, pending {@code Unsafe.putObject}.
 24.1012 +     */
 24.1013 +    private MethodType() {
 24.1014 +        this.rtype = null;
 24.1015 +        this.ptypes = null;
 24.1016 +    }
 24.1017 +    private void MethodType_init(Class<?> rtype, Class<?>[] ptypes) {
 24.1018 +        // In order to communicate these values to readResolve, we must
 24.1019 +        // store them into the implementation-specific final fields.
 24.1020 +        checkRtype(rtype);
 24.1021 +        checkPtypes(ptypes);
 24.1022 +        UNSAFE.putObject(this, rtypeOffset, rtype);
 24.1023 +        UNSAFE.putObject(this, ptypesOffset, ptypes);
 24.1024 +    }
 24.1025 +
 24.1026 +    // Support for resetting final fields while deserializing
 24.1027 +    private static final long rtypeOffset, ptypesOffset;
 24.1028 +    static {
 24.1029 +        try {
 24.1030 +            rtypeOffset = UNSAFE.objectFieldOffset
 24.1031 +                (MethodType.class.getDeclaredField("rtype"));
 24.1032 +            ptypesOffset = UNSAFE.objectFieldOffset
 24.1033 +                (MethodType.class.getDeclaredField("ptypes"));
 24.1034 +        } catch (Exception ex) {
 24.1035 +            throw new Error(ex);
 24.1036 +        }
 24.1037 +    }
 24.1038 +
 24.1039 +    /**
 24.1040 +     * Resolves and initializes a {@code MethodType} object
 24.1041 +     * after serialization.
 24.1042 +     * @return the fully initialized {@code MethodType} object
 24.1043 +     */
 24.1044 +    private Object readResolve() {
 24.1045 +        // Do not use a trusted path for deserialization:
 24.1046 +        //return makeImpl(rtype, ptypes, true);
 24.1047 +        // Verify all operands, and make sure ptypes is unshared:
 24.1048 +        return methodType(rtype, ptypes);
 24.1049 +    }
 24.1050 +
 24.1051 +    /**
 24.1052 +     * Simple implementation of weak concurrent intern set.
 24.1053 +     *
 24.1054 +     * @param <T> interned type
 24.1055 +     */
 24.1056 +    private static class ConcurrentWeakInternSet<T> {
 24.1057 +
 24.1058 +        private final ConcurrentMap<WeakEntry<T>, WeakEntry<T>> map;
 24.1059 +        private final ReferenceQueue<T> stale;
 24.1060 +
 24.1061 +        public ConcurrentWeakInternSet() {
 24.1062 +            this.map = new ConcurrentHashMap<>();
 24.1063 +            this.stale = new ReferenceQueue<>();
 24.1064 +        }
 24.1065 +
 24.1066 +        /**
 24.1067 +         * Get the existing interned element.
 24.1068 +         * This method returns null if no element is interned.
 24.1069 +         *
 24.1070 +         * @param elem element to look up
 24.1071 +         * @return the interned element
 24.1072 +         */
 24.1073 +        public T get(T elem) {
 24.1074 +            if (elem == null) throw new NullPointerException();
 24.1075 +            expungeStaleElements();
 24.1076 +
 24.1077 +            WeakEntry<T> value = map.get(new WeakEntry<>(elem));
 24.1078 +            if (value != null) {
 24.1079 +                T res = value.get();
 24.1080 +                if (res != null) {
 24.1081 +                    return res;
 24.1082 +                }
 24.1083 +            }
 24.1084 +            return null;
 24.1085 +        }
 24.1086 +
 24.1087 +        /**
 24.1088 +         * Interns the element.
 24.1089 +         * Always returns non-null element, matching the one in the intern set.
 24.1090 +         * Under the race against another add(), it can return <i>different</i>
 24.1091 +         * element, if another thread beats us to interning it.
 24.1092 +         *
 24.1093 +         * @param elem element to add
 24.1094 +         * @return element that was actually added
 24.1095 +         */
 24.1096 +        public T add(T elem) {
 24.1097 +            if (elem == null) throw new NullPointerException();
 24.1098 +
 24.1099 +            // Playing double race here, and so spinloop is required.
 24.1100 +            // First race is with two concurrent updaters.
 24.1101 +            // Second race is with GC purging weak ref under our feet.
 24.1102 +            // Hopefully, we almost always end up with a single pass.
 24.1103 +            T interned;
 24.1104 +            WeakEntry<T> e = new WeakEntry<>(elem, stale);
 24.1105 +            do {
 24.1106 +                expungeStaleElements();
 24.1107 +                WeakEntry<T> exist = map.putIfAbsent(e, e);
 24.1108 +                interned = (exist == null) ? elem : exist.get();
 24.1109 +            } while (interned == null);
 24.1110 +            return interned;
 24.1111 +        }
 24.1112 +
 24.1113 +        private void expungeStaleElements() {
 24.1114 +            Reference<? extends T> reference;
 24.1115 +            while ((reference = stale.poll()) != null) {
 24.1116 +                map.remove(reference);
 24.1117 +            }
 24.1118 +        }
 24.1119 +
 24.1120 +        private static class WeakEntry<T> extends WeakReference<T> {
 24.1121 +
 24.1122 +            public final int hashcode;
 24.1123 +
 24.1124 +            public WeakEntry(T key, ReferenceQueue<T> queue) {
 24.1125 +                super(key, queue);
 24.1126 +                hashcode = key.hashCode();
 24.1127 +            }
 24.1128 +
 24.1129 +            public WeakEntry(T key) {
 24.1130 +                super(key);
 24.1131 +                hashcode = key.hashCode();
 24.1132 +            }
 24.1133 +
 24.1134 +            @Override
 24.1135 +            public boolean equals(Object obj) {
 24.1136 +                if (obj instanceof WeakEntry) {
 24.1137 +                    Object that = ((WeakEntry) obj).get();
 24.1138 +                    Object mine = get();
 24.1139 +                    return (that == null || mine == null) ? (this == obj) : mine.equals(that);
 24.1140 +                }
 24.1141 +                return false;
 24.1142 +            }
 24.1143 +
 24.1144 +            @Override
 24.1145 +            public int hashCode() {
 24.1146 +                return hashcode;
 24.1147 +            }
 24.1148 +
 24.1149 +        }
 24.1150 +    }
 24.1151 +
 24.1152 +}
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/MethodTypeForm.java	Sat Aug 09 11:12:05 2014 +0200
    25.3 @@ -0,0 +1,388 @@
    25.4 +/*
    25.5 + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
    25.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    25.7 + *
    25.8 + * This code is free software; you can redistribute it and/or modify it
    25.9 + * under the terms of the GNU General Public License version 2 only, as
   25.10 + * published by the Free Software Foundation.  Oracle designates this
   25.11 + * particular file as subject to the "Classpath" exception as provided
   25.12 + * by Oracle in the LICENSE file that accompanied this code.
   25.13 + *
   25.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   25.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   25.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   25.17 + * version 2 for more details (a copy is included in the LICENSE file that
   25.18 + * accompanied this code).
   25.19 + *
   25.20 + * You should have received a copy of the GNU General Public License version
   25.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   25.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   25.23 + *
   25.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   25.25 + * or visit www.oracle.com if you need additional information or have any
   25.26 + * questions.
   25.27 + */
   25.28 +
   25.29 +package java.lang.invoke;
   25.30 +
   25.31 +import sun.invoke.util.Wrapper;
   25.32 +import static java.lang.invoke.MethodHandleStatics.*;
   25.33 +import static java.lang.invoke.MethodHandleNatives.Constants.*;
   25.34 + import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
   25.35 +
   25.36 +/**
   25.37 + * Shared information for a group of method types, which differ
   25.38 + * only by reference types, and therefore share a common erasure
   25.39 + * and wrapping.
   25.40 + * <p>
   25.41 + * For an empirical discussion of the structure of method types,
   25.42 + * see <a href="http://groups.google.com/group/jvm-languages/browse_thread/thread/ac9308ae74da9b7e/">
   25.43 + * the thread "Avoiding Boxing" on jvm-languages</a>.
   25.44 + * There are approximately 2000 distinct erased method types in the JDK.
   25.45 + * There are a little over 10 times that number of unerased types.
   25.46 + * No more than half of these are likely to be loaded at once.
   25.47 + * @author John Rose
   25.48 + */
   25.49 +final class MethodTypeForm {
   25.50 +    final int[] argToSlotTable, slotToArgTable;
   25.51 +    final long argCounts;               // packed slot & value counts
   25.52 +    final long primCounts;              // packed prim & double counts
   25.53 +    final int vmslots;                  // total number of parameter slots
   25.54 +    final MethodType erasedType;        // the canonical erasure
   25.55 +    final MethodType basicType;         // the canonical erasure, with primitives simplified
   25.56 +
   25.57 +    // Cached adapter information:
   25.58 +    @Stable String typeString;           // argument type signature characters
   25.59 +    @Stable MethodHandle genericInvoker; // JVM hook for inexact invoke
   25.60 +    @Stable MethodHandle basicInvoker;   // cached instance of MH.invokeBasic
   25.61 +    @Stable MethodHandle namedFunctionInvoker; // cached helper for LF.NamedFunction
   25.62 +
   25.63 +    // Cached lambda form information, for basic types only:
   25.64 +    final @Stable LambdaForm[] lambdaForms;
   25.65 +    // Indexes into lambdaForms:
   25.66 +    static final int
   25.67 +            LF_INVVIRTUAL     =  0,  // DMH invokeVirtual
   25.68 +            LF_INVSTATIC      =  1,
   25.69 +            LF_INVSPECIAL     =  2,
   25.70 +            LF_NEWINVSPECIAL  =  3,
   25.71 +            LF_INVINTERFACE   =  4,
   25.72 +            LF_INVSTATIC_INIT =  5,  // DMH invokeStatic with <clinit> barrier
   25.73 +            LF_INTERPRET      =  6,  // LF interpreter
   25.74 +            LF_COUNTER        =  7,  // CMH wrapper
   25.75 +            LF_REINVOKE       =  8,  // other wrapper
   25.76 +            LF_EX_LINKER      =  9,  // invokeExact_MT
   25.77 +            LF_EX_INVOKER     = 10,  // invokeExact MH
   25.78 +            LF_GEN_LINKER     = 11,
   25.79 +            LF_GEN_INVOKER    = 12,
   25.80 +            LF_CS_LINKER      = 13,  // linkToCallSite_CS
   25.81 +            LF_MH_LINKER      = 14,  // linkToCallSite_MH
   25.82 +            LF_LIMIT          = 15;
   25.83 +
   25.84 +    public MethodType erasedType() {
   25.85 +        return erasedType;
   25.86 +    }
   25.87 +
   25.88 +    public MethodType basicType() {
   25.89 +        return basicType;
   25.90 +    }
   25.91 +
   25.92 +    public LambdaForm cachedLambdaForm(int which) {
   25.93 +        return lambdaForms[which];
   25.94 +    }
   25.95 +
   25.96 +    public LambdaForm setCachedLambdaForm(int which, LambdaForm form) {
   25.97 +        // Should we perform some sort of CAS, to avoid racy duplication?
   25.98 +        return lambdaForms[which] = form;
   25.99 +    }
  25.100 +
  25.101 +    public MethodHandle basicInvoker() {
  25.102 +        assert(erasedType == basicType) : "erasedType: " + erasedType + " != basicType: " + basicType;  // primitives must be flattened also
  25.103 +        MethodHandle invoker = basicInvoker;
  25.104 +        if (invoker != null)  return invoker;
  25.105 +        invoker = DirectMethodHandle.make(invokeBasicMethod(basicType));
  25.106 +        basicInvoker = invoker;
  25.107 +        return invoker;
  25.108 +    }
  25.109 +
  25.110 +    // This next one is called from LambdaForm.NamedFunction.<init>.
  25.111 +    /*non-public*/ static MemberName invokeBasicMethod(MethodType basicType) {
  25.112 +        assert(basicType == basicType.basicType());
  25.113 +        try {
  25.114 +            // Do approximately the same as this public API call:
  25.115 +            //   Lookup.findVirtual(MethodHandle.class, name, type);
  25.116 +            // But bypass access and corner case checks, since we know exactly what we need.
  25.117 +            return IMPL_LOOKUP.resolveOrFail(REF_invokeVirtual, MethodHandle.class, "invokeBasic", basicType);
  25.118 +         } catch (ReflectiveOperationException ex) {
  25.119 +            throw newInternalError("JVM cannot find invoker for "+basicType, ex);
  25.120 +        }
  25.121 +    }
  25.122 +
  25.123 +    /**
  25.124 +     * Build an MTF for a given type, which must have all references erased to Object.
  25.125 +     * This MTF will stand for that type and all un-erased variations.
  25.126 +     * Eagerly compute some basic properties of the type, common to all variations.
  25.127 +     */
  25.128 +    protected MethodTypeForm(MethodType erasedType) {
  25.129 +        this.erasedType = erasedType;
  25.130 +
  25.131 +        Class<?>[] ptypes = erasedType.ptypes();
  25.132 +        int ptypeCount = ptypes.length;
  25.133 +        int pslotCount = ptypeCount;            // temp. estimate
  25.134 +        int rtypeCount = 1;                     // temp. estimate
  25.135 +        int rslotCount = 1;                     // temp. estimate
  25.136 +
  25.137 +        int[] argToSlotTab = null, slotToArgTab = null;
  25.138 +
  25.139 +        // Walk the argument types, looking for primitives.
  25.140 +        int pac = 0, lac = 0, prc = 0, lrc = 0;
  25.141 +        Class<?>[] epts = ptypes;
  25.142 +        Class<?>[] bpts = epts;
  25.143 +        for (int i = 0; i < epts.length; i++) {
  25.144 +            Class<?> pt = epts[i];
  25.145 +            if (pt != Object.class) {
  25.146 +                ++pac;
  25.147 +                Wrapper w = Wrapper.forPrimitiveType(pt);
  25.148 +                if (w.isDoubleWord())  ++lac;
  25.149 +                if (w.isSubwordOrInt() && pt != int.class) {
  25.150 +                    if (bpts == epts)
  25.151 +                        bpts = bpts.clone();
  25.152 +                    bpts[i] = int.class;
  25.153 +                }
  25.154 +            }
  25.155 +        }
  25.156 +        pslotCount += lac;                  // #slots = #args + #longs
  25.157 +        Class<?> rt = erasedType.returnType();
  25.158 +        Class<?> bt = rt;
  25.159 +        if (rt != Object.class) {
  25.160 +            ++prc;          // even void.class counts as a prim here
  25.161 +            Wrapper w = Wrapper.forPrimitiveType(rt);
  25.162 +            if (w.isDoubleWord())  ++lrc;
  25.163 +            if (w.isSubwordOrInt() && rt != int.class)
  25.164 +                bt = int.class;
  25.165 +            // adjust #slots, #args
  25.166 +            if (rt == void.class)
  25.167 +                rtypeCount = rslotCount = 0;
  25.168 +            else
  25.169 +                rslotCount += lrc;
  25.170 +        }
  25.171 +        if (epts == bpts && bt == rt) {
  25.172 +            this.basicType = erasedType;
  25.173 +        } else {
  25.174 +            this.basicType = MethodType.makeImpl(bt, bpts, true);
  25.175 +        }
  25.176 +        if (lac != 0) {
  25.177 +            int slot = ptypeCount + lac;
  25.178 +            slotToArgTab = new int[slot+1];
  25.179 +            argToSlotTab = new int[1+ptypeCount];
  25.180 +            argToSlotTab[0] = slot;  // argument "-1" is past end of slots
  25.181 +            for (int i = 0; i < epts.length; i++) {
  25.182 +                Class<?> pt = epts[i];
  25.183 +                Wrapper w = Wrapper.forBasicType(pt);
  25.184 +                if (w.isDoubleWord())  --slot;
  25.185 +                --slot;
  25.186 +                slotToArgTab[slot] = i+1; // "+1" see argSlotToParameter note
  25.187 +                argToSlotTab[1+i]  = slot;
  25.188 +            }
  25.189 +            assert(slot == 0);  // filled the table
  25.190 +        }
  25.191 +        this.primCounts = pack(lrc, prc, lac, pac);
  25.192 +        this.argCounts = pack(rslotCount, rtypeCount, pslotCount, ptypeCount);
  25.193 +        if (slotToArgTab == null) {
  25.194 +            int slot = ptypeCount; // first arg is deepest in stack
  25.195 +            slotToArgTab = new int[slot+1];
  25.196 +            argToSlotTab = new int[1+ptypeCount];
  25.197 +            argToSlotTab[0] = slot;  // argument "-1" is past end of slots
  25.198 +            for (int i = 0; i < ptypeCount; i++) {
  25.199 +                --slot;
  25.200 +                slotToArgTab[slot] = i+1; // "+1" see argSlotToParameter note
  25.201 +                argToSlotTab[1+i]  = slot;
  25.202 +            }
  25.203 +        }
  25.204 +        this.argToSlotTable = argToSlotTab;
  25.205 +        this.slotToArgTable = slotToArgTab;
  25.206 +
  25.207 +        if (pslotCount >= 256)  throw newIllegalArgumentException("too many arguments");
  25.208 +
  25.209 +        // send a few bits down to the JVM:
  25.210 +        this.vmslots = parameterSlotCount();
  25.211 +
  25.212 +        if (basicType == erasedType) {
  25.213 +            lambdaForms = new LambdaForm[LF_LIMIT];
  25.214 +        } else {
  25.215 +            lambdaForms = null;  // could be basicType.form().lambdaForms;
  25.216 +        }
  25.217 +    }
  25.218 +
  25.219 +    private static long pack(int a, int b, int c, int d) {
  25.220 +        assert(((a|b|c|d) & ~0xFFFF) == 0);
  25.221 +        long hw = ((a << 16) | b), lw = ((c << 16) | d);
  25.222 +        return (hw << 32) | lw;
  25.223 +    }
  25.224 +    private static char unpack(long packed, int word) { // word==0 => return a, ==3 => return d
  25.225 +        assert(word <= 3);
  25.226 +        return (char)(packed >> ((3-word) * 16));
  25.227 +    }
  25.228 +
  25.229 +    public int parameterCount() {                      // # outgoing values
  25.230 +        return unpack(argCounts, 3);
  25.231 +    }
  25.232 +    public int parameterSlotCount() {                  // # outgoing interpreter slots
  25.233 +        return unpack(argCounts, 2);
  25.234 +    }
  25.235 +    public int returnCount() {                         // = 0 (V), or 1
  25.236 +        return unpack(argCounts, 1);
  25.237 +    }
  25.238 +    public int returnSlotCount() {                     // = 0 (V), 2 (J/D), or 1
  25.239 +        return unpack(argCounts, 0);
  25.240 +    }
  25.241 +    public int primitiveParameterCount() {
  25.242 +        return unpack(primCounts, 3);
  25.243 +    }
  25.244 +    public int longPrimitiveParameterCount() {
  25.245 +        return unpack(primCounts, 2);
  25.246 +    }
  25.247 +    public int primitiveReturnCount() {                // = 0 (obj), or 1
  25.248 +        return unpack(primCounts, 1);
  25.249 +    }
  25.250 +    public int longPrimitiveReturnCount() {            // = 1 (J/D), or 0
  25.251 +        return unpack(primCounts, 0);
  25.252 +    }
  25.253 +    public boolean hasPrimitives() {
  25.254 +        return primCounts != 0;
  25.255 +    }
  25.256 +    public boolean hasNonVoidPrimitives() {
  25.257 +        if (primCounts == 0)  return false;
  25.258 +        if (primitiveParameterCount() != 0)  return true;
  25.259 +        return (primitiveReturnCount() != 0 && returnCount() != 0);
  25.260 +    }
  25.261 +    public boolean hasLongPrimitives() {
  25.262 +        return (longPrimitiveParameterCount() | longPrimitiveReturnCount()) != 0;
  25.263 +    }
  25.264 +    public int parameterToArgSlot(int i) {
  25.265 +        return argToSlotTable[1+i];
  25.266 +    }
  25.267 +    public int argSlotToParameter(int argSlot) {
  25.268 +        // Note:  Empty slots are represented by zero in this table.
  25.269 +        // Valid arguments slots contain incremented entries, so as to be non-zero.
  25.270 +        // We return -1 the caller to mean an empty slot.
  25.271 +        return slotToArgTable[argSlot] - 1;
  25.272 +    }
  25.273 +
  25.274 +    static MethodTypeForm findForm(MethodType mt) {
  25.275 +        MethodType erased = canonicalize(mt, ERASE, ERASE);
  25.276 +        if (erased == null) {
  25.277 +            // It is already erased.  Make a new MethodTypeForm.
  25.278 +            return new MethodTypeForm(mt);
  25.279 +        } else {
  25.280 +            // Share the MethodTypeForm with the erased version.
  25.281 +            return erased.form();
  25.282 +        }
  25.283 +    }
  25.284 +
  25.285 +    /** Codes for {@link #canonicalize(java.lang.Class, int)}.
  25.286 +     * ERASE means change every reference to {@code Object}.
  25.287 +     * WRAP means convert primitives (including {@code void} to their
  25.288 +     * corresponding wrapper types.  UNWRAP means the reverse of WRAP.
  25.289 +     * INTS means convert all non-void primitive types to int or long,
  25.290 +     * according to size.  LONGS means convert all non-void primitives
  25.291 +     * to long, regardless of size.  RAW_RETURN means convert a type
  25.292 +     * (assumed to be a return type) to int if it is smaller than an int,
  25.293 +     * or if it is void.
  25.294 +     */
  25.295 +    public static final int NO_CHANGE = 0, ERASE = 1, WRAP = 2, UNWRAP = 3, INTS = 4, LONGS = 5, RAW_RETURN = 6;
  25.296 +
  25.297 +    /** Canonicalize the types in the given method type.
  25.298 +     * If any types change, intern the new type, and return it.
  25.299 +     * Otherwise return null.
  25.300 +     */
  25.301 +    public static MethodType canonicalize(MethodType mt, int howRet, int howArgs) {
  25.302 +        Class<?>[] ptypes = mt.ptypes();
  25.303 +        Class<?>[] ptc = MethodTypeForm.canonicalizes(ptypes, howArgs);
  25.304 +        Class<?> rtype = mt.returnType();
  25.305 +        Class<?> rtc = MethodTypeForm.canonicalize(rtype, howRet);
  25.306 +        if (ptc == null && rtc == null) {
  25.307 +            // It is already canonical.
  25.308 +            return null;
  25.309 +        }
  25.310 +        // Find the erased version of the method type:
  25.311 +        if (rtc == null)  rtc = rtype;
  25.312 +        if (ptc == null)  ptc = ptypes;
  25.313 +        return MethodType.makeImpl(rtc, ptc, true);
  25.314 +    }
  25.315 +
  25.316 +    /** Canonicalize the given return or param type.
  25.317 +     *  Return null if the type is already canonicalized.
  25.318 +     */
  25.319 +    static Class<?> canonicalize(Class<?> t, int how) {
  25.320 +        Class<?> ct;
  25.321 +        if (t == Object.class) {
  25.322 +            // no change, ever
  25.323 +        } else if (!t.isPrimitive()) {
  25.324 +            switch (how) {
  25.325 +                case UNWRAP:
  25.326 +                    ct = Wrapper.asPrimitiveType(t);
  25.327 +                    if (ct != t)  return ct;
  25.328 +                    break;
  25.329 +                case RAW_RETURN:
  25.330 +                case ERASE:
  25.331 +                    return Object.class;
  25.332 +            }
  25.333 +        } else if (t == void.class) {
  25.334 +            // no change, usually
  25.335 +            switch (how) {
  25.336 +                case RAW_RETURN:
  25.337 +                    return int.class;
  25.338 +                case WRAP:
  25.339 +                    return Void.class;
  25.340 +            }
  25.341 +        } else {
  25.342 +            // non-void primitive
  25.343 +            switch (how) {
  25.344 +                case WRAP:
  25.345 +                    return Wrapper.asWrapperType(t);
  25.346 +                case INTS:
  25.347 +                    if (t == int.class || t == long.class)
  25.348 +                        return null;  // no change
  25.349 +                    if (t == double.class)
  25.350 +                        return long.class;
  25.351 +                    return int.class;
  25.352 +                case LONGS:
  25.353 +                    if (t == long.class)
  25.354 +                        return null;  // no change
  25.355 +                    return long.class;
  25.356 +                case RAW_RETURN:
  25.357 +                    if (t == int.class || t == long.class ||
  25.358 +                        t == float.class || t == double.class)
  25.359 +                        return null;  // no change
  25.360 +                    // everything else returns as an int
  25.361 +                    return int.class;
  25.362 +            }
  25.363 +        }
  25.364 +        // no change; return null to signify
  25.365 +        return null;
  25.366 +    }
  25.367 +
  25.368 +    /** Canonicalize each param type in the given array.
  25.369 +     *  Return null if all types are already canonicalized.
  25.370 +     */
  25.371 +    static Class<?>[] canonicalizes(Class<?>[] ts, int how) {
  25.372 +        Class<?>[] cs = null;
  25.373 +        for (int imax = ts.length, i = 0; i < imax; i++) {
  25.374 +            Class<?> c = canonicalize(ts[i], how);
  25.375 +            if (c == void.class)
  25.376 +                c = null;  // a Void parameter was unwrapped to void; ignore
  25.377 +            if (c != null) {
  25.378 +                if (cs == null)
  25.379 +                    cs = ts.clone();
  25.380 +                cs[i] = c;
  25.381 +            }
  25.382 +        }
  25.383 +        return cs;
  25.384 +    }
  25.385 +
  25.386 +    @Override
  25.387 +    public String toString() {
  25.388 +        return "Form"+erasedType;
  25.389 +    }
  25.390 +
  25.391 +}
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/MutableCallSite.java	Sat Aug 09 11:12:05 2014 +0200
    26.3 @@ -0,0 +1,283 @@
    26.4 +/*
    26.5 + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
    26.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    26.7 + *
    26.8 + * This code is free software; you can redistribute it and/or modify it
    26.9 + * under the terms of the GNU General Public License version 2 only, as
   26.10 + * published by the Free Software Foundation.  Oracle designates this
   26.11 + * particular file as subject to the "Classpath" exception as provided
   26.12 + * by Oracle in the LICENSE file that accompanied this code.
   26.13 + *
   26.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   26.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   26.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   26.17 + * version 2 for more details (a copy is included in the LICENSE file that
   26.18 + * accompanied this code).
   26.19 + *
   26.20 + * You should have received a copy of the GNU General Public License version
   26.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   26.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   26.23 + *
   26.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   26.25 + * or visit www.oracle.com if you need additional information or have any
   26.26 + * questions.
   26.27 + */
   26.28 +
   26.29 +package java.lang.invoke;
   26.30 +
   26.31 +import java.util.concurrent.atomic.AtomicInteger;
   26.32 +
   26.33 +/**
   26.34 + * A {@code MutableCallSite} is a {@link CallSite} whose target variable
   26.35 + * behaves like an ordinary field.
   26.36 + * An {@code invokedynamic} instruction linked to a {@code MutableCallSite} delegates
   26.37 + * all calls to the site's current target.
   26.38 + * The {@linkplain CallSite#dynamicInvoker dynamic invoker} of a mutable call site
   26.39 + * also delegates each call to the site's current target.
   26.40 + * <p>
   26.41 + * Here is an example of a mutable call site which introduces a
   26.42 + * state variable into a method handle chain.
   26.43 + * <!-- JavaDocExamplesTest.testMutableCallSite -->
   26.44 + * <blockquote><pre>{@code
   26.45 +MutableCallSite name = new MutableCallSite(MethodType.methodType(String.class));
   26.46 +MethodHandle MH_name = name.dynamicInvoker();
   26.47 +MethodType MT_str1 = MethodType.methodType(String.class);
   26.48 +MethodHandle MH_upcase = MethodHandles.lookup()
   26.49 +    .findVirtual(String.class, "toUpperCase", MT_str1);
   26.50 +MethodHandle worker1 = MethodHandles.filterReturnValue(MH_name, MH_upcase);
   26.51 +name.setTarget(MethodHandles.constant(String.class, "Rocky"));
   26.52 +assertEquals("ROCKY", (String) worker1.invokeExact());
   26.53 +name.setTarget(MethodHandles.constant(String.class, "Fred"));
   26.54 +assertEquals("FRED", (String) worker1.invokeExact());
   26.55 +// (mutation can be continued indefinitely)
   26.56 + * }</pre></blockquote>
   26.57 + * <p>
   26.58 + * The same call site may be used in several places at once.
   26.59 + * <blockquote><pre>{@code
   26.60 +MethodType MT_str2 = MethodType.methodType(String.class, String.class);
   26.61 +MethodHandle MH_cat = lookup().findVirtual(String.class,
   26.62 +  "concat", methodType(String.class, String.class));
   26.63 +MethodHandle MH_dear = MethodHandles.insertArguments(MH_cat, 1, ", dear?");
   26.64 +MethodHandle worker2 = MethodHandles.filterReturnValue(MH_name, MH_dear);
   26.65 +assertEquals("Fred, dear?", (String) worker2.invokeExact());
   26.66 +name.setTarget(MethodHandles.constant(String.class, "Wilma"));
   26.67 +assertEquals("WILMA", (String) worker1.invokeExact());
   26.68 +assertEquals("Wilma, dear?", (String) worker2.invokeExact());
   26.69 + * }</pre></blockquote>
   26.70 + * <p>
   26.71 + * <em>Non-synchronization of target values:</em>
   26.72 + * A write to a mutable call site's target does not force other threads
   26.73 + * to become aware of the updated value.  Threads which do not perform
   26.74 + * suitable synchronization actions relative to the updated call site
   26.75 + * may cache the old target value and delay their use of the new target
   26.76 + * value indefinitely.
   26.77 + * (This is a normal consequence of the Java Memory Model as applied
   26.78 + * to object fields.)
   26.79 + * <p>
   26.80 + * The {@link #syncAll syncAll} operation provides a way to force threads
   26.81 + * to accept a new target value, even if there is no other synchronization.
   26.82 + * <p>
   26.83 + * For target values which will be frequently updated, consider using
   26.84 + * a {@linkplain VolatileCallSite volatile call site} instead.
   26.85 + * @author John Rose, JSR 292 EG
   26.86 + */
   26.87 +public class MutableCallSite extends CallSite {
   26.88 +    /**
   26.89 +     * Creates a blank call site object with the given method type.
   26.90 +     * The initial target is set to a method handle of the given type
   26.91 +     * which will throw an {@link IllegalStateException} if called.
   26.92 +     * <p>
   26.93 +     * The type of the call site is permanently set to the given type.
   26.94 +     * <p>
   26.95 +     * Before this {@code CallSite} object is returned from a bootstrap method,
   26.96 +     * or invoked in some other manner,
   26.97 +     * it is usually provided with a more useful target method,
   26.98 +     * via a call to {@link CallSite#setTarget(MethodHandle) setTarget}.
   26.99 +     * @param type the method type that this call site will have
  26.100 +     * @throws NullPointerException if the proposed type is null
  26.101 +     */
  26.102 +    public MutableCallSite(MethodType type) {
  26.103 +        super(type);
  26.104 +    }
  26.105 +
  26.106 +    /**
  26.107 +     * Creates a call site object with an initial target method handle.
  26.108 +     * The type of the call site is permanently set to the initial target's type.
  26.109 +     * @param target the method handle that will be the initial target of the call site
  26.110 +     * @throws NullPointerException if the proposed target is null
  26.111 +     */
  26.112 +    public MutableCallSite(MethodHandle target) {
  26.113 +        super(target);
  26.114 +    }
  26.115 +
  26.116 +    /**
  26.117 +     * Returns the target method of the call site, which behaves
  26.118 +     * like a normal field of the {@code MutableCallSite}.
  26.119 +     * <p>
  26.120 +     * The interactions of {@code getTarget} with memory are the same
  26.121 +     * as of a read from an ordinary variable, such as an array element or a
  26.122 +     * non-volatile, non-final field.
  26.123 +     * <p>
  26.124 +     * In particular, the current thread may choose to reuse the result
  26.125 +     * of a previous read of the target from memory, and may fail to see
  26.126 +     * a recent update to the target by another thread.
  26.127 +     *
  26.128 +     * @return the linkage state of this call site, a method handle which can change over time
  26.129 +     * @see #setTarget
  26.130 +     */
  26.131 +    @Override public final MethodHandle getTarget() {
  26.132 +        return target;
  26.133 +    }
  26.134 +
  26.135 +    /**
  26.136 +     * Updates the target method of this call site, as a normal variable.
  26.137 +     * The type of the new target must agree with the type of the old target.
  26.138 +     * <p>
  26.139 +     * The interactions with memory are the same
  26.140 +     * as of a write to an ordinary variable, such as an array element or a
  26.141 +     * non-volatile, non-final field.
  26.142 +     * <p>
  26.143 +     * In particular, unrelated threads may fail to see the updated target
  26.144 +     * until they perform a read from memory.
  26.145 +     * Stronger guarantees can be created by putting appropriate operations
  26.146 +     * into the bootstrap method and/or the target methods used
  26.147 +     * at any given call site.
  26.148 +     *
  26.149 +     * @param newTarget the new target
  26.150 +     * @throws NullPointerException if the proposed new target is null
  26.151 +     * @throws WrongMethodTypeException if the proposed new target
  26.152 +     *         has a method type that differs from the previous target
  26.153 +     * @see #getTarget
  26.154 +     */
  26.155 +    @Override public void setTarget(MethodHandle newTarget) {
  26.156 +        checkTargetChange(this.target, newTarget);
  26.157 +        setTargetNormal(newTarget);
  26.158 +    }
  26.159 +
  26.160 +    /**
  26.161 +     * {@inheritDoc}
  26.162 +     */
  26.163 +    @Override
  26.164 +    public final MethodHandle dynamicInvoker() {
  26.165 +        return makeDynamicInvoker();
  26.166 +    }
  26.167 +
  26.168 +    /**
  26.169 +     * Performs a synchronization operation on each call site in the given array,
  26.170 +     * forcing all other threads to throw away any cached values previously
  26.171 +     * loaded from the target of any of the call sites.
  26.172 +     * <p>
  26.173 +     * This operation does not reverse any calls that have already started
  26.174 +     * on an old target value.
  26.175 +     * (Java supports {@linkplain java.lang.Object#wait() forward time travel} only.)
  26.176 +     * <p>
  26.177 +     * The overall effect is to force all future readers of each call site's target
  26.178 +     * to accept the most recently stored value.
  26.179 +     * ("Most recently" is reckoned relative to the {@code syncAll} itself.)
  26.180 +     * Conversely, the {@code syncAll} call may block until all readers have
  26.181 +     * (somehow) decached all previous versions of each call site's target.
  26.182 +     * <p>
  26.183 +     * To avoid race conditions, calls to {@code setTarget} and {@code syncAll}
  26.184 +     * should generally be performed under some sort of mutual exclusion.
  26.185 +     * Note that reader threads may observe an updated target as early
  26.186 +     * as the {@code setTarget} call that install the value
  26.187 +     * (and before the {@code syncAll} that confirms the value).
  26.188 +     * On the other hand, reader threads may observe previous versions of
  26.189 +     * the target until the {@code syncAll} call returns
  26.190 +     * (and after the {@code setTarget} that attempts to convey the updated version).
  26.191 +     * <p>
  26.192 +     * This operation is likely to be expensive and should be used sparingly.
  26.193 +     * If possible, it should be buffered for batch processing on sets of call sites.
  26.194 +     * <p>
  26.195 +     * If {@code sites} contains a null element,
  26.196 +     * a {@code NullPointerException} will be raised.
  26.197 +     * In this case, some non-null elements in the array may be
  26.198 +     * processed before the method returns abnormally.
  26.199 +     * Which elements these are (if any) is implementation-dependent.
  26.200 +     *
  26.201 +     * <h1>Java Memory Model details</h1>
  26.202 +     * In terms of the Java Memory Model, this operation performs a synchronization
  26.203 +     * action which is comparable in effect to the writing of a volatile variable
  26.204 +     * by the current thread, and an eventual volatile read by every other thread
  26.205 +     * that may access one of the affected call sites.
  26.206 +     * <p>
  26.207 +     * The following effects are apparent, for each individual call site {@code S}:
  26.208 +     * <ul>
  26.209 +     * <li>A new volatile variable {@code V} is created, and written by the current thread.
  26.210 +     *     As defined by the JMM, this write is a global synchronization event.
  26.211 +     * <li>As is normal with thread-local ordering of write events,
  26.212 +     *     every action already performed by the current thread is
  26.213 +     *     taken to happen before the volatile write to {@code V}.
  26.214 +     *     (In some implementations, this means that the current thread
  26.215 +     *     performs a global release operation.)
  26.216 +     * <li>Specifically, the write to the current target of {@code S} is
  26.217 +     *     taken to happen before the volatile write to {@code V}.
  26.218 +     * <li>The volatile write to {@code V} is placed
  26.219 +     *     (in an implementation specific manner)
  26.220 +     *     in the global synchronization order.
  26.221 +     * <li>Consider an arbitrary thread {@code T} (other than the current thread).
  26.222 +     *     If {@code T} executes a synchronization action {@code A}
  26.223 +     *     after the volatile write to {@code V} (in the global synchronization order),
  26.224 +     *     it is therefore required to see either the current target
  26.225 +     *     of {@code S}, or a later write to that target,
  26.226 +     *     if it executes a read on the target of {@code S}.
  26.227 +     *     (This constraint is called "synchronization-order consistency".)
  26.228 +     * <li>The JMM specifically allows optimizing compilers to elide
  26.229 +     *     reads or writes of variables that are known to be useless.
  26.230 +     *     Such elided reads and writes have no effect on the happens-before
  26.231 +     *     relation.  Regardless of this fact, the volatile {@code V}
  26.232 +     *     will not be elided, even though its written value is
  26.233 +     *     indeterminate and its read value is not used.
  26.234 +     * </ul>
  26.235 +     * Because of the last point, the implementation behaves as if a
  26.236 +     * volatile read of {@code V} were performed by {@code T}
  26.237 +     * immediately after its action {@code A}.  In the local ordering
  26.238 +     * of actions in {@code T}, this read happens before any future
  26.239 +     * read of the target of {@code S}.  It is as if the
  26.240 +     * implementation arbitrarily picked a read of {@code S}'s target
  26.241 +     * by {@code T}, and forced a read of {@code V} to precede it,
  26.242 +     * thereby ensuring communication of the new target value.
  26.243 +     * <p>
  26.244 +     * As long as the constraints of the Java Memory Model are obeyed,
  26.245 +     * implementations may delay the completion of a {@code syncAll}
  26.246 +     * operation while other threads ({@code T} above) continue to
  26.247 +     * use previous values of {@code S}'s target.
  26.248 +     * However, implementations are (as always) encouraged to avoid
  26.249 +     * livelock, and to eventually require all threads to take account
  26.250 +     * of the updated target.
  26.251 +     *
  26.252 +     * <p style="font-size:smaller;">
  26.253 +     * <em>Discussion:</em>
  26.254 +     * For performance reasons, {@code syncAll} is not a virtual method
  26.255 +     * on a single call site, but rather applies to a set of call sites.
  26.256 +     * Some implementations may incur a large fixed overhead cost
  26.257 +     * for processing one or more synchronization operations,
  26.258 +     * but a small incremental cost for each additional call site.
  26.259 +     * In any case, this operation is likely to be costly, since
  26.260 +     * other threads may have to be somehow interrupted
  26.261 +     * in order to make them notice the updated target value.
  26.262 +     * However, it may be observed that a single call to synchronize
  26.263 +     * several sites has the same formal effect as many calls,
  26.264 +     * each on just one of the sites.
  26.265 +     *
  26.266 +     * <p style="font-size:smaller;">
  26.267 +     * <em>Implementation Note:</em>
  26.268 +     * Simple implementations of {@code MutableCallSite} may use
  26.269 +     * a volatile variable for the target of a mutable call site.
  26.270 +     * In such an implementation, the {@code syncAll} method can be a no-op,
  26.271 +     * and yet it will conform to the JMM behavior documented above.
  26.272 +     *
  26.273 +     * @param sites an array of call sites to be synchronized
  26.274 +     * @throws NullPointerException if the {@code sites} array reference is null
  26.275 +     *                              or the array contains a null
  26.276 +     */
  26.277 +    public static void syncAll(MutableCallSite[] sites) {
  26.278 +        if (sites.length == 0)  return;
  26.279 +        STORE_BARRIER.lazySet(0);
  26.280 +        for (int i = 0; i < sites.length; i++) {
  26.281 +            sites[i].getClass();  // trigger NPE on first null
  26.282 +        }
  26.283 +        // FIXME: NYI
  26.284 +    }
  26.285 +    private static final AtomicInteger STORE_BARRIER = new AtomicInteger();
  26.286 +}
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/ProxyClassesDumper.java	Sat Aug 09 11:12:05 2014 +0200
    27.3 @@ -0,0 +1,147 @@
    27.4 +/*
    27.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    27.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    27.7 + *
    27.8 + * This code is free software; you can redistribute it and/or modify it
    27.9 + * under the terms of the GNU General Public License version 2 only, as
   27.10 + * published by the Free Software Foundation.  Oracle designates this
   27.11 + * particular file as subject to the "Classpath" exception as provided
   27.12 + * by Oracle in the LICENSE file that accompanied this code.
   27.13 + *
   27.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   27.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   27.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   27.17 + * version 2 for more details (a copy is included in the LICENSE file that
   27.18 + * accompanied this code).
   27.19 + *
   27.20 + * You should have received a copy of the GNU General Public License version
   27.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   27.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   27.23 + *
   27.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   27.25 + * or visit www.oracle.com if you need additional information or have any
   27.26 + * questions.
   27.27 + */
   27.28 +package java.lang.invoke;
   27.29 +
   27.30 +import sun.util.logging.PlatformLogger;
   27.31 +
   27.32 +import java.io.FilePermission;
   27.33 +import java.nio.file.Files;
   27.34 +import java.nio.file.InvalidPathException;
   27.35 +import java.nio.file.Path;
   27.36 +import java.nio.file.Paths;
   27.37 +import java.security.AccessController;
   27.38 +import java.security.PrivilegedAction;
   27.39 +import java.util.Objects;
   27.40 +import java.util.concurrent.atomic.AtomicBoolean;
   27.41 +
   27.42 +/**
   27.43 + * Helper class used by InnerClassLambdaMetafactory to log generated classes
   27.44 + *
   27.45 + * @implNote
   27.46 + * <p> Because this class is called by LambdaMetafactory, make use
   27.47 + * of lambda lead to recursive calls cause stack overflow.
   27.48 + */
   27.49 +final class ProxyClassesDumper {
   27.50 +    private static final char[] HEX = {
   27.51 +        '0', '1', '2', '3', '4', '5', '6', '7',
   27.52 +        '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
   27.53 +    };
   27.54 +    private static final char[] BAD_CHARS = {
   27.55 +        '\\', ':', '*', '?', '"', '<', '>', '|'
   27.56 +    };
   27.57 +    private static final String[] REPLACEMENT = {
   27.58 +        "%5C", "%3A", "%2A", "%3F", "%22", "%3C", "%3E", "%7C"
   27.59 +    };
   27.60 +
   27.61 +    private final Path dumpDir;
   27.62 +
   27.63 +    public static ProxyClassesDumper getInstance(String path) {
   27.64 +        if (null == path) {
   27.65 +            return null;
   27.66 +        }
   27.67 +        try {
   27.68 +            path = path.trim();
   27.69 +            final Path dir = Paths.get(path.length() == 0 ? "." : path);
   27.70 +            AccessController.doPrivileged(new PrivilegedAction<Void>() {
   27.71 +                    @Override
   27.72 +                    public Void run() {
   27.73 +                        validateDumpDir(dir);
   27.74 +                        return null;
   27.75 +                    }
   27.76 +                }, null, new FilePermission("<<ALL FILES>>", "read, write"));
   27.77 +            return new ProxyClassesDumper(dir);
   27.78 +        } catch (InvalidPathException ex) {
   27.79 +            PlatformLogger.getLogger(ProxyClassesDumper.class.getName())
   27.80 +                          .warning("Path " + path + " is not valid - dumping disabled", ex);
   27.81 +        } catch (IllegalArgumentException iae) {
   27.82 +            PlatformLogger.getLogger(ProxyClassesDumper.class.getName())
   27.83 +                          .warning(iae.getMessage() + " - dumping disabled");
   27.84 +        }
   27.85 +        return null;
   27.86 +    }
   27.87 +
   27.88 +    private ProxyClassesDumper(Path path) {
   27.89 +        dumpDir = Objects.requireNonNull(path);
   27.90 +    }
   27.91 +
   27.92 +    private static void validateDumpDir(Path path) {
   27.93 +        if (!Files.exists(path)) {
   27.94 +            throw new IllegalArgumentException("Directory " + path + " does not exist");
   27.95 +        } else if (!Files.isDirectory(path)) {
   27.96 +            throw new IllegalArgumentException("Path " + path + " is not a directory");
   27.97 +        } else if (!Files.isWritable(path)) {
   27.98 +            throw new IllegalArgumentException("Directory " + path + " is not writable");
   27.99 +        }
  27.100 +    }
  27.101 +
  27.102 +    public static String encodeForFilename(String className) {
  27.103 +        final int len = className.length();
  27.104 +        StringBuilder sb = new StringBuilder(len);
  27.105 +
  27.106 +        for (int i = 0; i < len; i++) {
  27.107 +            char c = className.charAt(i);
  27.108 +            // control characters
  27.109 +            if (c <= 31) {
  27.110 +                sb.append('%');
  27.111 +                sb.append(HEX[c >> 4 & 0x0F]);
  27.112 +                sb.append(HEX[c & 0x0F]);
  27.113 +            } else {
  27.114 +                int j = 0;
  27.115 +                for (; j < BAD_CHARS.length; j++) {
  27.116 +                    if (c == BAD_CHARS[j]) {
  27.117 +                        sb.append(REPLACEMENT[j]);
  27.118 +                        break;
  27.119 +                    }
  27.120 +                }
  27.121 +                if (j >= BAD_CHARS.length) {
  27.122 +                    sb.append(c);
  27.123 +                }
  27.124 +            }
  27.125 +        }
  27.126 +
  27.127 +        return sb.toString();
  27.128 +    }
  27.129 +
  27.130 +    public void dumpClass(String className, final byte[] classBytes) {
  27.131 +        Path file;
  27.132 +        try {
  27.133 +            file = dumpDir.resolve(encodeForFilename(className) + ".class");
  27.134 +        } catch (InvalidPathException ex) {
  27.135 +            PlatformLogger.getLogger(ProxyClassesDumper.class.getName())
  27.136 +                          .warning("Invalid path for class " + className);
  27.137 +            return;
  27.138 +        }
  27.139 +
  27.140 +        try {
  27.141 +            Path dir = file.getParent();
  27.142 +            Files.createDirectories(dir);
  27.143 +            Files.write(file, classBytes);
  27.144 +        } catch (Exception ignore) {
  27.145 +            PlatformLogger.getLogger(ProxyClassesDumper.class.getName())
  27.146 +                          .warning("Exception writing to path at " + file.toString());
  27.147 +            // simply don't care if this operation failed
  27.148 +        }
  27.149 +    }
  27.150 +}
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/SerializedLambda.java	Sat Aug 09 11:12:05 2014 +0200
    28.3 @@ -0,0 +1,258 @@
    28.4 +/*
    28.5 + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
    28.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    28.7 + *
    28.8 + * This code is free software; you can redistribute it and/or modify it
    28.9 + * under the terms of the GNU General Public License version 2 only, as
   28.10 + * published by the Free Software Foundation.  Oracle designates this
   28.11 + * particular file as subject to the "Classpath" exception as provided
   28.12 + * by Oracle in the LICENSE file that accompanied this code.
   28.13 + *
   28.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   28.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   28.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   28.17 + * version 2 for more details (a copy is included in the LICENSE file that
   28.18 + * accompanied this code).
   28.19 + *
   28.20 + * You should have received a copy of the GNU General Public License version
   28.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   28.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   28.23 + *
   28.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   28.25 + * or visit www.oracle.com if you need additional information or have any
   28.26 + * questions.
   28.27 + */
   28.28 +package java.lang.invoke;
   28.29 +
   28.30 +import java.io.Serializable;
   28.31 +import java.lang.reflect.Method;
   28.32 +import java.security.AccessController;
   28.33 +import java.security.PrivilegedActionException;
   28.34 +import java.security.PrivilegedExceptionAction;
   28.35 +import java.util.Objects;
   28.36 +
   28.37 +/**
   28.38 + * Serialized form of a lambda expression.  The properties of this class
   28.39 + * represent the information that is present at the lambda factory site, including
   28.40 + * static metafactory arguments such as the identity of the primary functional
   28.41 + * interface method and the identity of the implementation method, as well as
   28.42 + * dynamic metafactory arguments such as values captured from the lexical scope
   28.43 + * at the time of lambda capture.
   28.44 + *
   28.45 + * <p>Implementors of serializable lambdas, such as compilers or language
   28.46 + * runtime libraries, are expected to ensure that instances deserialize properly.
   28.47 + * One means to do so is to ensure that the {@code writeReplace} method returns
   28.48 + * an instance of {@code SerializedLambda}, rather than allowing default
   28.49 + * serialization to proceed.
   28.50 + *
   28.51 + * <p>{@code SerializedLambda} has a {@code readResolve} method that looks for
   28.52 + * a (possibly private) static method called
   28.53 + * {@code $deserializeLambda$(SerializedLambda)} in the capturing class, invokes
   28.54 + * that with itself as the first argument, and returns the result.  Lambda classes
   28.55 + * implementing {@code $deserializeLambda$} are responsible for validating
   28.56 + * that the properties of the {@code SerializedLambda} are consistent with a
   28.57 + * lambda actually captured by that class.
   28.58 + *
   28.59 + * @see LambdaMetafactory
   28.60 + */
   28.61 +public final class SerializedLambda implements Serializable {
   28.62 +    private static final long serialVersionUID = 8025925345765570181L;
   28.63 +    private final Class<?> capturingClass;
   28.64 +    private final String functionalInterfaceClass;
   28.65 +    private final String functionalInterfaceMethodName;
   28.66 +    private final String functionalInterfaceMethodSignature;
   28.67 +    private final String implClass;
   28.68 +    private final String implMethodName;
   28.69 +    private final String implMethodSignature;
   28.70 +    private final int implMethodKind;
   28.71 +    private final String instantiatedMethodType;
   28.72 +    private final Object[] capturedArgs;
   28.73 +
   28.74 +    /**
   28.75 +     * Create a {@code SerializedLambda} from the low-level information present
   28.76 +     * at the lambda factory site.
   28.77 +     *
   28.78 +     * @param capturingClass The class in which the lambda expression appears
   28.79 +     * @param functionalInterfaceClass Name, in slash-delimited form, of static
   28.80 +     *                                 type of the returned lambda object
   28.81 +     * @param functionalInterfaceMethodName Name of the functional interface
   28.82 +     *                                      method for the present at the
   28.83 +     *                                      lambda factory site
   28.84 +     * @param functionalInterfaceMethodSignature Signature of the functional
   28.85 +     *                                           interface method present at
   28.86 +     *                                           the lambda factory site
   28.87 +     * @param implMethodKind Method handle kind for the implementation method
   28.88 +     * @param implClass Name, in slash-delimited form, for the class holding
   28.89 +     *                  the implementation method
   28.90 +     * @param implMethodName Name of the implementation method
   28.91 +     * @param implMethodSignature Signature of the implementation method
   28.92 +     * @param instantiatedMethodType The signature of the primary functional
   28.93 +     *                               interface method after type variables
   28.94 +     *                               are substituted with their instantiation
   28.95 +     *                               from the capture site
   28.96 +     * @param capturedArgs The dynamic arguments to the lambda factory site,
   28.97 +     *                     which represent variables captured by
   28.98 +     *                     the lambda
   28.99 +     */
  28.100 +    public SerializedLambda(Class<?> capturingClass,
  28.101 +                            String functionalInterfaceClass,
  28.102 +                            String functionalInterfaceMethodName,
  28.103 +                            String functionalInterfaceMethodSignature,
  28.104 +                            int implMethodKind,
  28.105 +                            String implClass,
  28.106 +                            String implMethodName,
  28.107 +                            String implMethodSignature,
  28.108 +                            String instantiatedMethodType,
  28.109 +                            Object[] capturedArgs) {
  28.110 +        this.capturingClass = capturingClass;
  28.111 +        this.functionalInterfaceClass = functionalInterfaceClass;
  28.112 +        this.functionalInterfaceMethodName = functionalInterfaceMethodName;
  28.113 +        this.functionalInterfaceMethodSignature = functionalInterfaceMethodSignature;
  28.114 +        this.implMethodKind = implMethodKind;
  28.115 +        this.implClass = implClass;
  28.116 +        this.implMethodName = implMethodName;
  28.117 +        this.implMethodSignature = implMethodSignature;
  28.118 +        this.instantiatedMethodType = instantiatedMethodType;
  28.119 +        this.capturedArgs = Objects.requireNonNull(capturedArgs).clone();
  28.120 +    }
  28.121 +
  28.122 +    /**
  28.123 +     * Get the name of the class that captured this lambda.
  28.124 +     * @return the name of the class that captured this lambda
  28.125 +     */
  28.126 +    public String getCapturingClass() {
  28.127 +        return capturingClass.getName().replace('.', '/');
  28.128 +    }
  28.129 +
  28.130 +    /**
  28.131 +     * Get the name of the invoked type to which this
  28.132 +     * lambda has been converted
  28.133 +     * @return the name of the functional interface class to which
  28.134 +     * this lambda has been converted
  28.135 +     */
  28.136 +    public String getFunctionalInterfaceClass() {
  28.137 +        return functionalInterfaceClass;
  28.138 +    }
  28.139 +
  28.140 +    /**
  28.141 +     * Get the name of the primary method for the functional interface
  28.142 +     * to which this lambda has been converted.
  28.143 +     * @return the name of the primary methods of the functional interface
  28.144 +     */
  28.145 +    public String getFunctionalInterfaceMethodName() {
  28.146 +        return functionalInterfaceMethodName;
  28.147 +    }
  28.148 +
  28.149 +    /**
  28.150 +     * Get the signature of the primary method for the functional
  28.151 +     * interface to which this lambda has been converted.
  28.152 +     * @return the signature of the primary method of the functional
  28.153 +     * interface
  28.154 +     */
  28.155 +    public String getFunctionalInterfaceMethodSignature() {
  28.156 +        return functionalInterfaceMethodSignature;
  28.157 +    }
  28.158 +
  28.159 +    /**
  28.160 +     * Get the name of the class containing the implementation
  28.161 +     * method.
  28.162 +     * @return the name of the class containing the implementation
  28.163 +     * method
  28.164 +     */
  28.165 +    public String getImplClass() {
  28.166 +        return implClass;
  28.167 +    }
  28.168 +
  28.169 +    /**
  28.170 +     * Get the name of the implementation method.
  28.171 +     * @return the name of the implementation method
  28.172 +     */
  28.173 +    public String getImplMethodName() {
  28.174 +        return implMethodName;
  28.175 +    }
  28.176 +
  28.177 +    /**
  28.178 +     * Get the signature of the implementation method.
  28.179 +     * @return the signature of the implementation method
  28.180 +     */
  28.181 +    public String getImplMethodSignature() {
  28.182 +        return implMethodSignature;
  28.183 +    }
  28.184 +
  28.185 +    /**
  28.186 +     * Get the method handle kind (see {@link MethodHandleInfo}) of
  28.187 +     * the implementation method.
  28.188 +     * @return the method handle kind of the implementation method
  28.189 +     */
  28.190 +    public int getImplMethodKind() {
  28.191 +        return implMethodKind;
  28.192 +    }
  28.193 +
  28.194 +    /**
  28.195 +     * Get the signature of the primary functional interface method
  28.196 +     * after type variables are substituted with their instantiation
  28.197 +     * from the capture site.
  28.198 +     * @return the signature of the primary functional interface method
  28.199 +     * after type variable processing
  28.200 +     */
  28.201 +    public final String getInstantiatedMethodType() {
  28.202 +        return instantiatedMethodType;
  28.203 +    }
  28.204 +
  28.205 +    /**
  28.206 +     * Get the count of dynamic arguments to the lambda capture site.
  28.207 +     * @return the count of dynamic arguments to the lambda capture site
  28.208 +     */
  28.209 +    public int getCapturedArgCount() {
  28.210 +        return capturedArgs.length;
  28.211 +    }
  28.212 +
  28.213 +    /**
  28.214 +     * Get a dynamic argument to the lambda capture site.
  28.215 +     * @param i the argument to capture
  28.216 +     * @return a dynamic argument to the lambda capture site
  28.217 +     */
  28.218 +    public Object getCapturedArg(int i) {
  28.219 +        return capturedArgs[i];
  28.220 +    }
  28.221 +
  28.222 +    private Object readResolve() throws ReflectiveOperationException {
  28.223 +        try {
  28.224 +            Method deserialize = AccessController.doPrivileged(new PrivilegedExceptionAction<Method>() {
  28.225 +                @Override
  28.226 +                public Method run() throws Exception {
  28.227 +                    Method m = capturingClass.getDeclaredMethod("$deserializeLambda$", SerializedLambda.class);
  28.228 +                    m.setAccessible(true);
  28.229 +                    return m;
  28.230 +                }
  28.231 +            });
  28.232 +
  28.233 +            return deserialize.invoke(null, this);
  28.234 +        }
  28.235 +        catch (PrivilegedActionException e) {
  28.236 +            Exception cause = e.getException();
  28.237 +            if (cause instanceof ReflectiveOperationException)
  28.238 +                throw (ReflectiveOperationException) cause;
  28.239 +            else if (cause instanceof RuntimeException)
  28.240 +                throw (RuntimeException) cause;
  28.241 +            else
  28.242 +                throw new RuntimeException("Exception in SerializedLambda.readResolve", e);
  28.243 +        }
  28.244 +    }
  28.245 +
  28.246 +    @Override
  28.247 +    public String toString() {
  28.248 +        String implKind=MethodHandleInfo.referenceKindToString(implMethodKind);
  28.249 +        return String.format("SerializedLambda[%s=%s, %s=%s.%s:%s, " +
  28.250 +                             "%s=%s %s.%s:%s, %s=%s, %s=%d]",
  28.251 +                             "capturingClass", capturingClass,
  28.252 +                             "functionalInterfaceMethod", functionalInterfaceClass,
  28.253 +                               functionalInterfaceMethodName,
  28.254 +                               functionalInterfaceMethodSignature,
  28.255 +                             "implementation",
  28.256 +                               implKind,
  28.257 +                               implClass, implMethodName, implMethodSignature,
  28.258 +                             "instantiatedMethodType", instantiatedMethodType,
  28.259 +                             "numCaptured", capturedArgs.length);
  28.260 +    }
  28.261 +}
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/SimpleMethodHandle.java	Sat Aug 09 11:12:05 2014 +0200
    29.3 @@ -0,0 +1,70 @@
    29.4 +/*
    29.5 + * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
    29.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    29.7 + *
    29.8 + * This code is free software; you can redistribute it and/or modify it
    29.9 + * under the terms of the GNU General Public License version 2 only, as
   29.10 + * published by the Free Software Foundation.  Oracle designates this
   29.11 + * particular file as subject to the "Classpath" exception as provided
   29.12 + * by Oracle in the LICENSE file that accompanied this code.
   29.13 + *
   29.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   29.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   29.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   29.17 + * version 2 for more details (a copy is included in the LICENSE file that
   29.18 + * accompanied this code).
   29.19 + *
   29.20 + * You should have received a copy of the GNU General Public License version
   29.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   29.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   29.23 + *
   29.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   29.25 + * or visit www.oracle.com if you need additional information or have any
   29.26 + * questions.
   29.27 + */
   29.28 +
   29.29 +package java.lang.invoke;
   29.30 +
   29.31 +import static java.lang.invoke.LambdaForm.*;
   29.32 +import static java.lang.invoke.MethodHandleNatives.Constants.*;
   29.33 +import java.util.logging.Level;
   29.34 +import java.util.logging.Logger;
   29.35 +
   29.36 +/**
   29.37 + * A method handle whose behavior is determined only by its LambdaForm.
   29.38 + * @author jrose
   29.39 + */
   29.40 +final class SimpleMethodHandle extends MethodHandle {
   29.41 +    private SimpleMethodHandle(MethodType type, LambdaForm form) {
   29.42 +        super(type, form);
   29.43 +    }
   29.44 +
   29.45 +    /*non-public*/ static SimpleMethodHandle make(MethodType type, LambdaForm form) {
   29.46 +        return new SimpleMethodHandle(type, form);
   29.47 +    }
   29.48 +
   29.49 +    @Override
   29.50 +    MethodHandle bindArgument(int pos, char basicType, Object value) {
   29.51 +        MethodType type2 = type().dropParameterTypes(pos, pos+1);
   29.52 +        LambdaForm form2 = internalForm().bind(1+pos, BoundMethodHandle.SpeciesData.EMPTY);
   29.53 +        return BoundMethodHandle.bindSingle(type2, form2, basicType, value);
   29.54 +    }
   29.55 +
   29.56 +    @Override
   29.57 +    MethodHandle dropArguments(MethodType srcType, int pos, int drops) {
   29.58 +        LambdaForm newForm = internalForm().addArguments(pos, srcType.parameterList().subList(pos, pos+drops));
   29.59 +        return new SimpleMethodHandle(srcType, newForm);
   29.60 +    }
   29.61 +
   29.62 +    @Override
   29.63 +    MethodHandle permuteArguments(MethodType newType, int[] reorder) {
   29.64 +        LambdaForm form2 = internalForm().permuteArguments(1, reorder, basicTypes(newType.parameterList()));
   29.65 +        return new SimpleMethodHandle(newType, form2);
   29.66 +    }
   29.67 +
   29.68 +    @Override
   29.69 +    MethodHandle copyWith(MethodType mt, LambdaForm lf) {
   29.70 +        return new SimpleMethodHandle(mt, lf);
   29.71 +    }
   29.72 +
   29.73 +}
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/Stable.java	Sat Aug 09 11:12:05 2014 +0200
    30.3 @@ -0,0 +1,73 @@
    30.4 +/*
    30.5 + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
    30.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    30.7 + *
    30.8 + * This code is free software; you can redistribute it and/or modify it
    30.9 + * under the terms of the GNU General Public License version 2 only, as
   30.10 + * published by the Free Software Foundation.  Oracle designates this
   30.11 + * particular file as subject to the "Classpath" exception as provided
   30.12 + * by Oracle in the LICENSE file that accompanied this code.
   30.13 + *
   30.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   30.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   30.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   30.17 + * version 2 for more details (a copy is included in the LICENSE file that
   30.18 + * accompanied this code).
   30.19 + *
   30.20 + * You should have received a copy of the GNU General Public License version
   30.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   30.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   30.23 + *
   30.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   30.25 + * or visit www.oracle.com if you need additional information or have any
   30.26 + * questions.
   30.27 + */
   30.28 +
   30.29 +package java.lang.invoke;
   30.30 +
   30.31 +import java.lang.annotation.*;
   30.32 +
   30.33 +/**
   30.34 + * A field may be annotated as stable if all of its component variables
   30.35 + * changes value at most once.
   30.36 + * A field's value counts as its component value.
   30.37 + * If the field is typed as an array, then all the non-null components
   30.38 + * of the array, of depth up to the rank of the field's array type,
   30.39 + * also count as component values.
   30.40 + * By extension, any variable (either array or field) which has annotated
   30.41 + * as stable is called a stable variable, and its non-null or non-zero
   30.42 + * value is called a stable value.
   30.43 + * <p>
   30.44 + * Since all fields begin with a default value of null for references
   30.45 + * (resp., zero for primitives), it follows that this annotation indicates
   30.46 + * that the first non-null (resp., non-zero) value stored in the field
   30.47 + * will never be changed.
   30.48 + * <p>
   30.49 + * If the field is not of an array type, there are no array elements,
   30.50 + * then the value indicated as stable is simply the value of the field.
   30.51 + * If the dynamic type of the field value is an array but the static type
   30.52 + * is not, the components of the array are <em>not</em> regarded as stable.
   30.53 + * <p>
   30.54 + * If the field is an array type, then both the field value and
   30.55 + * all the components of the field value (if the field value is non-null)
   30.56 + * are indicated to be stable.
   30.57 + * If the field type is an array type with rank {@code N &gt; 1},
   30.58 + * then each component of the field value (if the field value is non-null),
   30.59 + * is regarded as a stable array of rank {@code N-1}.
   30.60 + * <p>
   30.61 + * Fields which are declared {@code final} may also be annotated as stable.
   30.62 + * Since final fields already behave as stable values, such an annotation
   30.63 + * indicates no additional information, unless the type of the field is
   30.64 + * an array type.
   30.65 + * <p>
   30.66 + * It is (currently) undefined what happens if a field annotated as stable
   30.67 + * is given a third value.  In practice, if the JVM relies on this annotation
   30.68 + * to promote a field reference to a constant, it may be that the Java memory
   30.69 + * model would appear to be broken, if such a constant (the second value of the field)
   30.70 + * is used as the value of the field even after the field value has changed.
   30.71 + */
   30.72 +/* package-private */
   30.73 +@Target(ElementType.FIELD)
   30.74 +@Retention(RetentionPolicy.RUNTIME)
   30.75 +@interface Stable {
   30.76 +}
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/SwitchPoint.java	Sat Aug 09 11:12:05 2014 +0200
    31.3 @@ -0,0 +1,228 @@
    31.4 +/*
    31.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
    31.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    31.7 + *
    31.8 + * This code is free software; you can redistribute it and/or modify it
    31.9 + * under the terms of the GNU General Public License version 2 only, as
   31.10 + * published by the Free Software Foundation.  Oracle designates this
   31.11 + * particular file as subject to the "Classpath" exception as provided
   31.12 + * by Oracle in the LICENSE file that accompanied this code.
   31.13 + *
   31.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   31.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   31.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   31.17 + * version 2 for more details (a copy is included in the LICENSE file that
   31.18 + * accompanied this code).
   31.19 + *
   31.20 + * You should have received a copy of the GNU General Public License version
   31.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   31.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   31.23 + *
   31.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   31.25 + * or visit www.oracle.com if you need additional information or have any
   31.26 + * questions.
   31.27 + */
   31.28 +
   31.29 +package java.lang.invoke;
   31.30 +
   31.31 +/**
   31.32 + * <p>
   31.33 + * A {@code SwitchPoint} is an object which can publish state transitions to other threads.
   31.34 + * A switch point is initially in the <em>valid</em> state, but may at any time be
   31.35 + * changed to the <em>invalid</em> state.  Invalidation cannot be reversed.
   31.36 + * A switch point can combine a <em>guarded pair</em> of method handles into a
   31.37 + * <em>guarded delegator</em>.
   31.38 + * The guarded delegator is a method handle which delegates to one of the old method handles.
   31.39 + * The state of the switch point determines which of the two gets the delegation.
   31.40 + * <p>
   31.41 + * A single switch point may be used to control any number of method handles.
   31.42 + * (Indirectly, therefore, it can control any number of call sites.)
   31.43 + * This is done by using the single switch point as a factory for combining
   31.44 + * any number of guarded method handle pairs into guarded delegators.
   31.45 + * <p>
   31.46 + * When a guarded delegator is created from a guarded pair, the pair
   31.47 + * is wrapped in a new method handle {@code M},
   31.48 + * which is permanently associated with the switch point that created it.
   31.49 + * Each pair consists of a target {@code T} and a fallback {@code F}.
   31.50 + * While the switch point is valid, invocations to {@code M} are delegated to {@code T}.
   31.51 + * After it is invalidated, invocations are delegated to {@code F}.
   31.52 + * <p>
   31.53 + * Invalidation is global and immediate, as if the switch point contained a
   31.54 + * volatile boolean variable consulted on every call to {@code M}.
   31.55 + * The invalidation is also permanent, which means the switch point
   31.56 + * can change state only once.
   31.57 + * The switch point will always delegate to {@code F} after being invalidated.
   31.58 + * At that point {@code guardWithTest} may ignore {@code T} and return {@code F}.
   31.59 + * <p>
   31.60 + * Here is an example of a switch point in action:
   31.61 + * <blockquote><pre>{@code
   31.62 +MethodHandle MH_strcat = MethodHandles.lookup()
   31.63 +    .findVirtual(String.class, "concat", MethodType.methodType(String.class, String.class));
   31.64 +SwitchPoint spt = new SwitchPoint();
   31.65 +assert(!spt.hasBeenInvalidated());
   31.66 +// the following steps may be repeated to re-use the same switch point:
   31.67 +MethodHandle worker1 = MH_strcat;
   31.68 +MethodHandle worker2 = MethodHandles.permuteArguments(MH_strcat, MH_strcat.type(), 1, 0);
   31.69 +MethodHandle worker = spt.guardWithTest(worker1, worker2);
   31.70 +assertEquals("method", (String) worker.invokeExact("met", "hod"));
   31.71 +SwitchPoint.invalidateAll(new SwitchPoint[]{ spt });
   31.72 +assert(spt.hasBeenInvalidated());
   31.73 +assertEquals("hodmet", (String) worker.invokeExact("met", "hod"));
   31.74 + * }</pre></blockquote>
   31.75 + * <p style="font-size:smaller;">
   31.76 + * <em>Discussion:</em>
   31.77 + * Switch points are useful without subclassing.  They may also be subclassed.
   31.78 + * This may be useful in order to associate application-specific invalidation logic
   31.79 + * with the switch point.
   31.80 + * Notice that there is no permanent association between a switch point and
   31.81 + * the method handles it produces and consumes.
   31.82 + * The garbage collector may collect method handles produced or consumed
   31.83 + * by a switch point independently of the lifetime of the switch point itself.
   31.84 + * <p style="font-size:smaller;">
   31.85 + * <em>Implementation Note:</em>
   31.86 + * A switch point behaves as if implemented on top of {@link MutableCallSite},
   31.87 + * approximately as follows:
   31.88 + * <blockquote><pre>{@code
   31.89 +public class SwitchPoint {
   31.90 +  private static final MethodHandle
   31.91 +    K_true  = MethodHandles.constant(boolean.class, true),
   31.92 +    K_false = MethodHandles.constant(boolean.class, false);
   31.93 +  private final MutableCallSite mcs;
   31.94 +  private final MethodHandle mcsInvoker;
   31.95 +  public SwitchPoint() {
   31.96 +    this.mcs = new MutableCallSite(K_true);
   31.97 +    this.mcsInvoker = mcs.dynamicInvoker();
   31.98 +  }
   31.99 +  public MethodHandle guardWithTest(
  31.100 +                MethodHandle target, MethodHandle fallback) {
  31.101 +    // Note:  mcsInvoker is of type ()boolean.
  31.102 +    // Target and fallback may take any arguments, but must have the same type.
  31.103 +    return MethodHandles.guardWithTest(this.mcsInvoker, target, fallback);
  31.104 +  }
  31.105 +  public static void invalidateAll(SwitchPoint[] spts) {
  31.106 +    List&lt;MutableCallSite&gt; mcss = new ArrayList&lt;&gt;();
  31.107 +    for (SwitchPoint spt : spts)  mcss.add(spt.mcs);
  31.108 +    for (MutableCallSite mcs : mcss)  mcs.setTarget(K_false);
  31.109 +    MutableCallSite.syncAll(mcss.toArray(new MutableCallSite[0]));
  31.110 +  }
  31.111 +}
  31.112 + * }</pre></blockquote>
  31.113 + * @author Remi Forax, JSR 292 EG
  31.114 + */
  31.115 +public class SwitchPoint {
  31.116 +    private static final MethodHandle
  31.117 +        K_true  = MethodHandles.constant(boolean.class, true),
  31.118 +        K_false = MethodHandles.constant(boolean.class, false);
  31.119 +
  31.120 +    private final MutableCallSite mcs;
  31.121 +    private final MethodHandle mcsInvoker;
  31.122 +
  31.123 +    /**
  31.124 +     * Creates a new switch point.
  31.125 +     */
  31.126 +    public SwitchPoint() {
  31.127 +        this.mcs = new MutableCallSite(K_true);
  31.128 +        this.mcsInvoker = mcs.dynamicInvoker();
  31.129 +    }
  31.130 +
  31.131 +    /**
  31.132 +     * Determines if this switch point has been invalidated yet.
  31.133 +     *
  31.134 +     * <p style="font-size:smaller;">
  31.135 +     * <em>Discussion:</em>
  31.136 +     * Because of the one-way nature of invalidation, once a switch point begins
  31.137 +     * to return true for {@code hasBeenInvalidated},
  31.138 +     * it will always do so in the future.
  31.139 +     * On the other hand, a valid switch point visible to other threads may
  31.140 +     * be invalidated at any moment, due to a request by another thread.
  31.141 +     * <p style="font-size:smaller;">
  31.142 +     * Since invalidation is a global and immediate operation,
  31.143 +     * the execution of this query, on a valid switchpoint,
  31.144 +     * must be internally sequenced with any
  31.145 +     * other threads that could cause invalidation.
  31.146 +     * This query may therefore be expensive.
  31.147 +     * The recommended way to build a boolean-valued method handle
  31.148 +     * which queries the invalidation state of a switch point {@code s} is
  31.149 +     * to call {@code s.guardWithTest} on
  31.150 +     * {@link MethodHandles#constant constant} true and false method handles.
  31.151 +     *
  31.152 +     * @return true if this switch point has been invalidated
  31.153 +     */
  31.154 +    public boolean hasBeenInvalidated() {
  31.155 +        return (mcs.getTarget() != K_true);
  31.156 +    }
  31.157 +
  31.158 +    /**
  31.159 +     * Returns a method handle which always delegates either to the target or the fallback.
  31.160 +     * The method handle will delegate to the target exactly as long as the switch point is valid.
  31.161 +     * After that, it will permanently delegate to the fallback.
  31.162 +     * <p>
  31.163 +     * The target and fallback must be of exactly the same method type,
  31.164 +     * and the resulting combined method handle will also be of this type.
  31.165 +     *
  31.166 +     * @param target the method handle selected by the switch point as long as it is valid
  31.167 +     * @param fallback the method handle selected by the switch point after it is invalidated
  31.168 +     * @return a combined method handle which always calls either the target or fallback
  31.169 +     * @throws NullPointerException if either argument is null
  31.170 +     * @throws IllegalArgumentException if the two method types do not match
  31.171 +     * @see MethodHandles#guardWithTest
  31.172 +     */
  31.173 +    public MethodHandle guardWithTest(MethodHandle target, MethodHandle fallback) {
  31.174 +        if (mcs.getTarget() == K_false)
  31.175 +            return fallback;  // already invalid
  31.176 +        return MethodHandles.guardWithTest(mcsInvoker, target, fallback);
  31.177 +    }
  31.178 +
  31.179 +    /**
  31.180 +     * Sets all of the given switch points into the invalid state.
  31.181 +     * After this call executes, no thread will observe any of the
  31.182 +     * switch points to be in a valid state.
  31.183 +     * <p>
  31.184 +     * This operation is likely to be expensive and should be used sparingly.
  31.185 +     * If possible, it should be buffered for batch processing on sets of switch points.
  31.186 +     * <p>
  31.187 +     * If {@code switchPoints} contains a null element,
  31.188 +     * a {@code NullPointerException} will be raised.
  31.189 +     * In this case, some non-null elements in the array may be
  31.190 +     * processed before the method returns abnormally.
  31.191 +     * Which elements these are (if any) is implementation-dependent.
  31.192 +     *
  31.193 +     * <p style="font-size:smaller;">
  31.194 +     * <em>Discussion:</em>
  31.195 +     * For performance reasons, {@code invalidateAll} is not a virtual method
  31.196 +     * on a single switch point, but rather applies to a set of switch points.
  31.197 +     * Some implementations may incur a large fixed overhead cost
  31.198 +     * for processing one or more invalidation operations,
  31.199 +     * but a small incremental cost for each additional invalidation.
  31.200 +     * In any case, this operation is likely to be costly, since
  31.201 +     * other threads may have to be somehow interrupted
  31.202 +     * in order to make them notice the updated switch point state.
  31.203 +     * However, it may be observed that a single call to invalidate
  31.204 +     * several switch points has the same formal effect as many calls,
  31.205 +     * each on just one of the switch points.
  31.206 +     *
  31.207 +     * <p style="font-size:smaller;">
  31.208 +     * <em>Implementation Note:</em>
  31.209 +     * Simple implementations of {@code SwitchPoint} may use
  31.210 +     * a private {@link MutableCallSite} to publish the state of a switch point.
  31.211 +     * In such an implementation, the {@code invalidateAll} method can
  31.212 +     * simply change the call site's target, and issue one call to
  31.213 +     * {@linkplain MutableCallSite#syncAll synchronize} all the
  31.214 +     * private call sites.
  31.215 +     *
  31.216 +     * @param switchPoints an array of call sites to be synchronized
  31.217 +     * @throws NullPointerException if the {@code switchPoints} array reference is null
  31.218 +     *                              or the array contains a null
  31.219 +     */
  31.220 +    public static void invalidateAll(SwitchPoint[] switchPoints) {
  31.221 +        if (switchPoints.length == 0)  return;
  31.222 +        MutableCallSite[] sites = new MutableCallSite[switchPoints.length];
  31.223 +        for (int i = 0; i < switchPoints.length; i++) {
  31.224 +            SwitchPoint spt = switchPoints[i];
  31.225 +            if (spt == null)  break;  // MSC.syncAll will trigger a NPE
  31.226 +            sites[i] = spt.mcs;
  31.227 +            spt.mcs.setTarget(K_false);
  31.228 +        }
  31.229 +        MutableCallSite.syncAll(sites);
  31.230 +    }
  31.231 +}
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/TypeConvertingMethodAdapter.java	Sat Aug 09 11:12:05 2014 +0200
    32.3 @@ -0,0 +1,302 @@
    32.4 +/*
    32.5 + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
    32.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    32.7 + *
    32.8 + * This code is free software; you can redistribute it and/or modify it
    32.9 + * under the terms of the GNU General Public License version 2 only, as
   32.10 + * published by the Free Software Foundation.  Oracle designates this
   32.11 + * particular file as subject to the "Classpath" exception as provided
   32.12 + * by Oracle in the LICENSE file that accompanied this code.
   32.13 + *
   32.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   32.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   32.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   32.17 + * version 2 for more details (a copy is included in the LICENSE file that
   32.18 + * accompanied this code).
   32.19 + *
   32.20 + * You should have received a copy of the GNU General Public License version
   32.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   32.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   32.23 + *
   32.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   32.25 + * or visit www.oracle.com if you need additional information or have any
   32.26 + * questions.
   32.27 + */
   32.28 +
   32.29 +package java.lang.invoke;
   32.30 +
   32.31 +import jdk.internal.org.objectweb.asm.MethodVisitor;
   32.32 +import jdk.internal.org.objectweb.asm.Opcodes;
   32.33 +import jdk.internal.org.objectweb.asm.Type;
   32.34 +import sun.invoke.util.BytecodeDescriptor;
   32.35 +import sun.invoke.util.Wrapper;
   32.36 +import static sun.invoke.util.Wrapper.*;
   32.37 +
   32.38 +class TypeConvertingMethodAdapter extends MethodVisitor {
   32.39 +
   32.40 +    TypeConvertingMethodAdapter(MethodVisitor mv) {
   32.41 +        super(Opcodes.ASM5, mv);
   32.42 +    }
   32.43 +
   32.44 +    private static final int NUM_WRAPPERS = Wrapper.values().length;
   32.45 +
   32.46 +    private static final String NAME_OBJECT = "java/lang/Object";
   32.47 +    private static final String WRAPPER_PREFIX = "Ljava/lang/";
   32.48 +
   32.49 +    // Same for all primitives; name of the boxing method
   32.50 +    private static final String NAME_BOX_METHOD = "valueOf";
   32.51 +
   32.52 +    // Table of opcodes for widening primitive conversions; NOP = no conversion
   32.53 +    private static final int[][] wideningOpcodes = new int[NUM_WRAPPERS][NUM_WRAPPERS];
   32.54 +
   32.55 +    private static final Wrapper[] FROM_WRAPPER_NAME = new Wrapper[16];
   32.56 +
   32.57 +    // Table of wrappers for primitives, indexed by ASM type sorts
   32.58 +    private static final Wrapper[] FROM_TYPE_SORT = new Wrapper[16];
   32.59 +
   32.60 +    static {
   32.61 +        for (Wrapper w : Wrapper.values()) {
   32.62 +            if (w.basicTypeChar() != 'L') {
   32.63 +                int wi = hashWrapperName(w.wrapperSimpleName());
   32.64 +                assert (FROM_WRAPPER_NAME[wi] == null);
   32.65 +                FROM_WRAPPER_NAME[wi] = w;
   32.66 +            }
   32.67 +        }
   32.68 +
   32.69 +        for (int i = 0; i < NUM_WRAPPERS; i++) {
   32.70 +            for (int j = 0; j < NUM_WRAPPERS; j++) {
   32.71 +                wideningOpcodes[i][j] = Opcodes.NOP;
   32.72 +            }
   32.73 +        }
   32.74 +
   32.75 +        initWidening(LONG,   Opcodes.I2L, BYTE, SHORT, INT, CHAR);
   32.76 +        initWidening(LONG,   Opcodes.F2L, FLOAT);
   32.77 +        initWidening(FLOAT,  Opcodes.I2F, BYTE, SHORT, INT, CHAR);
   32.78 +        initWidening(FLOAT,  Opcodes.L2F, LONG);
   32.79 +        initWidening(DOUBLE, Opcodes.I2D, BYTE, SHORT, INT, CHAR);
   32.80 +        initWidening(DOUBLE, Opcodes.F2D, FLOAT);
   32.81 +        initWidening(DOUBLE, Opcodes.L2D, LONG);
   32.82 +
   32.83 +        FROM_TYPE_SORT[Type.BYTE] = Wrapper.BYTE;
   32.84 +        FROM_TYPE_SORT[Type.SHORT] = Wrapper.SHORT;
   32.85 +        FROM_TYPE_SORT[Type.INT] = Wrapper.INT;
   32.86 +        FROM_TYPE_SORT[Type.LONG] = Wrapper.LONG;
   32.87 +        FROM_TYPE_SORT[Type.CHAR] = Wrapper.CHAR;
   32.88 +        FROM_TYPE_SORT[Type.FLOAT] = Wrapper.FLOAT;
   32.89 +        FROM_TYPE_SORT[Type.DOUBLE] = Wrapper.DOUBLE;
   32.90 +        FROM_TYPE_SORT[Type.BOOLEAN] = Wrapper.BOOLEAN;
   32.91 +    }
   32.92 +
   32.93 +    private static void initWidening(Wrapper to, int opcode, Wrapper... from) {
   32.94 +        for (Wrapper f : from) {
   32.95 +            wideningOpcodes[f.ordinal()][to.ordinal()] = opcode;
   32.96 +        }
   32.97 +    }
   32.98 +
   32.99 +    /**
  32.100 +     * Class name to Wrapper hash, derived from Wrapper.hashWrap()
  32.101 +     * @param xn
  32.102 +     * @return The hash code 0-15
  32.103 +     */
  32.104 +    private static int hashWrapperName(String xn) {
  32.105 +        if (xn.length() < 3) {
  32.106 +            return 0;
  32.107 +        }
  32.108 +        return (3 * xn.charAt(1) + xn.charAt(2)) % 16;
  32.109 +    }
  32.110 +
  32.111 +    private Wrapper wrapperOrNullFromDescriptor(String desc) {
  32.112 +        if (!desc.startsWith(WRAPPER_PREFIX)) {
  32.113 +            // Not a class type (array or method), so not a boxed type
  32.114 +            // or not in the right package
  32.115 +            return null;
  32.116 +        }
  32.117 +        // Pare it down to the simple class name
  32.118 +        String cname = desc.substring(WRAPPER_PREFIX.length(), desc.length() - 1);
  32.119 +        // Hash to a Wrapper
  32.120 +        Wrapper w = FROM_WRAPPER_NAME[hashWrapperName(cname)];
  32.121 +        if (w == null || w.wrapperSimpleName().equals(cname)) {
  32.122 +            return w;
  32.123 +        } else {
  32.124 +            return null;
  32.125 +        }
  32.126 +    }
  32.127 +
  32.128 +    private static String wrapperName(Wrapper w) {
  32.129 +        return "java/lang/" + w.wrapperSimpleName();
  32.130 +    }
  32.131 +
  32.132 +    private static String unboxMethod(Wrapper w) {
  32.133 +        return w.primitiveSimpleName() + "Value";
  32.134 +    }
  32.135 +
  32.136 +    private static String boxingDescriptor(Wrapper w) {
  32.137 +        return String.format("(%s)L%s;", w.basicTypeChar(), wrapperName(w));
  32.138 +    }
  32.139 +
  32.140 +    private static String unboxingDescriptor(Wrapper w) {
  32.141 +        return "()" + w.basicTypeChar();
  32.142 +    }
  32.143 +
  32.144 +    void boxIfTypePrimitive(Type t) {
  32.145 +        Wrapper w = FROM_TYPE_SORT[t.getSort()];
  32.146 +        if (w != null) {
  32.147 +            box(w);
  32.148 +        }
  32.149 +    }
  32.150 +
  32.151 +    void widen(Wrapper ws, Wrapper wt) {
  32.152 +        if (ws != wt) {
  32.153 +            int opcode = wideningOpcodes[ws.ordinal()][wt.ordinal()];
  32.154 +            if (opcode != Opcodes.NOP) {
  32.155 +                visitInsn(opcode);
  32.156 +            }
  32.157 +        }
  32.158 +    }
  32.159 +
  32.160 +    void box(Wrapper w) {
  32.161 +        visitMethodInsn(Opcodes.INVOKESTATIC,
  32.162 +                wrapperName(w),
  32.163 +                NAME_BOX_METHOD,
  32.164 +                boxingDescriptor(w));
  32.165 +    }
  32.166 +
  32.167 +    /**
  32.168 +     * Convert types by unboxing. The source type is known to be a primitive wrapper.
  32.169 +     * @param ws A primitive wrapper corresponding to wrapped reference source type
  32.170 +     * @param wt A primitive wrapper being converted to
  32.171 +     */
  32.172 +    void unbox(String sname, Wrapper wt) {
  32.173 +        visitMethodInsn(Opcodes.INVOKEVIRTUAL,
  32.174 +                sname,
  32.175 +                unboxMethod(wt),
  32.176 +                unboxingDescriptor(wt));
  32.177 +    }
  32.178 +
  32.179 +    private String descriptorToName(String desc) {
  32.180 +        int last = desc.length() - 1;
  32.181 +        if (desc.charAt(0) == 'L' && desc.charAt(last) == ';') {
  32.182 +            // In descriptor form
  32.183 +            return desc.substring(1, last);
  32.184 +        } else {
  32.185 +            // Already in internal name form
  32.186 +            return desc;
  32.187 +        }
  32.188 +    }
  32.189 +
  32.190 +    void cast(String ds, String dt) {
  32.191 +        String ns = descriptorToName(ds);
  32.192 +        String nt = descriptorToName(dt);
  32.193 +        if (!nt.equals(ns) && !nt.equals(NAME_OBJECT)) {
  32.194 +            visitTypeInsn(Opcodes.CHECKCAST, nt);
  32.195 +        }
  32.196 +    }
  32.197 +
  32.198 +    private boolean isPrimitive(Wrapper w) {
  32.199 +        return w != OBJECT;
  32.200 +    }
  32.201 +
  32.202 +    private Wrapper toWrapper(String desc) {
  32.203 +        char first = desc.charAt(0);
  32.204 +        if (first == '[' || first == '(') {
  32.205 +            first = 'L';
  32.206 +        }
  32.207 +        return Wrapper.forBasicType(first);
  32.208 +    }
  32.209 +
  32.210 +    /**
  32.211 +     * Convert an argument of type 'arg' to be passed to 'target' assuring that it is 'functional'.
  32.212 +     * Insert the needed conversion instructions in the method code.
  32.213 +     * @param arg
  32.214 +     * @param target
  32.215 +     * @param functional
  32.216 +     */
  32.217 +    void convertType(Class<?> arg, Class<?> target, Class<?> functional) {
  32.218 +        if (arg.equals(target) && arg.equals(functional)) {
  32.219 +            return;
  32.220 +        }
  32.221 +        if (arg == Void.TYPE || target == Void.TYPE) {
  32.222 +            return;
  32.223 +        }
  32.224 +        if (arg.isPrimitive()) {
  32.225 +            Wrapper wArg = Wrapper.forPrimitiveType(arg);
  32.226 +            if (target.isPrimitive()) {
  32.227 +                // Both primitives: widening
  32.228 +                widen(wArg, Wrapper.forPrimitiveType(target));
  32.229 +            } else {
  32.230 +                // Primitive argument to reference target
  32.231 +                String dTarget = BytecodeDescriptor.unparse(target);
  32.232 +                Wrapper wPrimTarget = wrapperOrNullFromDescriptor(dTarget);
  32.233 +                if (wPrimTarget != null) {
  32.234 +                    // The target is a boxed primitive type, widen to get there before boxing
  32.235 +                    widen(wArg, wPrimTarget);
  32.236 +                    box(wPrimTarget);
  32.237 +                } else {
  32.238 +                    // Otherwise, box and cast
  32.239 +                    box(wArg);
  32.240 +                    cast(wrapperName(wArg), dTarget);
  32.241 +                }
  32.242 +            }
  32.243 +        } else {
  32.244 +            String dArg = BytecodeDescriptor.unparse(arg);
  32.245 +            String dSrc;
  32.246 +            if (functional.isPrimitive()) {
  32.247 +                dSrc = dArg;
  32.248 +            } else {
  32.249 +                // Cast to convert to possibly more specific type, and generate CCE for invalid arg
  32.250 +                dSrc = BytecodeDescriptor.unparse(functional);
  32.251 +                cast(dArg, dSrc);
  32.252 +            }
  32.253 +            String dTarget = BytecodeDescriptor.unparse(target);
  32.254 +            if (target.isPrimitive()) {
  32.255 +                Wrapper wTarget = toWrapper(dTarget);
  32.256 +                // Reference argument to primitive target
  32.257 +                Wrapper wps = wrapperOrNullFromDescriptor(dSrc);
  32.258 +                if (wps != null) {
  32.259 +                    if (wps.isSigned() || wps.isFloating()) {
  32.260 +                        // Boxed number to primitive
  32.261 +                        unbox(wrapperName(wps), wTarget);
  32.262 +                    } else {
  32.263 +                        // Character or Boolean
  32.264 +                        unbox(wrapperName(wps), wps);
  32.265 +                        widen(wps, wTarget);
  32.266 +                    }
  32.267 +                } else {
  32.268 +                    // Source type is reference type, but not boxed type,
  32.269 +                    // assume it is super type of target type
  32.270 +                    String intermediate;
  32.271 +                    if (wTarget.isSigned() || wTarget.isFloating()) {
  32.272 +                        // Boxed number to primitive
  32.273 +                        intermediate = "java/lang/Number";
  32.274 +                    } else {
  32.275 +                        // Character or Boolean
  32.276 +                        intermediate = wrapperName(wTarget);
  32.277 +                    }
  32.278 +                    cast(dSrc, intermediate);
  32.279 +                    unbox(intermediate, wTarget);
  32.280 +                }
  32.281 +            } else {
  32.282 +                // Both reference types: just case to target type
  32.283 +                cast(dSrc, dTarget);
  32.284 +            }
  32.285 +        }
  32.286 +    }
  32.287 +
  32.288 +    /**
  32.289 +     * The following method is copied from
  32.290 +     * org.objectweb.asm.commons.InstructionAdapter. Part of ASM: a very small
  32.291 +     * and fast Java bytecode manipulation framework.
  32.292 +     * Copyright (c) 2000-2005 INRIA, France Telecom All rights reserved.
  32.293 +     */
  32.294 +    void iconst(final int cst) {
  32.295 +        if (cst >= -1 && cst <= 5) {
  32.296 +            mv.visitInsn(Opcodes.ICONST_0 + cst);
  32.297 +        } else if (cst >= Byte.MIN_VALUE && cst <= Byte.MAX_VALUE) {
  32.298 +            mv.visitIntInsn(Opcodes.BIPUSH, cst);
  32.299 +        } else if (cst >= Short.MIN_VALUE && cst <= Short.MAX_VALUE) {
  32.300 +            mv.visitIntInsn(Opcodes.SIPUSH, cst);
  32.301 +        } else {
  32.302 +            mv.visitLdcInsn(cst);
  32.303 +        }
  32.304 +    }
  32.305 +}
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/VolatileCallSite.java	Sat Aug 09 11:12:05 2014 +0200
    33.3 @@ -0,0 +1,109 @@
    33.4 +/*
    33.5 + * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
    33.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    33.7 + *
    33.8 + * This code is free software; you can redistribute it and/or modify it
    33.9 + * under the terms of the GNU General Public License version 2 only, as
   33.10 + * published by the Free Software Foundation.  Oracle designates this
   33.11 + * particular file as subject to the "Classpath" exception as provided
   33.12 + * by Oracle in the LICENSE file that accompanied this code.
   33.13 + *
   33.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   33.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   33.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   33.17 + * version 2 for more details (a copy is included in the LICENSE file that
   33.18 + * accompanied this code).
   33.19 + *
   33.20 + * You should have received a copy of the GNU General Public License version
   33.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   33.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   33.23 + *
   33.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   33.25 + * or visit www.oracle.com if you need additional information or have any
   33.26 + * questions.
   33.27 + */
   33.28 +
   33.29 +package java.lang.invoke;
   33.30 +
   33.31 +/**
   33.32 + * A {@code VolatileCallSite} is a {@link CallSite} whose target acts like a volatile variable.
   33.33 + * An {@code invokedynamic} instruction linked to a {@code VolatileCallSite} sees updates
   33.34 + * to its call site target immediately, even if the update occurs in another thread.
   33.35 + * There may be a performance penalty for such tight coupling between threads.
   33.36 + * <p>
   33.37 + * Unlike {@code MutableCallSite}, there is no
   33.38 + * {@linkplain MutableCallSite#syncAll syncAll operation} on volatile
   33.39 + * call sites, since every write to a volatile variable is implicitly
   33.40 + * synchronized with reader threads.
   33.41 + * <p>
   33.42 + * In other respects, a {@code VolatileCallSite} is interchangeable
   33.43 + * with {@code MutableCallSite}.
   33.44 + * @see MutableCallSite
   33.45 + * @author John Rose, JSR 292 EG
   33.46 + */
   33.47 +public class VolatileCallSite extends CallSite {
   33.48 +    /**
   33.49 +     * Creates a call site with a volatile binding to its target.
   33.50 +     * The initial target is set to a method handle
   33.51 +     * of the given type which will throw an {@code IllegalStateException} if called.
   33.52 +     * @param type the method type that this call site will have
   33.53 +     * @throws NullPointerException if the proposed type is null
   33.54 +     */
   33.55 +    public VolatileCallSite(MethodType type) {
   33.56 +        super(type);
   33.57 +    }
   33.58 +
   33.59 +    /**
   33.60 +     * Creates a call site with a volatile binding to its target.
   33.61 +     * The target is set to the given value.
   33.62 +     * @param target the method handle that will be the initial target of the call site
   33.63 +     * @throws NullPointerException if the proposed target is null
   33.64 +     */
   33.65 +    public VolatileCallSite(MethodHandle target) {
   33.66 +        super(target);
   33.67 +    }
   33.68 +
   33.69 +    /**
   33.70 +     * Returns the target method of the call site, which behaves
   33.71 +     * like a {@code volatile} field of the {@code VolatileCallSite}.
   33.72 +     * <p>
   33.73 +     * The interactions of {@code getTarget} with memory are the same
   33.74 +     * as of a read from a {@code volatile} field.
   33.75 +     * <p>
   33.76 +     * In particular, the current thread is required to issue a fresh
   33.77 +     * read of the target from memory, and must not fail to see
   33.78 +     * a recent update to the target by another thread.
   33.79 +     *
   33.80 +     * @return the linkage state of this call site, a method handle which can change over time
   33.81 +     * @see #setTarget
   33.82 +     */
   33.83 +    @Override public final MethodHandle getTarget() {
   33.84 +        return getTargetVolatile();
   33.85 +    }
   33.86 +
   33.87 +    /**
   33.88 +     * Updates the target method of this call site, as a volatile variable.
   33.89 +     * The type of the new target must agree with the type of the old target.
   33.90 +     * <p>
   33.91 +     * The interactions with memory are the same as of a write to a volatile field.
   33.92 +     * In particular, any threads is guaranteed to see the updated target
   33.93 +     * the next time it calls {@code getTarget}.
   33.94 +     * @param newTarget the new target
   33.95 +     * @throws NullPointerException if the proposed new target is null
   33.96 +     * @throws WrongMethodTypeException if the proposed new target
   33.97 +     *         has a method type that differs from the previous target
   33.98 +     * @see #getTarget
   33.99 +     */
  33.100 +    @Override public void setTarget(MethodHandle newTarget) {
  33.101 +        checkTargetChange(getTargetVolatile(), newTarget);
  33.102 +        setTargetVolatile(newTarget);
  33.103 +    }
  33.104 +
  33.105 +    /**
  33.106 +     * {@inheritDoc}
  33.107 +     */
  33.108 +    @Override
  33.109 +    public final MethodHandle dynamicInvoker() {
  33.110 +        return makeDynamicInvoker();
  33.111 +    }
  33.112 +}
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/WrongMethodTypeException.java	Sat Aug 09 11:12:05 2014 +0200
    34.3 @@ -0,0 +1,85 @@
    34.4 +/*
    34.5 + * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
    34.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    34.7 + *
    34.8 + * This code is free software; you can redistribute it and/or modify it
    34.9 + * under the terms of the GNU General Public License version 2 only, as
   34.10 + * published by the Free Software Foundation.  Oracle designates this
   34.11 + * particular file as subject to the "Classpath" exception as provided
   34.12 + * by Oracle in the LICENSE file that accompanied this code.
   34.13 + *
   34.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   34.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   34.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   34.17 + * version 2 for more details (a copy is included in the LICENSE file that
   34.18 + * accompanied this code).
   34.19 + *
   34.20 + * You should have received a copy of the GNU General Public License version
   34.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   34.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   34.23 + *
   34.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   34.25 + * or visit www.oracle.com if you need additional information or have any
   34.26 + * questions.
   34.27 + */
   34.28 +
   34.29 +package java.lang.invoke;
   34.30 +
   34.31 +/**
   34.32 + * Thrown to indicate that code has attempted to call a method handle
   34.33 + * via the wrong method type.  As with the bytecode representation of
   34.34 + * normal Java method calls, method handle calls are strongly typed
   34.35 + * to a specific type descriptor associated with a call site.
   34.36 + * <p>
   34.37 + * This exception may also be thrown when two method handles are
   34.38 + * composed, and the system detects that their types cannot be
   34.39 + * matched up correctly.  This amounts to an early evaluation
   34.40 + * of the type mismatch, at method handle construction time,
   34.41 + * instead of when the mismatched method handle is called.
   34.42 + *
   34.43 + * @author John Rose, JSR 292 EG
   34.44 + * @since 1.7
   34.45 + */
   34.46 +public class WrongMethodTypeException extends RuntimeException {
   34.47 +    private static final long serialVersionUID = 292L;
   34.48 +
   34.49 +    /**
   34.50 +     * Constructs a {@code WrongMethodTypeException} with no detail message.
   34.51 +     */
   34.52 +    public WrongMethodTypeException() {
   34.53 +        super();
   34.54 +    }
   34.55 +
   34.56 +    /**
   34.57 +     * Constructs a {@code WrongMethodTypeException} with the specified
   34.58 +     * detail message.
   34.59 +     *
   34.60 +     * @param s the detail message.
   34.61 +     */
   34.62 +    public WrongMethodTypeException(String s) {
   34.63 +        super(s);
   34.64 +    }
   34.65 +
   34.66 +    /**
   34.67 +     * Constructs a {@code WrongMethodTypeException} with the specified
   34.68 +     * detail message and cause.
   34.69 +     *
   34.70 +     * @param s the detail message.
   34.71 +     * @param cause the cause of the exception, or null.
   34.72 +     */
   34.73 +    //FIXME: make this public in MR1
   34.74 +    /*non-public*/ WrongMethodTypeException(String s, Throwable cause) {
   34.75 +        super(s, cause);
   34.76 +    }
   34.77 +
   34.78 +    /**
   34.79 +     * Constructs a {@code WrongMethodTypeException} with the specified
   34.80 +     * cause.
   34.81 +     *
   34.82 +     * @param cause the cause of the exception, or null.
   34.83 +     */
   34.84 +    //FIXME: make this public in MR1
   34.85 +    /*non-public*/ WrongMethodTypeException(Throwable cause) {
   34.86 +        super(cause);
   34.87 +    }
   34.88 +}
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/rt/emul/compact/src/main/java/java/lang/invoke/package-info.java	Sat Aug 09 11:12:05 2014 +0200
    35.3 @@ -0,0 +1,211 @@
    35.4 +/*
    35.5 + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
    35.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    35.7 + *
    35.8 + * This code is free software; you can redistribute it and/or modify it
    35.9 + * under the terms of the GNU General Public License version 2 only, as
   35.10 + * published by the Free Software Foundation.  Oracle designates this
   35.11 + * particular file as subject to the "Classpath" exception as provided
   35.12 + * by Oracle in the LICENSE file that accompanied this code.
   35.13 + *
   35.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   35.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   35.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   35.17 + * version 2 for more details (a copy is included in the LICENSE file that
   35.18 + * accompanied this code).
   35.19 + *
   35.20 + * You should have received a copy of the GNU General Public License version
   35.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   35.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   35.23 + *
   35.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   35.25 + * or visit www.oracle.com if you need additional information or have any
   35.26 + * questions.
   35.27 + */
   35.28 +
   35.29 +/**
   35.30 + * The {@code java.lang.invoke} package contains dynamic language support provided directly by
   35.31 + * the Java core class libraries and virtual machine.
   35.32 + *
   35.33 + * <p>
   35.34 + * As described in the Java Virtual Machine Specification,
   35.35 + * certain types in this package have special relations to dynamic
   35.36 + * language support in the virtual machine:
   35.37 + * <ul>
   35.38 + * <li>The class {@link java.lang.invoke.MethodHandle MethodHandle} contains
   35.39 + * <a href="MethodHandle.html#sigpoly">signature polymorphic methods</a>
   35.40 + * which can be linked regardless of their type descriptor.
   35.41 + * Normally, method linkage requires exact matching of type descriptors.
   35.42 + * </li>
   35.43 + *
   35.44 + * <li>The JVM bytecode format supports immediate constants of
   35.45 + * the classes {@link java.lang.invoke.MethodHandle MethodHandle} and {@link java.lang.invoke.MethodType MethodType}.
   35.46 + * </li>
   35.47 + * </ul>
   35.48 + *
   35.49 + * <h1><a name="jvm_mods"></a>Summary of relevant Java Virtual Machine changes</h1>
   35.50 + * The following low-level information summarizes relevant parts of the
   35.51 + * Java Virtual Machine specification.  For full details, please see the
   35.52 + * current version of that specification.
   35.53 + *
   35.54 + * Each occurrence of an {@code invokedynamic} instruction is called a <em>dynamic call site</em>.
   35.55 + * <h2><a name="indyinsn"></a>{@code invokedynamic} instructions</h2>
   35.56 + * A dynamic call site is originally in an unlinked state.  In this state, there is
   35.57 + * no target method for the call site to invoke.
   35.58 + * <p>
   35.59 + * Before the JVM can execute a dynamic call site (an {@code invokedynamic} instruction),
   35.60 + * the call site must first be <em>linked</em>.
   35.61 + * Linking is accomplished by calling a <em>bootstrap method</em>
   35.62 + * which is given the static information content of the call site,
   35.63 + * and which must produce a {@link java.lang.invoke.MethodHandle method handle}
   35.64 + * that gives the behavior of the call site.
   35.65 + * <p>
   35.66 + * Each {@code invokedynamic} instruction statically specifies its own
   35.67 + * bootstrap method as a constant pool reference.
   35.68 + * The constant pool reference also specifies the call site's name and type descriptor,
   35.69 + * just like {@code invokevirtual} and the other invoke instructions.
   35.70 + * <p>
   35.71 + * Linking starts with resolving the constant pool entry for the
   35.72 + * bootstrap method, and resolving a {@link java.lang.invoke.MethodType MethodType} object for
   35.73 + * the type descriptor of the dynamic call site.
   35.74 + * This resolution process may trigger class loading.
   35.75 + * It may therefore throw an error if a class fails to load.
   35.76 + * This error becomes the abnormal termination of the dynamic
   35.77 + * call site execution.
   35.78 + * Linkage does not trigger class initialization.
   35.79 + * <p>
   35.80 + * The bootstrap method is invoked on at least three values:
   35.81 + * <ul>
   35.82 + * <li>a {@code MethodHandles.Lookup}, a lookup object on the <em>caller class</em> in which dynamic call site occurs </li>
   35.83 + * <li>a {@code String}, the method name mentioned in the call site </li>
   35.84 + * <li>a {@code MethodType}, the resolved type descriptor of the call </li>
   35.85 + * <li>optionally, between 1 and 251 additional static arguments taken from the constant pool </li>
   35.86 + * </ul>
   35.87 + * Invocation is as if by
   35.88 + * {@link java.lang.invoke.MethodHandle#invoke MethodHandle.invoke}.
   35.89 + * The returned result must be a {@link java.lang.invoke.CallSite CallSite} (or a subclass).
   35.90 + * The type of the call site's target must be exactly equal to the type
   35.91 + * derived from the dynamic call site's type descriptor and passed to
   35.92 + * the bootstrap method.
   35.93 + * The call site then becomes permanently linked to the dynamic call site.
   35.94 + * <p>
   35.95 + * As documented in the JVM specification, all failures arising from
   35.96 + * the linkage of a dynamic call site are reported
   35.97 + * by a {@link java.lang.BootstrapMethodError BootstrapMethodError},
   35.98 + * which is thrown as the abnormal termination of the dynamic call
   35.99 + * site execution.
  35.100 + * If this happens, the same error will the thrown for all subsequent
  35.101 + * attempts to execute the dynamic call site.
  35.102 + *
  35.103 + * <h2>timing of linkage</h2>
  35.104 + * A dynamic call site is linked just before its first execution.
  35.105 + * The bootstrap method call implementing the linkage occurs within
  35.106 + * a thread that is attempting a first execution.
  35.107 + * <p>
  35.108 + * If there are several such threads, the bootstrap method may be
  35.109 + * invoked in several threads concurrently.
  35.110 + * Therefore, bootstrap methods which access global application
  35.111 + * data must take the usual precautions against race conditions.
  35.112 + * In any case, every {@code invokedynamic} instruction is either
  35.113 + * unlinked or linked to a unique {@code CallSite} object.
  35.114 + * <p>
  35.115 + * In an application which requires dynamic call sites with individually
  35.116 + * mutable behaviors, their bootstrap methods should produce distinct
  35.117 + * {@link java.lang.invoke.CallSite CallSite} objects, one for each linkage request.
  35.118 + * Alternatively, an application can link a single {@code CallSite} object
  35.119 + * to several {@code invokedynamic} instructions, in which case
  35.120 + * a change to the target method will become visible at each of
  35.121 + * the instructions.
  35.122 + * <p>
  35.123 + * If several threads simultaneously execute a bootstrap method for a single dynamic
  35.124 + * call site, the JVM must choose one {@code CallSite} object and install it visibly to
  35.125 + * all threads.  Any other bootstrap method calls are allowed to complete, but their
  35.126 + * results are ignored, and their dynamic call site invocations proceed with the originally
  35.127 + * chosen target object.
  35.128 +
  35.129 + * <p style="font-size:smaller;">
  35.130 + * <em>Discussion:</em>
  35.131 + * These rules do not enable the JVM to duplicate dynamic call sites,
  35.132 + * or to issue &ldquo;causeless&rdquo; bootstrap method calls.
  35.133 + * Every dynamic call site transitions at most once from unlinked to linked,
  35.134 + * just before its first invocation.
  35.135 + * There is no way to undo the effect of a completed bootstrap method call.
  35.136 + *
  35.137 + * <h2>types of bootstrap methods</h2>
  35.138 + * As long as each bootstrap method can be correctly invoked
  35.139 + * by {@code MethodHandle.invoke}, its detailed type is arbitrary.
  35.140 + * For example, the first argument could be {@code Object}
  35.141 + * instead of {@code MethodHandles.Lookup}, and the return type
  35.142 + * could also be {@code Object} instead of {@code CallSite}.
  35.143 + * (Note that the types and number of the stacked arguments limit
  35.144 + * the legal kinds of bootstrap methods to appropriately typed
  35.145 + * static methods and constructors of {@code CallSite} subclasses.)
  35.146 + * <p>
  35.147 + * If a given {@code invokedynamic} instruction specifies no static arguments,
  35.148 + * the instruction's bootstrap method will be invoked on three arguments,
  35.149 + * conveying the instruction's caller class, name, and method type.
  35.150 + * If the {@code invokedynamic} instruction specifies one or more static arguments,
  35.151 + * those values will be passed as additional arguments to the method handle.
  35.152 + * (Note that because there is a limit of 255 arguments to any method,
  35.153 + * at most 251 extra arguments can be supplied, since the bootstrap method
  35.154 + * handle itself and its first three arguments must also be stacked.)
  35.155 + * The bootstrap method will be invoked as if by either {@code MethodHandle.invoke}
  35.156 + * or {@code invokeWithArguments}.  (There is no way to tell the difference.)
  35.157 + * <p>
  35.158 + * The normal argument conversion rules for {@code MethodHandle.invoke} apply to all stacked arguments.
  35.159 + * For example, if a pushed value is a primitive type, it may be converted to a reference by boxing conversion.
  35.160 + * If the bootstrap method is a variable arity method (its modifier bit {@code 0x0080} is set),
  35.161 + * then some or all of the arguments specified here may be collected into a trailing array parameter.
  35.162 + * (This is not a special rule, but rather a useful consequence of the interaction
  35.163 + * between {@code CONSTANT_MethodHandle} constants, the modifier bit for variable arity methods,
  35.164 + * and the {@link java.lang.invoke.MethodHandle#asVarargsCollector asVarargsCollector} transformation.)
  35.165 + * <p>
  35.166 + * Given these rules, here are examples of legal bootstrap method declarations,
  35.167 + * given various numbers {@code N} of extra arguments.
  35.168 + * The first rows (marked {@code *}) will work for any number of extra arguments.
  35.169 + * <table border=1 cellpadding=5 summary="Static argument types">
  35.170 + * <tr><th>N</th><th>sample bootstrap method</th></tr>
  35.171 + * <tr><td>*</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, Object... args)</code></td></tr>
  35.172 + * <tr><td>*</td><td><code>CallSite bootstrap(Object... args)</code></td></tr>
  35.173 + * <tr><td>*</td><td><code>CallSite bootstrap(Object caller, Object... nameAndTypeWithArgs)</code></td></tr>
  35.174 + * <tr><td>0</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type)</code></td></tr>
  35.175 + * <tr><td>0</td><td><code>CallSite bootstrap(Lookup caller, Object... nameAndType)</code></td></tr>
  35.176 + * <tr><td>1</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, Object arg)</code></td></tr>
  35.177 + * <tr><td>2</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, Object... args)</code></td></tr>
  35.178 + * <tr><td>2</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, String... args)</code></td></tr>
  35.179 + * <tr><td>2</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, String x, int y)</code></td></tr>
  35.180 + * </table>
  35.181 + * The last example assumes that the extra arguments are of type
  35.182 + * {@code CONSTANT_String} and {@code CONSTANT_Integer}, respectively.
  35.183 + * The second-to-last example assumes that all extra arguments are of type
  35.184 + * {@code CONSTANT_String}.
  35.185 + * The other examples work with all types of extra arguments.
  35.186 + * <p>
  35.187 + * As noted above, the actual method type of the bootstrap method can vary.
  35.188 + * For example, the fourth argument could be {@code MethodHandle},
  35.189 + * if that is the type of the corresponding constant in
  35.190 + * the {@code CONSTANT_InvokeDynamic} entry.
  35.191 + * In that case, the {@code MethodHandle.invoke} call will pass the extra method handle
  35.192 + * constant as an {@code Object}, but the type matching machinery of {@code MethodHandle.invoke}
  35.193 + * will cast the reference back to {@code MethodHandle} before invoking the bootstrap method.
  35.194 + * (If a string constant were passed instead, by badly generated code, that cast would then fail,
  35.195 + * resulting in a {@code BootstrapMethodError}.)
  35.196 + * <p>
  35.197 + * Note that, as a consequence of the above rules, the bootstrap method may accept a primitive
  35.198 + * argument, if it can be represented by a constant pool entry.
  35.199 + * However, arguments of type {@code boolean}, {@code byte}, {@code short}, or {@code char}
  35.200 + * cannot be created for bootstrap methods, since such constants cannot be directly
  35.201 + * represented in the constant pool, and the invocation of the bootstrap method will
  35.202 + * not perform the necessary narrowing primitive conversions.
  35.203 + * <p>
  35.204 + * Extra bootstrap method arguments are intended to allow language implementors
  35.205 + * to safely and compactly encode metadata.
  35.206 + * In principle, the name and extra arguments are redundant,
  35.207 + * since each call site could be given its own unique bootstrap method.
  35.208 + * Such a practice is likely to produce large class files and constant pools.
  35.209 + *
  35.210 + * @author John Rose, JSR 292 EG
  35.211 + * @since 1.7
  35.212 + */
  35.213 +
  35.214 +package java.lang.invoke;
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/rt/emul/compact/src/main/java/sun/invoke/WrapperInstance.java	Sat Aug 09 11:12:05 2014 +0200
    36.3 @@ -0,0 +1,48 @@
    36.4 +/*
    36.5 + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
    36.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    36.7 + *
    36.8 + * This code is free software; you can redistribute it and/or modify it
    36.9 + * under the terms of the GNU General Public License version 2 only, as
   36.10 + * published by the Free Software Foundation.  Oracle designates this
   36.11 + * particular file as subject to the "Classpath" exception as provided
   36.12 + * by Oracle in the LICENSE file that accompanied this code.
   36.13 + *
   36.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   36.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   36.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   36.17 + * version 2 for more details (a copy is included in the LICENSE file that
   36.18 + * accompanied this code).
   36.19 + *
   36.20 + * You should have received a copy of the GNU General Public License version
   36.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   36.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   36.23 + *
   36.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   36.25 + * or visit www.oracle.com if you need additional information or have any
   36.26 + * questions.
   36.27 + */
   36.28 +
   36.29 +package sun.invoke;
   36.30 +
   36.31 +import java.lang.invoke.MethodHandle;
   36.32 +
   36.33 +/**
   36.34 + * Private API used inside of java.lang.invoke.MethodHandles.
   36.35 + * Interface implemented by every object which is produced by
   36.36 + * {@link java.lang.invoke.MethodHandleProxies#asInterfaceInstance MethodHandleProxies.asInterfaceInstance}.
   36.37 + * The methods of this interface allow a caller to recover the parameters
   36.38 + * to {@code asInstance}.
   36.39 + * This allows applications to repeatedly convert between method handles
   36.40 + * and SAM objects, without the risk of creating unbounded delegation chains.
   36.41 + */
   36.42 +public interface WrapperInstance {
   36.43 +    /** Produce or recover a target method handle which is behaviorally
   36.44 +     *  equivalent to the SAM method of this object.
   36.45 +     */
   36.46 +    public MethodHandle getWrapperInstanceTarget();
   36.47 +    /** Recover the SAM type for which this object was created.
   36.48 +     */
   36.49 +    public Class<?> getWrapperInstanceType();
   36.50 +}
   36.51 +
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/rt/emul/compact/src/main/java/sun/invoke/anon/AnonymousClassLoader.java	Sat Aug 09 11:12:05 2014 +0200
    37.3 @@ -0,0 +1,230 @@
    37.4 +/*
    37.5 + * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
    37.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    37.7 + *
    37.8 + * This code is free software; you can redistribute it and/or modify it
    37.9 + * under the terms of the GNU General Public License version 2 only, as
   37.10 + * published by the Free Software Foundation.  Oracle designates this
   37.11 + * particular file as subject to the "Classpath" exception as provided
   37.12 + * by Oracle in the LICENSE file that accompanied this code.
   37.13 + *
   37.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   37.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   37.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   37.17 + * version 2 for more details (a copy is included in the LICENSE file that
   37.18 + * accompanied this code).
   37.19 + *
   37.20 + * You should have received a copy of the GNU General Public License version
   37.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   37.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   37.23 + *
   37.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   37.25 + * or visit www.oracle.com if you need additional information or have any
   37.26 + * questions.
   37.27 + */
   37.28 +
   37.29 +package sun.invoke.anon;
   37.30 +
   37.31 +import java.io.IOException;
   37.32 +import java.lang.reflect.InvocationTargetException;
   37.33 +import java.lang.reflect.Method;
   37.34 +import sun.misc.IOUtils;
   37.35 +
   37.36 +/**
   37.37 + * Anonymous class loader.  Will load any valid classfile, producing
   37.38 + * a {@link Class} metaobject, without installing that class in the
   37.39 + * system dictionary.  Therefore, {@link Class#forName(String)} will never
   37.40 + * produce a reference to an anonymous class.
   37.41 + * <p>
   37.42 + * The access permissions of the anonymous class are borrowed from
   37.43 + * a <em>host class</em>.  The new class behaves as if it were an
   37.44 + * inner class of the host class.  It can access the host's private
   37.45 + * members, if the creator of the class loader has permission to
   37.46 + * do so (or to create accessible reflective objects).
   37.47 + * <p>
   37.48 + * When the anonymous class is loaded, elements of its constant pool
   37.49 + * can be patched to new values.  This provides a hook to pre-resolve
   37.50 + * named classes in the constant pool to other classes, including
   37.51 + * anonymous ones.  Also, string constants can be pre-resolved to
   37.52 + * any reference.  (The verifier treats non-string, non-class reference
   37.53 + * constants as plain objects.)
   37.54 + *  <p>
   37.55 + * Why include the patching function?  It makes some use cases much easier.
   37.56 + * Second, the constant pool needed some internal patching anyway,
   37.57 + * to anonymize the loaded class itself.  Finally, if you are going
   37.58 + * to use this seriously, you'll want to build anonymous classes
   37.59 + * on top of pre-existing anonymous classes, and that requires patching.
   37.60 + *
   37.61 + * <p>%%% TO-DO:
   37.62 + * <ul>
   37.63 + * <li>needs better documentation</li>
   37.64 + * <li>needs more security work (for safe delegation)</li>
   37.65 + * <li>needs a clearer story about error processing</li>
   37.66 + * <li>patch member references also (use ';' as delimiter char)</li>
   37.67 + * <li>patch method references to (conforming) method handles</li>
   37.68 + * </ul>
   37.69 + *
   37.70 + * @author jrose
   37.71 + * @author Remi Forax
   37.72 + * @see <a href="http://blogs.sun.com/jrose/entry/anonymous_classes_in_the_vm">
   37.73 + *      http://blogs.sun.com/jrose/entry/anonymous_classes_in_the_vm</a>
   37.74 + */
   37.75 +
   37.76 +public class AnonymousClassLoader {
   37.77 +    final Class<?> hostClass;
   37.78 +
   37.79 +    // Privileged constructor.
   37.80 +    private AnonymousClassLoader(Class<?> hostClass) {
   37.81 +        this.hostClass = hostClass;
   37.82 +    }
   37.83 +
   37.84 +    public static AnonymousClassLoader make(sun.misc.Unsafe unsafe, Class<?> hostClass) {
   37.85 +        if (unsafe == null)  throw new NullPointerException();
   37.86 +        return new AnonymousClassLoader(hostClass);
   37.87 +    }
   37.88 +
   37.89 +    public Class<?> loadClass(byte[] classFile) {
   37.90 +        if (defineAnonymousClass == null) {
   37.91 +            // no JVM support; try to fake an approximation
   37.92 +            try {
   37.93 +                return fakeLoadClass(new ConstantPoolParser(classFile).createPatch());
   37.94 +            } catch (InvalidConstantPoolFormatException ee) {
   37.95 +                throw new IllegalArgumentException(ee);
   37.96 +            }
   37.97 +        }
   37.98 +        return loadClass(classFile, null);
   37.99 +    }
  37.100 +
  37.101 +    public Class<?> loadClass(ConstantPoolPatch classPatch) {
  37.102 +        if (defineAnonymousClass == null) {
  37.103 +            // no JVM support; try to fake an approximation
  37.104 +            return fakeLoadClass(classPatch);
  37.105 +        }
  37.106 +        Object[] patches = classPatch.patchArray;
  37.107 +        // Convert class names (this late in the game)
  37.108 +        // to use slash '/' instead of dot '.'.
  37.109 +        // Java likes dots, but the JVM likes slashes.
  37.110 +        for (int i = 0; i < patches.length; i++) {
  37.111 +            Object value = patches[i];
  37.112 +            if (value != null) {
  37.113 +                byte tag = classPatch.getTag(i);
  37.114 +                switch (tag) {
  37.115 +                case ConstantPoolVisitor.CONSTANT_Class:
  37.116 +                    if (value instanceof String) {
  37.117 +                        if (patches == classPatch.patchArray)
  37.118 +                            patches = patches.clone();
  37.119 +                        patches[i] = ((String)value).replace('.', '/');
  37.120 +                    }
  37.121 +                    break;
  37.122 +                case ConstantPoolVisitor.CONSTANT_Fieldref:
  37.123 +                case ConstantPoolVisitor.CONSTANT_Methodref:
  37.124 +                case ConstantPoolVisitor.CONSTANT_InterfaceMethodref:
  37.125 +                case ConstantPoolVisitor.CONSTANT_NameAndType:
  37.126 +                    // When/if the JVM supports these patches,
  37.127 +                    // we'll probably need to reformat them also.
  37.128 +                    // Meanwhile, let the class loader create the error.
  37.129 +                    break;
  37.130 +                }
  37.131 +            }
  37.132 +        }
  37.133 +        return loadClass(classPatch.outer.classFile, classPatch.patchArray);
  37.134 +    }
  37.135 +
  37.136 +    private Class<?> loadClass(byte[] classFile, Object[] patchArray) {
  37.137 +        try {
  37.138 +            return (Class<?>)
  37.139 +                defineAnonymousClass.invoke(unsafe,
  37.140 +                                            hostClass, classFile, patchArray);
  37.141 +        } catch (Exception ex) {
  37.142 +            throwReflectedException(ex);
  37.143 +            throw new RuntimeException("error loading into "+hostClass, ex);
  37.144 +        }
  37.145 +    }
  37.146 +
  37.147 +    private static void throwReflectedException(Exception ex) {
  37.148 +        if (ex instanceof InvocationTargetException) {
  37.149 +            Throwable tex = ((InvocationTargetException)ex).getTargetException();
  37.150 +            if (tex instanceof Error)
  37.151 +                throw (Error) tex;
  37.152 +            ex = (Exception) tex;
  37.153 +        }
  37.154 +        if (ex instanceof RuntimeException) {
  37.155 +            throw (RuntimeException) ex;
  37.156 +        }
  37.157 +    }
  37.158 +
  37.159 +    private Class<?> fakeLoadClass(ConstantPoolPatch classPatch) {
  37.160 +        // Implementation:
  37.161 +        // 1. Make up a new name nobody has used yet.
  37.162 +        // 2. Inspect the tail-header of the class to find the this_class index.
  37.163 +        // 3. Patch the CONSTANT_Class for this_class to the new name.
  37.164 +        // 4. Add other CP entries required by (e.g.) string patches.
  37.165 +        // 5. Flatten Class constants down to their names, making sure that
  37.166 +        //    the host class loader can pick them up again accurately.
  37.167 +        // 6. Generate the edited class file bytes.
  37.168 +        //
  37.169 +        // Potential limitations:
  37.170 +        // * The class won't be truly anonymous, and may interfere with others.
  37.171 +        // * Flattened class constants might not work, because of loader issues.
  37.172 +        // * Pseudo-string constants will not flatten down to real strings.
  37.173 +        // * Method handles will (of course) fail to flatten to linkage strings.
  37.174 +        if (true)  throw new UnsupportedOperationException("NYI");
  37.175 +        Object[] cpArray;
  37.176 +        try {
  37.177 +            cpArray = classPatch.getOriginalCP();
  37.178 +        } catch (InvalidConstantPoolFormatException ex) {
  37.179 +            throw new RuntimeException(ex);
  37.180 +        }
  37.181 +        int thisClassIndex = classPatch.getParser().getThisClassIndex();
  37.182 +        String thisClassName = (String) cpArray[thisClassIndex];
  37.183 +        synchronized (AnonymousClassLoader.class) {
  37.184 +            thisClassName = thisClassName+"\\|"+(++fakeNameCounter);
  37.185 +        }
  37.186 +        classPatch.putUTF8(thisClassIndex, thisClassName);
  37.187 +        byte[] classFile = null;
  37.188 +        return unsafe.defineClass(null, classFile, 0, classFile.length,
  37.189 +                                  hostClass.getClassLoader(),
  37.190 +                                  hostClass.getProtectionDomain());
  37.191 +    }
  37.192 +    private static int fakeNameCounter = 99999;
  37.193 +
  37.194 +    // ignore two warnings on this line:
  37.195 +    private static sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
  37.196 +    // preceding line requires that this class be on the boot class path
  37.197 +
  37.198 +    static private final Method defineAnonymousClass;
  37.199 +    static {
  37.200 +        Method dac = null;
  37.201 +        Class<? extends sun.misc.Unsafe> unsafeClass = unsafe.getClass();
  37.202 +        try {
  37.203 +            dac = unsafeClass.getMethod("defineAnonymousClass",
  37.204 +                                        Class.class,
  37.205 +                                        byte[].class,
  37.206 +                                        Object[].class);
  37.207 +        } catch (Exception ee) {
  37.208 +            dac = null;
  37.209 +        }
  37.210 +        defineAnonymousClass = dac;
  37.211 +    }
  37.212 +
  37.213 +    private static void noJVMSupport() {
  37.214 +        throw new UnsupportedOperationException("no JVM support for anonymous classes");
  37.215 +    }
  37.216 +
  37.217 +
  37.218 +    private static native Class<?> loadClassInternal(Class<?> hostClass,
  37.219 +                                                     byte[] classFile,
  37.220 +                                                     Object[] patchArray);
  37.221 +
  37.222 +    public static byte[] readClassFile(Class<?> templateClass) throws IOException {
  37.223 +        String templateName = templateClass.getName();
  37.224 +        int lastDot = templateName.lastIndexOf('.');
  37.225 +        java.net.URL url = templateClass.getResource(templateName.substring(lastDot+1)+".class");
  37.226 +        java.net.URLConnection connection = url.openConnection();
  37.227 +        int contentLength = connection.getContentLength();
  37.228 +        if (contentLength < 0)
  37.229 +            throw new IOException("invalid content length "+contentLength);
  37.230 +
  37.231 +        return IOUtils.readFully(connection.getInputStream(), contentLength, true);
  37.232 +    }
  37.233 +}
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/rt/emul/compact/src/main/java/sun/invoke/anon/ConstantPoolParser.java	Sat Aug 09 11:12:05 2014 +0200
    38.3 @@ -0,0 +1,368 @@
    38.4 +/*
    38.5 + * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
    38.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    38.7 + *
    38.8 + * This code is free software; you can redistribute it and/or modify it
    38.9 + * under the terms of the GNU General Public License version 2 only, as
   38.10 + * published by the Free Software Foundation.  Oracle designates this
   38.11 + * particular file as subject to the "Classpath" exception as provided
   38.12 + * by Oracle in the LICENSE file that accompanied this code.
   38.13 + *
   38.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   38.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   38.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   38.17 + * version 2 for more details (a copy is included in the LICENSE file that
   38.18 + * accompanied this code).
   38.19 + *
   38.20 + * You should have received a copy of the GNU General Public License version
   38.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   38.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   38.23 + *
   38.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   38.25 + * or visit www.oracle.com if you need additional information or have any
   38.26 + * questions.
   38.27 + */
   38.28 +
   38.29 +package sun.invoke.anon;
   38.30 +
   38.31 +import java.io.IOException;
   38.32 +import java.io.OutputStream;
   38.33 +import java.nio.BufferUnderflowException;
   38.34 +import java.nio.ByteBuffer;
   38.35 +
   38.36 +import static sun.invoke.anon.ConstantPoolVisitor.*;
   38.37 +
   38.38 +/** A constant pool parser.
   38.39 + */
   38.40 +public class ConstantPoolParser {
   38.41 +    final byte[] classFile;
   38.42 +    final byte[] tags;
   38.43 +    final char[] firstHeader;  // maghi, maglo, minor, major, cplen
   38.44 +
   38.45 +    // these are filled in on first parse:
   38.46 +    int endOffset;
   38.47 +    char[] secondHeader;       // flags, this_class, super_class, intlen
   38.48 +
   38.49 +    // used to decode UTF8 array
   38.50 +    private char[] charArray = new char[80];
   38.51 +
   38.52 +    /** Creates a constant pool parser.
   38.53 +     * @param classFile an array of bytes containing a class.
   38.54 +     * @throws InvalidConstantPoolFormatException if the header of the class has errors.
   38.55 +     */
   38.56 +    public ConstantPoolParser(byte[] classFile) throws InvalidConstantPoolFormatException {
   38.57 +        this.classFile = classFile;
   38.58 +        this.firstHeader = parseHeader(classFile);
   38.59 +        this.tags = new byte[firstHeader[4]];
   38.60 +    }
   38.61 +
   38.62 +    /** Create a constant pool parser by loading the bytecodes of the
   38.63 +     *  class taken as argument.
   38.64 +     *
   38.65 +     * @param templateClass the class to parse.
   38.66 +     *
   38.67 +     * @throws IOException raised if an I/O occurs when loading
   38.68 +     *  the bytecode of the template class.
   38.69 +     * @throws InvalidConstantPoolFormatException if the header of the class has errors.
   38.70 +     *
   38.71 +     * @see #ConstantPoolParser(byte[])
   38.72 +     * @see AnonymousClassLoader#readClassFile(Class)
   38.73 +     */
   38.74 +    public ConstantPoolParser(Class<?> templateClass) throws IOException, InvalidConstantPoolFormatException {
   38.75 +        this(AnonymousClassLoader.readClassFile(templateClass));
   38.76 +    }
   38.77 +
   38.78 +    /** Creates an empty patch to patch the class file
   38.79 +     *  used by the current parser.
   38.80 +     * @return a new class patch.
   38.81 +     */
   38.82 +    public ConstantPoolPatch createPatch() {
   38.83 +        return new ConstantPoolPatch(this);
   38.84 +    }
   38.85 +
   38.86 +    /** Report the tag of the indicated CP entry.
   38.87 +     * @param index
   38.88 +     * @return one of {@link ConstantPoolVisitor#CONSTANT_Utf8}, etc.
   38.89 +     */
   38.90 +    public byte getTag(int index) {
   38.91 +        getEndOffset();  // trigger an exception if we haven't parsed yet
   38.92 +        return tags[index];
   38.93 +    }
   38.94 +
   38.95 +    /** Report the length of the constant pool. */
   38.96 +    public int getLength() {
   38.97 +        return firstHeader[4];
   38.98 +    }
   38.99 +
  38.100 +    /** Report the offset, within the class file, of the start of the constant pool. */
  38.101 +    public int getStartOffset() {
  38.102 +        return firstHeader.length * 2;
  38.103 +    }
  38.104 +
  38.105 +    /** Report the offset, within the class file, of the end of the constant pool. */
  38.106 +    public int getEndOffset() {
  38.107 +        if (endOffset == 0)
  38.108 +            throw new IllegalStateException("class file has not yet been parsed");
  38.109 +        return endOffset;
  38.110 +    }
  38.111 +
  38.112 +    /** Report the CP index of this class's own name. */
  38.113 +    public int getThisClassIndex() {
  38.114 +        getEndOffset();   // provoke exception if not yet parsed
  38.115 +        return secondHeader[1];
  38.116 +    }
  38.117 +
  38.118 +    /** Report the total size of the class file. */
  38.119 +    public int getTailLength() {
  38.120 +        return classFile.length - getEndOffset();
  38.121 +    }
  38.122 +
  38.123 +    /** Write the head (header plus constant pool)
  38.124 +     *  of the class file to the indicated stream.
  38.125 +     */
  38.126 +    public void writeHead(OutputStream out) throws IOException {
  38.127 +        out.write(classFile, 0, getEndOffset());
  38.128 +    }
  38.129 +
  38.130 +    /** Write the head (header plus constant pool)
  38.131 +     *  of the class file to the indicated stream,
  38.132 +     *  incorporating the non-null entries of the given array
  38.133 +     *  as patches.
  38.134 +     */
  38.135 +    void writePatchedHead(OutputStream out, Object[] patchArray) {
  38.136 +        // this will be useful to partially emulate the class loader on old JVMs
  38.137 +        throw new UnsupportedOperationException("Not yet implemented");
  38.138 +    }
  38.139 +
  38.140 +    /** Write the tail (everything after the constant pool)
  38.141 +     *  of the class file to the indicated stream.
  38.142 +     */
  38.143 +    public void writeTail(OutputStream out) throws IOException {
  38.144 +        out.write(classFile, getEndOffset(), getTailLength());
  38.145 +    }
  38.146 +
  38.147 +    private static char[] parseHeader(byte[] classFile) throws InvalidConstantPoolFormatException {
  38.148 +        char[] result = new char[5];
  38.149 +        ByteBuffer buffer = ByteBuffer.wrap(classFile);
  38.150 +        for (int i = 0; i < result.length; i++)
  38.151 +            result[i] = (char) getUnsignedShort(buffer);
  38.152 +        int magic = result[0] << 16 | result[1] << 0;
  38.153 +        if (magic != 0xCAFEBABE)
  38.154 +            throw new InvalidConstantPoolFormatException("invalid magic number "+magic);
  38.155 +        // skip major, minor version
  38.156 +        int len = result[4];
  38.157 +        if (len < 1)
  38.158 +            throw new InvalidConstantPoolFormatException("constant pool length < 1");
  38.159 +        return result;
  38.160 +    }
  38.161 +
  38.162 +    /** Parse the constant pool of the class
  38.163 +     *  calling a method visit* each time a constant pool entry is parsed.
  38.164 +     *
  38.165 +     *  The order of the calls to visit* is not guaranteed to be the same
  38.166 +     *  than the order of the constant pool entry in the bytecode array.
  38.167 +     *
  38.168 +     * @param visitor
  38.169 +     * @throws InvalidConstantPoolFormatException
  38.170 +     */
  38.171 +    public void parse(ConstantPoolVisitor visitor) throws InvalidConstantPoolFormatException {
  38.172 +        ByteBuffer buffer = ByteBuffer.wrap(classFile);
  38.173 +        buffer.position(getStartOffset()); //skip header
  38.174 +
  38.175 +        Object[] values = new Object[getLength()];
  38.176 +        try {
  38.177 +            parseConstantPool(buffer, values, visitor);
  38.178 +        } catch(BufferUnderflowException e) {
  38.179 +            throw new InvalidConstantPoolFormatException(e);
  38.180 +        }
  38.181 +        if (endOffset == 0) {
  38.182 +            endOffset = buffer.position();
  38.183 +            secondHeader = new char[4];
  38.184 +            for (int i = 0; i < secondHeader.length; i++) {
  38.185 +                secondHeader[i] = (char) getUnsignedShort(buffer);
  38.186 +            }
  38.187 +        }
  38.188 +        resolveConstantPool(values, visitor);
  38.189 +    }
  38.190 +
  38.191 +    private char[] getCharArray(int utfLength) {
  38.192 +        if (utfLength <= charArray.length)
  38.193 +            return charArray;
  38.194 +        return charArray = new char[utfLength];
  38.195 +    }
  38.196 +
  38.197 +    private void parseConstantPool(ByteBuffer buffer, Object[] values, ConstantPoolVisitor visitor) throws InvalidConstantPoolFormatException {
  38.198 +        for (int i = 1; i < tags.length; ) {
  38.199 +            byte tag = (byte) getUnsignedByte(buffer);
  38.200 +            assert(tags[i] == 0 || tags[i] == tag);
  38.201 +            tags[i] = tag;
  38.202 +            switch (tag) {
  38.203 +                case CONSTANT_Utf8:
  38.204 +                    int utfLen = getUnsignedShort(buffer);
  38.205 +                    String value = getUTF8(buffer, utfLen, getCharArray(utfLen));
  38.206 +                    visitor.visitUTF8(i, CONSTANT_Utf8, value);
  38.207 +                    tags[i] = tag;
  38.208 +                    values[i++] = value;
  38.209 +                    break;
  38.210 +                case CONSTANT_Integer:
  38.211 +                    visitor.visitConstantValue(i, tag, buffer.getInt());
  38.212 +                    i++;
  38.213 +                    break;
  38.214 +                case CONSTANT_Float:
  38.215 +                    visitor.visitConstantValue(i, tag, buffer.getFloat());
  38.216 +                    i++;
  38.217 +                    break;
  38.218 +                case CONSTANT_Long:
  38.219 +                    visitor.visitConstantValue(i, tag, buffer.getLong());
  38.220 +                    i+=2;
  38.221 +                    break;
  38.222 +                case CONSTANT_Double:
  38.223 +                    visitor.visitConstantValue(i, tag, buffer.getDouble());
  38.224 +                    i+=2;
  38.225 +                    break;
  38.226 +
  38.227 +                case CONSTANT_Class:    // fall through:
  38.228 +                case CONSTANT_String:
  38.229 +                    tags[i] = tag;
  38.230 +                    values[i++] = new int[] { getUnsignedShort(buffer) };
  38.231 +                    break;
  38.232 +
  38.233 +                case CONSTANT_Fieldref:           // fall through:
  38.234 +                case CONSTANT_Methodref:          // fall through:
  38.235 +                case CONSTANT_InterfaceMethodref: // fall through:
  38.236 +                case CONSTANT_NameAndType:
  38.237 +                    tags[i] = tag;
  38.238 +                    values[i++] = new int[] { getUnsignedShort(buffer), getUnsignedShort(buffer) };
  38.239 +                    break;
  38.240 +                default:
  38.241 +                    throw new AssertionError("invalid constant "+tag);
  38.242 +            }
  38.243 +        }
  38.244 +    }
  38.245 +
  38.246 +    private void resolveConstantPool(Object[] values, ConstantPoolVisitor visitor) {
  38.247 +        // clean out the int[] values, which are temporary
  38.248 +        for (int beg = 1, end = values.length-1, beg2, end2;
  38.249 +             beg <= end;
  38.250 +             beg = beg2, end = end2) {
  38.251 +             beg2 = end; end2 = beg-1;
  38.252 +             //System.out.println("CP resolve pass: "+beg+".."+end);
  38.253 +             for (int i = beg; i <= end; i++) {
  38.254 +                  Object value = values[i];
  38.255 +                  if (!(value instanceof int[]))
  38.256 +                      continue;
  38.257 +                  int[] array = (int[]) value;
  38.258 +                  byte tag = tags[i];
  38.259 +                  switch (tag) {
  38.260 +                      case CONSTANT_String:
  38.261 +                          String stringBody = (String) values[array[0]];
  38.262 +                          visitor.visitConstantString(i, tag, stringBody, array[0]);
  38.263 +                          values[i] = null;
  38.264 +                          break;
  38.265 +                      case CONSTANT_Class: {
  38.266 +                          String className = (String) values[array[0]];
  38.267 +                          // use the external form favored by Class.forName:
  38.268 +                          className = className.replace('/', '.');
  38.269 +                          visitor.visitConstantString(i, tag, className, array[0]);
  38.270 +                          values[i] = className;
  38.271 +                          break;
  38.272 +                      }
  38.273 +                      case CONSTANT_NameAndType: {
  38.274 +                          String memberName = (String) values[array[0]];
  38.275 +                          String signature  = (String) values[array[1]];
  38.276 +                          visitor.visitDescriptor(i, tag, memberName, signature,
  38.277 +                                                  array[0], array[1]);
  38.278 +                          values[i] = new String[] {memberName, signature};
  38.279 +                          break;
  38.280 +                      }
  38.281 +                      case CONSTANT_Fieldref:           // fall through:
  38.282 +                      case CONSTANT_Methodref:          // fall through:
  38.283 +                      case CONSTANT_InterfaceMethodref: {
  38.284 +                              Object className   = values[array[0]];
  38.285 +                              Object nameAndType = values[array[1]];
  38.286 +                              if (!(className instanceof String) ||
  38.287 +                                  !(nameAndType instanceof String[])) {
  38.288 +                                   // one more pass is needed
  38.289 +                                   if (beg2 > i)  beg2 = i;
  38.290 +                                   if (end2 < i)  end2 = i;
  38.291 +                                   continue;
  38.292 +                              }
  38.293 +                              String[] nameAndTypeArray = (String[]) nameAndType;
  38.294 +                              visitor.visitMemberRef(i, tag,
  38.295 +                                  (String)className,
  38.296 +                                  nameAndTypeArray[0],
  38.297 +                                  nameAndTypeArray[1],
  38.298 +                                  array[0], array[1]);
  38.299 +                              values[i] = null;
  38.300 +                          }
  38.301 +                          break;
  38.302 +                      default:
  38.303 +                          continue;
  38.304 +                }
  38.305 +            }
  38.306 +        }
  38.307 +    }
  38.308 +
  38.309 +    private static int getUnsignedByte(ByteBuffer buffer) {
  38.310 +        return buffer.get() & 0xFF;
  38.311 +    }
  38.312 +
  38.313 +    private static int getUnsignedShort(ByteBuffer buffer) {
  38.314 +        int b1 = getUnsignedByte(buffer);
  38.315 +        int b2 = getUnsignedByte(buffer);
  38.316 +        return (b1 << 8) + (b2 << 0);
  38.317 +    }
  38.318 +
  38.319 +    private static String getUTF8(ByteBuffer buffer, int utfLen, char[] charArray) throws InvalidConstantPoolFormatException {
  38.320 +      int utfLimit = buffer.position() + utfLen;
  38.321 +      int index = 0;
  38.322 +      while (buffer.position() < utfLimit) {
  38.323 +          int c = buffer.get() & 0xff;
  38.324 +          if (c > 127) {
  38.325 +              buffer.position(buffer.position() - 1);
  38.326 +              return getUTF8Extended(buffer, utfLimit, charArray, index);
  38.327 +          }
  38.328 +          charArray[index++] = (char)c;
  38.329 +      }
  38.330 +      return new String(charArray, 0, index);
  38.331 +    }
  38.332 +
  38.333 +    private static String getUTF8Extended(ByteBuffer buffer, int utfLimit, char[] charArray, int index) throws InvalidConstantPoolFormatException {
  38.334 +        int c, c2, c3;
  38.335 +        while (buffer.position() < utfLimit) {
  38.336 +            c = buffer.get() & 0xff;
  38.337 +            switch (c >> 4) {
  38.338 +                case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
  38.339 +                    /* 0xxxxxxx*/
  38.340 +                    charArray[index++] = (char)c;
  38.341 +                    break;
  38.342 +                case 12: case 13:
  38.343 +                    /* 110x xxxx   10xx xxxx*/
  38.344 +                    c2 = buffer.get();
  38.345 +                    if ((c2 & 0xC0) != 0x80)
  38.346 +                        throw new InvalidConstantPoolFormatException(
  38.347 +                            "malformed input around byte " + buffer.position());
  38.348 +                     charArray[index++] = (char)(((c  & 0x1F) << 6) |
  38.349 +                                                  (c2 & 0x3F));
  38.350 +                    break;
  38.351 +                case 14:
  38.352 +                    /* 1110 xxxx  10xx xxxx  10xx xxxx */
  38.353 +                    c2 = buffer.get();
  38.354 +                    c3 = buffer.get();
  38.355 +                    if (((c2 & 0xC0) != 0x80) || ((c3 & 0xC0) != 0x80))
  38.356 +                       throw new InvalidConstantPoolFormatException(
  38.357 +                          "malformed input around byte " + (buffer.position()));
  38.358 +                    charArray[index++] = (char)(((c  & 0x0F) << 12) |
  38.359 +                                                ((c2 & 0x3F) << 6)  |
  38.360 +                                                ((c3 & 0x3F) << 0));
  38.361 +                    break;
  38.362 +                default:
  38.363 +                    /* 10xx xxxx,  1111 xxxx */
  38.364 +                    throw new InvalidConstantPoolFormatException(
  38.365 +                        "malformed input around byte " + buffer.position());
  38.366 +            }
  38.367 +        }
  38.368 +        // The number of chars produced may be less than utflen
  38.369 +        return new String(charArray, 0, index);
  38.370 +    }
  38.371 +}
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/rt/emul/compact/src/main/java/sun/invoke/anon/ConstantPoolPatch.java	Sat Aug 09 11:12:05 2014 +0200
    39.3 @@ -0,0 +1,503 @@
    39.4 +/*
    39.5 + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
    39.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    39.7 + *
    39.8 + * This code is free software; you can redistribute it and/or modify it
    39.9 + * under the terms of the GNU General Public License version 2 only, as
   39.10 + * published by the Free Software Foundation.  Oracle designates this
   39.11 + * particular file as subject to the "Classpath" exception as provided
   39.12 + * by Oracle in the LICENSE file that accompanied this code.
   39.13 + *
   39.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   39.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   39.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   39.17 + * version 2 for more details (a copy is included in the LICENSE file that
   39.18 + * accompanied this code).
   39.19 + *
   39.20 + * You should have received a copy of the GNU General Public License version
   39.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   39.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   39.23 + *
   39.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   39.25 + * or visit www.oracle.com if you need additional information or have any
   39.26 + * questions.
   39.27 + */
   39.28 +
   39.29 +package sun.invoke.anon;
   39.30 +
   39.31 +import java.io.IOException;
   39.32 +import java.io.OutputStream;
   39.33 +import java.util.Arrays;
   39.34 +import java.util.HashSet;
   39.35 +import java.util.IdentityHashMap;
   39.36 +import java.util.Map;
   39.37 +
   39.38 +import static sun.invoke.anon.ConstantPoolVisitor.*;
   39.39 +
   39.40 +/** A class and its patched constant pool.
   39.41 + *
   39.42 + *  This class allow to modify (patch) a constant pool
   39.43 + *  by changing the value of its entry.
   39.44 + *  Entry are referenced using index that can be get
   39.45 + *  by parsing the constant pool using
   39.46 + *  {@link ConstantPoolParser#parse(ConstantPoolVisitor)}.
   39.47 + *
   39.48 + * @see ConstantPoolVisitor
   39.49 + * @see ConstantPoolParser#createPatch()
   39.50 + */
   39.51 +public class ConstantPoolPatch {
   39.52 +    final ConstantPoolParser outer;
   39.53 +    final Object[] patchArray;
   39.54 +
   39.55 +    ConstantPoolPatch(ConstantPoolParser outer) {
   39.56 +        this.outer      = outer;
   39.57 +        this.patchArray = new Object[outer.getLength()];
   39.58 +    }
   39.59 +
   39.60 +    /** Create a {@link ConstantPoolParser} and
   39.61 +     *  a {@link ConstantPoolPatch} in one step.
   39.62 +     *  Equivalent to {@code new ConstantPoolParser(classFile).createPatch()}.
   39.63 +     *
   39.64 +     * @param classFile an array of bytes containing a class.
   39.65 +     * @see #ConstantPoolParser(Class)
   39.66 +     */
   39.67 +    public ConstantPoolPatch(byte[] classFile) throws InvalidConstantPoolFormatException {
   39.68 +        this(new ConstantPoolParser(classFile));
   39.69 +    }
   39.70 +
   39.71 +    /** Create a {@link ConstantPoolParser} and
   39.72 +     *  a {@link ConstantPoolPatch} in one step.
   39.73 +     *  Equivalent to {@code new ConstantPoolParser(templateClass).createPatch()}.
   39.74 +     *
   39.75 +     * @param templateClass the class to parse.
   39.76 +     * @see #ConstantPoolParser(Class)
   39.77 +     */
   39.78 +    public ConstantPoolPatch(Class<?> templateClass) throws IOException, InvalidConstantPoolFormatException {
   39.79 +        this(new ConstantPoolParser(templateClass));
   39.80 +    }
   39.81 +
   39.82 +
   39.83 +    /** Creates a patch from an existing patch.
   39.84 +     *  All changes are copied from that patch.
   39.85 +     * @param patch a patch
   39.86 +     *
   39.87 +     * @see ConstantPoolParser#createPatch()
   39.88 +     */
   39.89 +    public ConstantPoolPatch(ConstantPoolPatch patch) {
   39.90 +        outer      = patch.outer;
   39.91 +        patchArray = patch.patchArray.clone();
   39.92 +    }
   39.93 +
   39.94 +    /** Which parser built this patch? */
   39.95 +    public ConstantPoolParser getParser() {
   39.96 +        return outer;
   39.97 +    }
   39.98 +
   39.99 +    /** Report the tag at the given index in the constant pool. */
  39.100 +    public byte getTag(int index) {
  39.101 +        return outer.getTag(index);
  39.102 +    }
  39.103 +
  39.104 +    /** Report the current patch at the given index of the constant pool.
  39.105 +     *  Null means no patch will be made.
  39.106 +     *  To observe the unpatched entry at the given index, use
  39.107 +     *  {@link #getParser()}{@code .}@link ConstantPoolParser#parse(ConstantPoolVisitor)}
  39.108 +     */
  39.109 +    public Object getPatch(int index) {
  39.110 +        Object value = patchArray[index];
  39.111 +        if (value == null)  return null;
  39.112 +        switch (getTag(index)) {
  39.113 +        case CONSTANT_Fieldref:
  39.114 +        case CONSTANT_Methodref:
  39.115 +        case CONSTANT_InterfaceMethodref:
  39.116 +            if (value instanceof String)
  39.117 +                value = stripSemis(2, (String) value);
  39.118 +            break;
  39.119 +        case CONSTANT_NameAndType:
  39.120 +            if (value instanceof String)
  39.121 +                value = stripSemis(1, (String) value);
  39.122 +            break;
  39.123 +        }
  39.124 +        return value;
  39.125 +    }
  39.126 +
  39.127 +    /** Clear all patches. */
  39.128 +    public void clear() {
  39.129 +        Arrays.fill(patchArray, null);
  39.130 +    }
  39.131 +
  39.132 +    /** Clear one patch. */
  39.133 +    public void clear(int index) {
  39.134 +        patchArray[index] = null;
  39.135 +    }
  39.136 +
  39.137 +    /** Produce the patches as an array. */
  39.138 +    public Object[] getPatches() {
  39.139 +        return patchArray.clone();
  39.140 +    }
  39.141 +
  39.142 +    /** Produce the original constant pool as an array. */
  39.143 +    public Object[] getOriginalCP() throws InvalidConstantPoolFormatException {
  39.144 +        return getOriginalCP(0, patchArray.length, -1);
  39.145 +    }
  39.146 +
  39.147 +    /** Walk the constant pool, applying patches using the given map.
  39.148 +     *
  39.149 +     * @param utf8Map Utf8 strings to modify, if encountered
  39.150 +     * @param classMap Classes (or their names) to modify, if encountered
  39.151 +     * @param valueMap Constant values to modify, if encountered
  39.152 +     * @param deleteUsedEntries if true, delete map entries that are used
  39.153 +     */
  39.154 +    public void putPatches(final Map<String,String> utf8Map,
  39.155 +                           final Map<String,Object> classMap,
  39.156 +                           final Map<Object,Object> valueMap,
  39.157 +                           boolean deleteUsedEntries) throws InvalidConstantPoolFormatException {
  39.158 +        final HashSet<String> usedUtf8Keys;
  39.159 +        final HashSet<String> usedClassKeys;
  39.160 +        final HashSet<Object> usedValueKeys;
  39.161 +        if (deleteUsedEntries) {
  39.162 +            usedUtf8Keys  = (utf8Map  == null) ? null : new HashSet<String>();
  39.163 +            usedClassKeys = (classMap == null) ? null : new HashSet<String>();
  39.164 +            usedValueKeys = (valueMap == null) ? null : new HashSet<Object>();
  39.165 +        } else {
  39.166 +            usedUtf8Keys = null;
  39.167 +            usedClassKeys = null;
  39.168 +            usedValueKeys = null;
  39.169 +        }
  39.170 +
  39.171 +        outer.parse(new ConstantPoolVisitor() {
  39.172 +
  39.173 +            @Override
  39.174 +            public void visitUTF8(int index, byte tag, String utf8) {
  39.175 +                putUTF8(index, utf8Map.get(utf8));
  39.176 +                if (usedUtf8Keys != null)  usedUtf8Keys.add(utf8);
  39.177 +            }
  39.178 +
  39.179 +            @Override
  39.180 +            public void visitConstantValue(int index, byte tag, Object value) {
  39.181 +                putConstantValue(index, tag, valueMap.get(value));
  39.182 +                if (usedValueKeys != null)  usedValueKeys.add(value);
  39.183 +            }
  39.184 +
  39.185 +            @Override
  39.186 +            public void visitConstantString(int index, byte tag, String name, int nameIndex) {
  39.187 +                if (tag == CONSTANT_Class) {
  39.188 +                    putConstantValue(index, tag, classMap.get(name));
  39.189 +                    if (usedClassKeys != null)  usedClassKeys.add(name);
  39.190 +                } else {
  39.191 +                    assert(tag == CONSTANT_String);
  39.192 +                    visitConstantValue(index, tag, name);
  39.193 +                }
  39.194 +            }
  39.195 +        });
  39.196 +        if (usedUtf8Keys != null)   utf8Map.keySet().removeAll(usedUtf8Keys);
  39.197 +        if (usedClassKeys != null)  classMap.keySet().removeAll(usedClassKeys);
  39.198 +        if (usedValueKeys != null)  valueMap.keySet().removeAll(usedValueKeys);
  39.199 +    }
  39.200 +
  39.201 +    Object[] getOriginalCP(final int startIndex,
  39.202 +                           final int endIndex,
  39.203 +                           final int tagMask) throws InvalidConstantPoolFormatException {
  39.204 +        final Object[] cpArray = new Object[endIndex - startIndex];
  39.205 +        outer.parse(new ConstantPoolVisitor() {
  39.206 +
  39.207 +            void show(int index, byte tag, Object value) {
  39.208 +                if (index < startIndex || index >= endIndex)  return;
  39.209 +                if (((1 << tag) & tagMask) == 0)  return;
  39.210 +                cpArray[index - startIndex] = value;
  39.211 +            }
  39.212 +
  39.213 +            @Override
  39.214 +            public void visitUTF8(int index, byte tag, String utf8) {
  39.215 +                show(index, tag, utf8);
  39.216 +            }
  39.217 +
  39.218 +            @Override
  39.219 +            public void visitConstantValue(int index, byte tag, Object value) {
  39.220 +                assert(tag != CONSTANT_String);
  39.221 +                show(index, tag, value);
  39.222 +            }
  39.223 +
  39.224 +            @Override
  39.225 +            public void visitConstantString(int index, byte tag,
  39.226 +                                            String value, int j) {
  39.227 +                show(index, tag, value);
  39.228 +            }
  39.229 +
  39.230 +            @Override
  39.231 +            public void visitMemberRef(int index, byte tag,
  39.232 +                    String className, String memberName,
  39.233 +                    String signature,
  39.234 +                    int j, int k) {
  39.235 +                show(index, tag, new String[]{ className, memberName, signature });
  39.236 +            }
  39.237 +
  39.238 +            @Override
  39.239 +            public void visitDescriptor(int index, byte tag,
  39.240 +                    String memberName, String signature,
  39.241 +                    int j, int k) {
  39.242 +                show(index, tag, new String[]{ memberName, signature });
  39.243 +            }
  39.244 +        });
  39.245 +        return cpArray;
  39.246 +    }
  39.247 +
  39.248 +    /** Write the head (header plus constant pool)
  39.249 +     *  of the patched class file to the indicated stream.
  39.250 +     */
  39.251 +    void writeHead(OutputStream out) throws IOException {
  39.252 +        outer.writePatchedHead(out, patchArray);
  39.253 +    }
  39.254 +
  39.255 +    /** Write the tail (everything after the constant pool)
  39.256 +     *  of the patched class file to the indicated stream.
  39.257 +     */
  39.258 +    void writeTail(OutputStream out) throws IOException {
  39.259 +        outer.writeTail(out);
  39.260 +    }
  39.261 +
  39.262 +    private void checkConstantTag(byte tag, Object value) {
  39.263 +        if (value == null)
  39.264 +            throw new IllegalArgumentException(
  39.265 +                    "invalid null constant value");
  39.266 +        if (classForTag(tag) != value.getClass())
  39.267 +            throw new IllegalArgumentException(
  39.268 +                    "invalid constant value"
  39.269 +                    + (tag == CONSTANT_None ? ""
  39.270 +                        : " for tag "+tagName(tag))
  39.271 +                    + " of class "+value.getClass());
  39.272 +    }
  39.273 +
  39.274 +    private void checkTag(int index, byte putTag) {
  39.275 +        byte tag = outer.tags[index];
  39.276 +        if (tag != putTag)
  39.277 +            throw new IllegalArgumentException(
  39.278 +                "invalid put operation"
  39.279 +                + " for " + tagName(putTag)
  39.280 +                + " at index " + index + " found " + tagName(tag));
  39.281 +    }
  39.282 +
  39.283 +    private void checkTagMask(int index, int tagBitMask) {
  39.284 +        byte tag = outer.tags[index];
  39.285 +        int tagBit = ((tag & 0x1F) == tag) ? (1 << tag) : 0;
  39.286 +        if ((tagBit & tagBitMask) == 0)
  39.287 +            throw new IllegalArgumentException(
  39.288 +                "invalid put operation"
  39.289 +                + " at index " + index + " found " + tagName(tag));
  39.290 +    }
  39.291 +
  39.292 +    private static void checkMemberName(String memberName) {
  39.293 +        if (memberName.indexOf(';') >= 0)
  39.294 +            throw new IllegalArgumentException("memberName " + memberName + " contains a ';'");
  39.295 +    }
  39.296 +
  39.297 +    /** Set the entry of the constant pool indexed by index to
  39.298 +     *  a new string.
  39.299 +     *
  39.300 +     * @param index an index to a constant pool entry containing a
  39.301 +     *        {@link ConstantPoolVisitor#CONSTANT_Utf8} value.
  39.302 +     * @param utf8 a string
  39.303 +     *
  39.304 +     * @see ConstantPoolVisitor#visitUTF8(int, byte, String)
  39.305 +     */
  39.306 +    public void putUTF8(int index, String utf8) {
  39.307 +        if (utf8 == null) { clear(index); return; }
  39.308 +        checkTag(index, CONSTANT_Utf8);
  39.309 +        patchArray[index] = utf8;
  39.310 +    }
  39.311 +
  39.312 +    /** Set the entry of the constant pool indexed by index to
  39.313 +     *  a new value, depending on its dynamic type.
  39.314 +     *
  39.315 +     * @param index an index to a constant pool entry containing a
  39.316 +     *        one of the following structures:
  39.317 +     *        {@link ConstantPoolVisitor#CONSTANT_Integer},
  39.318 +     *        {@link ConstantPoolVisitor#CONSTANT_Float},
  39.319 +     *        {@link ConstantPoolVisitor#CONSTANT_Long},
  39.320 +     *        {@link ConstantPoolVisitor#CONSTANT_Double},
  39.321 +     *        {@link ConstantPoolVisitor#CONSTANT_String}, or
  39.322 +     *        {@link ConstantPoolVisitor#CONSTANT_Class}
  39.323 +     * @param value a boxed int, float, long or double; or a string or class object
  39.324 +     * @throws IllegalArgumentException if the type of the constant does not
  39.325 +     *         match the constant pool entry type,
  39.326 +     *         as reported by {@link #getTag(int)}
  39.327 +     *
  39.328 +     * @see #putConstantValue(int, byte, Object)
  39.329 +     * @see ConstantPoolVisitor#visitConstantValue(int, byte, Object)
  39.330 +     * @see ConstantPoolVisitor#visitConstantString(int, byte, String, int)
  39.331 +     */
  39.332 +    public void putConstantValue(int index, Object value) {
  39.333 +        if (value == null) { clear(index); return; }
  39.334 +        byte tag = tagForConstant(value.getClass());
  39.335 +        checkConstantTag(tag, value);
  39.336 +        checkTag(index, tag);
  39.337 +        patchArray[index] = value;
  39.338 +    }
  39.339 +
  39.340 +    /** Set the entry of the constant pool indexed by index to
  39.341 +     *  a new value.
  39.342 +     *
  39.343 +     * @param index an index to a constant pool entry matching the given tag
  39.344 +     * @param tag one of the following values:
  39.345 +     *        {@link ConstantPoolVisitor#CONSTANT_Integer},
  39.346 +     *        {@link ConstantPoolVisitor#CONSTANT_Float},
  39.347 +     *        {@link ConstantPoolVisitor#CONSTANT_Long},
  39.348 +     *        {@link ConstantPoolVisitor#CONSTANT_Double},
  39.349 +     *        {@link ConstantPoolVisitor#CONSTANT_String}, or
  39.350 +     *        {@link ConstantPoolVisitor#CONSTANT_Class}
  39.351 +     * @param value a boxed number, string, or class object
  39.352 +     * @throws IllegalArgumentException if the type of the constant does not
  39.353 +     *         match the constant pool entry type, or if a class name contains
  39.354 +     *         '/' or ';'
  39.355 +     *
  39.356 +     * @see #putConstantValue(int, Object)
  39.357 +     * @see ConstantPoolVisitor#visitConstantValue(int, byte, Object)
  39.358 +     * @see ConstantPoolVisitor#visitConstantString(int, byte, String, int)
  39.359 +     */
  39.360 +    public void putConstantValue(int index, byte tag, Object value) {
  39.361 +        if (value == null) { clear(index); return; }
  39.362 +        checkTag(index, tag);
  39.363 +        if (tag == CONSTANT_Class && value instanceof String) {
  39.364 +            checkClassName((String) value);
  39.365 +        } else if (tag == CONSTANT_String) {
  39.366 +            // the JVM accepts any object as a patch for a string
  39.367 +        } else {
  39.368 +            // make sure the incoming value is the right type
  39.369 +            checkConstantTag(tag, value);
  39.370 +        }
  39.371 +        checkTag(index, tag);
  39.372 +        patchArray[index] = value;
  39.373 +    }
  39.374 +
  39.375 +    /** Set the entry of the constant pool indexed by index to
  39.376 +     *  a new {@link ConstantPoolVisitor#CONSTANT_NameAndType} value.
  39.377 +     *
  39.378 +     * @param index an index to a constant pool entry containing a
  39.379 +     *        {@link ConstantPoolVisitor#CONSTANT_NameAndType} value.
  39.380 +     * @param memberName a memberName
  39.381 +     * @param signature a signature
  39.382 +     * @throws IllegalArgumentException if memberName contains the character ';'
  39.383 +     *
  39.384 +     * @see ConstantPoolVisitor#visitDescriptor(int, byte, String, String, int, int)
  39.385 +     */
  39.386 +    public void putDescriptor(int index, String memberName, String signature) {
  39.387 +        checkTag(index, CONSTANT_NameAndType);
  39.388 +        checkMemberName(memberName);
  39.389 +        patchArray[index] = addSemis(memberName, signature);
  39.390 +    }
  39.391 +
  39.392 +    /** Set the entry of the constant pool indexed by index to
  39.393 +     *  a new {@link ConstantPoolVisitor#CONSTANT_Fieldref},
  39.394 +     *  {@link ConstantPoolVisitor#CONSTANT_Methodref}, or
  39.395 +     *  {@link ConstantPoolVisitor#CONSTANT_InterfaceMethodref} value.
  39.396 +     *
  39.397 +     * @param index an index to a constant pool entry containing a member reference
  39.398 +     * @param className a class name
  39.399 +     * @param memberName a field or method name
  39.400 +     * @param signature a field or method signature
  39.401 +     * @throws IllegalArgumentException if memberName contains the character ';'
  39.402 +     *             or signature is not a correct signature
  39.403 +     *
  39.404 +     * @see ConstantPoolVisitor#visitMemberRef(int, byte, String, String, String, int, int)
  39.405 +     */
  39.406 +    public void putMemberRef(int index, byte tag,
  39.407 +                    String className, String memberName, String signature) {
  39.408 +        checkTagMask(tag, CONSTANT_MemberRef_MASK);
  39.409 +        checkTag(index, tag);
  39.410 +        checkClassName(className);
  39.411 +        checkMemberName(memberName);
  39.412 +        if (signature.startsWith("(") == (tag == CONSTANT_Fieldref))
  39.413 +            throw new IllegalArgumentException("bad signature: "+signature);
  39.414 +        patchArray[index] = addSemis(className, memberName, signature);
  39.415 +    }
  39.416 +
  39.417 +    static private final int CONSTANT_MemberRef_MASK =
  39.418 +              CONSTANT_Fieldref
  39.419 +            | CONSTANT_Methodref
  39.420 +            | CONSTANT_InterfaceMethodref;
  39.421 +
  39.422 +    private static final Map<Class<?>, Byte> CONSTANT_VALUE_CLASS_TAG
  39.423 +        = new IdentityHashMap<Class<?>, Byte>();
  39.424 +    private static final Class<?>[] CONSTANT_VALUE_CLASS = new Class<?>[16];
  39.425 +    static {
  39.426 +        Object[][] values = {
  39.427 +            {Integer.class, CONSTANT_Integer},
  39.428 +            {Long.class, CONSTANT_Long},
  39.429 +            {Float.class, CONSTANT_Float},
  39.430 +            {Double.class, CONSTANT_Double},
  39.431 +            {String.class, CONSTANT_String},
  39.432 +            {Class.class, CONSTANT_Class}
  39.433 +        };
  39.434 +        for (Object[] value : values) {
  39.435 +            Class<?> cls = (Class<?>)value[0];
  39.436 +            Byte     tag = (Byte) value[1];
  39.437 +            CONSTANT_VALUE_CLASS_TAG.put(cls, tag);
  39.438 +            CONSTANT_VALUE_CLASS[(byte)tag] = cls;
  39.439 +        }
  39.440 +    }
  39.441 +
  39.442 +    static Class<?> classForTag(byte tag) {
  39.443 +        if ((tag & 0xFF) >= CONSTANT_VALUE_CLASS.length)
  39.444 +            return null;
  39.445 +        return CONSTANT_VALUE_CLASS[tag];
  39.446 +    }
  39.447 +
  39.448 +    static byte tagForConstant(Class<?> cls) {
  39.449 +        Byte tag = CONSTANT_VALUE_CLASS_TAG.get(cls);
  39.450 +        return (tag == null) ? CONSTANT_None : (byte)tag;
  39.451 +    }
  39.452 +
  39.453 +    private static void checkClassName(String className) {
  39.454 +        if (className.indexOf('/') >= 0 || className.indexOf(';') >= 0)
  39.455 +            throw new IllegalArgumentException("invalid class name " + className);
  39.456 +    }
  39.457 +
  39.458 +    static String addSemis(String name, String... names) {
  39.459 +        StringBuilder buf = new StringBuilder(name.length() * 5);
  39.460 +        buf.append(name);
  39.461 +        for (String name2 : names) {
  39.462 +            buf.append(';').append(name2);
  39.463 +        }
  39.464 +        String res = buf.toString();
  39.465 +        assert(stripSemis(names.length, res)[0].equals(name));
  39.466 +        assert(stripSemis(names.length, res)[1].equals(names[0]));
  39.467 +        assert(names.length == 1 ||
  39.468 +               stripSemis(names.length, res)[2].equals(names[1]));
  39.469 +        return res;
  39.470 +    }
  39.471 +
  39.472 +    static String[] stripSemis(int count, String string) {
  39.473 +        String[] res = new String[count+1];
  39.474 +        int pos = 0;
  39.475 +        for (int i = 0; i < count; i++) {
  39.476 +            int pos2 = string.indexOf(';', pos);
  39.477 +            if (pos2 < 0)  pos2 = string.length();  // yuck
  39.478 +            res[i] = string.substring(pos, pos2);
  39.479 +            pos = pos2;
  39.480 +        }
  39.481 +        res[count] = string.substring(pos);
  39.482 +        return res;
  39.483 +    }
  39.484 +
  39.485 +    public String toString() {
  39.486 +        StringBuilder buf = new StringBuilder(this.getClass().getName());
  39.487 +        buf.append("{");
  39.488 +        Object[] origCP = null;
  39.489 +        for (int i = 0; i < patchArray.length; i++) {
  39.490 +            if (patchArray[i] == null)  continue;
  39.491 +            if (origCP != null) {
  39.492 +                buf.append(", ");
  39.493 +            } else {
  39.494 +                try {
  39.495 +                    origCP = getOriginalCP();
  39.496 +                } catch (InvalidConstantPoolFormatException ee) {
  39.497 +                    origCP = new Object[0];
  39.498 +                }
  39.499 +            }
  39.500 +            Object orig = (i < origCP.length) ? origCP[i] : "?";
  39.501 +            buf.append(orig).append("=").append(patchArray[i]);
  39.502 +        }
  39.503 +        buf.append("}");
  39.504 +        return buf.toString();
  39.505 +    }
  39.506 +}
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/rt/emul/compact/src/main/java/sun/invoke/anon/ConstantPoolVisitor.java	Sat Aug 09 11:12:05 2014 +0200
    40.3 @@ -0,0 +1,192 @@
    40.4 +/*
    40.5 + * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
    40.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    40.7 + *
    40.8 + * This code is free software; you can redistribute it and/or modify it
    40.9 + * under the terms of the GNU General Public License version 2 only, as
   40.10 + * published by the Free Software Foundation.  Oracle designates this
   40.11 + * particular file as subject to the "Classpath" exception as provided
   40.12 + * by Oracle in the LICENSE file that accompanied this code.
   40.13 + *
   40.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   40.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   40.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   40.17 + * version 2 for more details (a copy is included in the LICENSE file that
   40.18 + * accompanied this code).
   40.19 + *
   40.20 + * You should have received a copy of the GNU General Public License version
   40.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   40.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   40.23 + *
   40.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   40.25 + * or visit www.oracle.com if you need additional information or have any
   40.26 + * questions.
   40.27 + */
   40.28 +
   40.29 +package sun.invoke.anon;
   40.30 +
   40.31 +/**
   40.32 + * A visitor called by {@link ConstantPoolParser#parse(ConstantPoolVisitor)}
   40.33 + * when a constant pool entry is parsed.
   40.34 + * <p>
   40.35 + * A visit* method is called when a constant pool entry is parsed.
   40.36 + * The first argument is always the constant pool index.
   40.37 + * The second argument is always the constant pool tag,
   40.38 + * even for methods like {@link #visitUTF8(int, byte, String)} which only apply to one tag.
   40.39 + * String arguments refer to Utf8 or NameAndType entries declared elsewhere,
   40.40 + * and are always accompanied by the indexes of those entries.
   40.41 + * <p>
   40.42 + * The order of the calls to the visit* methods is not necessarily related
   40.43 + * to the order of the entries in the constant pool.
   40.44 + * If one entry has a reference to another entry, the latter (lower-level)
   40.45 + * entry will be visited first.
   40.46 + * <p>
   40.47 + * The following table shows the relation between constant pool entry
   40.48 + * types and the corresponding visit* methods:
   40.49 + *
   40.50 + * <table border=1 cellpadding=5 summary="constant pool visitor methods">
   40.51 + * <tr><th>Tag(s)</th><th>Method</th></tr>
   40.52 + * <tr>
   40.53 + *   <td>{@link #CONSTANT_Utf8}</td>
   40.54 + *   <td>{@link #visitUTF8(int, byte, String)}</td>
   40.55 + * </tr><tr>
   40.56 + *   <td>{@link #CONSTANT_Integer}, {@link #CONSTANT_Float},
   40.57 + *       {@link #CONSTANT_Long}, {@link #CONSTANT_Double}</td>
   40.58 + *   <td>{@link #visitConstantValue(int, byte, Object)}</td>
   40.59 + * </tr><tr>
   40.60 + *   <td>{@link #CONSTANT_String}, {@link #CONSTANT_Class}</td>
   40.61 + *   <td>{@link #visitConstantString(int, byte, String, int)}</td>
   40.62 + * </tr><tr>
   40.63 + *   <td>{@link #CONSTANT_NameAndType}</td>
   40.64 + *   <td>{@link #visitDescriptor(int, byte, String, String, int, int)}</td>
   40.65 + * </tr><tr>
   40.66 + *   <td>{@link #CONSTANT_Fieldref},
   40.67 + *       {@link #CONSTANT_Methodref},
   40.68 + *       {@link #CONSTANT_InterfaceMethodref}</td>
   40.69 + *   <td>{@link #visitMemberRef(int, byte, String, String, String, int, int)}</td>
   40.70 + * </tr>
   40.71 + * </table>
   40.72 + *
   40.73 + * @see ConstantPoolPatch
   40.74 + * @author Remi Forax
   40.75 + * @author jrose
   40.76 + */
   40.77 +public class ConstantPoolVisitor {
   40.78 +  /** Called each time an UTF8 constant pool entry is found.
   40.79 +   * @param index the constant pool index
   40.80 +   * @param tag always {@link #CONSTANT_Utf8}
   40.81 +   * @param utf8 string encoded in modified UTF-8 format passed as a {@code String}
   40.82 +   *
   40.83 +   * @see ConstantPoolPatch#putUTF8(int, String)
   40.84 +   */
   40.85 +  public void visitUTF8(int index, byte tag, String utf8) {
   40.86 +    // do nothing
   40.87 +  }
   40.88 +
   40.89 +  /** Called for each constant pool entry that encodes an integer,
   40.90 +   *  a float, a long, or a double.
   40.91 +   *  Constant strings and classes are not managed by this method but
   40.92 +   *  by {@link #visitConstantString(int, byte, String, int)}.
   40.93 +   *
   40.94 +   * @param index the constant pool index
   40.95 +   * @param tag one of {@link #CONSTANT_Integer},
   40.96 +   *            {@link #CONSTANT_Float},
   40.97 +   *            {@link #CONSTANT_Long},
   40.98 +   *            or {@link #CONSTANT_Double}
   40.99 +   * @param value encoded value
  40.100 +   *
  40.101 +   * @see ConstantPoolPatch#putConstantValue(int, Object)
  40.102 +   */
  40.103 +  public void visitConstantValue(int index, byte tag, Object value) {
  40.104 +    // do nothing
  40.105 +  }
  40.106 +
  40.107 +  /** Called for each constant pool entry that encodes a string or a class.
  40.108 +   * @param index the constant pool index
  40.109 +   * @param tag one of {@link #CONSTANT_String},
  40.110 +   *            {@link #CONSTANT_Class},
  40.111 +   * @param name string body or class name (using dot separator)
  40.112 +   * @param nameIndex the index of the Utf8 string for the name
  40.113 +   *
  40.114 +   * @see ConstantPoolPatch#putConstantValue(int, byte, Object)
  40.115 +   */
  40.116 +  public void visitConstantString(int index, byte tag,
  40.117 +                                  String name, int nameIndex) {
  40.118 +    // do nothing
  40.119 +  }
  40.120 +
  40.121 +  /** Called for each constant pool entry that encodes a name and type.
  40.122 +   * @param index the constant pool index
  40.123 +   * @param tag always {@link #CONSTANT_NameAndType}
  40.124 +   * @param memberName a field or method name
  40.125 +   * @param signature the member signature
  40.126 +   * @param memberNameIndex index of the Utf8 string for the member name
  40.127 +   * @param signatureIndex index of the Utf8 string for the signature
  40.128 +   *
  40.129 +   * @see ConstantPoolPatch#putDescriptor(int, String, String)
  40.130 +   */
  40.131 +  public void visitDescriptor(int index, byte tag,
  40.132 +                              String memberName, String signature,
  40.133 +                              int memberNameIndex, int signatureIndex) {
  40.134 +    // do nothing
  40.135 +  }
  40.136 +
  40.137 +  /** Called for each constant pool entry that encodes a field or method.
  40.138 +   * @param index the constant pool index
  40.139 +   * @param tag one of {@link #CONSTANT_Fieldref},
  40.140 +   *            or {@link #CONSTANT_Methodref},
  40.141 +   *            or {@link #CONSTANT_InterfaceMethodref}
  40.142 +   * @param className the class name (using dot separator)
  40.143 +   * @param memberName name of the field or method
  40.144 +   * @param signature the field or method signature
  40.145 +   * @param classNameIndex index of the Utf8 string for the class name
  40.146 +   * @param descriptorIndex index of the NameAndType descriptor constant
  40.147 +   *
  40.148 +   * @see ConstantPoolPatch#putMemberRef(int, byte, String, String, String)
  40.149 +   */
  40.150 +  public void visitMemberRef(int index, byte tag,
  40.151 +                             String className, String memberName, String signature,
  40.152 +                             int classNameIndex, int descriptorIndex) {
  40.153 +    // do nothing
  40.154 +  }
  40.155 +
  40.156 +    public static final byte
  40.157 +      CONSTANT_None = 0,
  40.158 +      CONSTANT_Utf8 = 1,
  40.159 +      //CONSTANT_Unicode = 2,               /* unused */
  40.160 +      CONSTANT_Integer = 3,
  40.161 +      CONSTANT_Float = 4,
  40.162 +      CONSTANT_Long = 5,
  40.163 +      CONSTANT_Double = 6,
  40.164 +      CONSTANT_Class = 7,
  40.165 +      CONSTANT_String = 8,
  40.166 +      CONSTANT_Fieldref = 9,
  40.167 +      CONSTANT_Methodref = 10,
  40.168 +      CONSTANT_InterfaceMethodref = 11,
  40.169 +      CONSTANT_NameAndType = 12;
  40.170 +
  40.171 +    private static String[] TAG_NAMES = {
  40.172 +        "Empty",
  40.173 +        "Utf8",
  40.174 +        null, //"Unicode",
  40.175 +        "Integer",
  40.176 +        "Float",
  40.177 +        "Long",
  40.178 +        "Double",
  40.179 +        "Class",
  40.180 +        "String",
  40.181 +        "Fieldref",
  40.182 +        "Methodref",
  40.183 +        "InterfaceMethodref",
  40.184 +        "NameAndType"
  40.185 +    };
  40.186 +
  40.187 +    public static String tagName(byte tag) {
  40.188 +        String name = null;
  40.189 +        if ((tag & 0xFF) < TAG_NAMES.length)
  40.190 +            name = TAG_NAMES[tag];
  40.191 +        if (name == null)
  40.192 +            name = "Unknown#"+(tag&0xFF);
  40.193 +        return name;
  40.194 +    }
  40.195 +}
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/rt/emul/compact/src/main/java/sun/invoke/anon/InvalidConstantPoolFormatException.java	Sat Aug 09 11:12:05 2014 +0200
    41.3 @@ -0,0 +1,45 @@
    41.4 +/*
    41.5 + * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
    41.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    41.7 + *
    41.8 + * This code is free software; you can redistribute it and/or modify it
    41.9 + * under the terms of the GNU General Public License version 2 only, as
   41.10 + * published by the Free Software Foundation.  Oracle designates this
   41.11 + * particular file as subject to the "Classpath" exception as provided
   41.12 + * by Oracle in the LICENSE file that accompanied this code.
   41.13 + *
   41.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   41.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   41.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   41.17 + * version 2 for more details (a copy is included in the LICENSE file that
   41.18 + * accompanied this code).
   41.19 + *
   41.20 + * You should have received a copy of the GNU General Public License version
   41.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   41.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   41.23 + *
   41.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   41.25 + * or visit www.oracle.com if you need additional information or have any
   41.26 + * questions.
   41.27 + */
   41.28 +
   41.29 +package sun.invoke.anon;
   41.30 +
   41.31 +/** Exception used when there is an error in the constant pool
   41.32 + *  format.
   41.33 + */
   41.34 +public class InvalidConstantPoolFormatException extends Exception {
   41.35 +    private static final long serialVersionUID=-6103888330523770949L;
   41.36 +
   41.37 +    public InvalidConstantPoolFormatException(String message,Throwable cause) {
   41.38 +        super(message,cause);
   41.39 +    }
   41.40 +
   41.41 +    public InvalidConstantPoolFormatException(String message) {
   41.42 +        super(message);
   41.43 +    }
   41.44 +
   41.45 +    public InvalidConstantPoolFormatException(Throwable cause) {
   41.46 +        super(cause);
   41.47 +    }
   41.48 +}
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/rt/emul/compact/src/main/java/sun/invoke/empty/Empty.java	Sat Aug 09 11:12:05 2014 +0200
    42.3 @@ -0,0 +1,40 @@
    42.4 +/*
    42.5 + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
    42.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    42.7 + *
    42.8 + * This code is free software; you can redistribute it and/or modify it
    42.9 + * under the terms of the GNU General Public License version 2 only, as
   42.10 + * published by the Free Software Foundation.  Oracle designates this
   42.11 + * particular file as subject to the "Classpath" exception as provided
   42.12 + * by Oracle in the LICENSE file that accompanied this code.
   42.13 + *
   42.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   42.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   42.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   42.17 + * version 2 for more details (a copy is included in the LICENSE file that
   42.18 + * accompanied this code).
   42.19 + *
   42.20 + * You should have received a copy of the GNU General Public License version
   42.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   42.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   42.23 + *
   42.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   42.25 + * or visit www.oracle.com if you need additional information or have any
   42.26 + * questions.
   42.27 + */
   42.28 +
   42.29 +package sun.invoke.empty;
   42.30 +
   42.31 +/**
   42.32 + * An empty class in an empty package.
   42.33 + * Used as a proxy for unprivileged code, since making access checks
   42.34 + * against it will only succeed against public methods in public types.
   42.35 + * <p>
   42.36 + * This class also stands (internally to sun.invoke) for the type of a
   42.37 + * value that cannot be produced, because the expression of this type
   42.38 + * always returns abnormally.  (Cf. Nothing in the closures proposal.)
   42.39 + * @author jrose
   42.40 + */
   42.41 +public class Empty {
   42.42 +    private Empty() { throw new InternalError(); }
   42.43 +}
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/rt/emul/compact/src/main/java/sun/invoke/package-info.java	Sat Aug 09 11:12:05 2014 +0200
    43.3 @@ -0,0 +1,31 @@
    43.4 +/*
    43.5 + * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
    43.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    43.7 + *
    43.8 + * This code is free software; you can redistribute it and/or modify it
    43.9 + * under the terms of the GNU General Public License version 2 only, as
   43.10 + * published by the Free Software Foundation.  Oracle designates this
   43.11 + * particular file as subject to the "Classpath" exception as provided
   43.12 + * by Oracle in the LICENSE file that accompanied this code.
   43.13 + *
   43.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   43.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   43.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   43.17 + * version 2 for more details (a copy is included in the LICENSE file that
   43.18 + * accompanied this code).
   43.19 + *
   43.20 + * You should have received a copy of the GNU General Public License version
   43.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   43.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   43.23 + *
   43.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   43.25 + * or visit www.oracle.com if you need additional information or have any
   43.26 + * questions.
   43.27 + */
   43.28 +
   43.29 +/**
   43.30 + * Implementation details for JSR 292 RI, package java.lang.invoke.
   43.31 + * @author jrose
   43.32 + */
   43.33 +
   43.34 +package sun.invoke;
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/rt/emul/compact/src/main/java/sun/invoke/util/BytecodeDescriptor.java	Sat Aug 09 11:12:05 2014 +0200
    44.3 @@ -0,0 +1,137 @@
    44.4 +/*
    44.5 + * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
    44.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    44.7 + *
    44.8 + * This code is free software; you can redistribute it and/or modify it
    44.9 + * under the terms of the GNU General Public License version 2 only, as
   44.10 + * published by the Free Software Foundation.  Oracle designates this
   44.11 + * particular file as subject to the "Classpath" exception as provided
   44.12 + * by Oracle in the LICENSE file that accompanied this code.
   44.13 + *
   44.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   44.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   44.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   44.17 + * version 2 for more details (a copy is included in the LICENSE file that
   44.18 + * accompanied this code).
   44.19 + *
   44.20 + * You should have received a copy of the GNU General Public License version
   44.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   44.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   44.23 + *
   44.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   44.25 + * or visit www.oracle.com if you need additional information or have any
   44.26 + * questions.
   44.27 + */
   44.28 +
   44.29 +package sun.invoke.util;
   44.30 +
   44.31 +import java.lang.invoke.MethodType;
   44.32 +import java.util.ArrayList;
   44.33 +import java.util.List;
   44.34 +
   44.35 +/**
   44.36 + * Utility routines for dealing with bytecode-level signatures.
   44.37 + * @author jrose
   44.38 + */
   44.39 +public class BytecodeDescriptor {
   44.40 +
   44.41 +    private BytecodeDescriptor() { }  // cannot instantiate
   44.42 +
   44.43 +    public static List<Class<?>> parseMethod(String bytecodeSignature, ClassLoader loader) {
   44.44 +        return parseMethod(bytecodeSignature, 0, bytecodeSignature.length(), loader);
   44.45 +    }
   44.46 +
   44.47 +    static List<Class<?>> parseMethod(String bytecodeSignature,
   44.48 +            int start, int end, ClassLoader loader) {
   44.49 +        if (loader == null)
   44.50 +            loader = ClassLoader.getSystemClassLoader();
   44.51 +        String str = bytecodeSignature;
   44.52 +        int[] i = {start};
   44.53 +        ArrayList<Class<?>> ptypes = new ArrayList<Class<?>>();
   44.54 +        if (i[0] < end && str.charAt(i[0]) == '(') {
   44.55 +            ++i[0];  // skip '('
   44.56 +            while (i[0] < end && str.charAt(i[0]) != ')') {
   44.57 +                Class<?> pt = parseSig(str, i, end, loader);
   44.58 +                if (pt == null || pt == void.class)
   44.59 +                    parseError(str, "bad argument type");
   44.60 +                ptypes.add(pt);
   44.61 +            }
   44.62 +            ++i[0];  // skip ')'
   44.63 +        } else {
   44.64 +            parseError(str, "not a method type");
   44.65 +        }
   44.66 +        Class<?> rtype = parseSig(str, i, end, loader);
   44.67 +        if (rtype == null || i[0] != end)
   44.68 +            parseError(str, "bad return type");
   44.69 +        ptypes.add(rtype);
   44.70 +        return ptypes;
   44.71 +    }
   44.72 +
   44.73 +    static private void parseError(String str, String msg) {
   44.74 +        throw new IllegalArgumentException("bad signature: "+str+": "+msg);
   44.75 +    }
   44.76 +
   44.77 +    static private Class<?> parseSig(String str, int[] i, int end, ClassLoader loader) {
   44.78 +        if (i[0] == end)  return null;
   44.79 +        char c = str.charAt(i[0]++);
   44.80 +        if (c == 'L') {
   44.81 +            int begc = i[0], endc = str.indexOf(';', begc);
   44.82 +            if (endc < 0)  return null;
   44.83 +            i[0] = endc+1;
   44.84 +            String name = str.substring(begc, endc).replace('/', '.');
   44.85 +            try {
   44.86 +                return loader.loadClass(name);
   44.87 +            } catch (ClassNotFoundException ex) {
   44.88 +                throw new TypeNotPresentException(name, ex);
   44.89 +            }
   44.90 +        } else if (c == '[') {
   44.91 +            Class<?> t = parseSig(str, i, end, loader);
   44.92 +            if (t != null)
   44.93 +                t = java.lang.reflect.Array.newInstance(t, 0).getClass();
   44.94 +            return t;
   44.95 +        } else {
   44.96 +            return Wrapper.forBasicType(c).primitiveType();
   44.97 +        }
   44.98 +    }
   44.99 +
  44.100 +    public static String unparse(Class<?> type) {
  44.101 +        StringBuilder sb = new StringBuilder();
  44.102 +        unparseSig(type, sb);
  44.103 +        return sb.toString();
  44.104 +    }
  44.105 +
  44.106 +    public static String unparse(MethodType type) {
  44.107 +        return unparseMethod(type.returnType(), type.parameterList());
  44.108 +    }
  44.109 +
  44.110 +    public static String unparse(Object type) {
  44.111 +        if (type instanceof Class<?>)
  44.112 +            return unparse((Class<?>) type);
  44.113 +        if (type instanceof MethodType)
  44.114 +            return unparse((MethodType) type);
  44.115 +        return (String) type;
  44.116 +    }
  44.117 +
  44.118 +    public static String unparseMethod(Class<?> rtype, List<Class<?>> ptypes) {
  44.119 +        StringBuilder sb = new StringBuilder();
  44.120 +        sb.append('(');
  44.121 +        for (Class<?> pt : ptypes)
  44.122 +            unparseSig(pt, sb);
  44.123 +        sb.append(')');
  44.124 +        unparseSig(rtype, sb);
  44.125 +        return sb.toString();
  44.126 +    }
  44.127 +
  44.128 +    static private void unparseSig(Class<?> t, StringBuilder sb) {
  44.129 +        char c = Wrapper.forBasicType(t).basicTypeChar();
  44.130 +        if (c != 'L') {
  44.131 +            sb.append(c);
  44.132 +        } else {
  44.133 +            boolean lsemi = (!t.isArray());
  44.134 +            if (lsemi)  sb.append('L');
  44.135 +            sb.append(t.getName().replace('.', '/'));
  44.136 +            if (lsemi)  sb.append(';');
  44.137 +        }
  44.138 +    }
  44.139 +
  44.140 +}
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/rt/emul/compact/src/main/java/sun/invoke/util/BytecodeName.java	Sat Aug 09 11:12:05 2014 +0200
    45.3 @@ -0,0 +1,627 @@
    45.4 +/*
    45.5 + * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
    45.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    45.7 + *
    45.8 + * This code is free software; you can redistribute it and/or modify it
    45.9 + * under the terms of the GNU General Public License version 2 only, as
   45.10 + * published by the Free Software Foundation.  Oracle designates this
   45.11 + * particular file as subject to the "Classpath" exception as provided
   45.12 + * by Oracle in the LICENSE file that accompanied this code.
   45.13 + *
   45.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   45.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   45.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   45.17 + * version 2 for more details (a copy is included in the LICENSE file that
   45.18 + * accompanied this code).
   45.19 + *
   45.20 + * You should have received a copy of the GNU General Public License version
   45.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   45.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   45.23 + *
   45.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   45.25 + * or visit www.oracle.com if you need additional information or have any
   45.26 + * questions.
   45.27 + */
   45.28 +
   45.29 +package sun.invoke.util;
   45.30 +
   45.31 +/**
   45.32 + * Utility routines for dealing with bytecode-level names.
   45.33 + * Includes universal mangling rules for the JVM.
   45.34 + *
   45.35 + * <h3>Avoiding Dangerous Characters </h3>
   45.36 + *
   45.37 + * <p>
   45.38 + * The JVM defines a very small set of characters which are illegal
   45.39 + * in name spellings.  We will slightly extend and regularize this set
   45.40 + * into a group of <cite>dangerous characters</cite>.
   45.41 + * These characters will then be replaced, in mangled names, by escape sequences.
   45.42 + * In addition, accidental escape sequences must be further escaped.
   45.43 + * Finally, a special prefix will be applied if and only if
   45.44 + * the mangling would otherwise fail to begin with the escape character.
   45.45 + * This happens to cover the corner case of the null string,
   45.46 + * and also clearly marks symbols which need demangling.
   45.47 + * </p>
   45.48 + * <p>
   45.49 + * Dangerous characters are the union of all characters forbidden
   45.50 + * or otherwise restricted by the JVM specification,
   45.51 + * plus their mates, if they are brackets
   45.52 + * (<code><big><b>[</b></big></code> and <code><big><b>]</b></big></code>,
   45.53 + * <code><big><b>&lt;</b></big></code> and <code><big><b>&gt;</b></big></code>),
   45.54 + * plus, arbitrarily, the colon character <code><big><b>:</b></big></code>.
   45.55 + * There is no distinction between type, method, and field names.
   45.56 + * This makes it easier to convert between mangled names of different
   45.57 + * types, since they do not need to be decoded (demangled).
   45.58 + * </p>
   45.59 + * <p>
   45.60 + * The escape character is backslash <code><big><b>\</b></big></code>
   45.61 + * (also known as reverse solidus).
   45.62 + * This character is, until now, unheard of in bytecode names,
   45.63 + * but traditional in the proposed role.
   45.64 + *
   45.65 + * </p>
   45.66 + * <h3> Replacement Characters </h3>
   45.67 + *
   45.68 + *
   45.69 + * <p>
   45.70 + * Every escape sequence is two characters
   45.71 + * (in fact, two UTF8 bytes) beginning with
   45.72 + * the escape character and followed by a
   45.73 + * <cite>replacement character</cite>.
   45.74 + * (Since the replacement character is never a backslash,
   45.75 + * iterated manglings do not double in size.)
   45.76 + * </p>
   45.77 + * <p>
   45.78 + * Each dangerous character has some rough visual similarity
   45.79 + * to its corresponding replacement character.
   45.80 + * This makes mangled symbols easier to recognize by sight.
   45.81 + * </p>
   45.82 + * <p>
   45.83 + * The dangerous characters are
   45.84 + * <code><big><b>/</b></big></code> (forward slash, used to delimit package components),
   45.85 + * <code><big><b>.</b></big></code> (dot, also a package delimiter),
   45.86 + * <code><big><b>;</b></big></code> (semicolon, used in signatures),
   45.87 + * <code><big><b>$</b></big></code> (dollar, used in inner classes and synthetic members),
   45.88 + * <code><big><b>&lt;</b></big></code> (left angle),
   45.89 + * <code><big><b>&gt;</b></big></code> (right angle),
   45.90 + * <code><big><b>[</b></big></code> (left square bracket, used in array types),
   45.91 + * <code><big><b>]</b></big></code> (right square bracket, reserved in this scheme for language use),
   45.92 + * and <code><big><b>:</b></big></code> (colon, reserved in this scheme for language use).
   45.93 + * Their replacements are, respectively,
   45.94 + * <code><big><b>|</b></big></code> (vertical bar),
   45.95 + * <code><big><b>,</b></big></code> (comma),
   45.96 + * <code><big><b>?</b></big></code> (question mark),
   45.97 + * <code><big><b>%</b></big></code> (percent),
   45.98 + * <code><big><b>^</b></big></code> (caret),
   45.99 + * <code><big><b>_</b></big></code> (underscore), and
  45.100 + * <code><big><b>{</b></big></code> (left curly bracket),
  45.101 + * <code><big><b>}</b></big></code> (right curly bracket),
  45.102 + * <code><big><b>!</b></big></code> (exclamation mark).
  45.103 + * In addition, the replacement character for the escape character itself is
  45.104 + * <code><big><b>-</b></big></code> (hyphen),
  45.105 + * and the replacement character for the null prefix is
  45.106 + * <code><big><b>=</b></big></code> (equal sign).
  45.107 + * </p>
  45.108 + * <p>
  45.109 + * An escape character <code><big><b>\</b></big></code>
  45.110 + * followed by any of these replacement characters
  45.111 + * is an escape sequence, and there are no other escape sequences.
  45.112 + * An equal sign is only part of an escape sequence
  45.113 + * if it is the second character in the whole string, following a backslash.
  45.114 + * Two consecutive backslashes do <em>not</em> form an escape sequence.
  45.115 + * </p>
  45.116 + * <p>
  45.117 + * Each escape sequence replaces a so-called <cite>original character</cite>
  45.118 + * which is either one of the dangerous characters or the escape character.
  45.119 + * A null prefix replaces an initial null string, not a character.
  45.120 + * </p>
  45.121 + * <p>
  45.122 + * All this implies that escape sequences cannot overlap and may be
  45.123 + * determined all at once for a whole string.  Note that a spelling
  45.124 + * string can contain <cite>accidental escapes</cite>, apparent escape
  45.125 + * sequences which must not be interpreted as manglings.
  45.126 + * These are disabled by replacing their leading backslash with an
  45.127 + * escape sequence (<code><big><b>\-</b></big></code>).  To mangle a string, three logical steps
  45.128 + * are required, though they may be carried out in one pass:
  45.129 + * </p>
  45.130 + * <ol>
  45.131 + *   <li>In each accidental escape, replace the backslash with an escape sequence
  45.132 + * (<code><big><b>\-</b></big></code>).</li>
  45.133 + *   <li>Replace each dangerous character with an escape sequence
  45.134 + * (<code><big><b>\|</b></big></code> for <code><big><b>/</b></big></code>, etc.).</li>
  45.135 + *   <li>If the first two steps introduced any change, <em>and</em>
  45.136 + * if the string does not already begin with a backslash, prepend a null prefix (<code><big><b>\=</b></big></code>).</li>
  45.137 + * </ol>
  45.138 + *
  45.139 + * To demangle a mangled string that begins with an escape,
  45.140 + * remove any null prefix, and then replace (in parallel)
  45.141 + * each escape sequence by its original character.
  45.142 + * <p>Spelling strings which contain accidental
  45.143 + * escapes <em>must</em> have them replaced, even if those
  45.144 + * strings do not contain dangerous characters.
  45.145 + * This restriction means that mangling a string always
  45.146 + * requires a scan of the string for escapes.
  45.147 + * But then, a scan would be required anyway,
  45.148 + * to check for dangerous characters.
  45.149 + *
  45.150 + * </p>
  45.151 + * <h3> Nice Properties </h3>
  45.152 + *
  45.153 + * <p>
  45.154 + * If a bytecode name does not contain any escape sequence,
  45.155 + * demangling is a no-op:  The string demangles to itself.
  45.156 + * Such a string is called <cite>self-mangling</cite>.
  45.157 + * Almost all strings are self-mangling.
  45.158 + * In practice, to demangle almost any name &ldquo;found in nature&rdquo;,
  45.159 + * simply verify that it does not begin with a backslash.
  45.160 + * </p>
  45.161 + * <p>
  45.162 + * Mangling is a one-to-one function, while demangling
  45.163 + * is a many-to-one function.
  45.164 + * A mangled string is defined as <cite>validly mangled</cite> if
  45.165 + * it is in fact the unique mangling of its spelling string.
  45.166 + * Three examples of invalidly mangled strings are <code><big><b>\=foo</b></big></code>,
  45.167 + * <code><big><b>\-bar</b></big></code>, and <code><big><b>baz\!</b></big></code>, which demangle to <code><big><b>foo</b></big></code>, <code><big><b>\bar</b></big></code>, and
  45.168 + * <code><big><b>baz\!</b></big></code>, but then remangle to <code><big><b>foo</b></big></code>, <code><big><b>\bar</b></big></code>, and <code><big><b>\=baz\-!</b></big></code>.
  45.169 + * If a language back-end or runtime is using mangled names,
  45.170 + * it should never present an invalidly mangled bytecode
  45.171 + * name to the JVM.  If the runtime encounters one,
  45.172 + * it should also report an error, since such an occurrence
  45.173 + * probably indicates a bug in name encoding which
  45.174 + * will lead to errors in linkage.
  45.175 + * However, this note does not propose that the JVM verifier
  45.176 + * detect invalidly mangled names.
  45.177 + * </p>
  45.178 + * <p>
  45.179 + * As a result of these rules, it is a simple matter to
  45.180 + * compute validly mangled substrings and concatenations
  45.181 + * of validly mangled strings, and (with a little care)
  45.182 + * these correspond to corresponding operations on their
  45.183 + * spelling strings.
  45.184 + * </p>
  45.185 + * <ul>
  45.186 + *   <li>Any prefix of a validly mangled string is also validly mangled,
  45.187 + * although a null prefix may need to be removed.</li>
  45.188 + *   <li>Any suffix of a validly mangled string is also validly mangled,
  45.189 + * although a null prefix may need to be added.</li>
  45.190 + *   <li>Two validly mangled strings, when concatenated,
  45.191 + * are also validly mangled, although any null prefix
  45.192 + * must be removed from the second string,
  45.193 + * and a trailing backslash on the first string may need escaping,
  45.194 + * if it would participate in an accidental escape when followed
  45.195 + * by the first character of the second string.</li>
  45.196 + * </ul>
  45.197 + * <p>If languages that include non-Java symbol spellings use this
  45.198 + * mangling convention, they will enjoy the following advantages:
  45.199 + * </p>
  45.200 + * <ul>
  45.201 + *   <li>They can interoperate via symbols they share in common.</li>
  45.202 + *   <li>Low-level tools, such as backtrace printers, will have readable displays.</li>
  45.203 + *   <li>Future JVM and language extensions can safely use the dangerous characters
  45.204 + * for structuring symbols, but will never interfere with valid spellings.</li>
  45.205 + *   <li>Runtimes and compilers can use standard libraries for mangling and demangling.</li>
  45.206 + *   <li>Occasional transliterations and name composition will be simple and regular,
  45.207 + * for classes, methods, and fields.</li>
  45.208 + *   <li>Bytecode names will continue to be compact.
  45.209 + * When mangled, spellings will at most double in length, either in
  45.210 + * UTF8 or UTF16 format, and most will not change at all.</li>
  45.211 + * </ul>
  45.212 + *
  45.213 + *
  45.214 + * <h3> Suggestions for Human Readable Presentations </h3>
  45.215 + *
  45.216 + *
  45.217 + * <p>
  45.218 + * For human readable displays of symbols,
  45.219 + * it will be better to present a string-like quoted
  45.220 + * representation of the spelling, because JVM users
  45.221 + * are generally familiar with such tokens.
  45.222 + * We suggest using single or double quotes before and after
  45.223 + * mangled symbols which are not valid Java identifiers,
  45.224 + * with quotes, backslashes, and non-printing characters
  45.225 + * escaped as if for literals in the Java language.
  45.226 + * </p>
  45.227 + * <p>
  45.228 + * For example, an HTML-like spelling
  45.229 + * <code><big><b>&lt;pre&gt;</b></big></code> mangles to
  45.230 + * <code><big><b>\^pre\_</b></big></code> and could
  45.231 + * display more cleanly as
  45.232 + * <code><big><b>'&lt;pre&gt;'</b></big></code>,
  45.233 + * with the quotes included.
  45.234 + * Such string-like conventions are <em>not</em> suitable
  45.235 + * for mangled bytecode names, in part because
  45.236 + * dangerous characters must be eliminated, rather
  45.237 + * than just quoted.  Otherwise internally structured
  45.238 + * strings like package prefixes and method signatures
  45.239 + * could not be reliably parsed.
  45.240 + * </p>
  45.241 + * <p>
  45.242 + * In such human-readable displays, invalidly mangled
  45.243 + * names should <em>not</em> be demangled and quoted,
  45.244 + * for this would be misleading.  Likewise, JVM symbols
  45.245 + * which contain dangerous characters (like dots in field
  45.246 + * names or brackets in method names) should not be
  45.247 + * simply quoted.  The bytecode names
  45.248 + * <code><big><b>\=phase\,1</b></big></code> and
  45.249 + * <code><big><b>phase.1</b></big></code> are distinct,
  45.250 + * and in demangled displays they should be presented as
  45.251 + * <code><big><b>'phase.1'</b></big></code> and something like
  45.252 + * <code><big><b>'phase'.1</b></big></code>, respectively.
  45.253 + * </p>
  45.254 + *
  45.255 + * @author John Rose
  45.256 + * @version 1.2, 02/06/2008
  45.257 + * @see http://blogs.sun.com/jrose/entry/symbolic_freedom_in_the_vm
  45.258 + */
  45.259 +public class BytecodeName {
  45.260 +    private BytecodeName() { }  // static only class
  45.261 +
  45.262 +    /** Given a source name, produce the corresponding bytecode name.
  45.263 +     * The source name should not be qualified, because any syntactic
  45.264 +     * markers (dots, slashes, dollar signs, colons, etc.) will be mangled.
  45.265 +     * @param s the source name
  45.266 +     * @return a valid bytecode name which represents the source name
  45.267 +     */
  45.268 +    public static String toBytecodeName(String s) {
  45.269 +        String bn = mangle(s);
  45.270 +        assert((Object)bn == s || looksMangled(bn)) : bn;
  45.271 +        assert(s.equals(toSourceName(bn))) : s;
  45.272 +        return bn;
  45.273 +    }
  45.274 +
  45.275 +    /** Given an unqualified bytecode name, produce the corresponding source name.
  45.276 +     * The bytecode name must not contain dangerous characters.
  45.277 +     * In particular, it must not be qualified or segmented by colon {@code ':'}.
  45.278 +     * @param s the bytecode name
  45.279 +     * @return the source name, which may possibly have unsafe characters
  45.280 +     * @throws IllegalArgumentException if the bytecode name is not {@link #isSafeBytecodeName safe}
  45.281 +     * @see #isSafeBytecodeName(java.lang.String)
  45.282 +     */
  45.283 +    public static String toSourceName(String s) {
  45.284 +        checkSafeBytecodeName(s);
  45.285 +        String sn = s;
  45.286 +        if (looksMangled(s)) {
  45.287 +            sn = demangle(s);
  45.288 +            assert(s.equals(mangle(sn))) : s+" => "+sn+" => "+mangle(sn);
  45.289 +        }
  45.290 +        return sn;
  45.291 +    }
  45.292 +
  45.293 +    /**
  45.294 +     * Given a bytecode name from a classfile, separate it into
  45.295 +     * components delimited by dangerous characters.
  45.296 +     * Each resulting array element will be either a dangerous character,
  45.297 +     * or else a safe bytecode name.
  45.298 +     * (The safe name might possibly be mangled to hide further dangerous characters.)
  45.299 +     * For example, the qualified class name {@code java/lang/String}
  45.300 +     * will be parsed into the array {@code {"java", '/', "lang", '/', "String"}}.
  45.301 +     * The name {@code &lt;init&gt;} will be parsed into { '&lt;', "init", '&gt;'}}
  45.302 +     * The name {@code foo/bar$:baz} will be parsed into
  45.303 +     * {@code {"foo", '/', "bar", '$', ':', "baz"}}.
  45.304 +     * The name {@code ::\=:foo:\=bar\!baz} will be parsed into
  45.305 +     * {@code {':', ':', "", ':', "foo", ':', "bar:baz"}}.
  45.306 +     */
  45.307 +    public static Object[] parseBytecodeName(String s) {
  45.308 +        int slen = s.length();
  45.309 +        Object[] res = null;
  45.310 +        for (int pass = 0; pass <= 1; pass++) {
  45.311 +            int fillp = 0;
  45.312 +            int lasti = 0;
  45.313 +            for (int i = 0; i <= slen; i++) {
  45.314 +                int whichDC = -1;
  45.315 +                if (i < slen) {
  45.316 +                    whichDC = DANGEROUS_CHARS.indexOf(s.charAt(i));
  45.317 +                    if (whichDC < DANGEROUS_CHAR_FIRST_INDEX)  continue;
  45.318 +                }
  45.319 +                // got to end of string or next dangerous char
  45.320 +                if (lasti < i) {
  45.321 +                    // normal component
  45.322 +                    if (pass != 0)
  45.323 +                        res[fillp] = toSourceName(s.substring(lasti, i));
  45.324 +                    fillp++;
  45.325 +                    lasti = i+1;
  45.326 +                }
  45.327 +                if (whichDC >= DANGEROUS_CHAR_FIRST_INDEX) {
  45.328 +                    if (pass != 0)
  45.329 +                        res[fillp] = DANGEROUS_CHARS_CA[whichDC];
  45.330 +                    fillp++;
  45.331 +                    lasti = i+1;
  45.332 +                }
  45.333 +            }
  45.334 +            if (pass != 0)  break;
  45.335 +            // between passes, build the result array
  45.336 +            res = new Object[fillp];
  45.337 +            if (fillp <= 1 && lasti == 0) {
  45.338 +                if (fillp != 0)  res[0] = toSourceName(s);
  45.339 +                break;
  45.340 +            }
  45.341 +        }
  45.342 +        return res;
  45.343 +    }
  45.344 +
  45.345 +    /**
  45.346 +     * Given a series of components, create a bytecode name for a classfile.
  45.347 +     * This is the inverse of {@link #parseBytecodeName(java.lang.String)}.
  45.348 +     * Each component must either be an interned one-character string of
  45.349 +     * a dangerous character, or else a safe bytecode name.
  45.350 +     * @param components a series of name components
  45.351 +     * @return the concatenation of all components
  45.352 +     * @throws IllegalArgumentException if any component contains an unsafe
  45.353 +     *          character, and is not an interned one-character string
  45.354 +     * @throws NullPointerException if any component is null
  45.355 +     */
  45.356 +    public static String unparseBytecodeName(Object[] components) {
  45.357 +        Object[] components0 = components;
  45.358 +        for (int i = 0; i < components.length; i++) {
  45.359 +            Object c = components[i];
  45.360 +            if (c instanceof String) {
  45.361 +                String mc = toBytecodeName((String) c);
  45.362 +                if (i == 0 && components.length == 1)
  45.363 +                    return mc;  // usual case
  45.364 +                if ((Object)mc != c) {
  45.365 +                    if (components == components0)
  45.366 +                        components = components.clone();
  45.367 +                    components[i] = c = mc;
  45.368 +                }
  45.369 +            }
  45.370 +        }
  45.371 +        return appendAll(components);
  45.372 +    }
  45.373 +    private static String appendAll(Object[] components) {
  45.374 +        if (components.length <= 1) {
  45.375 +            if (components.length == 1) {
  45.376 +                return String.valueOf(components[0]);
  45.377 +            }
  45.378 +            return "";
  45.379 +        }
  45.380 +        int slen = 0;
  45.381 +        for (Object c : components) {
  45.382 +            if (c instanceof String)
  45.383 +                slen += String.valueOf(c).length();
  45.384 +            else
  45.385 +                slen += 1;
  45.386 +        }
  45.387 +        StringBuilder sb = new StringBuilder(slen);
  45.388 +        for (Object c : components) {
  45.389 +            sb.append(c);
  45.390 +        }
  45.391 +        return sb.toString();
  45.392 +    }
  45.393 +
  45.394 +    /**
  45.395 +     * Given a bytecode name, produce the corresponding display name.
  45.396 +     * This is the source name, plus quotes if needed.
  45.397 +     * If the bytecode name contains dangerous characters,
  45.398 +     * assume that they are being used as punctuation,
  45.399 +     * and pass them through unchanged.
  45.400 +     * Non-empty runs of non-dangerous characters are demangled
  45.401 +     * if necessary, and the resulting names are quoted if
  45.402 +     * they are not already valid Java identifiers, or if
  45.403 +     * they contain a dangerous character (i.e., dollar sign "$").
  45.404 +     * Single quotes are used when quoting.
  45.405 +     * Within quoted names, embedded single quotes and backslashes
  45.406 +     * are further escaped by prepended backslashes.
  45.407 +     *
  45.408 +     * @param s the original bytecode name (which may be qualified)
  45.409 +     * @return a human-readable presentation
  45.410 +     */
  45.411 +    public static String toDisplayName(String s) {
  45.412 +        Object[] components = parseBytecodeName(s);
  45.413 +        for (int i = 0; i < components.length; i++) {
  45.414 +            if (!(components[i] instanceof String))
  45.415 +                continue;
  45.416 +            String sn = (String) components[i];
  45.417 +            // note that the name is already demangled!
  45.418 +            //sn = toSourceName(sn);
  45.419 +            if (!isJavaIdent(sn) || sn.indexOf('$') >=0 ) {
  45.420 +                components[i] = quoteDisplay(sn);
  45.421 +            }
  45.422 +        }
  45.423 +        return appendAll(components);
  45.424 +    }
  45.425 +    private static boolean isJavaIdent(String s) {
  45.426 +        int slen = s.length();
  45.427 +        if (slen == 0)  return false;
  45.428 +        if (!Character.isJavaIdentifierStart(s.charAt(0)))
  45.429 +            return false;
  45.430 +        for (int i = 1; i < slen; i++) {
  45.431 +            if (!Character.isJavaIdentifierPart(s.charAt(i)))
  45.432 +                return false;
  45.433 +        }
  45.434 +        return true;
  45.435 +    }
  45.436 +    private static String quoteDisplay(String s) {
  45.437 +        // TO DO:  Replace wierd characters in s by C-style escapes.
  45.438 +        return "'"+s.replaceAll("['\\\\]", "\\\\$0")+"'";
  45.439 +    }
  45.440 +
  45.441 +    private static void checkSafeBytecodeName(String s)
  45.442 +            throws IllegalArgumentException {
  45.443 +        if (!isSafeBytecodeName(s)) {
  45.444 +            throw new IllegalArgumentException(s);
  45.445 +        }
  45.446 +    }
  45.447 +
  45.448 +    /**
  45.449 +     * Report whether a simple name is safe as a bytecode name.
  45.450 +     * Such names are acceptable in class files as class, method, and field names.
  45.451 +     * Additionally, they are free of "dangerous" characters, even if those
  45.452 +     * characters are legal in some (or all) names in class files.
  45.453 +     * @param s the proposed bytecode name
  45.454 +     * @return true if the name is non-empty and all of its characters are safe
  45.455 +     */
  45.456 +    public static boolean isSafeBytecodeName(String s) {
  45.457 +        if (s.length() == 0)  return false;
  45.458 +        // check occurrences of each DANGEROUS char
  45.459 +        for (char xc : DANGEROUS_CHARS_A) {
  45.460 +            if (xc == ESCAPE_C)  continue;  // not really that dangerous
  45.461 +            if (s.indexOf(xc) >= 0)  return false;
  45.462 +        }
  45.463 +        return true;
  45.464 +    }
  45.465 +
  45.466 +    /**
  45.467 +     * Report whether a character is safe in a bytecode name.
  45.468 +     * This is true of any unicode character except the following
  45.469 +     * <em>dangerous characters</em>: {@code ".;:$[]<>/"}.
  45.470 +     * @param s the proposed character
  45.471 +     * @return true if the character is safe to use in classfiles
  45.472 +     */
  45.473 +    public static boolean isSafeBytecodeChar(char c) {
  45.474 +        return DANGEROUS_CHARS.indexOf(c) < DANGEROUS_CHAR_FIRST_INDEX;
  45.475 +    }
  45.476 +
  45.477 +    private static boolean looksMangled(String s) {
  45.478 +        return s.charAt(0) == ESCAPE_C;
  45.479 +    }
  45.480 +
  45.481 +    private static String mangle(String s) {
  45.482 +        if (s.length() == 0)
  45.483 +            return NULL_ESCAPE;
  45.484 +
  45.485 +        // build this lazily, when we first need an escape:
  45.486 +        StringBuilder sb = null;
  45.487 +
  45.488 +        for (int i = 0, slen = s.length(); i < slen; i++) {
  45.489 +            char c = s.charAt(i);
  45.490 +
  45.491 +            boolean needEscape = false;
  45.492 +            if (c == ESCAPE_C) {
  45.493 +                if (i+1 < slen) {
  45.494 +                    char c1 = s.charAt(i+1);
  45.495 +                    if ((i == 0 && c1 == NULL_ESCAPE_C)
  45.496 +                        || c1 != originalOfReplacement(c1)) {
  45.497 +                        // an accidental escape
  45.498 +                        needEscape = true;
  45.499 +                    }
  45.500 +                }
  45.501 +            } else {
  45.502 +                needEscape = isDangerous(c);
  45.503 +            }
  45.504 +
  45.505 +            if (!needEscape) {
  45.506 +                if (sb != null)  sb.append(c);
  45.507 +                continue;
  45.508 +            }
  45.509 +
  45.510 +            // build sb if this is the first escape
  45.511 +            if (sb == null) {
  45.512 +                sb = new StringBuilder(s.length()+10);
  45.513 +                // mangled names must begin with a backslash:
  45.514 +                if (s.charAt(0) != ESCAPE_C && i > 0)
  45.515 +                    sb.append(NULL_ESCAPE);
  45.516 +                // append the string so far, which is unremarkable:
  45.517 +                sb.append(s.substring(0, i));
  45.518 +            }
  45.519 +
  45.520 +            // rewrite \ to \-, / to \|, etc.
  45.521 +            sb.append(ESCAPE_C);
  45.522 +            sb.append(replacementOf(c));
  45.523 +        }
  45.524 +
  45.525 +        if (sb != null)   return sb.toString();
  45.526 +
  45.527 +        return s;
  45.528 +    }
  45.529 +
  45.530 +    private static String demangle(String s) {
  45.531 +        // build this lazily, when we first meet an escape:
  45.532 +        StringBuilder sb = null;
  45.533 +
  45.534 +        int stringStart = 0;
  45.535 +        if (s.startsWith(NULL_ESCAPE))
  45.536 +            stringStart = 2;
  45.537 +
  45.538 +        for (int i = stringStart, slen = s.length(); i < slen; i++) {
  45.539 +            char c = s.charAt(i);
  45.540 +
  45.541 +            if (c == ESCAPE_C && i+1 < slen) {
  45.542 +                // might be an escape sequence
  45.543 +                char rc = s.charAt(i+1);
  45.544 +                char oc = originalOfReplacement(rc);
  45.545 +                if (oc != rc) {
  45.546 +                    // build sb if this is the first escape
  45.547 +                    if (sb == null) {
  45.548 +                        sb = new StringBuilder(s.length());
  45.549 +                        // append the string so far, which is unremarkable:
  45.550 +                        sb.append(s.substring(stringStart, i));
  45.551 +                    }
  45.552 +                    ++i;  // skip both characters
  45.553 +                    c = oc;
  45.554 +                }
  45.555 +            }
  45.556 +
  45.557 +            if (sb != null)
  45.558 +                sb.append(c);
  45.559 +        }
  45.560 +
  45.561 +        if (sb != null)   return sb.toString();
  45.562 +
  45.563 +        return s.substring(stringStart);
  45.564 +    }
  45.565 +
  45.566 +    static char ESCAPE_C = '\\';
  45.567 +    // empty escape sequence to avoid a null name or illegal prefix
  45.568 +    static char NULL_ESCAPE_C = '=';
  45.569 +    static String NULL_ESCAPE = ESCAPE_C+""+NULL_ESCAPE_C;
  45.570 +
  45.571 +    static final String DANGEROUS_CHARS   = "\\/.;:$[]<>"; // \\ must be first
  45.572 +    static final String REPLACEMENT_CHARS =  "-|,?!%{}^_";
  45.573 +    static final int DANGEROUS_CHAR_FIRST_INDEX = 1; // index after \\
  45.574 +    static char[] DANGEROUS_CHARS_A   = DANGEROUS_CHARS.toCharArray();
  45.575 +    static char[] REPLACEMENT_CHARS_A = REPLACEMENT_CHARS.toCharArray();
  45.576 +    static final Character[] DANGEROUS_CHARS_CA;
  45.577 +    static {
  45.578 +        Character[] dcca = new Character[DANGEROUS_CHARS.length()];
  45.579 +        for (int i = 0; i < dcca.length; i++)
  45.580 +            dcca[i] = Character.valueOf(DANGEROUS_CHARS.charAt(i));
  45.581 +        DANGEROUS_CHARS_CA = dcca;
  45.582 +    }
  45.583 +
  45.584 +    static final long[] SPECIAL_BITMAP = new long[2];  // 128 bits
  45.585 +    static {
  45.586 +        String SPECIAL = DANGEROUS_CHARS + REPLACEMENT_CHARS;
  45.587 +        //System.out.println("SPECIAL = "+SPECIAL);
  45.588 +        for (char c : SPECIAL.toCharArray()) {
  45.589 +            SPECIAL_BITMAP[c >>> 6] |= 1L << c;
  45.590 +        }
  45.591 +    }
  45.592 +    static boolean isSpecial(char c) {
  45.593 +        if ((c >>> 6) < SPECIAL_BITMAP.length)
  45.594 +            return ((SPECIAL_BITMAP[c >>> 6] >> c) & 1) != 0;
  45.595 +        else
  45.596 +            return false;
  45.597 +    }
  45.598 +    static char replacementOf(char c) {
  45.599 +        if (!isSpecial(c))  return c;
  45.600 +        int i = DANGEROUS_CHARS.indexOf(c);
  45.601 +        if (i < 0)  return c;
  45.602 +        return REPLACEMENT_CHARS.charAt(i);
  45.603 +    }
  45.604 +    static char originalOfReplacement(char c) {
  45.605 +        if (!isSpecial(c))  return c;
  45.606 +        int i = REPLACEMENT_CHARS.indexOf(c);
  45.607 +        if (i < 0)  return c;
  45.608 +        return DANGEROUS_CHARS.charAt(i);
  45.609 +    }
  45.610 +    static boolean isDangerous(char c) {
  45.611 +        if (!isSpecial(c))  return false;
  45.612 +        return (DANGEROUS_CHARS.indexOf(c) >= DANGEROUS_CHAR_FIRST_INDEX);
  45.613 +    }
  45.614 +    static int indexOfDangerousChar(String s, int from) {
  45.615 +        for (int i = from, slen = s.length(); i < slen; i++) {
  45.616 +            if (isDangerous(s.charAt(i)))
  45.617 +                return i;
  45.618 +        }
  45.619 +        return -1;
  45.620 +    }
  45.621 +    static int lastIndexOfDangerousChar(String s, int from) {
  45.622 +        for (int i = Math.min(from, s.length()-1); i >= 0; i--) {
  45.623 +            if (isDangerous(s.charAt(i)))
  45.624 +                return i;
  45.625 +        }
  45.626 +        return -1;
  45.627 +    }
  45.628 +
  45.629 +
  45.630 +}
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/rt/emul/compact/src/main/java/sun/invoke/util/ValueConversions.java	Sat Aug 09 11:12:05 2014 +0200
    46.3 @@ -0,0 +1,1188 @@
    46.4 +/*
    46.5 + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
    46.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    46.7 + *
    46.8 + * This code is free software; you can redistribute it and/or modify it
    46.9 + * under the terms of the GNU General Public License version 2 only, as
   46.10 + * published by the Free Software Foundation.  Oracle designates this
   46.11 + * particular file as subject to the "Classpath" exception as provided
   46.12 + * by Oracle in the LICENSE file that accompanied this code.
   46.13 + *
   46.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   46.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   46.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   46.17 + * version 2 for more details (a copy is included in the LICENSE file that
   46.18 + * accompanied this code).
   46.19 + *
   46.20 + * You should have received a copy of the GNU General Public License version
   46.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   46.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   46.23 + *
   46.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   46.25 + * or visit www.oracle.com if you need additional information or have any
   46.26 + * questions.
   46.27 + */
   46.28 +
   46.29 +package sun.invoke.util;
   46.30 +
   46.31 +import java.lang.invoke.MethodHandle;
   46.32 +import java.lang.invoke.MethodHandles;
   46.33 +import java.lang.invoke.MethodHandles.Lookup;
   46.34 +import java.lang.invoke.MethodType;
   46.35 +import java.security.AccessController;
   46.36 +import java.security.PrivilegedAction;
   46.37 +import java.util.ArrayList;
   46.38 +import java.util.Arrays;
   46.39 +import java.util.Collections;
   46.40 +import java.util.EnumMap;
   46.41 +import java.util.List;
   46.42 +
   46.43 +public class ValueConversions {
   46.44 +    private static final Class<?> THIS_CLASS = ValueConversions.class;
   46.45 +    // Do not adjust this except for special platforms:
   46.46 +    private static final int MAX_ARITY;
   46.47 +    static {
   46.48 +        final Object[] values = { 255 };
   46.49 +        AccessController.doPrivileged(new PrivilegedAction<Void>() {
   46.50 +                @Override
   46.51 +                public Void run() {
   46.52 +                    values[0] = Integer.getInteger(THIS_CLASS.getName()+".MAX_ARITY", 255);
   46.53 +                    return null;
   46.54 +                }
   46.55 +            });
   46.56 +        MAX_ARITY = (Integer) values[0];
   46.57 +    }
   46.58 +
   46.59 +    private static final Lookup IMPL_LOOKUP = MethodHandles.lookup();
   46.60 +
   46.61 +    private static EnumMap<Wrapper, MethodHandle>[] newWrapperCaches(int n) {
   46.62 +        @SuppressWarnings("unchecked")  // generic array creation
   46.63 +        EnumMap<Wrapper, MethodHandle>[] caches
   46.64 +                = (EnumMap<Wrapper, MethodHandle>[]) new EnumMap<?,?>[n];
   46.65 +        for (int i = 0; i < n; i++)
   46.66 +            caches[i] = new EnumMap<>(Wrapper.class);
   46.67 +        return caches;
   46.68 +    }
   46.69 +
   46.70 +    /// Converting references to values.
   46.71 +
   46.72 +    // There are several levels of this unboxing conversions:
   46.73 +    //   no conversions:  exactly Integer.valueOf, etc.
   46.74 +    //   implicit conversions sanctioned by JLS 5.1.2, etc.
   46.75 +    //   explicit conversions as allowed by explicitCastArguments
   46.76 +
   46.77 +    static int unboxInteger(Object x, boolean cast) {
   46.78 +        if (x instanceof Integer)
   46.79 +            return ((Integer) x).intValue();
   46.80 +        return primitiveConversion(Wrapper.INT, x, cast).intValue();
   46.81 +    }
   46.82 +
   46.83 +    static byte unboxByte(Object x, boolean cast) {
   46.84 +        if (x instanceof Byte)
   46.85 +            return ((Byte) x).byteValue();
   46.86 +        return primitiveConversion(Wrapper.BYTE, x, cast).byteValue();
   46.87 +    }
   46.88 +
   46.89 +    static short unboxShort(Object x, boolean cast) {
   46.90 +        if (x instanceof Short)
   46.91 +            return ((Short) x).shortValue();
   46.92 +        return primitiveConversion(Wrapper.SHORT, x, cast).shortValue();
   46.93 +    }
   46.94 +
   46.95 +    static boolean unboxBoolean(Object x, boolean cast) {
   46.96 +        if (x instanceof Boolean)
   46.97 +            return ((Boolean) x).booleanValue();
   46.98 +        return (primitiveConversion(Wrapper.BOOLEAN, x, cast).intValue() & 1) != 0;
   46.99 +    }
  46.100 +
  46.101 +    static char unboxCharacter(Object x, boolean cast) {
  46.102 +        if (x instanceof Character)
  46.103 +            return ((Character) x).charValue();
  46.104 +        return (char) primitiveConversion(Wrapper.CHAR, x, cast).intValue();
  46.105 +    }
  46.106 +
  46.107 +    static long unboxLong(Object x, boolean cast) {
  46.108 +        if (x instanceof Long)
  46.109 +            return ((Long) x).longValue();
  46.110 +        return primitiveConversion(Wrapper.LONG, x, cast).longValue();
  46.111 +    }
  46.112 +
  46.113 +    static float unboxFloat(Object x, boolean cast) {
  46.114 +        if (x instanceof Float)
  46.115 +            return ((Float) x).floatValue();
  46.116 +        return primitiveConversion(Wrapper.FLOAT, x, cast).floatValue();
  46.117 +    }
  46.118 +
  46.119 +    static double unboxDouble(Object x, boolean cast) {
  46.120 +        if (x instanceof Double)
  46.121 +            return ((Double) x).doubleValue();
  46.122 +        return primitiveConversion(Wrapper.DOUBLE, x, cast).doubleValue();
  46.123 +    }
  46.124 +
  46.125 +    private static MethodType unboxType(Wrapper wrap) {
  46.126 +        return MethodType.methodType(wrap.primitiveType(), Object.class, boolean.class);
  46.127 +    }
  46.128 +
  46.129 +    private static final EnumMap<Wrapper, MethodHandle>[]
  46.130 +            UNBOX_CONVERSIONS = newWrapperCaches(2);
  46.131 +
  46.132 +    private static MethodHandle unbox(Wrapper wrap, boolean cast) {
  46.133 +        EnumMap<Wrapper, MethodHandle> cache = UNBOX_CONVERSIONS[(cast?1:0)];
  46.134 +        MethodHandle mh = cache.get(wrap);
  46.135 +        if (mh != null) {
  46.136 +            return mh;
  46.137 +        }
  46.138 +        // slow path
  46.139 +        switch (wrap) {
  46.140 +            case OBJECT:
  46.141 +                mh = IDENTITY; break;
  46.142 +            case VOID:
  46.143 +                mh = IGNORE; break;
  46.144 +        }
  46.145 +        if (mh != null) {
  46.146 +            cache.put(wrap, mh);
  46.147 +            return mh;
  46.148 +        }
  46.149 +        // look up the method
  46.150 +        String name = "unbox" + wrap.wrapperSimpleName();
  46.151 +        MethodType type = unboxType(wrap);
  46.152 +        try {
  46.153 +            mh = IMPL_LOOKUP.findStatic(THIS_CLASS, name, type);
  46.154 +        } catch (ReflectiveOperationException ex) {
  46.155 +            mh = null;
  46.156 +        }
  46.157 +        if (mh != null) {
  46.158 +            mh = MethodHandles.insertArguments(mh, 1, cast);
  46.159 +            cache.put(wrap, mh);
  46.160 +            return mh;
  46.161 +        }
  46.162 +        throw new IllegalArgumentException("cannot find unbox adapter for " + wrap
  46.163 +                + (cast ? " (cast)" : ""));
  46.164 +    }
  46.165 +
  46.166 +    public static MethodHandle unboxCast(Wrapper type) {
  46.167 +        return unbox(type, true);
  46.168 +    }
  46.169 +
  46.170 +    public static MethodHandle unbox(Class<?> type) {
  46.171 +        return unbox(Wrapper.forPrimitiveType(type), false);
  46.172 +    }
  46.173 +
  46.174 +    public static MethodHandle unboxCast(Class<?> type) {
  46.175 +        return unbox(Wrapper.forPrimitiveType(type), true);
  46.176 +    }
  46.177 +
  46.178 +    static private final Integer ZERO_INT = 0, ONE_INT = 1;
  46.179 +
  46.180 +    /// Primitive conversions
  46.181 +    /**
  46.182 +     * Produce a Number which represents the given value {@code x}
  46.183 +     * according to the primitive type of the given wrapper {@code wrap}.
  46.184 +     * Caller must invoke intValue, byteValue, longValue (etc.) on the result
  46.185 +     * to retrieve the desired primitive value.
  46.186 +     */
  46.187 +    public static Number primitiveConversion(Wrapper wrap, Object x, boolean cast) {
  46.188 +        // Maybe merge this code with Wrapper.convert/cast.
  46.189 +        Number res;
  46.190 +        if (x == null) {
  46.191 +            if (!cast)  return null;
  46.192 +            return ZERO_INT;
  46.193 +        }
  46.194 +        if (x instanceof Number) {
  46.195 +            res = (Number) x;
  46.196 +        } else if (x instanceof Boolean) {
  46.197 +            res = ((boolean)x ? ONE_INT : ZERO_INT);
  46.198 +        } else if (x instanceof Character) {
  46.199 +            res = (int)(char)x;
  46.200 +        } else {
  46.201 +            // this will fail with the required ClassCastException:
  46.202 +            res = (Number) x;
  46.203 +        }
  46.204 +        Wrapper xwrap = Wrapper.findWrapperType(x.getClass());
  46.205 +        if (xwrap == null || !cast && !wrap.isConvertibleFrom(xwrap))
  46.206 +            // this will fail with the required ClassCastException:
  46.207 +            return (Number) wrap.wrapperType().cast(x);
  46.208 +        return res;
  46.209 +    }
  46.210 +
  46.211 +    /**
  46.212 +     * The JVM verifier allows boolean, byte, short, or char to widen to int.
  46.213 +     * Support exactly this conversion, from a boxed value type Boolean,
  46.214 +     * Byte, Short, Character, or Integer.
  46.215 +     */
  46.216 +    public static int widenSubword(Object x) {
  46.217 +        if (x instanceof Integer)
  46.218 +            return (int) x;
  46.219 +        else if (x instanceof Boolean)
  46.220 +            return fromBoolean((boolean) x);
  46.221 +        else if (x instanceof Character)
  46.222 +            return (char) x;
  46.223 +        else if (x instanceof Short)
  46.224 +            return (short) x;
  46.225 +        else if (x instanceof Byte)
  46.226 +            return (byte) x;
  46.227 +        else
  46.228 +            // Fail with a ClassCastException.
  46.229 +            return (int) x;
  46.230 +    }
  46.231 +
  46.232 +    /// Converting primitives to references
  46.233 +
  46.234 +    static Integer boxInteger(int x) {
  46.235 +        return x;
  46.236 +    }
  46.237 +
  46.238 +    static Byte boxByte(byte x) {
  46.239 +        return x;
  46.240 +    }
  46.241 +
  46.242 +    static Short boxShort(short x) {
  46.243 +        return x;
  46.244 +    }
  46.245 +
  46.246 +    static Boolean boxBoolean(boolean x) {
  46.247 +        return x;
  46.248 +    }
  46.249 +
  46.250 +    static Character boxCharacter(char x) {
  46.251 +        return x;
  46.252 +    }
  46.253 +
  46.254 +    static Long boxLong(long x) {
  46.255 +        return x;
  46.256 +    }
  46.257 +
  46.258 +    static Float boxFloat(float x) {
  46.259 +        return x;
  46.260 +    }
  46.261 +
  46.262 +    static Double boxDouble(double x) {
  46.263 +        return x;
  46.264 +    }
  46.265 +
  46.266 +    private static MethodType boxType(Wrapper wrap) {
  46.267 +        // be exact, since return casts are hard to compose
  46.268 +        Class<?> boxType = wrap.wrapperType();
  46.269 +        return MethodType.methodType(boxType, wrap.primitiveType());
  46.270 +    }
  46.271 +
  46.272 +    private static final EnumMap<Wrapper, MethodHandle>[]
  46.273 +            BOX_CONVERSIONS = newWrapperCaches(2);
  46.274 +
  46.275 +    private static MethodHandle box(Wrapper wrap, boolean exact) {
  46.276 +        EnumMap<Wrapper, MethodHandle> cache = BOX_CONVERSIONS[(exact?1:0)];
  46.277 +        MethodHandle mh = cache.get(wrap);
  46.278 +        if (mh != null) {
  46.279 +            return mh;
  46.280 +        }
  46.281 +        // slow path
  46.282 +        switch (wrap) {
  46.283 +            case OBJECT:
  46.284 +                mh = IDENTITY; break;
  46.285 +            case VOID:
  46.286 +                mh = ZERO_OBJECT;
  46.287 +                break;
  46.288 +        }
  46.289 +        if (mh != null) {
  46.290 +            cache.put(wrap, mh);
  46.291 +            return mh;
  46.292 +        }
  46.293 +        // look up the method
  46.294 +        String name = "box" + wrap.wrapperSimpleName();
  46.295 +        MethodType type = boxType(wrap);
  46.296 +        if (exact) {
  46.297 +            try {
  46.298 +                mh = IMPL_LOOKUP.findStatic(THIS_CLASS, name, type);
  46.299 +            } catch (ReflectiveOperationException ex) {
  46.300 +                mh = null;
  46.301 +            }
  46.302 +        } else {
  46.303 +            mh = box(wrap, !exact).asType(type.erase());
  46.304 +        }
  46.305 +        if (mh != null) {
  46.306 +            cache.put(wrap, mh);
  46.307 +            return mh;
  46.308 +        }
  46.309 +        throw new IllegalArgumentException("cannot find box adapter for "
  46.310 +                + wrap + (exact ? " (exact)" : ""));
  46.311 +    }
  46.312 +
  46.313 +    public static MethodHandle box(Class<?> type) {
  46.314 +        boolean exact = false;
  46.315 +        // e.g., boxShort(short)Short if exact,
  46.316 +        // e.g., boxShort(short)Object if !exact
  46.317 +        return box(Wrapper.forPrimitiveType(type), exact);
  46.318 +    }
  46.319 +
  46.320 +    public static MethodHandle box(Wrapper type) {
  46.321 +        boolean exact = false;
  46.322 +        return box(type, exact);
  46.323 +    }
  46.324 +
  46.325 +    /// Constant functions
  46.326 +
  46.327 +    static void ignore(Object x) {
  46.328 +        // no value to return; this is an unbox of null
  46.329 +    }
  46.330 +
  46.331 +    static void empty() {
  46.332 +    }
  46.333 +
  46.334 +    static Object zeroObject() {
  46.335 +        return null;
  46.336 +    }
  46.337 +
  46.338 +    static int zeroInteger() {
  46.339 +        return 0;
  46.340 +    }
  46.341 +
  46.342 +    static long zeroLong() {
  46.343 +        return 0;
  46.344 +    }
  46.345 +
  46.346 +    static float zeroFloat() {
  46.347 +        return 0;
  46.348 +    }
  46.349 +
  46.350 +    static double zeroDouble() {
  46.351 +        return 0;
  46.352 +    }
  46.353 +
  46.354 +    private static final EnumMap<Wrapper, MethodHandle>[]
  46.355 +            CONSTANT_FUNCTIONS = newWrapperCaches(2);
  46.356 +
  46.357 +    public static MethodHandle zeroConstantFunction(Wrapper wrap) {
  46.358 +        EnumMap<Wrapper, MethodHandle> cache = CONSTANT_FUNCTIONS[0];
  46.359 +        MethodHandle mh = cache.get(wrap);
  46.360 +        if (mh != null) {
  46.361 +            return mh;
  46.362 +        }
  46.363 +        // slow path
  46.364 +        MethodType type = MethodType.methodType(wrap.primitiveType());
  46.365 +        switch (wrap) {
  46.366 +            case VOID:
  46.367 +                mh = EMPTY;
  46.368 +                break;
  46.369 +            case OBJECT:
  46.370 +            case INT: case LONG: case FLOAT: case DOUBLE:
  46.371 +                try {
  46.372 +                    mh = IMPL_LOOKUP.findStatic(THIS_CLASS, "zero"+wrap.wrapperSimpleName(), type);
  46.373 +                } catch (ReflectiveOperationException ex) {
  46.374 +                    mh = null;
  46.375 +                }
  46.376 +                break;
  46.377 +        }
  46.378 +        if (mh != null) {
  46.379 +            cache.put(wrap, mh);
  46.380 +            return mh;
  46.381 +        }
  46.382 +
  46.383 +        // use zeroInt and cast the result
  46.384 +        if (wrap.isSubwordOrInt() && wrap != Wrapper.INT) {
  46.385 +            mh = MethodHandles.explicitCastArguments(zeroConstantFunction(Wrapper.INT), type);
  46.386 +            cache.put(wrap, mh);
  46.387 +            return mh;
  46.388 +        }
  46.389 +        throw new IllegalArgumentException("cannot find zero constant for " + wrap);
  46.390 +    }
  46.391 +
  46.392 +    /// Converting references to references.
  46.393 +
  46.394 +    /**
  46.395 +     * Identity function.
  46.396 +     * @param x an arbitrary reference value
  46.397 +     * @return the same value x
  46.398 +     */
  46.399 +    static <T> T identity(T x) {
  46.400 +        return x;
  46.401 +    }
  46.402 +
  46.403 +    static <T> T[] identity(T[] x) {
  46.404 +        return x;
  46.405 +    }
  46.406 +
  46.407 +    /**
  46.408 +     * Identity function on ints.
  46.409 +     * @param x an arbitrary int value
  46.410 +     * @return the same value x
  46.411 +     */
  46.412 +    static int identity(int x) {
  46.413 +        return x;
  46.414 +    }
  46.415 +
  46.416 +    static byte identity(byte x) {
  46.417 +        return x;
  46.418 +    }
  46.419 +
  46.420 +    static short identity(short x) {
  46.421 +        return x;
  46.422 +    }
  46.423 +
  46.424 +    static boolean identity(boolean x) {
  46.425 +        return x;
  46.426 +    }
  46.427 +
  46.428 +    static char identity(char x) {
  46.429 +        return x;
  46.430 +    }
  46.431 +
  46.432 +    /**
  46.433 +     * Identity function on longs.
  46.434 +     * @param x an arbitrary long value
  46.435 +     * @return the same value x
  46.436 +     */
  46.437 +    static long identity(long x) {
  46.438 +        return x;
  46.439 +    }
  46.440 +
  46.441 +    static float identity(float x) {
  46.442 +        return x;
  46.443 +    }
  46.444 +
  46.445 +    static double identity(double x) {
  46.446 +        return x;
  46.447 +    }
  46.448 +
  46.449 +    /**
  46.450 +     * Identity function, with reference cast.
  46.451 +     * @param t an arbitrary reference type
  46.452 +     * @param x an arbitrary reference value
  46.453 +     * @return the same value x
  46.454 +     */
  46.455 +    @SuppressWarnings("unchecked")
  46.456 +    static <T,U> T castReference(Class<? extends T> t, U x) {
  46.457 +        // inlined Class.cast because we can't ForceInline it
  46.458 +        if (x != null && !t.isInstance(x))
  46.459 +            throw newClassCastException(t, x);
  46.460 +        return (T) x;
  46.461 +    }
  46.462 +
  46.463 +    private static ClassCastException newClassCastException(Class<?> t, Object obj) {
  46.464 +        return new ClassCastException("Cannot cast " + obj.getClass().getName() + " to " + t.getName());
  46.465 +    }
  46.466 +
  46.467 +    private static final MethodHandle IDENTITY, CAST_REFERENCE, ZERO_OBJECT, IGNORE, EMPTY,
  46.468 +            ARRAY_IDENTITY, FILL_NEW_TYPED_ARRAY, FILL_NEW_ARRAY;
  46.469 +    static {
  46.470 +        try {
  46.471 +            MethodType idType = MethodType.genericMethodType(1);
  46.472 +            MethodType castType = idType.insertParameterTypes(0, Class.class);
  46.473 +            MethodType ignoreType = idType.changeReturnType(void.class);
  46.474 +            MethodType zeroObjectType = MethodType.genericMethodType(0);
  46.475 +            IDENTITY = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", idType);
  46.476 +            //CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType);
  46.477 +            CAST_REFERENCE = IMPL_LOOKUP.findStatic(THIS_CLASS, "castReference", castType);
  46.478 +            ZERO_OBJECT = IMPL_LOOKUP.findStatic(THIS_CLASS, "zeroObject", zeroObjectType);
  46.479 +            IGNORE = IMPL_LOOKUP.findStatic(THIS_CLASS, "ignore", ignoreType);
  46.480 +            EMPTY = IMPL_LOOKUP.findStatic(THIS_CLASS, "empty", ignoreType.dropParameterTypes(0, 1));
  46.481 +            ARRAY_IDENTITY = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", MethodType.methodType(Object[].class, Object[].class));
  46.482 +            FILL_NEW_ARRAY = IMPL_LOOKUP
  46.483 +                    .findStatic(THIS_CLASS, "fillNewArray",
  46.484 +                          MethodType.methodType(Object[].class, Integer.class, Object[].class));
  46.485 +            FILL_NEW_TYPED_ARRAY = IMPL_LOOKUP
  46.486 +                    .findStatic(THIS_CLASS, "fillNewTypedArray",
  46.487 +                          MethodType.methodType(Object[].class, Object[].class, Integer.class, Object[].class));
  46.488 +        } catch (NoSuchMethodException | IllegalAccessException ex) {
  46.489 +            throw newInternalError("uncaught exception", ex);
  46.490 +        }
  46.491 +    }
  46.492 +
  46.493 +    // Varargs methods need to be in a separately initialized class, to avoid bootstrapping problems.
  46.494 +    static class LazyStatics {
  46.495 +        private static final MethodHandle COPY_AS_REFERENCE_ARRAY, COPY_AS_PRIMITIVE_ARRAY, MAKE_LIST;
  46.496 +        static {
  46.497 +            try {
  46.498 +                //MAKE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "makeArray", MethodType.methodType(Object[].class, Object[].class));
  46.499 +                COPY_AS_REFERENCE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "copyAsReferenceArray", MethodType.methodType(Object[].class, Class.class, Object[].class));
  46.500 +                COPY_AS_PRIMITIVE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "copyAsPrimitiveArray", MethodType.methodType(Object.class, Wrapper.class, Object[].class));
  46.501 +                MAKE_LIST = IMPL_LOOKUP.findStatic(THIS_CLASS, "makeList", MethodType.methodType(List.class, Object[].class));
  46.502 +            } catch (ReflectiveOperationException ex) {
  46.503 +                throw newInternalError("uncaught exception", ex);
  46.504 +            }
  46.505 +        }
  46.506 +    }
  46.507 +
  46.508 +    private static final EnumMap<Wrapper, MethodHandle>[] WRAPPER_CASTS
  46.509 +            = newWrapperCaches(1);
  46.510 +
  46.511 +    /** Return a method that casts its sole argument (an Object) to the given type
  46.512 +     *  and returns it as the given type.
  46.513 +     */
  46.514 +    public static MethodHandle cast(Class<?> type) {
  46.515 +        if (type.isPrimitive())  throw new IllegalArgumentException("cannot cast primitive type "+type);
  46.516 +        MethodHandle mh;
  46.517 +        Wrapper wrap = null;
  46.518 +        EnumMap<Wrapper, MethodHandle> cache = null;
  46.519 +        if (Wrapper.isWrapperType(type)) {
  46.520 +            wrap = Wrapper.forWrapperType(type);
  46.521 +            cache = WRAPPER_CASTS[0];
  46.522 +            mh = cache.get(wrap);
  46.523 +            if (mh != null)  return mh;
  46.524 +        }
  46.525 +        mh = MethodHandles.insertArguments(CAST_REFERENCE, 0, type);
  46.526 +        if (cache != null)
  46.527 +            cache.put(wrap, mh);
  46.528 +        return mh;
  46.529 +    }
  46.530 +
  46.531 +    public static MethodHandle identity() {
  46.532 +        return IDENTITY;
  46.533 +    }
  46.534 +
  46.535 +    public static MethodHandle identity(Class<?> type) {
  46.536 +        if (!type.isPrimitive())
  46.537 +            // Reference identity has been moved into MethodHandles:
  46.538 +            return MethodHandles.identity(type);
  46.539 +        return identity(Wrapper.findPrimitiveType(type));
  46.540 +    }
  46.541 +
  46.542 +    public static MethodHandle identity(Wrapper wrap) {
  46.543 +        EnumMap<Wrapper, MethodHandle> cache = CONSTANT_FUNCTIONS[1];
  46.544 +        MethodHandle mh = cache.get(wrap);
  46.545 +        if (mh != null) {
  46.546 +            return mh;
  46.547 +        }
  46.548 +        // slow path
  46.549 +        MethodType type = MethodType.methodType(wrap.primitiveType());
  46.550 +        if (wrap != Wrapper.VOID)
  46.551 +            type = type.appendParameterTypes(wrap.primitiveType());
  46.552 +        try {
  46.553 +            mh = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", type);
  46.554 +        } catch (ReflectiveOperationException ex) {
  46.555 +            mh = null;
  46.556 +        }
  46.557 +        if (mh == null && wrap == Wrapper.VOID) {
  46.558 +            mh = EMPTY;  // #(){} : #()void
  46.559 +        }
  46.560 +        if (mh != null) {
  46.561 +            cache.put(wrap, mh);
  46.562 +            return mh;
  46.563 +        }
  46.564 +
  46.565 +        if (mh != null) {
  46.566 +            cache.put(wrap, mh);
  46.567 +            return mh;
  46.568 +        }
  46.569 +        throw new IllegalArgumentException("cannot find identity for " + wrap);
  46.570 +    }
  46.571 +
  46.572 +    /// Primitive conversions.
  46.573 +    // These are supported directly by the JVM, usually by a single instruction.
  46.574 +    // In the case of narrowing to a subword, there may be a pair of instructions.
  46.575 +    // In the case of booleans, there may be a helper routine to manage a 1-bit value.
  46.576 +    // This is the full 8x8 matrix (minus the diagonal).
  46.577 +
  46.578 +    // narrow double to all other types:
  46.579 +    static float doubleToFloat(double x) {  // bytecode: d2f
  46.580 +        return (float) x;
  46.581 +    }
  46.582 +    static long doubleToLong(double x) {  // bytecode: d2l
  46.583 +        return (long) x;
  46.584 +    }
  46.585 +    static int doubleToInt(double x) {  // bytecode: d2i
  46.586 +        return (int) x;
  46.587 +    }
  46.588 +    static short doubleToShort(double x) {  // bytecodes: d2i, i2s
  46.589 +        return (short) x;
  46.590 +    }
  46.591 +    static char doubleToChar(double x) {  // bytecodes: d2i, i2c
  46.592 +        return (char) x;
  46.593 +    }
  46.594 +    static byte doubleToByte(double x) {  // bytecodes: d2i, i2b
  46.595 +        return (byte) x;
  46.596 +    }
  46.597 +    static boolean doubleToBoolean(double x) {
  46.598 +        return toBoolean((byte) x);
  46.599 +    }
  46.600 +
  46.601 +    // widen float:
  46.602 +    static double floatToDouble(float x) {  // bytecode: f2d
  46.603 +        return x;
  46.604 +    }
  46.605 +    // narrow float:
  46.606 +    static long floatToLong(float x) {  // bytecode: f2l
  46.607 +        return (long) x;
  46.608 +    }
  46.609 +    static int floatToInt(float x) {  // bytecode: f2i
  46.610 +        return (int) x;
  46.611 +    }
  46.612 +    static short floatToShort(float x) {  // bytecodes: f2i, i2s
  46.613 +        return (short) x;
  46.614 +    }
  46.615 +    static char floatToChar(float x) {  // bytecodes: f2i, i2c
  46.616 +        return (char) x;
  46.617 +    }
  46.618 +    static byte floatToByte(float x) {  // bytecodes: f2i, i2b
  46.619 +        return (byte) x;
  46.620 +    }
  46.621 +    static boolean floatToBoolean(float x) {
  46.622 +        return toBoolean((byte) x);
  46.623 +    }
  46.624 +
  46.625 +    // widen long:
  46.626 +    static double longToDouble(long x) {  // bytecode: l2d
  46.627 +        return x;
  46.628 +    }
  46.629 +    static float longToFloat(long x) {  // bytecode: l2f
  46.630 +        return x;
  46.631 +    }
  46.632 +    // narrow long:
  46.633 +    static int longToInt(long x) {  // bytecode: l2i
  46.634 +        return (int) x;
  46.635 +    }
  46.636 +    static short longToShort(long x) {  // bytecodes: f2i, i2s
  46.637 +        return (short) x;
  46.638 +    }
  46.639 +    static char longToChar(long x) {  // bytecodes: f2i, i2c
  46.640 +        return (char) x;
  46.641 +    }
  46.642 +    static byte longToByte(long x) {  // bytecodes: f2i, i2b
  46.643 +        return (byte) x;
  46.644 +    }
  46.645 +    static boolean longToBoolean(long x) {
  46.646 +        return toBoolean((byte) x);
  46.647 +    }
  46.648 +
  46.649 +    // widen int:
  46.650 +    static double intToDouble(int x) {  // bytecode: i2d
  46.651 +        return x;
  46.652 +    }
  46.653 +    static float intToFloat(int x) {  // bytecode: i2f
  46.654 +        return x;
  46.655 +    }
  46.656 +    static long intToLong(int x) {  // bytecode: i2l
  46.657 +        return x;
  46.658 +    }
  46.659 +    // narrow int:
  46.660 +    static short intToShort(int x) {  // bytecode: i2s
  46.661 +        return (short) x;
  46.662 +    }
  46.663 +    static char intToChar(int x) {  // bytecode: i2c
  46.664 +        return (char) x;
  46.665 +    }
  46.666 +    static byte intToByte(int x) {  // bytecode: i2b
  46.667 +        return (byte) x;
  46.668 +    }
  46.669 +    static boolean intToBoolean(int x) {
  46.670 +        return toBoolean((byte) x);
  46.671 +    }
  46.672 +
  46.673 +    // widen short:
  46.674 +    static double shortToDouble(short x) {  // bytecode: i2d (implicit 's2i')
  46.675 +        return x;
  46.676 +    }
  46.677 +    static float shortToFloat(short x) {  // bytecode: i2f (implicit 's2i')
  46.678 +        return x;
  46.679 +    }
  46.680 +    static long shortToLong(short x) {  // bytecode: i2l (implicit 's2i')
  46.681 +        return x;
  46.682 +    }
  46.683 +    static int shortToInt(short x) {  // (implicit 's2i')
  46.684 +        return x;
  46.685 +    }
  46.686 +    // narrow short:
  46.687 +    static char shortToChar(short x) {  // bytecode: i2c (implicit 's2i')
  46.688 +        return (char)x;
  46.689 +    }
  46.690 +    static byte shortToByte(short x) {  // bytecode: i2b (implicit 's2i')
  46.691 +        return (byte)x;
  46.692 +    }
  46.693 +    static boolean shortToBoolean(short x) {
  46.694 +        return toBoolean((byte) x);
  46.695 +    }
  46.696 +
  46.697 +    // widen char:
  46.698 +    static double charToDouble(char x) {  // bytecode: i2d (implicit 'c2i')
  46.699 +        return x;
  46.700 +    }
  46.701 +    static float charToFloat(char x) {  // bytecode: i2f (implicit 'c2i')
  46.702 +        return x;
  46.703 +    }
  46.704 +    static long charToLong(char x) {  // bytecode: i2l (implicit 'c2i')
  46.705 +        return x;
  46.706 +    }
  46.707 +    static int charToInt(char x) {  // (implicit 'c2i')
  46.708 +        return x;
  46.709 +    }
  46.710 +    // narrow char:
  46.711 +    static short charToShort(char x) {  // bytecode: i2s (implicit 'c2i')
  46.712 +        return (short)x;
  46.713 +    }
  46.714 +    static byte charToByte(char x) {  // bytecode: i2b (implicit 'c2i')
  46.715 +        return (byte)x;
  46.716 +    }
  46.717 +    static boolean charToBoolean(char x) {
  46.718 +        return toBoolean((byte) x);
  46.719 +    }
  46.720 +
  46.721 +    // widen byte:
  46.722 +    static double byteToDouble(byte x) {  // bytecode: i2d (implicit 'b2i')
  46.723 +        return x;
  46.724 +    }
  46.725 +    static float byteToFloat(byte x) {  // bytecode: i2f (implicit 'b2i')
  46.726 +        return x;
  46.727 +    }
  46.728 +    static long byteToLong(byte x) {  // bytecode: i2l (implicit 'b2i')
  46.729 +        return x;
  46.730 +    }
  46.731 +    static int byteToInt(byte x) {  // (implicit 'b2i')
  46.732 +        return x;
  46.733 +    }
  46.734 +    static short byteToShort(byte x) {  // bytecode: i2s (implicit 'b2i')
  46.735 +        return (short)x;
  46.736 +    }
  46.737 +    static char byteToChar(byte x) {  // bytecode: i2b (implicit 'b2i')
  46.738 +        return (char)x;
  46.739 +    }
  46.740 +    // narrow byte to boolean:
  46.741 +    static boolean byteToBoolean(byte x) {
  46.742 +        return toBoolean(x);
  46.743 +    }
  46.744 +
  46.745 +    // widen boolean to all types:
  46.746 +    static double booleanToDouble(boolean x) {
  46.747 +        return fromBoolean(x);
  46.748 +    }
  46.749 +    static float booleanToFloat(boolean x) {
  46.750 +        return fromBoolean(x);
  46.751 +    }
  46.752 +    static long booleanToLong(boolean x) {
  46.753 +        return fromBoolean(x);
  46.754 +    }
  46.755 +    static int booleanToInt(boolean x) {
  46.756 +        return fromBoolean(x);
  46.757 +    }
  46.758 +    static short booleanToShort(boolean x) {
  46.759 +        return fromBoolean(x);
  46.760 +    }
  46.761 +    static char booleanToChar(boolean x) {
  46.762 +        return (char)fromBoolean(x);
  46.763 +    }
  46.764 +    static byte booleanToByte(boolean x) {
  46.765 +        return fromBoolean(x);
  46.766 +    }
  46.767 +
  46.768 +    // helpers to force boolean into the conversion scheme:
  46.769 +    static boolean toBoolean(byte x) {
  46.770 +        // see javadoc for MethodHandles.explicitCastArguments
  46.771 +        return ((x & 1) != 0);
  46.772 +    }
  46.773 +    static byte fromBoolean(boolean x) {
  46.774 +        // see javadoc for MethodHandles.explicitCastArguments
  46.775 +        return (x ? (byte)1 : (byte)0);
  46.776 +    }
  46.777 +
  46.778 +    private static final EnumMap<Wrapper, MethodHandle>[]
  46.779 +            CONVERT_PRIMITIVE_FUNCTIONS = newWrapperCaches(Wrapper.values().length);
  46.780 +
  46.781 +    public static MethodHandle convertPrimitive(Wrapper wsrc, Wrapper wdst) {
  46.782 +        EnumMap<Wrapper, MethodHandle> cache = CONVERT_PRIMITIVE_FUNCTIONS[wsrc.ordinal()];
  46.783 +        MethodHandle mh = cache.get(wdst);
  46.784 +        if (mh != null) {
  46.785 +            return mh;
  46.786 +        }
  46.787 +        // slow path
  46.788 +        Class<?> src = wsrc.primitiveType();
  46.789 +        Class<?> dst = wdst.primitiveType();
  46.790 +        MethodType type = src == void.class ? MethodType.methodType(dst) : MethodType.methodType(dst, src);
  46.791 +        if (wsrc == wdst) {
  46.792 +            mh = identity(src);
  46.793 +        } else if (wsrc == Wrapper.VOID) {
  46.794 +            mh = zeroConstantFunction(wdst);
  46.795 +        } else if (wdst == Wrapper.VOID) {
  46.796 +            mh = MethodHandles.dropArguments(EMPTY, 0, src);  // Defer back to MethodHandles.
  46.797 +        } else if (wsrc == Wrapper.OBJECT) {
  46.798 +            mh = unboxCast(dst);
  46.799 +        } else if (wdst == Wrapper.OBJECT) {
  46.800 +            mh = box(src);
  46.801 +        } else {
  46.802 +            assert(src.isPrimitive() && dst.isPrimitive());
  46.803 +            try {
  46.804 +                mh = IMPL_LOOKUP.findStatic(THIS_CLASS, src.getSimpleName()+"To"+capitalize(dst.getSimpleName()), type);
  46.805 +            } catch (ReflectiveOperationException ex) {
  46.806 +                mh = null;
  46.807 +            }
  46.808 +        }
  46.809 +        if (mh != null) {
  46.810 +            assert(mh.type() == type) : mh;
  46.811 +            cache.put(wdst, mh);
  46.812 +            return mh;
  46.813 +        }
  46.814 +
  46.815 +        throw new IllegalArgumentException("cannot find primitive conversion function for " +
  46.816 +                                           src.getSimpleName()+" -> "+dst.getSimpleName());
  46.817 +    }
  46.818 +
  46.819 +    public static MethodHandle convertPrimitive(Class<?> src, Class<?> dst) {
  46.820 +        return convertPrimitive(Wrapper.forPrimitiveType(src), Wrapper.forPrimitiveType(dst));
  46.821 +    }
  46.822 +
  46.823 +    private static String capitalize(String x) {
  46.824 +        return Character.toUpperCase(x.charAt(0))+x.substring(1);
  46.825 +    }
  46.826 +
  46.827 +    /// Collection of multiple arguments.
  46.828 +
  46.829 +    public static Object convertArrayElements(Class<?> arrayType, Object array) {
  46.830 +        Class<?> src = array.getClass().getComponentType();
  46.831 +        Class<?> dst = arrayType.getComponentType();
  46.832 +        if (src == null || dst == null)  throw new IllegalArgumentException("not array type");
  46.833 +        Wrapper sw = (src.isPrimitive() ? Wrapper.forPrimitiveType(src) : null);
  46.834 +        Wrapper dw = (dst.isPrimitive() ? Wrapper.forPrimitiveType(dst) : null);
  46.835 +        int length;
  46.836 +        if (sw == null) {
  46.837 +            Object[] a = (Object[]) array;
  46.838 +            length = a.length;
  46.839 +            if (dw == null)
  46.840 +                return Arrays.copyOf(a, length, arrayType.asSubclass(Object[].class));
  46.841 +            Object res = dw.makeArray(length);
  46.842 +            dw.copyArrayUnboxing(a, 0, res, 0, length);
  46.843 +            return res;
  46.844 +        }
  46.845 +        length = java.lang.reflect.Array.getLength(array);
  46.846 +        Object[] res;
  46.847 +        if (dw == null) {
  46.848 +            res = Arrays.copyOf(NO_ARGS_ARRAY, length, arrayType.asSubclass(Object[].class));
  46.849 +        } else {
  46.850 +            res = new Object[length];
  46.851 +        }
  46.852 +        sw.copyArrayBoxing(array, 0, res, 0, length);
  46.853 +        if (dw == null)  return res;
  46.854 +        Object a = dw.makeArray(length);
  46.855 +        dw.copyArrayUnboxing(res, 0, a, 0, length);
  46.856 +        return a;
  46.857 +    }
  46.858 +
  46.859 +    private static MethodHandle findCollector(String name, int nargs, Class<?> rtype, Class<?>... ptypes) {
  46.860 +        MethodType type = MethodType.genericMethodType(nargs)
  46.861 +                .changeReturnType(rtype)
  46.862 +                .insertParameterTypes(0, ptypes);
  46.863 +        try {
  46.864 +            return IMPL_LOOKUP.findStatic(THIS_CLASS, name, type);
  46.865 +        } catch (ReflectiveOperationException ex) {
  46.866 +            return null;
  46.867 +        }
  46.868 +    }
  46.869 +
  46.870 +    private static final Object[] NO_ARGS_ARRAY = {};
  46.871 +    private static Object[] makeArray(Object... args) { return args; }
  46.872 +    private static Object[] array() { return NO_ARGS_ARRAY; }
  46.873 +    private static Object[] array(Object a0)
  46.874 +                { return makeArray(a0); }
  46.875 +    private static Object[] array(Object a0, Object a1)
  46.876 +                { return makeArray(a0, a1); }
  46.877 +    private static Object[] array(Object a0, Object a1, Object a2)
  46.878 +                { return makeArray(a0, a1, a2); }
  46.879 +    private static Object[] array(Object a0, Object a1, Object a2, Object a3)
  46.880 +                { return makeArray(a0, a1, a2, a3); }
  46.881 +    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
  46.882 +                                  Object a4)
  46.883 +                { return makeArray(a0, a1, a2, a3, a4); }
  46.884 +    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
  46.885 +                                  Object a4, Object a5)
  46.886 +                { return makeArray(a0, a1, a2, a3, a4, a5); }
  46.887 +    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
  46.888 +                                  Object a4, Object a5, Object a6)
  46.889 +                { return makeArray(a0, a1, a2, a3, a4, a5, a6); }
  46.890 +    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
  46.891 +                                  Object a4, Object a5, Object a6, Object a7)
  46.892 +                { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7); }
  46.893 +    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
  46.894 +                                  Object a4, Object a5, Object a6, Object a7,
  46.895 +                                  Object a8)
  46.896 +                { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
  46.897 +    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
  46.898 +                                  Object a4, Object a5, Object a6, Object a7,
  46.899 +                                  Object a8, Object a9)
  46.900 +                { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
  46.901 +    private static MethodHandle[] makeArrays() {
  46.902 +        ArrayList<MethodHandle> mhs = new ArrayList<>();
  46.903 +        for (;;) {
  46.904 +            MethodHandle mh = findCollector("array", mhs.size(), Object[].class);
  46.905 +            if (mh == null)  break;
  46.906 +            mhs.add(mh);
  46.907 +        }
  46.908 +        assert(mhs.size() == 11);  // current number of methods
  46.909 +        return mhs.toArray(new MethodHandle[MAX_ARITY+1]);
  46.910 +    }
  46.911 +    private static final MethodHandle[] ARRAYS = makeArrays();
  46.912 +
  46.913 +    // filling versions of the above:
  46.914 +    // using Integer len instead of int len and no varargs to avoid bootstrapping problems
  46.915 +    private static Object[] fillNewArray(Integer len, Object[] /*not ...*/ args) {
  46.916 +        Object[] a = new Object[len];
  46.917 +        fillWithArguments(a, 0, args);
  46.918 +        return a;
  46.919 +    }
  46.920 +    private static Object[] fillNewTypedArray(Object[] example, Integer len, Object[] /*not ...*/ args) {
  46.921 +        Object[] a = Arrays.copyOf(example, len);
  46.922 +        fillWithArguments(a, 0, args);
  46.923 +        return a;
  46.924 +    }
  46.925 +    private static void fillWithArguments(Object[] a, int pos, Object... args) {
  46.926 +        System.arraycopy(args, 0, a, pos, args.length);
  46.927 +    }
  46.928 +    // using Integer pos instead of int pos to avoid bootstrapping problems
  46.929 +    private static Object[] fillArray(Integer pos, Object[] a, Object a0)
  46.930 +                { fillWithArguments(a, pos, a0); return a; }
  46.931 +    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1)
  46.932 +                { fillWithArguments(a, pos, a0, a1); return a; }
  46.933 +    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2)
  46.934 +                { fillWithArguments(a, pos, a0, a1, a2); return a; }
  46.935 +    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3)
  46.936 +                { fillWithArguments(a, pos, a0, a1, a2, a3); return a; }
  46.937 +    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
  46.938 +                                  Object a4)
  46.939 +                { fillWithArguments(a, pos, a0, a1, a2, a3, a4); return a; }
  46.940 +    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
  46.941 +                                  Object a4, Object a5)
  46.942 +                { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5); return a; }
  46.943 +    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
  46.944 +                                  Object a4, Object a5, Object a6)
  46.945 +                { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6); return a; }
  46.946 +    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
  46.947 +                                  Object a4, Object a5, Object a6, Object a7)
  46.948 +                { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7); return a; }
  46.949 +    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
  46.950 +                                  Object a4, Object a5, Object a6, Object a7,
  46.951 +                                  Object a8)
  46.952 +                { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8); return a; }
  46.953 +    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
  46.954 +                                  Object a4, Object a5, Object a6, Object a7,
  46.955 +                                  Object a8, Object a9)
  46.956 +                { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); return a; }
  46.957 +    private static MethodHandle[] makeFillArrays() {
  46.958 +        ArrayList<MethodHandle> mhs = new ArrayList<>();
  46.959 +        mhs.add(null);  // there is no empty fill; at least a0 is required
  46.960 +        for (;;) {
  46.961 +            MethodHandle mh = findCollector("fillArray", mhs.size(), Object[].class, Integer.class, Object[].class);
  46.962 +            if (mh == null)  break;
  46.963 +            mhs.add(mh);
  46.964 +        }
  46.965 +        assert(mhs.size() == 11);  // current number of methods
  46.966 +        return mhs.toArray(new MethodHandle[0]);
  46.967 +    }
  46.968 +    private static final MethodHandle[] FILL_ARRAYS = makeFillArrays();
  46.969 +
  46.970 +    private static Object[] copyAsReferenceArray(Class<? extends Object[]> arrayType, Object... a) {
  46.971 +        return Arrays.copyOf(a, a.length, arrayType);
  46.972 +    }
  46.973 +    private static Object copyAsPrimitiveArray(Wrapper w, Object... boxes) {
  46.974 +        Object a = w.makeArray(boxes.length);
  46.975 +        w.copyArrayUnboxing(boxes, 0, a, 0, boxes.length);
  46.976 +        return a;
  46.977 +    }
  46.978 +
  46.979 +    /** Return a method handle that takes the indicated number of Object
  46.980 +     *  arguments and returns an Object array of them, as if for varargs.
  46.981 +     */
  46.982 +    public static MethodHandle varargsArray(int nargs) {
  46.983 +        MethodHandle mh = ARRAYS[nargs];
  46.984 +        if (mh != null)  return mh;
  46.985 +        mh = findCollector("array", nargs, Object[].class);
  46.986 +        if (mh != null)  return ARRAYS[nargs] = mh;
  46.987 +        mh = buildVarargsArray(FILL_NEW_ARRAY, ARRAY_IDENTITY, nargs);
  46.988 +        assert(assertCorrectArity(mh, nargs));
  46.989 +        return ARRAYS[nargs] = mh;
  46.990 +    }
  46.991 +
  46.992 +    private static boolean assertCorrectArity(MethodHandle mh, int arity) {
  46.993 +        assert(mh.type().parameterCount() == arity) : "arity != "+arity+": "+mh;
  46.994 +        return true;
  46.995 +    }
  46.996 +
  46.997 +    private static MethodHandle buildVarargsArray(MethodHandle newArray, MethodHandle finisher, int nargs) {
  46.998 +        // Build up the result mh as a sequence of fills like this:
  46.999 +        //   finisher(fill(fill(newArrayWA(23,x1..x10),10,x11..x20),20,x21..x23))
 46.1000 +        // The various fill(_,10*I,___*[J]) are reusable.
 46.1001 +        int leftLen = Math.min(nargs, LEFT_ARGS);  // absorb some arguments immediately
 46.1002 +        int rightLen = nargs - leftLen;
 46.1003 +        MethodHandle leftCollector = newArray.bindTo(nargs);
 46.1004 +        leftCollector = leftCollector.asCollector(Object[].class, leftLen);
 46.1005 +        MethodHandle mh = finisher;
 46.1006 +        if (rightLen > 0) {
 46.1007 +            MethodHandle rightFiller = fillToRight(LEFT_ARGS + rightLen);
 46.1008 +            if (mh == ARRAY_IDENTITY)
 46.1009 +                mh = rightFiller;
 46.1010 +            else
 46.1011 +                mh = MethodHandles.collectArguments(mh, 0, rightFiller);
 46.1012 +        }
 46.1013 +        if (mh == ARRAY_IDENTITY)
 46.1014 +            mh = leftCollector;
 46.1015 +        else
 46.1016 +            mh = MethodHandles.collectArguments(mh, 0, leftCollector);
 46.1017 +        return mh;
 46.1018 +    }
 46.1019 +
 46.1020 +    private static final int LEFT_ARGS = (FILL_ARRAYS.length - 1);
 46.1021 +    private static final MethodHandle[] FILL_ARRAY_TO_RIGHT = new MethodHandle[MAX_ARITY+1];
 46.1022 +    /** fill_array_to_right(N).invoke(a, argL..arg[N-1])
 46.1023 +     *  fills a[L]..a[N-1] with corresponding arguments,
 46.1024 +     *  and then returns a.  The value L is a global constant (LEFT_ARGS).
 46.1025 +     */
 46.1026 +    private static MethodHandle fillToRight(int nargs) {
 46.1027 +        MethodHandle filler = FILL_ARRAY_TO_RIGHT[nargs];
 46.1028 +        if (filler != null)  return filler;
 46.1029 +        filler = buildFiller(nargs);
 46.1030 +        assert(assertCorrectArity(filler, nargs - LEFT_ARGS + 1));
 46.1031 +        return FILL_ARRAY_TO_RIGHT[nargs] = filler;
 46.1032 +    }
 46.1033 +    private static MethodHandle buildFiller(int nargs) {
 46.1034 +        if (nargs <= LEFT_ARGS)
 46.1035 +            return ARRAY_IDENTITY;  // no args to fill; return the array unchanged
 46.1036 +        // we need room for both mh and a in mh.invoke(a, arg*[nargs])
 46.1037 +        final int CHUNK = LEFT_ARGS;
 46.1038 +        int rightLen = nargs % CHUNK;
 46.1039 +        int midLen = nargs - rightLen;
 46.1040 +        if (rightLen == 0) {
 46.1041 +            midLen = nargs - (rightLen = CHUNK);
 46.1042 +            if (FILL_ARRAY_TO_RIGHT[midLen] == null) {
 46.1043 +                // build some precursors from left to right
 46.1044 +                for (int j = LEFT_ARGS % CHUNK; j < midLen; j += CHUNK)
 46.1045 +                    if (j > LEFT_ARGS)  fillToRight(j);
 46.1046 +            }
 46.1047 +        }
 46.1048 +        if (midLen < LEFT_ARGS) rightLen = nargs - (midLen = LEFT_ARGS);
 46.1049 +        assert(rightLen > 0);
 46.1050 +        MethodHandle midFill = fillToRight(midLen);  // recursive fill
 46.1051 +        MethodHandle rightFill = FILL_ARRAYS[rightLen].bindTo(midLen);  // [midLen..nargs-1]
 46.1052 +        assert(midFill.type().parameterCount()   == 1 + midLen - LEFT_ARGS);
 46.1053 +        assert(rightFill.type().parameterCount() == 1 + rightLen);
 46.1054 +
 46.1055 +        // Combine the two fills:
 46.1056 +        //   right(mid(a, x10..x19), x20..x23)
 46.1057 +        // The final product will look like this:
 46.1058 +        //   right(mid(newArrayLeft(24, x0..x9), x10..x19), x20..x23)
 46.1059 +        if (midLen == LEFT_ARGS)
 46.1060 +            return rightFill;
 46.1061 +        else
 46.1062 +            return MethodHandles.collectArguments(rightFill, 0, midFill);
 46.1063 +    }
 46.1064 +
 46.1065 +    // Type-polymorphic version of varargs maker.
 46.1066 +    private static final ClassValue<MethodHandle[]> TYPED_COLLECTORS
 46.1067 +        = new ClassValue<MethodHandle[]>() {
 46.1068 +            @Override
 46.1069 +            protected MethodHandle[] computeValue(Class<?> type) {
 46.1070 +                return new MethodHandle[256];
 46.1071 +            }
 46.1072 +    };
 46.1073 +
 46.1074 +    static final int MAX_JVM_ARITY = 255;  // limit imposed by the JVM
 46.1075 +
 46.1076 +    /** Return a method handle that takes the indicated number of
 46.1077 +     *  typed arguments and returns an array of them.
 46.1078 +     *  The type argument is the array type.
 46.1079 +     */
 46.1080 +    public static MethodHandle varargsArray(Class<?> arrayType, int nargs) {
 46.1081 +        Class<?> elemType = arrayType.getComponentType();
 46.1082 +        if (elemType == null)  throw new IllegalArgumentException("not an array: "+arrayType);
 46.1083 +        // FIXME: Need more special casing and caching here.
 46.1084 +        if (nargs >= MAX_JVM_ARITY/2 - 1) {
 46.1085 +            int slots = nargs;
 46.1086 +            final int MAX_ARRAY_SLOTS = MAX_JVM_ARITY - 1;  // 1 for receiver MH
 46.1087 +            if (arrayType == double[].class || arrayType == long[].class)
 46.1088 +                slots *= 2;
 46.1089 +            if (slots > MAX_ARRAY_SLOTS)
 46.1090 +                throw new IllegalArgumentException("too many arguments: "+arrayType.getSimpleName()+", length "+nargs);
 46.1091 +        }
 46.1092 +        if (elemType == Object.class)
 46.1093 +            return varargsArray(nargs);
 46.1094 +        // other cases:  primitive arrays, subtypes of Object[]
 46.1095 +        MethodHandle cache[] = TYPED_COLLECTORS.get(elemType);
 46.1096 +        MethodHandle mh = nargs < cache.length ? cache[nargs] : null;
 46.1097 +        if (mh != null)  return mh;
 46.1098 +        if (elemType.isPrimitive()) {
 46.1099 +            MethodHandle builder = FILL_NEW_ARRAY;
 46.1100 +            MethodHandle producer = buildArrayProducer(arrayType);
 46.1101 +            mh = buildVarargsArray(builder, producer, nargs);
 46.1102 +        } else {
 46.1103 +            @SuppressWarnings("unchecked")
 46.1104 +            Class<? extends Object[]> objArrayType = (Class<? extends Object[]>) arrayType;
 46.1105 +            Object[] example = Arrays.copyOf(NO_ARGS_ARRAY, 0, objArrayType);
 46.1106 +            MethodHandle builder = FILL_NEW_TYPED_ARRAY.bindTo(example);
 46.1107 +            MethodHandle producer = ARRAY_IDENTITY;
 46.1108 +            mh = buildVarargsArray(builder, producer, nargs);
 46.1109 +        }
 46.1110 +        mh = mh.asType(MethodType.methodType(arrayType, Collections.<Class<?>>nCopies(nargs, elemType)));
 46.1111 +        assert(assertCorrectArity(mh, nargs));
 46.1112 +        if (nargs < cache.length)
 46.1113 +            cache[nargs] = mh;
 46.1114 +        return mh;
 46.1115 +    }
 46.1116 +
 46.1117 +    private static MethodHandle buildArrayProducer(Class<?> arrayType) {
 46.1118 +        Class<?> elemType = arrayType.getComponentType();
 46.1119 +        if (elemType.isPrimitive())
 46.1120 +            return LazyStatics.COPY_AS_PRIMITIVE_ARRAY.bindTo(Wrapper.forPrimitiveType(elemType));
 46.1121 +        else
 46.1122 +            return LazyStatics.COPY_AS_REFERENCE_ARRAY.bindTo(arrayType);
 46.1123 +    }
 46.1124 +
 46.1125 +    // List version of varargs maker.
 46.1126 +
 46.1127 +    private static final List<Object> NO_ARGS_LIST = Arrays.asList(NO_ARGS_ARRAY);
 46.1128 +    private static List<Object> makeList(Object... args) { return Arrays.asList(args); }
 46.1129 +    private static List<Object> list() { return NO_ARGS_LIST; }
 46.1130 +    private static List<Object> list(Object a0)
 46.1131 +                { return makeList(a0); }
 46.1132 +    private static List<Object> list(Object a0, Object a1)
 46.1133 +                { return makeList(a0, a1); }
 46.1134 +    private static List<Object> list(Object a0, Object a1, Object a2)
 46.1135 +                { return makeList(a0, a1, a2); }
 46.1136 +    private static List<Object> list(Object a0, Object a1, Object a2, Object a3)
 46.1137 +                { return makeList(a0, a1, a2, a3); }
 46.1138 +    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
 46.1139 +                                     Object a4)
 46.1140 +                { return makeList(a0, a1, a2, a3, a4); }
 46.1141 +    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
 46.1142 +                                     Object a4, Object a5)
 46.1143 +                { return makeList(a0, a1, a2, a3, a4, a5); }
 46.1144 +    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
 46.1145 +                                     Object a4, Object a5, Object a6)
 46.1146 +                { return makeList(a0, a1, a2, a3, a4, a5, a6); }
 46.1147 +    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
 46.1148 +                                     Object a4, Object a5, Object a6, Object a7)
 46.1149 +                { return makeList(a0, a1, a2, a3, a4, a5, a6, a7); }
 46.1150 +    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
 46.1151 +                                     Object a4, Object a5, Object a6, Object a7,
 46.1152 +                                     Object a8)
 46.1153 +                { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
 46.1154 +    private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
 46.1155 +                                     Object a4, Object a5, Object a6, Object a7,
 46.1156 +                                     Object a8, Object a9)
 46.1157 +                { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
 46.1158 +    private static MethodHandle[] makeLists() {
 46.1159 +        ArrayList<MethodHandle> mhs = new ArrayList<>();
 46.1160 +        for (;;) {
 46.1161 +            MethodHandle mh = findCollector("list", mhs.size(), List.class);
 46.1162 +            if (mh == null)  break;
 46.1163 +            mhs.add(mh);
 46.1164 +        }
 46.1165 +        assert(mhs.size() == 11);  // current number of methods
 46.1166 +        return mhs.toArray(new MethodHandle[MAX_ARITY+1]);
 46.1167 +    }
 46.1168 +    private static final MethodHandle[] LISTS = makeLists();
 46.1169 +
 46.1170 +    /** Return a method handle that takes the indicated number of Object
 46.1171 +     *  arguments and returns a List.
 46.1172 +     */
 46.1173 +    public static MethodHandle varargsList(int nargs) {
 46.1174 +        MethodHandle mh = LISTS[nargs];
 46.1175 +        if (mh != null)  return mh;
 46.1176 +        mh = findCollector("list", nargs, List.class);
 46.1177 +        if (mh != null)  return LISTS[nargs] = mh;
 46.1178 +        return LISTS[nargs] = buildVarargsList(nargs);
 46.1179 +    }
 46.1180 +    private static MethodHandle buildVarargsList(int nargs) {
 46.1181 +        return MethodHandles.filterReturnValue(varargsArray(nargs), LazyStatics.MAKE_LIST);
 46.1182 +    }
 46.1183 +
 46.1184 +    // handy shared exception makers (they simplify the common case code)
 46.1185 +    private static InternalError newInternalError(String message, Throwable cause) {
 46.1186 +        return new InternalError(message, cause);
 46.1187 +    }
 46.1188 +    private static InternalError newInternalError(Throwable cause) {
 46.1189 +        return new InternalError(cause);
 46.1190 +    }
 46.1191 +}
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/rt/emul/compact/src/main/java/sun/invoke/util/VerifyAccess.java	Sat Aug 09 11:12:05 2014 +0200
    47.3 @@ -0,0 +1,301 @@
    47.4 +/*
    47.5 + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
    47.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    47.7 + *
    47.8 + * This code is free software; you can redistribute it and/or modify it
    47.9 + * under the terms of the GNU General Public License version 2 only, as
   47.10 + * published by the Free Software Foundation.  Oracle designates this
   47.11 + * particular file as subject to the "Classpath" exception as provided
   47.12 + * by Oracle in the LICENSE file that accompanied this code.
   47.13 + *
   47.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   47.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   47.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   47.17 + * version 2 for more details (a copy is included in the LICENSE file that
   47.18 + * accompanied this code).
   47.19 + *
   47.20 + * You should have received a copy of the GNU General Public License version
   47.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   47.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   47.23 + *
   47.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   47.25 + * or visit www.oracle.com if you need additional information or have any
   47.26 + * questions.
   47.27 + */
   47.28 +
   47.29 +package sun.invoke.util;
   47.30 +
   47.31 +import java.lang.reflect.Modifier;
   47.32 +import static java.lang.reflect.Modifier.*;
   47.33 +import sun.reflect.Reflection;
   47.34 +
   47.35 +/**
   47.36 + * This class centralizes information about the JVM's linkage access control.
   47.37 + * @author jrose
   47.38 + */
   47.39 +public class VerifyAccess {
   47.40 +
   47.41 +    private VerifyAccess() { }  // cannot instantiate
   47.42 +
   47.43 +    private static final int PACKAGE_ONLY = 0;
   47.44 +    private static final int PACKAGE_ALLOWED = java.lang.invoke.MethodHandles.Lookup.PACKAGE;
   47.45 +    private static final int PROTECTED_OR_PACKAGE_ALLOWED = (PACKAGE_ALLOWED|PROTECTED);
   47.46 +    private static final int ALL_ACCESS_MODES = (PUBLIC|PRIVATE|PROTECTED|PACKAGE_ONLY);
   47.47 +    private static final boolean ALLOW_NESTMATE_ACCESS = false;
   47.48 +
   47.49 +    /**
   47.50 +     * Evaluate the JVM linkage rules for access to the given method
   47.51 +     * on behalf of a caller class which proposes to perform the access.
   47.52 +     * Return true if the caller class has privileges to invoke a method
   47.53 +     * or access a field with the given properties.
   47.54 +     * This requires an accessibility check of the referencing class,
   47.55 +     * plus an accessibility check of the member within the class,
   47.56 +     * which depends on the member's modifier flags.
   47.57 +     * <p>
   47.58 +     * The relevant properties include the defining class ({@code defc})
   47.59 +     * of the member, and its modifier flags ({@code mods}).
   47.60 +     * Also relevant is the class used to make the initial symbolic reference
   47.61 +     * to the member ({@code refc}).  If this latter class is not distinguished,
   47.62 +     * the defining class should be passed for both arguments ({@code defc == refc}).
   47.63 +     * <h3>JVM Specification, 5.4.4 "Access Control"</h3>
   47.64 +     * A field or method R is accessible to a class or interface D if
   47.65 +     * and only if any of the following conditions is true:<ul>
   47.66 +     * <li>R is public.
   47.67 +     * <li>R is protected and is declared in a class C, and D is either
   47.68 +     *     a subclass of C or C itself.  Furthermore, if R is not
   47.69 +     *     static, then the symbolic reference to R must contain a
   47.70 +     *     symbolic reference to a class T, such that T is either a
   47.71 +     *     subclass of D, a superclass of D or D itself.
   47.72 +     * <li>R is either protected or has default access (that is,
   47.73 +     *     neither public nor protected nor private), and is declared
   47.74 +     *     by a class in the same runtime package as D.
   47.75 +     * <li>R is private and is declared in D.
   47.76 +     * </ul>
   47.77 +     * This discussion of access control omits a related restriction
   47.78 +     * on the target of a protected field access or method invocation
   47.79 +     * (the target must be of class D or a subtype of D). That
   47.80 +     * requirement is checked as part of the verification process
   47.81 +     * (5.4.1); it is not part of link-time access control.
   47.82 +     * @param refc the class used in the symbolic reference to the proposed member
   47.83 +     * @param defc the class in which the proposed member is actually defined
   47.84 +     * @param mods modifier flags for the proposed member
   47.85 +     * @param lookupClass the class for which the access check is being made
   47.86 +     * @return true iff the the accessing class can access such a member
   47.87 +     */
   47.88 +    public static boolean isMemberAccessible(Class<?> refc,  // symbolic ref class
   47.89 +                                             Class<?> defc,  // actual def class
   47.90 +                                             int      mods,  // actual member mods
   47.91 +                                             Class<?> lookupClass,
   47.92 +                                             int      allowedModes) {
   47.93 +        if (allowedModes == 0)  return false;
   47.94 +        assert((allowedModes & PUBLIC) != 0 &&
   47.95 +               (allowedModes & ~(ALL_ACCESS_MODES|PACKAGE_ALLOWED)) == 0);
   47.96 +        // The symbolic reference class (refc) must always be fully verified.
   47.97 +        if (!isClassAccessible(refc, lookupClass, allowedModes)) {
   47.98 +            return false;
   47.99 +        }
  47.100 +        // Usually refc and defc are the same, but verify defc also in case they differ.
  47.101 +        if (defc == lookupClass &&
  47.102 +            (allowedModes & PRIVATE) != 0)
  47.103 +            return true;        // easy check; all self-access is OK
  47.104 +        switch (mods & ALL_ACCESS_MODES) {
  47.105 +        case PUBLIC:
  47.106 +            return true;  // already checked above
  47.107 +        case PROTECTED:
  47.108 +            if ((allowedModes & PROTECTED_OR_PACKAGE_ALLOWED) != 0 &&
  47.109 +                isSamePackage(defc, lookupClass))
  47.110 +                return true;
  47.111 +            if ((allowedModes & PROTECTED) == 0)
  47.112 +                return false;
  47.113 +            if ((mods & STATIC) != 0 &&
  47.114 +                !isRelatedClass(refc, lookupClass))
  47.115 +                return false;
  47.116 +            if ((allowedModes & PROTECTED) != 0 &&
  47.117 +                isSuperClass(defc, lookupClass))
  47.118 +                return true;
  47.119 +            return false;
  47.120 +        case PACKAGE_ONLY:  // That is, zero.  Unmarked member is package-only access.
  47.121 +            return ((allowedModes & PACKAGE_ALLOWED) != 0 &&
  47.122 +                    isSamePackage(defc, lookupClass));
  47.123 +        case PRIVATE:
  47.124 +            // Loosened rules for privates follows access rules for inner classes.
  47.125 +            return (ALLOW_NESTMATE_ACCESS &&
  47.126 +                    (allowedModes & PRIVATE) != 0 &&
  47.127 +                    isSamePackageMember(defc, lookupClass));
  47.128 +        default:
  47.129 +            throw new IllegalArgumentException("bad modifiers: "+Modifier.toString(mods));
  47.130 +        }
  47.131 +    }
  47.132 +
  47.133 +    static boolean isRelatedClass(Class<?> refc, Class<?> lookupClass) {
  47.134 +        return (refc == lookupClass ||
  47.135 +                refc.isAssignableFrom(lookupClass) ||
  47.136 +                lookupClass.isAssignableFrom(refc));
  47.137 +    }
  47.138 +
  47.139 +    static boolean isSuperClass(Class<?> defc, Class<?> lookupClass) {
  47.140 +        return defc.isAssignableFrom(lookupClass);
  47.141 +    }
  47.142 +
  47.143 +    static int getClassModifiers(Class<?> c) {
  47.144 +        // This would return the mask stored by javac for the source-level modifiers.
  47.145 +        //   return c.getModifiers();
  47.146 +        // But what we need for JVM access checks are the actual bits from the class header.
  47.147 +        // ...But arrays and primitives are synthesized with their own odd flags:
  47.148 +        if (c.isArray() || c.isPrimitive())
  47.149 +            return c.getModifiers();
  47.150 +        return Reflection.getClassAccessFlags(c);
  47.151 +    }
  47.152 +
  47.153 +    /**
  47.154 +     * Evaluate the JVM linkage rules for access to the given class on behalf of caller.
  47.155 +     * <h3>JVM Specification, 5.4.4 "Access Control"</h3>
  47.156 +     * A class or interface C is accessible to a class or interface D
  47.157 +     * if and only if either of the following conditions are true:<ul>
  47.158 +     * <li>C is public.
  47.159 +     * <li>C and D are members of the same runtime package.
  47.160 +     * </ul>
  47.161 +     * @param refc the symbolic reference class to which access is being checked (C)
  47.162 +     * @param lookupClass the class performing the lookup (D)
  47.163 +     */
  47.164 +    public static boolean isClassAccessible(Class<?> refc, Class<?> lookupClass,
  47.165 +                                            int allowedModes) {
  47.166 +        if (allowedModes == 0)  return false;
  47.167 +        assert((allowedModes & PUBLIC) != 0 &&
  47.168 +               (allowedModes & ~(ALL_ACCESS_MODES|PACKAGE_ALLOWED)) == 0);
  47.169 +        int mods = getClassModifiers(refc);
  47.170 +        if (isPublic(mods))
  47.171 +            return true;
  47.172 +        if ((allowedModes & PACKAGE_ALLOWED) != 0 &&
  47.173 +            isSamePackage(lookupClass, refc))
  47.174 +            return true;
  47.175 +        return false;
  47.176 +    }
  47.177 +
  47.178 +    /**
  47.179 +     * Decide if the given method type, attributed to a member or symbolic
  47.180 +     * reference of a given reference class, is really visible to that class.
  47.181 +     * @param type the supposed type of a member or symbolic reference of refc
  47.182 +     * @param refc the class attempting to make the reference
  47.183 +     */
  47.184 +    public static boolean isTypeVisible(Class<?> type, Class<?> refc) {
  47.185 +        if (type == refc)  return true;  // easy check
  47.186 +        while (type.isArray())  type = type.getComponentType();
  47.187 +        if (type.isPrimitive() || type == Object.class)  return true;
  47.188 +        ClassLoader parent = type.getClassLoader();
  47.189 +        if (parent == null)  return true;
  47.190 +        ClassLoader child  = refc.getClassLoader();
  47.191 +        if (child == null)  return false;
  47.192 +        if (parent == child || loadersAreRelated(parent, child, true))
  47.193 +            return true;
  47.194 +        // Do it the hard way:  Look up the type name from the refc loader.
  47.195 +        try {
  47.196 +            Class<?> res = child.loadClass(type.getName());
  47.197 +            return (type == res);
  47.198 +        } catch (ClassNotFoundException ex) {
  47.199 +            return false;
  47.200 +        }
  47.201 +    }
  47.202 +
  47.203 +    /**
  47.204 +     * Decide if the given method type, attributed to a member or symbolic
  47.205 +     * reference of a given reference class, is really visible to that class.
  47.206 +     * @param type the supposed type of a member or symbolic reference of refc
  47.207 +     * @param refc the class attempting to make the reference
  47.208 +     */
  47.209 +    public static boolean isTypeVisible(java.lang.invoke.MethodType type, Class<?> refc) {
  47.210 +        for (int n = -1, max = type.parameterCount(); n < max; n++) {
  47.211 +            Class<?> ptype = (n < 0 ? type.returnType() : type.parameterType(n));
  47.212 +            if (!isTypeVisible(ptype, refc))
  47.213 +                return false;
  47.214 +        }
  47.215 +        return true;
  47.216 +    }
  47.217 +
  47.218 +    /**
  47.219 +     * Test if two classes have the same class loader and package qualifier.
  47.220 +     * @param class1 a class
  47.221 +     * @param class2 another class
  47.222 +     * @return whether they are in the same package
  47.223 +     */
  47.224 +    public static boolean isSamePackage(Class<?> class1, Class<?> class2) {
  47.225 +        assert(!class1.isArray() && !class2.isArray());
  47.226 +        if (class1 == class2)
  47.227 +            return true;
  47.228 +        if (class1.getClassLoader() != class2.getClassLoader())
  47.229 +            return false;
  47.230 +        String name1 = class1.getName(), name2 = class2.getName();
  47.231 +        int dot = name1.lastIndexOf('.');
  47.232 +        if (dot != name2.lastIndexOf('.'))
  47.233 +            return false;
  47.234 +        for (int i = 0; i < dot; i++) {
  47.235 +            if (name1.charAt(i) != name2.charAt(i))
  47.236 +                return false;
  47.237 +        }
  47.238 +        return true;
  47.239 +    }
  47.240 +
  47.241 +    /** Return the package name for this class.
  47.242 +     */
  47.243 +    public static String getPackageName(Class<?> cls) {
  47.244 +        assert(!cls.isArray());
  47.245 +        String name = cls.getName();
  47.246 +        int dot = name.lastIndexOf('.');
  47.247 +        if (dot < 0)  return "";
  47.248 +        return name.substring(0, dot);
  47.249 +    }
  47.250 +
  47.251 +    /**
  47.252 +     * Test if two classes are defined as part of the same package member (top-level class).
  47.253 +     * If this is true, they can share private access with each other.
  47.254 +     * @param class1 a class
  47.255 +     * @param class2 another class
  47.256 +     * @return whether they are identical or nested together
  47.257 +     */
  47.258 +    public static boolean isSamePackageMember(Class<?> class1, Class<?> class2) {
  47.259 +        if (class1 == class2)
  47.260 +            return true;
  47.261 +        if (!isSamePackage(class1, class2))
  47.262 +            return false;
  47.263 +        if (getOutermostEnclosingClass(class1) != getOutermostEnclosingClass(class2))
  47.264 +            return false;
  47.265 +        return true;
  47.266 +    }
  47.267 +
  47.268 +    private static Class<?> getOutermostEnclosingClass(Class<?> c) {
  47.269 +        Class<?> pkgmem = c;
  47.270 +        for (Class<?> enc = c; (enc = enc.getEnclosingClass()) != null; )
  47.271 +            pkgmem = enc;
  47.272 +        return pkgmem;
  47.273 +    }
  47.274 +
  47.275 +    private static boolean loadersAreRelated(ClassLoader loader1, ClassLoader loader2,
  47.276 +                                             boolean loader1MustBeParent) {
  47.277 +        if (loader1 == loader2 || loader1 == null
  47.278 +                || (loader2 == null && !loader1MustBeParent)) {
  47.279 +            return true;
  47.280 +        }
  47.281 +        for (ClassLoader scan2 = loader2;
  47.282 +                scan2 != null; scan2 = scan2.getParent()) {
  47.283 +            if (scan2 == loader1)  return true;
  47.284 +        }
  47.285 +        if (loader1MustBeParent)  return false;
  47.286 +        // see if loader2 is a parent of loader1:
  47.287 +        for (ClassLoader scan1 = loader1;
  47.288 +                scan1 != null; scan1 = scan1.getParent()) {
  47.289 +            if (scan1 == loader2)  return true;
  47.290 +        }
  47.291 +        return false;
  47.292 +    }
  47.293 +
  47.294 +    /**
  47.295 +     * Is the class loader of parentClass identical to, or an ancestor of,
  47.296 +     * the class loader of childClass?
  47.297 +     * @param parentClass a class
  47.298 +     * @param childClass another class, which may be a descendent of the first class
  47.299 +     * @return whether parentClass precedes or equals childClass in class loader order
  47.300 +     */
  47.301 +    public static boolean classLoaderIsAncestor(Class<?> parentClass, Class<?> childClass) {
  47.302 +        return loadersAreRelated(parentClass.getClassLoader(), childClass.getClassLoader(), true);
  47.303 +    }
  47.304 +}
    48.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2 +++ b/rt/emul/compact/src/main/java/sun/invoke/util/VerifyType.java	Sat Aug 09 11:12:05 2014 +0200
    48.3 @@ -0,0 +1,194 @@
    48.4 +/*
    48.5 + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
    48.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    48.7 + *
    48.8 + * This code is free software; you can redistribute it and/or modify it
    48.9 + * under the terms of the GNU General Public License version 2 only, as
   48.10 + * published by the Free Software Foundation.  Oracle designates this
   48.11 + * particular file as subject to the "Classpath" exception as provided
   48.12 + * by Oracle in the LICENSE file that accompanied this code.
   48.13 + *
   48.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   48.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   48.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   48.17 + * version 2 for more details (a copy is included in the LICENSE file that
   48.18 + * accompanied this code).
   48.19 + *
   48.20 + * You should have received a copy of the GNU General Public License version
   48.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   48.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   48.23 + *
   48.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   48.25 + * or visit www.oracle.com if you need additional information or have any
   48.26 + * questions.
   48.27 + */
   48.28 +
   48.29 +package sun.invoke.util;
   48.30 +
   48.31 +import java.lang.invoke.MethodType;
   48.32 +import sun.invoke.empty.Empty;
   48.33 +
   48.34 +/**
   48.35 + * This class centralizes information about the JVM verifier
   48.36 + * and its requirements about type correctness.
   48.37 + * @author jrose
   48.38 + */
   48.39 +public class VerifyType {
   48.40 +
   48.41 +    private VerifyType() { }  // cannot instantiate
   48.42 +
   48.43 +    /**
   48.44 +     * True if a value can be stacked as the source type and unstacked as the
   48.45 +     * destination type, without violating the JVM's type consistency.
   48.46 +     *
   48.47 +     * @param src the type of a stacked value
   48.48 +     * @param dst the type by which we'd like to treat it
   48.49 +     * @return whether the retyping can be done without motion or reformatting
   48.50 +     */
   48.51 +    public static boolean isNullConversion(Class<?> src, Class<?> dst) {
   48.52 +        if (src == dst)            return true;
   48.53 +        // Verifier allows any interface to be treated as Object:
   48.54 +        if (dst.isInterface())     dst = Object.class;
   48.55 +        if (src.isInterface())     src = Object.class;
   48.56 +        if (src == dst)            return true;  // check again
   48.57 +        if (dst == void.class)     return true;  // drop any return value
   48.58 +        if (isNullType(src))       return !dst.isPrimitive();
   48.59 +        if (!src.isPrimitive())    return dst.isAssignableFrom(src);
   48.60 +        if (!dst.isPrimitive())    return false;
   48.61 +        // Verifier allows an int to carry byte, short, char, or even boolean:
   48.62 +        Wrapper sw = Wrapper.forPrimitiveType(src);
   48.63 +        if (dst == int.class)      return sw.isSubwordOrInt();
   48.64 +        Wrapper dw = Wrapper.forPrimitiveType(dst);
   48.65 +        if (!sw.isSubwordOrInt())  return false;
   48.66 +        if (!dw.isSubwordOrInt())  return false;
   48.67 +        if (!dw.isSigned() && sw.isSigned())  return false;
   48.68 +        return dw.bitWidth() > sw.bitWidth();
   48.69 +    }
   48.70 +
   48.71 +    /**
   48.72 +     * Specialization of isNullConversion to reference types.
   48.73 +     * @param src the type of a stacked value
   48.74 +     * @param dst the reference type by which we'd like to treat it
   48.75 +     * @return whether the retyping can be done without a cast
   48.76 +     */
   48.77 +    public static boolean isNullReferenceConversion(Class<?> src, Class<?> dst) {
   48.78 +        assert(!dst.isPrimitive());
   48.79 +        if (dst.isInterface())  return true;   // verifier allows this
   48.80 +        if (isNullType(src))    return true;
   48.81 +        return dst.isAssignableFrom(src);
   48.82 +    }
   48.83 +
   48.84 +    /**
   48.85 +     * Is the given type java.lang.Null or an equivalent null-only type?
   48.86 +     */
   48.87 +    public static boolean isNullType(Class<?> type) {
   48.88 +        if (type == null)  return false;
   48.89 +        return type == NULL_CLASS
   48.90 +            // This one may also be used as a null type.
   48.91 +            // TO DO: Decide if we really want to legitimize it here.
   48.92 +            // Probably we do, unless java.lang.Null really makes it into Java 7
   48.93 +            //|| type == Void.class
   48.94 +            // Locally known null-only class:
   48.95 +            || type == Empty.class
   48.96 +            ;
   48.97 +    }
   48.98 +    private static final Class<?> NULL_CLASS;
   48.99 +    static {
  48.100 +        Class<?> nullClass = null;
  48.101 +        try {
  48.102 +            nullClass = Class.forName("java.lang.Null");
  48.103 +        } catch (ClassNotFoundException ex) {
  48.104 +            // OK, we'll cope
  48.105 +        }
  48.106 +        NULL_CLASS = nullClass;
  48.107 +    }
  48.108 +
  48.109 +    /**
  48.110 +     * True if a method handle can receive a call under a slightly different
  48.111 +     * method type, without moving or reformatting any stack elements.
  48.112 +     *
  48.113 +     * @param call the type of call being made
  48.114 +     * @param recv the type of the method handle receiving the call
  48.115 +     * @return whether the retyping can be done without motion or reformatting
  48.116 +     */
  48.117 +    public static boolean isNullConversion(MethodType call, MethodType recv) {
  48.118 +        if (call == recv)  return true;
  48.119 +        int len = call.parameterCount();
  48.120 +        if (len != recv.parameterCount())  return false;
  48.121 +        for (int i = 0; i < len; i++)
  48.122 +            if (!isNullConversion(call.parameterType(i), recv.parameterType(i)))
  48.123 +                return false;
  48.124 +        return isNullConversion(recv.returnType(), call.returnType());
  48.125 +    }
  48.126 +
  48.127 +    /**
  48.128 +     * Determine if the JVM verifier allows a value of type call to be
  48.129 +     * passed to a formal parameter (or return variable) of type recv.
  48.130 +     * Returns 1 if the verifier allows the types to match without conversion.
  48.131 +     * Returns -1 if the types can be made to match by a JVM-supported adapter.
  48.132 +     * Cases supported are:
  48.133 +     * <ul><li>checkcast
  48.134 +     * </li><li>conversion between any two integral types (but not floats)
  48.135 +     * </li><li>unboxing from a wrapper to its corresponding primitive type
  48.136 +     * </li><li>conversion in either direction between float and double
  48.137 +     * </li></ul>
  48.138 +     * (Autoboxing is not supported here; it must be done via Java code.)
  48.139 +     * Returns 0 otherwise.
  48.140 +     */
  48.141 +    public static int canPassUnchecked(Class<?> src, Class<?> dst) {
  48.142 +        if (src == dst)
  48.143 +            return 1;
  48.144 +
  48.145 +        if (dst.isPrimitive()) {
  48.146 +            if (dst == void.class)
  48.147 +                // Return anything to a caller expecting void.
  48.148 +                // This is a property of the implementation, which links
  48.149 +                // return values via a register rather than via a stack push.
  48.150 +                // This makes it possible to ignore cleanly.
  48.151 +                return 1;
  48.152 +            if (src == void.class)
  48.153 +                return 0;  // void-to-something?
  48.154 +            if (!src.isPrimitive())
  48.155 +                // Cannot pass a reference to any primitive type (exc. void).
  48.156 +                return 0;
  48.157 +            Wrapper sw = Wrapper.forPrimitiveType(src);
  48.158 +            Wrapper dw = Wrapper.forPrimitiveType(dst);
  48.159 +            if (sw.isSubwordOrInt() && dw.isSubwordOrInt()) {
  48.160 +                if (sw.bitWidth() >= dw.bitWidth())
  48.161 +                    return -1;   // truncation may be required
  48.162 +                if (!dw.isSigned() && sw.isSigned())
  48.163 +                    return -1;   // sign elimination may be required
  48.164 +                return 1;
  48.165 +            }
  48.166 +            if (src == float.class || dst == float.class) {
  48.167 +                if (src == double.class || dst == double.class)
  48.168 +                    return -1;   // floating conversion may be required
  48.169 +                else
  48.170 +                    return 0;    // other primitive conversions NYI
  48.171 +            } else {
  48.172 +                // all fixed-point conversions are supported
  48.173 +                return 0;
  48.174 +            }
  48.175 +        } else if (src.isPrimitive()) {
  48.176 +            // Cannot pass a primitive to any reference type.
  48.177 +            // (Maybe allow null.class?)
  48.178 +            return 0;
  48.179 +        }
  48.180 +
  48.181 +        // Handle reference types in the rest of the block:
  48.182 +
  48.183 +        // The verifier treats interfaces exactly like Object.
  48.184 +        if (isNullReferenceConversion(src, dst))
  48.185 +            // pass any reference to object or an arb. interface
  48.186 +            return 1;
  48.187 +        // else it's a definite "maybe" (cast is required)
  48.188 +        return -1;
  48.189 +    }
  48.190 +
  48.191 +    public static boolean isSpreadArgType(Class<?> spreadArg) {
  48.192 +        return spreadArg.isArray();
  48.193 +    }
  48.194 +    public static Class<?> spreadArgElementType(Class<?> spreadArg, int i) {
  48.195 +        return spreadArg.getComponentType();
  48.196 +    }
  48.197 +}
    49.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.2 +++ b/rt/emul/compact/src/main/java/sun/invoke/util/Wrapper.java	Sat Aug 09 11:12:05 2014 +0200
    49.3 @@ -0,0 +1,614 @@
    49.4 +/*
    49.5 + * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
    49.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    49.7 + *
    49.8 + * This code is free software; you can redistribute it and/or modify it
    49.9 + * under the terms of the GNU General Public License version 2 only, as
   49.10 + * published by the Free Software Foundation.  Oracle designates this
   49.11 + * particular file as subject to the "Classpath" exception as provided
   49.12 + * by Oracle in the LICENSE file that accompanied this code.
   49.13 + *
   49.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   49.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   49.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   49.17 + * version 2 for more details (a copy is included in the LICENSE file that
   49.18 + * accompanied this code).
   49.19 + *
   49.20 + * You should have received a copy of the GNU General Public License version
   49.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   49.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   49.23 + *
   49.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   49.25 + * or visit www.oracle.com if you need additional information or have any
   49.26 + * questions.
   49.27 + */
   49.28 +
   49.29 +package sun.invoke.util;
   49.30 +
   49.31 +public enum Wrapper {
   49.32 +    BOOLEAN(Boolean.class, boolean.class, 'Z', (Boolean)false, new boolean[0], Format.unsigned(1)),
   49.33 +    // These must be in the order defined for widening primitive conversions in JLS 5.1.2
   49.34 +    BYTE(Byte.class, byte.class, 'B', (Byte)(byte)0, new byte[0], Format.signed(8)),
   49.35 +    SHORT(Short.class, short.class, 'S', (Short)(short)0, new short[0], Format.signed(16)),
   49.36 +    CHAR(Character.class, char.class, 'C', (Character)(char)0, new char[0], Format.unsigned(16)),
   49.37 +    INT(Integer.class, int.class, 'I', (Integer)/*(int)*/0, new int[0], Format.signed(32)),
   49.38 +    LONG(Long.class, long.class, 'J', (Long)(long)0, new long[0], Format.signed(64)),
   49.39 +    FLOAT(Float.class, float.class, 'F', (Float)(float)0, new float[0], Format.floating(32)),
   49.40 +    DOUBLE(Double.class, double.class, 'D', (Double)(double)0, new double[0], Format.floating(64)),
   49.41 +    //NULL(Null.class, null.class, 'N', null, null, Format.other(1)),
   49.42 +    OBJECT(Object.class, Object.class, 'L', null, new Object[0], Format.other(1)),
   49.43 +    // VOID must be the last type, since it is "assignable" from any other type:
   49.44 +    VOID(Void.class, void.class, 'V', null, null, Format.other(0)),
   49.45 +    ;
   49.46 +
   49.47 +    private final Class<?> wrapperType;
   49.48 +    private final Class<?> primitiveType;
   49.49 +    private final char     basicTypeChar;
   49.50 +    private final Object   zero;
   49.51 +    private final Object   emptyArray;
   49.52 +    private final int      format;
   49.53 +    private final String   wrapperSimpleName;
   49.54 +    private final String   primitiveSimpleName;
   49.55 +
   49.56 +    private Wrapper(Class<?> wtype, Class<?> ptype, char tchar, Object zero, Object emptyArray, int format) {
   49.57 +        this.wrapperType = wtype;
   49.58 +        this.primitiveType = ptype;
   49.59 +        this.basicTypeChar = tchar;
   49.60 +        this.zero = zero;
   49.61 +        this.emptyArray = emptyArray;
   49.62 +        this.format = format;
   49.63 +        this.wrapperSimpleName = wtype.getSimpleName();
   49.64 +        this.primitiveSimpleName = ptype.getSimpleName();
   49.65 +    }
   49.66 +
   49.67 +    /** For debugging, give the details of this wrapper. */
   49.68 +    public String detailString() {
   49.69 +        return wrapperSimpleName+
   49.70 +                java.util.Arrays.asList(wrapperType, primitiveType,
   49.71 +                basicTypeChar, zero,
   49.72 +                "0x"+Integer.toHexString(format));
   49.73 +    }
   49.74 +
   49.75 +    private static abstract class Format {
   49.76 +        static final int SLOT_SHIFT = 0, SIZE_SHIFT = 2, KIND_SHIFT = 12;
   49.77 +        static final int
   49.78 +                SIGNED   = (-1) << KIND_SHIFT,
   49.79 +                UNSIGNED = 0    << KIND_SHIFT,
   49.80 +                FLOATING = 1    << KIND_SHIFT;
   49.81 +        static final int
   49.82 +                SLOT_MASK = ((1<<(SIZE_SHIFT-SLOT_SHIFT))-1),
   49.83 +                SIZE_MASK = ((1<<(KIND_SHIFT-SIZE_SHIFT))-1);
   49.84 +        static int format(int kind, int size, int slots) {
   49.85 +            assert(((kind >> KIND_SHIFT) << KIND_SHIFT) == kind);
   49.86 +            assert((size & (size-1)) == 0); // power of two
   49.87 +            assert((kind == SIGNED)   ? (size > 0) :
   49.88 +                   (kind == UNSIGNED) ? (size > 0) :
   49.89 +                   (kind == FLOATING) ? (size == 32 || size == 64)  :
   49.90 +                   false);
   49.91 +            assert((slots == 2) ? (size == 64) :
   49.92 +                   (slots == 1) ? (size <= 32) :
   49.93 +                   false);
   49.94 +            return kind | (size << SIZE_SHIFT) | (slots << SLOT_SHIFT);
   49.95 +        }
   49.96 +        static final int
   49.97 +                INT      = SIGNED   | (32 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
   49.98 +                SHORT    = SIGNED   | (16 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
   49.99 +                BOOLEAN  = UNSIGNED | (1  << SIZE_SHIFT) | (1 << SLOT_SHIFT),
  49.100 +                CHAR     = UNSIGNED | (16 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
  49.101 +                FLOAT    = FLOATING | (32 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
  49.102 +                VOID     = UNSIGNED | (0  << SIZE_SHIFT) | (0 << SLOT_SHIFT),
  49.103 +                NUM_MASK = (-1) << SIZE_SHIFT;
  49.104 +        static int signed(int size)   { return format(SIGNED,   size, (size > 32 ? 2 : 1)); }
  49.105 +        static int unsigned(int size) { return format(UNSIGNED, size, (size > 32 ? 2 : 1)); }
  49.106 +        static int floating(int size) { return format(FLOATING, size, (size > 32 ? 2 : 1)); }
  49.107 +        static int other(int slots)   { return slots << SLOT_SHIFT; }
  49.108 +    }
  49.109 +
  49.110 +    /// format queries:
  49.111 +
  49.112 +    /** How many bits are in the wrapped value?  Returns 0 for OBJECT or VOID. */
  49.113 +    public int     bitWidth()      { return (format >> Format.SIZE_SHIFT) & Format.SIZE_MASK; }
  49.114 +    /** How many JVM stack slots occupied by the wrapped value?  Returns 0 for VOID. */
  49.115 +    public int     stackSlots()    { return (format >> Format.SLOT_SHIFT) & Format.SLOT_MASK; }
  49.116 +    /** Does the wrapped value occupy a single JVM stack slot? */
  49.117 +    public boolean isSingleWord()  { return (format & (1 << Format.SLOT_SHIFT)) != 0; }
  49.118 +    /** Does the wrapped value occupy two JVM stack slots? */
  49.119 +    public boolean isDoubleWord()  { return (format & (2 << Format.SLOT_SHIFT)) != 0; }
  49.120 +    /** Is the wrapped type numeric (not void or object)? */
  49.121 +    public boolean isNumeric()     { return (format & Format.NUM_MASK) != 0; }
  49.122 +    /** Is the wrapped type a primitive other than float, double, or void? */
  49.123 +    public boolean isIntegral()    { return isNumeric() && format < Format.FLOAT; }
  49.124 +    /** Is the wrapped type one of int, boolean, byte, char, or short? */
  49.125 +    public boolean isSubwordOrInt() { return isIntegral() && isSingleWord(); }
  49.126 +    /* Is the wrapped value a signed integral type (one of byte, short, int, or long)? */
  49.127 +    public boolean isSigned()      { return format < Format.VOID; }
  49.128 +    /* Is the wrapped value an unsigned integral type (one of boolean or char)? */
  49.129 +    public boolean isUnsigned()    { return format >= Format.BOOLEAN && format < Format.FLOAT; }
  49.130 +    /** Is the wrapped type either float or double? */
  49.131 +    public boolean isFloating()    { return format >= Format.FLOAT; }
  49.132 +    /** Is the wrapped type either void or a reference? */
  49.133 +    public boolean isOther()       { return (format & ~Format.SLOT_MASK) == 0; }
  49.134 +
  49.135 +    /** Does the JLS 5.1.2 allow a variable of this wrapper's
  49.136 +     *  primitive type to be assigned from a value of the given wrapper's primitive type?
  49.137 +     *  Cases:
  49.138 +     *  <ul>
  49.139 +     *  <li>unboxing followed by widening primitive conversion
  49.140 +     *  <li>any type converted to {@code void} (i.e., dropping a method call's value)
  49.141 +     *  <li>boxing conversion followed by widening reference conversion to {@code Object}
  49.142 +     *  </ul>
  49.143 +     *  These are the cases allowed by MethodHandle.asType.
  49.144 +     */
  49.145 +    public boolean isConvertibleFrom(Wrapper source) {
  49.146 +        if (this == source)  return true;
  49.147 +        if (this.compareTo(source) < 0) {
  49.148 +            // At best, this is a narrowing conversion.
  49.149 +            return false;
  49.150 +        }
  49.151 +        // All conversions are allowed in the enum order between floats and signed ints.
  49.152 +        // First detect non-signed non-float types (boolean, char, Object, void).
  49.153 +        boolean floatOrSigned = (((this.format & source.format) & Format.SIGNED) != 0);
  49.154 +        if (!floatOrSigned) {
  49.155 +            if (this.isOther())  return true;
  49.156 +            // can convert char to int or wider, but nothing else
  49.157 +            if (source.format == Format.CHAR)  return true;
  49.158 +            // no other conversions are classified as widening
  49.159 +            return false;
  49.160 +        }
  49.161 +        // All signed and float conversions in the enum order are widening.
  49.162 +        assert(this.isFloating() || this.isSigned());
  49.163 +        assert(source.isFloating() || source.isSigned());
  49.164 +        return true;
  49.165 +    }
  49.166 +
  49.167 +    static { assert(checkConvertibleFrom()); }
  49.168 +    private static boolean checkConvertibleFrom() {
  49.169 +        // Check the matrix for correct classification of widening conversions.
  49.170 +        for (Wrapper w : values()) {
  49.171 +            assert(w.isConvertibleFrom(w));
  49.172 +            assert(VOID.isConvertibleFrom(w));
  49.173 +            if (w != VOID) {
  49.174 +                assert(OBJECT.isConvertibleFrom(w));
  49.175 +                assert(!w.isConvertibleFrom(VOID));
  49.176 +            }
  49.177 +            // check relations with unsigned integral types:
  49.178 +            if (w != CHAR) {
  49.179 +                assert(!CHAR.isConvertibleFrom(w));
  49.180 +                if (!w.isConvertibleFrom(INT))
  49.181 +                    assert(!w.isConvertibleFrom(CHAR));
  49.182 +            }
  49.183 +            if (w != BOOLEAN) {
  49.184 +                assert(!BOOLEAN.isConvertibleFrom(w));
  49.185 +                if (w != VOID && w != OBJECT)
  49.186 +                    assert(!w.isConvertibleFrom(BOOLEAN));
  49.187 +            }
  49.188 +            // check relations with signed integral types:
  49.189 +            if (w.isSigned()) {
  49.190 +                for (Wrapper x : values()) {
  49.191 +                    if (w == x)  continue;
  49.192 +                    if (x.isFloating())
  49.193 +                        assert(!w.isConvertibleFrom(x));
  49.194 +                    else if (x.isSigned()) {
  49.195 +                        if (w.compareTo(x) < 0)
  49.196 +                            assert(!w.isConvertibleFrom(x));
  49.197 +                        else
  49.198 +                            assert(w.isConvertibleFrom(x));
  49.199 +                    }
  49.200 +                }
  49.201 +            }
  49.202 +            // check relations with floating types:
  49.203 +            if (w.isFloating()) {
  49.204 +                for (Wrapper x : values()) {
  49.205 +                    if (w == x)  continue;
  49.206 +                    if (x.isSigned())
  49.207 +                        assert(w.isConvertibleFrom(x));
  49.208 +                    else if (x.isFloating()) {
  49.209 +                        if (w.compareTo(x) < 0)
  49.210 +                            assert(!w.isConvertibleFrom(x));
  49.211 +                        else
  49.212 +                            assert(w.isConvertibleFrom(x));
  49.213 +                    }
  49.214 +                }
  49.215 +            }
  49.216 +        }
  49.217 +        return true;  // i.e., assert(true)
  49.218 +    }
  49.219 +
  49.220 +    /** Produce a zero value for the given wrapper type.
  49.221 +     *  This will be a numeric zero for a number or character,
  49.222 +     *  false for a boolean, and null for a reference or void.
  49.223 +     *  The common thread is that this is what is contained
  49.224 +     *  in a default-initialized variable of the given primitive
  49.225 +     *  type.  (For void, it is what a reflective method returns
  49.226 +     *  instead of no value at all.)
  49.227 +     */
  49.228 +    public Object zero() { return zero; }
  49.229 +
  49.230 +    /** Produce a zero value for the given wrapper type T.
  49.231 +     *  The optional argument must a type compatible with this wrapper.
  49.232 +     *  Equivalent to {@code this.cast(this.zero(), type)}.
  49.233 +     */
  49.234 +    public <T> T zero(Class<T> type) { return convert(zero, type); }
  49.235 +
  49.236 +//    /** Produce a wrapper for the given wrapper or primitive type. */
  49.237 +//    public static Wrapper valueOf(Class<?> type) {
  49.238 +//        if (isPrimitiveType(type))
  49.239 +//            return forPrimitiveType(type);
  49.240 +//        else
  49.241 +//            return forWrapperType(type);
  49.242 +//    }
  49.243 +
  49.244 +    /** Return the wrapper that wraps values of the given type.
  49.245 +     *  The type may be {@code Object}, meaning the {@code OBJECT} wrapper.
  49.246 +     *  Otherwise, the type must be a primitive.
  49.247 +     *  @throws IllegalArgumentException for unexpected types
  49.248 +     */
  49.249 +    public static Wrapper forPrimitiveType(Class<?> type) {
  49.250 +        Wrapper w = findPrimitiveType(type);
  49.251 +        if (w != null)  return w;
  49.252 +        if (type.isPrimitive())
  49.253 +            throw new InternalError(); // redo hash function
  49.254 +        throw newIllegalArgumentException("not primitive: "+type);
  49.255 +    }
  49.256 +
  49.257 +    static Wrapper findPrimitiveType(Class<?> type) {
  49.258 +        Wrapper w = FROM_PRIM[hashPrim(type)];
  49.259 +        if (w != null && w.primitiveType == type) {
  49.260 +            return w;
  49.261 +        }
  49.262 +        return null;
  49.263 +    }
  49.264 +
  49.265 +    /** Return the wrapper that wraps values into the given wrapper type.
  49.266 +     *  If it is {@code Object}, return {@code OBJECT}.
  49.267 +     *  Otherwise, it must be a wrapper type.
  49.268 +     *  The type must not be a primitive type.
  49.269 +     *  @throws IllegalArgumentException for unexpected types
  49.270 +     */
  49.271 +    public static Wrapper forWrapperType(Class<?> type) {
  49.272 +        Wrapper w = findWrapperType(type);
  49.273 +        if (w != null)  return w;
  49.274 +        for (Wrapper x : values())
  49.275 +            if (x.wrapperType == type)
  49.276 +                throw new InternalError(); // redo hash function
  49.277 +        throw newIllegalArgumentException("not wrapper: "+type);
  49.278 +    }
  49.279 +
  49.280 +    static Wrapper findWrapperType(Class<?> type) {
  49.281 +        Wrapper w = FROM_WRAP[hashWrap(type)];
  49.282 +        if (w != null && w.wrapperType == type) {
  49.283 +            return w;
  49.284 +        }
  49.285 +        return null;
  49.286 +    }
  49.287 +
  49.288 +    /** Return the wrapper that corresponds to the given bytecode
  49.289 +     *  signature character.  Return {@code OBJECT} for the character 'L'.
  49.290 +     *  @throws IllegalArgumentException for any non-signature character or {@code '['}.
  49.291 +     */
  49.292 +    public static Wrapper forBasicType(char type) {
  49.293 +        Wrapper w = FROM_CHAR[hashChar(type)];
  49.294 +        if (w != null && w.basicTypeChar == type) {
  49.295 +            return w;
  49.296 +        }
  49.297 +        for (Wrapper x : values())
  49.298 +            if (w.basicTypeChar == type)
  49.299 +                throw new InternalError(); // redo hash function
  49.300 +        throw newIllegalArgumentException("not basic type char: "+type);
  49.301 +    }
  49.302 +
  49.303 +    /** Return the wrapper for the given type, if it is
  49.304 +     *  a primitive type, else return {@code OBJECT}.
  49.305 +     */
  49.306 +    public static Wrapper forBasicType(Class<?> type) {
  49.307 +        if (type.isPrimitive())
  49.308 +            return forPrimitiveType(type);
  49.309 +        return OBJECT;  // any reference, including wrappers or arrays
  49.310 +    }
  49.311 +
  49.312 +    // Note on perfect hashes:
  49.313 +    //   for signature chars c, do (c + (c >> 1)) % 16
  49.314 +    //   for primitive type names n, do (n[0] + n[2]) % 16
  49.315 +    // The type name hash works for both primitive and wrapper names.
  49.316 +    // You can add "java/lang/Object" to the primitive names.
  49.317 +    // But you add the wrapper name Object, use (n[2] + (3*n[1])) % 16.
  49.318 +    private static final Wrapper[] FROM_PRIM = new Wrapper[16];
  49.319 +    private static final Wrapper[] FROM_WRAP = new Wrapper[16];
  49.320 +    private static final Wrapper[] FROM_CHAR = new Wrapper[16];
  49.321 +    private static int hashPrim(Class<?> x) {
  49.322 +        String xn = x.getName();
  49.323 +        if (xn.length() < 3)  return 0;
  49.324 +        return (xn.charAt(0) + xn.charAt(2)) % 16;
  49.325 +    }
  49.326 +    private static int hashWrap(Class<?> x) {
  49.327 +        String xn = x.getName();
  49.328 +        final int offset = 10; assert(offset == "java.lang.".length());
  49.329 +        if (xn.length() < offset+3)  return 0;
  49.330 +        return (3*xn.charAt(offset+1) + xn.charAt(offset+2)) % 16;
  49.331 +    }
  49.332 +    private static int hashChar(char x) {
  49.333 +        return (x + (x >> 1)) % 16;
  49.334 +    }
  49.335 +    static {
  49.336 +        for (Wrapper w : values()) {
  49.337 +            int pi = hashPrim(w.primitiveType);
  49.338 +            int wi = hashWrap(w.wrapperType);
  49.339 +            int ci = hashChar(w.basicTypeChar);
  49.340 +            assert(FROM_PRIM[pi] == null);
  49.341 +            assert(FROM_WRAP[wi] == null);
  49.342 +            assert(FROM_CHAR[ci] == null);
  49.343 +            FROM_PRIM[pi] = w;
  49.344 +            FROM_WRAP[wi] = w;
  49.345 +            FROM_CHAR[ci] = w;
  49.346 +        }
  49.347 +        //assert(jdk.sun.invoke.util.WrapperTest.test(false));
  49.348 +    }
  49.349 +
  49.350 +    /** What is the primitive type wrapped by this wrapper? */
  49.351 +    public Class<?> primitiveType() { return primitiveType; }
  49.352 +
  49.353 +    /** What is the wrapper type for this wrapper? */
  49.354 +    public Class<?> wrapperType() { return wrapperType; }
  49.355 +
  49.356 +    /** What is the wrapper type for this wrapper?
  49.357 +     * Otherwise, the example type must be the wrapper type,
  49.358 +     * or the corresponding primitive type.
  49.359 +     * (For {@code OBJECT}, the example type can be any non-primitive,
  49.360 +     * and is normalized to {@code Object.class}.)
  49.361 +     * The resulting class type has the same type parameter.
  49.362 +     */
  49.363 +    public <T> Class<T> wrapperType(Class<T> exampleType) {
  49.364 +        if (exampleType == wrapperType) {
  49.365 +            return exampleType;
  49.366 +        } else if (exampleType == primitiveType ||
  49.367 +                   wrapperType == Object.class ||
  49.368 +                   exampleType.isInterface()) {
  49.369 +            return forceType(wrapperType, exampleType);
  49.370 +        }
  49.371 +        throw newClassCastException(exampleType, primitiveType);
  49.372 +    }
  49.373 +
  49.374 +    private static ClassCastException newClassCastException(Class<?> actual, Class<?> expected) {
  49.375 +        return new ClassCastException(actual + " is not compatible with " + expected);
  49.376 +    }
  49.377 +
  49.378 +    /** If {@code type} is a primitive type, return the corresponding
  49.379 +     *  wrapper type, else return {@code type} unchanged.
  49.380 +     */
  49.381 +    public static <T> Class<T> asWrapperType(Class<T> type) {
  49.382 +        if (type.isPrimitive()) {
  49.383 +            return forPrimitiveType(type).wrapperType(type);
  49.384 +        }
  49.385 +        return type;
  49.386 +    }
  49.387 +
  49.388 +    /** If {@code type} is a wrapper type, return the corresponding
  49.389 +     *  primitive type, else return {@code type} unchanged.
  49.390 +     */
  49.391 +    public static <T> Class<T> asPrimitiveType(Class<T> type) {
  49.392 +        Wrapper w = findWrapperType(type);
  49.393 +        if (w != null) {
  49.394 +            return forceType(w.primitiveType(), type);
  49.395 +        }
  49.396 +        return type;
  49.397 +    }
  49.398 +
  49.399 +    /** Query:  Is the given type a wrapper, such as {@code Integer} or {@code Void}? */
  49.400 +    public static boolean isWrapperType(Class<?> type) {
  49.401 +        return findWrapperType(type) != null;
  49.402 +    }
  49.403 +
  49.404 +    /** Query:  Is the given type a primitive, such as {@code int} or {@code void}? */
  49.405 +    public static boolean isPrimitiveType(Class<?> type) {
  49.406 +        return type.isPrimitive();
  49.407 +    }
  49.408 +
  49.409 +    /** What is the bytecode signature character for this type?
  49.410 +     *  All non-primitives, including array types, report as 'L', the signature character for references.
  49.411 +     */
  49.412 +    public static char basicTypeChar(Class<?> type) {
  49.413 +        if (!type.isPrimitive())
  49.414 +            return 'L';
  49.415 +        else
  49.416 +            return forPrimitiveType(type).basicTypeChar();
  49.417 +    }
  49.418 +
  49.419 +    /** What is the bytecode signature character for this wrapper's
  49.420 +     *  primitive type?
  49.421 +     */
  49.422 +    public char basicTypeChar() { return basicTypeChar; }
  49.423 +
  49.424 +    /** What is the simple name of the wrapper type?
  49.425 +     */
  49.426 +    public String wrapperSimpleName() { return wrapperSimpleName; }
  49.427 +
  49.428 +    /** What is the simple name of the primitive type?
  49.429 +     */
  49.430 +    public String primitiveSimpleName() { return primitiveSimpleName; }
  49.431 +
  49.432 +//    /** Wrap a value in the given type, which may be either a primitive or wrapper type.
  49.433 +//     *  Performs standard primitive conversions, including truncation and float conversions.
  49.434 +//     */
  49.435 +//    public static <T> T wrap(Object x, Class<T> type) {
  49.436 +//        return Wrapper.valueOf(type).cast(x, type);
  49.437 +//    }
  49.438 +
  49.439 +    /** Cast a wrapped value to the given type, which may be either a primitive or wrapper type.
  49.440 +     *  The given target type must be this wrapper's primitive or wrapper type.
  49.441 +     *  If this wrapper is OBJECT, the target type may also be an interface, perform no runtime check.
  49.442 +     *  Performs standard primitive conversions, including truncation and float conversions.
  49.443 +     *  The given type must be compatible with this wrapper.  That is, it must either
  49.444 +     *  be the wrapper type (or a subtype, in the case of {@code OBJECT}) or else
  49.445 +     *  it must be the wrapper's primitive type.
  49.446 +     *  Primitive conversions are only performed if the given type is itself a primitive.
  49.447 +     *  @throws ClassCastException if the given type is not compatible with this wrapper
  49.448 +     */
  49.449 +    public <T> T cast(Object x, Class<T> type) {
  49.450 +        return convert(x, type, true);
  49.451 +    }
  49.452 +
  49.453 +    /** Convert a wrapped value to the given type.
  49.454 +     *  The given target type must be this wrapper's primitive or wrapper type.
  49.455 +     *  This is equivalent to {@link #cast}, except that it refuses to perform
  49.456 +     *  narrowing primitive conversions.
  49.457 +     */
  49.458 +    public <T> T convert(Object x, Class<T> type) {
  49.459 +        return convert(x, type, false);
  49.460 +    }
  49.461 +
  49.462 +    private <T> T convert(Object x, Class<T> type, boolean isCast) {
  49.463 +        if (this == OBJECT) {
  49.464 +            // If the target wrapper is OBJECT, just do a reference cast.
  49.465 +            // If the target type is an interface, perform no runtime check.
  49.466 +            // (This loophole is safe, and is allowed by the JVM verifier.)
  49.467 +            // If the target type is a primitive, change it to a wrapper.
  49.468 +            assert(!type.isPrimitive());
  49.469 +            if (!type.isInterface())
  49.470 +                type.cast(x);
  49.471 +            @SuppressWarnings("unchecked")
  49.472 +            T result = (T) x;  // unchecked warning is expected here
  49.473 +            return result;
  49.474 +        }
  49.475 +        Class<T> wtype = wrapperType(type);
  49.476 +        if (wtype.isInstance(x)) {
  49.477 +            return wtype.cast(x);
  49.478 +        }
  49.479 +        if (!isCast) {
  49.480 +            Class<?> sourceType = x.getClass();  // throw NPE if x is null
  49.481 +            Wrapper source = findWrapperType(sourceType);
  49.482 +            if (source == null || !this.isConvertibleFrom(source)) {
  49.483 +                throw newClassCastException(wtype, sourceType);
  49.484 +            }
  49.485 +        } else if (x == null) {
  49.486 +            @SuppressWarnings("unchecked")
  49.487 +            T z = (T) zero;
  49.488 +            return z;
  49.489 +        }
  49.490 +        @SuppressWarnings("unchecked")
  49.491 +        T result = (T) wrap(x);  // unchecked warning is expected here
  49.492 +        assert (result == null ? Void.class : result.getClass()) == wtype;
  49.493 +        return result;
  49.494 +    }
  49.495 +
  49.496 +    /** Cast a reference type to another reference type.
  49.497 +     * If the target type is an interface, perform no runtime check.
  49.498 +     * (This loophole is safe, and is allowed by the JVM verifier.)
  49.499 +     * If the target type is a primitive, change it to a wrapper.
  49.500 +     */
  49.501 +    static <T> Class<T> forceType(Class<?> type, Class<T> exampleType) {
  49.502 +        boolean z = (type == exampleType ||
  49.503 +               type.isPrimitive() && forPrimitiveType(type) == findWrapperType(exampleType) ||
  49.504 +               exampleType.isPrimitive() && forPrimitiveType(exampleType) == findWrapperType(type) ||
  49.505 +               type == Object.class && !exampleType.isPrimitive());
  49.506 +        if (!z)
  49.507 +            System.out.println(type+" <= "+exampleType);
  49.508 +        assert(type == exampleType ||
  49.509 +               type.isPrimitive() && forPrimitiveType(type) == findWrapperType(exampleType) ||
  49.510 +               exampleType.isPrimitive() && forPrimitiveType(exampleType) == findWrapperType(type) ||
  49.511 +               type == Object.class && !exampleType.isPrimitive());
  49.512 +        @SuppressWarnings("unchecked")
  49.513 +        Class<T> result = (Class<T>) type;  // unchecked warning is expected here
  49.514 +        return result;
  49.515 +    }
  49.516 +
  49.517 +    /** Wrap a value in this wrapper's type.
  49.518 +     * Performs standard primitive conversions, including truncation and float conversions.
  49.519 +     * Performs returns the unchanged reference for {@code OBJECT}.
  49.520 +     * Returns null for {@code VOID}.
  49.521 +     * Returns a zero value for a null input.
  49.522 +     * @throws ClassCastException if this wrapper is numeric and the operand
  49.523 +     *                            is not a number, character, boolean, or null
  49.524 +     */
  49.525 +    public Object wrap(Object x) {
  49.526 +        // do non-numeric wrappers first
  49.527 +        switch (basicTypeChar) {
  49.528 +            case 'L': return x;
  49.529 +            case 'V': return null;
  49.530 +        }
  49.531 +        Number xn = numberValue(x);
  49.532 +        switch (basicTypeChar) {
  49.533 +            case 'I': return Integer.valueOf(xn.intValue());
  49.534 +            case 'J': return Long.valueOf(xn.longValue());
  49.535 +            case 'F': return Float.valueOf(xn.floatValue());
  49.536 +            case 'D': return Double.valueOf(xn.doubleValue());
  49.537 +            case 'S': return Short.valueOf((short) xn.intValue());
  49.538 +            case 'B': return Byte.valueOf((byte) xn.intValue());
  49.539 +            case 'C': return Character.valueOf((char) xn.intValue());
  49.540 +            case 'Z': return Boolean.valueOf(boolValue(xn.byteValue()));
  49.541 +        }
  49.542 +        throw new InternalError("bad wrapper");
  49.543 +    }
  49.544 +
  49.545 +    /** Wrap a value (an int or smaller value) in this wrapper's type.
  49.546 +     * Performs standard primitive conversions, including truncation and float conversions.
  49.547 +     * Produces an {@code Integer} for {@code OBJECT}, although the exact type
  49.548 +     * of the operand is not known.
  49.549 +     * Returns null for {@code VOID}.
  49.550 +     */
  49.551 +    public Object wrap(int x) {
  49.552 +        if (basicTypeChar == 'L')  return (Integer)x;
  49.553 +        switch (basicTypeChar) {
  49.554 +            case 'L': throw newIllegalArgumentException("cannot wrap to object type");
  49.555 +            case 'V': return null;
  49.556 +            case 'I': return Integer.valueOf(x);
  49.557 +            case 'J': return Long.valueOf(x);
  49.558 +            case 'F': return Float.valueOf(x);
  49.559 +            case 'D': return Double.valueOf(x);
  49.560 +            case 'S': return Short.valueOf((short) x);
  49.561 +            case 'B': return Byte.valueOf((byte) x);
  49.562 +            case 'C': return Character.valueOf((char) x);
  49.563 +            case 'Z': return Boolean.valueOf(boolValue((byte) x));
  49.564 +        }
  49.565 +        throw new InternalError("bad wrapper");
  49.566 +    }
  49.567 +
  49.568 +    private static Number numberValue(Object x) {
  49.569 +        if (x instanceof Number)     return (Number)x;
  49.570 +        if (x instanceof Character)  return (int)(Character)x;
  49.571 +        if (x instanceof Boolean)    return (Boolean)x ? 1 : 0;
  49.572 +        // Remaining allowed case of void:  Must be a null reference.
  49.573 +        return (Number)x;
  49.574 +    }
  49.575 +
  49.576 +    // Parameter type of boolValue must be byte, because
  49.577 +    // MethodHandles.explicitCastArguments defines boolean
  49.578 +    // conversion as first converting to byte.
  49.579 +    private static boolean boolValue(byte bits) {
  49.580 +        bits &= 1;  // simple 31-bit zero extension
  49.581 +        return (bits != 0);
  49.582 +    }
  49.583 +
  49.584 +    private static RuntimeException newIllegalArgumentException(String message, Object x) {
  49.585 +        return newIllegalArgumentException(message + x);
  49.586 +    }
  49.587 +    private static RuntimeException newIllegalArgumentException(String message) {
  49.588 +        return new IllegalArgumentException(message);
  49.589 +    }
  49.590 +
  49.591 +    // primitive array support
  49.592 +    public Object makeArray(int len) {
  49.593 +        return java.lang.reflect.Array.newInstance(primitiveType, len);
  49.594 +    }
  49.595 +    public Class<?> arrayType() {
  49.596 +        return emptyArray.getClass();
  49.597 +    }
  49.598 +    public void copyArrayUnboxing(Object[] values, int vpos, Object a, int apos, int length) {
  49.599 +        if (a.getClass() != arrayType())
  49.600 +            arrayType().cast(a);  // throw NPE or CCE if bad type
  49.601 +        for (int i = 0; i < length; i++) {
  49.602 +            Object value = values[i+vpos];
  49.603 +            value = convert(value, primitiveType);
  49.604 +            java.lang.reflect.Array.set(a, i+apos, value);
  49.605 +        }
  49.606 +    }
  49.607 +    public void copyArrayBoxing(Object a, int apos, Object[] values, int vpos, int length) {
  49.608 +        if (a.getClass() != arrayType())
  49.609 +            arrayType().cast(a);  // throw NPE or CCE if bad type
  49.610 +        for (int i = 0; i < length; i++) {
  49.611 +            Object value = java.lang.reflect.Array.get(a, i+apos);
  49.612 +            //Already done: value = convert(value, primitiveType);
  49.613 +            assert(value.getClass() == wrapperType);
  49.614 +            values[i+vpos] = value;
  49.615 +        }
  49.616 +    }
  49.617 +}
    50.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.2 +++ b/rt/emul/compact/src/main/java/sun/invoke/util/package-info.java	Sat Aug 09 11:12:05 2014 +0200
    50.3 @@ -0,0 +1,31 @@
    50.4 +/*
    50.5 + * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
    50.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    50.7 + *
    50.8 + * This code is free software; you can redistribute it and/or modify it
    50.9 + * under the terms of the GNU General Public License version 2 only, as
   50.10 + * published by the Free Software Foundation.  Oracle designates this
   50.11 + * particular file as subject to the "Classpath" exception as provided
   50.12 + * by Oracle in the LICENSE file that accompanied this code.
   50.13 + *
   50.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   50.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   50.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   50.17 + * version 2 for more details (a copy is included in the LICENSE file that
   50.18 + * accompanied this code).
   50.19 + *
   50.20 + * You should have received a copy of the GNU General Public License version
   50.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   50.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   50.23 + *
   50.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   50.25 + * or visit www.oracle.com if you need additional information or have any
   50.26 + * questions.
   50.27 + */
   50.28 +
   50.29 +/**
   50.30 + * Extra support for using JSR 292 RI, package java.lang.invoke.
   50.31 + * @author jrose
   50.32 + */
   50.33 +
   50.34 +package sun.invoke.util;