write refs for functions

This commit is contained in:
Robert Muir 2016-06-11 14:29:15 -04:00
parent ab457be9d8
commit 8d5a70200f
3 changed files with 31 additions and 3 deletions

View File

@ -46,6 +46,7 @@ public final class WriterConstants {
public final static Type CLASS_TYPE = Type.getObjectType(CLASS_NAME.replace('.', '/'));
public final static Method CONSTRUCTOR = getAsmMethod(void.class, "<init>", String.class, String.class, BitSet.class);
public final static Method CLINIT = getAsmMethod(void.class, "<clinit>");
public final static Method EXECUTE =
getAsmMethod(Object.class, "execute", Map.class, Scorer.class, LeafDocLookup.class, Object.class);

View File

@ -27,10 +27,13 @@ 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 java.util.BitSet;
import java.util.Collections;
import java.util.HashMap;
@ -151,7 +154,31 @@ public final class SSource extends AStatement {
write(execute);
execute.endMethod();
if (!functions.isEmpty()) {
// write a reference to each function
for (SFunction function : functions) {
// XXX: Opcodes.ACC_FINAL too
writer.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC,
"handle$" + function.name + "$" + function.parameters.size(),
Type.getDescriptor(MethodHandle.class),
null,
null).visitEnd();
}
MethodWriter clinit = new MethodWriter(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
WriterConstants.CLINIT, writer, expressions);
for (SFunction function : functions) {
Handle handle = new Handle(Opcodes.H_INVOKESTATIC,
CLASS_TYPE.getInternalName(),
function.name,
function.method.method.getDescriptor(),
false);
clinit.push(handle);
clinit.putStatic(CLASS_TYPE, "handle$" + function.name + "$" + function.parameters.size(), Type.getType(MethodHandle.class));
}
clinit.returnValue();
clinit.endMethod();
}
// End writing the class and store the generated bytes.
writer.visitEnd();

View File

@ -110,8 +110,8 @@ public class FunctionRefTests extends ScriptTestCase {
}
public void testOwnStaticMethodReference() {
//System.out.println(Debugger.toString("int mycompare(int i, int j) { return j - i; } " +
// "List l = new ArrayList(); l.add(2); l.add(1); l.sort(this::mycompare); return l.get(0);"));
System.out.println(Debugger.toString("int mycompare(int i, int j) { return j - i; } " +
"List l = new ArrayList(); l.add(2); l.add(1); l.sort(this::mycompare); return l.get(0);"));
assertEquals(2, exec("int mycompare(int i, int j) { j - i } " +
"List l = new ArrayList(); l.add(2); l.add(1); l.sort(this::mycompare); return l.get(0);"));
}