Merge pull request #18849 from rmuir/give_indy_ops_types
Remove casts and boxing for dynamic math
This commit is contained in:
commit
e4dc469e58
|
@ -262,6 +262,51 @@ public final class MethodWriter extends GeneratorAdapter {
|
|||
}
|
||||
}
|
||||
|
||||
/** Writes a dynamic binary instruction: returnType, lhs, and rhs can be different */
|
||||
public void writeDynamicBinaryInstruction(Location location, Type returnType, Type lhs, Type rhs, Operation operation) {
|
||||
org.objectweb.asm.Type methodType = org.objectweb.asm.Type.getMethodType(returnType.type, lhs.type, rhs.type);
|
||||
String descriptor = methodType.getDescriptor();
|
||||
|
||||
switch (operation) {
|
||||
case MUL:
|
||||
invokeDynamic("mul", descriptor, DEF_BOOTSTRAP_HANDLE, DefBootstrap.BINARY_OPERATOR);
|
||||
break;
|
||||
case DIV:
|
||||
invokeDynamic("div", descriptor, DEF_BOOTSTRAP_HANDLE, DefBootstrap.BINARY_OPERATOR);
|
||||
break;
|
||||
case REM:
|
||||
invokeDynamic("rem", descriptor, DEF_BOOTSTRAP_HANDLE, DefBootstrap.BINARY_OPERATOR);
|
||||
break;
|
||||
case ADD:
|
||||
invokeDynamic("add", descriptor, DEF_BOOTSTRAP_HANDLE, DefBootstrap.BINARY_OPERATOR);
|
||||
break;
|
||||
case SUB:
|
||||
invokeDynamic("sub", descriptor, DEF_BOOTSTRAP_HANDLE, DefBootstrap.BINARY_OPERATOR);
|
||||
break;
|
||||
case LSH:
|
||||
invokeDynamic("lsh", descriptor, DEF_BOOTSTRAP_HANDLE, DefBootstrap.SHIFT_OPERATOR);
|
||||
break;
|
||||
case USH:
|
||||
invokeDynamic("ush", descriptor, DEF_BOOTSTRAP_HANDLE, DefBootstrap.SHIFT_OPERATOR);
|
||||
break;
|
||||
case RSH:
|
||||
invokeDynamic("rsh", descriptor, DEF_BOOTSTRAP_HANDLE, DefBootstrap.SHIFT_OPERATOR);
|
||||
break;
|
||||
case BWAND:
|
||||
invokeDynamic("and", descriptor, DEF_BOOTSTRAP_HANDLE, DefBootstrap.BINARY_OPERATOR);
|
||||
break;
|
||||
case XOR:
|
||||
invokeDynamic("xor", descriptor, DEF_BOOTSTRAP_HANDLE, DefBootstrap.BINARY_OPERATOR);
|
||||
break;
|
||||
case BWOR:
|
||||
invokeDynamic("or", descriptor, DEF_BOOTSTRAP_HANDLE, DefBootstrap.BINARY_OPERATOR);
|
||||
break;
|
||||
default:
|
||||
throw location.createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
/** Writes a static binary instruction */
|
||||
public void writeBinaryInstruction(Location location, Type type, Operation operation) {
|
||||
final Sort sort = type.sort;
|
||||
|
||||
|
@ -272,64 +317,20 @@ public final class MethodWriter extends GeneratorAdapter {
|
|||
throw location.createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
if (sort == Sort.DEF) {
|
||||
// XXX: move this out, so we can populate descriptor with what we really have (instead of casts/boxing!)
|
||||
org.objectweb.asm.Type objectType = org.objectweb.asm.Type.getType(Object.class);
|
||||
org.objectweb.asm.Type descriptor = org.objectweb.asm.Type.getMethodType(objectType, objectType, objectType);
|
||||
|
||||
switch (operation) {
|
||||
case MUL:
|
||||
invokeDynamic("mul", descriptor.getDescriptor(), DEF_BOOTSTRAP_HANDLE, DefBootstrap.BINARY_OPERATOR);
|
||||
break;
|
||||
case DIV:
|
||||
invokeDynamic("div", descriptor.getDescriptor(), DEF_BOOTSTRAP_HANDLE, DefBootstrap.BINARY_OPERATOR);
|
||||
break;
|
||||
case REM:
|
||||
invokeDynamic("rem", descriptor.getDescriptor(), DEF_BOOTSTRAP_HANDLE, DefBootstrap.BINARY_OPERATOR);
|
||||
break;
|
||||
case ADD:
|
||||
invokeDynamic("add", descriptor.getDescriptor(), DEF_BOOTSTRAP_HANDLE, DefBootstrap.BINARY_OPERATOR);
|
||||
break;
|
||||
case SUB:
|
||||
invokeDynamic("sub", descriptor.getDescriptor(), DEF_BOOTSTRAP_HANDLE, DefBootstrap.BINARY_OPERATOR);
|
||||
break;
|
||||
case LSH:
|
||||
invokeDynamic("lsh", descriptor.getDescriptor(), DEF_BOOTSTRAP_HANDLE, DefBootstrap.SHIFT_OPERATOR);
|
||||
break;
|
||||
case USH:
|
||||
invokeDynamic("ush", descriptor.getDescriptor(), DEF_BOOTSTRAP_HANDLE, DefBootstrap.SHIFT_OPERATOR);
|
||||
break;
|
||||
case RSH:
|
||||
invokeDynamic("rsh", descriptor.getDescriptor(), DEF_BOOTSTRAP_HANDLE, DefBootstrap.SHIFT_OPERATOR);
|
||||
break;
|
||||
case BWAND:
|
||||
invokeDynamic("and", descriptor.getDescriptor(), DEF_BOOTSTRAP_HANDLE, DefBootstrap.BINARY_OPERATOR);
|
||||
break;
|
||||
case XOR:
|
||||
invokeDynamic("xor", descriptor.getDescriptor(), DEF_BOOTSTRAP_HANDLE, DefBootstrap.BINARY_OPERATOR);
|
||||
break;
|
||||
case BWOR:
|
||||
invokeDynamic("or", descriptor.getDescriptor(), DEF_BOOTSTRAP_HANDLE, DefBootstrap.BINARY_OPERATOR);
|
||||
break;
|
||||
default:
|
||||
throw location.createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
} else {
|
||||
switch (operation) {
|
||||
case MUL: math(GeneratorAdapter.MUL, type.type); break;
|
||||
case DIV: math(GeneratorAdapter.DIV, type.type); break;
|
||||
case REM: math(GeneratorAdapter.REM, type.type); break;
|
||||
case ADD: math(GeneratorAdapter.ADD, type.type); break;
|
||||
case SUB: math(GeneratorAdapter.SUB, type.type); break;
|
||||
case LSH: math(GeneratorAdapter.SHL, type.type); break;
|
||||
case USH: math(GeneratorAdapter.USHR, type.type); break;
|
||||
case RSH: math(GeneratorAdapter.SHR, type.type); break;
|
||||
case BWAND: math(GeneratorAdapter.AND, type.type); break;
|
||||
case XOR: math(GeneratorAdapter.XOR, type.type); break;
|
||||
case BWOR: math(GeneratorAdapter.OR, type.type); break;
|
||||
default:
|
||||
throw location.createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
switch (operation) {
|
||||
case MUL: math(GeneratorAdapter.MUL, type.type); break;
|
||||
case DIV: math(GeneratorAdapter.DIV, type.type); break;
|
||||
case REM: math(GeneratorAdapter.REM, type.type); break;
|
||||
case ADD: math(GeneratorAdapter.ADD, type.type); break;
|
||||
case SUB: math(GeneratorAdapter.SUB, type.type); break;
|
||||
case LSH: math(GeneratorAdapter.SHL, type.type); break;
|
||||
case USH: math(GeneratorAdapter.USHR, type.type); break;
|
||||
case RSH: math(GeneratorAdapter.SHR, type.type); break;
|
||||
case BWAND: math(GeneratorAdapter.AND, type.type); break;
|
||||
case XOR: math(GeneratorAdapter.XOR, type.type); break;
|
||||
case BWOR: math(GeneratorAdapter.OR, type.type); break;
|
||||
default:
|
||||
throw location.createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,8 @@ public final class EBinary extends AExpression {
|
|||
final Operation operation;
|
||||
AExpression left;
|
||||
AExpression right;
|
||||
Type promote; // promoted type
|
||||
Type shiftDistance; // for shifts, the RHS is promoted independently
|
||||
|
||||
boolean cat = false;
|
||||
|
||||
|
@ -80,15 +82,25 @@ public final class EBinary extends AExpression {
|
|||
left.analyze(variables);
|
||||
right.analyze(variables);
|
||||
|
||||
Type promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||
promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||
|
||||
if (promote == null) {
|
||||
throw createError(new ClassCastException("Cannot apply multiply [*] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
left.expected = promote;
|
||||
right.expected = promote;
|
||||
actual = promote;
|
||||
|
||||
if (promote.sort == Sort.DEF) {
|
||||
left.expected = left.actual;
|
||||
right.expected = right.actual;
|
||||
if (expected != null) {
|
||||
actual = expected;
|
||||
}
|
||||
} else {
|
||||
left.expected = promote;
|
||||
right.expected = promote;
|
||||
}
|
||||
|
||||
left = left.cast(variables);
|
||||
right = right.cast(variables);
|
||||
|
@ -108,23 +120,30 @@ public final class EBinary extends AExpression {
|
|||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
actual = promote;
|
||||
}
|
||||
|
||||
private void analyzeDiv(Locals variables) {
|
||||
left.analyze(variables);
|
||||
right.analyze(variables);
|
||||
|
||||
Type promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||
promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||
|
||||
if (promote == null) {
|
||||
throw createError(new ClassCastException("Cannot apply divide [/] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
left.expected = promote;
|
||||
right.expected = promote;
|
||||
actual = promote;
|
||||
if (promote.sort == Sort.DEF) {
|
||||
left.expected = left.actual;
|
||||
right.expected = right.actual;
|
||||
if (expected != null) {
|
||||
actual = expected;
|
||||
}
|
||||
} else {
|
||||
left.expected = promote;
|
||||
right.expected = promote;
|
||||
}
|
||||
|
||||
left = left.cast(variables);
|
||||
right = right.cast(variables);
|
||||
|
@ -148,23 +167,31 @@ public final class EBinary extends AExpression {
|
|||
throw createError(e);
|
||||
}
|
||||
}
|
||||
|
||||
actual = promote;
|
||||
}
|
||||
|
||||
private void analyzeRem(Locals variables) {
|
||||
left.analyze(variables);
|
||||
right.analyze(variables);
|
||||
|
||||
Type promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||
promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||
|
||||
if (promote == null) {
|
||||
throw createError(new ClassCastException("Cannot apply remainder [%] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
left.expected = promote;
|
||||
right.expected = promote;
|
||||
actual = promote;
|
||||
|
||||
if (promote.sort == Sort.DEF) {
|
||||
left.expected = left.actual;
|
||||
right.expected = right.actual;
|
||||
if (expected != null) {
|
||||
actual = expected;
|
||||
}
|
||||
} else {
|
||||
left.expected = promote;
|
||||
right.expected = promote;
|
||||
}
|
||||
|
||||
left = left.cast(variables);
|
||||
right = right.cast(variables);
|
||||
|
@ -188,15 +215,13 @@ public final class EBinary extends AExpression {
|
|||
throw createError(e);
|
||||
}
|
||||
}
|
||||
|
||||
actual = promote;
|
||||
}
|
||||
|
||||
private void analyzeAdd(Locals variables) {
|
||||
left.analyze(variables);
|
||||
right.analyze(variables);
|
||||
|
||||
Type promote = AnalyzerCaster.promoteAdd(left.actual, right.actual);
|
||||
promote = AnalyzerCaster.promoteAdd(left.actual, right.actual);
|
||||
|
||||
if (promote == null) {
|
||||
throw createError(new ClassCastException("Cannot apply add [+] to types " +
|
||||
|
@ -205,6 +230,8 @@ public final class EBinary extends AExpression {
|
|||
|
||||
Sort sort = promote.sort;
|
||||
|
||||
actual = promote;
|
||||
|
||||
if (sort == Sort.STRING) {
|
||||
left.expected = left.actual;
|
||||
|
||||
|
@ -217,6 +244,12 @@ public final class EBinary extends AExpression {
|
|||
if (right instanceof EBinary && ((EBinary)right).operation == Operation.ADD && right.actual.sort == Sort.STRING) {
|
||||
((EBinary)right).cat = true;
|
||||
}
|
||||
} else if (sort == Sort.DEF) {
|
||||
left.expected = left.actual;
|
||||
right.expected = right.actual;
|
||||
if (expected != null) {
|
||||
actual = expected;
|
||||
}
|
||||
} else {
|
||||
left.expected = promote;
|
||||
right.expected = promote;
|
||||
|
@ -241,22 +274,31 @@ public final class EBinary extends AExpression {
|
|||
}
|
||||
}
|
||||
|
||||
actual = promote;
|
||||
}
|
||||
|
||||
private void analyzeSub(Locals variables) {
|
||||
left.analyze(variables);
|
||||
right.analyze(variables);
|
||||
|
||||
Type promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||
promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||
|
||||
if (promote == null) {
|
||||
throw createError(new ClassCastException("Cannot apply subtract [-] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
left.expected = promote;
|
||||
right.expected = promote;
|
||||
actual = promote;
|
||||
|
||||
if (promote.sort == Sort.DEF) {
|
||||
left.expected = left.actual;
|
||||
right.expected = right.actual;
|
||||
if (expected != null) {
|
||||
actual = expected;
|
||||
}
|
||||
} else {
|
||||
left.expected = promote;
|
||||
right.expected = promote;
|
||||
}
|
||||
|
||||
left = left.cast(variables);
|
||||
right = right.cast(variables);
|
||||
|
@ -276,8 +318,6 @@ public final class EBinary extends AExpression {
|
|||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
actual = promote;
|
||||
}
|
||||
|
||||
private void analyzeLSH(Locals variables) {
|
||||
|
@ -292,12 +332,23 @@ public final class EBinary extends AExpression {
|
|||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
left.expected = lhspromote;
|
||||
if (rhspromote.sort == Sort.LONG) {
|
||||
right.expected = Definition.INT_TYPE;
|
||||
right.explicit = true;
|
||||
actual = promote = lhspromote;
|
||||
shiftDistance = rhspromote;
|
||||
|
||||
if (lhspromote.sort == Sort.DEF || rhspromote.sort == Sort.DEF) {
|
||||
left.expected = left.actual;
|
||||
right.expected = right.actual;
|
||||
if (expected != null) {
|
||||
actual = expected;
|
||||
}
|
||||
} else {
|
||||
right.expected = rhspromote;
|
||||
left.expected = lhspromote;
|
||||
if (rhspromote.sort == Sort.LONG) {
|
||||
right.expected = Definition.INT_TYPE;
|
||||
right.explicit = true;
|
||||
} else {
|
||||
right.expected = rhspromote;
|
||||
}
|
||||
}
|
||||
|
||||
left = left.cast(variables);
|
||||
|
@ -314,8 +365,6 @@ public final class EBinary extends AExpression {
|
|||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
actual = lhspromote;
|
||||
}
|
||||
|
||||
private void analyzeRSH(Locals variables) {
|
||||
|
@ -330,12 +379,23 @@ public final class EBinary extends AExpression {
|
|||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
left.expected = lhspromote;
|
||||
if (rhspromote.sort == Sort.LONG) {
|
||||
right.expected = Definition.INT_TYPE;
|
||||
right.explicit = true;
|
||||
actual = promote = lhspromote;
|
||||
shiftDistance = rhspromote;
|
||||
|
||||
if (lhspromote.sort == Sort.DEF || rhspromote.sort == Sort.DEF) {
|
||||
left.expected = left.actual;
|
||||
right.expected = right.actual;
|
||||
if (expected != null) {
|
||||
actual = expected;
|
||||
}
|
||||
} else {
|
||||
right.expected = rhspromote;
|
||||
left.expected = lhspromote;
|
||||
if (rhspromote.sort == Sort.LONG) {
|
||||
right.expected = Definition.INT_TYPE;
|
||||
right.explicit = true;
|
||||
} else {
|
||||
right.expected = rhspromote;
|
||||
}
|
||||
}
|
||||
|
||||
left = left.cast(variables);
|
||||
|
@ -352,8 +412,6 @@ public final class EBinary extends AExpression {
|
|||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
actual = lhspromote;
|
||||
}
|
||||
|
||||
private void analyzeUSH(Locals variables) {
|
||||
|
@ -363,17 +421,28 @@ public final class EBinary extends AExpression {
|
|||
Type lhspromote = AnalyzerCaster.promoteNumeric(left.actual, false);
|
||||
Type rhspromote = AnalyzerCaster.promoteNumeric(right.actual, false);
|
||||
|
||||
actual = promote = lhspromote;
|
||||
shiftDistance = rhspromote;
|
||||
|
||||
if (lhspromote == null || rhspromote == null) {
|
||||
throw createError(new ClassCastException("Cannot apply unsigned shift [>>>] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
left.expected = lhspromote;
|
||||
if (rhspromote.sort == Sort.LONG) {
|
||||
right.expected = Definition.INT_TYPE;
|
||||
right.explicit = true;
|
||||
if (lhspromote.sort == Sort.DEF || rhspromote.sort == Sort.DEF) {
|
||||
left.expected = left.actual;
|
||||
right.expected = right.actual;
|
||||
if (expected != null) {
|
||||
actual = expected;
|
||||
}
|
||||
} else {
|
||||
right.expected = rhspromote;
|
||||
left.expected = lhspromote;
|
||||
if (rhspromote.sort == Sort.LONG) {
|
||||
right.expected = Definition.INT_TYPE;
|
||||
right.explicit = true;
|
||||
} else {
|
||||
right.expected = rhspromote;
|
||||
}
|
||||
}
|
||||
|
||||
left = left.cast(variables);
|
||||
|
@ -390,23 +459,31 @@ public final class EBinary extends AExpression {
|
|||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
actual = lhspromote;
|
||||
}
|
||||
|
||||
private void analyzeBWAnd(Locals variables) {
|
||||
left.analyze(variables);
|
||||
right.analyze(variables);
|
||||
|
||||
Type promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, false);
|
||||
promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, false);
|
||||
|
||||
if (promote == null) {
|
||||
throw createError(new ClassCastException("Cannot apply and [&] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
left.expected = promote;
|
||||
right.expected = promote;
|
||||
actual = promote;
|
||||
|
||||
if (promote.sort == Sort.DEF) {
|
||||
left.expected = left.actual;
|
||||
right.expected = right.actual;
|
||||
if (expected != null) {
|
||||
actual = expected;
|
||||
}
|
||||
} else {
|
||||
left.expected = promote;
|
||||
right.expected = promote;
|
||||
}
|
||||
|
||||
left = left.cast(variables);
|
||||
right = right.cast(variables);
|
||||
|
@ -422,23 +499,31 @@ public final class EBinary extends AExpression {
|
|||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
actual = promote;
|
||||
}
|
||||
|
||||
private void analyzeXor(Locals variables) {
|
||||
left.analyze(variables);
|
||||
right.analyze(variables);
|
||||
|
||||
Type promote = AnalyzerCaster.promoteXor(left.actual, right.actual);
|
||||
promote = AnalyzerCaster.promoteXor(left.actual, right.actual);
|
||||
|
||||
if (promote == null) {
|
||||
throw createError(new ClassCastException("Cannot apply xor [^] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
left.expected = promote;
|
||||
right.expected = promote;
|
||||
actual = promote;
|
||||
|
||||
if (promote.sort == Sort.DEF) {
|
||||
left.expected = left.actual;
|
||||
right.expected = right.actual;
|
||||
if (expected != null) {
|
||||
actual = expected;
|
||||
}
|
||||
} else {
|
||||
left.expected = promote;
|
||||
right.expected = promote;
|
||||
}
|
||||
|
||||
left = left.cast(variables);
|
||||
right = right.cast(variables);
|
||||
|
@ -456,23 +541,31 @@ public final class EBinary extends AExpression {
|
|||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
actual = promote;
|
||||
}
|
||||
|
||||
private void analyzeBWOr(Locals variables) {
|
||||
left.analyze(variables);
|
||||
right.analyze(variables);
|
||||
|
||||
Type promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, false);
|
||||
promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, false);
|
||||
|
||||
if (promote == null) {
|
||||
throw createError(new ClassCastException("Cannot apply or [|] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
left.expected = promote;
|
||||
right.expected = promote;
|
||||
actual = promote;
|
||||
|
||||
if (promote.sort == Sort.DEF) {
|
||||
left.expected = left.actual;
|
||||
right.expected = right.actual;
|
||||
if (expected != null) {
|
||||
actual = expected;
|
||||
}
|
||||
} else {
|
||||
left.expected = promote;
|
||||
right.expected = promote;
|
||||
}
|
||||
|
||||
left = left.cast(variables);
|
||||
right = right.cast(variables);
|
||||
|
@ -488,15 +581,13 @@ public final class EBinary extends AExpression {
|
|||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
actual = promote;
|
||||
}
|
||||
|
||||
@Override
|
||||
void write(MethodWriter writer) {
|
||||
writer.writeDebugInfo(location);
|
||||
|
||||
if (actual.sort == Sort.STRING && operation == Operation.ADD) {
|
||||
if (promote.sort == Sort.STRING && operation == Operation.ADD) {
|
||||
if (!cat) {
|
||||
writer.writeNewStrings();
|
||||
}
|
||||
|
@ -520,7 +611,11 @@ public final class EBinary extends AExpression {
|
|||
left.write(writer);
|
||||
right.write(writer);
|
||||
|
||||
writer.writeBinaryInstruction(location, actual, operation);
|
||||
if (promote.sort == Sort.DEF || (shiftDistance != null && shiftDistance.sort == Sort.DEF)) {
|
||||
writer.writeDynamicBinaryInstruction(location, expected, left.actual, right.actual, operation);
|
||||
} else {
|
||||
writer.writeBinaryInstruction(location, actual, operation);
|
||||
}
|
||||
}
|
||||
|
||||
writer.writeBranch(tru, fals);
|
||||
|
|
|
@ -334,7 +334,15 @@ public final class EChain extends AExpression {
|
|||
writer.writeCast(there); // if necessary cast the current link's value
|
||||
// to the promotion type between the lhs and rhs types
|
||||
expression.write(writer); // write the bytecode for the rhs expression
|
||||
writer.writeBinaryInstruction(location, promote, operation); // write the operation instruction for compound assignment
|
||||
// XXX: fix these types, but first we need def compound assignment tests.
|
||||
// (and also corner cases such as shifts). its tricky here as there are possibly explicit casts, too.
|
||||
// write the operation instruction for compound assignment
|
||||
if (promote.sort == Sort.DEF) {
|
||||
writer.writeDynamicBinaryInstruction(location, promote,
|
||||
Definition.DEF_TYPE, Definition.DEF_TYPE, operation);
|
||||
} else {
|
||||
writer.writeBinaryInstruction(location, promote, operation);
|
||||
}
|
||||
|
||||
writer.writeCast(back); // if necessary cast the promotion type value back to the link's type
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ public final class EComp extends AExpression {
|
|||
final Operation operation;
|
||||
AExpression left;
|
||||
AExpression right;
|
||||
Type promotedType;
|
||||
|
||||
public EComp(Location location, Operation operation, AExpression left, AExpression right) {
|
||||
super(location);
|
||||
|
@ -78,15 +79,20 @@ public final class EComp extends AExpression {
|
|||
left.analyze(variables);
|
||||
right.analyze(variables);
|
||||
|
||||
Type promote = AnalyzerCaster.promoteEquality(left.actual, right.actual);
|
||||
promotedType = AnalyzerCaster.promoteEquality(left.actual, right.actual);
|
||||
|
||||
if (promote == null) {
|
||||
if (promotedType == null) {
|
||||
throw createError(new ClassCastException("Cannot apply equals [==] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
left.expected = promote;
|
||||
right.expected = promote;
|
||||
if (promotedType.sort == Sort.DEF) {
|
||||
left.expected = left.actual;
|
||||
right.expected = right.actual;
|
||||
} else {
|
||||
left.expected = promotedType;
|
||||
right.expected = promotedType;
|
||||
}
|
||||
|
||||
left = left.cast(variables);
|
||||
right = right.cast(variables);
|
||||
|
@ -96,7 +102,7 @@ public final class EComp extends AExpression {
|
|||
}
|
||||
|
||||
if ((left.constant != null || left.isNull) && (right.constant != null || right.isNull)) {
|
||||
Sort sort = promote.sort;
|
||||
Sort sort = promotedType.sort;
|
||||
|
||||
if (sort == Sort.BOOL) {
|
||||
constant = (boolean)left.constant == (boolean)right.constant;
|
||||
|
@ -124,15 +130,20 @@ public final class EComp extends AExpression {
|
|||
left.analyze(variables);
|
||||
right.analyze(variables);
|
||||
|
||||
Type promote = AnalyzerCaster.promoteEquality(left.actual, right.actual);
|
||||
promotedType = AnalyzerCaster.promoteEquality(left.actual, right.actual);
|
||||
|
||||
if (promote == null) {
|
||||
if (promotedType == null) {
|
||||
throw createError(new ClassCastException("Cannot apply reference equals [===] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
left.expected = promote;
|
||||
right.expected = promote;
|
||||
if (promotedType.sort == Sort.DEF) {
|
||||
left.expected = left.actual;
|
||||
right.expected = right.actual;
|
||||
} else {
|
||||
left.expected = promotedType;
|
||||
right.expected = promotedType;
|
||||
}
|
||||
|
||||
left = left.cast(variables);
|
||||
right = right.cast(variables);
|
||||
|
@ -142,7 +153,7 @@ public final class EComp extends AExpression {
|
|||
}
|
||||
|
||||
if ((left.constant != null || left.isNull) && (right.constant != null || right.isNull)) {
|
||||
Sort sort = promote.sort;
|
||||
Sort sort = promotedType.sort;
|
||||
|
||||
if (sort == Sort.BOOL) {
|
||||
constant = (boolean)left.constant == (boolean)right.constant;
|
||||
|
@ -166,15 +177,20 @@ public final class EComp extends AExpression {
|
|||
left.analyze(variables);
|
||||
right.analyze(variables);
|
||||
|
||||
Type promote = AnalyzerCaster.promoteEquality(left.actual, right.actual);
|
||||
promotedType = AnalyzerCaster.promoteEquality(left.actual, right.actual);
|
||||
|
||||
if (promote == null) {
|
||||
if (promotedType == null) {
|
||||
throw createError(new ClassCastException("Cannot apply not equals [!=] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
left.expected = promote;
|
||||
right.expected = promote;
|
||||
if (promotedType.sort == Sort.DEF) {
|
||||
left.expected = left.actual;
|
||||
right.expected = right.actual;
|
||||
} else {
|
||||
left.expected = promotedType;
|
||||
right.expected = promotedType;
|
||||
}
|
||||
|
||||
left = left.cast(variables);
|
||||
right = right.cast(variables);
|
||||
|
@ -184,7 +200,7 @@ public final class EComp extends AExpression {
|
|||
}
|
||||
|
||||
if ((left.constant != null || left.isNull) && (right.constant != null || right.isNull)) {
|
||||
Sort sort = promote.sort;
|
||||
Sort sort = promotedType.sort;
|
||||
|
||||
if (sort == Sort.BOOL) {
|
||||
constant = (boolean)left.constant != (boolean)right.constant;
|
||||
|
@ -212,15 +228,20 @@ public final class EComp extends AExpression {
|
|||
left.analyze(variables);
|
||||
right.analyze(variables);
|
||||
|
||||
Type promote = AnalyzerCaster.promoteEquality(left.actual, right.actual);
|
||||
promotedType = AnalyzerCaster.promoteEquality(left.actual, right.actual);
|
||||
|
||||
if (promote == null) {
|
||||
if (promotedType == null) {
|
||||
throw createError(new ClassCastException("Cannot apply reference not equals [!==] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
left.expected = promote;
|
||||
right.expected = promote;
|
||||
if (promotedType.sort == Sort.DEF) {
|
||||
left.expected = left.actual;
|
||||
right.expected = right.actual;
|
||||
} else {
|
||||
left.expected = promotedType;
|
||||
right.expected = promotedType;
|
||||
}
|
||||
|
||||
left = left.cast(variables);
|
||||
right = right.cast(variables);
|
||||
|
@ -230,7 +251,7 @@ public final class EComp extends AExpression {
|
|||
}
|
||||
|
||||
if ((left.constant != null || left.isNull) && (right.constant != null || right.isNull)) {
|
||||
Sort sort = promote.sort;
|
||||
Sort sort = promotedType.sort;
|
||||
|
||||
if (sort == Sort.BOOL) {
|
||||
constant = (boolean)left.constant != (boolean)right.constant;
|
||||
|
@ -254,21 +275,26 @@ public final class EComp extends AExpression {
|
|||
left.analyze(variables);
|
||||
right.analyze(variables);
|
||||
|
||||
Type promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||
promotedType = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||
|
||||
if (promote == null) {
|
||||
if (promotedType == null) {
|
||||
throw createError(new ClassCastException("Cannot apply greater than or equals [>=] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
left.expected = promote;
|
||||
right.expected = promote;
|
||||
if (promotedType.sort == Sort.DEF) {
|
||||
left.expected = left.actual;
|
||||
right.expected = right.actual;
|
||||
} else {
|
||||
left.expected = promotedType;
|
||||
right.expected = promotedType;
|
||||
}
|
||||
|
||||
left = left.cast(variables);
|
||||
right = right.cast(variables);
|
||||
|
||||
if (left.constant != null && right.constant != null) {
|
||||
Sort sort = promote.sort;
|
||||
Sort sort = promotedType.sort;
|
||||
|
||||
if (sort == Sort.INT) {
|
||||
constant = (int)left.constant >= (int)right.constant;
|
||||
|
@ -290,21 +316,26 @@ public final class EComp extends AExpression {
|
|||
left.analyze(variables);
|
||||
right.analyze(variables);
|
||||
|
||||
Type promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||
promotedType = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||
|
||||
if (promote == null) {
|
||||
if (promotedType == null) {
|
||||
throw createError(new ClassCastException("Cannot apply greater than [>] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
left.expected = promote;
|
||||
right.expected = promote;
|
||||
if (promotedType.sort == Sort.DEF) {
|
||||
left.expected = left.actual;
|
||||
right.expected = right.actual;
|
||||
} else {
|
||||
left.expected = promotedType;
|
||||
right.expected = promotedType;
|
||||
}
|
||||
|
||||
left = left.cast(variables);
|
||||
right = right.cast(variables);
|
||||
|
||||
if (left.constant != null && right.constant != null) {
|
||||
Sort sort = promote.sort;
|
||||
Sort sort = promotedType.sort;
|
||||
|
||||
if (sort == Sort.INT) {
|
||||
constant = (int)left.constant > (int)right.constant;
|
||||
|
@ -326,21 +357,26 @@ public final class EComp extends AExpression {
|
|||
left.analyze(variables);
|
||||
right.analyze(variables);
|
||||
|
||||
Type promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||
promotedType = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||
|
||||
if (promote == null) {
|
||||
if (promotedType == null) {
|
||||
throw createError(new ClassCastException("Cannot apply less than or equals [<=] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
left.expected = promote;
|
||||
right.expected = promote;
|
||||
if (promotedType.sort == Sort.DEF) {
|
||||
left.expected = left.actual;
|
||||
right.expected = right.actual;
|
||||
} else {
|
||||
left.expected = promotedType;
|
||||
right.expected = promotedType;
|
||||
}
|
||||
|
||||
left = left.cast(variables);
|
||||
right = right.cast(variables);
|
||||
|
||||
if (left.constant != null && right.constant != null) {
|
||||
Sort sort = promote.sort;
|
||||
Sort sort = promotedType.sort;
|
||||
|
||||
if (sort == Sort.INT) {
|
||||
constant = (int)left.constant <= (int)right.constant;
|
||||
|
@ -362,21 +398,26 @@ public final class EComp extends AExpression {
|
|||
left.analyze(variables);
|
||||
right.analyze(variables);
|
||||
|
||||
Type promote = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||
promotedType = AnalyzerCaster.promoteNumeric(left.actual, right.actual, true);
|
||||
|
||||
if (promote == null) {
|
||||
if (promotedType == null) {
|
||||
throw createError(new ClassCastException("Cannot apply less than [>=] to types " +
|
||||
"[" + left.actual.name + "] and [" + right.actual.name + "]."));
|
||||
}
|
||||
|
||||
left.expected = promote;
|
||||
right.expected = promote;
|
||||
if (promotedType.sort == Sort.DEF) {
|
||||
left.expected = left.actual;
|
||||
right.expected = right.actual;
|
||||
} else {
|
||||
left.expected = promotedType;
|
||||
right.expected = promotedType;
|
||||
}
|
||||
|
||||
left = left.cast(variables);
|
||||
right = right.cast(variables);
|
||||
|
||||
if (left.constant != null && right.constant != null) {
|
||||
Sort sort = promote.sort;
|
||||
Sort sort = promotedType.sort;
|
||||
|
||||
if (sort == Sort.INT) {
|
||||
constant = (int)left.constant < (int)right.constant;
|
||||
|
@ -399,8 +440,6 @@ public final class EComp extends AExpression {
|
|||
writer.writeDebugInfo(location);
|
||||
|
||||
boolean branch = tru != null || fals != null;
|
||||
org.objectweb.asm.Type rtype = right.actual.type;
|
||||
Sort rsort = right.actual.sort;
|
||||
|
||||
left.write(writer);
|
||||
|
||||
|
@ -422,7 +461,7 @@ public final class EComp extends AExpression {
|
|||
|
||||
boolean writejump = true;
|
||||
|
||||
switch (rsort) {
|
||||
switch (promotedType.sort) {
|
||||
case VOID:
|
||||
case BYTE:
|
||||
case SHORT:
|
||||
|
@ -440,12 +479,12 @@ public final class EComp extends AExpression {
|
|||
case LONG:
|
||||
case FLOAT:
|
||||
case DOUBLE:
|
||||
if (eq) writer.ifCmp(rtype, MethodWriter.EQ, jump);
|
||||
else if (ne) writer.ifCmp(rtype, MethodWriter.NE, jump);
|
||||
else if (lt) writer.ifCmp(rtype, MethodWriter.LT, jump);
|
||||
else if (lte) writer.ifCmp(rtype, MethodWriter.LE, jump);
|
||||
else if (gt) writer.ifCmp(rtype, MethodWriter.GT, jump);
|
||||
else if (gte) writer.ifCmp(rtype, MethodWriter.GE, jump);
|
||||
if (eq) writer.ifCmp(promotedType.type, MethodWriter.EQ, jump);
|
||||
else if (ne) writer.ifCmp(promotedType.type, MethodWriter.NE, jump);
|
||||
else if (lt) writer.ifCmp(promotedType.type, MethodWriter.LT, jump);
|
||||
else if (lte) writer.ifCmp(promotedType.type, MethodWriter.LE, jump);
|
||||
else if (gt) writer.ifCmp(promotedType.type, MethodWriter.GT, jump);
|
||||
else if (gte) writer.ifCmp(promotedType.type, MethodWriter.GE, jump);
|
||||
else {
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
@ -454,8 +493,7 @@ public final class EComp extends AExpression {
|
|||
case DEF:
|
||||
// XXX: move this out, so we can populate descriptor with what we really have (instead of casts/boxing!)
|
||||
org.objectweb.asm.Type booleanType = org.objectweb.asm.Type.getType(boolean.class);
|
||||
org.objectweb.asm.Type objectType = org.objectweb.asm.Type.getType(Object.class);
|
||||
org.objectweb.asm.Type descriptor = org.objectweb.asm.Type.getMethodType(booleanType, objectType, objectType);
|
||||
org.objectweb.asm.Type descriptor = org.objectweb.asm.Type.getMethodType(booleanType, left.actual.type, right.actual.type);
|
||||
if (eq) {
|
||||
if (right.isNull) {
|
||||
writer.ifNull(jump);
|
||||
|
@ -463,7 +501,7 @@ public final class EComp extends AExpression {
|
|||
writer.invokeDynamic("eq", descriptor.getDescriptor(), DEF_BOOTSTRAP_HANDLE, DefBootstrap.BINARY_OPERATOR);
|
||||
writejump = false;
|
||||
} else {
|
||||
writer.ifCmp(rtype, MethodWriter.EQ, jump);
|
||||
writer.ifCmp(promotedType.type, MethodWriter.EQ, jump);
|
||||
}
|
||||
} else if (ne) {
|
||||
if (right.isNull) {
|
||||
|
@ -472,7 +510,7 @@ public final class EComp extends AExpression {
|
|||
writer.invokeDynamic("eq", descriptor.getDescriptor(), DEF_BOOTSTRAP_HANDLE, DefBootstrap.BINARY_OPERATOR);
|
||||
writer.ifZCmp(MethodWriter.EQ, jump);
|
||||
} else {
|
||||
writer.ifCmp(rtype, MethodWriter.NE, jump);
|
||||
writer.ifCmp(promotedType.type, MethodWriter.NE, jump);
|
||||
}
|
||||
} else if (lt) {
|
||||
writer.invokeDynamic("lt", descriptor.getDescriptor(), DEF_BOOTSTRAP_HANDLE, DefBootstrap.BINARY_OPERATOR);
|
||||
|
@ -508,7 +546,7 @@ public final class EComp extends AExpression {
|
|||
|
||||
writejump = false;
|
||||
} else {
|
||||
writer.ifCmp(rtype, MethodWriter.EQ, jump);
|
||||
writer.ifCmp(promotedType.type, MethodWriter.EQ, jump);
|
||||
}
|
||||
} else if (ne) {
|
||||
if (right.isNull) {
|
||||
|
@ -517,7 +555,7 @@ public final class EComp extends AExpression {
|
|||
writer.invokeStatic(OBJECTS_TYPE, EQUALS);
|
||||
writer.ifZCmp(MethodWriter.EQ, jump);
|
||||
} else {
|
||||
writer.ifCmp(rtype, MethodWriter.NE, jump);
|
||||
writer.ifCmp(promotedType.type, MethodWriter.NE, jump);
|
||||
}
|
||||
} else {
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -178,4 +178,229 @@ public class DefOptimizationTests extends ScriptTestCase {
|
|||
});
|
||||
assertTrue(exception.getMessage().contains("Cannot cast java.lang.Double to java.lang.Integer"));
|
||||
}
|
||||
|
||||
public void testMulOptLHS() {
|
||||
assertBytecodeExists("int x = 1; def y = 2; return x * y",
|
||||
"INVOKEDYNAMIC mul(ILjava/lang/Object;)Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
public void testMulOptRHS() {
|
||||
assertBytecodeExists("def x = 1; int y = 2; return x * y",
|
||||
"INVOKEDYNAMIC mul(Ljava/lang/Object;I)Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
public void testMulOptRet() {
|
||||
assertBytecodeExists("def x = 1; def y = 2; double d = x * y",
|
||||
"INVOKEDYNAMIC mul(Ljava/lang/Object;Ljava/lang/Object;)D");
|
||||
}
|
||||
|
||||
public void testDivOptLHS() {
|
||||
assertBytecodeExists("int x = 1; def y = 2; return x / y",
|
||||
"INVOKEDYNAMIC div(ILjava/lang/Object;)Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
public void testDivOptRHS() {
|
||||
assertBytecodeExists("def x = 1; int y = 2; return x / y",
|
||||
"INVOKEDYNAMIC div(Ljava/lang/Object;I)Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
public void testDivOptRet() {
|
||||
assertBytecodeExists("def x = 1; def y = 2; double d = x / y",
|
||||
"INVOKEDYNAMIC div(Ljava/lang/Object;Ljava/lang/Object;)D");
|
||||
}
|
||||
|
||||
public void testRemOptLHS() {
|
||||
assertBytecodeExists("int x = 1; def y = 2; return x % y",
|
||||
"INVOKEDYNAMIC rem(ILjava/lang/Object;)Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
public void testRemOptRHS() {
|
||||
assertBytecodeExists("def x = 1; int y = 2; return x % y",
|
||||
"INVOKEDYNAMIC rem(Ljava/lang/Object;I)Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
public void testRemOptRet() {
|
||||
assertBytecodeExists("def x = 1; def y = 2; double d = x % y",
|
||||
"INVOKEDYNAMIC rem(Ljava/lang/Object;Ljava/lang/Object;)D");
|
||||
}
|
||||
|
||||
public void testAddOptLHS() {
|
||||
assertBytecodeExists("int x = 1; def y = 2; return x + y",
|
||||
"INVOKEDYNAMIC add(ILjava/lang/Object;)Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
public void testAddOptRHS() {
|
||||
assertBytecodeExists("def x = 1; int y = 2; return x + y",
|
||||
"INVOKEDYNAMIC add(Ljava/lang/Object;I)Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
public void testAddOptRet() {
|
||||
assertBytecodeExists("def x = 1; def y = 2; double d = x + y",
|
||||
"INVOKEDYNAMIC add(Ljava/lang/Object;Ljava/lang/Object;)D");
|
||||
}
|
||||
|
||||
public void testSubOptLHS() {
|
||||
assertBytecodeExists("int x = 1; def y = 2; return x - y",
|
||||
"INVOKEDYNAMIC sub(ILjava/lang/Object;)Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
public void testSubOptRHS() {
|
||||
assertBytecodeExists("def x = 1; int y = 2; return x - y",
|
||||
"INVOKEDYNAMIC sub(Ljava/lang/Object;I)Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
public void testSubOptRet() {
|
||||
assertBytecodeExists("def x = 1; def y = 2; double d = x - y",
|
||||
"INVOKEDYNAMIC sub(Ljava/lang/Object;Ljava/lang/Object;)D");
|
||||
}
|
||||
|
||||
public void testLshOptLHS() {
|
||||
assertBytecodeExists("int x = 1; def y = 2; return x << y",
|
||||
"INVOKEDYNAMIC lsh(ILjava/lang/Object;)Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
public void testLshOptRHS() {
|
||||
assertBytecodeExists("def x = 1; int y = 2; return x << y",
|
||||
"INVOKEDYNAMIC lsh(Ljava/lang/Object;I)Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
public void testLshOptRet() {
|
||||
assertBytecodeExists("def x = 1; def y = 2; double d = x << y",
|
||||
"INVOKEDYNAMIC lsh(Ljava/lang/Object;Ljava/lang/Object;)D");
|
||||
}
|
||||
|
||||
public void testRshOptLHS() {
|
||||
assertBytecodeExists("int x = 1; def y = 2; return x >> y",
|
||||
"INVOKEDYNAMIC rsh(ILjava/lang/Object;)Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
public void testRshOptRHS() {
|
||||
assertBytecodeExists("def x = 1; int y = 2; return x >> y",
|
||||
"INVOKEDYNAMIC rsh(Ljava/lang/Object;I)Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
public void testRshOptRet() {
|
||||
assertBytecodeExists("def x = 1; def y = 2; double d = x >> y",
|
||||
"INVOKEDYNAMIC rsh(Ljava/lang/Object;Ljava/lang/Object;)D");
|
||||
}
|
||||
|
||||
public void testUshOptLHS() {
|
||||
assertBytecodeExists("int x = 1; def y = 2; return x >>> y",
|
||||
"INVOKEDYNAMIC ush(ILjava/lang/Object;)Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
public void testUshOptRHS() {
|
||||
assertBytecodeExists("def x = 1; int y = 2; return x >>> y",
|
||||
"INVOKEDYNAMIC ush(Ljava/lang/Object;I)Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
public void testUshOptRet() {
|
||||
assertBytecodeExists("def x = 1; def y = 2; double d = x >>> y",
|
||||
"INVOKEDYNAMIC ush(Ljava/lang/Object;Ljava/lang/Object;)D");
|
||||
}
|
||||
|
||||
public void testAndOptLHS() {
|
||||
assertBytecodeExists("int x = 1; def y = 2; return x & y",
|
||||
"INVOKEDYNAMIC and(ILjava/lang/Object;)Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
public void testAndOptRHS() {
|
||||
assertBytecodeExists("def x = 1; int y = 2; return x & y",
|
||||
"INVOKEDYNAMIC and(Ljava/lang/Object;I)Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
public void testAndOptRet() {
|
||||
assertBytecodeExists("def x = 1; def y = 2; double d = x & y",
|
||||
"INVOKEDYNAMIC and(Ljava/lang/Object;Ljava/lang/Object;)D");
|
||||
}
|
||||
|
||||
public void testOrOptLHS() {
|
||||
assertBytecodeExists("int x = 1; def y = 2; return x | y",
|
||||
"INVOKEDYNAMIC or(ILjava/lang/Object;)Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
public void testOrOptRHS() {
|
||||
assertBytecodeExists("def x = 1; int y = 2; return x | y",
|
||||
"INVOKEDYNAMIC or(Ljava/lang/Object;I)Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
public void testOrOptRet() {
|
||||
assertBytecodeExists("def x = 1; def y = 2; double d = x | y",
|
||||
"INVOKEDYNAMIC or(Ljava/lang/Object;Ljava/lang/Object;)D");
|
||||
}
|
||||
|
||||
public void testXorOptLHS() {
|
||||
assertBytecodeExists("int x = 1; def y = 2; return x ^ y",
|
||||
"INVOKEDYNAMIC xor(ILjava/lang/Object;)Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
public void testXorOptRHS() {
|
||||
assertBytecodeExists("def x = 1; int y = 2; return x ^ y",
|
||||
"INVOKEDYNAMIC xor(Ljava/lang/Object;I)Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
public void testXorOptRet() {
|
||||
assertBytecodeExists("def x = 1; def y = 2; double d = x ^ y",
|
||||
"INVOKEDYNAMIC xor(Ljava/lang/Object;Ljava/lang/Object;)D");
|
||||
}
|
||||
|
||||
public void testLtOptLHS() {
|
||||
assertBytecodeExists("int x = 1; def y = 2; return x < y",
|
||||
"INVOKEDYNAMIC lt(ILjava/lang/Object;)Z");
|
||||
}
|
||||
|
||||
public void testLtOptRHS() {
|
||||
assertBytecodeExists("def x = 1; int y = 2; return x < y",
|
||||
"INVOKEDYNAMIC lt(Ljava/lang/Object;I)Z");
|
||||
}
|
||||
|
||||
public void testLteOptLHS() {
|
||||
assertBytecodeExists("int x = 1; def y = 2; return x <= y",
|
||||
"INVOKEDYNAMIC lte(ILjava/lang/Object;)Z");
|
||||
}
|
||||
|
||||
public void testLteOptRHS() {
|
||||
assertBytecodeExists("def x = 1; int y = 2; return x <= y",
|
||||
"INVOKEDYNAMIC lte(Ljava/lang/Object;I)Z");
|
||||
}
|
||||
|
||||
public void testEqOptLHS() {
|
||||
assertBytecodeExists("int x = 1; def y = 2; return x == y",
|
||||
"INVOKEDYNAMIC eq(ILjava/lang/Object;)Z");
|
||||
}
|
||||
|
||||
public void testEqOptRHS() {
|
||||
assertBytecodeExists("def x = 1; int y = 2; return x == y",
|
||||
"INVOKEDYNAMIC eq(Ljava/lang/Object;I)Z");
|
||||
}
|
||||
|
||||
public void testNeqOptLHS() {
|
||||
assertBytecodeExists("int x = 1; def y = 2; return x != y",
|
||||
"INVOKEDYNAMIC eq(ILjava/lang/Object;)Z");
|
||||
}
|
||||
|
||||
public void testNeqOptRHS() {
|
||||
assertBytecodeExists("def x = 1; int y = 2; return x != y",
|
||||
"INVOKEDYNAMIC eq(Ljava/lang/Object;I)Z");
|
||||
}
|
||||
|
||||
public void testGteOptLHS() {
|
||||
assertBytecodeExists("int x = 1; def y = 2; return x >= y",
|
||||
"INVOKEDYNAMIC gte(ILjava/lang/Object;)Z");
|
||||
}
|
||||
|
||||
public void testGteOptRHS() {
|
||||
assertBytecodeExists("def x = 1; int y = 2; return x >= y",
|
||||
"INVOKEDYNAMIC gte(Ljava/lang/Object;I)Z");
|
||||
}
|
||||
|
||||
public void testGtOptLHS() {
|
||||
assertBytecodeExists("int x = 1; def y = 2; return x > y",
|
||||
"INVOKEDYNAMIC gt(ILjava/lang/Object;)Z");
|
||||
}
|
||||
|
||||
public void testGtOptRHS() {
|
||||
assertBytecodeExists("def x = 1; int y = 2; return x > y",
|
||||
"INVOKEDYNAMIC gt(Ljava/lang/Object;I)Z");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue