--- old/src/java.base/share/classes/java/lang/invoke/MethodHandles.java 2016-02-29 14:38:03.000000000 +0100 +++ new/src/java.base/share/classes/java/lang/invoke/MethodHandles.java 2016-02-29 14:38:03.000000000 +0100 @@ -3268,12 +3268,17 @@ *
- * Step 1B: Determine loop parameters.
* Step 1C: Determine loop return type.
- * (Implementation Note: Steps 1A, 1B, 1C, 1D are logically independent of each other, and may be performed in any - * order.) - *
* Step 2: Determine parameter lists.
{@code * // iterative implementation of the factorial function as a loop handle * static int one(int k) { return 1; } - * int inc(int i, int acc, int k) { return i + 1; } - * int mult(int i, int acc, int k) { return i * acc; } - * boolean pred(int i, int acc, int k) { return i < k; } - * int fin(int i, int acc, int k) { return acc; } + * static int inc(int i, int acc, int k) { return i + 1; } + * static int mult(int i, int acc, int k) { return i * acc; } + * static boolean pred(int i, int acc, int k) { return i < k; } + * static int fin(int i, int acc, int k) { return acc; } * // assume MH_one, MH_inc, MH_mult, MH_pred, and MH_fin are handles to the above methods * // null initializer for counter, should initialize to 0 * MethodHandle[] counterClause = new MethodHandle[]{null, MH_inc}; @@ -3436,9 +3438,7 @@ collect(Collectors.toList()); // Step 1B: determine loop parameters. - final List> empty = new ArrayList<>(); - final List > commonSuffix = init.stream().filter(Objects::nonNull).map(MethodHandle::type). - map(MethodType::parameterList).reduce((p, q) -> p.size() >= q.size() ? p : q).orElse(empty); + final List > commonSuffix = buildCommonSuffix(init, step, pred, fini, commonPrefix.size()); checkLoop1b(init, commonSuffix); // Step 1C: determine loop return type. @@ -3520,9 +3520,9 @@ * @apiNote Example: * {@code * // implement the zip function for lists as a loop handle - * ListinitZip(Iterator a, Iterator b) { return new ArrayList<>(); } - * boolean zipPred(List zip, Iterator a, Iterator b) { return a.hasNext() && b.hasNext(); } - * List zipStep(List zip, Iterator a, Iterator b) { + * static List initZip(Iterator a, Iterator b) { return new ArrayList<>(); } + * static boolean zipPred(List zip, Iterator a, Iterator b) { return a.hasNext() && b.hasNext(); } + * static List zipStep(List zip, Iterator a, Iterator b) { * zip.add(a.next()); * zip.add(b.next()); * return zip; @@ -3594,9 +3594,9 @@ * @apiNote Example: * {@code * // int i = 0; while (i < limit) { ++i; } return i; => limit - * int zero(int limit) { return 0; } - * int step(int i, int limit) { return i + 1; } - * boolean pred(int i, int limit) { return i < limit; } + * static int zero(int limit) { return 0; } + * static int step(int i, int limit) { return i + 1; } + * static boolean pred(int i, int limit) { return i < limit; } * // assume MH_zero, MH_step, and MH_pred are handles to the above methods * MethodHandle loop = MethodHandles.doWhileLoop(MH_zero, MH_step, MH_pred); * assertEquals(23, loop.invoke(23)); @@ -3664,8 +3664,8 @@ *{@code * // String s = "Lambdaman!"; for (int i = 0; i < 13; ++i) { s = "na " + s; } return s; * // => a variation on a well known theme - * String start(String arg) { return arg; } - * String step(int counter, String v, String arg) { return "na " + v; } + * static String start(String arg) { return arg; } + * static String step(int counter, String v, String arg) { return "na " + v; } * // assume MH_start and MH_step are handles to the two methods above * MethodHandle fit13 = MethodHandles.constant(int.class, 13); * MethodHandle loop = MethodHandles.countedLoop(fit13, MH_start, MH_step); @@ -3808,11 +3808,11 @@ * @apiNote Example: *{@code * // reverse a list - * ListreverseStep(String e, List r, List l) { + * static List reverseStep(String e, List r, List l) { * r.add(0, e); * return r; * } - * List newArrayList(List l) { return new ArrayList<>(); } + * static List newArrayList(List l) { return new ArrayList<>(); } * // assume MH_reverseStep, MH_newArrayList are handles to the above methods * MethodHandle loop = MethodHandles.iteratedLoop(null, MH_newArrayList, MH_reverseStep); * List list = Arrays.asList("a", "b", "c", "d", "e"); @@ -4084,6 +4084,21 @@ } } + private static List > buildCommonSuffix(List init, List step, List pred, List fini, int cpSize) { + final List > empty = List.of(); + final List nonNullInits = init.stream().filter(Objects::nonNull).collect(Collectors.toList()); + if (nonNullInits.isEmpty()) { + final List > longest = Stream.of(step, pred, fini).flatMap(List::stream).filter(Objects::nonNull). + // take only those that can contribute to a common suffix because they are longer than the prefix + map(MethodHandle::type).filter(t -> t.parameterCount() > cpSize).map(MethodType::parameterList). + reduce((p, q) -> p.size() >= q.size() ? p : q).orElse(empty); + return longest.size() == 0 ? empty : longest.subList(cpSize, longest.size()); + } else { + return nonNullInits.stream().map(MethodHandle::type).map(MethodType::parameterList). + reduce((p, q) -> p.size() >= q.size() ? p : q).get(); + } + } + private static void checkLoop1b(List init, List > commonSuffix) { if (init.stream().filter(Objects::nonNull).map(MethodHandle::type).map(MethodType::parameterList). anyMatch(pl -> !pl.equals(commonSuffix.subList(0, pl.size())))) { @@ -4109,8 +4124,10 @@ } private static void checkLoop2(List step, List pred, List fini, List > commonParameterSequence) { + final int cpSize = commonParameterSequence.size(); if (Stream.of(step, pred, fini).flatMap(List::stream).filter(Objects::nonNull).map(MethodHandle::type). - map(MethodType::parameterList).anyMatch(pl -> !pl.equals(commonParameterSequence.subList(0, pl.size())))) { + map(MethodType::parameterList). + anyMatch(pl -> pl.size() > cpSize || !pl.equals(commonParameterSequence.subList(0, pl.size())))) { throw newIllegalArgumentException("found non-effectively identical parameter type lists:\nstep: " + step + "\npred: " + pred + "\nfini: " + fini + " (common parameter sequence: " + commonParameterSequence + ")"); }