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

📄 codegen.java

📁 Javassist是一个开源的分析、编辑和创建Java字节码的类库。是由东京技术学院的数学和计算机科学系的 Shigeru Chiba 所创建的。它已加入了开放源代码JBoss 应用服务器项目,通过使
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
        int pc3 = bytecode.currentPc();        if (update != null)            update.accept(this);        bytecode.addOpcode(Opcode.GOTO);        bytecode.addIndex(pc - bytecode.currentPc() + 1);        int pc4 = bytecode.currentPc();        if (expr != null)            bytecode.write16bit(pc2, pc4 - pc2 + 1);        patchGoto(breakList, pc4);        patchGoto(continueList, pc3);        continueList = prevContList;        breakList = prevBreakList;        hasReturned = false;    }    private void atSwitchStmnt(Stmnt st) throws CompileError {        compileExpr(st.head());        ArrayList prevBreakList = breakList;        breakList = new ArrayList();        int opcodePc = bytecode.currentPc();        bytecode.addOpcode(LOOKUPSWITCH);        int npads = 3 - (opcodePc & 3);        while (npads-- > 0)            bytecode.add(0);        Stmnt body = (Stmnt)st.tail();        int npairs = 0;        for (ASTList list = body; list != null; list = list.tail())            if (((Stmnt)list.head()).getOperator() == CASE)                ++npairs;        // opcodePc2 is the position at which the default jump offset is.        int opcodePc2 = bytecode.currentPc();        bytecode.addGap(4);        bytecode.add32bit(npairs);        bytecode.addGap(npairs * 8);        long[] pairs = new long[npairs];        int ipairs = 0;        int defaultPc = -1;        for (ASTList list = body; list != null; list = list.tail()) {            Stmnt label = (Stmnt)list.head();            int op = label.getOperator();            if (op == DEFAULT)                defaultPc = bytecode.currentPc();            else if (op != CASE)                fatal();            else {                pairs[ipairs++]                    = ((long)computeLabel(label.head()) << 32) +                       ((long)(bytecode.currentPc() - opcodePc) & 0xffffffff);            }            hasReturned = false;            ((Stmnt)label.tail()).accept(this);        }        Arrays.sort(pairs);        int pc = opcodePc2 + 8;        for (int i = 0; i < npairs; ++i) {            bytecode.write32bit(pc, (int)(pairs[i] >>> 32));            bytecode.write32bit(pc + 4, (int)pairs[i]);            pc += 8;        }         if (defaultPc < 0 || breakList.size() > 0)            hasReturned = false;        int endPc = bytecode.currentPc();        if (defaultPc < 0)            defaultPc = endPc;        bytecode.write32bit(opcodePc2, defaultPc - opcodePc);        patchGoto(breakList, endPc);        breakList = prevBreakList;    }    private int computeLabel(ASTree expr) throws CompileError {        doTypeCheck(expr);        expr = TypeChecker.stripPlusExpr(expr);        if (expr instanceof IntConst)            return (int)((IntConst)expr).get();        else            throw new CompileError("bad case label");    }    private void atBreakStmnt(Stmnt st, boolean notCont)        throws CompileError    {        if (st.head() != null)            throw new CompileError(                        "sorry, not support labeled break or continue");        bytecode.addOpcode(Opcode.GOTO);        Integer pc = new Integer(bytecode.currentPc());        bytecode.addIndex(0);        if (notCont)            breakList.add(pc);        else            continueList.add(pc);    }    protected void atReturnStmnt(Stmnt st) throws CompileError {        atReturnStmnt2(st.getLeft());    }    protected final void atReturnStmnt2(ASTree result) throws CompileError {        int op;        if (result == null)            op = Opcode.RETURN;        else {            compileExpr(result);            if (arrayDim > 0)                op = ARETURN;            else {                int type = exprType;                if (type == DOUBLE)                    op = DRETURN;                else if (type == FLOAT)                    op = FRETURN;                else if (type == LONG)                    op = LRETURN;                else if (isRefType(type))                    op = ARETURN;                else                    op = IRETURN;            }        }        for (ReturnHook har = returnHooks; har != null; har = har.next)            har.doit(bytecode, op);        bytecode.addOpcode(op);        hasReturned = true;    }    private void atThrowStmnt(Stmnt st) throws CompileError {        ASTree e = st.getLeft();        compileExpr(e);        if (exprType != CLASS || arrayDim > 0)            throw new CompileError("bad throw statement");        bytecode.addOpcode(ATHROW);        hasReturned = true;    }    /* overridden in MemberCodeGen     */    protected void atTryStmnt(Stmnt st) throws CompileError {        hasReturned = false;    }    private void atSyncStmnt(Stmnt st) throws CompileError {        int nbreaks = getListSize(breakList);        int ncontinues = getListSize(continueList);        compileExpr(st.head());        if (exprType != CLASS && arrayDim == 0)            throw new CompileError("bad type expr for synchronized block");        Bytecode bc = bytecode;        final int var = bc.getMaxLocals();        bc.incMaxLocals(1);        bc.addOpcode(DUP);        bc.addAstore(var);        bc.addOpcode(MONITORENTER);        ReturnHook rh = new ReturnHook(this) {            protected void doit(Bytecode b, int opcode) {                b.addAload(var);                b.addOpcode(MONITOREXIT);            }        };        int pc = bc.currentPc();        Stmnt body = (Stmnt)st.tail();        if (body != null)            body.accept(this);        int pc2 = bc.currentPc();        int pc3 = 0;        if (!hasReturned) {            rh.doit(bc, 0);     // the 2nd arg is ignored.            bc.addOpcode(Opcode.GOTO);            pc3 = bc.currentPc();            bc.addIndex(0);        }        int pc4 = bc.currentPc();        rh.doit(bc, 0);         // the 2nd arg is ignored.        bc.addOpcode(ATHROW);        bc.addExceptionHandler(pc, pc2, pc4, 0);        if (!hasReturned)            bc.write16bit(pc3, bc.currentPc() - pc3 + 1);        rh.remove(this);        if (getListSize(breakList) != nbreaks            || getListSize(continueList) != ncontinues)            throw new CompileError(                "sorry, cannot break/continue in synchronized block");    }    private static int getListSize(ArrayList list) {        return list == null ? 0 : list.size();    }    private static boolean isPlusPlusExpr(ASTree expr) {        if (expr instanceof Expr) {            int op = ((Expr)expr).getOperator();            return op == PLUSPLUS || op == MINUSMINUS;        }        return false;    }    public void atDeclarator(Declarator d) throws CompileError {        d.setLocalVar(getMaxLocals());        d.setClassName(resolveClassName(d.getClassName()));        int size;        if (is2word(d.getType(), d.getArrayDim()))            size = 2;        else            size = 1;        incMaxLocals(size);        /*  NOTE: Array initializers has not been supported.         */        ASTree init = d.getInitializer();        if (init != null) {            doTypeCheck(init);            atVariableAssign(null, '=', null, d, init, false);        }    }    public abstract void atNewExpr(NewExpr n) throws CompileError;    public abstract void atArrayInit(ArrayInit init) throws CompileError;    public void atAssignExpr(AssignExpr expr) throws CompileError {        atAssignExpr(expr, true);    }    protected void atAssignExpr(AssignExpr expr, boolean doDup)        throws CompileError    {        // =, %=, &=, *=, /=, +=, -=, ^=, |=, <<=, >>=, >>>=        int op = expr.getOperator();        ASTree left = expr.oprand1();        ASTree right = expr.oprand2();        if (left instanceof Variable)            atVariableAssign(expr, op, (Variable)left,                             ((Variable)left).getDeclarator(),                             right, doDup);        else {            if (left instanceof Expr) {                Expr e = (Expr)left;                if (e.getOperator() == ARRAY) {                    atArrayAssign(expr, op, (Expr)left, right, doDup);                    return;                }            }            atFieldAssign(expr, op, left, right, doDup);        }    }    protected static void badAssign(Expr expr) throws CompileError {        String msg;        if (expr == null)            msg = "incompatible type for assignment";        else            msg = "incompatible type for " + expr.getName();        throw new CompileError(msg);    }    /* op is either =, %=, &=, *=, /=, +=, -=, ^=, |=, <<=, >>=, or >>>=.     *     * expr and var can be null.     */    private void atVariableAssign(Expr expr, int op, Variable var,                                  Declarator d, ASTree right,                                  boolean doDup) throws CompileError    {        int varType = d.getType();        int varArray = d.getArrayDim();        String varClass = d.getClassName();        int varNo = getLocalVar(d);        if (op != '=')            atVariable(var);        // expr is null if the caller is atDeclarator().        if (expr == null && right instanceof ArrayInit)            atArrayVariableAssign((ArrayInit)right, varType, varArray, varClass);        else            atAssignCore(expr, op, right, varType, varArray, varClass);        if (doDup)            if (is2word(varType, varArray))                bytecode.addOpcode(DUP2);            else                bytecode.addOpcode(DUP);        if (varArray > 0)            bytecode.addAstore(varNo);        else if (varType == DOUBLE)            bytecode.addDstore(varNo);        else if (varType == FLOAT)            bytecode.addFstore(varNo);        else if (varType == LONG)            bytecode.addLstore(varNo);        else if (isRefType(varType))            bytecode.addAstore(varNo);        else            bytecode.addIstore(varNo);        exprType = varType;        arrayDim = varArray;        className = varClass;    }    protected abstract void atArrayVariableAssign(ArrayInit init,            int varType, int varArray, String varClass) throws CompileError;    private void atArrayAssign(Expr expr, int op, Expr array,                        ASTree right, boolean doDup) throws CompileError    {        arrayAccess(array.oprand1(), array.oprand2());        if (op != '=') {            bytecode.addOpcode(DUP2);            bytecode.addOpcode(getArrayReadOp(exprType, arrayDim));        }        int aType = exprType;        int aDim = arrayDim;        String cname = className;        atAssignCore(expr, op, right, aType, aDim, cname);        if (doDup)            if (is2word(aType, aDim))                bytecode.addOpcode(DUP2_X2);            else                bytecode.addOpcode(DUP_X2);        bytecode.addOpcode(getArrayWriteOp(aType, aDim));        exprType = aType;        arrayDim = aDim;        className = cname;    }    protected abstract void atFieldAssign(Expr expr, int op, ASTree left,                        ASTree right, boolean doDup) throws CompileError;    protected void atAssignCore(Expr expr, int op, ASTree right,                                int type, int dim, String cname)        throws CompileError    {        if (op == PLUS_E && dim == 0 && type == CLASS)            atStringPlusEq(expr, type, dim, cname, right);        else {            right.accept(this);            if (invalidDim(exprType, arrayDim, className, type, dim, cname,                           false) || (op != '=' && dim > 0))                badAssign(expr);            if (op != '=') {                int token = assignOps[op - MOD_E];                int k = lookupBinOp(token);                if (k < 0)                    fatal();                atArithBinExpr(expr, token, k, type);            }        }        if (op != '=' || (dim == 0 && !isRefType(type)))            atNumCastExpr(exprType, type);        // type check should be done here.    }    private void atStringPlusEq(Expr expr, int type, int dim, String cname,                                ASTree right)        throws CompileError    {        if (!jvmJavaLangString.equals(cname))            badAssign(expr);        convToString(type, dim);    // the value might be null.        right.accept(this);        convToString(exprType, arrayDim);        bytecode.addInvokevirtual(javaLangString, "concat",                                "(Ljava/lang/String;)Ljava/lang/String;");        exprType = CLASS;        arrayDim = 0;        className = jvmJavaLangString;    }    private boolean invalidDim(int srcType, int srcDim, String srcClass,                               int destType, int destDim, String destClass,                               boolean isCast)    {        if (srcDim != destDim)            if (srcType == NULL)                return false;            else if (destDim == 0 && destType == CLASS                     && jvmJavaLangObject.equals(destClass))                return false;            else if (isCast && srcDim == 0 && srcType == CLASS                     && jvmJavaLangObject.equals(srcClass))                return false;            else                return true;        return false;    }    public void atCondExpr(CondExpr expr) throws CompileError {        booleanExpr(false, expr.condExpr());        int pc = bytecode.currentPc();        bytecode.addIndex(0);   // correct later        expr.thenExpr().accept(this);        int dim1 = arrayDim;        bytecode.addOpcode(Opcode.GOTO);        int pc2 = bytecode.currentPc();        bytecode.addIndex(0);        bytecode.write16bit(pc, bytecode.currentPc() - pc + 1);        expr.elseExpr().accept(this);        if (dim1 != arrayDim)            throw new CompileError("type mismatch in ?:");        bytecode.write16bit(pc2, bytecode.currentPc() - pc2 + 1);    }    static final int[] binOp = {        '+', DADD, FADD, LADD, IADD,        '-', DSUB, FSUB, LSUB, ISUB,        '*', DMUL, FMUL, LMUL, IMUL,        '/', DDIV, FDIV, LDIV, IDIV,        '%', DREM, FREM, LREM, IREM,        '|', NOP,  NOP,  LOR,  IOR,        '^', NOP,  NOP,  LXOR, IXOR,        '&', NOP,  NOP,  LAND, IAND,        LSHIFT, NOP, NOP, LSHL, ISHL,        RSHIFT, NOP, NOP, LSHR, ISHR,        ARSHIFT, NOP, NOP, LUSHR, IUSHR };    static int lookupBinOp(int token) {        int[] code = binOp;        int s = code.length;        for (int k = 0; k < s; k = k + 5)            if (code[k] == token)                return k;        return -1;    }    public void atBinExpr(BinExpr expr) throws CompileError {        int token = expr.getOperator();        /* arithmetic operators: +, -, *, /, %, |, ^, &, <<, >>, >>>         */        int k = lookupBinOp(token);

⌨️ 快捷键说明

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