Fix boxing.
This commit is contained in:
parent
c0eb813e10
commit
2b793c1e06
|
@ -33,6 +33,12 @@ import java.util.ArrayList;
|
||||||
import java.util.Deque;
|
import java.util.Deque;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.elasticsearch.painless.WriterConstants.BOOLEAN_OBJECT;
|
||||||
|
import static org.elasticsearch.painless.WriterConstants.BOOLEAN_VALUE_OF;
|
||||||
|
import static org.elasticsearch.painless.WriterConstants.BYTE_OBJECT;
|
||||||
|
import static org.elasticsearch.painless.WriterConstants.BYTE_VALUE_OF;
|
||||||
|
import static org.elasticsearch.painless.WriterConstants.CHARACTER_OBJECT;
|
||||||
|
import static org.elasticsearch.painless.WriterConstants.CHARACTER_VALUE_OF;
|
||||||
import static org.elasticsearch.painless.WriterConstants.CHAR_TO_STRING;
|
import static org.elasticsearch.painless.WriterConstants.CHAR_TO_STRING;
|
||||||
import static org.elasticsearch.painless.WriterConstants.DEF_ADD_CALL;
|
import static org.elasticsearch.painless.WriterConstants.DEF_ADD_CALL;
|
||||||
import static org.elasticsearch.painless.WriterConstants.DEF_AND_CALL;
|
import static org.elasticsearch.painless.WriterConstants.DEF_AND_CALL;
|
||||||
|
@ -61,9 +67,19 @@ import static org.elasticsearch.painless.WriterConstants.DEF_TO_SHORT_IMPLICIT;
|
||||||
import static org.elasticsearch.painless.WriterConstants.DEF_UTIL_TYPE;
|
import static org.elasticsearch.painless.WriterConstants.DEF_UTIL_TYPE;
|
||||||
import static org.elasticsearch.painless.WriterConstants.DEF_USH_CALL;
|
import static org.elasticsearch.painless.WriterConstants.DEF_USH_CALL;
|
||||||
import static org.elasticsearch.painless.WriterConstants.DEF_XOR_CALL;
|
import static org.elasticsearch.painless.WriterConstants.DEF_XOR_CALL;
|
||||||
|
import static org.elasticsearch.painless.WriterConstants.DOUBLE_OBJECT;
|
||||||
|
import static org.elasticsearch.painless.WriterConstants.DOUBLE_VALUE_OF;
|
||||||
|
import static org.elasticsearch.painless.WriterConstants.FLOAT_OBJECT;
|
||||||
|
import static org.elasticsearch.painless.WriterConstants.FLOAT_VALUE_OF;
|
||||||
import static org.elasticsearch.painless.WriterConstants.INDY_STRING_CONCAT_BOOTSTRAP_HANDLE;
|
import static org.elasticsearch.painless.WriterConstants.INDY_STRING_CONCAT_BOOTSTRAP_HANDLE;
|
||||||
|
import static org.elasticsearch.painless.WriterConstants.INTEGER_OBJECT;
|
||||||
|
import static org.elasticsearch.painless.WriterConstants.INTEGER_VALUE_OF;
|
||||||
|
import static org.elasticsearch.painless.WriterConstants.LONG_OBJECT;
|
||||||
|
import static org.elasticsearch.painless.WriterConstants.LONG_VALUE_OF;
|
||||||
import static org.elasticsearch.painless.WriterConstants.MAX_INDY_STRING_CONCAT_ARGS;
|
import static org.elasticsearch.painless.WriterConstants.MAX_INDY_STRING_CONCAT_ARGS;
|
||||||
import static org.elasticsearch.painless.WriterConstants.PAINLESS_ERROR_TYPE;
|
import static org.elasticsearch.painless.WriterConstants.PAINLESS_ERROR_TYPE;
|
||||||
|
import static org.elasticsearch.painless.WriterConstants.SHORT_OBJECT;
|
||||||
|
import static org.elasticsearch.painless.WriterConstants.SHORT_VALUE_OF;
|
||||||
import static org.elasticsearch.painless.WriterConstants.STRINGBUILDER_APPEND_BOOLEAN;
|
import static org.elasticsearch.painless.WriterConstants.STRINGBUILDER_APPEND_BOOLEAN;
|
||||||
import static org.elasticsearch.painless.WriterConstants.STRINGBUILDER_APPEND_CHAR;
|
import static org.elasticsearch.painless.WriterConstants.STRINGBUILDER_APPEND_CHAR;
|
||||||
import static org.elasticsearch.painless.WriterConstants.STRINGBUILDER_APPEND_DOUBLE;
|
import static org.elasticsearch.painless.WriterConstants.STRINGBUILDER_APPEND_DOUBLE;
|
||||||
|
@ -184,6 +200,22 @@ public final class MethodWriter extends GeneratorAdapter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void box(final org.objectweb.asm.Type type) {
|
||||||
|
switch (type.getSort()) {
|
||||||
|
case org.objectweb.asm.Type.BOOLEAN: invokeStatic(BOOLEAN_OBJECT , BOOLEAN_VALUE_OF); break;
|
||||||
|
case org.objectweb.asm.Type.BYTE: invokeStatic(BYTE_OBJECT , BYTE_VALUE_OF); break;
|
||||||
|
case org.objectweb.asm.Type.SHORT: invokeStatic(SHORT_OBJECT , SHORT_VALUE_OF); break;
|
||||||
|
case org.objectweb.asm.Type.CHAR: invokeStatic(CHARACTER_OBJECT, CHARACTER_VALUE_OF); break;
|
||||||
|
case org.objectweb.asm.Type.INT: invokeStatic(INTEGER_OBJECT , INTEGER_VALUE_OF); break;
|
||||||
|
case org.objectweb.asm.Type.LONG: invokeStatic(LONG_OBJECT , LONG_VALUE_OF); break;
|
||||||
|
case org.objectweb.asm.Type.FLOAT: invokeStatic(FLOAT_OBJECT , FLOAT_VALUE_OF); break;
|
||||||
|
case org.objectweb.asm.Type.DOUBLE: invokeStatic(DOUBLE_OBJECT , DOUBLE_VALUE_OF); break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Illegal tree structure.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void writeBranch(final Label tru, final Label fals) {
|
public void writeBranch(final Label tru, final Label fals) {
|
||||||
if (tru != null) {
|
if (tru != null) {
|
||||||
visitJumpInsn(Opcodes.IFNE, tru);
|
visitJumpInsn(Opcodes.IFNE, tru);
|
||||||
|
|
|
@ -138,6 +138,25 @@ public final class WriterConstants {
|
||||||
public final static Method CHECKEQUALS =
|
public final static Method CHECKEQUALS =
|
||||||
getAsmMethod(boolean.class, "checkEquals", Object.class, Object.class);
|
getAsmMethod(boolean.class, "checkEquals", Object.class, Object.class);
|
||||||
|
|
||||||
|
public final static Type BOOLEAN_OBJECT = Type.getType(Boolean.class);
|
||||||
|
public final static Type BYTE_OBJECT = Type.getType(Byte.class);
|
||||||
|
public final static Type SHORT_OBJECT = Type.getType(Short.class);
|
||||||
|
public final static Type CHARACTER_OBJECT = Type.getType(Character.class);
|
||||||
|
public final static Type INTEGER_OBJECT = Type.getType(Integer.class);
|
||||||
|
public final static Type LONG_OBJECT = Type.getType(Long.class);
|
||||||
|
public final static Type FLOAT_OBJECT = Type.getType(Float.class);
|
||||||
|
public final static Type DOUBLE_OBJECT = Type.getType(Double.class);
|
||||||
|
|
||||||
|
/** box methods to replace the GeneratorAdapter's slow way of boxing */
|
||||||
|
public final static Method BOOLEAN_VALUE_OF = getAsmMethod(Boolean.class , "valueOf", boolean.class);
|
||||||
|
public final static Method BYTE_VALUE_OF = getAsmMethod(Byte.class , "valueOf", byte.class);
|
||||||
|
public final static Method SHORT_VALUE_OF = getAsmMethod(Short.class , "valueOf", short.class);
|
||||||
|
public final static Method CHARACTER_VALUE_OF = getAsmMethod(Character.class, "valueOf", char.class);
|
||||||
|
public final static Method INTEGER_VALUE_OF = getAsmMethod(Integer.class , "valueOf", int.class);
|
||||||
|
public final static Method LONG_VALUE_OF = getAsmMethod(Long.class , "valueOf", long.class);
|
||||||
|
public final static Method FLOAT_VALUE_OF = getAsmMethod(Float.class , "valueOf", float.class);
|
||||||
|
public final static Method DOUBLE_VALUE_OF = getAsmMethod(Double.class , "valueOf", double.class);
|
||||||
|
|
||||||
private static Method getAsmMethod(final Class<?> rtype, final String name, final Class<?>... ptypes) {
|
private static Method getAsmMethod(final Class<?> rtype, final String name, final Class<?>... ptypes) {
|
||||||
return new Method(name, MethodType.methodType(rtype, ptypes).toMethodDescriptorString());
|
return new Method(name, MethodType.methodType(rtype, ptypes).toMethodDescriptorString());
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,39 +45,49 @@ public class BasicAPITests extends ScriptTestCase {
|
||||||
assertEquals(3, exec("Map x = new HashMap(); x.put(2, 2); x.put(3, 3); x.put(-2, -2); Iterator y = x.values().iterator(); " +
|
assertEquals(3, exec("Map x = new HashMap(); x.put(2, 2); x.put(3, 3); x.put(-2, -2); Iterator y = x.values().iterator(); " +
|
||||||
"int total = 0; while (y.hasNext()) total += (int)y.next(); return total;"));
|
"int total = 0; while (y.hasNext()) total += (int)y.next(); return total;"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Test loads and stores with a map */
|
/** Test loads and stores with a map */
|
||||||
public void testMapLoadStore() {
|
public void testMapLoadStore() {
|
||||||
assertEquals(5, exec("def x = new HashMap(); x.abc = 5; return x.abc;"));
|
assertEquals(5, exec("def x = new HashMap(); x.abc = 5; return x.abc;"));
|
||||||
assertEquals(5, exec("def x = new HashMap(); x['abc'] = 5; return x['abc'];"));
|
assertEquals(5, exec("def x = new HashMap(); x['abc'] = 5; return x['abc'];"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Test loads and stores with a list */
|
/** Test loads and stores with a list */
|
||||||
public void testListLoadStore() {
|
public void testListLoadStore() {
|
||||||
assertEquals(5, exec("def x = new ArrayList(); x.add(3); x.0 = 5; return x.0;"));
|
assertEquals(5, exec("def x = new ArrayList(); x.add(3); x.0 = 5; return x.0;"));
|
||||||
assertEquals(5, exec("def x = new ArrayList(); x.add(3); x[0] = 5; return x[0];"));
|
assertEquals(5, exec("def x = new ArrayList(); x.add(3); x[0] = 5; return x[0];"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Test shortcut for getters with isXXXX */
|
/** Test shortcut for getters with isXXXX */
|
||||||
public void testListEmpty() {
|
public void testListEmpty() {
|
||||||
assertEquals(true, exec("def x = new ArrayList(); return x.empty;"));
|
assertEquals(true, exec("def x = new ArrayList(); return x.empty;"));
|
||||||
assertEquals(true, exec("def x = new HashMap(); return x.empty;"));
|
assertEquals(true, exec("def x = new HashMap(); return x.empty;"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Test list method invocation */
|
/** Test list method invocation */
|
||||||
public void testListGet() {
|
public void testListGet() {
|
||||||
assertEquals(5, exec("def x = new ArrayList(); x.add(5); return x.get(0);"));
|
assertEquals(5, exec("def x = new ArrayList(); x.add(5); return x.get(0);"));
|
||||||
assertEquals(5, exec("def x = new ArrayList(); x.add(5); def index = 0; return x.get(index);"));
|
assertEquals(5, exec("def x = new ArrayList(); x.add(5); def index = 0; return x.get(index);"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testListAsArray() {
|
public void testListAsArray() {
|
||||||
assertEquals(1, exec("def x = new ArrayList(); x.add(5); return x.length"));
|
assertEquals(1, exec("def x = new ArrayList(); x.add(5); return x.length"));
|
||||||
assertEquals(5, exec("def x = new ArrayList(); x.add(5); return x[0]"));
|
assertEquals(5, exec("def x = new ArrayList(); x.add(5); return x[0]"));
|
||||||
assertEquals(1, exec("List x = new ArrayList(); x.add('Hallo'); return x.length"));
|
assertEquals(1, exec("List x = new ArrayList(); x.add('Hallo'); return x.length"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testDefAssignments() {
|
public void testDefAssignments() {
|
||||||
assertEquals(2, exec("int x; def y = 2.0; x = (int)y;"));
|
assertEquals(2, exec("int x; def y = 2.0; x = (int)y;"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testInternalBoxing() {
|
||||||
|
assertBytecodeExists("def x = true", "INVOKESTATIC java/lang/Boolean.valueOf (Z)Ljava/lang/Boolean;");
|
||||||
|
assertBytecodeExists("def x = (byte)1", "INVOKESTATIC java/lang/Byte.valueOf (B)Ljava/lang/Byte;");
|
||||||
|
assertBytecodeExists("def x = (short)1", "INVOKESTATIC java/lang/Short.valueOf (S)Ljava/lang/Short;");
|
||||||
|
assertBytecodeExists("def x = (char)1", "INVOKESTATIC java/lang/Character.valueOf (C)Ljava/lang/Character;");
|
||||||
|
assertBytecodeExists("def x = 1", "INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;");
|
||||||
|
assertBytecodeExists("def x = 1L", "INVOKESTATIC java/lang/Long.valueOf (J)Ljava/lang/Long;");
|
||||||
|
assertBytecodeExists("def x = 1F", "INVOKESTATIC java/lang/Float.valueOf (F)Ljava/lang/Float;");
|
||||||
|
assertBytecodeExists("def x = 1D", "INVOKESTATIC java/lang/Double.valueOf (D)Ljava/lang/Double;");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -799,7 +799,7 @@ public class DefOperationTests extends ScriptTestCase {
|
||||||
assertEquals(false, exec("def x = (byte)7; def y = (int)7; return x === y"));
|
assertEquals(false, exec("def x = (byte)7; def y = (int)7; return x === y"));
|
||||||
assertEquals(false, exec("def x = (short)6; def y = (int)6; return x === y"));
|
assertEquals(false, exec("def x = (short)6; def y = (int)6; return x === y"));
|
||||||
assertEquals(false, exec("def x = (char)5; def y = (int)5; return x === y"));
|
assertEquals(false, exec("def x = (char)5; def y = (int)5; return x === y"));
|
||||||
assertEquals(false, exec("def x = (int)4; def y = (int)4; return x === y"));
|
assertEquals(true, exec("def x = (int)4; def y = (int)4; return x === y"));
|
||||||
assertEquals(false, exec("def x = (long)5; def y = (int)3; return x === y"));
|
assertEquals(false, exec("def x = (long)5; def y = (int)3; return x === y"));
|
||||||
assertEquals(false, exec("def x = (float)6; def y = (int)2; return x === y"));
|
assertEquals(false, exec("def x = (float)6; def y = (int)2; return x === y"));
|
||||||
assertEquals(false, exec("def x = (double)7; def y = (int)1; return x === y"));
|
assertEquals(false, exec("def x = (double)7; def y = (int)1; return x === y"));
|
||||||
|
@ -837,7 +837,7 @@ public class DefOperationTests extends ScriptTestCase {
|
||||||
assertEquals(true, exec("def x = (byte)7; def y = (int)7; return x !== y"));
|
assertEquals(true, exec("def x = (byte)7; def y = (int)7; return x !== y"));
|
||||||
assertEquals(true, exec("def x = (short)6; def y = (int)6; return x !== y"));
|
assertEquals(true, exec("def x = (short)6; def y = (int)6; return x !== y"));
|
||||||
assertEquals(true, exec("def x = (char)5; def y = (int)5; return x !== y"));
|
assertEquals(true, exec("def x = (char)5; def y = (int)5; return x !== y"));
|
||||||
assertEquals(true, exec("def x = (int)4; def y = (int)4; return x !== y"));
|
assertEquals(false, exec("def x = (int)4; def y = (int)4; return x !== y"));
|
||||||
assertEquals(true, exec("def x = (long)5; def y = (int)3; return x !== y"));
|
assertEquals(true, exec("def x = (long)5; def y = (int)3; return x !== y"));
|
||||||
assertEquals(true, exec("def x = (float)6; def y = (int)2; return x !== y"));
|
assertEquals(true, exec("def x = (float)6; def y = (int)2; return x !== y"));
|
||||||
assertEquals(true, exec("def x = (double)7; def y = (int)1; return x !== y"));
|
assertEquals(true, exec("def x = (double)7; def y = (int)1; return x !== y"));
|
||||||
|
|
|
@ -118,7 +118,7 @@ public class EqualsTests extends ScriptTestCase {
|
||||||
public void testBranchEquals() {
|
public void testBranchEquals() {
|
||||||
assertEquals(0, exec("def a = (char)'a'; def b = (char)'b'; if (a == b) return 1; else return 0;"));
|
assertEquals(0, exec("def a = (char)'a'; def b = (char)'b'; if (a == b) return 1; else return 0;"));
|
||||||
assertEquals(1, exec("def a = (char)'a'; def b = (char)'a'; if (a == b) return 1; else return 0;"));
|
assertEquals(1, exec("def a = (char)'a'; def b = (char)'a'; if (a == b) return 1; else return 0;"));
|
||||||
assertEquals(0, exec("def a = 1; def b = 1; if (a === b) return 1; else return 0;"));
|
assertEquals(1, exec("def a = 1; def b = 1; if (a === b) return 1; else return 0;"));
|
||||||
assertEquals(0, exec("def a = (char)'a'; def b = (char)'a'; if (a === b) return 1; else return 0;"));
|
assertEquals(0, exec("def a = (char)'a'; def b = (char)'a'; if (a === b) return 1; else return 0;"));
|
||||||
assertEquals(1, exec("def a = (char)'a'; Object b = a; if (a === b) return 1; else return 0;"));
|
assertEquals(1, exec("def a = (char)'a'; Object b = a; if (a === b) return 1; else return 0;"));
|
||||||
assertEquals(1, exec("def a = 1; Number b = a; Number c = a; if (c === b) return 1; else return 0;"));
|
assertEquals(1, exec("def a = 1; Number b = a; Number c = a; if (c === b) return 1; else return 0;"));
|
||||||
|
@ -128,7 +128,7 @@ public class EqualsTests extends ScriptTestCase {
|
||||||
public void testBranchNotEquals() {
|
public void testBranchNotEquals() {
|
||||||
assertEquals(1, exec("def a = (char)'a'; def b = (char)'b'; if (a != b) return 1; else return 0;"));
|
assertEquals(1, exec("def a = (char)'a'; def b = (char)'b'; if (a != b) return 1; else return 0;"));
|
||||||
assertEquals(0, exec("def a = (char)'a'; def b = (char)'a'; if (a != b) return 1; else return 0;"));
|
assertEquals(0, exec("def a = (char)'a'; def b = (char)'a'; if (a != b) return 1; else return 0;"));
|
||||||
assertEquals(1, exec("def a = 1; def b = 1; if (a !== b) return 1; else return 0;"));
|
assertEquals(0, exec("def a = 1; def b = 1; if (a !== b) return 1; else return 0;"));
|
||||||
assertEquals(1, exec("def a = (char)'a'; def b = (char)'a'; if (a !== b) return 1; else return 0;"));
|
assertEquals(1, exec("def a = (char)'a'; def b = (char)'a'; if (a !== b) return 1; else return 0;"));
|
||||||
assertEquals(0, exec("def a = (char)'a'; Object b = a; if (a !== b) return 1; else return 0;"));
|
assertEquals(0, exec("def a = (char)'a'; Object b = a; if (a !== b) return 1; else return 0;"));
|
||||||
assertEquals(0, exec("def a = 1; Number b = a; Number c = a; if (c !== b) return 1; else return 0;"));
|
assertEquals(0, exec("def a = 1; Number b = a; Number c = a; if (c !== b) return 1; else return 0;"));
|
||||||
|
|
Loading…
Reference in New Issue