⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 codegen.java

📁 Javassist是一个开源的分析、编辑和创建Java字节码的类库。是由东京技术学院的数学和计算机科学系的 Shigeru Chiba 所创建的。它已加入了开放源代码JBoss 应用服务器项目,通过使
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
        if (k >= 0) {            expr.oprand1().accept(this);            ASTree right = expr.oprand2();            if (right == null)                return;     // see TypeChecker.atBinExpr().            int type1 = exprType;            int dim1 = arrayDim;            String cname1 = className;            right.accept(this);            if (dim1 != arrayDim)                throw new CompileError("incompatible array types");            if (token == '+' && dim1 == 0                && (type1 == CLASS || exprType == CLASS))                atStringConcatExpr(expr, type1, dim1, cname1);            else                atArithBinExpr(expr, token, k, type1);        }        else {            /* equation: &&, ||, ==, !=, <=, >=, <, >            */            booleanExpr(true, expr);            bytecode.addIndex(7);            bytecode.addIconst(0);  // false            bytecode.addOpcode(Opcode.GOTO);            bytecode.addIndex(4);            bytecode.addIconst(1);  // true        }    }    /* arrayDim values of the two oprands must be equal.     * If an oprand type is not a numeric type, this method     * throws an exception.     */    private void atArithBinExpr(Expr expr, int token,                                int index, int type1) throws CompileError    {        if (arrayDim != 0)            badTypes(expr);        int type2 = exprType;        if (token == LSHIFT || token == RSHIFT || token == ARSHIFT)            if (type2 == INT || type2 == SHORT                || type2 == CHAR || type2 == BYTE)                exprType = type1;            else                badTypes(expr);        else            convertOprandTypes(type1, type2, expr);        int p = typePrecedence(exprType);        if (p >= 0) {            int op = binOp[index + p + 1];            if (op != NOP) {                if (p == P_INT && exprType != BOOLEAN)                    exprType = INT;     // type1 may be BYTE, ...                bytecode.addOpcode(op);                return;            }        }        badTypes(expr);    }    private void atStringConcatExpr(Expr expr, int type1, int dim1,                                    String cname1) throws CompileError    {        int type2 = exprType;        int dim2 = arrayDim;        boolean type2Is2 = is2word(type2, dim2);        boolean type2IsString            = (type2 == CLASS && jvmJavaLangString.equals(className));        if (type2Is2)            convToString(type2, dim2);        if (is2word(type1, dim1)) {            bytecode.addOpcode(DUP_X2);            bytecode.addOpcode(POP);        }        else            bytecode.addOpcode(SWAP);        // even if type1 is String, the left operand might be null.        convToString(type1, dim1);        bytecode.addOpcode(SWAP);        if (!type2Is2 && !type2IsString)            convToString(type2, dim2);        bytecode.addInvokevirtual(javaLangString, "concat",                                "(Ljava/lang/String;)Ljava/lang/String;");        exprType = CLASS;        arrayDim = 0;        className = jvmJavaLangString;    }    private void convToString(int type, int dim) throws CompileError {        final String method = "valueOf";        if (isRefType(type) || dim > 0)            bytecode.addInvokestatic(javaLangString, method,                                "(Ljava/lang/Object;)Ljava/lang/String;");        else if (type == DOUBLE)            bytecode.addInvokestatic(javaLangString, method,                                     "(D)Ljava/lang/String;");        else if (type == FLOAT)            bytecode.addInvokestatic(javaLangString, method,                                     "(F)Ljava/lang/String;");        else if (type == LONG)            bytecode.addInvokestatic(javaLangString, method,                                     "(J)Ljava/lang/String;");        else if (type == BOOLEAN)            bytecode.addInvokestatic(javaLangString, method,                                     "(Z)Ljava/lang/String;");        else if (type == CHAR)            bytecode.addInvokestatic(javaLangString, method,                                     "(C)Ljava/lang/String;");        else if (type == VOID)            throw new CompileError("void type expression");        else /* INT, BYTE, SHORT */            bytecode.addInvokestatic(javaLangString, method,                                     "(I)Ljava/lang/String;");    }    /* Produces the opcode to branch if the condition is true.     * The oprand is not produced.     *     * @return	true if the compiled code is GOTO (always branch).     */    private boolean booleanExpr(boolean branchIf, ASTree expr)        throws CompileError    {        boolean isAndAnd;        int op = getCompOperator(expr);        if (op == EQ) {         // ==, !=, ...            BinExpr bexpr = (BinExpr)expr;            int type1 = compileOprands(bexpr);            // here, arrayDim might represent the array dim. of the left oprand            // if the right oprand is NULL.            compareExpr(branchIf, bexpr.getOperator(), type1, bexpr);        }        else if (op == '!')            booleanExpr(!branchIf, ((Expr)expr).oprand1());        else if ((isAndAnd = (op == ANDAND)) || op == OROR) {            BinExpr bexpr = (BinExpr)expr;            booleanExpr(!isAndAnd, bexpr.oprand1());            int pc = bytecode.currentPc();            bytecode.addIndex(0);       // correct later            booleanExpr(isAndAnd, bexpr.oprand2());            bytecode.write16bit(pc, bytecode.currentPc() - pc + 3);            if (branchIf != isAndAnd) {                bytecode.addIndex(6);   // skip GOTO instruction                bytecode.addOpcode(Opcode.GOTO);            }        }        else if (isAlwaysBranch(expr, branchIf)) {            bytecode.addOpcode(Opcode.GOTO);            return true;	// always branch        }        else {                          // others            expr.accept(this);            if (exprType != BOOLEAN || arrayDim != 0)                throw new CompileError("boolean expr is required");            bytecode.addOpcode(branchIf ? IFNE : IFEQ);        }        exprType = BOOLEAN;        arrayDim = 0;        return false;    }    private static boolean isAlwaysBranch(ASTree expr, boolean branchIf) {        if (expr instanceof Keyword) {            int t = ((Keyword)expr).get();            return branchIf ? t == TRUE : t == FALSE;        }        return false;    }    static int getCompOperator(ASTree expr) throws CompileError {        if (expr instanceof Expr) {            Expr bexpr = (Expr)expr;            int token = bexpr.getOperator();            if (token == '!')                return '!';            else if ((bexpr instanceof BinExpr)                     && token != OROR && token != ANDAND                     && token != '&' && token != '|')                return EQ;      // ==, !=, ...            else                return token;        }        return ' ';     // others    }    private int compileOprands(BinExpr expr) throws CompileError {        expr.oprand1().accept(this);        int type1 = exprType;        int dim1 = arrayDim;        expr.oprand2().accept(this);        if (dim1 != arrayDim)            if (type1 != NULL && exprType != NULL)                throw new CompileError("incompatible array types");            else if (exprType == NULL)                arrayDim = dim1;        if (type1 == NULL)            return exprType;        else            return type1;    }    private static final int ifOp[] = { EQ, IF_ICMPEQ, IF_ICMPNE,                                        NEQ, IF_ICMPNE, IF_ICMPEQ,                                        LE, IF_ICMPLE, IF_ICMPGT,                                        GE, IF_ICMPGE, IF_ICMPLT,                                        '<', IF_ICMPLT, IF_ICMPGE,                                        '>', IF_ICMPGT, IF_ICMPLE };    private static final int ifOp2[] = { EQ, IFEQ, IFNE,                                         NEQ, IFNE, IFEQ,                                         LE, IFLE, IFGT,                                         GE, IFGE, IFLT,                                         '<', IFLT, IFGE,                                         '>', IFGT, IFLE };    /* Produces the opcode to branch if the condition is true.     * The oprands are not produced.     *     * Parameter expr - compare expression ==, !=, <=, >=, <, >     */    private void compareExpr(boolean branchIf,                             int token, int type1, BinExpr expr)        throws CompileError    {        if (arrayDim == 0)            convertOprandTypes(type1, exprType, expr);        int p = typePrecedence(exprType);        if (p == P_OTHER || arrayDim > 0)            if (token == EQ)                bytecode.addOpcode(branchIf ? IF_ACMPEQ : IF_ACMPNE);            else if (token == NEQ)                bytecode.addOpcode(branchIf ? IF_ACMPNE : IF_ACMPEQ);            else                badTypes(expr);        else            if (p == P_INT) {                int op[] = ifOp;                for (int i = 0; i < op.length; i += 3)                    if (op[i] == token) {                        bytecode.addOpcode(op[i + (branchIf ? 1 : 2)]);                        return;                    }                badTypes(expr);            }            else {                if (p == P_DOUBLE)                    if (token == '<' || token == LE)                        bytecode.addOpcode(DCMPG);                    else                        bytecode.addOpcode(DCMPL);                else if (p == P_FLOAT)                    if (token == '<' || token == LE)                        bytecode.addOpcode(FCMPG);                    else                        bytecode.addOpcode(FCMPL);                else if (p == P_LONG)                    bytecode.addOpcode(LCMP); // 1: >, 0: =, -1: <                else                    fatal();                int[] op = ifOp2;                for (int i = 0; i < op.length; i += 3)                    if (op[i] == token) {                        bytecode.addOpcode(op[i + (branchIf ? 1 : 2)]);                        return;                    }                badTypes(expr);            }    }    protected static void badTypes(Expr expr) throws CompileError {        throw new CompileError("invalid types for " + expr.getName());    }    private static final int P_DOUBLE = 0;    private static final int P_FLOAT = 1;    private static final int P_LONG = 2;    private static final int P_INT = 3;    private static final int P_OTHER = -1;    protected static boolean isRefType(int type) {        return type == CLASS || type == NULL;    }    private static int typePrecedence(int type) {        if (type == DOUBLE)            return P_DOUBLE;        else if (type == FLOAT)            return P_FLOAT;        else if (type == LONG)            return P_LONG;        else if (isRefType(type))            return P_OTHER;        else if (type == VOID)            return P_OTHER;     // this is wrong, but ...        else            return P_INT;       // BOOLEAN, BYTE, CHAR, SHORT, INT    }    // used in TypeChecker.    static boolean isP_INT(int type) {        return typePrecedence(type) == P_INT;    }    // used in TypeChecker.    static boolean rightIsStrong(int type1, int type2) {        int type1_p = typePrecedence(type1);        int type2_p = typePrecedence(type2);        return type1_p >= 0 && type2_p >= 0 && type1_p > type2_p;    }    private static final int[] castOp = {            /*            D    F    L    I */            /* double */ NOP, D2F, D2L, D2I,            /* float  */ F2D, NOP, F2L, F2I,            /* long   */ L2D, L2F, NOP, L2I,            /* other  */ I2D, I2F, I2L, NOP };    /* do implicit type conversion.     * arrayDim values of the two oprands must be zero.     */    private void convertOprandTypes(int type1, int type2, Expr expr)        throws CompileError    {        boolean rightStrong;        int type1_p = typePrecedence(type1);        int type2_p = typePrecedence(type2);        if (type2_p < 0 && type1_p < 0) // not primitive types            return;        if (type2_p < 0 || type1_p < 0) // either is not a primitive type            badTypes(expr);        int op, result_type;        if (type1_p <= type2_p) {            rightStrong = false;            exprType = type1;            op = castOp[type2_p * 4 + type1_p];            result_type = type1_p;        }        else {            rightStrong = true;            op = castOp[type1_p * 4 + type2_p];            result_type = type2_p;        }        if (rightStrong) {            if (result_type == P_DOUBLE || result_type == P_LONG) {                if (type1_p == P_DOUBLE || type1_p == P_LONG)                    bytecode.addOpcode(DUP2_X2);                else                    bytecode.addOpcode(DUP2_X1);                bytecode.addOpcode(POP2);                bytecode.addOpcode(op);                bytecode.addOpcode(DUP2_X2);                bytecode.addOpcode(POP2);            }            else if (result_type == P_FLOAT) {                if (type1_p == P_LONG) {                    bytecode.addOpcode(DUP_X2);                    bytecode.addOpcode(POP);                }                else                    bytecode.addOpcode(SWAP);                bytecode.addOpcode(op);                bytecode.addOpcode(SWAP);            }            else                fatal();        }        else if (op != NOP)            bytecode.addOpcode(op);    }    public void atCastExpr(CastExpr expr) throws CompileError {        String cname = resolveClassName(expr.getClassName());        String toClass = checkCastExpr(expr, cname);        int srcType = exprType;        exprType = expr.getType();        arrayDim = expr.getArrayDim();        className = cname;        if (toClass == null)            atNumCastExpr(srcType, exprType);   // built-in type        else            bytecode.addCheckcast(toClass);    }    public void atInstanceOfExpr(InstanceOfExpr expr) throws CompileError {        String cname = resolveClassName(expr.getClassName());        String toClass = checkCastExpr(expr, cname);        bytecode.addInstanceof(toClass);        exprType = BOOLEAN;        arrayDim = 0;    }    private String checkCastExpr(CastExpr expr, String name)        throws CompileError    {        final String msg = "invalid cast";        ASTree oprand = expr.getOprand();        int dim = expr.getArrayDim();        int type = expr.getType();        oprand.accept(this);        int srcType = exprType;        if (invalidDim(srcType, arrayDim, className, type, dim, name, true)            || srcType == VOID || type == VOID)            throw new CompileError(msg);        if (type == CLASS) {            if (!isRefType(srcType))                throw new CompileError(msg);            return toJvmArrayName(name, dim);        }        else            if (dim > 0)                return toJvmTypeName(type, dim);            else                return null;    // built-in type    }    void atNumCastExpr(int srcType, int destType)        throws CompileError    {        if (srcType == destType)            return;                int op, op2;        int stype = typePrecedence(srcType);        int dtype = typePrecedence(destType);        if (0 <= stype && stype < 3)            op = castOp[stype * 4 + dtype];        else            op = NOP;        if (destType == DOUBLE)            op2 = I2D;        else if (destType == FLOAT)            op2 = I2F;        else if (destType == LONG)            op2 = I2L;        else if (destType == SHORT)            op2 = I2S;        else if (destType == CHAR)            op2 = I2C;        else if (destType == BYTE)            op2 = I2B;        else            op2 = NOP;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -