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('.');
|
int separator = signature.indexOf('.');
|
||||||
FunctionRef ref = new FunctionRef(clazz, signature.substring(0, separator), signature.substring(separator+1));
|
FunctionRef ref = new FunctionRef(clazz, signature.substring(0, separator), signature.substring(separator+1));
|
||||||
final CallSite callSite;
|
final CallSite callSite;
|
||||||
// XXX: clean all this up to use handles in FunctionRef, deal with ASM in EFunctionRef differently
|
if (ref.interfaceType.equals(ref.samType)) {
|
||||||
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)) {
|
|
||||||
callSite = LambdaMetafactory.altMetafactory(lookup,
|
callSite = LambdaMetafactory.altMetafactory(lookup,
|
||||||
ref.invokedName,
|
ref.invokedName,
|
||||||
invokedType,
|
ref.invokedMethodType,
|
||||||
samMethodType,
|
ref.samMethodType,
|
||||||
ref.implMethodHandle,
|
ref.implMethodHandle,
|
||||||
samMethodType,
|
ref.samMethodType,
|
||||||
0);
|
0);
|
||||||
} else {
|
} else {
|
||||||
callSite = LambdaMetafactory.altMetafactory(lookup,
|
callSite = LambdaMetafactory.altMetafactory(lookup,
|
||||||
ref.invokedName,
|
ref.invokedName,
|
||||||
invokedType,
|
ref.invokedMethodType,
|
||||||
samMethodType,
|
ref.samMethodType,
|
||||||
ref.implMethodHandle,
|
ref.implMethodHandle,
|
||||||
samMethodType,
|
ref.samMethodType,
|
||||||
LambdaMetafactory.FLAG_BRIDGES,
|
LambdaMetafactory.FLAG_BRIDGES,
|
||||||
1,
|
1,
|
||||||
interfaceType);
|
ref.interfaceMethodType);
|
||||||
}
|
}
|
||||||
// we could actually invoke and cache here (in non-capturing cases), but this is not a speedup.
|
// 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));
|
MethodHandle factory = callSite.dynamicInvoker().asType(MethodType.methodType(clazz.clazz));
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.objectweb.asm.Opcodes;
|
||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
|
import java.lang.invoke.MethodType;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,15 +33,19 @@ import java.lang.reflect.Modifier;
|
||||||
* and reference class + method name
|
* and reference class + method name
|
||||||
*/
|
*/
|
||||||
public class FunctionRef {
|
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 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 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) {
|
public FunctionRef(Definition.Type expected, String type, String call) {
|
||||||
boolean isCtorReference = "new".equals(call);
|
boolean isCtorReference = "new".equals(call);
|
||||||
|
@ -55,8 +60,10 @@ public class FunctionRef {
|
||||||
invokedName = method.name;
|
invokedName = method.name;
|
||||||
// e.g. (Object)Comparator
|
// e.g. (Object)Comparator
|
||||||
invokedType = Type.getMethodType(expected.type);
|
invokedType = Type.getMethodType(expected.type);
|
||||||
|
invokedMethodType = MethodType.methodType(expected.clazz);
|
||||||
// e.g. (Object,Object)int
|
// e.g. (Object,Object)int
|
||||||
interfaceType = Type.getMethodType(method.method.getDescriptor());
|
interfaceType = Type.getMethodType(method.method.getDescriptor());
|
||||||
|
interfaceMethodType = method.handle.type().dropParameterTypes(0, 1);
|
||||||
// lookup requested method
|
// lookup requested method
|
||||||
Definition.Struct struct = Definition.getType(type).struct;
|
Definition.Struct struct = Definition.getType(type).struct;
|
||||||
final Definition.Method impl;
|
final Definition.Method impl;
|
||||||
|
@ -89,15 +96,18 @@ public class FunctionRef {
|
||||||
implMethod = new Handle(tag, struct.type.getInternalName(), impl.name, impl.method.getDescriptor());
|
implMethod = new Handle(tag, struct.type.getInternalName(), impl.name, impl.method.getDescriptor());
|
||||||
implMethodHandle = impl.handle;
|
implMethodHandle = impl.handle;
|
||||||
if (isCtorReference) {
|
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)) {
|
} 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 {
|
} else {
|
||||||
Type[] argTypes = impl.method.getArgumentTypes();
|
Type[] argTypes = impl.method.getArgumentTypes();
|
||||||
Type[] params = new Type[argTypes.length + 1];
|
Type[] params = new Type[argTypes.length + 1];
|
||||||
System.arraycopy(argTypes, 0, params, 1, argTypes.length);
|
System.arraycopy(argTypes, 0, params, 1, argTypes.length);
|
||||||
params[0] = struct.type;
|
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);
|
writer.writeDebugInfo(location);
|
||||||
// currently if the interface differs, we ask for a bridge, but maybe we should do smarter checking?
|
// 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 :)
|
// 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,
|
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 {
|
} else {
|
||||||
writer.invokeDynamic(ref.invokedName, ref.invokedType.getDescriptor(), LAMBDA_BOOTSTRAP_HANDLE,
|
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);
|
LambdaMetafactory.FLAG_BRIDGES, 1, ref.interfaceType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue