Merge pull request #18338 from uschindler/painless_arrayindextype

painless: build descriptor of array and field load/store in code
This commit is contained in:
Jack Conradson 2016-05-13 14:25:40 -07:00
commit 8f82fa9a58
5 changed files with 21 additions and 22 deletions

View File

@ -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);

View File

@ -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 });
}
}

View File

@ -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 });
}

View File

@ -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 });
}
}

View File

@ -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'];");
});
}
}