Change Painless regex node to use SField instead of Globals (#47944)

* Change Painless regex node to use SField instead of Globals

* Use reflection instead of ASM to specify modifiers

* Remove synthetic from SField
This commit is contained in:
Jack Conradson 2019-10-15 07:46:29 -07:00
parent b2ce72850b
commit 155ecd0a76
5 changed files with 40 additions and 23 deletions

View File

@ -27,6 +27,7 @@ import org.objectweb.asm.util.Printer;
import org.objectweb.asm.util.TraceClassVisitor;
import java.io.Closeable;
import java.lang.reflect.Modifier;
import java.util.BitSet;
/**
@ -35,6 +36,30 @@ import java.util.BitSet;
*/
public class ClassWriter implements Closeable {
/**
* Converts Java reflection modifiers to ASM access constants.
* @param modifiers Java reflection {@code Modifiers}
* @param synthetic {@code true} if the item is synthetically generated
* @return ASM access constants
*/
public static int buildAccess(int modifiers, boolean synthetic) {
int access = synthetic ? Opcodes.ACC_SYNTHETIC : 0;
if (Modifier.isFinal(modifiers)) access |= Opcodes.ACC_FINAL;
if (Modifier.isInterface(modifiers)) access |= Opcodes.ACC_INTERFACE;
if (Modifier.isNative(modifiers)) access |= Opcodes.ACC_NATIVE;
if (Modifier.isPrivate(modifiers)) access |= Opcodes.ACC_PRIVATE;
if (Modifier.isProtected(modifiers)) access |= Opcodes.ACC_PROTECTED;
if (Modifier.isPublic(modifiers)) access |= Opcodes.ACC_PUBLIC;
if (Modifier.isStatic(modifiers)) access |= Opcodes.ACC_STATIC;
if (Modifier.isStrict(modifiers)) access |= Opcodes.ACC_STRICT;
if (Modifier.isSynchronized(modifiers)) access |= Opcodes.ACC_SYNCHRONIZED;
if (Modifier.isTransient(modifiers)) access |= Opcodes.ACC_TRANSIENT;
if (Modifier.isVolatile(modifiers)) access |= Opcodes.ACC_VOLATILE;
return access;
}
protected final CompilerSettings compilerSettings;
protected final BitSet statements;

View File

@ -34,15 +34,13 @@ import org.objectweb.asm.Label;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import static org.elasticsearch.painless.WriterConstants.CLASS_TYPE;
import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
import static org.objectweb.asm.Opcodes.ACC_STATIC;
/**
* Represents a user-defined call.
@ -144,13 +142,13 @@ public final class ECallLocal extends AExpression {
actual = classBinding.returnType;
bindingName = scriptRoot.getNextSyntheticName("class_binding");
scriptRoot.getClassNode().addField(new SField(location,
ACC_PRIVATE, bindingName, classBinding.javaConstructor.getDeclaringClass(), null));
Modifier.PRIVATE, bindingName, classBinding.javaConstructor.getDeclaringClass(), null));
} else if (instanceBinding != null) {
typeParameters = new ArrayList<>(instanceBinding.typeParameters);
actual = instanceBinding.returnType;
bindingName = scriptRoot.getNextSyntheticName("instance_binding");
scriptRoot.getClassNode().addField(new SField(location,
ACC_STATIC | ACC_PUBLIC, bindingName, instanceBinding.targetInstance.getClass(), instanceBinding.targetInstance));
scriptRoot.getClassNode().addField(new SField(location, Modifier.STATIC | Modifier.PUBLIC,
bindingName, instanceBinding.targetInstance.getClass(), instanceBinding.targetInstance));
} else {
throw new IllegalStateException("Illegal tree structure.");
}

View File

@ -29,6 +29,7 @@ import org.elasticsearch.painless.MethodWriter;
import org.elasticsearch.painless.ScriptRoot;
import org.elasticsearch.painless.WriterConstants;
import java.lang.reflect.Modifier;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
@ -87,8 +88,10 @@ public final class ERegex extends AExpression {
new IllegalArgumentException("Error compiling regex: " + e.getDescription()));
}
constant = new Constant(
location, MethodWriter.getType(Pattern.class), "regexAt$" + location.getOffset(), this::initializeConstant);
String name = scriptRoot.getNextSyntheticName("regex");
scriptRoot.getClassNode().addField(
new SField(location, Modifier.FINAL | Modifier.STATIC | Modifier.PRIVATE, name, Pattern.class, null));
constant = new Constant(location, MethodWriter.getType(Pattern.class), name, this::initializeConstant);
actual = Pattern.class;
}

View File

@ -303,16 +303,6 @@ public final class SClass extends AStatement {
if (false == globals.getConstantInitializers().isEmpty()) {
Collection<Constant> inits = globals.getConstantInitializers().values();
// Fields
for (Constant constant : inits) {
classVisitor.visitField(
Opcodes.ACC_FINAL | Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC,
constant.name,
constant.type.getDescriptor(),
null,
null).visitEnd();
}
// Initialize the constants in a static initializer
final MethodWriter clinit = new MethodWriter(Opcodes.ACC_STATIC,
WriterConstants.CLINIT, classVisitor, globals.getStatements(), settings);

View File

@ -35,7 +35,7 @@ import java.util.Set;
*/
public class SField extends ANode {
private final int access;
private final int modifiers;
private final String name;
private final Class<?> type;
private final Object instance;
@ -43,15 +43,15 @@ public class SField extends ANode {
/**
* Standard constructor.
* @param location original location in the source
* @param access asm constants for field modifiers
* @param modifiers java modifiers for the field
* @param name name of the field
* @param type type of the field
* @param instance initial value for the field
*/
public SField(Location location, int access, String name, Class<?> type, Object instance) {
public SField(Location location, int modifiers, String name, Class<?> type, Object instance) {
super(location);
this.access = access;
this.modifiers = modifiers;
this.name = name;
this.type = type;
this.instance = instance;
@ -86,7 +86,8 @@ public class SField extends ANode {
}
void write(ClassWriter classWriter) {
classWriter.getClassVisitor().visitField(access, name, Type.getType(type).getDescriptor(), null, null).visitEnd();
classWriter.getClassVisitor().visitField(
ClassWriter.buildAccess(modifiers, true), name, Type.getType(type).getDescriptor(), null, null).visitEnd();
}
@Override