src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java

Print this page
rev 17771 : 8184777: species logic for BoundMethodHandle doesn't scale, needs refactor


 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     /**


 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         }


 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);


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;


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


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);


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


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));




 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().factory().invokeBasic(type, form,
 731                                 (Object) test, (Object) profile(target), (Object) profile(fallback), counts);
 732             } else {
 733                 mh = (BoundMethodHandle)
 734                         BoundMethodHandle.speciesData_LLL().factory().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     /**


 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.BMHSpecies 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         }


 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.BMHSpecies 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);


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.BMHSpecies data = BoundMethodHandle.speciesData_LLLLL();
1041         BoundMethodHandle mh;
1042         try {
1043             mh = (BoundMethodHandle) data.factory().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;


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.BMHSpecies data = BoundMethodHandle.speciesData_LLL();
1825         BoundMethodHandle mh;
1826         try {
1827             mh = (BoundMethodHandle) data.factory().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


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.BMHSpecies 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);


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.BMHSpecies data = BoundMethodHandle.speciesData_LLLL();
2068         BoundMethodHandle mh;
2069         try {
2070             mh = (BoundMethodHandle) data.factory().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


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.BMHSpecies 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));