Browse Source

Remove Painless Type From Locals, Variables, Params, and ScriptInfo (#28471)

Jack Conradson 7 years ago
parent
commit
df1c696e1d
16 changed files with 119 additions and 123 deletions
  1. 9 9
      modules/lang-painless/src/main/java/org/elasticsearch/painless/LambdaBootstrap.java
  2. 25 26
      modules/lang-painless/src/main/java/org/elasticsearch/painless/Locals.java
  3. 21 21
      modules/lang-painless/src/main/java/org/elasticsearch/painless/ScriptClassInfo.java
  4. 10 9
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECapturingFunctionRef.java
  5. 6 6
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ELambda.java
  6. 1 1
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EVariable.java
  7. 7 6
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SCatch.java
  8. 6 6
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclaration.java
  9. 3 3
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SEach.java
  10. 3 5
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SExpression.java
  11. 1 1
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SFunction.java
  12. 1 1
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SReturn.java
  13. 3 3
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSource.java
  14. 14 16
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSubEachArray.java
  15. 7 8
      modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSubEachIterable.java
  16. 2 2
      modules/lang-painless/src/test/java/org/elasticsearch/painless/node/NodeToStringTests.java

+ 9 - 9
modules/lang-painless/src/main/java/org/elasticsearch/painless/LambdaBootstrap.java

@@ -93,7 +93,7 @@ import static org.objectweb.asm.Opcodes.H_NEWINVOKESPECIAL;
  *         private $$Lambda0(List arg$0) {
  *             this.arg$0 = arg$0;
  *         }
- *         
+ *
  *         public static Consumer create$lambda(List arg$0) {
  *             return new $$Lambda0(arg$0);
  *         }
@@ -212,7 +212,7 @@ public final class LambdaBootstrap {
         ClassWriter cw = beginLambdaClass(lambdaClassName, factoryMethodType.returnType());
         Capture[] captures = generateCaptureFields(cw, factoryMethodType);
         generateLambdaConstructor(cw, lambdaClassType, factoryMethodType, captures);
-        
+
         // Handles the special case where a method reference refers to a ctor (we need a static wrapper method):
         if (delegateInvokeType == H_NEWINVOKESPECIAL) {
             assert CTOR_METHOD_NAME.equals(delegateMethodName);
@@ -226,7 +226,7 @@ public final class LambdaBootstrap {
         generateInterfaceMethod(cw, factoryMethodType, lambdaClassType, interfaceMethodName,
             interfaceMethodType, delegateClassType, delegateInvokeType,
             delegateMethodName, delegateMethodType, captures);
-        
+
         endLambdaClass(cw);
 
         Class<?> lambdaClass = createLambdaClass(loader, cw, lambdaClassType);
@@ -321,7 +321,7 @@ public final class LambdaBootstrap {
 
         constructor.returnValue();
         constructor.endMethod();
-        
+
         // Add a factory method, if lambda takes captures.
         // @uschindler says: I talked with Rémi Forax about this. Technically, a plain ctor
         // and a MethodHandle to the ctor would be enough - BUT: Hotspot is unable to
@@ -337,10 +337,10 @@ public final class LambdaBootstrap {
     /**
      * Generates a factory method to delegate to constructors.
      */
-    private static void generateStaticCtorDelegator(ClassWriter cw, int access, String delegatorMethodName, 
+    private static void generateStaticCtorDelegator(ClassWriter cw, int access, String delegatorMethodName,
             Type delegateClassType, MethodType delegateMethodType) {
         Method wrapperMethod = new Method(delegatorMethodName, delegateMethodType.toMethodDescriptorString());
-        Method constructorMethod = 
+        Method constructorMethod =
             new Method(CTOR_METHOD_NAME, delegateMethodType.changeReturnType(void.class).toMethodDescriptorString());
         int modifiers = access | ACC_STATIC;
 
@@ -379,7 +379,7 @@ public final class LambdaBootstrap {
         GeneratorAdapter iface = new GeneratorAdapter(modifiers, lamMeth,
             cw.visitMethod(modifiers, interfaceMethodName, lamDesc, null, null));
         iface.visitCode();
-        
+
         // Loads any captured variables onto the stack.
         for (int captureCount = 0; captureCount < captures.length; ++captureCount) {
             iface.loadThis();
@@ -473,7 +473,7 @@ public final class LambdaBootstrap {
     private static CallSite createNoCaptureCallSite(
             MethodType factoryMethodType,
             Class<?> lambdaClass) {
-        
+
         try {
             return new ConstantCallSite(MethodHandles.constant(
                 factoryMethodType.returnType(), lambdaClass.getConstructor().newInstance()));
@@ -503,7 +503,7 @@ public final class LambdaBootstrap {
      * delegate method will use converted types from the interface method.  Using
      * invokedynamic to make the delegate method call allows
      * {@link MethodHandle#asType} to be used to do the type conversion instead
-     * of either a lot more code or requiring many {@link Definition.Type}s to be looked
+     * of either a lot more code or requiring many {@link Class}es to be looked
      * up at link-time.
      */
     public static CallSite delegateBootstrap(Lookup lookup,

+ 25 - 26
modules/lang-painless/src/main/java/org/elasticsearch/painless/Locals.java

@@ -21,7 +21,6 @@ package org.elasticsearch.painless;
 
 import org.elasticsearch.painless.Definition.Method;
 import org.elasticsearch.painless.Definition.MethodKey;
-import org.elasticsearch.painless.Definition.Type;
 import org.elasticsearch.painless.ScriptClassInfo.MethodArgument;
 
 import java.util.Arrays;
@@ -58,7 +57,7 @@ public final class Locals {
      * <p>
      * This is just like {@link #newFunctionScope}, except the captured parameters are made read-only.
      */
-    public static Locals newLambdaScope(Locals programScope, Type returnType, List<Parameter> parameters,
+    public static Locals newLambdaScope(Locals programScope, Class<?> returnType, List<Parameter> parameters,
                                         int captureCount, int maxLoopCounter) {
         Locals locals = new Locals(programScope, programScope.definition, returnType, KEYWORDS);
         for (int i = 0; i < parameters.size(); i++) {
@@ -68,43 +67,43 @@ public final class Locals {
             // currently, this cannot be allowed, as we swap in real types,
             // but that can prevent a store of a different type...
             boolean isCapture = true;
-            locals.addVariable(parameter.location, parameter.type, parameter.name, isCapture);
+            locals.addVariable(parameter.location, parameter.clazz, parameter.name, isCapture);
         }
         // Loop counter to catch infinite loops.  Internal use only.
         if (maxLoopCounter > 0) {
-            locals.defineVariable(null, locals.getDefinition().intType, LOOP, true);
+            locals.defineVariable(null, int.class, LOOP, true);
         }
         return locals;
     }
 
     /** Creates a new function scope inside the current scope */
-    public static Locals newFunctionScope(Locals programScope, Type returnType, List<Parameter> parameters, int maxLoopCounter) {
+    public static Locals newFunctionScope(Locals programScope, Class<?> returnType, List<Parameter> parameters, int maxLoopCounter) {
         Locals locals = new Locals(programScope, programScope.definition, returnType, KEYWORDS);
         for (Parameter parameter : parameters) {
-            locals.addVariable(parameter.location, parameter.type, parameter.name, false);
+            locals.addVariable(parameter.location, parameter.clazz, parameter.name, false);
         }
         // Loop counter to catch infinite loops.  Internal use only.
         if (maxLoopCounter > 0) {
-            locals.defineVariable(null, locals.getDefinition().intType, LOOP, true);
+            locals.defineVariable(null, int.class, LOOP, true);
         }
         return locals;
     }
 
     /** Creates a new main method scope */
     public static Locals newMainMethodScope(ScriptClassInfo scriptClassInfo, Locals programScope, int maxLoopCounter) {
-        Locals locals = new Locals(programScope, programScope.definition,
-                scriptClassInfo.getExecuteMethodReturnType(), KEYWORDS);
+        Locals locals = new Locals(
+            programScope, programScope.definition, scriptClassInfo.getExecuteMethodReturnType(), KEYWORDS);
         // This reference. Internal use only.
-        locals.defineVariable(null, programScope.definition.getType("Object"), THIS, true);
+        locals.defineVariable(null, Object.class, THIS, true);
 
         // Method arguments
         for (MethodArgument arg : scriptClassInfo.getExecuteArguments()) {
-            locals.defineVariable(null, arg.getType(), arg.getName(), true);
+            locals.defineVariable(null, arg.getClazz(), arg.getName(), true);
         }
 
         // Loop counter to catch infinite loops.  Internal use only.
         if (maxLoopCounter > 0) {
-            locals.defineVariable(null, locals.getDefinition().intType, LOOP, true);
+            locals.defineVariable(null, int.class, LOOP, true);
         }
         return locals;
     }
@@ -155,18 +154,18 @@ public final class Locals {
     }
 
     /** Creates a new variable. Throws IAE if the variable has already been defined (even in a parent) or reserved. */
-    public Variable addVariable(Location location, Type type, String name, boolean readonly) {
+    public Variable addVariable(Location location, Class<?> clazz, String name, boolean readonly) {
         if (hasVariable(name)) {
             throw location.createError(new IllegalArgumentException("Variable [" + name + "] is already defined."));
         }
         if (keywords.contains(name)) {
             throw location.createError(new IllegalArgumentException("Variable [" + name + "] is reserved."));
         }
-        return defineVariable(location, type, name, readonly);
+        return defineVariable(location, clazz, name, readonly);
     }
 
     /** Return type of this scope (e.g. int, if inside a function that returns int) */
-    public Type getReturnType() {
+    public Class<?> getReturnType() {
         return returnType;
     }
 
@@ -191,7 +190,7 @@ public final class Locals {
     // parent scope
     private final Locals parent;
     // return type of this scope
-    private final Type returnType;
+    private final Class<?> returnType;
     // keywords for this scope
     private final Set<String> keywords;
     // next slot number to assign
@@ -211,7 +210,7 @@ public final class Locals {
     /**
      * Create a new Locals with specified return type
      */
-    private Locals(Locals parent, Definition definition, Type returnType, Set<String> keywords) {
+    private Locals(Locals parent, Definition definition, Class<?> returnType, Set<String> keywords) {
         this.parent = parent;
         this.definition = definition;
         this.returnType = returnType;
@@ -246,13 +245,13 @@ public final class Locals {
 
 
     /** Defines a variable at this scope internally. */
-    private Variable defineVariable(Location location, Type type, String name, boolean readonly) {
+    private Variable defineVariable(Location location, Class<?> type, String name, boolean readonly) {
         if (variables == null) {
             variables = new HashMap<>();
         }
         Variable variable = new Variable(location, name, type, getNextSlot(), readonly);
         variables.put(name, variable); // TODO: check result
-        nextSlotNumber += type.type.getSize();
+        nextSlotNumber += MethodWriter.getType(type).getSize();
         return variable;
     }
 
@@ -272,15 +271,15 @@ public final class Locals {
     public static final class Variable {
         public final Location location;
         public final String name;
-        public final Type type;
+        public final Class<?> clazz;
         public final boolean readonly;
         private final int slot;
         private boolean used;
 
-        public Variable(Location location, String name, Type type, int slot, boolean readonly) {
+        public Variable(Location location, String name, Class<?> clazz, int slot, boolean readonly) {
             this.location = location;
             this.name = name;
-            this.type = type;
+            this.clazz = clazz;
             this.slot = slot;
             this.readonly = readonly;
         }
@@ -292,7 +291,7 @@ public final class Locals {
         @Override
         public String toString() {
             StringBuilder b = new StringBuilder();
-            b.append("Variable[type=").append(type);
+            b.append("Variable[type=").append(Definition.ClassToName(clazz));
             b.append(",name=").append(name);
             b.append(",slot=").append(slot);
             if (readonly) {
@@ -306,12 +305,12 @@ public final class Locals {
     public static final class Parameter {
         public final Location location;
         public final String name;
-        public final Type type;
+        public final Class<?> clazz;
 
-        public Parameter(Location location, String name, Type type) {
+        public Parameter(Location location, String name, Class<?> clazz) {
             this.location = location;
             this.name = name;
-            this.type = type;
+            this.clazz = clazz;
         }
     }
 }

+ 21 - 21
modules/lang-painless/src/main/java/org/elasticsearch/painless/ScriptClassInfo.java

@@ -38,11 +38,11 @@ public class ScriptClassInfo {
 
     private final Class<?> baseClass;
     private final org.objectweb.asm.commons.Method executeMethod;
-    private final Definition.Type executeMethodReturnType;
+    private final Class<?> executeMethodReturnType;
     private final List<MethodArgument> executeArguments;
     private final List<org.objectweb.asm.commons.Method> needsMethods;
     private final List<org.objectweb.asm.commons.Method> getMethods;
-    private final List<Definition.Type> getReturns;
+    private final List<Class<?>> getReturns;
 
     public ScriptClassInfo(Definition definition, Class<?> baseClass) {
         this.baseClass = baseClass;
@@ -51,7 +51,7 @@ public class ScriptClassInfo {
         java.lang.reflect.Method executeMethod = null;
         List<org.objectweb.asm.commons.Method> needsMethods = new ArrayList<>();
         List<org.objectweb.asm.commons.Method> getMethods = new ArrayList<>();
-        List<Definition.Type> getReturns = new ArrayList<>();
+        List<Class<?>> getReturns = new ArrayList<>();
         for (java.lang.reflect.Method m : baseClass.getMethods()) {
             if (m.isDefault()) {
                 continue;
@@ -65,7 +65,7 @@ public class ScriptClassInfo {
                                     + "] has more than one.");
                 }
             }
-            if (m.getName().startsWith("needs") && m.getReturnType().equals(boolean.class) && m.getParameterTypes().length == 0) {
+            if (m.getName().startsWith("needs") && m.getReturnType() == boolean.class && m.getParameterTypes().length == 0) {
                 needsMethods.add(new org.objectweb.asm.commons.Method(m.getName(), NEEDS_PARAMETER_METHOD_TYPE.toMethodDescriptorString()));
             }
             if (m.getName().startsWith("get") && m.getName().equals("getClass") == false && Modifier.isStatic(m.getModifiers()) == false) {
@@ -118,15 +118,15 @@ public class ScriptClassInfo {
     }
 
     /**
-     * The Painless {@link Definition.Type} or the return type of the {@code execute} method. This is used to generate the appropriate
+     * The Painless {@link Class} or the return type of the {@code execute} method. This is used to generate the appropriate
      * return bytecode.
      */
-    public Definition.Type getExecuteMethodReturnType() {
+    public Class<?> getExecuteMethodReturnType() {
         return executeMethodReturnType;
     }
 
     /**
-     * Painless {@link Definition.Type}s and names of the arguments to the {@code execute} method. The names are exposed to the Painless
+     * Painless {@link Class}s and names of the arguments to the {@code execute} method. The names are exposed to the Painless
      * script.
      */
     public List<MethodArgument> getExecuteArguments() {
@@ -150,24 +150,24 @@ public class ScriptClassInfo {
     /**
      * The {@code getVarName} methods return types.
      */
-    public List<Definition.Type> getGetReturns() {
+    public List<Class<?>> getGetReturns() {
         return getReturns;
     }
 
     /**
-     * Painless {@link Definition.Type}s and name of the argument to the {@code execute} method.
+     * Painless {@link Class}es and name of the argument to the {@code execute} method.
      */
     public static class MethodArgument {
-        private final Definition.Type type;
+        private final Class<?> clazz;
         private final String name;
 
-        public MethodArgument(Definition.Type type, String name) {
-            this.type = type;
+        public MethodArgument(Class<?> clazz, String name) {
+            this.clazz = clazz;
             this.name = name;
         }
 
-        public Definition.Type getType() {
-            return type;
+        public Class<?> getClazz() {
+            return clazz;
         }
 
         public String getName() {
@@ -175,13 +175,13 @@ public class ScriptClassInfo {
         }
     }
 
-    private MethodArgument methodArgument(Definition definition, Class<?> type, String argName) {
-        Definition.Type defType = definitionTypeForClass(definition, type, componentType -> "[" + argName + "] is of unknown type ["
+    private MethodArgument methodArgument(Definition definition, Class<?> clazz, String argName) {
+        Class<?> defClass = definitionTypeForClass(definition, clazz, componentType -> "[" + argName + "] is of unknown type ["
                 + componentType.getName() + ". Painless interfaces can only accept arguments that are of whitelisted types.");
-        return new MethodArgument(defType, argName);
+        return new MethodArgument(defClass, argName);
     }
 
-    private static Definition.Type definitionTypeForClass(Definition definition, Class<?> type,
+    private static Class<?> definitionTypeForClass(Definition definition, Class<?> type,
             Function<Class<?>, String> unknownErrorMessageSource) {
         int dimensions = 0;
         Class<?> componentType = type;
@@ -190,8 +190,8 @@ public class ScriptClassInfo {
             componentType = componentType.getComponentType();
         }
         Definition.Struct struct;
-        if (componentType.equals(Object.class)) {
-            struct = definition.DefType.struct;
+        if (componentType == Object.class) {
+            struct = definition.getType("def").struct;
         } else {
             Definition.RuntimeClass runtimeClass = definition.getRuntimeClass(componentType);
             if (runtimeClass == null) {
@@ -199,7 +199,7 @@ public class ScriptClassInfo {
             }
             struct = runtimeClass.getStruct();
         }
-        return definition.getType(struct, dimensions);
+        return Definition.TypeToClass(definition.getType(struct, dimensions));
     }
 
     private static String[] readArgumentNamesConstant(Class<?> iface) {

+ 10 - 9
modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ECapturingFunctionRef.java

@@ -22,6 +22,7 @@ package org.elasticsearch.painless.node;
 import org.elasticsearch.painless.AnalyzerCaster;
 import org.elasticsearch.painless.DefBootstrap;
 import org.elasticsearch.painless.Definition;
+import org.elasticsearch.painless.Definition.def;
 import org.elasticsearch.painless.FunctionRef;
 import org.elasticsearch.painless.Globals;
 import org.elasticsearch.painless.Locals;
@@ -63,20 +64,20 @@ public final class ECapturingFunctionRef extends AExpression implements ILambda
     void analyze(Locals locals) {
         captured = locals.getVariable(location, variable);
         if (expected == null) {
-            if (captured.type.dynamic) {
+            if (captured.clazz == def.class) {
                 // dynamic implementation
                 defPointer = "D" + variable + "." + call + ",1";
             } else {
                 // typed implementation
-                defPointer = "S" + captured.type.name + "." + call + ",1";
+                defPointer = "S" + Definition.ClassToName(captured.clazz) + "." + call + ",1";
             }
             actual = String.class;
         } else {
             defPointer = null;
             // static case
-            if (captured.type.dynamic == false) {
+            if (captured.clazz != def.class) {
                 try {
-                    ref = new FunctionRef(locals.getDefinition(), expected, captured.type.name, call, 1);
+                    ref = new FunctionRef(locals.getDefinition(), expected, Definition.ClassToName(captured.clazz), call, 1);
 
                     // check casts between the interface method and the delegate method are legal
                     for (int i = 0; i < ref.interfaceMethod.arguments.size(); ++i) {
@@ -103,15 +104,15 @@ public final class ECapturingFunctionRef extends AExpression implements ILambda
             // dynamic interface: push captured parameter on stack
             // TODO: don't do this: its just to cutover :)
             writer.push((String)null);
-            writer.visitVarInsn(captured.type.type.getOpcode(Opcodes.ILOAD), captured.getSlot());
+            writer.visitVarInsn(MethodWriter.getType(captured.clazz).getOpcode(Opcodes.ILOAD), captured.getSlot());
         } else if (ref == null) {
             // typed interface, dynamic implementation
-            writer.visitVarInsn(captured.type.type.getOpcode(Opcodes.ILOAD), captured.getSlot());
-            Type methodType = Type.getMethodType(MethodWriter.getType(expected), captured.type.type);
+            writer.visitVarInsn(MethodWriter.getType(captured.clazz).getOpcode(Opcodes.ILOAD), captured.getSlot());
+            Type methodType = Type.getMethodType(MethodWriter.getType(expected), MethodWriter.getType(captured.clazz));
             writer.invokeDefCall(call, methodType, DefBootstrap.REFERENCE, Definition.ClassToName(expected));
         } else {
             // typed interface, typed implementation
-            writer.visitVarInsn(captured.type.type.getOpcode(Opcodes.ILOAD), captured.getSlot());
+            writer.visitVarInsn(MethodWriter.getType(captured.clazz).getOpcode(Opcodes.ILOAD), captured.getSlot());
             writer.invokeDynamic(
                 ref.interfaceMethodName,
                 ref.factoryDescriptor,
@@ -132,7 +133,7 @@ public final class ECapturingFunctionRef extends AExpression implements ILambda
 
     @Override
     public Type[] getCaptures() {
-        return new Type[] { captured.type.type };
+        return new Type[] { MethodWriter.getType(captured.clazz) };
     }
 
     @Override

+ 6 - 6
modules/lang-painless/src/main/java/org/elasticsearch/painless/node/ELambda.java

@@ -162,7 +162,7 @@ public final class ELambda extends AExpression implements ILambda {
         List<String> paramTypes = new ArrayList<>(captures.size() + actualParamTypeStrs.size());
         List<String> paramNames = new ArrayList<>(captures.size() + paramNameStrs.size());
         for (Variable var : captures) {
-            paramTypes.add(var.type.name);
+            paramTypes.add(Definition.ClassToName(var.clazz));
             paramNames.add(var.name);
         }
         paramTypes.addAll(actualParamTypeStrs);
@@ -172,7 +172,7 @@ public final class ELambda extends AExpression implements ILambda {
         desugared = new SFunction(reserved, location, Definition.ClassToName(returnType), name,
                                             paramTypes, paramNames, statements, true);
         desugared.generateSignature(locals.getDefinition());
-        desugared.analyze(Locals.newLambdaScope(locals.getProgramScope(), locals.getDefinition().ClassToType(returnType),
+        desugared.analyze(Locals.newLambdaScope(locals.getProgramScope(), returnType,
                                                 desugared.parameters, captures.size(), reserved.getMaxLoopCounter()));
 
         // setup method reference to synthetic method
@@ -191,7 +191,7 @@ public final class ELambda extends AExpression implements ILambda {
             // check casts between the interface method and the delegate method are legal
             for (int i = 0; i < interfaceMethod.arguments.size(); ++i) {
                 Class<?> from = interfaceMethod.arguments.get(i);
-                Class<?> to = Definition.TypeToClass(desugared.parameters.get(i + captures.size()).type);
+                Class<?> to = desugared.parameters.get(i + captures.size()).clazz;
                 AnalyzerCaster.getLegalCast(location, from, to, false, true);
             }
 
@@ -211,7 +211,7 @@ public final class ELambda extends AExpression implements ILambda {
             writer.writeDebugInfo(location);
             // load captures
             for (Variable capture : captures) {
-                writer.visitVarInsn(MethodWriter.getType(capture.type.clazz).getOpcode(Opcodes.ILOAD), capture.getSlot());
+                writer.visitVarInsn(MethodWriter.getType(capture.clazz).getOpcode(Opcodes.ILOAD), capture.getSlot());
             }
 
             writer.invokeDynamic(
@@ -229,7 +229,7 @@ public final class ELambda extends AExpression implements ILambda {
             writer.push((String)null);
             // load captures
             for (Variable capture : captures) {
-                writer.visitVarInsn(MethodWriter.getType(capture.type.clazz).getOpcode(Opcodes.ILOAD), capture.getSlot());
+                writer.visitVarInsn(MethodWriter.getType(capture.clazz).getOpcode(Opcodes.ILOAD), capture.getSlot());
             }
         }
 
@@ -246,7 +246,7 @@ public final class ELambda extends AExpression implements ILambda {
     public org.objectweb.asm.Type[] getCaptures() {
         org.objectweb.asm.Type[] types = new org.objectweb.asm.Type[captures.size()];
         for (int i = 0; i < types.length; i++) {
-            types[i] = MethodWriter.getType(captures.get(i).type.clazz);
+            types[i] = MethodWriter.getType(captures.get(i).clazz);
         }
         return types;
     }

+ 1 - 1
modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EVariable.java

@@ -58,7 +58,7 @@ public final class EVariable extends AStoreable {
             throw createError(new IllegalArgumentException("Variable [" + variable.name + "] is read-only."));
         }
 
-        actual = Definition.TypeToClass(variable.type);
+        actual = variable.clazz;
     }
 
     @Override

+ 7 - 6
modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SCatch.java

@@ -19,6 +19,7 @@
 
 package org.elasticsearch.painless.node;
 
+import org.elasticsearch.painless.Definition;
 import org.elasticsearch.painless.Definition.Type;
 import org.elasticsearch.painless.Globals;
 import org.elasticsearch.painless.Locals;
@@ -65,19 +66,19 @@ public final class SCatch extends AStatement {
 
     @Override
     void analyze(Locals locals) {
-        final Type type;
+        Class<?> clazz;
 
         try {
-            type = locals.getDefinition().getType(this.type);
+            clazz = Definition.TypeToClass(locals.getDefinition().getType(this.type));
         } catch (IllegalArgumentException exception) {
             throw createError(new IllegalArgumentException("Not a type [" + this.type + "]."));
         }
 
-        if (!Exception.class.isAssignableFrom(type.clazz)) {
+        if (!Exception.class.isAssignableFrom(clazz)) {
             throw createError(new ClassCastException("Not an exception type [" + this.type + "]."));
         }
 
-        variable = locals.addVariable(location, type, name, true);
+        variable = locals.addVariable(location, clazz, name, true);
 
         if (block != null) {
             block.lastSource = lastSource;
@@ -102,7 +103,7 @@ public final class SCatch extends AStatement {
         Label jump = new Label();
 
         writer.mark(jump);
-        writer.visitVarInsn(variable.type.type.getOpcode(Opcodes.ISTORE), variable.getSlot());
+        writer.visitVarInsn(MethodWriter.getType(variable.clazz).getOpcode(Opcodes.ISTORE), variable.getSlot());
 
         if (block != null) {
             block.continu = continu;
@@ -110,7 +111,7 @@ public final class SCatch extends AStatement {
             block.write(writer, globals);
         }
 
-        writer.visitTryCatchBlock(begin, end, jump, variable.type.type.getInternalName());
+        writer.visitTryCatchBlock(begin, end, jump, MethodWriter.getType(variable.clazz).getInternalName());
 
         if (exception != null && !block.allEscape) {
             writer.goTo(exception);

+ 6 - 6
modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SDeclaration.java

@@ -61,21 +61,21 @@ public final class SDeclaration extends AStatement {
 
     @Override
     void analyze(Locals locals) {
-        final Type type;
+        Class<?> clazz;
 
         try {
-            type = locals.getDefinition().getType(this.type);
+            clazz = Definition.TypeToClass(locals.getDefinition().getType(this.type));
         } catch (IllegalArgumentException exception) {
             throw createError(new IllegalArgumentException("Not a type [" + this.type + "]."));
         }
 
         if (expression != null) {
-            expression.expected = Definition.TypeToClass(type);
+            expression.expected = clazz;
             expression.analyze(locals);
             expression = expression.cast(locals);
         }
 
-        variable = locals.addVariable(location, type, name, false);
+        variable = locals.addVariable(location, clazz, name, false);
     }
 
     @Override
@@ -83,7 +83,7 @@ public final class SDeclaration extends AStatement {
         writer.writeStatementOffset(location);
 
         if (expression == null) {
-            Class<?> sort = variable.type.clazz;
+            Class<?> sort = variable.clazz;
 
             if (sort == void.class || sort == boolean.class || sort == byte.class ||
                 sort == short.class || sort == char.class || sort == int.class) {
@@ -101,7 +101,7 @@ public final class SDeclaration extends AStatement {
             expression.write(writer, globals);
         }
 
-        writer.visitVarInsn(variable.type.type.getOpcode(Opcodes.ISTORE), variable.getSlot());
+        writer.visitVarInsn(MethodWriter.getType(variable.clazz).getOpcode(Opcodes.ISTORE), variable.getSlot());
     }
 
     @Override

+ 3 - 3
modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SEach.java

@@ -69,16 +69,16 @@ public class SEach extends AStatement {
         expression.expected = expression.actual;
         expression = expression.cast(locals);
 
-        final Type type;
+        Class<?> clazz;
 
         try {
-            type = locals.getDefinition().getType(this.type);
+            clazz = Definition.TypeToClass(locals.getDefinition().getType(this.type));
         } catch (IllegalArgumentException exception) {
             throw createError(new IllegalArgumentException("Not a type [" + this.type + "]."));
         }
 
         locals = Locals.newLocalScope(locals);
-        Variable variable = locals.addVariable(location, type, name, true);
+        Variable variable = locals.addVariable(location, clazz, name, true);
 
         if (expression.actual.isArray()) {
             sub = new SSubEachArray(location, variable, expression, block);

+ 3 - 5
modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SExpression.java

@@ -19,8 +19,6 @@
 
 package org.elasticsearch.painless.node;
 
-import org.elasticsearch.painless.Definition;
-import org.elasticsearch.painless.Definition.Type;
 import org.elasticsearch.painless.Globals;
 import org.elasticsearch.painless.Locals;
 import org.elasticsearch.painless.Location;
@@ -49,8 +47,8 @@ public final class SExpression extends AStatement {
 
     @Override
     void analyze(Locals locals) {
-        Type rtnType = locals.getReturnType();
-        boolean isVoid = rtnType.clazz == void.class;
+        Class<?> rtnType = locals.getReturnType();
+        boolean isVoid = rtnType == void.class;
 
         expression.read = lastSource && !isVoid;
         expression.analyze(locals);
@@ -61,7 +59,7 @@ public final class SExpression extends AStatement {
 
         boolean rtn = lastSource && !isVoid && expression.actual != void.class;
 
-        expression.expected = rtn ? Definition.TypeToClass(rtnType) : expression.actual;
+        expression.expected = rtn ? rtnType : expression.actual;
         expression.internal = rtn;
         expression = expression.cast(locals);
 

+ 1 - 1
modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SFunction.java

@@ -137,7 +137,7 @@ public final class SFunction extends AStatement {
 
                 paramClasses[param] = Definition.defClassToObjectClass(paramType);
                 paramTypes.add(paramType);
-                parameters.add(new Parameter(location, paramNameStrs.get(param), definition.ClassToType(paramType)));
+                parameters.add(new Parameter(location, paramNameStrs.get(param), paramType));
             } catch (IllegalArgumentException exception) {
                 throw createError(new IllegalArgumentException(
                     "Illegal parameter type [" + this.paramTypeStrs.get(param) + "] for function [" + name + "]."));

+ 1 - 1
modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SReturn.java

@@ -48,7 +48,7 @@ public final class SReturn extends AStatement {
 
     @Override
     void analyze(Locals locals) {
-        expression.expected = Definition.TypeToClass(locals.getReturnType());
+        expression.expected = locals.getReturnType();
         expression.internal = true;
         expression.analyze(locals);
         expression = expression.cast(locals);

+ 3 - 3
modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSource.java

@@ -186,8 +186,8 @@ public final class SSource extends AStatement {
     @Override
     void analyze(Locals program) {
         for (SFunction function : functions) {
-            Locals functionLocals = Locals.newFunctionScope(program, program.getDefinition().ClassToType(function.rtnType),
-                                                            function.parameters, function.reserved.getMaxLoopCounter());
+            Locals functionLocals =
+                Locals.newFunctionScope(program, function.rtnType, function.parameters, function.reserved.getMaxLoopCounter());
             function.analyze(functionLocals);
         }
 
@@ -203,7 +203,7 @@ public final class SSource extends AStatement {
             name = Character.toLowerCase(name.charAt(0)) + name.substring(1);
 
             if (reserved.getUsedVariables().contains(name)) {
-                Definition.Type rtn = scriptClassInfo.getGetReturns().get(get);
+                Class<?> rtn = scriptClassInfo.getGetReturns().get(get);
                 mainMethod.addVariable(new Location("getter [" + name + "]", 0), rtn, name, true);
                 getMethods.add(method);
             }

+ 14 - 16
modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSubEachArray.java

@@ -22,7 +22,6 @@ package org.elasticsearch.painless.node;
 import org.elasticsearch.painless.AnalyzerCaster;
 import org.elasticsearch.painless.Definition;
 import org.elasticsearch.painless.Definition.Cast;
-import org.elasticsearch.painless.Definition.Type;
 import org.elasticsearch.painless.Globals;
 import org.elasticsearch.painless.Locals;
 import org.elasticsearch.painless.Locals.Variable;
@@ -45,7 +44,7 @@ final class SSubEachArray extends AStatement {
     private Cast cast = null;
     private Variable array = null;
     private Variable index = null;
-    private Type indexed = null;
+    private Class<?> indexed = null;
 
     SSubEachArray(Location location, Variable variable, AExpression expression, SBlock block) {
         super(location);
@@ -64,11 +63,10 @@ final class SSubEachArray extends AStatement {
     void analyze(Locals locals) {
         // We must store the array and index as variables for securing slots on the stack, and
         // also add the location offset to make the names unique in case of nested for each loops.
-        Type actualType = locals.getDefinition().ClassToType(expression.actual);
-        array = locals.addVariable(location, actualType, "#array" + location.getOffset(), true);
-        index = locals.addVariable(location, locals.getDefinition().intType, "#index" + location.getOffset(), true);
-        indexed = locals.getDefinition().getType(actualType.struct, actualType.dimensions - 1);
-        cast = AnalyzerCaster.getLegalCast(location, Definition.TypeToClass(indexed), Definition.TypeToClass(variable.type), true, true);
+        array = locals.addVariable(location, expression.actual, "#array" + location.getOffset(), true);
+        index = locals.addVariable(location, int.class, "#index" + location.getOffset(), true);
+        indexed = expression.actual.getComponentType();
+        cast = AnalyzerCaster.getLegalCast(location, indexed, variable.clazz, true, true);
     }
 
     @Override
@@ -76,9 +74,9 @@ final class SSubEachArray extends AStatement {
         writer.writeStatementOffset(location);
 
         expression.write(writer, globals);
-        writer.visitVarInsn(array.type.type.getOpcode(Opcodes.ISTORE), array.getSlot());
+        writer.visitVarInsn(MethodWriter.getType(array.clazz).getOpcode(Opcodes.ISTORE), array.getSlot());
         writer.push(-1);
-        writer.visitVarInsn(index.type.type.getOpcode(Opcodes.ISTORE), index.getSlot());
+        writer.visitVarInsn(MethodWriter.getType(index.clazz).getOpcode(Opcodes.ISTORE), index.getSlot());
 
         Label begin = new Label();
         Label end = new Label();
@@ -86,16 +84,16 @@ final class SSubEachArray extends AStatement {
         writer.mark(begin);
 
         writer.visitIincInsn(index.getSlot(), 1);
-        writer.visitVarInsn(index.type.type.getOpcode(Opcodes.ILOAD), index.getSlot());
-        writer.visitVarInsn(array.type.type.getOpcode(Opcodes.ILOAD), array.getSlot());
+        writer.visitVarInsn(MethodWriter.getType(index.clazz).getOpcode(Opcodes.ILOAD), index.getSlot());
+        writer.visitVarInsn(MethodWriter.getType(array.clazz).getOpcode(Opcodes.ILOAD), array.getSlot());
         writer.arrayLength();
         writer.ifICmp(MethodWriter.GE, end);
 
-        writer.visitVarInsn(array.type.type.getOpcode(Opcodes.ILOAD), array.getSlot());
-        writer.visitVarInsn(index.type.type.getOpcode(Opcodes.ILOAD), index.getSlot());
-        writer.arrayLoad(indexed.type);
+        writer.visitVarInsn(MethodWriter.getType(array.clazz).getOpcode(Opcodes.ILOAD), array.getSlot());
+        writer.visitVarInsn(MethodWriter.getType(index.clazz).getOpcode(Opcodes.ILOAD), index.getSlot());
+        writer.arrayLoad(MethodWriter.getType(indexed));
         writer.writeCast(cast);
-        writer.visitVarInsn(variable.type.type.getOpcode(Opcodes.ISTORE), variable.getSlot());
+        writer.visitVarInsn(MethodWriter.getType(variable.clazz).getOpcode(Opcodes.ISTORE), variable.getSlot());
 
         if (loopCounter != null) {
             writer.writeLoopCounter(loopCounter.getSlot(), statementCount, location);
@@ -111,6 +109,6 @@ final class SSubEachArray extends AStatement {
 
     @Override
     public String toString() {
-        return singleLineToString(variable.type.name, variable.name, expression, block);
+        return singleLineToString(Definition.ClassToName(variable.clazz), variable.name, expression, block);
     }
 }

+ 7 - 8
modules/lang-painless/src/main/java/org/elasticsearch/painless/node/SSubEachIterable.java

@@ -73,8 +73,7 @@ final class SSubEachIterable extends AStatement {
     void analyze(Locals locals) {
         // We must store the iterator as a variable for securing a slot on the stack, and
         // also add the location offset to make the name unique in case of nested for each loops.
-        iterator = locals.addVariable(location, locals.getDefinition().getType("Iterator"),
-                "#itr" + location.getOffset(), true);
+        iterator = locals.addVariable(location, Iterator.class, "#itr" + location.getOffset(), true);
 
         if (expression.actual == def.class) {
             method = null;
@@ -88,7 +87,7 @@ final class SSubEachIterable extends AStatement {
             }
         }
 
-        cast = AnalyzerCaster.getLegalCast(location, def.class, Definition.TypeToClass(variable.type), true, true);
+        cast = AnalyzerCaster.getLegalCast(location, def.class, variable.clazz, true, true);
     }
 
     @Override
@@ -105,21 +104,21 @@ final class SSubEachIterable extends AStatement {
             method.write(writer);
         }
 
-        writer.visitVarInsn(iterator.type.type.getOpcode(Opcodes.ISTORE), iterator.getSlot());
+        writer.visitVarInsn(MethodWriter.getType(iterator.clazz).getOpcode(Opcodes.ISTORE), iterator.getSlot());
 
         Label begin = new Label();
         Label end = new Label();
 
         writer.mark(begin);
 
-        writer.visitVarInsn(iterator.type.type.getOpcode(Opcodes.ILOAD), iterator.getSlot());
+        writer.visitVarInsn(MethodWriter.getType(iterator.clazz).getOpcode(Opcodes.ILOAD), iterator.getSlot());
         writer.invokeInterface(ITERATOR_TYPE, ITERATOR_HASNEXT);
         writer.ifZCmp(MethodWriter.EQ, end);
 
-        writer.visitVarInsn(iterator.type.type.getOpcode(Opcodes.ILOAD), iterator.getSlot());
+        writer.visitVarInsn(MethodWriter.getType(iterator.clazz).getOpcode(Opcodes.ILOAD), iterator.getSlot());
         writer.invokeInterface(ITERATOR_TYPE, ITERATOR_NEXT);
         writer.writeCast(cast);
-        writer.visitVarInsn(variable.type.type.getOpcode(Opcodes.ISTORE), variable.getSlot());
+        writer.visitVarInsn(MethodWriter.getType(variable.clazz).getOpcode(Opcodes.ISTORE), variable.getSlot());
 
         if (loopCounter != null) {
             writer.writeLoopCounter(loopCounter.getSlot(), statementCount, location);
@@ -135,6 +134,6 @@ final class SSubEachIterable extends AStatement {
 
     @Override
     public String toString() {
-        return singleLineToString(variable.type.name, variable.name, expression, block);
+        return singleLineToString(Definition.ClassToName(variable.clazz), variable.name, expression, block);
     }
 }

+ 2 - 2
modules/lang-painless/src/test/java/org/elasticsearch/painless/node/NodeToStringTests.java

@@ -763,7 +763,7 @@ public class NodeToStringTests extends ESTestCase {
 
     public void testSSubEachArray() {
         Location l = new Location(getTestName(), 0);
-        Variable v = new Variable(l, "test", definition.intType, 5, false);
+        Variable v = new Variable(l, "test", int.class, 5, false);
         AExpression e = new ENewArray(l, "int", Arrays.asList(new EConstant(l, 1), new EConstant(l, 2), new EConstant(l, 3)), true);
         SBlock b = new SBlock(l, singletonList(new SReturn(l, new EConstant(l, 5))));
         SSubEachArray node = new SSubEachArray(l, v, e, b);
@@ -775,7 +775,7 @@ public class NodeToStringTests extends ESTestCase {
 
     public void testSSubEachIterable() {
         Location l = new Location(getTestName(), 0);
-        Variable v = new Variable(l, "test", definition.intType, 5, false);
+        Variable v = new Variable(l, "test", int.class, 5, false);
         AExpression e = new EListInit(l, Arrays.asList(new EConstant(l, 1), new EConstant(l, 2), new EConstant(l, 3)));
         SBlock b = new SBlock(l, singletonList(new SReturn(l, new EConstant(l, 5))));
         SSubEachIterable node = new SSubEachIterable(l, v, e, b);