Skip to content

Commit 1514ec8

Browse files
committed
Painless: Add method type to method. (#32441)
MethodType can be computed at compile-time rather than run-time. This removes the method that collects MethodType at run-time from a PainlessMethod since is it no longer necessary.
1 parent 7b11c28 commit 1514ec8

File tree

4 files changed

+20
-57
lines changed

4 files changed

+20
-57
lines changed

modules/lang-painless/src/main/java/org/elasticsearch/painless/FunctionRef.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,12 @@ public FunctionRef(PainlessLookup painlessLookup, Class<?> expected, String type
9393
* @param numCaptures number of captured arguments
9494
*/
9595
public FunctionRef(Class<?> expected, PainlessMethod interfaceMethod, PainlessMethod delegateMethod, int numCaptures) {
96-
MethodType delegateMethodType = delegateMethod.getMethodType();
96+
MethodType delegateMethodType = delegateMethod.methodType;
9797

9898
interfaceMethodName = interfaceMethod.name;
9999
factoryMethodType = MethodType.methodType(expected,
100100
delegateMethodType.dropParameterTypes(numCaptures, delegateMethodType.parameterCount()));
101-
interfaceMethodType = interfaceMethod.getMethodType().dropParameterTypes(0, 1);
101+
interfaceMethodType = interfaceMethod.methodType.dropParameterTypes(0, 1);
102102

103103
// the Painless$Script class can be inferred if owner is null
104104
if (delegateMethod.target == null) {
@@ -142,7 +142,7 @@ public FunctionRef(Class<?> expected,
142142
interfaceMethodName = interfaceMethod.name;
143143
factoryMethodType = MethodType.methodType(expected,
144144
delegateMethodType.dropParameterTypes(numCaptures, delegateMethodType.parameterCount()));
145-
interfaceMethodType = interfaceMethod.getMethodType().dropParameterTypes(0, 1);
145+
interfaceMethodType = interfaceMethod.methodType.dropParameterTypes(0, 1);
146146

147147
delegateClassName = CLASS_NAME;
148148
delegateInvokeType = H_INVOKESTATIC;

modules/lang-painless/src/main/java/org/elasticsearch/painless/lookup/PainlessLookupBuilder.java

+10-3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
import java.lang.invoke.MethodHandle;
2929
import java.lang.invoke.MethodHandles;
30+
import java.lang.invoke.MethodType;
3031
import java.lang.reflect.Constructor;
3132
import java.lang.reflect.Field;
3233
import java.lang.reflect.Method;
@@ -356,10 +357,12 @@ public void addPainlessConstructor(Class<?> targetClass, List<Class<?>> typePara
356357
"[[" + targetCanonicalClassName + "], " + typesToCanonicalTypeNames(typeParameters) + "] not found", iae);
357358
}
358359

360+
MethodType methodType = methodHandle.type();
361+
359362
painlessConstructor = painlessMethodCache.computeIfAbsent(
360363
new PainlessMethodCacheKey(targetClass, CONSTRUCTOR_NAME, typeParameters),
361364
key -> new PainlessMethod(CONSTRUCTOR_NAME, targetClass, null, void.class, typeParameters,
362-
asmConstructor, javaConstructor.getModifiers(), methodHandle)
365+
asmConstructor, javaConstructor.getModifiers(), methodHandle, methodType)
363366
);
364367

365368
painlessClassBuilder.constructors.put(painlessMethodKey, painlessConstructor);
@@ -516,10 +519,12 @@ public void addPainlessMethod(Class<?> targetClass, Class<?> augmentedClass, Str
516519
"[" + methodName + "], " + typesToCanonicalTypeNames(typeParameters) + "] not found", iae);
517520
}
518521

522+
MethodType methodType = methodHandle.type();
523+
519524
painlessMethod = painlessMethodCache.computeIfAbsent(
520525
new PainlessMethodCacheKey(targetClass, methodName, typeParameters),
521526
key -> new PainlessMethod(methodName, targetClass, null, returnType,
522-
typeParameters, asmMethod, javaMethod.getModifiers(), methodHandle));
527+
typeParameters, asmMethod, javaMethod.getModifiers(), methodHandle, methodType));
523528

524529
painlessClassBuilder.staticMethods.put(painlessMethodKey, painlessMethod);
525530
} else if ((painlessMethod.name.equals(methodName) && painlessMethod.rtn == returnType &&
@@ -557,10 +562,12 @@ public void addPainlessMethod(Class<?> targetClass, Class<?> augmentedClass, Str
557562
}
558563
}
559564

565+
MethodType methodType = methodHandle.type();
566+
560567
painlessMethod = painlessMethodCache.computeIfAbsent(
561568
new PainlessMethodCacheKey(targetClass, methodName, typeParameters),
562569
key -> new PainlessMethod(methodName, targetClass, augmentedClass, returnType,
563-
typeParameters, asmMethod, javaMethod.getModifiers(), methodHandle));
570+
typeParameters, asmMethod, javaMethod.getModifiers(), methodHandle, methodType));
564571

565572
painlessClassBuilder.methods.put(painlessMethodKey, painlessMethod);
566573
} else if ((painlessMethod.name.equals(methodName) && painlessMethod.rtn == returnType &&

modules/lang-painless/src/main/java/org/elasticsearch/painless/lookup/PainlessMethod.java

+4-50
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,10 @@ public class PainlessMethod {
3838
public final org.objectweb.asm.commons.Method method;
3939
public final int modifiers;
4040
public final MethodHandle handle;
41+
public final MethodType methodType;
4142

4243
public PainlessMethod(String name, Class<?> target, Class<?> augmentation, Class<?> rtn, List<Class<?>> arguments,
43-
org.objectweb.asm.commons.Method method, int modifiers, MethodHandle handle) {
44+
org.objectweb.asm.commons.Method method, int modifiers, MethodHandle handle, MethodType methodType) {
4445
this.name = name;
4546
this.augmentation = augmentation;
4647
this.target = target;
@@ -49,54 +50,7 @@ public PainlessMethod(String name, Class<?> target, Class<?> augmentation, Class
4950
this.method = method;
5051
this.modifiers = modifiers;
5152
this.handle = handle;
52-
}
53-
54-
/**
55-
* Returns MethodType for this method.
56-
* <p>
57-
* This works even for user-defined Methods (where the MethodHandle is null).
58-
*/
59-
public MethodType getMethodType() {
60-
// we have a methodhandle already (e.g. whitelisted class)
61-
// just return its type
62-
if (handle != null) {
63-
return handle.type();
64-
}
65-
// otherwise compute it
66-
final Class<?> params[];
67-
final Class<?> returnValue;
68-
if (augmentation != null) {
69-
// static method disguised as virtual/interface method
70-
params = new Class<?>[1 + arguments.size()];
71-
params[0] = augmentation;
72-
for (int i = 0; i < arguments.size(); i++) {
73-
params[i + 1] = PainlessLookupUtility.typeToJavaType(arguments.get(i));
74-
}
75-
returnValue = PainlessLookupUtility.typeToJavaType(rtn);
76-
} else if (Modifier.isStatic(modifiers)) {
77-
// static method: straightforward copy
78-
params = new Class<?>[arguments.size()];
79-
for (int i = 0; i < arguments.size(); i++) {
80-
params[i] = PainlessLookupUtility.typeToJavaType(arguments.get(i));
81-
}
82-
returnValue = PainlessLookupUtility.typeToJavaType(rtn);
83-
} else if ("<init>".equals(name)) {
84-
// constructor: returns the owner class
85-
params = new Class<?>[arguments.size()];
86-
for (int i = 0; i < arguments.size(); i++) {
87-
params[i] = PainlessLookupUtility.typeToJavaType(arguments.get(i));
88-
}
89-
returnValue = target;
90-
} else {
91-
// virtual/interface method: add receiver class
92-
params = new Class<?>[1 + arguments.size()];
93-
params[0] = target;
94-
for (int i = 0; i < arguments.size(); i++) {
95-
params[i + 1] = PainlessLookupUtility.typeToJavaType(arguments.get(i));
96-
}
97-
returnValue = PainlessLookupUtility.typeToJavaType(rtn);
98-
}
99-
return MethodType.methodType(returnValue, params);
53+
this.methodType = methodType;
10054
}
10155

10256
public void write(MethodWriter writer) {
@@ -118,7 +72,7 @@ public void write(MethodWriter writer) {
11872
// method since java 8 did not check, but java 9 and 10 do
11973
if (Modifier.isInterface(clazz.getModifiers())) {
12074
writer.visitMethodInsn(Opcodes.INVOKESTATIC,
121-
type.getInternalName(), name, getMethodType().toMethodDescriptorString(), true);
75+
type.getInternalName(), name, methodType.toMethodDescriptorString(), true);
12276
} else {
12377
writer.invokeStatic(type, method);
12478
}

modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SFunction.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -145,9 +145,11 @@ void generateSignature(PainlessLookup painlessLookup) {
145145
}
146146
}
147147

148+
int modifiers = Modifier.STATIC | Modifier.PRIVATE;
148149
org.objectweb.asm.commons.Method method = new org.objectweb.asm.commons.Method(name, MethodType.methodType(
149150
PainlessLookupUtility.typeToJavaType(rtnType), paramClasses).toMethodDescriptorString());
150-
this.method = new PainlessMethod(name, null, null, rtnType, paramTypes, method, Modifier.STATIC | Modifier.PRIVATE, null);
151+
MethodType methodType = MethodType.methodType(PainlessLookupUtility.typeToJavaType(rtnType), paramClasses);
152+
this.method = new PainlessMethod(name, null, null, rtnType, paramTypes, method, modifiers, null, methodType);
151153
}
152154

153155
@Override

0 commit comments

Comments
 (0)