1/*
2 * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package java.lang.invoke;
27
28import jdk.internal.misc.JavaLangInvokeAccess;
29import jdk.internal.misc.SharedSecrets;
30import jdk.internal.org.objectweb.asm.AnnotationVisitor;
31import jdk.internal.org.objectweb.asm.ClassWriter;
32import jdk.internal.org.objectweb.asm.MethodVisitor;
33import jdk.internal.reflect.CallerSensitive;
34import jdk.internal.reflect.Reflection;
35import jdk.internal.vm.annotation.ForceInline;
36import jdk.internal.vm.annotation.Stable;
37import sun.invoke.empty.Empty;
38import sun.invoke.util.ValueConversions;
39import sun.invoke.util.VerifyType;
40import sun.invoke.util.Wrapper;
41
42import java.lang.reflect.Array;
43import java.util.Arrays;
44import java.util.Collections;
45import java.util.Iterator;
46import java.util.List;
47import java.util.Map;
48import java.util.function.Function;
49import java.util.stream.Stream;
50
51import static java.lang.invoke.LambdaForm.*;
52import static java.lang.invoke.MethodHandleStatics.*;
53import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
54import static jdk.internal.org.objectweb.asm.Opcodes.*;
55
56/**
57 * Trusted implementation code for MethodHandle.
58 * @author jrose
59 */
60/*non-public*/ abstract class MethodHandleImpl {
61
62    /// Factory methods to create method handles:
63
64    static MethodHandle makeArrayElementAccessor(Class<?> arrayClass, ArrayAccess access) {
65        if (arrayClass == Object[].class) {
66            return ArrayAccess.objectAccessor(access);
67        }
68        if (!arrayClass.isArray())
69            throw newIllegalArgumentException("not an array: "+arrayClass);
70        MethodHandle[] cache = ArrayAccessor.TYPED_ACCESSORS.get(arrayClass);
71        int cacheIndex = ArrayAccess.cacheIndex(access);
72        MethodHandle mh = cache[cacheIndex];
73        if (mh != null)  return mh;
74        mh = ArrayAccessor.getAccessor(arrayClass, access);
75        MethodType correctType = ArrayAccessor.correctType(arrayClass, access);
76        if (mh.type() != correctType) {
77            assert(mh.type().parameterType(0) == Object[].class);
78            /* if access == SET */ assert(access != ArrayAccess.SET || mh.type().parameterType(2) == Object.class);
79            /* if access == GET */ assert(access != ArrayAccess.GET ||
80                    (mh.type().returnType() == Object.class &&
81                     correctType.parameterType(0).getComponentType() == correctType.returnType()));
82            // safe to view non-strictly, because element type follows from array type
83            mh = mh.viewAsType(correctType, false);
84        }
85        mh = makeIntrinsic(mh, ArrayAccess.intrinsic(access));
86        // Atomically update accessor cache.
87        synchronized(cache) {
88            if (cache[cacheIndex] == null) {
89                cache[cacheIndex] = mh;
90            } else {
91                // Throw away newly constructed accessor and use cached version.
92                mh = cache[cacheIndex];
93            }
94        }
95        return mh;
96    }
97
98    enum ArrayAccess {
99        GET, SET, LENGTH;
100
101        // As ArrayAccess and ArrayAccessor have a circular dependency, the ArrayAccess properties cannot be stored in
102        // final fields.
103
104        static String opName(ArrayAccess a) {
105            switch (a) {
106                case GET: return "getElement";
107                case SET: return "setElement";
108                case LENGTH: return "length";
109            }
110            throw unmatchedArrayAccess(a);
111        }
112
113        static MethodHandle objectAccessor(ArrayAccess a) {
114            switch (a) {
115                case GET: return ArrayAccessor.OBJECT_ARRAY_GETTER;
116                case SET: return ArrayAccessor.OBJECT_ARRAY_SETTER;
117                case LENGTH: return ArrayAccessor.OBJECT_ARRAY_LENGTH;
118            }
119            throw unmatchedArrayAccess(a);
120        }
121
122        static int cacheIndex(ArrayAccess a) {
123            switch (a) {
124                case GET: return ArrayAccessor.GETTER_INDEX;
125                case SET: return ArrayAccessor.SETTER_INDEX;
126                case LENGTH: return ArrayAccessor.LENGTH_INDEX;
127            }
128            throw unmatchedArrayAccess(a);
129        }
130
131        static Intrinsic intrinsic(ArrayAccess a) {
132            switch (a) {
133                case GET: return Intrinsic.ARRAY_LOAD;
134                case SET: return Intrinsic.ARRAY_STORE;
135                case LENGTH: return Intrinsic.ARRAY_LENGTH;
136            }
137            throw unmatchedArrayAccess(a);
138        }
139    }
140
141    static InternalError unmatchedArrayAccess(ArrayAccess a) {
142        return newInternalError("should not reach here (unmatched ArrayAccess: " + a + ")");
143    }
144
145    static final class ArrayAccessor {
146        /// Support for array element and length access
147        static final int GETTER_INDEX = 0, SETTER_INDEX = 1, LENGTH_INDEX = 2, INDEX_LIMIT = 3;
148        static final ClassValue<MethodHandle[]> TYPED_ACCESSORS
149                = new ClassValue<MethodHandle[]>() {
150                    @Override
151                    protected MethodHandle[] computeValue(Class<?> type) {
152                        return new MethodHandle[INDEX_LIMIT];
153                    }
154                };
155        static final MethodHandle OBJECT_ARRAY_GETTER, OBJECT_ARRAY_SETTER, OBJECT_ARRAY_LENGTH;
156        static {
157            MethodHandle[] cache = TYPED_ACCESSORS.get(Object[].class);
158            cache[GETTER_INDEX] = OBJECT_ARRAY_GETTER = makeIntrinsic(getAccessor(Object[].class, ArrayAccess.GET),    Intrinsic.ARRAY_LOAD);
159            cache[SETTER_INDEX] = OBJECT_ARRAY_SETTER = makeIntrinsic(getAccessor(Object[].class, ArrayAccess.SET),    Intrinsic.ARRAY_STORE);
160            cache[LENGTH_INDEX] = OBJECT_ARRAY_LENGTH = makeIntrinsic(getAccessor(Object[].class, ArrayAccess.LENGTH), Intrinsic.ARRAY_LENGTH);
161
162            assert(InvokerBytecodeGenerator.isStaticallyInvocable(ArrayAccessor.OBJECT_ARRAY_GETTER.internalMemberName()));
163            assert(InvokerBytecodeGenerator.isStaticallyInvocable(ArrayAccessor.OBJECT_ARRAY_SETTER.internalMemberName()));
164            assert(InvokerBytecodeGenerator.isStaticallyInvocable(ArrayAccessor.OBJECT_ARRAY_LENGTH.internalMemberName()));
165        }
166
167        static int     getElementI(int[]     a, int i)            { return              a[i]; }
168        static long    getElementJ(long[]    a, int i)            { return              a[i]; }
169        static float   getElementF(float[]   a, int i)            { return              a[i]; }
170        static double  getElementD(double[]  a, int i)            { return              a[i]; }
171        static boolean getElementZ(boolean[] a, int i)            { return              a[i]; }
172        static byte    getElementB(byte[]    a, int i)            { return              a[i]; }
173        static short   getElementS(short[]   a, int i)            { return              a[i]; }
174        static char    getElementC(char[]    a, int i)            { return              a[i]; }
175        static Object  getElementL(Object[]  a, int i)            { return              a[i]; }
176
177        static void    setElementI(int[]     a, int i, int     x) {              a[i] = x; }
178        static void    setElementJ(long[]    a, int i, long    x) {              a[i] = x; }
179        static void    setElementF(float[]   a, int i, float   x) {              a[i] = x; }
180        static void    setElementD(double[]  a, int i, double  x) {              a[i] = x; }
181        static void    setElementZ(boolean[] a, int i, boolean x) {              a[i] = x; }
182        static void    setElementB(byte[]    a, int i, byte    x) {              a[i] = x; }
183        static void    setElementS(short[]   a, int i, short   x) {              a[i] = x; }
184        static void    setElementC(char[]    a, int i, char    x) {              a[i] = x; }
185        static void    setElementL(Object[]  a, int i, Object  x) {              a[i] = x; }
186
187        static int     lengthI(int[]     a)                       { return a.length; }
188        static int     lengthJ(long[]    a)                       { return a.length; }
189        static int     lengthF(float[]   a)                       { return a.length; }
190        static int     lengthD(double[]  a)                       { return a.length; }
191        static int     lengthZ(boolean[] a)                       { return a.length; }
192        static int     lengthB(byte[]    a)                       { return a.length; }
193        static int     lengthS(short[]   a)                       { return a.length; }
194        static int     lengthC(char[]    a)                       { return a.length; }
195        static int     lengthL(Object[]  a)                       { return a.length; }
196
197        static String name(Class<?> arrayClass, ArrayAccess access) {
198            Class<?> elemClass = arrayClass.getComponentType();
199            if (elemClass == null)  throw newIllegalArgumentException("not an array", arrayClass);
200            return ArrayAccess.opName(access) + Wrapper.basicTypeChar(elemClass);
201        }
202        static MethodType type(Class<?> arrayClass, ArrayAccess access) {
203            Class<?> elemClass = arrayClass.getComponentType();
204            Class<?> arrayArgClass = arrayClass;
205            if (!elemClass.isPrimitive()) {
206                arrayArgClass = Object[].class;
207                elemClass = Object.class;
208            }
209            switch (access) {
210                case GET:    return MethodType.methodType(elemClass,  arrayArgClass, int.class);
211                case SET:    return MethodType.methodType(void.class, arrayArgClass, int.class, elemClass);
212                case LENGTH: return MethodType.methodType(int.class,  arrayArgClass);
213            }
214            throw unmatchedArrayAccess(access);
215        }
216        static MethodType correctType(Class<?> arrayClass, ArrayAccess access) {
217            Class<?> elemClass = arrayClass.getComponentType();
218            switch (access) {
219                case GET:    return MethodType.methodType(elemClass,  arrayClass, int.class);
220                case SET:    return MethodType.methodType(void.class, arrayClass, int.class, elemClass);
221                case LENGTH: return MethodType.methodType(int.class,  arrayClass);
222            }
223            throw unmatchedArrayAccess(access);
224        }
225        static MethodHandle getAccessor(Class<?> arrayClass, ArrayAccess access) {
226            String     name = name(arrayClass, access);
227            MethodType type = type(arrayClass, access);
228            try {
229                return IMPL_LOOKUP.findStatic(ArrayAccessor.class, name, type);
230            } catch (ReflectiveOperationException ex) {
231                throw uncaughtException(ex);
232            }
233        }
234    }
235
236    /**
237     * Create a JVM-level adapter method handle to conform the given method
238     * handle to the similar newType, using only pairwise argument conversions.
239     * For each argument, convert incoming argument to the exact type needed.
240     * The argument conversions allowed are casting, boxing and unboxing,
241     * integral widening or narrowing, and floating point widening or narrowing.
242     * @param srcType required call type
243     * @param target original method handle
244     * @param strict if true, only asType conversions are allowed; if false, explicitCastArguments conversions allowed
245     * @param monobox if true, unboxing conversions are assumed to be exactly typed (Integer to int only, not long or double)
246     * @return an adapter to the original handle with the desired new type,
247     *          or the original target if the types are already identical
248     *          or null if the adaptation cannot be made
249     */
250    static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType,
251                                            boolean strict, boolean monobox) {
252        MethodType dstType = target.type();
253        if (srcType == dstType)
254            return target;
255        return makePairwiseConvertByEditor(target, srcType, strict, monobox);
256    }
257
258    private static int countNonNull(Object[] array) {
259        int count = 0;
260        for (Object x : array) {
261            if (x != null)  ++count;
262        }
263        return count;
264    }
265
266    static MethodHandle makePairwiseConvertByEditor(MethodHandle target, MethodType srcType,
267                                                    boolean strict, boolean monobox) {
268        Object[] convSpecs = computeValueConversions(srcType, target.type(), strict, monobox);
269        int convCount = countNonNull(convSpecs);
270        if (convCount == 0)
271            return target.viewAsType(srcType, strict);
272        MethodType basicSrcType = srcType.basicType();
273        MethodType midType = target.type().basicType();
274        BoundMethodHandle mh = target.rebind();
275        // FIXME: Reduce number of bindings when there is more than one Class conversion.
276        // FIXME: Reduce number of bindings when there are repeated conversions.
277        for (int i = 0; i < convSpecs.length-1; i++) {
278            Object convSpec = convSpecs[i];
279            if (convSpec == null)  continue;
280            MethodHandle fn;
281            if (convSpec instanceof Class) {
282                fn = getConstantHandle(MH_cast).bindTo(convSpec);
283            } else {
284                fn = (MethodHandle) convSpec;
285            }
286            Class<?> newType = basicSrcType.parameterType(i);
287            if (--convCount == 0)
288                midType = srcType;
289            else
290                midType = midType.changeParameterType(i, newType);
291            LambdaForm form2 = mh.editor().filterArgumentForm(1+i, BasicType.basicType(newType));
292            mh = mh.copyWithExtendL(midType, form2, fn);
293            mh = mh.rebind();
294        }
295        Object convSpec = convSpecs[convSpecs.length-1];
296        if (convSpec != null) {
297            MethodHandle fn;
298            if (convSpec instanceof Class) {
299                if (convSpec == void.class)
300                    fn = null;
301                else
302                    fn = getConstantHandle(MH_cast).bindTo(convSpec);
303            } else {
304                fn = (MethodHandle) convSpec;
305            }
306            Class<?> newType = basicSrcType.returnType();
307            assert(--convCount == 0);
308            midType = srcType;
309            if (fn != null) {
310                mh = mh.rebind();  // rebind if too complex
311                LambdaForm form2 = mh.editor().filterReturnForm(BasicType.basicType(newType), false);
312                mh = mh.copyWithExtendL(midType, form2, fn);
313            } else {
314                LambdaForm form2 = mh.editor().filterReturnForm(BasicType.basicType(newType), true);
315                mh = mh.copyWith(midType, form2);
316            }
317        }
318        assert(convCount == 0);
319        assert(mh.type().equals(srcType));
320        return mh;
321    }
322
323    static MethodHandle makePairwiseConvertIndirect(MethodHandle target, MethodType srcType,
324                                                    boolean strict, boolean monobox) {
325        assert(target.type().parameterCount() == srcType.parameterCount());
326        // Calculate extra arguments (temporaries) required in the names array.
327        Object[] convSpecs = computeValueConversions(srcType, target.type(), strict, monobox);
328        final int INARG_COUNT = srcType.parameterCount();
329        int convCount = countNonNull(convSpecs);
330        boolean retConv = (convSpecs[INARG_COUNT] != null);
331        boolean retVoid = srcType.returnType() == void.class;
332        if (retConv && retVoid) {
333            convCount -= 1;
334            retConv = false;
335        }
336
337        final int IN_MH         = 0;
338        final int INARG_BASE    = 1;
339        final int INARG_LIMIT   = INARG_BASE + INARG_COUNT;
340        final int NAME_LIMIT    = INARG_LIMIT + convCount + 1;
341        final int RETURN_CONV   = (!retConv ? -1         : NAME_LIMIT - 1);
342        final int OUT_CALL      = (!retConv ? NAME_LIMIT : RETURN_CONV) - 1;
343        final int RESULT        = (retVoid ? -1 : NAME_LIMIT - 1);
344
345        // Now build a LambdaForm.
346        MethodType lambdaType = srcType.basicType().invokerType();
347        Name[] names = arguments(NAME_LIMIT - INARG_LIMIT, lambdaType);
348
349        // Collect the arguments to the outgoing call, maybe with conversions:
350        final int OUTARG_BASE = 0;  // target MH is Name.function, name Name.arguments[0]
351        Object[] outArgs = new Object[OUTARG_BASE + INARG_COUNT];
352
353        int nameCursor = INARG_LIMIT;
354        for (int i = 0; i < INARG_COUNT; i++) {
355            Object convSpec = convSpecs[i];
356            if (convSpec == null) {
357                // do nothing: difference is trivial
358                outArgs[OUTARG_BASE + i] = names[INARG_BASE + i];
359                continue;
360            }
361
362            Name conv;
363            if (convSpec instanceof Class) {
364                Class<?> convClass = (Class<?>) convSpec;
365                conv = new Name(getConstantHandle(MH_cast), convClass, names[INARG_BASE + i]);
366            } else {
367                MethodHandle fn = (MethodHandle) convSpec;
368                conv = new Name(fn, names[INARG_BASE + i]);
369            }
370            assert(names[nameCursor] == null);
371            names[nameCursor++] = conv;
372            assert(outArgs[OUTARG_BASE + i] == null);
373            outArgs[OUTARG_BASE + i] = conv;
374        }
375
376        // Build argument array for the call.
377        assert(nameCursor == OUT_CALL);
378        names[OUT_CALL] = new Name(target, outArgs);
379
380        Object convSpec = convSpecs[INARG_COUNT];
381        if (!retConv) {
382            assert(OUT_CALL == names.length-1);
383        } else {
384            Name conv;
385            if (convSpec == void.class) {
386                conv = new Name(LambdaForm.constantZero(BasicType.basicType(srcType.returnType())));
387            } else if (convSpec instanceof Class) {
388                Class<?> convClass = (Class<?>) convSpec;
389                conv = new Name(getConstantHandle(MH_cast), convClass, names[OUT_CALL]);
390            } else {
391                MethodHandle fn = (MethodHandle) convSpec;
392                if (fn.type().parameterCount() == 0)
393                    conv = new Name(fn);  // don't pass retval to void conversion
394                else
395                    conv = new Name(fn, names[OUT_CALL]);
396            }
397            assert(names[RETURN_CONV] == null);
398            names[RETURN_CONV] = conv;
399            assert(RETURN_CONV == names.length-1);
400        }
401
402        LambdaForm form = new LambdaForm(lambdaType.parameterCount(), names, RESULT, Kind.CONVERT);
403        return SimpleMethodHandle.make(srcType, form);
404    }
405
406    static Object[] computeValueConversions(MethodType srcType, MethodType dstType,
407                                            boolean strict, boolean monobox) {
408        final int INARG_COUNT = srcType.parameterCount();
409        Object[] convSpecs = new Object[INARG_COUNT+1];
410        for (int i = 0; i <= INARG_COUNT; i++) {
411            boolean isRet = (i == INARG_COUNT);
412            Class<?> src = isRet ? dstType.returnType() : srcType.parameterType(i);
413            Class<?> dst = isRet ? srcType.returnType() : dstType.parameterType(i);
414            if (!VerifyType.isNullConversion(src, dst, /*keepInterfaces=*/ strict)) {
415                convSpecs[i] = valueConversion(src, dst, strict, monobox);
416            }
417        }
418        return convSpecs;
419    }
420    static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType,
421                                            boolean strict) {
422        return makePairwiseConvert(target, srcType, strict, /*monobox=*/ false);
423    }
424
425    /**
426     * Find a conversion function from the given source to the given destination.
427     * This conversion function will be used as a LF NamedFunction.
428     * Return a Class object if a simple cast is needed.
429     * Return void.class if void is involved.
430     */
431    static Object valueConversion(Class<?> src, Class<?> dst, boolean strict, boolean monobox) {
432        assert(!VerifyType.isNullConversion(src, dst, /*keepInterfaces=*/ strict));  // caller responsibility
433        if (dst == void.class)
434            return dst;
435        MethodHandle fn;
436        if (src.isPrimitive()) {
437            if (src == void.class) {
438                return void.class;  // caller must recognize this specially
439            } else if (dst.isPrimitive()) {
440                // Examples: int->byte, byte->int, boolean->int (!strict)
441                fn = ValueConversions.convertPrimitive(src, dst);
442            } else {
443                // Examples: int->Integer, boolean->Object, float->Number
444                Wrapper wsrc = Wrapper.forPrimitiveType(src);
445                fn = ValueConversions.boxExact(wsrc);
446                assert(fn.type().parameterType(0) == wsrc.primitiveType());
447                assert(fn.type().returnType() == wsrc.wrapperType());
448                if (!VerifyType.isNullConversion(wsrc.wrapperType(), dst, strict)) {
449                    // Corner case, such as int->Long, which will probably fail.
450                    MethodType mt = MethodType.methodType(dst, src);
451                    if (strict)
452                        fn = fn.asType(mt);
453                    else
454                        fn = MethodHandleImpl.makePairwiseConvert(fn, mt, /*strict=*/ false);
455                }
456            }
457        } else if (dst.isPrimitive()) {
458            Wrapper wdst = Wrapper.forPrimitiveType(dst);
459            if (monobox || src == wdst.wrapperType()) {
460                // Use a strongly-typed unboxer, if possible.
461                fn = ValueConversions.unboxExact(wdst, strict);
462            } else {
463                // Examples:  Object->int, Number->int, Comparable->int, Byte->int
464                // must include additional conversions
465                // src must be examined at runtime, to detect Byte, Character, etc.
466                fn = (strict
467                        ? ValueConversions.unboxWiden(wdst)
468                        : ValueConversions.unboxCast(wdst));
469            }
470        } else {
471            // Simple reference conversion.
472            // Note:  Do not check for a class hierarchy relation
473            // between src and dst.  In all cases a 'null' argument
474            // will pass the cast conversion.
475            return dst;
476        }
477        assert(fn.type().parameterCount() <= 1) : "pc"+Arrays.asList(src.getSimpleName(), dst.getSimpleName(), fn);
478        return fn;
479    }
480
481    static MethodHandle makeVarargsCollector(MethodHandle target, Class<?> arrayType) {
482        MethodType type = target.type();
483        int last = type.parameterCount() - 1;
484        if (type.parameterType(last) != arrayType)
485            target = target.asType(type.changeParameterType(last, arrayType));
486        target = target.asFixedArity();  // make sure this attribute is turned off
487        return new AsVarargsCollector(target, arrayType);
488    }
489
490    private static final class AsVarargsCollector extends DelegatingMethodHandle {
491        private final MethodHandle target;
492        private final Class<?> arrayType;
493        private @Stable MethodHandle asCollectorCache;
494
495        AsVarargsCollector(MethodHandle target, Class<?> arrayType) {
496            this(target.type(), target, arrayType);
497        }
498        AsVarargsCollector(MethodType type, MethodHandle target, Class<?> arrayType) {
499            super(type, target);
500            this.target = target;
501            this.arrayType = arrayType;
502            this.asCollectorCache = target.asCollector(arrayType, 0);
503        }
504
505        @Override
506        public boolean isVarargsCollector() {
507            return true;
508        }
509
510        @Override
511        protected MethodHandle getTarget() {
512            return target;
513        }
514
515        @Override
516        public MethodHandle asFixedArity() {
517            return target;
518        }
519
520        @Override
521        MethodHandle setVarargs(MemberName member) {
522            if (member.isVarargs())  return this;
523            return asFixedArity();
524        }
525
526        @Override
527        public MethodHandle asTypeUncached(MethodType newType) {
528            MethodType type = this.type();
529            int collectArg = type.parameterCount() - 1;
530            int newArity = newType.parameterCount();
531            if (newArity == collectArg+1 &&
532                type.parameterType(collectArg).isAssignableFrom(newType.parameterType(collectArg))) {
533                // if arity and trailing parameter are compatible, do normal thing
534                return asTypeCache = asFixedArity().asType(newType);
535            }
536            // check cache
537            MethodHandle acc = asCollectorCache;
538            if (acc != null && acc.type().parameterCount() == newArity)
539                return asTypeCache = acc.asType(newType);
540            // build and cache a collector
541            int arrayLength = newArity - collectArg;
542            MethodHandle collector;
543            try {
544                collector = asFixedArity().asCollector(arrayType, arrayLength);
545                assert(collector.type().parameterCount() == newArity) : "newArity="+newArity+" but collector="+collector;
546            } catch (IllegalArgumentException ex) {
547                throw new WrongMethodTypeException("cannot build collector", ex);
548            }
549            asCollectorCache = collector;
550            return asTypeCache = collector.asType(newType);
551        }
552
553        @Override
554        boolean viewAsTypeChecks(MethodType newType, boolean strict) {
555            super.viewAsTypeChecks(newType, true);
556            if (strict) return true;
557            // extra assertion for non-strict checks:
558            assert (type().lastParameterType().getComponentType()
559                    .isAssignableFrom(
560                            newType.lastParameterType().getComponentType()))
561                    : Arrays.asList(this, newType);
562            return true;
563        }
564    }
565
566    /** Factory method:  Spread selected argument. */
567    static MethodHandle makeSpreadArguments(MethodHandle target,
568                                            Class<?> spreadArgType, int spreadArgPos, int spreadArgCount) {
569        MethodType targetType = target.type();
570
571        for (int i = 0; i < spreadArgCount; i++) {
572            Class<?> arg = VerifyType.spreadArgElementType(spreadArgType, i);
573            if (arg == null)  arg = Object.class;
574            targetType = targetType.changeParameterType(spreadArgPos + i, arg);
575        }
576        target = target.asType(targetType);
577
578        MethodType srcType = targetType
579                .replaceParameterTypes(spreadArgPos, spreadArgPos + spreadArgCount, spreadArgType);
580        // Now build a LambdaForm.
581        MethodType lambdaType = srcType.invokerType();
582        Name[] names = arguments(spreadArgCount + 2, lambdaType);
583        int nameCursor = lambdaType.parameterCount();
584        int[] indexes = new int[targetType.parameterCount()];
585
586        for (int i = 0, argIndex = 1; i < targetType.parameterCount() + 1; i++, argIndex++) {
587            Class<?> src = lambdaType.parameterType(i);
588            if (i == spreadArgPos) {
589                // Spread the array.
590                MethodHandle aload = MethodHandles.arrayElementGetter(spreadArgType);
591                Name array = names[argIndex];
592                names[nameCursor++] = new Name(getFunction(NF_checkSpreadArgument), array, spreadArgCount);
593                for (int j = 0; j < spreadArgCount; i++, j++) {
594                    indexes[i] = nameCursor;
595                    names[nameCursor++] = new Name(new NamedFunction(aload, Intrinsic.ARRAY_LOAD), array, j);
596                }
597            } else if (i < indexes.length) {
598                indexes[i] = argIndex;
599            }
600        }
601        assert(nameCursor == names.length-1);  // leave room for the final call
602
603        // Build argument array for the call.
604        Name[] targetArgs = new Name[targetType.parameterCount()];
605        for (int i = 0; i < targetType.parameterCount(); i++) {
606            int idx = indexes[i];
607            targetArgs[i] = names[idx];
608        }
609        names[names.length - 1] = new Name(target, (Object[]) targetArgs);
610
611        LambdaForm form = new LambdaForm(lambdaType.parameterCount(), names, Kind.SPREAD);
612        return SimpleMethodHandle.make(srcType, form);
613    }
614
615    static void checkSpreadArgument(Object av, int n) {
616        if (av == null) {
617            if (n == 0)  return;
618        } else if (av instanceof Object[]) {
619            int len = ((Object[])av).length;
620            if (len == n)  return;
621        } else {
622            int len = java.lang.reflect.Array.getLength(av);
623            if (len == n)  return;
624        }
625        // fall through to error:
626        throw newIllegalArgumentException("array is not of length "+n);
627    }
628
629    /** Factory method:  Collect or filter selected argument(s). */
630    static MethodHandle makeCollectArguments(MethodHandle target,
631                MethodHandle collector, int collectArgPos, boolean retainOriginalArgs) {
632        MethodType targetType = target.type();          // (a..., c, [b...])=>r
633        MethodType collectorType = collector.type();    // (b...)=>c
634        int collectArgCount = collectorType.parameterCount();
635        Class<?> collectValType = collectorType.returnType();
636        int collectValCount = (collectValType == void.class ? 0 : 1);
637        MethodType srcType = targetType                 // (a..., [b...])=>r
638                .dropParameterTypes(collectArgPos, collectArgPos+collectValCount);
639        if (!retainOriginalArgs) {                      // (a..., b...)=>r
640            srcType = srcType.insertParameterTypes(collectArgPos, collectorType.parameterArray());
641        }
642        // in  arglist: [0: ...keep1 | cpos: collect...  | cpos+cacount: keep2... ]
643        // out arglist: [0: ...keep1 | cpos: collectVal? | cpos+cvcount: keep2... ]
644        // out(retain): [0: ...keep1 | cpos: cV? coll... | cpos+cvc+cac: keep2... ]
645
646        // Now build a LambdaForm.
647        MethodType lambdaType = srcType.invokerType();
648        Name[] names = arguments(2, lambdaType);
649        final int collectNamePos = names.length - 2;
650        final int targetNamePos  = names.length - 1;
651
652        Name[] collectorArgs = Arrays.copyOfRange(names, 1 + collectArgPos, 1 + collectArgPos + collectArgCount);
653        names[collectNamePos] = new Name(collector, (Object[]) collectorArgs);
654
655        // Build argument array for the target.
656        // Incoming LF args to copy are: [ (mh) headArgs collectArgs tailArgs ].
657        // Output argument array is [ headArgs (collectVal)? (collectArgs)? tailArgs ].
658        Name[] targetArgs = new Name[targetType.parameterCount()];
659        int inputArgPos  = 1;  // incoming LF args to copy to target
660        int targetArgPos = 0;  // fill pointer for targetArgs
661        int chunk = collectArgPos;  // |headArgs|
662        System.arraycopy(names, inputArgPos, targetArgs, targetArgPos, chunk);
663        inputArgPos  += chunk;
664        targetArgPos += chunk;
665        if (collectValType != void.class) {
666            targetArgs[targetArgPos++] = names[collectNamePos];
667        }
668        chunk = collectArgCount;
669        if (retainOriginalArgs) {
670            System.arraycopy(names, inputArgPos, targetArgs, targetArgPos, chunk);
671            targetArgPos += chunk;   // optionally pass on the collected chunk
672        }
673        inputArgPos += chunk;
674        chunk = targetArgs.length - targetArgPos;  // all the rest
675        System.arraycopy(names, inputArgPos, targetArgs, targetArgPos, chunk);
676        assert(inputArgPos + chunk == collectNamePos);  // use of rest of input args also
677        names[targetNamePos] = new Name(target, (Object[]) targetArgs);
678
679        LambdaForm form = new LambdaForm(lambdaType.parameterCount(), names, Kind.COLLECT);
680        return SimpleMethodHandle.make(srcType, form);
681    }
682
683    @LambdaForm.Hidden
684    static
685    MethodHandle selectAlternative(boolean testResult, MethodHandle target, MethodHandle fallback) {
686        if (testResult) {
687            return target;
688        } else {
689            return fallback;
690        }
691    }
692
693    // Intrinsified by C2. Counters are used during parsing to calculate branch frequencies.
694    @LambdaForm.Hidden
695    @jdk.internal.HotSpotIntrinsicCandidate
696    static
697    boolean profileBoolean(boolean result, int[] counters) {
698        // Profile is int[2] where [0] and [1] correspond to false and true occurrences respectively.
699        int idx = result ? 1 : 0;
700        try {
701            counters[idx] = Math.addExact(counters[idx], 1);
702        } catch (ArithmeticException e) {
703            // Avoid continuous overflow by halving the problematic count.
704            counters[idx] = counters[idx] / 2;
705        }
706        return result;
707    }
708
709    // Intrinsified by C2. Returns true if obj is a compile-time constant.
710    @LambdaForm.Hidden
711    @jdk.internal.HotSpotIntrinsicCandidate
712    static
713    boolean isCompileConstant(Object obj) {
714        return false;
715    }
716
717    static
718    MethodHandle makeGuardWithTest(MethodHandle test,
719                                   MethodHandle target,
720                                   MethodHandle fallback) {
721        MethodType type = target.type();
722        assert(test.type().equals(type.changeReturnType(boolean.class)) && fallback.type().equals(type));
723        MethodType basicType = type.basicType();
724        LambdaForm form = makeGuardWithTestForm(basicType);
725        BoundMethodHandle mh;
726        try {
727            if (PROFILE_GWT) {
728                int[] counts = new int[2];
729                mh = (BoundMethodHandle)
730                        BoundMethodHandle.speciesData_LLLL().constructor().invokeBasic(type, form,
731                                (Object) test, (Object) profile(target), (Object) profile(fallback), counts);
732            } else {
733                mh = (BoundMethodHandle)
734                        BoundMethodHandle.speciesData_LLL().constructor().invokeBasic(type, form,
735                                (Object) test, (Object) profile(target), (Object) profile(fallback));
736            }
737        } catch (Throwable ex) {
738            throw uncaughtException(ex);
739        }
740        assert(mh.type() == type);
741        return mh;
742    }
743
744
745    static
746    MethodHandle profile(MethodHandle target) {
747        if (DONT_INLINE_THRESHOLD >= 0) {
748            return makeBlockInliningWrapper(target);
749        } else {
750            return target;
751        }
752    }
753
754    /**
755     * Block inlining during JIT-compilation of a target method handle if it hasn't been invoked enough times.
756     * Corresponding LambdaForm has @DontInline when compiled into bytecode.
757     */
758    static
759    MethodHandle makeBlockInliningWrapper(MethodHandle target) {
760        LambdaForm lform;
761        if (DONT_INLINE_THRESHOLD > 0) {
762            lform = Makers.PRODUCE_BLOCK_INLINING_FORM.apply(target);
763        } else {
764            lform = Makers.PRODUCE_REINVOKER_FORM.apply(target);
765        }
766        return new CountingWrapper(target, lform,
767                Makers.PRODUCE_BLOCK_INLINING_FORM, Makers.PRODUCE_REINVOKER_FORM,
768                                   DONT_INLINE_THRESHOLD);
769    }
770
771    private final static class Makers {
772        /** Constructs reinvoker lambda form which block inlining during JIT-compilation for a particular method handle */
773        static final Function<MethodHandle, LambdaForm> PRODUCE_BLOCK_INLINING_FORM = new Function<MethodHandle, LambdaForm>() {
774            @Override
775            public LambdaForm apply(MethodHandle target) {
776                return DelegatingMethodHandle.makeReinvokerForm(target,
777                                   MethodTypeForm.LF_DELEGATE_BLOCK_INLINING, CountingWrapper.class, false,
778                                   DelegatingMethodHandle.NF_getTarget, CountingWrapper.NF_maybeStopCounting);
779            }
780        };
781
782        /** Constructs simple reinvoker lambda form for a particular method handle */
783        static final Function<MethodHandle, LambdaForm> PRODUCE_REINVOKER_FORM = new Function<MethodHandle, LambdaForm>() {
784            @Override
785            public LambdaForm apply(MethodHandle target) {
786                return DelegatingMethodHandle.makeReinvokerForm(target,
787                        MethodTypeForm.LF_DELEGATE, DelegatingMethodHandle.class, DelegatingMethodHandle.NF_getTarget);
788            }
789        };
790
791        /** Maker of type-polymorphic varargs */
792        static final ClassValue<MethodHandle[]> TYPED_COLLECTORS = new ClassValue<MethodHandle[]>() {
793            @Override
794            protected MethodHandle[] computeValue(Class<?> type) {
795                return new MethodHandle[MAX_JVM_ARITY + 1];
796            }
797        };
798    }
799
800    /**
801     * Counting method handle. It has 2 states: counting and non-counting.
802     * It is in counting state for the first n invocations and then transitions to non-counting state.
803     * Behavior in counting and non-counting states is determined by lambda forms produced by
804     * countingFormProducer & nonCountingFormProducer respectively.
805     */
806    static class CountingWrapper extends DelegatingMethodHandle {
807        private final MethodHandle target;
808        private int count;
809        private Function<MethodHandle, LambdaForm> countingFormProducer;
810        private Function<MethodHandle, LambdaForm> nonCountingFormProducer;
811        private volatile boolean isCounting;
812
813        private CountingWrapper(MethodHandle target, LambdaForm lform,
814                                Function<MethodHandle, LambdaForm> countingFromProducer,
815                                Function<MethodHandle, LambdaForm> nonCountingFormProducer,
816                                int count) {
817            super(target.type(), lform);
818            this.target = target;
819            this.count = count;
820            this.countingFormProducer = countingFromProducer;
821            this.nonCountingFormProducer = nonCountingFormProducer;
822            this.isCounting = (count > 0);
823        }
824
825        @Hidden
826        @Override
827        protected MethodHandle getTarget() {
828            return target;
829        }
830
831        @Override
832        public MethodHandle asTypeUncached(MethodType newType) {
833            MethodHandle newTarget = target.asType(newType);
834            MethodHandle wrapper;
835            if (isCounting) {
836                LambdaForm lform;
837                lform = countingFormProducer.apply(newTarget);
838                wrapper = new CountingWrapper(newTarget, lform, countingFormProducer, nonCountingFormProducer, DONT_INLINE_THRESHOLD);
839            } else {
840                wrapper = newTarget; // no need for a counting wrapper anymore
841            }
842            return (asTypeCache = wrapper);
843        }
844
845        // Customize target if counting happens for too long.
846        private int invocations = CUSTOMIZE_THRESHOLD;
847        private void maybeCustomizeTarget() {
848            int c = invocations;
849            if (c >= 0) {
850                if (c == 1) {
851                    target.customize();
852                }
853                invocations = c - 1;
854            }
855        }
856
857        boolean countDown() {
858            int c = count;
859            maybeCustomizeTarget();
860            if (c <= 1) {
861                // Try to limit number of updates. MethodHandle.updateForm() doesn't guarantee LF update visibility.
862                if (isCounting) {
863                    isCounting = false;
864                    return true;
865                } else {
866                    return false;
867                }
868            } else {
869                count = c - 1;
870                return false;
871            }
872        }
873
874        @Hidden
875        static void maybeStopCounting(Object o1) {
876             CountingWrapper wrapper = (CountingWrapper) o1;
877             if (wrapper.countDown()) {
878                 // Reached invocation threshold. Replace counting behavior with a non-counting one.
879                 LambdaForm lform = wrapper.nonCountingFormProducer.apply(wrapper.target);
880                 lform.compileToBytecode(); // speed up warmup by avoiding LF interpretation again after transition
881                 wrapper.updateForm(lform);
882             }
883        }
884
885        static final NamedFunction NF_maybeStopCounting;
886        static {
887            Class<?> THIS_CLASS = CountingWrapper.class;
888            try {
889                NF_maybeStopCounting = new NamedFunction(THIS_CLASS.getDeclaredMethod("maybeStopCounting", Object.class));
890            } catch (ReflectiveOperationException ex) {
891                throw newInternalError(ex);
892            }
893        }
894    }
895
896    static
897    LambdaForm makeGuardWithTestForm(MethodType basicType) {
898        LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_GWT);
899        if (lform != null)  return lform;
900        final int THIS_MH      = 0;  // the BMH_LLL
901        final int ARG_BASE     = 1;  // start of incoming arguments
902        final int ARG_LIMIT    = ARG_BASE + basicType.parameterCount();
903        int nameCursor = ARG_LIMIT;
904        final int GET_TEST     = nameCursor++;
905        final int GET_TARGET   = nameCursor++;
906        final int GET_FALLBACK = nameCursor++;
907        final int GET_COUNTERS = PROFILE_GWT ? nameCursor++ : -1;
908        final int CALL_TEST    = nameCursor++;
909        final int PROFILE      = (GET_COUNTERS != -1) ? nameCursor++ : -1;
910        final int TEST         = nameCursor-1; // previous statement: either PROFILE or CALL_TEST
911        final int SELECT_ALT   = nameCursor++;
912        final int CALL_TARGET  = nameCursor++;
913        assert(CALL_TARGET == SELECT_ALT+1);  // must be true to trigger IBG.emitSelectAlternative
914
915        MethodType lambdaType = basicType.invokerType();
916        Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType);
917
918        BoundMethodHandle.SpeciesData data =
919                (GET_COUNTERS != -1) ? BoundMethodHandle.speciesData_LLLL()
920                                     : BoundMethodHandle.speciesData_LLL();
921        names[THIS_MH] = names[THIS_MH].withConstraint(data);
922        names[GET_TEST]     = new Name(data.getterFunction(0), names[THIS_MH]);
923        names[GET_TARGET]   = new Name(data.getterFunction(1), names[THIS_MH]);
924        names[GET_FALLBACK] = new Name(data.getterFunction(2), names[THIS_MH]);
925        if (GET_COUNTERS != -1) {
926            names[GET_COUNTERS] = new Name(data.getterFunction(3), names[THIS_MH]);
927        }
928        Object[] invokeArgs = Arrays.copyOfRange(names, 0, ARG_LIMIT, Object[].class);
929
930        // call test
931        MethodType testType = basicType.changeReturnType(boolean.class).basicType();
932        invokeArgs[0] = names[GET_TEST];
933        names[CALL_TEST] = new Name(testType, invokeArgs);
934
935        // profile branch
936        if (PROFILE != -1) {
937            names[PROFILE] = new Name(getFunction(NF_profileBoolean), names[CALL_TEST], names[GET_COUNTERS]);
938        }
939        // call selectAlternative
940        names[SELECT_ALT] = new Name(new NamedFunction(getConstantHandle(MH_selectAlternative), Intrinsic.SELECT_ALTERNATIVE), names[TEST], names[GET_TARGET], names[GET_FALLBACK]);
941
942        // call target or fallback
943        invokeArgs[0] = names[SELECT_ALT];
944        names[CALL_TARGET] = new Name(basicType, invokeArgs);
945
946        lform = new LambdaForm(lambdaType.parameterCount(), names, /*forceInline=*/true, Kind.GUARD);
947
948        return basicType.form().setCachedLambdaForm(MethodTypeForm.LF_GWT, lform);
949    }
950
951    /**
952     * The LambdaForm shape for catchException combinator is the following:
953     * <blockquote><pre>{@code
954     *  guardWithCatch=Lambda(a0:L,a1:L,a2:L)=>{
955     *    t3:L=BoundMethodHandle$Species_LLLLL.argL0(a0:L);
956     *    t4:L=BoundMethodHandle$Species_LLLLL.argL1(a0:L);
957     *    t5:L=BoundMethodHandle$Species_LLLLL.argL2(a0:L);
958     *    t6:L=BoundMethodHandle$Species_LLLLL.argL3(a0:L);
959     *    t7:L=BoundMethodHandle$Species_LLLLL.argL4(a0:L);
960     *    t8:L=MethodHandle.invokeBasic(t6:L,a1:L,a2:L);
961     *    t9:L=MethodHandleImpl.guardWithCatch(t3:L,t4:L,t5:L,t8:L);
962     *   t10:I=MethodHandle.invokeBasic(t7:L,t9:L);t10:I}
963     * }</pre></blockquote>
964     *
965     * argL0 and argL2 are target and catcher method handles. argL1 is exception class.
966     * argL3 and argL4 are auxiliary method handles: argL3 boxes arguments and wraps them into Object[]
967     * (ValueConversions.array()) and argL4 unboxes result if necessary (ValueConversions.unbox()).
968     *
969     * Having t8 and t10 passed outside and not hardcoded into a lambda form allows to share lambda forms
970     * among catchException combinators with the same basic type.
971     */
972    private static LambdaForm makeGuardWithCatchForm(MethodType basicType) {
973        MethodType lambdaType = basicType.invokerType();
974
975        LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_GWC);
976        if (lform != null) {
977            return lform;
978        }
979        final int THIS_MH      = 0;  // the BMH_LLLLL
980        final int ARG_BASE     = 1;  // start of incoming arguments
981        final int ARG_LIMIT    = ARG_BASE + basicType.parameterCount();
982
983        int nameCursor = ARG_LIMIT;
984        final int GET_TARGET       = nameCursor++;
985        final int GET_CLASS        = nameCursor++;
986        final int GET_CATCHER      = nameCursor++;
987        final int GET_COLLECT_ARGS = nameCursor++;
988        final int GET_UNBOX_RESULT = nameCursor++;
989        final int BOXED_ARGS       = nameCursor++;
990        final int TRY_CATCH        = nameCursor++;
991        final int UNBOX_RESULT     = nameCursor++;
992
993        Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType);
994
995        BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL();
996        names[THIS_MH]          = names[THIS_MH].withConstraint(data);
997        names[GET_TARGET]       = new Name(data.getterFunction(0), names[THIS_MH]);
998        names[GET_CLASS]        = new Name(data.getterFunction(1), names[THIS_MH]);
999        names[GET_CATCHER]      = new Name(data.getterFunction(2), names[THIS_MH]);
1000        names[GET_COLLECT_ARGS] = new Name(data.getterFunction(3), names[THIS_MH]);
1001        names[GET_UNBOX_RESULT] = new Name(data.getterFunction(4), names[THIS_MH]);
1002
1003        // FIXME: rework argument boxing/result unboxing logic for LF interpretation
1004
1005        // t_{i}:L=MethodHandle.invokeBasic(collectArgs:L,a1:L,...);
1006        MethodType collectArgsType = basicType.changeReturnType(Object.class);
1007        MethodHandle invokeBasic = MethodHandles.basicInvoker(collectArgsType);
1008        Object[] args = new Object[invokeBasic.type().parameterCount()];
1009        args[0] = names[GET_COLLECT_ARGS];
1010        System.arraycopy(names, ARG_BASE, args, 1, ARG_LIMIT-ARG_BASE);
1011        names[BOXED_ARGS] = new Name(new NamedFunction(invokeBasic, Intrinsic.GUARD_WITH_CATCH), args);
1012
1013        // t_{i+1}:L=MethodHandleImpl.guardWithCatch(target:L,exType:L,catcher:L,t_{i}:L);
1014        Object[] gwcArgs = new Object[] {names[GET_TARGET], names[GET_CLASS], names[GET_CATCHER], names[BOXED_ARGS]};
1015        names[TRY_CATCH] = new Name(getFunction(NF_guardWithCatch), gwcArgs);
1016
1017        // t_{i+2}:I=MethodHandle.invokeBasic(unbox:L,t_{i+1}:L);
1018        MethodHandle invokeBasicUnbox = MethodHandles.basicInvoker(MethodType.methodType(basicType.rtype(), Object.class));
1019        Object[] unboxArgs  = new Object[] {names[GET_UNBOX_RESULT], names[TRY_CATCH]};
1020        names[UNBOX_RESULT] = new Name(invokeBasicUnbox, unboxArgs);
1021
1022        lform = new LambdaForm(lambdaType.parameterCount(), names, Kind.GUARD_WITH_CATCH);
1023
1024        return basicType.form().setCachedLambdaForm(MethodTypeForm.LF_GWC, lform);
1025    }
1026
1027    static
1028    MethodHandle makeGuardWithCatch(MethodHandle target,
1029                                    Class<? extends Throwable> exType,
1030                                    MethodHandle catcher) {
1031        MethodType type = target.type();
1032        LambdaForm form = makeGuardWithCatchForm(type.basicType());
1033
1034        // Prepare auxiliary method handles used during LambdaForm interpretation.
1035        // Box arguments and wrap them into Object[]: ValueConversions.array().
1036        MethodType varargsType = type.changeReturnType(Object[].class);
1037        MethodHandle collectArgs = varargsArray(type.parameterCount()).asType(varargsType);
1038        MethodHandle unboxResult = unboxResultHandle(type.returnType());
1039
1040        BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL();
1041        BoundMethodHandle mh;
1042        try {
1043            mh = (BoundMethodHandle) data.constructor().invokeBasic(type, form, (Object) target, (Object) exType,
1044                    (Object) catcher, (Object) collectArgs, (Object) unboxResult);
1045        } catch (Throwable ex) {
1046            throw uncaughtException(ex);
1047        }
1048        assert(mh.type() == type);
1049        return mh;
1050    }
1051
1052    /**
1053     * Intrinsified during LambdaForm compilation
1054     * (see {@link InvokerBytecodeGenerator#emitGuardWithCatch emitGuardWithCatch}).
1055     */
1056    @LambdaForm.Hidden
1057    static Object guardWithCatch(MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher,
1058                                 Object... av) throws Throwable {
1059        // Use asFixedArity() to avoid unnecessary boxing of last argument for VarargsCollector case.
1060        try {
1061            return target.asFixedArity().invokeWithArguments(av);
1062        } catch (Throwable t) {
1063            if (!exType.isInstance(t)) throw t;
1064            return catcher.asFixedArity().invokeWithArguments(prepend(av, t));
1065        }
1066    }
1067
1068    /** Prepend elements to an array. */
1069    @LambdaForm.Hidden
1070    private static Object[] prepend(Object[] array, Object... elems) {
1071        int nArray = array.length;
1072        int nElems = elems.length;
1073        Object[] newArray = new Object[nArray + nElems];
1074        System.arraycopy(elems, 0, newArray, 0, nElems);
1075        System.arraycopy(array, 0, newArray, nElems, nArray);
1076        return newArray;
1077    }
1078
1079    static
1080    MethodHandle throwException(MethodType type) {
1081        assert(Throwable.class.isAssignableFrom(type.parameterType(0)));
1082        int arity = type.parameterCount();
1083        if (arity > 1) {
1084            MethodHandle mh = throwException(type.dropParameterTypes(1, arity));
1085            mh = MethodHandles.dropArguments(mh, 1, Arrays.copyOfRange(type.parameterArray(), 1, arity));
1086            return mh;
1087        }
1088        return makePairwiseConvert(getFunction(NF_throwException).resolvedHandle(), type, false, true);
1089    }
1090
1091    static <T extends Throwable> Empty throwException(T t) throws T { throw t; }
1092
1093    static MethodHandle[] FAKE_METHOD_HANDLE_INVOKE = new MethodHandle[2];
1094    static MethodHandle fakeMethodHandleInvoke(MemberName method) {
1095        int idx;
1096        assert(method.isMethodHandleInvoke());
1097        switch (method.getName()) {
1098        case "invoke":       idx = 0; break;
1099        case "invokeExact":  idx = 1; break;
1100        default:             throw new InternalError(method.getName());
1101        }
1102        MethodHandle mh = FAKE_METHOD_HANDLE_INVOKE[idx];
1103        if (mh != null)  return mh;
1104        MethodType type = MethodType.methodType(Object.class, UnsupportedOperationException.class,
1105                                                MethodHandle.class, Object[].class);
1106        mh = throwException(type);
1107        mh = mh.bindTo(new UnsupportedOperationException("cannot reflectively invoke MethodHandle"));
1108        if (!method.getInvocationType().equals(mh.type()))
1109            throw new InternalError(method.toString());
1110        mh = mh.withInternalMemberName(method, false);
1111        mh = mh.withVarargs(true);
1112        assert(method.isVarargs());
1113        FAKE_METHOD_HANDLE_INVOKE[idx] = mh;
1114        return mh;
1115    }
1116    static MethodHandle fakeVarHandleInvoke(MemberName method) {
1117        // TODO caching, is it necessary?
1118        MethodType type = MethodType.methodType(method.getReturnType(), UnsupportedOperationException.class,
1119                                                VarHandle.class, Object[].class);
1120        MethodHandle mh = throwException(type);
1121        mh = mh.bindTo(new UnsupportedOperationException("cannot reflectively invoke VarHandle"));
1122        if (!method.getInvocationType().equals(mh.type()))
1123            throw new InternalError(method.toString());
1124        mh = mh.withInternalMemberName(method, false);
1125        mh = mh.asVarargsCollector(Object[].class);
1126        assert(method.isVarargs());
1127        return mh;
1128    }
1129
1130    /**
1131     * Create an alias for the method handle which, when called,
1132     * appears to be called from the same class loader and protection domain
1133     * as hostClass.
1134     * This is an expensive no-op unless the method which is called
1135     * is sensitive to its caller.  A small number of system methods
1136     * are in this category, including Class.forName and Method.invoke.
1137     */
1138    static
1139    MethodHandle bindCaller(MethodHandle mh, Class<?> hostClass) {
1140        return BindCaller.bindCaller(mh, hostClass);
1141    }
1142
1143    // Put the whole mess into its own nested class.
1144    // That way we can lazily load the code and set up the constants.
1145    private static class BindCaller {
1146        private static MethodType INVOKER_MT = MethodType.methodType(Object.class, MethodHandle.class, Object[].class);
1147
1148        static
1149        MethodHandle bindCaller(MethodHandle mh, Class<?> hostClass) {
1150            // Code in the the boot layer should now be careful while creating method handles or
1151            // functional interface instances created from method references to @CallerSensitive  methods,
1152            // it needs to be ensured the handles or interface instances are kept safe and are not passed
1153            // from the boot layer to untrusted code.
1154            if (hostClass == null
1155                ||    (hostClass.isArray() ||
1156                       hostClass.isPrimitive() ||
1157                       hostClass.getName().startsWith("java.lang.invoke."))) {
1158                throw new InternalError();  // does not happen, and should not anyway
1159            }
1160            // For simplicity, convert mh to a varargs-like method.
1161            MethodHandle vamh = prepareForInvoker(mh);
1162            // Cache the result of makeInjectedInvoker once per argument class.
1163            MethodHandle bccInvoker = CV_makeInjectedInvoker.get(hostClass);
1164            return restoreToType(bccInvoker.bindTo(vamh), mh, hostClass);
1165        }
1166
1167        private static MethodHandle makeInjectedInvoker(Class<?> hostClass) {
1168            try {
1169                Class<?> invokerClass = UNSAFE.defineAnonymousClass(hostClass, INJECTED_INVOKER_TEMPLATE, null);
1170                assert checkInjectedInvoker(hostClass, invokerClass);
1171                return IMPL_LOOKUP.findStatic(invokerClass, "invoke_V", INVOKER_MT);
1172            } catch (ReflectiveOperationException ex) {
1173                throw uncaughtException(ex);
1174            }
1175        }
1176
1177        private static ClassValue<MethodHandle> CV_makeInjectedInvoker = new ClassValue<MethodHandle>() {
1178            @Override protected MethodHandle computeValue(Class<?> hostClass) {
1179                return makeInjectedInvoker(hostClass);
1180            }
1181        };
1182
1183        // Adapt mh so that it can be called directly from an injected invoker:
1184        private static MethodHandle prepareForInvoker(MethodHandle mh) {
1185            mh = mh.asFixedArity();
1186            MethodType mt = mh.type();
1187            int arity = mt.parameterCount();
1188            MethodHandle vamh = mh.asType(mt.generic());
1189            vamh.internalForm().compileToBytecode();  // eliminate LFI stack frames
1190            vamh = vamh.asSpreader(Object[].class, arity);
1191            vamh.internalForm().compileToBytecode();  // eliminate LFI stack frames
1192            return vamh;
1193        }
1194
1195        // Undo the adapter effect of prepareForInvoker:
1196        private static MethodHandle restoreToType(MethodHandle vamh,
1197                                                  MethodHandle original,
1198                                                  Class<?> hostClass) {
1199            MethodType type = original.type();
1200            MethodHandle mh = vamh.asCollector(Object[].class, type.parameterCount());
1201            MemberName member = original.internalMemberName();
1202            mh = mh.asType(type);
1203            mh = new WrappedMember(mh, type, member, original.isInvokeSpecial(), hostClass);
1204            return mh;
1205        }
1206
1207        private static boolean checkInjectedInvoker(Class<?> hostClass, Class<?> invokerClass) {
1208            assert (hostClass.getClassLoader() == invokerClass.getClassLoader()) : hostClass.getName()+" (CL)";
1209            try {
1210                assert (hostClass.getProtectionDomain() == invokerClass.getProtectionDomain()) : hostClass.getName()+" (PD)";
1211            } catch (SecurityException ex) {
1212                // Self-check was blocked by security manager. This is OK.
1213            }
1214            try {
1215                // Test the invoker to ensure that it really injects into the right place.
1216                MethodHandle invoker = IMPL_LOOKUP.findStatic(invokerClass, "invoke_V", INVOKER_MT);
1217                MethodHandle vamh = prepareForInvoker(MH_checkCallerClass);
1218                return (boolean)invoker.invoke(vamh, new Object[]{ invokerClass });
1219            } catch (Throwable ex) {
1220                throw new InternalError(ex);
1221            }
1222        }
1223
1224        private static final MethodHandle MH_checkCallerClass;
1225        static {
1226            final Class<?> THIS_CLASS = BindCaller.class;
1227            assert(checkCallerClass(THIS_CLASS));
1228            try {
1229                MH_checkCallerClass = IMPL_LOOKUP
1230                    .findStatic(THIS_CLASS, "checkCallerClass",
1231                                MethodType.methodType(boolean.class, Class.class));
1232                assert((boolean) MH_checkCallerClass.invokeExact(THIS_CLASS));
1233            } catch (Throwable ex) {
1234                throw new InternalError(ex);
1235            }
1236        }
1237
1238        @CallerSensitive
1239        @ForceInline // to ensure Reflection.getCallerClass optimization
1240        private static boolean checkCallerClass(Class<?> expected) {
1241            // This method is called via MH_checkCallerClass and so it's correct to ask for the immediate caller here.
1242            Class<?> actual = Reflection.getCallerClass();
1243            if (actual != expected)
1244                throw new InternalError("found " + actual.getName() + ", expected " + expected.getName());
1245            return true;
1246        }
1247
1248        private static final byte[] INJECTED_INVOKER_TEMPLATE = generateInvokerTemplate();
1249
1250        /** Produces byte code for a class that is used as an injected invoker. */
1251        private static byte[] generateInvokerTemplate() {
1252            ClassWriter cw = new ClassWriter(0);
1253
1254            // private static class InjectedInvoker {
1255            //     @Hidden
1256            //     static Object invoke_V(MethodHandle vamh, Object[] args) throws Throwable {
1257            //        return vamh.invokeExact(args);
1258            //     }
1259            // }
1260            cw.visit(52, ACC_PRIVATE | ACC_SUPER, "InjectedInvoker", null, "java/lang/Object", null);
1261
1262            MethodVisitor mv = cw.visitMethod(ACC_STATIC, "invoke_V",
1263                          "(Ljava/lang/invoke/MethodHandle;[Ljava/lang/Object;)Ljava/lang/Object;",
1264                          null, null);
1265
1266            // Suppress invoker method in stack traces.
1267            AnnotationVisitor av0 = mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true);
1268            av0.visitEnd();
1269
1270            mv.visitCode();
1271            mv.visitVarInsn(ALOAD, 0);
1272            mv.visitVarInsn(ALOAD, 1);
1273            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle", "invokeExact",
1274                               "([Ljava/lang/Object;)Ljava/lang/Object;", false);
1275            mv.visitInsn(ARETURN);
1276            mv.visitMaxs(2, 2);
1277            mv.visitEnd();
1278
1279            cw.visitEnd();
1280            return cw.toByteArray();
1281        }
1282    }
1283
1284    /** This subclass allows a wrapped method handle to be re-associated with an arbitrary member name. */
1285    private static final class WrappedMember extends DelegatingMethodHandle {
1286        private final MethodHandle target;
1287        private final MemberName member;
1288        private final Class<?> callerClass;
1289        private final boolean isInvokeSpecial;
1290
1291        private WrappedMember(MethodHandle target, MethodType type,
1292                              MemberName member, boolean isInvokeSpecial,
1293                              Class<?> callerClass) {
1294            super(type, target);
1295            this.target = target;
1296            this.member = member;
1297            this.callerClass = callerClass;
1298            this.isInvokeSpecial = isInvokeSpecial;
1299        }
1300
1301        @Override
1302        MemberName internalMemberName() {
1303            return member;
1304        }
1305        @Override
1306        Class<?> internalCallerClass() {
1307            return callerClass;
1308        }
1309        @Override
1310        boolean isInvokeSpecial() {
1311            return isInvokeSpecial;
1312        }
1313        @Override
1314        protected MethodHandle getTarget() {
1315            return target;
1316        }
1317        @Override
1318        public MethodHandle asTypeUncached(MethodType newType) {
1319            // This MH is an alias for target, except for the MemberName
1320            // Drop the MemberName if there is any conversion.
1321            return asTypeCache = target.asType(newType);
1322        }
1323    }
1324
1325    static MethodHandle makeWrappedMember(MethodHandle target, MemberName member, boolean isInvokeSpecial) {
1326        if (member.equals(target.internalMemberName()) && isInvokeSpecial == target.isInvokeSpecial())
1327            return target;
1328        return new WrappedMember(target, target.type(), member, isInvokeSpecial, null);
1329    }
1330
1331    /** Intrinsic IDs */
1332    /*non-public*/
1333    enum Intrinsic {
1334        SELECT_ALTERNATIVE,
1335        GUARD_WITH_CATCH,
1336        TRY_FINALLY,
1337        LOOP,
1338        NEW_ARRAY,
1339        ARRAY_LOAD,
1340        ARRAY_STORE,
1341        ARRAY_LENGTH,
1342        IDENTITY,
1343        ZERO,
1344        NONE // no intrinsic associated
1345    }
1346
1347    /** Mark arbitrary method handle as intrinsic.
1348     * InvokerBytecodeGenerator uses this info to produce more efficient bytecode shape. */
1349    static final class IntrinsicMethodHandle extends DelegatingMethodHandle {
1350        private final MethodHandle target;
1351        private final Intrinsic intrinsicName;
1352
1353        IntrinsicMethodHandle(MethodHandle target, Intrinsic intrinsicName) {
1354            super(target.type(), target);
1355            this.target = target;
1356            this.intrinsicName = intrinsicName;
1357        }
1358
1359        @Override
1360        protected MethodHandle getTarget() {
1361            return target;
1362        }
1363
1364        @Override
1365        Intrinsic intrinsicName() {
1366            return intrinsicName;
1367        }
1368
1369        @Override
1370        public MethodHandle asTypeUncached(MethodType newType) {
1371            // This MH is an alias for target, except for the intrinsic name
1372            // Drop the name if there is any conversion.
1373            return asTypeCache = target.asType(newType);
1374        }
1375
1376        @Override
1377        String internalProperties() {
1378            return super.internalProperties() +
1379                    "\n& Intrinsic="+intrinsicName;
1380        }
1381
1382        @Override
1383        public MethodHandle asCollector(Class<?> arrayType, int arrayLength) {
1384            if (intrinsicName == Intrinsic.IDENTITY) {
1385                MethodType resultType = type().asCollectorType(arrayType, type().parameterCount() - 1, arrayLength);
1386                MethodHandle newArray = MethodHandleImpl.varargsArray(arrayType, arrayLength);
1387                return newArray.asType(resultType);
1388            }
1389            return super.asCollector(arrayType, arrayLength);
1390        }
1391    }
1392
1393    static MethodHandle makeIntrinsic(MethodHandle target, Intrinsic intrinsicName) {
1394        if (intrinsicName == target.intrinsicName())
1395            return target;
1396        return new IntrinsicMethodHandle(target, intrinsicName);
1397    }
1398
1399    static MethodHandle makeIntrinsic(MethodType type, LambdaForm form, Intrinsic intrinsicName) {
1400        return new IntrinsicMethodHandle(SimpleMethodHandle.make(type, form), intrinsicName);
1401    }
1402
1403    /// Collection of multiple arguments.
1404
1405    private static MethodHandle findCollector(String name, int nargs, Class<?> rtype, Class<?>... ptypes) {
1406        MethodType type = MethodType.genericMethodType(nargs)
1407                .changeReturnType(rtype)
1408                .insertParameterTypes(0, ptypes);
1409        try {
1410            return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, name, type);
1411        } catch (ReflectiveOperationException ex) {
1412            return null;
1413        }
1414    }
1415
1416    private static final Object[] NO_ARGS_ARRAY = {};
1417    private static Object[] makeArray(Object... args) { return args; }
1418    private static Object[] array() { return NO_ARGS_ARRAY; }
1419    private static Object[] array(Object a0)
1420                { return makeArray(a0); }
1421    private static Object[] array(Object a0, Object a1)
1422                { return makeArray(a0, a1); }
1423    private static Object[] array(Object a0, Object a1, Object a2)
1424                { return makeArray(a0, a1, a2); }
1425    private static Object[] array(Object a0, Object a1, Object a2, Object a3)
1426                { return makeArray(a0, a1, a2, a3); }
1427    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
1428                                  Object a4)
1429                { return makeArray(a0, a1, a2, a3, a4); }
1430    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
1431                                  Object a4, Object a5)
1432                { return makeArray(a0, a1, a2, a3, a4, a5); }
1433    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
1434                                  Object a4, Object a5, Object a6)
1435                { return makeArray(a0, a1, a2, a3, a4, a5, a6); }
1436    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
1437                                  Object a4, Object a5, Object a6, Object a7)
1438                { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7); }
1439    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
1440                                  Object a4, Object a5, Object a6, Object a7,
1441                                  Object a8)
1442                { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
1443    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
1444                                  Object a4, Object a5, Object a6, Object a7,
1445                                  Object a8, Object a9)
1446                { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
1447
1448    private static final int ARRAYS_COUNT = 11;
1449    private static final @Stable MethodHandle[] ARRAYS = new MethodHandle[MAX_ARITY + 1];
1450
1451    // filling versions of the above:
1452    // using Integer len instead of int len and no varargs to avoid bootstrapping problems
1453    private static Object[] fillNewArray(Integer len, Object[] /*not ...*/ args) {
1454        Object[] a = new Object[len];
1455        fillWithArguments(a, 0, args);
1456        return a;
1457    }
1458    private static Object[] fillNewTypedArray(Object[] example, Integer len, Object[] /*not ...*/ args) {
1459        Object[] a = Arrays.copyOf(example, len);
1460        assert(a.getClass() != Object[].class);
1461        fillWithArguments(a, 0, args);
1462        return a;
1463    }
1464    private static void fillWithArguments(Object[] a, int pos, Object... args) {
1465        System.arraycopy(args, 0, a, pos, args.length);
1466    }
1467    // using Integer pos instead of int pos to avoid bootstrapping problems
1468    private static Object[] fillArray(Integer pos, Object[] a, Object a0)
1469                { fillWithArguments(a, pos, a0); return a; }
1470    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1)
1471                { fillWithArguments(a, pos, a0, a1); return a; }
1472    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2)
1473                { fillWithArguments(a, pos, a0, a1, a2); return a; }
1474    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3)
1475                { fillWithArguments(a, pos, a0, a1, a2, a3); return a; }
1476    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
1477                                  Object a4)
1478                { fillWithArguments(a, pos, a0, a1, a2, a3, a4); return a; }
1479    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
1480                                  Object a4, Object a5)
1481                { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5); return a; }
1482    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
1483                                  Object a4, Object a5, Object a6)
1484                { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6); return a; }
1485    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
1486                                  Object a4, Object a5, Object a6, Object a7)
1487                { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7); return a; }
1488    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
1489                                  Object a4, Object a5, Object a6, Object a7,
1490                                  Object a8)
1491                { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8); return a; }
1492    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
1493                                  Object a4, Object a5, Object a6, Object a7,
1494                                  Object a8, Object a9)
1495                { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); return a; }
1496
1497    private static final int FILL_ARRAYS_COUNT = 11; // current number of fillArray methods
1498    private static final @Stable MethodHandle[] FILL_ARRAYS = new MethodHandle[FILL_ARRAYS_COUNT];
1499
1500    private static MethodHandle getFillArray(int count) {
1501        assert (count > 0 && count < FILL_ARRAYS_COUNT);
1502        MethodHandle mh = FILL_ARRAYS[count];
1503        if (mh != null) {
1504            return mh;
1505        }
1506        mh = findCollector("fillArray", count, Object[].class, Integer.class, Object[].class);
1507        FILL_ARRAYS[count] = mh;
1508        return mh;
1509    }
1510
1511    private static Object copyAsPrimitiveArray(Wrapper w, Object... boxes) {
1512        Object a = w.makeArray(boxes.length);
1513        w.copyArrayUnboxing(boxes, 0, a, 0, boxes.length);
1514        return a;
1515    }
1516
1517    /** Return a method handle that takes the indicated number of Object
1518     *  arguments and returns an Object array of them, as if for varargs.
1519     */
1520    static MethodHandle varargsArray(int nargs) {
1521        MethodHandle mh = ARRAYS[nargs];
1522        if (mh != null) {
1523            return mh;
1524        }
1525        if (nargs < ARRAYS_COUNT) {
1526            mh = findCollector("array", nargs, Object[].class);
1527        } else {
1528            mh = buildVarargsArray(getConstantHandle(MH_fillNewArray),
1529                    getConstantHandle(MH_arrayIdentity), nargs);
1530        }
1531        assert(assertCorrectArity(mh, nargs));
1532        mh = makeIntrinsic(mh, Intrinsic.NEW_ARRAY);
1533        return ARRAYS[nargs] = mh;
1534    }
1535
1536    private static boolean assertCorrectArity(MethodHandle mh, int arity) {
1537        assert(mh.type().parameterCount() == arity) : "arity != "+arity+": "+mh;
1538        return true;
1539    }
1540
1541    // Array identity function (used as getConstantHandle(MH_arrayIdentity)).
1542    static <T> T[] identity(T[] x) {
1543        return x;
1544    }
1545
1546    private static MethodHandle buildVarargsArray(MethodHandle newArray, MethodHandle finisher, int nargs) {
1547        // Build up the result mh as a sequence of fills like this:
1548        //   finisher(fill(fill(newArrayWA(23,x1..x10),10,x11..x20),20,x21..x23))
1549        // The various fill(_,10*I,___*[J]) are reusable.
1550        int leftLen = Math.min(nargs, LEFT_ARGS);  // absorb some arguments immediately
1551        int rightLen = nargs - leftLen;
1552        MethodHandle leftCollector = newArray.bindTo(nargs);
1553        leftCollector = leftCollector.asCollector(Object[].class, leftLen);
1554        MethodHandle mh = finisher;
1555        if (rightLen > 0) {
1556            MethodHandle rightFiller = fillToRight(LEFT_ARGS + rightLen);
1557            if (mh.equals(getConstantHandle(MH_arrayIdentity)))
1558                mh = rightFiller;
1559            else
1560                mh = MethodHandles.collectArguments(mh, 0, rightFiller);
1561        }
1562        if (mh.equals(getConstantHandle(MH_arrayIdentity)))
1563            mh = leftCollector;
1564        else
1565            mh = MethodHandles.collectArguments(mh, 0, leftCollector);
1566        return mh;
1567    }
1568
1569    private static final int LEFT_ARGS = FILL_ARRAYS_COUNT - 1;
1570    private static final @Stable MethodHandle[] FILL_ARRAY_TO_RIGHT = new MethodHandle[MAX_ARITY + 1];
1571    /** fill_array_to_right(N).invoke(a, argL..arg[N-1])
1572     *  fills a[L]..a[N-1] with corresponding arguments,
1573     *  and then returns a.  The value L is a global constant (LEFT_ARGS).
1574     */
1575    private static MethodHandle fillToRight(int nargs) {
1576        MethodHandle filler = FILL_ARRAY_TO_RIGHT[nargs];
1577        if (filler != null)  return filler;
1578        filler = buildFiller(nargs);
1579        assert(assertCorrectArity(filler, nargs - LEFT_ARGS + 1));
1580        return FILL_ARRAY_TO_RIGHT[nargs] = filler;
1581    }
1582    private static MethodHandle buildFiller(int nargs) {
1583        if (nargs <= LEFT_ARGS)
1584            return getConstantHandle(MH_arrayIdentity);  // no args to fill; return the array unchanged
1585        // we need room for both mh and a in mh.invoke(a, arg*[nargs])
1586        final int CHUNK = LEFT_ARGS;
1587        int rightLen = nargs % CHUNK;
1588        int midLen = nargs - rightLen;
1589        if (rightLen == 0) {
1590            midLen = nargs - (rightLen = CHUNK);
1591            if (FILL_ARRAY_TO_RIGHT[midLen] == null) {
1592                // build some precursors from left to right
1593                for (int j = LEFT_ARGS % CHUNK; j < midLen; j += CHUNK)
1594                    if (j > LEFT_ARGS)  fillToRight(j);
1595            }
1596        }
1597        if (midLen < LEFT_ARGS) rightLen = nargs - (midLen = LEFT_ARGS);
1598        assert(rightLen > 0);
1599        MethodHandle midFill = fillToRight(midLen);  // recursive fill
1600        MethodHandle rightFill = getFillArray(rightLen).bindTo(midLen);  // [midLen..nargs-1]
1601        assert(midFill.type().parameterCount()   == 1 + midLen - LEFT_ARGS);
1602        assert(rightFill.type().parameterCount() == 1 + rightLen);
1603
1604        // Combine the two fills:
1605        //   right(mid(a, x10..x19), x20..x23)
1606        // The final product will look like this:
1607        //   right(mid(newArrayLeft(24, x0..x9), x10..x19), x20..x23)
1608        if (midLen == LEFT_ARGS)
1609            return rightFill;
1610        else
1611            return MethodHandles.collectArguments(rightFill, 0, midFill);
1612    }
1613
1614    static final int MAX_JVM_ARITY = 255;  // limit imposed by the JVM
1615
1616    /** Return a method handle that takes the indicated number of
1617     *  typed arguments and returns an array of them.
1618     *  The type argument is the array type.
1619     */
1620    static MethodHandle varargsArray(Class<?> arrayType, int nargs) {
1621        Class<?> elemType = arrayType.getComponentType();
1622        if (elemType == null)  throw new IllegalArgumentException("not an array: "+arrayType);
1623        // FIXME: Need more special casing and caching here.
1624        if (nargs >= MAX_JVM_ARITY/2 - 1) {
1625            int slots = nargs;
1626            final int MAX_ARRAY_SLOTS = MAX_JVM_ARITY - 1;  // 1 for receiver MH
1627            if (slots <= MAX_ARRAY_SLOTS && elemType.isPrimitive())
1628                slots *= Wrapper.forPrimitiveType(elemType).stackSlots();
1629            if (slots > MAX_ARRAY_SLOTS)
1630                throw new IllegalArgumentException("too many arguments: "+arrayType.getSimpleName()+", length "+nargs);
1631        }
1632        if (elemType == Object.class)
1633            return varargsArray(nargs);
1634        // other cases:  primitive arrays, subtypes of Object[]
1635        MethodHandle cache[] = Makers.TYPED_COLLECTORS.get(elemType);
1636        MethodHandle mh = nargs < cache.length ? cache[nargs] : null;
1637        if (mh != null)  return mh;
1638        if (nargs == 0) {
1639            Object example = java.lang.reflect.Array.newInstance(arrayType.getComponentType(), 0);
1640            mh = MethodHandles.constant(arrayType, example);
1641        } else if (elemType.isPrimitive()) {
1642            MethodHandle builder = getConstantHandle(MH_fillNewArray);
1643            MethodHandle producer = buildArrayProducer(arrayType);
1644            mh = buildVarargsArray(builder, producer, nargs);
1645        } else {
1646            Class<? extends Object[]> objArrayType = arrayType.asSubclass(Object[].class);
1647            Object[] example = Arrays.copyOf(NO_ARGS_ARRAY, 0, objArrayType);
1648            MethodHandle builder = getConstantHandle(MH_fillNewTypedArray).bindTo(example);
1649            MethodHandle producer = getConstantHandle(MH_arrayIdentity); // must be weakly typed
1650            mh = buildVarargsArray(builder, producer, nargs);
1651        }
1652        mh = mh.asType(MethodType.methodType(arrayType, Collections.<Class<?>>nCopies(nargs, elemType)));
1653        mh = makeIntrinsic(mh, Intrinsic.NEW_ARRAY);
1654        assert(assertCorrectArity(mh, nargs));
1655        if (nargs < cache.length)
1656            cache[nargs] = mh;
1657        return mh;
1658    }
1659
1660    private static MethodHandle buildArrayProducer(Class<?> arrayType) {
1661        Class<?> elemType = arrayType.getComponentType();
1662        assert(elemType.isPrimitive());
1663        return getConstantHandle(MH_copyAsPrimitiveArray).bindTo(Wrapper.forPrimitiveType(elemType));
1664    }
1665
1666    /*non-public*/ static void assertSame(Object mh1, Object mh2) {
1667        if (mh1 != mh2) {
1668            String msg = String.format("mh1 != mh2: mh1 = %s (form: %s); mh2 = %s (form: %s)",
1669                    mh1, ((MethodHandle)mh1).form,
1670                    mh2, ((MethodHandle)mh2).form);
1671            throw newInternalError(msg);
1672        }
1673    }
1674
1675    // Local constant functions:
1676
1677    /* non-public */
1678    static final byte NF_checkSpreadArgument = 0,
1679            NF_guardWithCatch = 1,
1680            NF_throwException = 2,
1681            NF_tryFinally = 3,
1682            NF_loop = 4,
1683            NF_profileBoolean = 5,
1684            NF_LIMIT = 6;
1685
1686    private static final @Stable NamedFunction[] NFS = new NamedFunction[NF_LIMIT];
1687
1688    static NamedFunction getFunction(byte func) {
1689        NamedFunction nf = NFS[func];
1690        if (nf != null) {
1691            return nf;
1692        }
1693        return NFS[func] = createFunction(func);
1694    }
1695
1696    private static NamedFunction createFunction(byte func) {
1697        try {
1698            switch (func) {
1699                case NF_checkSpreadArgument:
1700                    return new NamedFunction(MethodHandleImpl.class
1701                            .getDeclaredMethod("checkSpreadArgument", Object.class, int.class));
1702                case NF_guardWithCatch:
1703                    return new NamedFunction(MethodHandleImpl.class
1704                            .getDeclaredMethod("guardWithCatch", MethodHandle.class, Class.class,
1705                                    MethodHandle.class, Object[].class));
1706                case NF_tryFinally:
1707                    return new NamedFunction(MethodHandleImpl.class
1708                            .getDeclaredMethod("tryFinally", MethodHandle.class, MethodHandle.class, Object[].class));
1709                case NF_loop:
1710                    return new NamedFunction(MethodHandleImpl.class
1711                            .getDeclaredMethod("loop", BasicType[].class, LoopClauses.class, Object[].class));
1712                case NF_throwException:
1713                    return new NamedFunction(MethodHandleImpl.class
1714                            .getDeclaredMethod("throwException", Throwable.class));
1715                case NF_profileBoolean:
1716                    return new NamedFunction(MethodHandleImpl.class
1717                            .getDeclaredMethod("profileBoolean", boolean.class, int[].class));
1718                default:
1719                    throw new InternalError("Undefined function: " + func);
1720            }
1721        } catch (ReflectiveOperationException ex) {
1722            throw newInternalError(ex);
1723        }
1724    }
1725
1726    static {
1727        SharedSecrets.setJavaLangInvokeAccess(new JavaLangInvokeAccess() {
1728            @Override
1729            public Object newMemberName() {
1730                return new MemberName();
1731            }
1732
1733            @Override
1734            public String getName(Object mname) {
1735                MemberName memberName = (MemberName)mname;
1736                return memberName.getName();
1737            }
1738
1739            @Override
1740            public boolean isNative(Object mname) {
1741                MemberName memberName = (MemberName)mname;
1742                return memberName.isNative();
1743            }
1744
1745            @Override
1746            public byte[] generateDirectMethodHandleHolderClassBytes(
1747                    String className, MethodType[] methodTypes, int[] types) {
1748                return GenerateJLIClassesHelper
1749                        .generateDirectMethodHandleHolderClassBytes(
1750                                className, methodTypes, types);
1751            }
1752
1753            @Override
1754            public byte[] generateDelegatingMethodHandleHolderClassBytes(
1755                    String className, MethodType[] methodTypes) {
1756                return GenerateJLIClassesHelper
1757                        .generateDelegatingMethodHandleHolderClassBytes(
1758                                className, methodTypes);
1759            }
1760
1761            @Override
1762            public Map.Entry<String, byte[]> generateConcreteBMHClassBytes(
1763                    final String types) {
1764                return GenerateJLIClassesHelper
1765                        .generateConcreteBMHClassBytes(types);
1766            }
1767
1768            @Override
1769            public byte[] generateBasicFormsClassBytes(final String className) {
1770                return GenerateJLIClassesHelper
1771                        .generateBasicFormsClassBytes(className);
1772            }
1773
1774            @Override
1775            public byte[] generateInvokersHolderClassBytes(final String className,
1776                    MethodType[] methodTypes) {
1777                return GenerateJLIClassesHelper
1778                        .generateInvokersHolderClassBytes(className, methodTypes);
1779            }
1780        });
1781    }
1782
1783    /** Result unboxing: ValueConversions.unbox() OR ValueConversions.identity() OR ValueConversions.ignore(). */
1784    private static MethodHandle unboxResultHandle(Class<?> returnType) {
1785        if (returnType.isPrimitive()) {
1786            if (returnType == void.class) {
1787                return ValueConversions.ignore();
1788            } else {
1789                Wrapper w = Wrapper.forPrimitiveType(returnType);
1790                return ValueConversions.unboxExact(w);
1791            }
1792        } else {
1793            return MethodHandles.identity(Object.class);
1794        }
1795    }
1796
1797    /**
1798     * Assembles a loop method handle from the given handles and type information.
1799     *
1800     * @param tloop the return type of the loop.
1801     * @param targs types of the arguments to be passed to the loop.
1802     * @param init sanitized array of initializers for loop-local variables.
1803     * @param step sanitited array of loop bodies.
1804     * @param pred sanitized array of predicates.
1805     * @param fini sanitized array of loop finalizers.
1806     *
1807     * @return a handle that, when invoked, will execute the loop.
1808     */
1809    static MethodHandle makeLoop(Class<?> tloop, List<Class<?>> targs, List<MethodHandle> init, List<MethodHandle> step,
1810                                 List<MethodHandle> pred, List<MethodHandle> fini) {
1811        MethodType type = MethodType.methodType(tloop, targs);
1812        BasicType[] initClauseTypes =
1813                init.stream().map(h -> h.type().returnType()).map(BasicType::basicType).toArray(BasicType[]::new);
1814        LambdaForm form = makeLoopForm(type.basicType(), initClauseTypes);
1815
1816        // Prepare auxiliary method handles used during LambdaForm interpretation.
1817        // Box arguments and wrap them into Object[]: ValueConversions.array().
1818        MethodType varargsType = type.changeReturnType(Object[].class);
1819        MethodHandle collectArgs = varargsArray(type.parameterCount()).asType(varargsType);
1820        MethodHandle unboxResult = unboxResultHandle(tloop);
1821
1822        LoopClauses clauseData =
1823                new LoopClauses(new MethodHandle[][]{toArray(init), toArray(step), toArray(pred), toArray(fini)});
1824        BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLL();
1825        BoundMethodHandle mh;
1826        try {
1827            mh = (BoundMethodHandle) data.constructor().invokeBasic(type, form, (Object) clauseData,
1828                    (Object) collectArgs, (Object) unboxResult);
1829        } catch (Throwable ex) {
1830            throw uncaughtException(ex);
1831        }
1832        assert(mh.type() == type);
1833        return mh;
1834    }
1835
1836    private static MethodHandle[] toArray(List<MethodHandle> l) {
1837        return l.toArray(new MethodHandle[0]);
1838    }
1839
1840    /**
1841     * Loops introduce some complexity as they can have additional local state. Hence, LambdaForms for loops are
1842     * generated from a template. The LambdaForm template shape for the loop combinator is as follows (assuming one
1843     * reference parameter passed in {@code a1}, and a reference return type, with the return value represented by
1844     * {@code t12}):
1845     * <blockquote><pre>{@code
1846     *  loop=Lambda(a0:L,a1:L)=>{
1847     *    t2:L=BoundMethodHandle$Species_L3.argL0(a0:L);    // LoopClauses holding init, step, pred, fini handles
1848     *    t3:L=BoundMethodHandle$Species_L3.argL1(a0:L);    // helper handle to box the arguments into an Object[]
1849     *    t4:L=BoundMethodHandle$Species_L3.argL2(a0:L);    // helper handle to unbox the result
1850     *    t5:L=MethodHandle.invokeBasic(t3:L,a1:L);         // box the arguments into an Object[]
1851     *    t6:L=MethodHandleImpl.loop(null,t2:L,t3:L);       // call the loop executor
1852     *    t7:L=MethodHandle.invokeBasic(t4:L,t6:L);t7:L}    // unbox the result; return the result
1853     * }</pre></blockquote>
1854     * <p>
1855     * {@code argL0} is a LoopClauses instance holding, in a 2-dimensional array, the init, step, pred, and fini method
1856     * handles. {@code argL1} and {@code argL2} are auxiliary method handles: {@code argL1} boxes arguments and wraps
1857     * them into {@code Object[]} ({@code ValueConversions.array()}), and {@code argL2} unboxes the result if necessary
1858     * ({@code ValueConversions.unbox()}).
1859     * <p>
1860     * Having {@code t3} and {@code t4} passed in via a BMH and not hardcoded in the lambda form allows to share lambda
1861     * forms among loop combinators with the same basic type.
1862     * <p>
1863     * The above template is instantiated by using the {@link LambdaFormEditor} to replace the {@code null} argument to
1864     * the {@code loop} invocation with the {@code BasicType} array describing the loop clause types. This argument is
1865     * ignored in the loop invoker, but will be extracted and used in {@linkplain InvokerBytecodeGenerator#emitLoop(int)
1866     * bytecode generation}.
1867     */
1868    private static LambdaForm makeLoopForm(MethodType basicType, BasicType[] localVarTypes) {
1869        MethodType lambdaType = basicType.invokerType();
1870
1871        final int THIS_MH = 0;  // the BMH_LLL
1872        final int ARG_BASE = 1; // start of incoming arguments
1873        final int ARG_LIMIT = ARG_BASE + basicType.parameterCount();
1874
1875        int nameCursor = ARG_LIMIT;
1876        final int GET_CLAUSE_DATA = nameCursor++;
1877        final int GET_COLLECT_ARGS = nameCursor++;
1878        final int GET_UNBOX_RESULT = nameCursor++;
1879        final int BOXED_ARGS = nameCursor++;
1880        final int LOOP = nameCursor++;
1881        final int UNBOX_RESULT = nameCursor++;
1882
1883        LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_LOOP);
1884        if (lform == null) {
1885            Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType);
1886
1887            BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLL();
1888            names[THIS_MH] = names[THIS_MH].withConstraint(data);
1889            names[GET_CLAUSE_DATA] = new Name(data.getterFunction(0), names[THIS_MH]);
1890            names[GET_COLLECT_ARGS] = new Name(data.getterFunction(1), names[THIS_MH]);
1891            names[GET_UNBOX_RESULT] = new Name(data.getterFunction(2), names[THIS_MH]);
1892
1893            // t_{i}:L=MethodHandle.invokeBasic(collectArgs:L,a1:L,...);
1894            MethodType collectArgsType = basicType.changeReturnType(Object.class);
1895            MethodHandle invokeBasic = MethodHandles.basicInvoker(collectArgsType);
1896            Object[] args = new Object[invokeBasic.type().parameterCount()];
1897            args[0] = names[GET_COLLECT_ARGS];
1898            System.arraycopy(names, ARG_BASE, args, 1, ARG_LIMIT - ARG_BASE);
1899            names[BOXED_ARGS] = new Name(new NamedFunction(invokeBasic, Intrinsic.LOOP), args);
1900
1901            // t_{i+1}:L=MethodHandleImpl.loop(localTypes:L,clauses:L,t_{i}:L);
1902            Object[] lArgs =
1903                    new Object[]{null, // placeholder for BasicType[] localTypes - will be added by LambdaFormEditor
1904                            names[GET_CLAUSE_DATA], names[BOXED_ARGS]};
1905            names[LOOP] = new Name(getFunction(NF_loop), lArgs);
1906
1907            // t_{i+2}:I=MethodHandle.invokeBasic(unbox:L,t_{i+1}:L);
1908            MethodHandle invokeBasicUnbox = MethodHandles.basicInvoker(MethodType.methodType(basicType.rtype(), Object.class));
1909            Object[] unboxArgs = new Object[]{names[GET_UNBOX_RESULT], names[LOOP]};
1910            names[UNBOX_RESULT] = new Name(invokeBasicUnbox, unboxArgs);
1911
1912            lform = basicType.form().setCachedLambdaForm(MethodTypeForm.LF_LOOP,
1913                    new LambdaForm(lambdaType.parameterCount(), names, Kind.LOOP));
1914        }
1915
1916        // BOXED_ARGS is the index into the names array where the loop idiom starts
1917        return lform.editor().noteLoopLocalTypesForm(BOXED_ARGS, localVarTypes);
1918    }
1919
1920    static class LoopClauses {
1921        @Stable final MethodHandle[][] clauses;
1922        LoopClauses(MethodHandle[][] clauses) {
1923            assert clauses.length == 4;
1924            this.clauses = clauses;
1925        }
1926        @Override
1927        public String toString() {
1928            StringBuffer sb = new StringBuffer("LoopClauses -- ");
1929            for (int i = 0; i < 4; ++i) {
1930                if (i > 0) {
1931                    sb.append("       ");
1932                }
1933                sb.append('<').append(i).append(">: ");
1934                MethodHandle[] hs = clauses[i];
1935                for (int j = 0; j < hs.length; ++j) {
1936                    if (j > 0) {
1937                        sb.append("          ");
1938                    }
1939                    sb.append('*').append(j).append(": ").append(hs[j]).append('\n');
1940                }
1941            }
1942            sb.append(" --\n");
1943            return sb.toString();
1944        }
1945    }
1946
1947    /**
1948     * Intrinsified during LambdaForm compilation
1949     * (see {@link InvokerBytecodeGenerator#emitLoop(int)}).
1950     */
1951    @LambdaForm.Hidden
1952    static Object loop(BasicType[] localTypes, LoopClauses clauseData, Object... av) throws Throwable {
1953        final MethodHandle[] init = clauseData.clauses[0];
1954        final MethodHandle[] step = clauseData.clauses[1];
1955        final MethodHandle[] pred = clauseData.clauses[2];
1956        final MethodHandle[] fini = clauseData.clauses[3];
1957        int varSize = (int) Stream.of(init).filter(h -> h.type().returnType() != void.class).count();
1958        int nArgs = init[0].type().parameterCount();
1959        Object[] varsAndArgs = new Object[varSize + nArgs];
1960        for (int i = 0, v = 0; i < init.length; ++i) {
1961            MethodHandle ih = init[i];
1962            if (ih.type().returnType() == void.class) {
1963                ih.invokeWithArguments(av);
1964            } else {
1965                varsAndArgs[v++] = ih.invokeWithArguments(av);
1966            }
1967        }
1968        System.arraycopy(av, 0, varsAndArgs, varSize, nArgs);
1969        final int nSteps = step.length;
1970        for (; ; ) {
1971            for (int i = 0, v = 0; i < nSteps; ++i) {
1972                MethodHandle p = pred[i];
1973                MethodHandle s = step[i];
1974                MethodHandle f = fini[i];
1975                if (s.type().returnType() == void.class) {
1976                    s.invokeWithArguments(varsAndArgs);
1977                } else {
1978                    varsAndArgs[v++] = s.invokeWithArguments(varsAndArgs);
1979                }
1980                if (!(boolean) p.invokeWithArguments(varsAndArgs)) {
1981                    return f.invokeWithArguments(varsAndArgs);
1982                }
1983            }
1984        }
1985    }
1986
1987    /**
1988     * This method is bound as the predicate in {@linkplain MethodHandles#countedLoop(MethodHandle, MethodHandle,
1989     * MethodHandle) counting loops}.
1990     *
1991     * @param limit the upper bound of the parameter, statically bound at loop creation time.
1992     * @param counter the counter parameter, passed in during loop execution.
1993     *
1994     * @return whether the counter has reached the limit.
1995     */
1996    static boolean countedLoopPredicate(int limit, int counter) {
1997        return counter < limit;
1998    }
1999
2000    /**
2001     * This method is bound as the step function in {@linkplain MethodHandles#countedLoop(MethodHandle, MethodHandle,
2002     * MethodHandle) counting loops} to increment the counter.
2003     *
2004     * @param limit the upper bound of the loop counter (ignored).
2005     * @param counter the loop counter.
2006     *
2007     * @return the loop counter incremented by 1.
2008     */
2009    static int countedLoopStep(int limit, int counter) {
2010        return counter + 1;
2011    }
2012
2013    /**
2014     * This is bound to initialize the loop-local iterator in {@linkplain MethodHandles#iteratedLoop iterating loops}.
2015     *
2016     * @param it the {@link Iterable} over which the loop iterates.
2017     *
2018     * @return an {@link Iterator} over the argument's elements.
2019     */
2020    static Iterator<?> initIterator(Iterable<?> it) {
2021        return it.iterator();
2022    }
2023
2024    /**
2025     * This method is bound as the predicate in {@linkplain MethodHandles#iteratedLoop iterating loops}.
2026     *
2027     * @param it the iterator to be checked.
2028     *
2029     * @return {@code true} iff there are more elements to iterate over.
2030     */
2031    static boolean iteratePredicate(Iterator<?> it) {
2032        return it.hasNext();
2033    }
2034
2035    /**
2036     * This method is bound as the step for retrieving the current value from the iterator in {@linkplain
2037     * MethodHandles#iteratedLoop iterating loops}.
2038     *
2039     * @param it the iterator.
2040     *
2041     * @return the next element from the iterator.
2042     */
2043    static Object iterateNext(Iterator<?> it) {
2044        return it.next();
2045    }
2046
2047    /**
2048     * Makes a {@code try-finally} handle that conforms to the type constraints.
2049     *
2050     * @param target the target to execute in a {@code try-finally} block.
2051     * @param cleanup the cleanup to execute in the {@code finally} block.
2052     * @param rtype the result type of the entire construct.
2053     * @param argTypes the types of the arguments.
2054     *
2055     * @return a handle on the constructed {@code try-finally} block.
2056     */
2057    static MethodHandle makeTryFinally(MethodHandle target, MethodHandle cleanup, Class<?> rtype, List<Class<?>> argTypes) {
2058        MethodType type = MethodType.methodType(rtype, argTypes);
2059        LambdaForm form = makeTryFinallyForm(type.basicType());
2060
2061        // Prepare auxiliary method handles used during LambdaForm interpretation.
2062        // Box arguments and wrap them into Object[]: ValueConversions.array().
2063        MethodType varargsType = type.changeReturnType(Object[].class);
2064        MethodHandle collectArgs = varargsArray(type.parameterCount()).asType(varargsType);
2065        MethodHandle unboxResult = unboxResultHandle(rtype);
2066
2067        BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLL();
2068        BoundMethodHandle mh;
2069        try {
2070            mh = (BoundMethodHandle) data.constructor().invokeBasic(type, form, (Object) target, (Object) cleanup,
2071                    (Object) collectArgs, (Object) unboxResult);
2072        } catch (Throwable ex) {
2073            throw uncaughtException(ex);
2074        }
2075        assert(mh.type() == type);
2076        return mh;
2077    }
2078
2079    /**
2080     * The LambdaForm shape for the tryFinally combinator is as follows (assuming one reference parameter passed in
2081     * {@code a1}, and a reference return type, with the return value represented by {@code t8}):
2082     * <blockquote><pre>{@code
2083     *  tryFinally=Lambda(a0:L,a1:L)=>{
2084     *    t2:L=BoundMethodHandle$Species_LLLL.argL0(a0:L);  // target method handle
2085     *    t3:L=BoundMethodHandle$Species_LLLL.argL1(a0:L);  // cleanup method handle
2086     *    t4:L=BoundMethodHandle$Species_LLLL.argL2(a0:L);  // helper handle to box the arguments into an Object[]
2087     *    t5:L=BoundMethodHandle$Species_LLLL.argL3(a0:L);  // helper handle to unbox the result
2088     *    t6:L=MethodHandle.invokeBasic(t4:L,a1:L);         // box the arguments into an Object[]
2089     *    t7:L=MethodHandleImpl.tryFinally(t2:L,t3:L,t6:L); // call the tryFinally executor
2090     *    t8:L=MethodHandle.invokeBasic(t5:L,t7:L);t8:L}    // unbox the result; return the result
2091     * }</pre></blockquote>
2092     * <p>
2093     * {@code argL0} and {@code argL1} are the target and cleanup method handles.
2094     * {@code argL2} and {@code argL3} are auxiliary method handles: {@code argL2} boxes arguments and wraps them into
2095     * {@code Object[]} ({@code ValueConversions.array()}), and {@code argL3} unboxes the result if necessary
2096     * ({@code ValueConversions.unbox()}).
2097     * <p>
2098     * Having {@code t4} and {@code t5} passed in via a BMH and not hardcoded in the lambda form allows to share lambda
2099     * forms among tryFinally combinators with the same basic type.
2100     */
2101    private static LambdaForm makeTryFinallyForm(MethodType basicType) {
2102        MethodType lambdaType = basicType.invokerType();
2103
2104        LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_TF);
2105        if (lform != null) {
2106            return lform;
2107        }
2108        final int THIS_MH      = 0;  // the BMH_LLLL
2109        final int ARG_BASE     = 1;  // start of incoming arguments
2110        final int ARG_LIMIT    = ARG_BASE + basicType.parameterCount();
2111
2112        int nameCursor = ARG_LIMIT;
2113        final int GET_TARGET       = nameCursor++;
2114        final int GET_CLEANUP      = nameCursor++;
2115        final int GET_COLLECT_ARGS = nameCursor++;
2116        final int GET_UNBOX_RESULT = nameCursor++;
2117        final int BOXED_ARGS       = nameCursor++;
2118        final int TRY_FINALLY      = nameCursor++;
2119        final int UNBOX_RESULT     = nameCursor++;
2120
2121        Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType);
2122
2123        BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLL();
2124        names[THIS_MH]          = names[THIS_MH].withConstraint(data);
2125        names[GET_TARGET]       = new Name(data.getterFunction(0), names[THIS_MH]);
2126        names[GET_CLEANUP]      = new Name(data.getterFunction(1), names[THIS_MH]);
2127        names[GET_COLLECT_ARGS] = new Name(data.getterFunction(2), names[THIS_MH]);
2128        names[GET_UNBOX_RESULT] = new Name(data.getterFunction(3), names[THIS_MH]);
2129
2130        // t_{i}:L=MethodHandle.invokeBasic(collectArgs:L,a1:L,...);
2131        MethodType collectArgsType = basicType.changeReturnType(Object.class);
2132        MethodHandle invokeBasic = MethodHandles.basicInvoker(collectArgsType);
2133        Object[] args = new Object[invokeBasic.type().parameterCount()];
2134        args[0] = names[GET_COLLECT_ARGS];
2135        System.arraycopy(names, ARG_BASE, args, 1, ARG_LIMIT-ARG_BASE);
2136        names[BOXED_ARGS] = new Name(new NamedFunction(invokeBasic, Intrinsic.TRY_FINALLY), args);
2137
2138        // t_{i+1}:L=MethodHandleImpl.tryFinally(target:L,exType:L,catcher:L,t_{i}:L);
2139        Object[] tfArgs = new Object[] {names[GET_TARGET], names[GET_CLEANUP], names[BOXED_ARGS]};
2140        names[TRY_FINALLY] = new Name(getFunction(NF_tryFinally), tfArgs);
2141
2142        // t_{i+2}:I=MethodHandle.invokeBasic(unbox:L,t_{i+1}:L);
2143        MethodHandle invokeBasicUnbox = MethodHandles.basicInvoker(MethodType.methodType(basicType.rtype(), Object.class));
2144        Object[] unboxArgs  = new Object[] {names[GET_UNBOX_RESULT], names[TRY_FINALLY]};
2145        names[UNBOX_RESULT] = new Name(invokeBasicUnbox, unboxArgs);
2146
2147        lform = new LambdaForm(lambdaType.parameterCount(), names, Kind.TRY_FINALLY);
2148
2149        return basicType.form().setCachedLambdaForm(MethodTypeForm.LF_TF, lform);
2150    }
2151
2152    /**
2153     * Intrinsified during LambdaForm compilation
2154     * (see {@link InvokerBytecodeGenerator#emitTryFinally emitTryFinally}).
2155     */
2156    @LambdaForm.Hidden
2157    static Object tryFinally(MethodHandle target, MethodHandle cleanup, Object... av) throws Throwable {
2158        Throwable t = null;
2159        Object r = null;
2160        try {
2161            r = target.invokeWithArguments(av);
2162        } catch (Throwable thrown) {
2163            t = thrown;
2164            throw t;
2165        } finally {
2166            Object[] args = target.type().returnType() == void.class ? prepend(av, t) : prepend(av, t, r);
2167            r = cleanup.invokeWithArguments(args);
2168        }
2169        return r;
2170    }
2171
2172    // Indexes into constant method handles:
2173    static final int
2174            MH_cast                  =  0,
2175            MH_selectAlternative     =  1,
2176            MH_copyAsPrimitiveArray  =  2,
2177            MH_fillNewTypedArray     =  3,
2178            MH_fillNewArray          =  4,
2179            MH_arrayIdentity         =  5,
2180            MH_countedLoopPred       =  6,
2181            MH_countedLoopStep       =  7,
2182            MH_initIterator          =  8,
2183            MH_iteratePred           =  9,
2184            MH_iterateNext           = 10,
2185            MH_Array_newInstance     = 11,
2186            MH_LIMIT                 = 12;
2187
2188    static MethodHandle getConstantHandle(int idx) {
2189        MethodHandle handle = HANDLES[idx];
2190        if (handle != null) {
2191            return handle;
2192        }
2193        return setCachedHandle(idx, makeConstantHandle(idx));
2194    }
2195
2196    private static synchronized MethodHandle setCachedHandle(int idx, final MethodHandle method) {
2197        // Simulate a CAS, to avoid racy duplication of results.
2198        MethodHandle prev = HANDLES[idx];
2199        if (prev != null) {
2200            return prev;
2201        }
2202        HANDLES[idx] = method;
2203        return method;
2204    }
2205
2206    // Local constant method handles:
2207    private static final @Stable MethodHandle[] HANDLES = new MethodHandle[MH_LIMIT];
2208
2209    private static MethodHandle makeConstantHandle(int idx) {
2210        try {
2211            switch (idx) {
2212                case MH_cast:
2213                    return IMPL_LOOKUP.findVirtual(Class.class, "cast",
2214                            MethodType.methodType(Object.class, Object.class));
2215                case MH_copyAsPrimitiveArray:
2216                    return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "copyAsPrimitiveArray",
2217                            MethodType.methodType(Object.class, Wrapper.class, Object[].class));
2218                case MH_arrayIdentity:
2219                    return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "identity",
2220                            MethodType.methodType(Object[].class, Object[].class));
2221                case MH_fillNewArray:
2222                    return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "fillNewArray",
2223                            MethodType.methodType(Object[].class, Integer.class, Object[].class));
2224                case MH_fillNewTypedArray:
2225                    return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "fillNewTypedArray",
2226                            MethodType.methodType(Object[].class, Object[].class, Integer.class, Object[].class));
2227                case MH_selectAlternative:
2228                    return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "selectAlternative",
2229                            MethodType.methodType(MethodHandle.class, boolean.class, MethodHandle.class, MethodHandle.class));
2230                case MH_countedLoopPred:
2231                    return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "countedLoopPredicate",
2232                            MethodType.methodType(boolean.class, int.class, int.class));
2233                case MH_countedLoopStep:
2234                    return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "countedLoopStep",
2235                            MethodType.methodType(int.class, int.class, int.class));
2236                case MH_initIterator:
2237                    return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "initIterator",
2238                            MethodType.methodType(Iterator.class, Iterable.class));
2239                case MH_iteratePred:
2240                    return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "iteratePredicate",
2241                            MethodType.methodType(boolean.class, Iterator.class));
2242                case MH_iterateNext:
2243                    return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "iterateNext",
2244                            MethodType.methodType(Object.class, Iterator.class));
2245                case MH_Array_newInstance:
2246                    return IMPL_LOOKUP.findStatic(Array.class, "newInstance",
2247                            MethodType.methodType(Object.class, Class.class, int.class));
2248            }
2249        } catch (ReflectiveOperationException ex) {
2250            throw newInternalError(ex);
2251        }
2252        throw newInternalError("Unknown function index: " + idx);
2253    }
2254}
2255