8310157: Allow void-returning filters for MethodHandles::collectCoordinates
Reviewed-by: mcimadamore
This commit is contained in:
parent
3fb9d117e3
commit
69a46c25cc
@ -8188,19 +8188,18 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
|
|||||||
* filter function and the target var handle is then called on the modified (usually shortened)
|
* filter function and the target var handle is then called on the modified (usually shortened)
|
||||||
* coordinate list.
|
* coordinate list.
|
||||||
* <p>
|
* <p>
|
||||||
* If {@code R} is the return type of the filter (which cannot be void), the target var handle must accept a value of
|
* If {@code R} is the return type of the filter, then:
|
||||||
* type {@code R} as its coordinate in position {@code pos}, preceded and/or followed by
|
* <ul>
|
||||||
* any coordinate not passed to the filter.
|
* <li>if {@code R} <em>is not</em> {@code void}, the target var handle must have a coordinate of type {@code R} in
|
||||||
* No coordinates are reordered, and the result returned from the filter
|
* position {@code pos}. The parameter types of the filter will replace the coordinate type at position {@code pos}
|
||||||
* replaces (in order) the whole subsequence of coordinates originally
|
* of the target var handle. When the returned var handle is invoked, it will be as if the filter is invoked first,
|
||||||
* passed to the adapter.
|
* and its result is passed in place of the coordinate at position {@code pos} in a downstream invocation of the
|
||||||
* <p>
|
* target var handle.</li>
|
||||||
* The argument types (if any) of the filter
|
* <li> if {@code R} <em>is</em> {@code void}, the parameter types (if any) of the filter will be inserted in the
|
||||||
* replace zero or one coordinate types of the target var handle, at position {@code pos},
|
* coordinate type list of the target var handle at position {@code pos}. In this case, when the returned var handle
|
||||||
* in the resulting adapted var handle.
|
* is invoked, the filter essentially acts as a side effect, consuming some of the coordinate values, before a
|
||||||
* The return type of the filter must be identical to the
|
* downstream invocation of the target var handle.</li>
|
||||||
* coordinate type of the target var handle at position {@code pos}, and that target var handle
|
* </ul>
|
||||||
* coordinate is supplied by the return value of the filter.
|
|
||||||
* <p>
|
* <p>
|
||||||
* If any of the filters throws a checked exception when invoked, the resulting var handle will
|
* If any of the filters throws a checked exception when invoked, the resulting var handle will
|
||||||
* throw an {@link IllegalStateException}.
|
* throw an {@link IllegalStateException}.
|
||||||
@ -8209,12 +8208,12 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
|
|||||||
* atomic access guarantees as those featured by the target var handle.
|
* atomic access guarantees as those featured by the target var handle.
|
||||||
*
|
*
|
||||||
* @param target the var handle to invoke after the coordinates have been filtered
|
* @param target the var handle to invoke after the coordinates have been filtered
|
||||||
* @param pos the position of the coordinate to be filtered
|
* @param pos the position in the coordinate list of the target var handle where the filter is to be inserted
|
||||||
* @param filter the filter method handle
|
* @param filter the filter method handle
|
||||||
* @return an adapter var handle which filters the incoming coordinate values,
|
* @return an adapter var handle which filters the incoming coordinate values,
|
||||||
* before calling the target var handle
|
* before calling the target var handle
|
||||||
* @throws IllegalArgumentException if the return type of {@code filter}
|
* @throws IllegalArgumentException if the return type of {@code filter}
|
||||||
* is void, or it is not the same as the {@code pos} coordinate of the target var handle,
|
* is not void, and it is not the same as the {@code pos} coordinate of the target var handle,
|
||||||
* if {@code pos} is not between 0 and the target var handle coordinate arity, inclusive,
|
* if {@code pos} is not between 0 and the target var handle coordinate arity, inclusive,
|
||||||
* if the resulting var handle's type would have <a href="MethodHandle.html#maxarity">too many coordinates</a>,
|
* if the resulting var handle's type would have <a href="MethodHandle.html#maxarity">too many coordinates</a>,
|
||||||
* or if it's determined that {@code filter} throws any checked exceptions.
|
* or if it's determined that {@code filter} throws any checked exceptions.
|
||||||
|
@ -563,14 +563,14 @@ final class VarHandles {
|
|||||||
List<Class<?>> targetCoordinates = target.coordinateTypes();
|
List<Class<?>> targetCoordinates = target.coordinateTypes();
|
||||||
if (pos < 0 || pos >= targetCoordinates.size()) {
|
if (pos < 0 || pos >= targetCoordinates.size()) {
|
||||||
throw newIllegalArgumentException("Invalid position " + pos + " for coordinate types", targetCoordinates);
|
throw newIllegalArgumentException("Invalid position " + pos + " for coordinate types", targetCoordinates);
|
||||||
} else if (filter.type().returnType() == void.class) {
|
} else if (filter.type().returnType() != void.class && filter.type().returnType() != targetCoordinates.get(pos)) {
|
||||||
throw newIllegalArgumentException("Invalid filter type " + filter.type() + " ; filter cannot be void");
|
|
||||||
} else if (filter.type().returnType() != targetCoordinates.get(pos)) {
|
|
||||||
throw newIllegalArgumentException("Invalid filter type " + filter.type() + " for coordinate type " + targetCoordinates.get(pos));
|
throw newIllegalArgumentException("Invalid filter type " + filter.type() + " for coordinate type " + targetCoordinates.get(pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Class<?>> newCoordinates = new ArrayList<>(targetCoordinates);
|
List<Class<?>> newCoordinates = new ArrayList<>(targetCoordinates);
|
||||||
newCoordinates.remove(pos);
|
if (filter.type().returnType() != void.class) {
|
||||||
|
newCoordinates.remove(pos);
|
||||||
|
}
|
||||||
newCoordinates.addAll(pos, filter.type().parameterList());
|
newCoordinates.addAll(pos, filter.type().parameterList());
|
||||||
|
|
||||||
return new IndirectVarHandle(target, target.varType(), newCoordinates.toArray(new Class<?>[0]),
|
return new IndirectVarHandle(target, target.varType(), newCoordinates.toArray(new Class<?>[0]),
|
||||||
|
@ -351,6 +351,12 @@ public class TestAdaptVarHandles {
|
|||||||
assertEquals(value, 42);
|
assertEquals(value, 42);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCollectCoordinatesVoidFilterType() {
|
||||||
|
VarHandle handle = MethodHandles.collectCoordinates(intHandle, 0, VOID_FILTER);
|
||||||
|
assertEquals(handle.coordinateTypes(), List.of(String.class, MemorySegment.class));
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||||
public void testBadCollectCoordinatesNegativePos() {
|
public void testBadCollectCoordinatesNegativePos() {
|
||||||
MethodHandles.collectCoordinates(intHandle, -1, SUM_OFFSETS);
|
MethodHandles.collectCoordinates(intHandle, -1, SUM_OFFSETS);
|
||||||
@ -366,11 +372,6 @@ public class TestAdaptVarHandles {
|
|||||||
MethodHandles.collectCoordinates(intHandle, 0, SUM_OFFSETS);
|
MethodHandles.collectCoordinates(intHandle, 0, SUM_OFFSETS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
|
||||||
public void testBadCollectCoordinatesWrongVoidFilterType() {
|
|
||||||
MethodHandles.collectCoordinates(intHandle, 0, VOID_FILTER);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||||
public void testBadCollectCoordinatesWrongFilterException() {
|
public void testBadCollectCoordinatesWrongFilterException() {
|
||||||
MethodHandles.collectCoordinates(intHandle, 0, S2L_EX);
|
MethodHandles.collectCoordinates(intHandle, 0, S2L_EX);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user