diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Def.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Def.java index af96e23771f..e7f56bdbeec 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Def.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Def.java @@ -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)); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/FunctionRef.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/FunctionRef.java index aa847535cd4..3ac6a29527b 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/FunctionRef.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/FunctionRef.java @@ -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(); } } } diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EFunctionRef.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EFunctionRef.java index a51ac3ad737..2f8394ebc17 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EFunctionRef.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EFunctionRef.java @@ -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); } }