changeset 14275:14065c26ea1a

8154751: MethodHandles.countedLoop does not accept empty bodies Reviewed-by: redestad
author mhaupt
date Fri, 22 Apr 2016 15:05:26 +0200
parents beac9a439d0f
children e8217d94b72e
files src/java.base/share/classes/java/lang/invoke/MethodHandles.java test/java/lang/invoke/LoopCombinatorTest.java
diffstat 2 files changed, 26 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Fri Apr 22 13:36:22 2016 +0200
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Fri Apr 22 15:05:26 2016 +0200
@@ -4476,12 +4476,16 @@
      * @since 9
      */
     public static MethodHandle countedLoop(MethodHandle start, MethodHandle end, MethodHandle init, MethodHandle body) {
-        MethodHandle returnVar = dropArguments(init == null || init.type().returnType() == void.class ?
-                zero(void.class) : identity(init.type().returnType()), 0, int.class, int.class);
+        MethodHandle defaultResultHandle = init == null || init.type().returnType() == void.class ?
+                zero(void.class) :
+                identity(init.type().returnType());
+        MethodHandle adaptedBody = body == null ? dropArguments(defaultResultHandle, 0, int.class) : body;
+        MethodHandle returnVar = dropArguments(defaultResultHandle, 0, int.class, int.class);
         MethodHandle[] indexVar = {start, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopStep)};
-        MethodHandle[] loopLimit = {end, null, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopPred), returnVar};
+        MethodHandle[] loopLimit = {end, null, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopPred),
+                returnVar};
         MethodHandle[] bodyClause = {init,
-                filterArgument(dropArguments(body, 1, int.class), 0,
+                filterArgument(dropArguments(adaptedBody, 1, int.class), 0,
                         MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_decrementCounter))};
         return loop(indexVar, loopLimit, bodyClause);
     }
--- a/test/java/lang/invoke/LoopCombinatorTest.java	Fri Apr 22 13:36:22 2016 +0200
+++ b/test/java/lang/invoke/LoopCombinatorTest.java	Fri Apr 22 15:05:26 2016 +0200
@@ -30,6 +30,7 @@
  * @bug 8150957
  * @bug 8152667
  * @bug 8153637
+ * @bug 8154751
  * @run testng/othervm -ea -esa test.java.lang.invoke.LoopCombinatorTest
  */
 
@@ -348,6 +349,23 @@
     }
 
     @Test
+    public static void testCountedLoopEmpty() throws Throwable {
+        // for (int i = 0; i < 5; ++i) { /* empty */ }
+        MethodHandle loop = MethodHandles.countedLoop(MethodHandles.constant(int.class, 5), null, null);
+        assertEquals(methodType(void.class), loop.type());
+        loop.invoke();
+    }
+
+    @Test
+    public static void testCountedRangeLoopEmpty() throws Throwable {
+        // for (int i = -5; i < 5; ++i) { /* empty */ }
+        MethodHandle loop = MethodHandles.countedLoop(MethodHandles.constant(int.class, -5),
+                MethodHandles.constant(int.class, 5), null, null);
+        assertEquals(methodType(void.class), loop.type());
+        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
         MethodHandle loop = MethodHandles.iteratedLoop(Iterate.MH_sumIterator, Iterate.MH_sumInit, Iterate.MH_sumStep);