convert FunctionRef/Def usage to methodhandles.
This commit is contained in:
parent
3108c399f0
commit
32965f043a
|
@ -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));
|
||||
|
|
|
@ -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,15 +33,19 @@ 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);
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue