3926 int foldArgs = combinerType.parameterCount();
3927 Class<?> rtype = combinerType.returnType();
3928 int foldVals = rtype == void.class ? 0 : 1;
3929 int afterInsertPos = foldPos + foldVals;
3930 boolean ok = (targetType.parameterCount() >= afterInsertPos + foldArgs);
3931 if (ok) {
3932 for (int i = 0; i < foldArgs; i++) {
3933 if (combinerType.parameterType(i) != targetType.parameterType(i + afterInsertPos)) {
3934 ok = false;
3935 break;
3936 }
3937 }
3938 }
3939 if (ok && foldVals != 0 && combinerType.returnType() != targetType.parameterType(foldPos))
3940 ok = false;
3941 if (!ok)
3942 throw misMatchedTypes("target and combiner types", targetType, combinerType);
3943 return rtype;
3944 }
3945
3946 /**
3947 * Makes a method handle which adapts a target method handle,
3948 * by guarding it with a test, a boolean-valued method handle.
3949 * If the guard fails, a fallback handle is called instead.
3950 * All three method handles must have the same corresponding
3951 * argument and return types, except that the return type
3952 * of the test must be boolean, and the test is allowed
3953 * to have fewer arguments than the other two method handles.
3954 * <p>
3955 * Here is pseudocode for the resulting adapter. In the code, {@code T}
3956 * represents the uniform result type of the three involved handles;
3957 * {@code A}/{@code a}, the types and values of the {@code target}
3958 * parameters and arguments that are consumed by the {@code test}; and
3959 * {@code B}/{@code b}, those types and values of the {@code target}
3960 * parameters and arguments that are not consumed by the {@code test}.
3961 * <blockquote><pre>{@code
3962 * boolean test(A...);
3963 * T target(A...,B...);
3964 * T fallback(A...,B...);
3965 * T adapter(A... a,B... b) {
4932 * are not identical with the argument types of {@code combiner}
4933 *
4934 * @see #foldArguments(MethodHandle, MethodHandle)
4935 * @since 9
4936 */
4937 public static MethodHandle foldArguments(MethodHandle target, int pos, MethodHandle combiner) {
4938 MethodType targetType = target.type();
4939 MethodType combinerType = combiner.type();
4940 Class<?> rtype = foldArgumentChecks(pos, targetType, combinerType);
4941 BoundMethodHandle result = target.rebind();
4942 boolean dropResult = rtype == void.class;
4943 LambdaForm lform = result.editor().foldArgumentsForm(1 + pos, dropResult, combinerType.basicType());
4944 MethodType newType = targetType;
4945 if (!dropResult) {
4946 newType = newType.dropParameterTypes(pos, pos + 1);
4947 }
4948 result = result.copyWithExtendL(newType, lform, combiner);
4949 return result;
4950 }
4951
4952
4953 private static void checkLoop0(MethodHandle[][] clauses) {
4954 if (clauses == null || clauses.length == 0) {
4955 throw newIllegalArgumentException("null or no clauses passed");
4956 }
4957 if (Stream.of(clauses).anyMatch(Objects::isNull)) {
4958 throw newIllegalArgumentException("null clauses are not allowed");
4959 }
4960 if (Stream.of(clauses).anyMatch(c -> c.length > 4)) {
4961 throw newIllegalArgumentException("All loop clauses must be represented as MethodHandle arrays with at most 4 elements.");
4962 }
4963 }
4964
4965 private static void checkLoop1a(int i, MethodHandle in, MethodHandle st) {
4966 if (in.type().returnType() != st.type().returnType()) {
4967 throw misMatchedTypes("clause " + i + ": init and step return types", in.type().returnType(),
4968 st.type().returnType());
4969 }
4970 }
4971
|
3926 int foldArgs = combinerType.parameterCount();
3927 Class<?> rtype = combinerType.returnType();
3928 int foldVals = rtype == void.class ? 0 : 1;
3929 int afterInsertPos = foldPos + foldVals;
3930 boolean ok = (targetType.parameterCount() >= afterInsertPos + foldArgs);
3931 if (ok) {
3932 for (int i = 0; i < foldArgs; i++) {
3933 if (combinerType.parameterType(i) != targetType.parameterType(i + afterInsertPos)) {
3934 ok = false;
3935 break;
3936 }
3937 }
3938 }
3939 if (ok && foldVals != 0 && combinerType.returnType() != targetType.parameterType(foldPos))
3940 ok = false;
3941 if (!ok)
3942 throw misMatchedTypes("target and combiner types", targetType, combinerType);
3943 return rtype;
3944 }
3945
3946 private static Class<?> foldArgumentChecks(int foldPos, MethodType targetType, MethodType combinerType, int ... argPos) {
3947 int foldArgs = combinerType.parameterCount();
3948 if (argPos.length != foldArgs) {
3949 throw newIllegalArgumentException("combiner and argument map must be equal size", combinerType, argPos.length);
3950 }
3951 Class<?> rtype = combinerType.returnType();
3952 int foldVals = rtype == void.class ? 0 : 1;
3953 boolean ok = true;
3954 for (int i = 0; i < foldArgs; i++) {
3955 int arg = argPos[i];
3956 if (arg < 0 || arg > targetType.parameterCount()) {
3957 throw newIllegalArgumentException("arg outside of target parameterRange", targetType, arg);
3958 }
3959 if (combinerType.parameterType(i) != targetType.parameterType(arg)) {
3960 throw newIllegalArgumentException("target argument type at position " + arg
3961 + " must match combiner argument type at index " + i + ": " + targetType
3962 + " -> " + combinerType + ", map: " + Arrays.toString(argPos));
3963 }
3964 }
3965 if (ok && foldVals != 0 && combinerType.returnType() != targetType.parameterType(foldPos)) {
3966 ok = false;
3967 }
3968 if (!ok)
3969 throw misMatchedTypes("target and combiner types", targetType, combinerType);
3970 return rtype;
3971 }
3972
3973 /**
3974 * Makes a method handle which adapts a target method handle,
3975 * by guarding it with a test, a boolean-valued method handle.
3976 * If the guard fails, a fallback handle is called instead.
3977 * All three method handles must have the same corresponding
3978 * argument and return types, except that the return type
3979 * of the test must be boolean, and the test is allowed
3980 * to have fewer arguments than the other two method handles.
3981 * <p>
3982 * Here is pseudocode for the resulting adapter. In the code, {@code T}
3983 * represents the uniform result type of the three involved handles;
3984 * {@code A}/{@code a}, the types and values of the {@code target}
3985 * parameters and arguments that are consumed by the {@code test}; and
3986 * {@code B}/{@code b}, those types and values of the {@code target}
3987 * parameters and arguments that are not consumed by the {@code test}.
3988 * <blockquote><pre>{@code
3989 * boolean test(A...);
3990 * T target(A...,B...);
3991 * T fallback(A...,B...);
3992 * T adapter(A... a,B... b) {
4959 * are not identical with the argument types of {@code combiner}
4960 *
4961 * @see #foldArguments(MethodHandle, MethodHandle)
4962 * @since 9
4963 */
4964 public static MethodHandle foldArguments(MethodHandle target, int pos, MethodHandle combiner) {
4965 MethodType targetType = target.type();
4966 MethodType combinerType = combiner.type();
4967 Class<?> rtype = foldArgumentChecks(pos, targetType, combinerType);
4968 BoundMethodHandle result = target.rebind();
4969 boolean dropResult = rtype == void.class;
4970 LambdaForm lform = result.editor().foldArgumentsForm(1 + pos, dropResult, combinerType.basicType());
4971 MethodType newType = targetType;
4972 if (!dropResult) {
4973 newType = newType.dropParameterTypes(pos, pos + 1);
4974 }
4975 result = result.copyWithExtendL(newType, lform, combiner);
4976 return result;
4977 }
4978
4979 /**
4980 *
4981 * @param target
4982 * @param pos
4983 * @param combiner
4984 * @param argPositions
4985 * @return
4986 */
4987 static MethodHandle foldArguments(MethodHandle target, int pos, MethodHandle combiner, int ... argPositions) {
4988 MethodType targetType = target.type();
4989 MethodType combinerType = combiner.type();
4990 Class<?> rtype = foldArgumentChecks(pos, targetType, combinerType, argPositions);
4991 BoundMethodHandle result = target.rebind();
4992 boolean dropResult = rtype == void.class;
4993 LambdaForm lform = result.editor().foldArgumentsForm(1 + pos, dropResult, combinerType.basicType(), argPositions);
4994 MethodType newType = targetType;
4995 if (!dropResult) {
4996 newType = newType.dropParameterTypes(pos, pos + 1);
4997 }
4998 result = result.copyWithExtendL(newType, lform, combiner);
4999 return result;
5000 }
5001
5002 private static void checkLoop0(MethodHandle[][] clauses) {
5003 if (clauses == null || clauses.length == 0) {
5004 throw newIllegalArgumentException("null or no clauses passed");
5005 }
5006 if (Stream.of(clauses).anyMatch(Objects::isNull)) {
5007 throw newIllegalArgumentException("null clauses are not allowed");
5008 }
5009 if (Stream.of(clauses).anyMatch(c -> c.length > 4)) {
5010 throw newIllegalArgumentException("All loop clauses must be represented as MethodHandle arrays with at most 4 elements.");
5011 }
5012 }
5013
5014 private static void checkLoop1a(int i, MethodHandle in, MethodHandle st) {
5015 if (in.type().returnType() != st.type().returnType()) {
5016 throw misMatchedTypes("clause " + i + ": init and step return types", in.type().returnType(),
5017 st.type().returnType());
5018 }
5019 }
5020
|