Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Painless: Add MethodType to PainlessMethod #32441

Merged
merged 2 commits into from
Jul 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,12 @@ public FunctionRef(PainlessLookup painlessLookup, Class<?> expected, String type
* @param numCaptures number of captured arguments
*/
public FunctionRef(Class<?> expected, PainlessMethod interfaceMethod, PainlessMethod delegateMethod, int numCaptures) {
MethodType delegateMethodType = delegateMethod.getMethodType();
MethodType delegateMethodType = delegateMethod.methodType;

interfaceMethodName = interfaceMethod.name;
factoryMethodType = MethodType.methodType(expected,
delegateMethodType.dropParameterTypes(numCaptures, delegateMethodType.parameterCount()));
interfaceMethodType = interfaceMethod.getMethodType().dropParameterTypes(0, 1);
interfaceMethodType = interfaceMethod.methodType.dropParameterTypes(0, 1);

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

delegateClassName = CLASS_NAME;
delegateInvokeType = H_INVOKESTATIC;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
Expand Down Expand Up @@ -356,10 +357,12 @@ public void addPainlessConstructor(Class<?> targetClass, List<Class<?>> typePara
"[[" + targetCanonicalClassName + "], " + typesToCanonicalTypeNames(typeParameters) + "] not found", iae);
}

MethodType methodType = methodHandle.type();

painlessConstructor = painlessMethodCache.computeIfAbsent(
new PainlessMethodCacheKey(targetClass, CONSTRUCTOR_NAME, typeParameters),
key -> new PainlessMethod(CONSTRUCTOR_NAME, targetClass, null, void.class, typeParameters,
asmConstructor, javaConstructor.getModifiers(), methodHandle)
asmConstructor, javaConstructor.getModifiers(), methodHandle, methodType)
);

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

MethodType methodType = methodHandle.type();

painlessMethod = painlessMethodCache.computeIfAbsent(
new PainlessMethodCacheKey(targetClass, methodName, typeParameters),
key -> new PainlessMethod(methodName, targetClass, null, returnType,
typeParameters, asmMethod, javaMethod.getModifiers(), methodHandle));
typeParameters, asmMethod, javaMethod.getModifiers(), methodHandle, methodType));

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

MethodType methodType = methodHandle.type();

painlessMethod = painlessMethodCache.computeIfAbsent(
new PainlessMethodCacheKey(targetClass, methodName, typeParameters),
key -> new PainlessMethod(methodName, targetClass, augmentedClass, returnType,
typeParameters, asmMethod, javaMethod.getModifiers(), methodHandle));
typeParameters, asmMethod, javaMethod.getModifiers(), methodHandle, methodType));

painlessClassBuilder.methods.put(painlessMethodKey, painlessMethod);
} else if ((painlessMethod.name.equals(methodName) && painlessMethod.rtn == returnType &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,10 @@ public class PainlessMethod {
public final org.objectweb.asm.commons.Method method;
public final int modifiers;
public final MethodHandle handle;
public final MethodType methodType;

public PainlessMethod(String name, Class<?> target, Class<?> augmentation, Class<?> rtn, List<Class<?>> arguments,
org.objectweb.asm.commons.Method method, int modifiers, MethodHandle handle) {
org.objectweb.asm.commons.Method method, int modifiers, MethodHandle handle, MethodType methodType) {
this.name = name;
this.augmentation = augmentation;
this.target = target;
Expand All @@ -49,54 +50,7 @@ public PainlessMethod(String name, Class<?> target, Class<?> augmentation, Class
this.method = method;
this.modifiers = modifiers;
this.handle = handle;
}

/**
* Returns MethodType for this method.
* <p>
* This works even for user-defined Methods (where the MethodHandle is null).
*/
public MethodType getMethodType() {
// we have a methodhandle already (e.g. whitelisted class)
// just return its type
if (handle != null) {
return handle.type();
}
// otherwise compute it
final Class<?> params[];
final Class<?> returnValue;
if (augmentation != null) {
// static method disguised as virtual/interface method
params = new Class<?>[1 + arguments.size()];
params[0] = augmentation;
for (int i = 0; i < arguments.size(); i++) {
params[i + 1] = PainlessLookupUtility.typeToJavaType(arguments.get(i));
}
returnValue = PainlessLookupUtility.typeToJavaType(rtn);
} else if (Modifier.isStatic(modifiers)) {
// static method: straightforward copy
params = new Class<?>[arguments.size()];
for (int i = 0; i < arguments.size(); i++) {
params[i] = PainlessLookupUtility.typeToJavaType(arguments.get(i));
}
returnValue = PainlessLookupUtility.typeToJavaType(rtn);
} else if ("<init>".equals(name)) {
// constructor: returns the owner class
params = new Class<?>[arguments.size()];
for (int i = 0; i < arguments.size(); i++) {
params[i] = PainlessLookupUtility.typeToJavaType(arguments.get(i));
}
returnValue = target;
} else {
// virtual/interface method: add receiver class
params = new Class<?>[1 + arguments.size()];
params[0] = target;
for (int i = 0; i < arguments.size(); i++) {
params[i + 1] = PainlessLookupUtility.typeToJavaType(arguments.get(i));
}
returnValue = PainlessLookupUtility.typeToJavaType(rtn);
}
return MethodType.methodType(returnValue, params);
this.methodType = methodType;
}

public void write(MethodWriter writer) {
Expand All @@ -118,7 +72,7 @@ public void write(MethodWriter writer) {
// method since java 8 did not check, but java 9 and 10 do
if (Modifier.isInterface(clazz.getModifiers())) {
writer.visitMethodInsn(Opcodes.INVOKESTATIC,
type.getInternalName(), name, getMethodType().toMethodDescriptorString(), true);
type.getInternalName(), name, methodType.toMethodDescriptorString(), true);
} else {
writer.invokeStatic(type, method);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,11 @@ void generateSignature(PainlessLookup painlessLookup) {
}
}

int modifiers = Modifier.STATIC | Modifier.PRIVATE;
org.objectweb.asm.commons.Method method = new org.objectweb.asm.commons.Method(name, MethodType.methodType(
PainlessLookupUtility.typeToJavaType(rtnType), paramClasses).toMethodDescriptorString());
this.method = new PainlessMethod(name, null, null, rtnType, paramTypes, method, Modifier.STATIC | Modifier.PRIVATE, null);
MethodType methodType = MethodType.methodType(PainlessLookupUtility.typeToJavaType(rtnType), paramClasses);
this.method = new PainlessMethod(name, null, null, rtnType, paramTypes, method, modifiers, null, methodType);
}

@Override
Expand Down