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++) {
|
for (int i = 0; i < args.length; i++) {
|
||||||
// its a functional reference, replace the argument with an impl
|
// its a functional reference, replace the argument with an impl
|
||||||
if ((recipe & (1L << (i - 1))) != 0) {
|
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);
|
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
|
/** 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
|
* @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('.');
|
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;
|
||||||
|
@ -270,7 +270,7 @@ public final class Def {
|
||||||
interfaceType);
|
interfaceType);
|
||||||
}
|
}
|
||||||
// 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));
|
MethodHandle factory = callSite.dynamicInvoker().asType(MethodType.methodType(clazz.clazz));
|
||||||
return MethodHandles.dropArguments(factory, 0, Object.class);
|
return MethodHandles.dropArguments(factory, 0, Object.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,14 +19,13 @@
|
||||||
|
|
||||||
package org.elasticsearch.painless;
|
package org.elasticsearch.painless;
|
||||||
|
|
||||||
|
import org.elasticsearch.painless.Definition.Method;
|
||||||
import org.objectweb.asm.Handle;
|
import org.objectweb.asm.Handle;
|
||||||
import org.objectweb.asm.Opcodes;
|
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.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* computes "everything you need" to call LambdaMetaFactory, given an expected interface,
|
* computes "everything you need" to call LambdaMetaFactory, given an expected interface,
|
||||||
|
@ -43,29 +42,33 @@ public class FunctionRef {
|
||||||
|
|
||||||
public final MethodHandle implMethodHandle;
|
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);
|
boolean isCtorReference = "new".equals(call);
|
||||||
// check its really a functional interface
|
// check its really a functional interface
|
||||||
// for e.g. Comparable
|
// 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
|
// e.g. compareTo
|
||||||
invokedName = method.getName();
|
invokedName = method.name;
|
||||||
// e.g. (Object)Comparator
|
// e.g. (Object)Comparator
|
||||||
invokedType = Type.getMethodType(Type.getType(expected));
|
invokedType = Type.getMethodType(expected.type);
|
||||||
// e.g. (Object,Object)int
|
// e.g. (Object,Object)int
|
||||||
interfaceType = Type.getMethodType(Type.getMethodDescriptor(method));
|
interfaceType = Type.getMethodType(method.method.getDescriptor());
|
||||||
// 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;
|
||||||
// ctor ref
|
// ctor ref
|
||||||
if (isCtorReference) {
|
if (isCtorReference) {
|
||||||
impl = struct.constructors.get(new Definition.MethodKey("<init>", method.getParameterCount()));
|
impl = struct.constructors.get(new Definition.MethodKey("<init>", method.arguments.size()));
|
||||||
} else {
|
} else {
|
||||||
// look for a static impl first
|
// 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) {
|
if (staticImpl == null) {
|
||||||
// otherwise a virtual impl
|
// 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 {
|
} else {
|
||||||
impl = staticImpl;
|
impl = staticImpl;
|
||||||
}
|
}
|
||||||
|
@ -97,30 +100,4 @@ public class FunctionRef {
|
||||||
samMethodType = Type.getMethodType(impl.method.getReturnType(), params);
|
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");
|
actual = Definition.getType("String");
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
ref = new FunctionRef(expected.clazz, type, call);
|
ref = new FunctionRef(expected, type, call);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
throw createError(e);
|
throw createError(e);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue