Unfuck the MethodWriter nesting. All MethodWriters should only live separately from each other, no nesting

This commit is contained in:
Uwe Schindler 2016-06-11 21:00:06 +02:00
parent e2f999b025
commit 876f0a613e
3 changed files with 25 additions and 24 deletions

View File

@ -87,7 +87,6 @@ import static org.elasticsearch.painless.WriterConstants.UTILITY_TYPE;
* shared by the nodes of the Painless tree.
*/
public final class MethodWriter extends GeneratorAdapter {
private final ClassWriter parent;
private final BitSet statements;
private final Deque<List<org.objectweb.asm.Type>> stringConcatArgs =
@ -97,17 +96,9 @@ public final class MethodWriter extends GeneratorAdapter {
super(Opcodes.ASM5, cw.visitMethod(access, method.getName(), method.getDescriptor(), null, null),
access, method.getName(), method.getDescriptor());
this.parent = cw;
this.statements = statements;
}
/**
* @return A new {@link MethodWriter} with the specified access and signature.
*/
public MethodWriter newMethodWriter(int access, Method method) {
return new MethodWriter(access, method, parent, statements);
}
/**
* Marks a new statement boundary.
* <p>
@ -362,4 +353,9 @@ public final class MethodWriter extends GeneratorAdapter {
super.endMethod();
}
@Override
public void visitEnd() {
throw new AssertionError("Should never call this method on MethodWriter, use endMethod() instead");
}
}

View File

@ -29,11 +29,13 @@ import org.elasticsearch.painless.Locals.FunctionReserved;
import org.elasticsearch.painless.Locals.Variable;
import org.elasticsearch.painless.Location;
import org.elasticsearch.painless.MethodWriter;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import java.lang.invoke.MethodType;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collections;
import java.util.List;
@ -132,11 +134,16 @@ public class SFunction extends AStatement {
locals.decrementScope();
}
/** Writes the function to given ClassWriter. */
void write (ClassWriter writer, BitSet statements) {
final MethodWriter function = new MethodWriter(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC, method.method, writer, statements);
write(function);
function.endMethod();
}
@Override
void write(MethodWriter writer) {
MethodWriter function = writer.newMethodWriter(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC, method.method);
void write(MethodWriter function) {
if (reserved.getMaxLoopCounter() > 0) {
// if there is infinite loop protection, we do this once:
// int #loop = settings.getMaxLoopCounter()
@ -158,7 +165,5 @@ public class SFunction extends AStatement {
throw createError(new IllegalStateException("Illegal tree structure."));
}
}
function.endMethod();
}
}

View File

@ -136,25 +136,29 @@ public final class SSource extends AStatement {
writer.visit(classVersion, classAccess, className, null, classBase, classInterfaces);
writer.visitSource(Location.computeSourceName(name, source), null);
// Create the execute MethodWriter.
expressions = new BitSet(source.length());
MethodWriter execute = new MethodWriter(Opcodes.ACC_PUBLIC, EXECUTE, writer, expressions);
// Write the constructor.
// Write the constructor:
MethodWriter constructor = execute.newMethodWriter(Opcodes.ACC_PUBLIC, CONSTRUCTOR);
MethodWriter constructor = new MethodWriter(Opcodes.ACC_PUBLIC, CONSTRUCTOR, writer, expressions);
constructor.loadThis();
constructor.loadArgs();
constructor.invokeConstructor(org.objectweb.asm.Type.getType(Executable.class), CONSTRUCTOR);
constructor.returnValue();
constructor.endMethod();
// Write the execute method.
// Write the execute method:
MethodWriter execute = new MethodWriter(Opcodes.ACC_PUBLIC, EXECUTE, writer, expressions);
write(execute);
execute.endMethod();
// Write all functions:
for (SFunction function : functions) {
function.write(writer, expressions);
}
if (!functions.isEmpty()) {
// write a reference to each function
for (SFunction function : functions) {
@ -186,10 +190,6 @@ public final class SSource extends AStatement {
@Override
void write(MethodWriter writer) {
for (SFunction function : functions) {
function.write(writer);
}
if (reserved.usesScore()) {
// if the _score value is used, we do this once:
// final double _score = scorer.score();