1 /*
2 * Copyright (c) 2008, 2016, 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
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(aload, 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) {
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(getConstantHandle(MH_selectAlternative), 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);
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(makeIntrinsic(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();
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(makeIntrinsic(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
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(makeIntrinsic(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
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 makeIntrinsic(IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "selectAlternative",
2229 MethodType.methodType(MethodHandle.class, boolean.class, MethodHandle.class, MethodHandle.class)),
2230 Intrinsic.SELECT_ALTERNATIVE);
2231 case MH_countedLoopPred:
2232 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "countedLoopPredicate",
2233 MethodType.methodType(boolean.class, int.class, int.class));
2234 case MH_countedLoopStep:
2235 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "countedLoopStep",
2236 MethodType.methodType(int.class, int.class, int.class));
2237 case MH_initIterator:
2238 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "initIterator",
2239 MethodType.methodType(Iterator.class, Iterable.class));
2240 case MH_iteratePred:
2241 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "iteratePredicate",
2242 MethodType.methodType(boolean.class, Iterator.class));
2243 case MH_iterateNext:
2244 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "iterateNext",
2245 MethodType.methodType(Object.class, Iterator.class));
2246 case MH_Array_newInstance:
2247 return IMPL_LOOKUP.findStatic(Array.class, "newInstance",
2248 MethodType.methodType(Object.class, Class.class, int.class));
2249 }
2250 } catch (ReflectiveOperationException ex) {
|
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
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) {
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);
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();
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
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
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) {
|