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

📄 codegen.java

📁 Javassist是一个开源的分析、编辑和创建Java字节码的类库。是由东京技术学院的数学和计算机科学系的 Shigeru Chiba 所创建的。它已加入了开放源代码JBoss 应用服务器项目,通过使
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
/* * Javassist, a Java-bytecode translator toolkit. * Copyright (C) 1999-2006 Shigeru Chiba. All Rights Reserved. * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License.  Alternatively, the contents of this file may be used under * the terms of the GNU Lesser General Public License Version 2.1 or later. * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. */package javassist.compiler;import java.util.ArrayList;import java.util.Arrays;import javassist.compiler.ast.*;import javassist.bytecode.*;/* The code generator is implemeted by three files: * CodeGen.java, MemberCodeGen.java, and JvstCodeGen. * I just wanted to split a big file into three smaller ones. */public abstract class CodeGen extends Visitor implements Opcode, TokenId {    static final String javaLangObject = "java.lang.Object";    static final String jvmJavaLangObject = "java/lang/Object";    static final String javaLangString = "java.lang.String";    static final String jvmJavaLangString = "java/lang/String";    protected Bytecode bytecode;    private int tempVar;    TypeChecker typeChecker;    /**     * true if the last visited node is a return statement.     */    protected boolean hasReturned;    /**     * Must be true if compilation is for a static method.     */    public boolean inStaticMethod;    protected ArrayList breakList, continueList;    /**     * doit() in ReturnHook is called from atReturn().     */    protected static abstract class ReturnHook {        ReturnHook next;        protected abstract void doit(Bytecode b, int opcode);        protected ReturnHook(CodeGen gen) {            next = gen.returnHooks;            gen.returnHooks = this;        }        protected void remove(CodeGen gen) {            gen.returnHooks = next;        }    }    protected ReturnHook returnHooks;    /* The following fields are used by atXXX() methods     * for returning the type of the compiled expression.     */    protected int exprType;     // VOID, NULL, CLASS, BOOLEAN, INT, ...    protected int arrayDim;    protected String className; // JVM-internal representation    public CodeGen(Bytecode b) {        bytecode = b;        tempVar = -1;        typeChecker = null;        hasReturned = false;        inStaticMethod = false;        breakList = null;        continueList = null;        returnHooks = null;    }    public void setTypeChecker(TypeChecker checker) {        typeChecker = checker;    }    protected static void fatal() throws CompileError {        throw new CompileError("fatal");    }    public static boolean is2word(int type, int dim) {        return dim == 0 && (type == DOUBLE || type == LONG);     }    public int getMaxLocals() { return bytecode.getMaxLocals(); }    public void setMaxLocals(int n) {        bytecode.setMaxLocals(n);    }    protected void incMaxLocals(int size) {        bytecode.incMaxLocals(size);    }    /**     * Returns a local variable that single or double words can be     * stored in.     */    protected int getTempVar() {        if (tempVar < 0) {            tempVar = getMaxLocals();            incMaxLocals(2);        }        return tempVar;    }    protected int getLocalVar(Declarator d) {        int v = d.getLocalVar();        if (v < 0) {            v = getMaxLocals(); // delayed variable allocation.            d.setLocalVar(v);            incMaxLocals(1);        }        return v;    }    /**     * Returns the JVM-internal representation of this class name.     */    protected abstract String getThisName();    /**     * Returns the JVM-internal representation of this super class name.     */    protected abstract String getSuperName() throws CompileError;    /* Converts a class name into a JVM-internal representation.     *     * It may also expand a simple class name to java.lang.*.     * For example, this converts Object into java/lang/Object.     */    protected abstract String resolveClassName(ASTList name)        throws CompileError;    /* Expands a simple class name to java.lang.*.     * For example, this converts Object into java/lang/Object.     */    protected abstract String resolveClassName(String jvmClassName)        throws CompileError;    /**     * @param name      the JVM-internal representation.     *                  name is not exapnded to java.lang.*.     */    protected static String toJvmArrayName(String name, int dim) {        if (name == null)            return null;        if (dim == 0)            return name;        else {            StringBuffer sbuf = new StringBuffer();            int d = dim;            while (d-- > 0)                sbuf.append('[');            sbuf.append('L');            sbuf.append(name);            sbuf.append(';');            return sbuf.toString();        }    }    protected static String toJvmTypeName(int type, int dim) {        char c = 'I';        switch(type) {        case BOOLEAN :            c = 'Z';            break;        case BYTE :            c = 'B';            break;        case CHAR :            c = 'C';            break;        case SHORT :            c = 'S';            break;        case INT :            c = 'I';            break;        case LONG :            c = 'J';            break;        case FLOAT :            c = 'F';            break;        case DOUBLE :            c = 'D';            break;        case VOID :            c = 'V';            break;        }        StringBuffer sbuf = new StringBuffer();        while (dim-- > 0)                sbuf.append('[');        sbuf.append(c);        return sbuf.toString();    }    public void compileExpr(ASTree expr) throws CompileError {        doTypeCheck(expr);        expr.accept(this);    }    public boolean compileBooleanExpr(boolean branchIf, ASTree expr)        throws CompileError    {        doTypeCheck(expr);        return booleanExpr(branchIf, expr);    }    public void doTypeCheck(ASTree expr) throws CompileError {        if (typeChecker != null)            expr.accept(typeChecker);    }    public void atASTList(ASTList n) throws CompileError { fatal(); }        public void atPair(Pair n) throws CompileError { fatal(); }    public void atSymbol(Symbol n) throws CompileError { fatal(); }    public void atFieldDecl(FieldDecl field) throws CompileError {        field.getInit().accept(this);    }    public void atMethodDecl(MethodDecl method) throws CompileError {        ASTList mods = method.getModifiers();        setMaxLocals(1);        while (mods != null) {            Keyword k = (Keyword)mods.head();            mods = mods.tail();            if (k.get() == STATIC) {                setMaxLocals(0);                inStaticMethod = true;            }        }                    ASTList params = method.getParams();        while (params != null) {            atDeclarator((Declarator)params.head());            params = params.tail();        }        Stmnt s = method.getBody();        atMethodBody(s, method.isConstructor(),                     method.getReturn().getType() == VOID);    }    /**     * @param isCons	true if super() must be called.     *			false if the method is a class initializer.     */    public void atMethodBody(Stmnt s, boolean isCons, boolean isVoid)        throws CompileError    {        if (s == null)            return;        if (isCons && needsSuperCall(s))            insertDefaultSuperCall();        hasReturned = false;        s.accept(this);        if (!hasReturned)            if (isVoid) {                bytecode.addOpcode(Opcode.RETURN);                hasReturned = true;            }            else                throw new CompileError("no return statement");    }    private boolean needsSuperCall(Stmnt body) throws CompileError {        if (body.getOperator() == BLOCK)            body = (Stmnt)body.head();        if (body != null && body.getOperator() == EXPR) {            ASTree expr = body.head();            if (expr != null && expr instanceof Expr                && ((Expr)expr).getOperator() == CALL) {                ASTree target = ((Expr)expr).head();                if (target instanceof Keyword) {                    int token = ((Keyword)target).get();                    return token != THIS && token != SUPER;                }            }        }        return true;    }    protected abstract void insertDefaultSuperCall() throws CompileError;    public void atStmnt(Stmnt st) throws CompileError {        if (st == null)            return;     // empty        int op = st.getOperator();        if (op == EXPR) {            ASTree expr = st.getLeft();            doTypeCheck(expr);            if (expr instanceof AssignExpr)                atAssignExpr((AssignExpr)expr, false);            else if (isPlusPlusExpr(expr)) {                Expr e = (Expr)expr;                atPlusPlus(e.getOperator(), e.oprand1(), e, false);            }            else {                expr.accept(this);                if (is2word(exprType, arrayDim))                    bytecode.addOpcode(POP2);                else if (exprType != VOID)                    bytecode.addOpcode(POP);            }        }        else if (op == DECL || op == BLOCK) {            ASTList list = st;            while (list != null) {                ASTree h = list.head();                list = list.tail();                if (h != null)                    h.accept(this);            }        }        else if (op == IF)            atIfStmnt(st);        else if (op == WHILE || op == DO)            atWhileStmnt(st, op == WHILE);        else if (op == FOR)            atForStmnt(st);        else if (op == BREAK || op == CONTINUE)            atBreakStmnt(st, op == BREAK);        else if (op == TokenId.RETURN)            atReturnStmnt(st);        else if (op == THROW)            atThrowStmnt(st);        else if (op == TRY)            atTryStmnt(st);        else if (op == SWITCH)            atSwitchStmnt(st);        else if (op == SYNCHRONIZED)            atSyncStmnt(st);        else {            // LABEL, SWITCH label stament might be null?.            hasReturned = false;            throw new CompileError(                "sorry, not supported statement: TokenId " + op);        }    }    private void atIfStmnt(Stmnt st) throws CompileError {        ASTree expr = st.head();        Stmnt thenp = (Stmnt)st.tail().head();        Stmnt elsep = (Stmnt)st.tail().tail().head();        compileBooleanExpr(false, expr);        int pc = bytecode.currentPc();        int pc2 = 0;        bytecode.addIndex(0);   // correct later        hasReturned = false;        if (thenp != null)            thenp.accept(this);        boolean thenHasReturned = hasReturned;        hasReturned = false;        if (elsep != null && !thenHasReturned) {            bytecode.addOpcode(Opcode.GOTO);            pc2 = bytecode.currentPc();            bytecode.addIndex(0);        }        bytecode.write16bit(pc, bytecode.currentPc() - pc + 1);        if (elsep != null) {            elsep.accept(this);            if (!thenHasReturned)                bytecode.write16bit(pc2, bytecode.currentPc() - pc2 + 1);            hasReturned = thenHasReturned && hasReturned;        }    }    private void atWhileStmnt(Stmnt st, boolean notDo) throws CompileError {        ArrayList prevBreakList = breakList;        ArrayList prevContList = continueList;        breakList = new ArrayList();        continueList = new ArrayList();        ASTree expr = st.head();        Stmnt body = (Stmnt)st.tail();        int pc = 0;        if (notDo) {            bytecode.addOpcode(Opcode.GOTO);            pc = bytecode.currentPc();            bytecode.addIndex(0);        }        int pc2 = bytecode.currentPc();        if (body != null)            body.accept(this);        int pc3 = bytecode.currentPc();        if (notDo)            bytecode.write16bit(pc, pc3 - pc + 1);        boolean alwaysBranch = compileBooleanExpr(true, expr);        bytecode.addIndex(pc2 - bytecode.currentPc() + 1);        patchGoto(breakList, bytecode.currentPc());        patchGoto(continueList, pc3);        continueList = prevContList;        breakList = prevBreakList;        hasReturned = alwaysBranch;    }    protected void patchGoto(ArrayList list, int targetPc) {        int n = list.size();        for (int i = 0; i < n; ++i) {            int pc = ((Integer)list.get(i)).intValue();            bytecode.write16bit(pc, targetPc - pc + 1);        }    }    private void atForStmnt(Stmnt st) throws CompileError {        ArrayList prevBreakList = breakList;        ArrayList prevContList = continueList;        breakList = new ArrayList();        continueList = new ArrayList();        Stmnt init = (Stmnt)st.head();        ASTList p = st.tail();        ASTree expr = p.head();        p = p.tail();        Stmnt update = (Stmnt)p.head();        Stmnt body = (Stmnt)p.tail();        if (init != null)            init.accept(this);        int pc = bytecode.currentPc();        int pc2 = 0;        if (expr != null) {            compileBooleanExpr(false, expr);            pc2 = bytecode.currentPc();            bytecode.addIndex(0);        }        if (body != null)            body.accept(this);

⌨️ 快捷键说明

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