diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java index 026e3062ae8..ab9b906e7ff 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java @@ -1753,6 +1753,18 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; return counter + 1; } + /** + * This method is bound as a filter in {@linkplain MethodHandles#countedLoop(MethodHandle, MethodHandle, MethodHandle, + * MethodHandle) counting loops} to pass the correct counter value to the body. + * + * @param counter the loop counter. + * + * @return the loop counter decremented by 1. + */ + static int decrementCounter(int counter) { + return counter - 1; + } + /** * This is bound to initialize the loop-local iterator in {@linkplain MethodHandles#iteratedLoop iterating loops}. * @@ -1879,7 +1891,8 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; MH_iterateNext = 11, MH_tryFinallyExec = 12, MH_tryFinallyVoidExec = 13, - MH_LIMIT = 14; + MH_decrementCounter = 14, + MH_LIMIT = 15; static MethodHandle getConstantHandle(int idx) { MethodHandle handle = HANDLES[idx]; @@ -1949,6 +1962,9 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; case MH_tryFinallyVoidExec: return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "tryFinallyVoidExecutor", MethodType.methodType(void.class, MethodHandle.class, MethodHandle.class, Object[].class)); + case MH_decrementCounter: + return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "decrementCounter", + MethodType.methodType(int.class, int.class)); } } catch (ReflectiveOperationException ex) { throw newInternalError(ex); diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index 76e29209fed..488decd542a 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -4322,11 +4322,13 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); *
@@ -4351,7 +4353,9 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); 0, int.class, int.class); MethodHandle[] indexVar = {start, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopStep)}; MethodHandle[] loopLimit = {end, null, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopPred), returnVar}; - MethodHandle[] bodyClause = {init, dropArguments(body, 1, int.class)}; + MethodHandle[] bodyClause = {init, + filterArgument(dropArguments(body, 1, int.class), 0, + MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_decrementCounter))}; return loop(indexVar, loopLimit, bodyClause); } diff --git a/jdk/test/java/lang/invoke/LoopCombinatorTest.java b/jdk/test/java/lang/invoke/LoopCombinatorTest.java index 2bae77e6a2e..71e4b0e89d8 100644 --- a/jdk/test/java/lang/invoke/LoopCombinatorTest.java +++ b/jdk/test/java/lang/invoke/LoopCombinatorTest.java @@ -26,6 +26,8 @@ /* @test * @bug 8139885 * @bug 8150635 + * @bug 8150957 + * @bug 8153637 * @run testng/othervm -ea -esa test.java.lang.invoke.LoopCombinatorTest */ @@ -301,6 +303,18 @@ public class LoopCombinatorTest { assertEquals("na na na na na na na na na na na na na Lambdaman!", loop.invoke("Lambdaman!")); } + @Test + public static void testCountedLoopCounterInit() throws Throwable { + // int x = 0; for (int i = 0; i < 5; ++i) { x += i; } return x; => 10 + // (only if counter's first value in body is 0) + MethodHandle iter = MethodHandles.constant(int.class, 5); + MethodHandle init = MethodHandles.constant(int.class, 0); + MethodHandle body = Counted.MH_addCounter; + MethodHandle loop = MethodHandles.countedLoop(iter, init, body); + assertEquals(Counted.MT_counterInit, loop.type()); + assertEquals(10, loop.invoke()); + } + @Test public static void testIterateSum() throws Throwable { // Integer[] a = new Integer[]{1,2,3,4,5,6}; int sum = 0; for (int e : a) { sum += e; } return sum; => 21 @@ -667,12 +681,17 @@ public class LoopCombinatorTest { System.out.print("hello"); } + static int addCounter(int counter, int x) { + return x + counter; + } + static final Class{@code * MethodHandle countedLoop(MethodHandle start, MethodHandle end, MethodHandle init, MethodHandle body) { * MethodHandle returnVar = dropArguments(identity(init.type().returnType()), 0, int.class, int.class); - * // assume MH_increment and MH_lessThan are handles to x+1 and x