< prev index next >

src/java.base/share/classes/java/lang/invoke/MethodHandles.java

Print this page
rev 14211 : 8154751: MethodHandles.countedLoop does not accept empty bodies


4459      *     return loop(indexVar, loopLimit, bodyClause);
4460      * }
4461      * }</pre></blockquote>
4462      *
4463      * @param start a handle to return the start value of the loop counter.
4464      *              If it is {@code null}, a constant zero is assumed.
4465      * @param end a non-{@code null} handle to return the end value of the loop counter (the loop will run to {@code end-1}).
4466      * @param init initializer for additional loop state. This determines the loop's result type.
4467      *             Passing {@code null} or a {@code void} init function will make the loop's result type
4468      *             {@code void}.
4469      * @param body the body of the loop, which must not be {@code null}.
4470      *             It must accept an initial {@code int} parameter (for the counter), and then any
4471      *             additional loop-local variable plus loop parameters.
4472      *
4473      * @return a method handle representing the loop.
4474      * @throws IllegalArgumentException if any argument has a type inconsistent with the loop structure
4475      *
4476      * @since 9
4477      */
4478     public static MethodHandle countedLoop(MethodHandle start, MethodHandle end, MethodHandle init, MethodHandle body) {
4479         MethodHandle returnVar = dropArguments(init == null || init.type().returnType() == void.class ?
4480                 zero(void.class) : identity(init.type().returnType()), 0, int.class, int.class);




4481         MethodHandle[] indexVar = {start, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopStep)};
4482         MethodHandle[] loopLimit = {end, null, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopPred), returnVar};
4483         MethodHandle[] bodyClause = {init,
4484                 filterArgument(dropArguments(body, 1, int.class), 0,
4485                         MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_decrementCounter))};
4486         return loop(indexVar, loopLimit, bodyClause);
4487     }
4488 
4489     /**
4490      * Constructs a loop that ranges over the elements produced by an {@code Iterator<T>}.
4491      * The iterator will be produced by the evaluation of the {@code iterator} handle.
4492      * This handle must have {@link java.util.Iterator} as its return type.
4493      * If this handle is passed as {@code null} the method {@link Iterable#iterator} will be used instead,
4494      * and will be applied to a leading argument of the loop handle.
4495      * Each value produced by the iterator is passed to the {@code body}, which must accept an initial {@code T} parameter.
4496      * The result of the loop execution is the final value of the additional local state
4497      * obtained by running {@code init}.
4498      * <p>
4499      * This is a convenience wrapper for the
4500      * {@linkplain MethodHandles#loop(MethodHandle[][]) generic loop combinator}, and the constraints imposed on the {@code body}
4501      * handle follow directly from those described for the latter.
4502      * <p>
4503      * Here is pseudocode for the resulting loop handle. In the code, {@code V}/{@code v} represent the type / value of
4504      * the loop variable as well as the result type of the loop; {@code T}/{@code t}, that of the elements of the




4459      *     return loop(indexVar, loopLimit, bodyClause);
4460      * }
4461      * }</pre></blockquote>
4462      *
4463      * @param start a handle to return the start value of the loop counter.
4464      *              If it is {@code null}, a constant zero is assumed.
4465      * @param end a non-{@code null} handle to return the end value of the loop counter (the loop will run to {@code end-1}).
4466      * @param init initializer for additional loop state. This determines the loop's result type.
4467      *             Passing {@code null} or a {@code void} init function will make the loop's result type
4468      *             {@code void}.
4469      * @param body the body of the loop, which must not be {@code null}.
4470      *             It must accept an initial {@code int} parameter (for the counter), and then any
4471      *             additional loop-local variable plus loop parameters.
4472      *
4473      * @return a method handle representing the loop.
4474      * @throws IllegalArgumentException if any argument has a type inconsistent with the loop structure
4475      *
4476      * @since 9
4477      */
4478     public static MethodHandle countedLoop(MethodHandle start, MethodHandle end, MethodHandle init, MethodHandle body) {
4479         boolean voidReturn = init == null || init.type().returnType() == void.class;
4480         MethodHandle adaptedBody = body == null ?
4481                 dropArguments(voidReturn ? zero(void.class) : identity(init.type().returnType()), 0, int.class) :
4482                 body;
4483         MethodHandle returnVar = dropArguments(voidReturn ? zero(void.class) : identity(init.type().returnType()),
4484                 0, int.class, int.class);
4485         MethodHandle[] indexVar = {start, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopStep)};
4486         MethodHandle[] loopLimit = {end, null, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopPred), returnVar};
4487         MethodHandle[] bodyClause = {init,
4488                 filterArgument(dropArguments(adaptedBody, 1, int.class), 0,
4489                         MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_decrementCounter))};
4490         return loop(indexVar, loopLimit, bodyClause);
4491     }
4492 
4493     /**
4494      * Constructs a loop that ranges over the elements produced by an {@code Iterator<T>}.
4495      * The iterator will be produced by the evaluation of the {@code iterator} handle.
4496      * This handle must have {@link java.util.Iterator} as its return type.
4497      * If this handle is passed as {@code null} the method {@link Iterable#iterator} will be used instead,
4498      * and will be applied to a leading argument of the loop handle.
4499      * Each value produced by the iterator is passed to the {@code body}, which must accept an initial {@code T} parameter.
4500      * The result of the loop execution is the final value of the additional local state
4501      * obtained by running {@code init}.
4502      * <p>
4503      * This is a convenience wrapper for the
4504      * {@linkplain MethodHandles#loop(MethodHandle[][]) generic loop combinator}, and the constraints imposed on the {@code body}
4505      * handle follow directly from those described for the latter.
4506      * <p>
4507      * Here is pseudocode for the resulting loop handle. In the code, {@code V}/{@code v} represent the type / value of
4508      * the loop variable as well as the result type of the loop; {@code T}/{@code t}, that of the elements of the


< prev index next >