Remove some hardcoded strings, fix exception handling (remove rethrow), add some utility methods around the "handle$" fields

This commit is contained in:
Uwe Schindler 2016-06-11 21:53:15 +02:00
parent 454881eeb4
commit fd9b0f9087
4 changed files with 24 additions and 25 deletions

View File

@ -23,7 +23,6 @@ import org.elasticsearch.painless.Definition.Method;
import org.elasticsearch.painless.Definition.RuntimeClass;
import java.lang.invoke.CallSite;
import java.lang.invoke.LambdaConversionException;
import java.lang.invoke.LambdaMetafactory;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
@ -219,11 +218,11 @@ public final class Def {
* @param args args passed to callsite
* @param recipe bitset marking functional parameters
* @return pointer to matching method to invoke. never returns null.
* @throws LambdaConversionException if a method reference cannot be converted to an functional interface
* @throws IllegalArgumentException if no matching whitelisted method was found.
* @throws Throwable if a method reference cannot be converted to an functional interface
*/
static MethodHandle lookupMethod(Lookup lookup, MethodType callSiteType,
Class<?> receiverClass, String name, Object args[], long recipe) throws LambdaConversionException {
Class<?> receiverClass, String name, Object args[], long recipe) throws Throwable {
// simple case: no lambdas
if (recipe == 0) {
return lookupMethodInternal(receiverClass, name, args.length - 1).handle;
@ -302,7 +301,7 @@ public final class Def {
* so we simply need to lookup the matching implementation method based on receiver type.
*/
static MethodHandle lookupReference(Lookup lookup, String interfaceClass,
Class<?> receiverClass, String name) throws LambdaConversionException {
Class<?> receiverClass, String name) throws Throwable {
Definition.Type interfaceType = Definition.getType(interfaceClass);
Method interfaceMethod = interfaceType.struct.getFunctionalMethod();
if (interfaceMethod == null) {
@ -313,11 +312,9 @@ public final class Def {
return lookupReferenceInternal(lookup, interfaceType, implMethod.owner.name, implMethod.name, receiverClass);
}
/** 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
*/
/** Returns a method handle to an implementation of clazz, given method reference signature. */
private static MethodHandle lookupReferenceInternal(Lookup lookup, Definition.Type clazz, String type,
String call, Class<?>... captures) throws LambdaConversionException {
String call, Class<?>... captures) throws Throwable {
final FunctionRef ref;
if ("this".equals(type)) {
// user written method
@ -330,14 +327,11 @@ public final class Def {
final MethodHandle handle;
try {
MethodHandle accessor = lookup.findStaticGetter(lookup.lookupClass(),
"handle$" + call + "$" + arity,
getUserFunctionHandleFieldName(call, arity),
MethodHandle.class);
handle = (MethodHandle) accessor.invokeExact();
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new IllegalArgumentException("Unknown call [" + call + "] with [" + arity + "] arguments.");
} catch (Throwable t) {
rethrow(t);
throw new AssertionError();
}
ref = new FunctionRef(clazz, interfaceMethod, handle, captures);
} else {
@ -367,6 +361,10 @@ public final class Def {
return callSite.dynamicInvoker().asType(MethodType.methodType(clazz.clazz, captures));
}
/** gets the field name used to lookup up the MethodHandle for a function. */
public static String getUserFunctionHandleFieldName(String name, int arity) {
return "handle$" + name + "$" + arity;
}
/**
* Looks up handle for a dynamic field getter (field load)

View File

@ -28,6 +28,7 @@ import org.objectweb.asm.commons.Method;
import java.lang.invoke.CallSite;
import java.lang.invoke.LambdaMetafactory;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.BitSet;
@ -66,6 +67,8 @@ public final class WriterConstants {
public final static Type UTILITY_TYPE = Type.getType(Utility.class);
public final static Method STRING_TO_CHAR = getAsmMethod(char.class, "StringTochar", String.class);
public final static Method CHAR_TO_STRING = getAsmMethod(String.class, "charToString", char.class);
public final static Type METHOD_HANDLE_TYPE = Type.getType(MethodHandle.class);
/** dynamic callsite bootstrap signature */
public final static MethodType DEF_BOOTSTRAP_TYPE =

View File

@ -19,6 +19,7 @@
package org.elasticsearch.painless.node;
import org.elasticsearch.painless.Def;
import org.elasticsearch.painless.Definition;
import org.elasticsearch.painless.Definition.Method;
import org.elasticsearch.painless.Definition.Sort;
@ -167,7 +168,7 @@ public class SFunction extends AStatement {
}
}
String getHandleStaticFieldName() {
return "handle$" + name + "$" + parameters.size();
String getStaticHandleFieldName() {
return Def.getUserFunctionHandleFieldName(name, parameters.size());
}
}

View File

@ -26,14 +26,13 @@ import org.elasticsearch.painless.Locals;
import org.elasticsearch.painless.Locals.ExecuteReserved;
import org.elasticsearch.painless.Locals.Variable;
import org.elasticsearch.painless.WriterConstants;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.elasticsearch.painless.Location;
import org.elasticsearch.painless.MethodWriter;
import java.lang.invoke.MethodHandle;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Opcodes;
import java.util.BitSet;
import java.util.Collections;
import java.util.HashMap;
@ -139,7 +138,6 @@ public final class SSource extends AStatement {
expressions = new BitSet(source.length());
// Write the constructor:
MethodWriter constructor = new MethodWriter(Opcodes.ACC_PUBLIC, CONSTRUCTOR, writer, expressions);
constructor.loadThis();
constructor.loadArgs();
@ -148,7 +146,6 @@ public final class SSource extends AStatement {
constructor.endMethod();
// Write the execute method:
MethodWriter execute = new MethodWriter(Opcodes.ACC_PUBLIC, EXECUTE, writer, expressions);
write(execute);
execute.endMethod();
@ -162,8 +159,8 @@ public final class SSource extends AStatement {
if (!functions.isEmpty()) {
for (SFunction function : functions) {
writer.visitField(Opcodes.ACC_FINAL | Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC,
function.getHandleStaticFieldName(),
Type.getDescriptor(MethodHandle.class),
function.getStaticHandleFieldName(),
WriterConstants.METHOD_HANDLE_TYPE.getDescriptor(),
null,
null).visitEnd();
}
@ -177,8 +174,8 @@ public final class SSource extends AStatement {
false);
clinit.push(handle);
clinit.putStatic(CLASS_TYPE,
function.getHandleStaticFieldName(),
Type.getType(MethodHandle.class));
function.getStaticHandleFieldName(),
WriterConstants.METHOD_HANDLE_TYPE);
}
clinit.returnValue();
clinit.endMethod();