convert FunctionRef/Def usage to methodhandles.

This commit is contained in:
Robert Muir 2016-06-07 10:23:49 -04:00
parent 3108c399f0
commit 32965f043a
3 changed files with 30 additions and 24 deletions

View File

@ -246,28 +246,24 @@ public final class Def {
int separator = signature.indexOf('.');
FunctionRef ref = new FunctionRef(clazz, signature.substring(0, separator), signature.substring(separator+1));
final CallSite callSite;
// XXX: clean all this up to use handles in FunctionRef, deal with ASM in EFunctionRef differently
MethodType invokedType = MethodType.fromMethodDescriptorString(ref.invokedType.getDescriptor(), Def.class.getClassLoader());
MethodType samMethodType = MethodType.fromMethodDescriptorString(ref.samMethodType.getDescriptor(), Def.class.getClassLoader());
MethodType interfaceType = MethodType.fromMethodDescriptorString(ref.interfaceType.getDescriptor(), Def.class.getClassLoader());
if (ref.interfaceType.equals(ref.samMethodType)) {
if (ref.interfaceType.equals(ref.samType)) {
callSite = LambdaMetafactory.altMetafactory(lookup,
ref.invokedName,
invokedType,
samMethodType,
ref.invokedMethodType,
ref.samMethodType,
ref.implMethodHandle,
samMethodType,
ref.samMethodType,
0);
} else {
callSite = LambdaMetafactory.altMetafactory(lookup,
ref.invokedName,
invokedType,
samMethodType,
ref.invokedMethodType,
ref.samMethodType,
ref.implMethodHandle,
samMethodType,
ref.samMethodType,
LambdaMetafactory.FLAG_BRIDGES,
1,
interfaceType);
ref.interfaceMethodType);
}
// we could actually invoke and cache here (in non-capturing cases), but this is not a speedup.
MethodHandle factory = callSite.dynamicInvoker().asType(MethodType.methodType(clazz.clazz));

View File

@ -25,6 +25,7 @@ import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
import java.lang.reflect.Modifier;
/**
@ -32,16 +33,20 @@ import java.lang.reflect.Modifier;
* and reference class + method name
*/
public class FunctionRef {
// XXX: this is a mess, because of ASM versus MethodHandle types
// clean all this up, move reflection out of here into definition, etc etc
public final String invokedName;
public final Type invokedType;
public final Handle implMethod;
public final Type samMethodType;
public final Type interfaceType;
public final Type invokedType;
public final MethodType invokedMethodType;
public final Handle implMethod;
public final MethodHandle implMethodHandle;
public final Type samType;
public final MethodType samMethodType;
public final Type interfaceType;
public final MethodType interfaceMethodType;
public FunctionRef(Definition.Type expected, String type, String call) {
boolean isCtorReference = "new".equals(call);
// check its really a functional interface
@ -55,8 +60,10 @@ public class FunctionRef {
invokedName = method.name;
// e.g. (Object)Comparator
invokedType = Type.getMethodType(expected.type);
invokedMethodType = MethodType.methodType(expected.clazz);
// e.g. (Object,Object)int
interfaceType = Type.getMethodType(method.method.getDescriptor());
interfaceMethodType = method.handle.type().dropParameterTypes(0, 1);
// lookup requested method
Definition.Struct struct = Definition.getType(type).struct;
final Definition.Method impl;
@ -89,15 +96,18 @@ public class FunctionRef {
implMethod = new Handle(tag, struct.type.getInternalName(), impl.name, impl.method.getDescriptor());
implMethodHandle = impl.handle;
if (isCtorReference) {
samMethodType = Type.getMethodType(interfaceType.getReturnType(), impl.method.getArgumentTypes());
samType = Type.getMethodType(interfaceType.getReturnType(), impl.method.getArgumentTypes());
samMethodType = MethodType.methodType(interfaceMethodType.returnType(), impl.handle.type().parameterArray());
} else if (Modifier.isStatic(impl.modifiers)) {
samMethodType = Type.getMethodType(impl.method.getReturnType(), impl.method.getArgumentTypes());
samType = Type.getMethodType(impl.method.getReturnType(), impl.method.getArgumentTypes());
samMethodType = impl.handle.type();
} else {
Type[] argTypes = impl.method.getArgumentTypes();
Type[] params = new Type[argTypes.length + 1];
System.arraycopy(argTypes, 0, params, 1, argTypes.length);
params[0] = struct.type;
samMethodType = Type.getMethodType(impl.method.getReturnType(), params);
samType = Type.getMethodType(impl.method.getReturnType(), params);
samMethodType = impl.handle.type();
}
}
}

View File

@ -68,12 +68,12 @@ public class EFunctionRef extends AExpression {
writer.writeDebugInfo(location);
// currently if the interface differs, we ask for a bridge, but maybe we should do smarter checking?
// either way, stuff will fail if its wrong :)
if (ref.interfaceType.equals(ref.samMethodType)) {
if (ref.interfaceType.equals(ref.samType)) {
writer.invokeDynamic(ref.invokedName, ref.invokedType.getDescriptor(), LAMBDA_BOOTSTRAP_HANDLE,
ref.samMethodType, ref.implMethod, ref.samMethodType, 0);
ref.samType, ref.implMethod, ref.samType, 0);
} else {
writer.invokeDynamic(ref.invokedName, ref.invokedType.getDescriptor(), LAMBDA_BOOTSTRAP_HANDLE,
ref.samMethodType, ref.implMethod, ref.samMethodType,
ref.samType, ref.implMethod, ref.samType,
LambdaMetafactory.FLAG_BRIDGES, 1, ref.interfaceType);
}
}