Browse Source

Merge pull request #18338 from uschindler/painless_arrayindextype

painless: build descriptor of array and field load/store in code
Jack Conradson 9 years ago
parent
commit
8f82fa9a58

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

@@ -61,15 +61,6 @@ public final class WriterConstants {
         new Handle(Opcodes.H_INVOKESTATIC, Type.getInternalName(DefBootstrap.class),
             "bootstrap", DEF_BOOTSTRAP_TYPE.toMethodDescriptorString());
 
-    public final static String DEF_DYNAMIC_LOAD_FIELD_DESC =
-        MethodType.methodType(Object.class, Object.class).toMethodDescriptorString();
-    public final static String DEF_DYNAMIC_STORE_FIELD_DESC =
-        MethodType.methodType(void.class, Object.class, Object.class).toMethodDescriptorString();
-    public final static String DEF_DYNAMIC_ARRAY_LOAD_DESC =
-        MethodType.methodType(Object.class, Object.class, Object.class).toMethodDescriptorString();
-    public final static String DEF_DYNAMIC_ARRAY_STORE_DESC =
-        MethodType.methodType(void.class, Object.class, Object.class, Object.class).toMethodDescriptorString();
-
     public final static Method DEF_NOT_CALL = getAsmMethod(Object.class, "not", Object.class);
     public final static Method DEF_NEG_CALL = getAsmMethod(Object.class, "neg", Object.class);
     public final static Method DEF_MUL_CALL = getAsmMethod(Object.class, "mul", Object.class, Object.class);

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

@@ -23,11 +23,10 @@ import org.elasticsearch.painless.CompilerSettings;
 import org.elasticsearch.painless.Definition;
 import org.elasticsearch.painless.DefBootstrap;
 import org.elasticsearch.painless.Variables;
+import org.objectweb.asm.Type;
 import org.objectweb.asm.commons.GeneratorAdapter;
 
 import static org.elasticsearch.painless.WriterConstants.DEF_BOOTSTRAP_HANDLE;
-import static org.elasticsearch.painless.WriterConstants.DEF_DYNAMIC_ARRAY_LOAD_DESC;
-import static org.elasticsearch.painless.WriterConstants.DEF_DYNAMIC_ARRAY_STORE_DESC;
 
 /**
  * Represents an array load/store or shortcut on a def type.  (Internal only.)
@@ -45,8 +44,8 @@ final class LDefArray extends ALink {
 
     @Override
     ALink analyze(final CompilerSettings settings, final Definition definition, final Variables variables) {
-        index.expected = definition.objectType;
         index.analyze(settings, definition, variables);
+        index.expected = index.actual;
         index = index.cast(settings, definition, variables);
 
         after = definition.defType;
@@ -61,14 +60,16 @@ final class LDefArray extends ALink {
 
     @Override
     void load(final CompilerSettings settings, final Definition definition, final GeneratorAdapter adapter) {
+        final String desc = Type.getMethodDescriptor(after.type, definition.defType.type, index.actual.type);
         adapter.visitInvokeDynamicInsn(
-            "arrayLoad", DEF_DYNAMIC_ARRAY_LOAD_DESC, DEF_BOOTSTRAP_HANDLE, new Object[] { DefBootstrap.ARRAY_LOAD });
-
+            "arrayLoad", desc, DEF_BOOTSTRAP_HANDLE, new Object[] { DefBootstrap.ARRAY_LOAD });
     }
 
     @Override
     void store(final CompilerSettings settings, final Definition definition, final GeneratorAdapter adapter) {
+        final String desc = Type.getMethodDescriptor(definition.voidType.type, definition.defType.type,
+            index.actual.type, definition.defType.type);
         adapter.visitInvokeDynamicInsn(
-            "arrayStore", DEF_DYNAMIC_ARRAY_STORE_DESC, DEF_BOOTSTRAP_HANDLE, new Object[] { DefBootstrap.ARRAY_STORE });
+            "arrayStore", desc, DEF_BOOTSTRAP_HANDLE, new Object[] { DefBootstrap.ARRAY_STORE });
     }
 }

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

@@ -82,7 +82,7 @@ final class LDefCall extends ALink {
 
         signature.append(')');
         // return value
-        signature.append(definition.defType.type.getDescriptor());
+        signature.append(after.type.getDescriptor());
 
         adapter.visitInvokeDynamicInsn(name, signature.toString(), DEF_BOOTSTRAP_HANDLE, new Object[] { DefBootstrap.METHOD_CALL });
     }

+ 5 - 4
modules/lang-painless/src/main/java/org/elasticsearch/painless/node/LDefField.java

@@ -23,11 +23,10 @@ import org.elasticsearch.painless.CompilerSettings;
 import org.elasticsearch.painless.Definition;
 import org.elasticsearch.painless.DefBootstrap;
 import org.elasticsearch.painless.Variables;
+import org.objectweb.asm.Type;
 import org.objectweb.asm.commons.GeneratorAdapter;
 
 import static org.elasticsearch.painless.WriterConstants.DEF_BOOTSTRAP_HANDLE;
-import static org.elasticsearch.painless.WriterConstants.DEF_DYNAMIC_LOAD_FIELD_DESC;
-import static org.elasticsearch.painless.WriterConstants.DEF_DYNAMIC_STORE_FIELD_DESC;
 
 /**
  * Represents a field load/store or shortcut on a def type.  (Internal only.)
@@ -57,11 +56,13 @@ final class LDefField extends ALink {
 
     @Override
     void load(final CompilerSettings settings, final Definition definition, final GeneratorAdapter adapter) {
-        adapter.visitInvokeDynamicInsn(value, DEF_DYNAMIC_LOAD_FIELD_DESC, DEF_BOOTSTRAP_HANDLE, new Object[] { DefBootstrap.LOAD });
+        final String desc = Type.getMethodDescriptor(after.type, definition.defType.type);
+        adapter.visitInvokeDynamicInsn(value, desc, DEF_BOOTSTRAP_HANDLE, new Object[] { DefBootstrap.LOAD });
     }
 
     @Override
     void store(final CompilerSettings settings, final Definition definition, final GeneratorAdapter adapter) {
-        adapter.visitInvokeDynamicInsn(value, DEF_DYNAMIC_STORE_FIELD_DESC, DEF_BOOTSTRAP_HANDLE, new Object[] { DefBootstrap.STORE });
+        final String desc = Type.getMethodDescriptor(definition.voidType.type, definition.defType.type, definition.defType.type);
+        adapter.visitInvokeDynamicInsn(value, desc, DEF_BOOTSTRAP_HANDLE, new Object[] { DefBootstrap.STORE });
     }
 }

+ 8 - 2
modules/lang-painless/src/test/java/org/elasticsearch/painless/WhenThingsGoWrongTests.java

@@ -175,9 +175,15 @@ public class WhenThingsGoWrongTests extends ScriptTestCase {
         });
     }
 
-    public void testDynamicWrongArgs() {
+    public void testDynamicArrayWrongIndex() {
         expectThrows(WrongMethodTypeException.class, () -> {
-            exec("def x = new ArrayList(); return x.get('bogus');");
+            exec("def x = new long[1]; x[0]=1; return x['bogus'];");
+        });
+    }
+
+    public void testDynamicListWrongIndex() {
+        expectThrows(WrongMethodTypeException.class, () -> {
+            exec("def x = new ArrayList(); x.add('foo'); return x['bogus'];");
         });
     }
 }