< prev index next >

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

Print this page
rev 14276 : 8154754: MethodHandles.countedLoop errors in deriving loop arguments, result type, and local state


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 defaultResultHandle = init == null || init.type().returnType() == void.class ?
4480                 zero(void.class) :
4481                 identity(init.type().returnType());
4482         MethodHandle adaptedBody = body == null ? dropArguments(defaultResultHandle, 0, int.class) : body;







4483         MethodHandle returnVar = dropArguments(defaultResultHandle, 0, int.class, int.class);

4484         MethodHandle[] indexVar = {start, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopStep)};
4485         MethodHandle[] loopLimit = {end, null, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopPred),
4486                 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




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         Class<?> resultType;
4480         MethodHandle actualInit;
4481         if (init == null) {
4482             resultType = body == null ? void.class : body.type().returnType();
4483             actualInit = empty(methodType(resultType));
4484         } else {
4485             resultType = init.type().returnType();
4486             actualInit = init;
4487         }
4488         MethodHandle defaultResultHandle = resultType == void.class ? zero(void.class) : identity(resultType);
4489         MethodHandle actualBody = body == null ? dropArguments(defaultResultHandle, 0, int.class) : body;
4490         MethodHandle returnVar = dropArguments(defaultResultHandle, 0, int.class, int.class);
4491         MethodHandle actualEnd = end == null ? constant(int.class, 0) : end;
4492         MethodHandle[] indexVar = {start, MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopStep)};
4493         MethodHandle[] loopLimit = {actualEnd, null,
4494                 MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_countedLoopPred), returnVar};
4495         MethodHandle[] bodyClause = {actualInit,
4496                 filterArgument(dropArguments(actualBody, 1, int.class), 0,
4497                         MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_decrementCounter))};
4498         return loop(indexVar, loopLimit, bodyClause);
4499     }
4500 
4501     /**
4502      * Constructs a loop that ranges over the elements produced by an {@code Iterator<T>}.
4503      * The iterator will be produced by the evaluation of the {@code iterator} handle.
4504      * This handle must have {@link java.util.Iterator} as its return type.
4505      * If this handle is passed as {@code null} the method {@link Iterable#iterator} will be used instead,
4506      * and will be applied to a leading argument of the loop handle.
4507      * Each value produced by the iterator is passed to the {@code body}, which must accept an initial {@code T} parameter.
4508      * The result of the loop execution is the final value of the additional local state
4509      * obtained by running {@code init}.
4510      * <p>
4511      * This is a convenience wrapper for the
4512      * {@linkplain MethodHandles#loop(MethodHandle[][]) generic loop combinator}, and the constraints imposed on the {@code body}
4513      * handle follow directly from those described for the latter.
4514      * <p>
4515      * Here is pseudocode for the resulting loop handle. In the code, {@code V}/{@code v} represent the type / value of
4516      * 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 >