Method from com.sun.tools.javac.comp.ConstFold Detail: |
Type coerce(Type etype,
Type ttype) {
// WAS if (etype.baseType() == ttype.baseType())
if (etype.tsym.type == ttype.tsym.type)
return etype;
if (etype.tag < = DOUBLE) {
Object n = etype.constValue();
switch (ttype.tag) {
case BYTE:
return syms.byteType.constType(0 + (byte)intValue(n));
case CHAR:
return syms.charType.constType(0 + (char)intValue(n));
case SHORT:
return syms.shortType.constType(0 + (short)intValue(n));
case INT:
return syms.intType.constType(intValue(n));
case LONG:
return syms.longType.constType(longValue(n));
case FLOAT:
return syms.floatType.constType(floatValue(n));
case DOUBLE:
return syms.doubleType.constType(doubleValue(n));
}
}
return ttype;
}
Coerce constant type to target type. |
Type fold(int opcode,
List<Type> argtypes) {
int argCount = argtypes.length();
if (argCount == 1)
return fold1(opcode, argtypes.head);
else if (argCount == 2)
return fold2(opcode, argtypes.head, argtypes.tail.head);
else
throw new AssertionError();
}
Fold binary or unary operation, returning constant type reflecting the
operations result. Return null if fold failed due to an
arithmetic exception. |
Type fold1(int opcode,
Type operand) {
try {
Object od = operand.constValue();
switch (opcode) {
case nop:
return operand;
case ineg: // unary -
return syms.intType.constType(-intValue(od));
case ixor: // ~
return syms.intType.constType(~intValue(od));
case bool_not: // !
return syms.booleanType.constType(b2i(intValue(od) == 0));
case ifeq:
return syms.booleanType.constType(b2i(intValue(od) == 0));
case ifne:
return syms.booleanType.constType(b2i(intValue(od) != 0));
case iflt:
return syms.booleanType.constType(b2i(intValue(od) < 0));
case ifgt:
return syms.booleanType.constType(b2i(intValue(od) > 0));
case ifle:
return syms.booleanType.constType(b2i(intValue(od) < = 0));
case ifge:
return syms.booleanType.constType(b2i(intValue(od) >= 0));
case lneg: // unary -
return syms.longType.constType(new Long(-longValue(od)));
case lxor: // ~
return syms.longType.constType(new Long(~longValue(od)));
case fneg: // unary -
return syms.floatType.constType(new Float(-floatValue(od)));
case dneg: // ~
return syms.doubleType.constType(new Double(-doubleValue(od)));
default:
return null;
}
} catch (ArithmeticException e) {
return null;
}
}
|
Type fold2(int opcode,
Type left,
Type right) {
try {
if (opcode > ByteCodes.preMask) {
// we are seeing a composite instruction of the form xcmp; ifxx.
// In this case fold both instructions separately.
Type t1 = fold2(opcode > > ByteCodes.preShift, left, right);
return (t1.constValue() == null) ? t1
: fold1(opcode & ByteCodes.preMask, t1);
} else {
Object l = left.constValue();
Object r = right.constValue();
switch (opcode) {
case iadd:
return syms.intType.constType(intValue(l) + intValue(r));
case isub:
return syms.intType.constType(intValue(l) - intValue(r));
case imul:
return syms.intType.constType(intValue(l) * intValue(r));
case idiv:
return syms.intType.constType(intValue(l) / intValue(r));
case imod:
return syms.intType.constType(intValue(l) % intValue(r));
case iand:
return (left.tag == BOOLEAN
? syms.booleanType : syms.intType)
.constType(intValue(l) & intValue(r));
case bool_and:
return syms.booleanType.constType(b2i((intValue(l) & intValue(r)) != 0));
case ior:
return (left.tag == BOOLEAN
? syms.booleanType : syms.intType)
.constType(intValue(l) | intValue(r));
case bool_or:
return syms.booleanType.constType(b2i((intValue(l) | intValue(r)) != 0));
case ixor:
return (left.tag == BOOLEAN
? syms.booleanType : syms.intType)
.constType(intValue(l) ^ intValue(r));
case ishl: case ishll:
return syms.intType.constType(intValue(l) < < intValue(r));
case ishr: case ishrl:
return syms.intType.constType(intValue(l) > > intValue(r));
case iushr: case iushrl:
return syms.intType.constType(intValue(l) > > > intValue(r));
case if_icmpeq:
return syms.booleanType.constType(
b2i(intValue(l) == intValue(r)));
case if_icmpne:
return syms.booleanType.constType(
b2i(intValue(l) != intValue(r)));
case if_icmplt:
return syms.booleanType.constType(
b2i(intValue(l) < intValue(r)));
case if_icmpgt:
return syms.booleanType.constType(
b2i(intValue(l) > intValue(r)));
case if_icmple:
return syms.booleanType.constType(
b2i(intValue(l) < = intValue(r)));
case if_icmpge:
return syms.booleanType.constType(
b2i(intValue(l) >= intValue(r)));
case ladd:
return syms.longType.constType(
new Long(longValue(l) + longValue(r)));
case lsub:
return syms.longType.constType(
new Long(longValue(l) - longValue(r)));
case lmul:
return syms.longType.constType(
new Long(longValue(l) * longValue(r)));
case ldiv:
return syms.longType.constType(
new Long(longValue(l) / longValue(r)));
case lmod:
return syms.longType.constType(
new Long(longValue(l) % longValue(r)));
case land:
return syms.longType.constType(
new Long(longValue(l) & longValue(r)));
case lor:
return syms.longType.constType(
new Long(longValue(l) | longValue(r)));
case lxor:
return syms.longType.constType(
new Long(longValue(l) ^ longValue(r)));
case lshl: case lshll:
return syms.longType.constType(
new Long(longValue(l) < < intValue(r)));
case lshr: case lshrl:
return syms.longType.constType(
new Long(longValue(l) > > intValue(r)));
case lushr:
return syms.longType.constType(
new Long(longValue(l) > > > intValue(r)));
case lcmp:
if (longValue(l) < longValue(r))
return syms.intType.constType(minusOne);
else if (longValue(l) > longValue(r))
return syms.intType.constType(one);
else
return syms.intType.constType(zero);
case fadd:
return syms.floatType.constType(
new Float(floatValue(l) + floatValue(r)));
case fsub:
return syms.floatType.constType(
new Float(floatValue(l) - floatValue(r)));
case fmul:
return syms.floatType.constType(
new Float(floatValue(l) * floatValue(r)));
case fdiv:
return syms.floatType.constType(
new Float(floatValue(l) / floatValue(r)));
case fmod:
return syms.floatType.constType(
new Float(floatValue(l) % floatValue(r)));
case fcmpg: case fcmpl:
if (floatValue(l) < floatValue(r))
return syms.intType.constType(minusOne);
else if (floatValue(l) > floatValue(r))
return syms.intType.constType(one);
else if (floatValue(l) == floatValue(r))
return syms.intType.constType(zero);
else if (opcode == fcmpg)
return syms.intType.constType(one);
else
return syms.intType.constType(minusOne);
case dadd:
return syms.doubleType.constType(
new Double(doubleValue(l) + doubleValue(r)));
case dsub:
return syms.doubleType.constType(
new Double(doubleValue(l) - doubleValue(r)));
case dmul:
return syms.doubleType.constType(
new Double(doubleValue(l) * doubleValue(r)));
case ddiv:
return syms.doubleType.constType(
new Double(doubleValue(l) / doubleValue(r)));
case dmod:
return syms.doubleType.constType(
new Double(doubleValue(l) % doubleValue(r)));
case dcmpg: case dcmpl:
if (doubleValue(l) < doubleValue(r))
return syms.intType.constType(minusOne);
else if (doubleValue(l) > doubleValue(r))
return syms.intType.constType(one);
else if (doubleValue(l) == doubleValue(r))
return syms.intType.constType(zero);
else if (opcode == dcmpg)
return syms.intType.constType(one);
else
return syms.intType.constType(minusOne);
case if_acmpeq:
return syms.booleanType.constType(b2i(l.equals(r)));
case if_acmpne:
return syms.booleanType.constType(b2i(!l.equals(r)));
case string_add:
return syms.stringType.constType(
left.stringValue() + right.stringValue());
default:
return null;
}
}
} catch (ArithmeticException e) {
return null;
}
}
|
public static ConstFold instance(Context context) {
ConstFold instance = context.get(constFoldKey);
if (instance == null)
instance = new ConstFold(context);
return instance;
}
|