Skip to content

Commit

Permalink
Switching to Carriers.boxedComponentValueArray (#8)
Browse files Browse the repository at this point in the history
* Switching to Carriers.boxedComponentValueArray

* Fixing UnreflectPattern
  • Loading branch information
viktorklang-ora authored Sep 9, 2024
1 parent 09128ed commit 512193a
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 64 deletions.
56 changes: 5 additions & 51 deletions src/java.base/share/classes/java/lang/invoke/MethodHandles.java
Original file line number Diff line number Diff line change
Expand Up @@ -3521,62 +3521,16 @@ public MethodHandle unreflectConstructor(Constructor<?> c) throws IllegalAccessE
*/
public MethodHandle unreflectDeconstructor(Deconstructor<?> d) throws IllegalAccessException {
Class<?> ownerType = d.getDeclaringClass(); // Implicit null-check of d
final MethodHandle deconstructorPhysicalHandle;
try {
deconstructorPhysicalHandle = unreflect(
ownerType.getDeclaredMethod(
SharedSecrets.getJavaLangReflectAccess().getMangledName(d),
ownerType
)
return unreflect(
ownerType.getDeclaredMethod(
SharedSecrets.getJavaLangReflectAccess().getMangledName(d),
ownerType
)
);
} catch (NoSuchMethodException | SecurityException ex) {
throw new InternalError(ex);
}

MethodType bindingType = MethodType.methodType(Object.class,
Arrays.stream(d.getPatternBindings()).map(PatternBinding::getType).toArray(Class<?>[]::new)
);

MethodType boxingType = MethodType.methodType(Object.class, Object.class);

return filterReturnValue(
deconstructorPhysicalHandle,
permuteArguments(
filterArguments(
identity(Object.class).asCollector(Object[].class, bindingType.parameterCount()),
0,
Carriers.components(bindingType)
.stream()
.map(c -> c.asType(boxingType))
.toArray(MethodHandle[]::new)
),
boxingType,
new int[bindingType.parameterCount()]
)
).asType(MethodType.methodType(Object[].class, ownerType)); // required for invokeExact
}

private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
private static MethodHandle CARRIER_TO_ARRAY;

static {
try {
CARRIER_TO_ARRAY = LOOKUP.findStatic(Lookup.class, "carrier2Array",
MethodType.methodType(Object[].class, Object.class, List.class));
} catch (ReflectiveOperationException e) {
throw new ExceptionInInitializerError(e);
}
}

private static Object[] carrier2Array(Object carrier, List<MethodHandle> componentHandles) throws Throwable {
Object[] result = new Object[componentHandles.size()];
int i = 0;

for (MethodHandle componentAccessor : componentHandles) {
result[i++] = componentAccessor.invoke(carrier);
}

return result;
}

/*
Expand Down
23 changes: 11 additions & 12 deletions src/java.base/share/classes/java/lang/reflect/Deconstructor.java
Original file line number Diff line number Diff line change
Expand Up @@ -426,19 +426,18 @@ public Object[] invoke(Object matchCandidate)
String underlyingName = getMangledName();

try {
Method method = this.getDeclaringClass().getDeclaredMethod(underlyingName, matchCandidate.getClass());
Method method = getDeclaringClass().getDeclaredMethod(underlyingName, matchCandidate.getClass());
method.setAccessible(override);
Object carrier = method.invoke(matchCandidate, matchCandidate);

Class<?>[] bindingClasses = Arrays.stream(this.getPatternBindings()).map(d -> d.getType()).toArray(Class[]::new);
MethodType methodType = MethodType.methodType(Object.class, bindingClasses);

ArrayList<Object> ret = new ArrayList<>();
for (int i = 0; i < bindingClasses.length; i++) {
ret.add(Carriers.component(methodType, i).invoke(carrier));
}

return ret.stream().toArray();
return (Object[])Carriers.boxedComponentValueArray(
MethodType.methodType(
Object.class,
Arrays.stream(this.getPatternBindings())
.map(PatternBinding::getType)
.toArray(Class[]::new)
)
).invoke(
method.invoke(matchCandidate, matchCandidate)
);
} catch (Throwable e) {
throw new MatchException(e.getMessage(), e);
}
Expand Down
20 changes: 20 additions & 0 deletions src/java.base/share/classes/java/lang/runtime/Carriers.java
Original file line number Diff line number Diff line change
Expand Up @@ -962,4 +962,24 @@ public static MethodHandle component(MethodType methodType, int i) {
return component;
}

/**
* {@return a {@link MethodHandle MethodHandle} which accepts a carrier object
* matching the given {@code methodType} which when invoked will return a newly
* created object array containing the boxed component values of the carrier object.}
*
* @param methodType {@link MethodType} whose parameter types supply the shape of the
* carrier's components
*/
public static MethodHandle boxedComponentValueArray(MethodType methodType) {
var boxingType = MethodType.methodType(Object.class, Object.class);
return MethodHandles.permuteArguments(
MethodHandles.filterArguments(
MethodHandles.identity(Object.class).asCollector(Object[].class, methodType.parameterCount()),
0,
CarrierFactory.of(methodType).components.stream().map(c -> c.asType(boxingType)).toArray(MethodHandle[]::new)
),
boxingType,
new int[methodType.parameterCount()]
).asType(boxingType.changeReturnType(Object[].class));
}
}
12 changes: 11 additions & 1 deletion test/jdk/java/lang/invoke/lookup/UnreflectPattern.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Deconstructor;
import java.lang.runtime.Carriers;
import java.util.Arrays;

public class UnreflectPattern {
Expand All @@ -43,7 +45,15 @@ public static void main(String... args) throws Throwable {
if (!Arrays.equals(expected, result1)) {
throw new AssertionError("Unexpected result: " + Arrays.toString(result1));
}
MethodHandle deconstructorHandle = MethodHandles.lookup().unreflectDeconstructor(deconstructor);
MethodHandle unreflected =
MethodHandles.lookup().unreflectDeconstructor(deconstructor);
if (!MethodType.methodType(Object.class, UnreflectPattern.class).equals(unreflected.type()))
throw new AssertionError("Unexpected type: " + unreflected.type());
MethodHandle deconstructorHandle =
MethodHandles.filterReturnValue(
unreflected,
Carriers.boxedComponentValueArray(MethodType.methodType(Object.class, String.class, Integer.TYPE))
);
Object[] result2 = (Object[]) deconstructorHandle.invokeExact(instance);
if (!Arrays.equals(expected, result2)) {
throw new AssertionError("Unexpected result: " + Arrays.toString(result2));
Expand Down

0 comments on commit 512193a

Please sign in to comment.