use painless types in FunctionRef
This commit is contained in:
parent
39550354a7
commit
3108c399f0
|
@ -230,7 +230,7 @@ public final class Def {
|
|||
for (int i = 0; i < args.length; i++) {
|
||||
// its a functional reference, replace the argument with an impl
|
||||
if ((recipe & (1L << (i - 1))) != 0) {
|
||||
filters[i] = lookupReference(lookup, method.arguments.get(i - 1).clazz, (String) args[i]);
|
||||
filters[i] = lookupReference(lookup, method.arguments.get(i - 1), (String) args[i]);
|
||||
}
|
||||
}
|
||||
handle = MethodHandles.filterArguments(handle, 0, filters);
|
||||
|
@ -242,7 +242,7 @@ public final class Def {
|
|||
/** Returns a method handle to an implementation of clazz, given method reference signature
|
||||
* @throws LambdaConversionException if a method reference cannot be converted to an functional interface
|
||||
*/
|
||||
private static MethodHandle lookupReference(Lookup lookup, Class<?> clazz, String signature) throws LambdaConversionException {
|
||||
private static MethodHandle lookupReference(Lookup lookup, Definition.Type clazz, String signature) throws LambdaConversionException {
|
||||
int separator = signature.indexOf('.');
|
||||
FunctionRef ref = new FunctionRef(clazz, signature.substring(0, separator), signature.substring(separator+1));
|
||||
final CallSite callSite;
|
||||
|
@ -270,7 +270,7 @@ public final class Def {
|
|||
interfaceType);
|
||||
}
|
||||
// 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));
|
||||
MethodHandle factory = callSite.dynamicInvoker().asType(MethodType.methodType(clazz.clazz));
|
||||
return MethodHandles.dropArguments(factory, 0, Object.class);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,14 +19,13 @@
|
|||
|
||||
package org.elasticsearch.painless;
|
||||
|
||||
import org.elasticsearch.painless.Definition.Method;
|
||||
import org.objectweb.asm.Handle;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* computes "everything you need" to call LambdaMetaFactory, given an expected interface,
|
||||
|
@ -43,29 +42,33 @@ public class FunctionRef {
|
|||
|
||||
public final MethodHandle implMethodHandle;
|
||||
|
||||
public FunctionRef(Class<?> expected, String type, String call) {
|
||||
public FunctionRef(Definition.Type expected, String type, String call) {
|
||||
boolean isCtorReference = "new".equals(call);
|
||||
// check its really a functional interface
|
||||
// for e.g. Comparable
|
||||
java.lang.reflect.Method method = getFunctionalMethod(type, call, expected);
|
||||
Method method = expected.struct.getFunctionalMethod();
|
||||
if (method == null) {
|
||||
throw new IllegalArgumentException("Cannot convert function reference [" + type + "::" + call + "] " +
|
||||
"to [" + expected.name + "], not a functional interface");
|
||||
}
|
||||
// e.g. compareTo
|
||||
invokedName = method.getName();
|
||||
invokedName = method.name;
|
||||
// e.g. (Object)Comparator
|
||||
invokedType = Type.getMethodType(Type.getType(expected));
|
||||
invokedType = Type.getMethodType(expected.type);
|
||||
// e.g. (Object,Object)int
|
||||
interfaceType = Type.getMethodType(Type.getMethodDescriptor(method));
|
||||
interfaceType = Type.getMethodType(method.method.getDescriptor());
|
||||
// lookup requested method
|
||||
Definition.Struct struct = Definition.getType(type).struct;
|
||||
final Definition.Method impl;
|
||||
// ctor ref
|
||||
if (isCtorReference) {
|
||||
impl = struct.constructors.get(new Definition.MethodKey("<init>", method.getParameterCount()));
|
||||
impl = struct.constructors.get(new Definition.MethodKey("<init>", method.arguments.size()));
|
||||
} else {
|
||||
// look for a static impl first
|
||||
Definition.Method staticImpl = struct.staticMethods.get(new Definition.MethodKey(call, method.getParameterCount()));
|
||||
Definition.Method staticImpl = struct.staticMethods.get(new Definition.MethodKey(call, method.arguments.size()));
|
||||
if (staticImpl == null) {
|
||||
// otherwise a virtual impl
|
||||
impl = struct.methods.get(new Definition.MethodKey(call, method.getParameterCount()-1));
|
||||
impl = struct.methods.get(new Definition.MethodKey(call, method.arguments.size()-1));
|
||||
} else {
|
||||
impl = staticImpl;
|
||||
}
|
||||
|
@ -97,30 +100,4 @@ public class FunctionRef {
|
|||
samMethodType = Type.getMethodType(impl.method.getReturnType(), params);
|
||||
}
|
||||
}
|
||||
|
||||
static final Set<Definition.MethodKey> OBJECT_METHODS = new HashSet<>();
|
||||
static {
|
||||
for (java.lang.reflect.Method m : Object.class.getMethods()) {
|
||||
OBJECT_METHODS.add(new Definition.MethodKey(m.getName(), m.getParameterCount()));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: move all this crap out, to Definition to compute up front
|
||||
java.lang.reflect.Method getFunctionalMethod(String type, String call, Class<?> clazz) {
|
||||
if (!clazz.isInterface()) {
|
||||
throw new IllegalArgumentException("Cannot convert function reference ["
|
||||
+ type + "::" + call + "] to [" + clazz + "]");
|
||||
}
|
||||
for (java.lang.reflect.Method m : clazz.getMethods()) {
|
||||
if (m.isDefault()) {
|
||||
continue;
|
||||
}
|
||||
if (OBJECT_METHODS.contains(new Definition.MethodKey(m.getName(), m.getParameterCount()))) {
|
||||
continue;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
throw new IllegalArgumentException("Cannot convert function reference ["
|
||||
+ type + "::" + call + "] to [" + clazz + "]");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ public class EFunctionRef extends AExpression {
|
|||
actual = Definition.getType("String");
|
||||
} else {
|
||||
try {
|
||||
ref = new FunctionRef(expected.clazz, type, call);
|
||||
ref = new FunctionRef(expected, type, call);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw createError(e);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue