📄 constfold.java
字号:
/**
* @(#)ConstFold.java 1.17 03/01/23
*
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package com.sun.tools.javac.v8.comp;
import com.sun.tools.javac.v8.util.*;
import com.sun.tools.javac.v8.code.*;
import com.sun.tools.javac.v8.code.Type.*;
/**
* Helper class for constant folding, used by the attribution phase
*/
strictfp class ConstFold implements TypeTags, ByteCodes {
private static final Context.Key constFoldKey = new Context.Key();
private Log log;
private Symtab syms;
public static ConstFold instance(Context context) {
ConstFold instance = (ConstFold) context.get(constFoldKey);
if (instance == null)
instance = new ConstFold(context);
return instance;
}
private ConstFold(Context context) {
super();
context.put(constFoldKey, this);
log = Log.instance(context);
syms = Symtab.instance(context);
}
static Integer minusOne = new Integer(-1);
static Integer zero = new Integer(0);
static Integer one = new Integer(1);
/**
* Convert boolean to integer (true = 1, false = 0).
*/
private static Integer b2i(boolean b) {
return b ? one : zero;
}
private static int intValue(Object x) {
return ((Number) x).intValue();
}
private static long longValue(Object x) {
return ((Number) x).longValue();
}
private static float floatValue(Object x) {
return ((Number) x).floatValue();
}
private static double doubleValue(Object x) {
return ((Number) x).doubleValue();
}
/**
* Fold binary or unary operation, returning constant type reflecting the
* operations result. Return null if fold failed due to an
* arithmetic exception.
* @param opcode The operation's opcode instruction (usually a byte code),
* as entered by class Symtab.
* @param argtypes The operation's argument types (a list of length 1 or 2).
* Argument types are assumed to have non-null constValue's.
*/
Type fold(int opcode, List argtypes) {
int argCount = argtypes.length();
if (argCount == 1)
return fold1(opcode, (Type) argtypes.head);
else if (argCount == 2)
return fold2(opcode, (Type) argtypes.head, (Type) argtypes.tail.head);
else
throw new AssertionError();
}
/**
* Fold unary operation.
* @param opcode The operation's opcode instruction (usually a byte code),
* as entered by class Symtab.
* opcode's ifeq to ifge are for postprocessing
* xcmp; ifxx pairs of instructions.
* @param operand The operation's operand type.
* Argument types are assumed to have non-null constValue's.
*/
Type fold1(int opcode, Type operand) {
try {
Object od = operand.constValue;
switch (opcode) {
case nop:
return operand;
case ineg:
return syms.intType.constType(new Integer(-intValue(od)));
case ixor:
return syms.intType.constType(new Integer(~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:
return syms.longType.constType(new Long(-longValue(od)));
case lxor:
return syms.longType.constType(new Long(~longValue(od)));
case fneg:
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;
}
}
/**
* Fold binary operation.
* @param opcode The operation's opcode instruction (usually a byte code),
* as entered by class Symtab.
* opcode's ifeq to ifge are for postprocessing
* xcmp; ifxx pairs of instructions.
* @param left The type of the operation's left operand.
* @param right The type of the operation's right operand.
*/
Type fold2(int opcode, Type left, Type right) {
try {
if (opcode > ByteCodes.preMask) {
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(
new Integer(intValue(l) + intValue(r)));
case isub:
return syms.intType.constType(
new Integer(intValue(l) - intValue(r)));
case imul:
return syms.intType.constType(
new Integer(intValue(l) * intValue(r)));
case idiv:
return syms.intType.constType(
new Integer(intValue(l) / intValue(r)));
case imod:
return syms.intType.constType(
new Integer(intValue(l) % intValue(r)));
case iand:
return (left.tag == BOOLEAN ? syms.booleanType :
syms.intType).constType(
new Integer(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(
new Integer(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(
new Integer(intValue(l) ^ intValue(r)));
case ishl:
case ishll:
return syms.intType.constType(
new Integer(intValue(l)<< intValue(r)));
case ishr:
case ishrl:
return syms.intType.constType(
new Integer(intValue(l)>> intValue(r)));
case iushr:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -